]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
SNMP: subagent improvements
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Mon, 22 Jul 2024 16:17:16 +0000 (18:17 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Mon, 22 Jul 2024 16:17:16 +0000 (18:17 +0200)
proto/snmp/subagent.c
proto/snmp/subagent.h

index db77347c53dcb56991138ab8db0b38579281794d..b18c37d97b2d0a880580a5ae16a792f218d9f657 100644 (file)
 #include "snmp_utils.h"
 #include "bgp4_mib.h"
 
-/* =============================================================
- *  Problems
- *  ------------------------------------------------------------
- *
- *    change of remote ip -> no notification, no update (be careful in recofing)
- *    same ip, different ports
- *    distinct VRF (two interfaces with overlapping private addrs)
- *    posible link-local addresses in LOCAL_IP
- *
- *    context is allocated as copied, is it approach really needed? wouldn't it
- *     sufficient just use the context in rx-buffer?
- *
+/*
+ * Goals:
+ *  In current situation, we do not handle the dynamic BGP case.
  */
 
 /**
@@ -69,7 +60,7 @@ static struct agentx_response *prepare_response(struct snmp_proto *p, struct snm
 static void response_err_ind(struct snmp_proto *p, struct agentx_response *res, enum agentx_response_errs err, u16 ind);
 static uint update_packet_size(struct agentx_header *start, byte *end);
 
-/* standard SNMP internet prefix (1.3.6.1) */
+/* standard SNMP internet prefix (.1.3.6.1) */
 const u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
 
 static inline int
@@ -141,20 +132,6 @@ snmp_register_ack(struct snmp_proto *p, struct agentx_response *res, u8 class)
   }
 }
 
-/*
- * snmp_error - handle a malformed packet
- * @p: SNMP protocol instance
- *
- * We wait until all packets are send. Then we close the socket which also
- * closes the established session on given socket. Finally we try to start a new
- * session.
- */
-static inline void
-snmp_error(struct snmp_proto *p)
-{
-  snmp_reset(p);
-}
-
 /*
  * snmp_simple_response - send an agentx-Response-PDU with no data payload
  * @p: SNMP protocol instance
@@ -249,10 +226,8 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
   struct snmp_pdu c;
   snmp_pdu_context(&c, p, sk);
 
-#define UPTIME_SIZE \
-  sizeof( struct { u32 vb_type; u32 oid_hdr; u32 ids[4]; } )
-#define TRAP0_HEADER_SIZE \
-  sizeof( struct { u32 vb_type; u32 oid_hdr; u32 ids[6]; } )
+#define UPTIME_SIZE sizeof(STATIC_OID(4))
+#define TRAP0_HEADER_SIZE sizeof(STATIC_OID(6))
 
   uint sz = AGENTX_HEADER_SIZE + TRAP0_HEADER_SIZE + snmp_oid_size(oid) \
     + size;
@@ -276,18 +251,18 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
   if (include_uptime)
   {
     /* sysUpTime.0 oid */
-    struct oid uptime_oid = {
+    STATIC_OID(4) sys_up_time_0 = {
       .n_subid = 4,
       .prefix = SNMP_MGMT,
       .include = 0,
       .reserved = 0,
+      .ids = { SNMP_MIB_2, SNMP_SYSTEM, SNMP_SYS_UP_TIME, 0 },
     };
-    /* {mgmt}.mib-2.system.sysUpTime.sysUpTimeInstance (0) */
-    u32 uptime_ids[] = { 1, 1, 3, 0 };
+    struct oid *uptime_0 = (struct oid *) &sys_up_time_0;
 
-    struct agentx_varbind *vb = snmp_create_varbind(c.buffer, &uptime_oid);
-    for (uint i = 0; i < uptime_oid.n_subid; i++)
-      STORE_U32(vb->name.ids[i], uptime_ids[i]);
+    struct agentx_varbind *vb = snmp_create_varbind(c.buffer, uptime_0);
+    for (uint i = 0; i < uptime_0->n_subid; i++)
+      STORE_U32(vb->name.ids[i], uptime_0->ids[i]);
 
     /* TODO use time from last reconfiguration instead? [config->load_time] */
     btime uptime = current_time() - boot_time;
@@ -297,18 +272,18 @@ snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *data, uint size, in
   }
 
   /* snmpTrapOID.0 oid */
-  struct oid trap0 = {
+  STATIC_OID(6) snmp_trap_oid_0 = {
     .n_subid = 6,
-    .prefix = 6, /* snmpV2 */
+    .prefix = SNMP_V2,
     .include = 0,
     .reserved = 0,
+    .ids = { SNMP_MODULES, SNMP_ALARM_NEXT_INDEX, SNMP_MIB_OBJECTS, SNMP_TRAP, SNMP_TRAP_OID, 0 },
   };
-  /* {snmpV2}.snmpModules.snmpAlarmNextIndex.snmpMIBObjects.snmpTrap.snmpTrapIOD.0 */
-  u32 trap0_ids[] = { 3, 1, 1, 4, 1, 0 };
+  struct oid *trap_0 = (struct oid *) &snmp_trap_oid_0;
 
-  struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, &trap0);
-  for (uint i = 0; i < trap0.n_subid; i++)
-    STORE_U32(trap_vb->name.ids[i], trap0_ids[i]);
+  struct agentx_varbind *trap_vb = snmp_create_varbind(c.buffer, trap_0);
+  for (uint i = 0; i < trap_0->n_subid; i++)
+    STORE_U32(trap_vb->name.ids[i], trap_0->ids[i]);
   trap_vb->type = AGENTX_OBJECT_ID;
   snmp_put_oid(snmp_varbind_data(trap_vb), oid);
   ADVANCE(c.buffer, c.size, snmp_varbind_size_unsafe(trap_vb));
@@ -425,7 +400,7 @@ snmp_register(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, u8 i
  *
  * For more detailed description see un_register_pdu() function.
  */
-void 
+void
 snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, uint contid)
 {
   un_register_pdu(p, oid, bound, index, AGENTX_UNREGISTER_PDU, 0, contid);
@@ -436,7 +411,7 @@ snmp_unregister(struct snmp_proto *p, struct oid *oid, u32 bound, uint index, ui
  * @p: SNMP protocol instance
  * @reason: reason for closure
  */
-static void 
+static void
 close_pdu(struct snmp_proto *p, enum agentx_close_reasons reason)
 {
   sock *sk = p->sock;
@@ -559,7 +534,7 @@ parse_test_set_pdu(struct snmp_proto *p, byte * const pkt_start)
   if (c.error != AGENTX_RES_NO_ERROR)
   {
     response_err_ind(p, res, c.error, c.index + 1);
-    snmp_error(p);
+    snmp_reset(p);  // error
   }
   else if (all_possible)
   {
@@ -621,7 +596,7 @@ parse_sets_pdu(struct snmp_proto *p, byte * const pkt_start, enum agentx_respons
 
   /* Reset the connection on unrecoverable error */
   if (c.error != AGENTX_RES_NO_ERROR && c.error != err)
-    snmp_error(p);
+    snmp_reset(p);    /* error */
 
   return pkt - pkt_start;
 }
@@ -716,6 +691,7 @@ space_for_response(const sock *sk)
 static uint
 parse_pkt(struct snmp_proto *p, byte *pkt, uint size)
 {
+  snmp_log("parse_pkt %t", current_time());
   /* TX-buffer free space */
   if (size < AGENTX_HEADER_SIZE)
     return 0;
@@ -1280,6 +1256,8 @@ parse_gets_pdu(struct snmp_proto *p, byte * const pkt_start)
   /* We send the message in TX-buffer. */
   sk_send(sk, s);
 
+  snmp_log("gets send %t", current_time());
+
   // TODO think through the error state
 
   /* number of bytes parsed from RX-buffer */
@@ -1298,10 +1276,8 @@ snmp_start_subagent(struct snmp_proto *p)
   ASSUME(p->state == SNMP_OPEN);
 
   /* blank oid means unsupported */
-  struct oid *blank = snmp_oid_blank(p);
-  open_pdu(p, blank);
-
-  mb_free(blank);
+  STATIC_OID(0) blank = { 0 };
+  open_pdu(p, (struct oid *) &blank);
 }
 
 /*
index 21fd61d183dd37d90631ce105e59ce8d5035ed0b..6696d98c4955add6dbec7d52beb7da2c93c6f2df 100644 (file)
@@ -15,6 +15,7 @@ void snmp_ping(struct snmp_proto *p);
 #define SNMP_STATE_BGP 1
 #define SNMP_STATE_INVALID 2
 
+/* standard snmp internet prefix */
 #define SNMP_ISO         1           /* last of oid .1               */
 #define SNMP_ORG         3           /* last of oid .1.3             */
 #define SNMP_DOD         6           /* last of oid .1.3.6           */
@@ -22,9 +23,21 @@ void snmp_ping(struct snmp_proto *p);
 
 #define SNMP_MGMT        2           /* last of oid .1.3.6.1.2       */
 #define SNMP_MIB_2       1           /* last of oid .1.3.6.1.2.1     */
-#define SNMP_OSPF_MIB   14           /* part of oid .1.3.6.1.2.1.14  */
-#define SNMP_BGP4_MIB   15           /* part of oid .1.3.6.1.2.1.15  */
-#define SNMP_OSPFv3_MIB        192           /* part of oid .1.3.6.1.2.1.192 */
+#define SNMP_SYSTEM      1           /* last of oid .1.3.6.1.2.1.1   */
+#define SNMP_OSPF_MIB   14           /* last of oid .1.3.6.1.2.1.14  */
+#define SNMP_BGP4_MIB   15           /* last of oid .1.3.6.1.2.1.15  */
+#define SNMP_OSPFv3_MIB        192           /* last of oid .1.3.6.1.2.1.192 */
+
+/* sysUpTime */
+#define SNMP_SYS_UP_TIME  3          /* last of oid .1.3.6.1.2.1.1.3 */
+
+/* snmpTrapOID */
+#define SNMP_V2                  6           /* last of oid .1.3.6.1.6           */
+#define SNMP_MODULES     3           /* last of oid .1.3.6.1.6.3         */
+#define SNMP_ALARM_NEXT_INDEX 1              /* last of oid .1.3.6.1.6.3.1       */
+#define SNMP_MIB_OBJECTS  1          /* last of oid .1.3.6.1.6.3.1.1     */
+#define SNMP_TRAP        4           /* last of oid .1.3.6.1.6.3.1.1.4   */
+#define SNMP_TRAP_OID    1           /* last of oid .1.3.6.1.6.3.1.1.4.1 */
 
 extern const u32 snmp_internet[4];