]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
SNMP: Fix handling of partially received PDUs
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 8 Nov 2023 12:10:13 +0000 (13:10 +0100)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Wed, 8 Nov 2023 12:10:13 +0000 (13:10 +0100)
proto/snmp/snmp.c
proto/snmp/snmp.h
proto/snmp/subagent.c

index 347521ebbdcdcd27089454e95b942799bfa861fd..ee86882584a5dfe673d291f41d88816f37eb3c49 100644 (file)
@@ -257,7 +257,6 @@ snmp_sock_err(sock *sk, int UNUSED err)
 {
   snmp_log("socket error '%s' (errno: %d)", strerror(err), err);
   struct snmp_proto *p = sk->data;
-  p->errs++;
 
   snmp_sock_disconnect(p, 1);
 }
@@ -280,10 +279,6 @@ snmp_start_locked(struct object_lock *lock)
   p->state = SNMP_LOCKED;
   sock *s = p->sock;
 
-  p->to_send = 0;
-  p->errs = 0;
-
-
   if (!p->bgp_trie)
     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;
     s->data = p;
-
-    p->to_send = 0;
-    p->errs = 0;
   }
 
   /* 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);
   return PS_START;
 }
@@ -651,9 +644,9 @@ snmp_shutdown(struct proto *P)
  */
 
 struct protocol proto_snmp = {
-  .name =              "Snmp",
+  .name =              "SNMP",
   .template =          "snmp%d",
-  .channel_mask =      NB_ANY,
+  .channel_mask =      0,
   .proto_size =                sizeof(struct snmp_proto),
   .config_size =       sizeof(struct snmp_config),
   .postconfig =                snmp_postconfig,
index f8e12f70d712858436fffcf4f3b652799ca95a2e..dc4b75065849c74c7c2d94168b7174813f030fba 100644 (file)
@@ -116,6 +116,7 @@ struct snmp_proto {
   u32 bgp_local_as;
 
   sock *sock;
+  void *last_header;             /* points to partial PDU header */
   u8 timeout;                    /* timeout is part of MIB registration. It
                                    specifies how long should the master
                                    agent wait for request responses. */
@@ -139,9 +140,6 @@ struct snmp_proto {
   uint startup_delay;
   timer *startup_timer;
   u8 state;
-
-  uint to_send;
-  uint errs;
 };
 
 //void snmp_tx(sock *sk);
index 72880b8f2c5814d7b992dbe39072292caf31e15e..05585ec26686a0e85dbfad8e0667880cb6ee3b6a 100644 (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);
   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);
 
 #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;
       for (bulk_state.index = 0; bulk_state.index < 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 */
-  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. */
   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. */
   sk_send(sk, s);
@@ -1542,8 +1550,9 @@ parse_gets2_pdu(struct snmp_proto *p, byte * const pkt_start, uint size, uint *s
 
 partial:
   /* 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;
+  p->last_header = h;
 
   /* number of bytes parsed from RX-buffer */
   ret = pkt - pkt_start;
@@ -1897,6 +1906,9 @@ snmp_manage_tbuf(struct snmp_proto UNUSED *p, struct snmp_pdu *c)
 static struct agentx_response *
 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_header *h = &r->h;