0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

SNMP: Fix handling of partially received PDUs

This commit is contained in:
Vojtech Vilimek 2023-11-08 13:10:13 +01:00
parent bcbb56bef6
commit fedaa0af5e
3 changed files with 21 additions and 18 deletions

View File

@ -257,7 +257,6 @@ snmp_sock_err(sock *sk, int UNUSED err)
{ {
snmp_log("socket error '%s' (errno: %d)", strerror(err), err); snmp_log("socket error '%s' (errno: %d)", strerror(err), err);
struct snmp_proto *p = sk->data; struct snmp_proto *p = sk->data;
p->errs++;
snmp_sock_disconnect(p, 1); snmp_sock_disconnect(p, 1);
} }
@ -280,10 +279,6 @@ snmp_start_locked(struct object_lock *lock)
p->state = SNMP_LOCKED; p->state = SNMP_LOCKED;
sock *s = p->sock; sock *s = p->sock;
p->to_send = 0;
p->errs = 0;
if (!p->bgp_trie) if (!p->bgp_trie)
p->bgp_trie = f_new_trie(p->lp, 0); // TODO user-data attachment size p->bgp_trie = f_new_trie(p->lp, 0); // TODO user-data attachment size
@ -303,9 +298,6 @@ snmp_start_locked(struct object_lock *lock)
p->sock = s; p->sock = s;
s->data = p; s->data = p;
p->to_send = 0;
p->errs = 0;
} }
/* Try opening the socket, schedule a retry on fail */ /* Try opening the socket, schedule a retry on fail */
@ -478,6 +470,7 @@ snmp_start(struct proto *P)
} }
} }
p->last_header = NULL;
snmp_startup(p); snmp_startup(p);
return PS_START; return PS_START;
} }
@ -651,9 +644,9 @@ snmp_shutdown(struct proto *P)
*/ */
struct protocol proto_snmp = { struct protocol proto_snmp = {
.name = "Snmp", .name = "SNMP",
.template = "snmp%d", .template = "snmp%d",
.channel_mask = NB_ANY, .channel_mask = 0,
.proto_size = sizeof(struct snmp_proto), .proto_size = sizeof(struct snmp_proto),
.config_size = sizeof(struct snmp_config), .config_size = sizeof(struct snmp_config),
.postconfig = snmp_postconfig, .postconfig = snmp_postconfig,

View File

@ -116,6 +116,7 @@ struct snmp_proto {
u32 bgp_local_as; u32 bgp_local_as;
sock *sock; sock *sock;
void *last_header; /* points to partial PDU header */
u8 timeout; /* timeout is part of MIB registration. It u8 timeout; /* timeout is part of MIB registration. It
specifies how long should the master specifies how long should the master
agent wait for request responses. */ agent wait for request responses. */
@ -139,9 +140,6 @@ struct snmp_proto {
uint startup_delay; uint startup_delay;
timer *startup_timer; timer *startup_timer;
u8 state; u8 state;
uint to_send;
uint errs;
}; };
//void snmp_tx(sock *sk); //void snmp_tx(sock *sk);

View File

@ -339,7 +339,7 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
memcpy(c.buffer, data, size); memcpy(c.buffer, data, size);
ADVANCE(c.buffer, c.size, size); ADVANCE(c.buffer, c.size, size);
uint s = update_packet_size(p, sk->tbuf, c.buffer); uint s = update_packet_size(p, sk->tpos, c.buffer);
sk_send(sk, s); sk_send(sk, s);
#undef TRAP0_HEADER_SIZE #undef TRAP0_HEADER_SIZE
@ -1522,15 +1522,23 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
has_any = 0; has_any = 0;
for (bulk_state.index = 0; bulk_state.index < bulk_state.repeaters; for (bulk_state.index = 0; bulk_state.index < bulk_state.repeaters;
bulk_state.repeaters++) bulk_state.repeaters++)
has_any = has_any || snmp_get_bulk2(p, start, end, &bulk_state, &c); has_any = snmp_get_bulk2(p, start, end, &bulk_state, &c) || has_any;
} }
} }
/* send the constructed packet */ /* send the constructed packet */
struct agentx_response *res = (void *) sk->tbuf; struct agentx_response *res;
if (p->last_header)
{
res = p->last_header;
p->last_header = NULL;
}
else
res = response_header;
/* We update the error, index pair on the beginning of the packet. */ /* We update the error, index pair on the beginning of the packet. */
response_err_ind(res, c.error, c.index + 1); response_err_ind(res, c.error, c.index + 1);
uint s = update_packet_size(p, (byte *) response_header, c.buffer); uint s = update_packet_size(p, (byte *) res, c.buffer);
/* We send the message in TX-buffer. */ /* We send the message in TX-buffer. */
sk_send(sk, s); sk_send(sk, s);
@ -1542,8 +1550,9 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
partial: partial:
/* need to tweak RX buffer packet size */ /* need to tweak RX buffer packet size */
(c.byte_ord) ? put_u32(&h->payload, pkt_size) : (h->payload = pkt_size); STORE_U32(h->payload, pkt_size);
*skip = AGENTX_HEADER_SIZE; *skip = AGENTX_HEADER_SIZE;
p->last_header = h;
/* number of bytes parsed from RX-buffer */ /* number of bytes parsed from RX-buffer */
ret = pkt - pkt_start; ret = pkt - pkt_start;
@ -1897,6 +1906,9 @@ snmp_manage_tbuf(struct snmp_proto UNUSED *p, struct snmp_pdu *c)
static struct agentx_response * static struct agentx_response *
prepare_response(struct snmp_proto *p, struct snmp_pdu *c) prepare_response(struct snmp_proto *p, struct snmp_pdu *c)
{ {
if (p->last_header)
return p->last_header;
struct agentx_response *r = (void *) c->buffer; struct agentx_response *r = (void *) c->buffer;
struct agentx_header *h = &r->h; struct agentx_header *h = &r->h;