]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
SNMP: BGP4-MIB notifications
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Mon, 4 Sep 2023 11:53:45 +0000 (13:53 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Mon, 4 Sep 2023 11:53:45 +0000 (13:53 +0200)
proto/snmp/bgp_mib.c
proto/snmp/bgp_mib.h
proto/snmp/subagent.c
proto/snmp/subagent.h

index 093b329fc2229a27eefd038223f721820b922d64..464fcf325f417b666a1921c9faa33aa6198ad031 100644 (file)
@@ -49,6 +49,73 @@ static const char * const debug_bgp_states[] UNUSED = {
   [BGP_INTERNAL_NO_VALUE]               = "BGP_INTERNAL_NO_VALUE",
 };
 
+static void
+snmp_bgp_notify_common(struct snmp_proto *p, uint type, ip4_addr ip4, char last_error[], uint state_val)
+{
+  // TODO remove heap allocation, put the data on stack
+
+#define SNMP_OID_SIZE_FROM_LEN(x) (sizeof(struct oid) + (x) * sizeof(u32))
+
+  /* trap OID bgpEstablishedNotification (.1.3.6.1.2.1.0.1) */
+  struct oid *head = mb_alloc(p->p.pool, SNMP_OID_SIZE_FROM_LEN(3));
+  head->n_subid = 3;
+  head->prefix = 2;
+  head->include = head->pad = 0;
+
+  u32 trap_ids[] = { 1, 0, type };
+  for (uint i = 0; i < head->n_subid; i++)
+    head->ids[i] = trap_ids[i];
+
+  /* OIDs, VB type headers, octet string, ip4 address, integer */
+  uint sz = 3 * SNMP_OID_SIZE_FROM_LEN(9) + 3 * 4 + 8 + 8 + 4;
+
+  /* Paylaod OIDs */
+
+  void *data = mb_alloc(p->p.pool, sz);
+  struct agentx_varbind *addr_vb = data;
+  /* +4 for varbind header, +8 for octet string */
+  struct agentx_varbind *error_vb = data + SNMP_OID_SIZE_FROM_LEN(9)  + 4 + 8;
+  struct agentx_varbind *state_vb = (void *) error_vb + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
+
+  addr_vb->pad = error_vb->pad = state_vb->pad = 0;
+
+  struct oid *addr = &addr_vb->name;
+  struct oid *error = &error_vb->name;
+  struct oid *state = &state_vb->name;
+
+  addr->n_subid = error->n_subid  = state->n_subid     = 9;
+  addr->prefix  = error->prefix   = state->prefix      = 2;
+  addr->include = error->include  = state->include     = 0;
+  addr->pad      = error->pad      = state->pad        = 0;
+
+  u32 oid_ids[] = {
+    SNMP_MIB_2, SNMP_BGP4_MIB, SNMP_BGP_PEER_TABLE, SNMP_BGP_PEER_ENTRY
+  };
+
+  for (uint i = 0; i < sizeof(oid_ids) / sizeof(oid_ids[0]); i++)
+    addr->ids[i] = error->ids[i] = state->ids[i] = oid_ids[i];
+
+  addr->ids[4]  = SNMP_BGP_REMOTE_ADDR;
+  error->ids[4] = SNMP_BGP_LAST_ERROR;
+  state->ids[4] = SNMP_BGP_STATE;
+
+  for (uint i = 0; i < 4; i++)
+    addr->ids[5 + i] = error->ids[5 + i] = state->ids[5 + i] \
+      = (ip4_to_u32(ip4) >> (8 * (3-i))) & 0xFF;
+
+  snmp_varbind_ip4(addr_vb, 100, ip4);
+
+  snmp_varbind_nstr(error_vb, 100, last_error, 2);
+
+  snmp_varbind_int(state_vb, 100, state_val);
+
+  snmp_notify_pdu(p, head, data, sz, 0);
+  mb_free(head);
+  mb_free(data);
+
+#undef SNMP_OID_SIZE_FROM_LEN
+}
+
 static inline uint
 snmp_bgp_fsm_state(struct bgp_proto *bgp_proto)
 {
@@ -68,6 +135,29 @@ snmp_bgp_fsm_state(struct bgp_proto *bgp_proto)
   return MAX(bgp_in->state, bgp_out->state);
 }
 
+static void
+snmp_bgp_notify_wrapper(struct snmp_proto *p, struct bgp_proto *bgp, uint type)
+{
+  // possibly dangerous
+  ip4_addr ip4 = ipa_to_ip4(bgp->remote_ip);
+  char last_error[2] = SNMP_BGP_LAST_ERROR(bgp);
+  uint state_val = snmp_bgp_fsm_state(bgp);
+  snmp_bgp_notify_common(p, type, ip4, last_error, state_val);
+}
+
+void
+snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp)
+{
+  /* .1.3.6.1.2.15.0.>1<  i.e. BGP4-MIB::bgpEstablishedNotification */
+  snmp_bgp_notify_wrapper(p, bgp, 1);
+}
+
+void
+snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp)
+{
+  /* .1.3.6.1.2.15.0.>2<  i.e. BGP4-MIB::bgpBackwardTransNotification */
+  snmp_bgp_notify_wrapper(p, bgp, 2);
+}
 
 void
 snmp_bgp_register(struct snmp_proto *p)
@@ -894,11 +984,8 @@ bgp_fill_dynamic(struct snmp_proto UNUSED *p, struct agentx_varbind *vb,
     return ((byte *) vb) + snmp_varbind_header_size(vb);
   }
 
-  struct bgp_conn *bgp_conn = bgp_proto->conn;
-  struct bgp_conn *bgp_in = &bgp_proto->incoming_conn;
-  struct bgp_conn *bgp_out = &bgp_proto->outgoing_conn;
-
-  struct bgp_stats *bgp_stats = &bgp_proto->stats;
+  const struct bgp_conn *bgp_conn = bgp_proto->conn;
+  const struct bgp_stats *bgp_stats = &bgp_proto->stats;
   const struct bgp_config *bgp_conf = bgp_proto->cf;
 
   uint bgp_state = snmp_bgp_fsm_state(bgp_proto);
index 1bca891f3a3934593f22ec60975d033c02f415f4..d22234981e93a3b69178f5b712345b51f9898952 100644 (file)
@@ -47,6 +47,9 @@ struct oid *snmp_bgp_search(struct snmp_proto *p, struct oid *o_start, struct oi
 enum snmp_search_res snmp_bgp_search2(struct snmp_proto *p, struct oid **searched, const struct oid *o_end, uint contid);
 void snmp_bgp_fill(struct snmp_proto *p, struct agentx_varbind *vb, struct snmp_pdu_context *c);
 
+void snmp_bgp_notify_established(struct snmp_proto *p, struct bgp_proto *bgp);
+void snmp_bgp_notify_backward_trans(struct snmp_proto *p, struct bgp_proto *bgp);
+
 #define SNMP_BGP_VERSION    1
 #define SNMP_BGP_LOCAL_AS   2
 #define SNMP_BGP_PEER_TABLE 3
index 66ebb4695e1803a268536cf92b0fd68729d4707c..5f6acf1ac00de8234f307c863859bfde8065591f 100644 (file)
@@ -36,7 +36,6 @@ static struct agentx_response *prepare_response(struct snmp_proto *p, struct snm
 static void response_err_ind(struct agentx_response *res, uint err, uint ind);
 static uint update_packet_size(struct snmp_proto *p, byte *start, byte *end);
 static struct oid *search_mib(struct snmp_proto *p, const struct oid *o_start, const struct oid *o_end, struct oid *o_curr, struct snmp_pdu_context *c, enum snmp_search_res *result);
-static void notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime);
 
 u32 snmp_internet[] = { SNMP_ISO, SNMP_ORG, SNMP_DOD, SNMP_INTERNET };
 
@@ -122,8 +121,8 @@ open_pdu(struct snmp_proto *p, struct oid *oid)
     snmp_log("sk_send error");
 }
 
-static void
-notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime)
+void
+snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime)
 {
   sock *sk = p->sock;
 
@@ -1227,64 +1226,6 @@ snmp_rx(sock *sk, uint size)
 void
 snmp_ping(struct snmp_proto *p)
 {
-  {
-#define SNMP_OID_SIZE_FROM_LEN(x) (sizeof(struct oid) + (x) * sizeof(u32))
-    /* trap OID bgpEstablishedNotification (.1.3.6.1.2.1.0.1) */
-    struct oid *head = mb_alloc(p->p.pool, SNMP_OID_SIZE_FROM_LEN(3));
-    head->n_subid = 3;
-    head->prefix = 2;
-    head->include = head->pad = 0;
-    
-    u32 trap_ids[] = { 1, 0, 1 };
-    for (uint i = 0; i < head->n_subid; i++)
-      head->ids[i] = trap_ids[i];    
-     
-    /* paylaod oids */
-    uint sz = 3 * SNMP_OID_SIZE_FROM_LEN(9) + 3 * 4 + 2 * 8 + 4 - 20;
-    void *data = mb_alloc(p->p.pool, sz);
-    struct agentx_varbind *addr_vb = data;
-    /* +4 for varbind header, +8 for octet string */
-    struct agentx_varbind *error_vb = data + SNMP_OID_SIZE_FROM_LEN(9)  + 4 + 8;
-    struct agentx_varbind *state_vb = (void *) error_vb + SNMP_OID_SIZE_FROM_LEN(9) + 4 + 8;
-#undef SNMP_OID_SIZE_FROM_LEN
-
-    addr_vb->pad = error_vb->pad = state_vb->pad = 0;
-
-    struct oid *addr = &addr_vb->name;
-    struct oid *error = &error_vb->name;
-    struct oid *state = &state_vb->name;
-
-    addr->n_subid = error->n_subid  = state->n_subid   = 9;
-    addr->prefix  = error->prefix   = state->prefix    = 2;
-    addr->include = error->include  = state->include   = 0;
-    addr->pad    = error->pad      = state->pad        = 0;
-
-    u32 oid_ids[] = {
-      SNMP_MIB_2, SNMP_BGP4_MIB, SNMP_BGP_PEER_TABLE, SNMP_BGP_PEER_ENTRY, 0,
-      10, 1, 2, 1
-    };
-    for (uint i = 0; i < addr->n_subid; i++)
-      addr->ids[i] = error->ids[i] = state->ids[i] = oid_ids[i];
-
-    addr->ids[4]  = SNMP_BGP_REMOTE_ADDR;
-    error->ids[4] = SNMP_BGP_LAST_ERROR;
-    state->ids[4] = SNMP_BGP_STATE;
-    
-    ip4_addr ip4 = ip4_build(10,1,2,1);
-    snmp_varbind_ip4(addr_vb, 100, ip4);  
-
-    char error_str[] = { 0, 0 };
-    snmp_varbind_nstr(error_vb, 100, error_str, 2);
-
-    snmp_varbind_int(state_vb, 100, 6);
-
-    u32 now = current_time() TO_S;
-    if (now % 4 == 0)
-      notify_pdu(p, head, data, sz, 1);
-    else if (now % 2 == 0)
-      notify_pdu(p, head, data, sz, 0);
-  }
-
   sock *sk = p->sock;
   snmp_dump_packet(sk->tpos, AGENTX_HEADER_SIZE + 4);
   snmp_log("snmp_ping sk->tpos 0x%p", sk->tpos);
index 57e1f5eb58a2db8ce5d5f050a9e81a4d3d518cce..d23d2d8ef3ee3046ab84d5d3d31fc0eb6bfd419c 100644 (file)
@@ -322,6 +322,8 @@ void snmp_manage_tbuf(struct snmp_proto *p, struct snmp_pdu_context *c);
 struct oid *snmp_prefixize(struct snmp_proto *p, const struct oid *o, int byte_ord);
 u8 snmp_get_mib_class(const struct oid *oid);
 
+void snmp_notify_pdu(struct snmp_proto *p, struct oid *oid, void *opaque, uint size, int include_uptime);
+
 // debug wrapper
 #define snmp_log(...) log(L_INFO "snmp " __VA_ARGS__)