]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
TMP: proto-snmp compiles and connects to master
authorVojtech Vilimek <vojtech.vilimek@nic.cz>
Tue, 2 Aug 2022 14:04:25 +0000 (16:04 +0200)
committerVojtech Vilimek <vojtech.vilimek@nic.cz>
Tue, 2 Aug 2022 14:06:00 +0000 (16:06 +0200)
proto/snmp/Makefile
proto/snmp/bgp_mib.c [new file with mode: 0644]
proto/snmp/bgp_mib.h [new file with mode: 0644]
proto/snmp/config.Y
proto/snmp/snmp.c
proto/snmp/snmp.h
proto/snmp/subagent.c [new file with mode: 0644]
proto/snmp/subagent.h [new file with mode: 0644]

index 844f5a03b34a6ed5eb7b8ff1b79e7772b7b106be..f121af2576140afd7762a321628e7702525defe7 100644 (file)
@@ -1,7 +1,8 @@
-src := snmp.c
+src := snmp.c bgp_mib.c subagent.c
 obj := $(src-o-files)
+LIBS += `net-snmp-config --agent-libs`
 $(all-daemon)
 $(cf-local)
-$(call proto-build,snmp_build)
+$(call proto-build,snmp_build_)
 
 tests_objs := $(tests_objs) $(src-o-files)
diff --git a/proto/snmp/bgp_mib.c b/proto/snmp/bgp_mib.c
new file mode 100644 (file)
index 0000000..09def03
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *     BIRD -- Simple Network Management Protocol (SNMP)
+ *        BGP4-MIB bgpPeerTable
+ *
+ *      (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
+ *      (c) 2022 CZ.NIC z.s.p.o
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ *
+ *      Parts of this file were auto-generated using mib2c
+ *      using mib2c.create-dataset.conf
+ */
+
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/varbind_api.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+// fix conflicts
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
+#include "proto/snmp/bgp_mib.h"
+#include "lib/birdlib.h"
+
+static int
+bgpPeerTable_handler(
+  netsnmp_mib_handler               *handler, // contains void * for internal use
+  netsnmp_handler_registration      *reginfo,
+  netsnmp_agent_request_info        *reqinfo,
+  netsnmp_request_info              *requests) {
+
+  /* perform anything here that you need to do.  The requests have
+     already been processed by the master table_dataset handler, but
+     this gives you chance to act on the request in some other way
+     if need be. */
+
+  log(L_INFO " bgpPeerTable_handler()");
+  // walk list of netsnmp_data_list
+  for (netsnmp_data_list *l = reqinfo->agent_data;
+       l; l->next)
+  {
+    log(L_INFO " name: %s,  poniter %p", l->name, l->data);
+  }
+
+  char buff[64];
+  // walk list of netsnmp_variable_list VB
+  for (netsnmp_variable_list *var = requests->requestvb;
+       var; var->next_variable)
+  {
+    snprint_value(buff, 64, var->name, var->name_length, var);
+    log(L_INFO "variable %s", buff);
+    memset((void *) buff, 0, 64);
+  }
+
+  return SNMP_ERR_NOERROR;
+}
+
+void
+snmp_init_bgp_table(void)
+{
+  const oid bgpPeerTable_oid[] = {1,3,6,1,2,1,15,3};
+  netsnmp_table_data_set *table_set;
+
+  /* create the table structure itself */
+  table_set = netsnmp_create_table_data_set("bgpPeerTable");
+
+  log(L_INFO "adding indexes to SNMP table bgpPeerTable");
+
+  netsnmp_table_set_add_indexes(
+    table_set,
+    ASN_IPADDRESS,  /* index: bgpPeerRemoteAddr */
+    0
+  );
+
+  log(L_INFO "adding column types to SNMP table bgpPeerTable");
+  netsnmp_table_set_multi_add_default_row(
+    table_set,
+    SNMP_BGP_IDENTIFIER, ASN_IPADDRESS, 0, NULL, 0,
+    SNMP_BGP_STATE, ASN_INTEGER, 0, NULL, 0,
+    /* change to ASN_INTEGER, 1, NULL, 0, below to allow write */
+    SNMP_BGP_ADMIN_STATUS, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_VERSION, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_LOCAL_ADDR, ASN_IPADDRESS, 0, NULL, 0,
+    SNMP_BGP_LOCAL_PORT, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_REMOTE_ADDR, ASN_IPADDRESS, 0, NULL, 0,
+    SNMP_BGP_REMOTE_PORT, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_REMOTE_AS, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_RX_UPDATES, ASN_COUNTER, 0, NULL, 0,
+    SNMP_BGP_TX_UPDATES, ASN_COUNTER, 0, NULL, 0,
+    SNMP_BGP_RX_MESSAGES, ASN_COUNTER, 0, NULL, 0,
+    SNMP_BGP_TX_MESSAGES, ASN_COUNTER, 0, NULL, 0,
+    SNMP_BGP_LAST_ERROR, ASN_OCTET_STR, 0, NULL, 0,
+    SNMP_BGP_FSM_TRANSITIONS, ASN_COUNTER, 0, NULL, 0,
+    SNMP_BGP_FSM_ESTABLISHED_TIME, ASN_GAUGE, 0, NULL, 0,
+    SNMP_BGP_RETRY_INTERVAL, ASN_INTEGER, 1, NULL, 0,
+    SNMP_BGP_HOLD_TIME, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_KEEPALIVE, ASN_INTEGER, 0, NULL, 0,
+    SNMP_BGP_HOLD_TIME_CONFIGURED, ASN_INTEGER, 1, NULL, 0,
+    SNMP_BGP_KEEPALIVE_CONFIGURED, ASN_INTEGER, 1, NULL, 0,
+    SNMP_BGP_ORIGINATION_INTERVAL, ASN_INTEGER, 1, NULL, 0,
+    SNMP_BGP_MIN_ROUTE_ADVERTISEMENT, ASN_INTEGER, 1, NULL, 0,
+    SNMP_BGP_MIN_UPDATE_ELAPSED_TIME, ASN_GAUGE, 0, NULL, 0,
+    0
+  );
+
+  /* registering the table with the master agent */
+  /* note: if you don't need a subhandler to deal with any aspects
+     of the request, change bgpPeerTable_handler to "NULL" */
+  netsnmp_register_table_data_set(
+    netsnmp_create_handler_registration(
+      "bgpPeerTable", bgpPeerTable_handler,
+      bgpPeerTable_oid,
+      OID_LENGTH(bgpPeerTable_oid),
+      HANDLER_CAN_RONLY
+      // HANDLER_CAN_RWRITE
+    ),
+    table_set, NULL
+  );
+}
+
+void
+snmp_del_bgp_table(void)
+{  
+  // XXX really needed ?
+  const oid bgpPeerTable_oid[] = {1,3,6,1,2,1,15,3};
+
+  remove_tree_entry(bgpPeerTable_oid, OID_LENGTH(bgpPeerTable_oid));
+}
diff --git a/proto/snmp/bgp_mib.h b/proto/snmp/bgp_mib.h
new file mode 100644 (file)
index 0000000..355ddb2
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _BIRD_SNMP_BGP_MIB_H_
+#define _BIRD_SNMP_BGP_MIB_H_
+
+/* peers attributes */
+#define SNMP_BGP_IDENTIFIER 1
+#define SNMP_BGP_STATE 2
+#define SNMP_BGP_ADMIN_STATUS 3                    /* in read-only mode */
+#define SNMP_BGP_VERSION 4
+#define SNMP_BGP_LOCAL_ADDR 5
+#define SNMP_BGP_LOCAL_PORT 6
+#define SNMP_BGP_REMOTE_ADDR 7
+#define SNMP_BGP_REMOTE_PORT 8
+#define SNMP_BGP_REMOTE_AS 9
+#define SNMP_BGP_RX_UPDATES 10             /* in updates */
+#define SNMP_BGP_TX_UPDATES 11             /* out updates */
+#define SNMP_BGP_RX_MESSAGES 12                    /* in total messages */
+#define SNMP_BGP_TX_MESSAGES 13                    /* out total messages */
+#define SNMP_BGP_LAST_ERROR 14             /* UNSUPPORTED */
+#define SNMP_BGP_FSM_TRANSITIONS 15        /* FSM established transitions */
+#define SNMP_BGP_FSM_ESTABLISHED_TIME 16    /* UNSUPPORTED FSM established time */
+#define SNMP_BGP_RETRY_INTERVAL 17               
+#define SNMP_BGP_HOLD_TIME 18            
+#define SNMP_BGP_KEEPALIVE 19            
+#define SNMP_BGP_HOLD_TIME_CONFIGURED 20         
+#define SNMP_BGP_KEEPALIVE_CONFIGURED 21  
+#define SNMP_BGP_ORIGINATION_INTERVAL 22    /* UNSUPPORTED */
+#define SNMP_BGP_MIN_ROUTE_ADVERTISEMENT 23 /* UNSUPPORTED */
+#define SNMP_BGP_MIN_UPDATE_ELAPSED_TIME 24 /* UNSUPPORTED */
+
+void snmp_init_bgp_table(void);
+void snmp_del_bgp_table(void);
+
+#endif
index e2d85f195415377e51ce5394b20522072fc1a167..f50f314b62192e15bd5a40df27db751b63c2ad70 100644 (file)
@@ -20,8 +20,6 @@ CF_DECLS
 
 CF_KEYWORDS(SNMP, TABLE, PROTOCOL, BPG)
 
-%type <cc> snmp_channel_start
-
 CF_GRAMMAR
 
 proto: snmp_proto '}' { this_channel = NULL; }  ;
@@ -29,46 +27,29 @@ proto: snmp_proto '}' { this_channel = NULL; }  ;
 snmp_proto:
    snmp_proto_start '{'
  | snmp_proto proto_item ';'
- | snmp_proto snmp_proto_channel ';'
+ | snmp_proto snmp_bgp_bond ';'
  | snmp_proto  ';'
  ;
 
 snmp_proto_start: proto_start SNMP
 {
   this_proto = proto_config_new(&proto_snmp, $1);
+  init_list(&SNMP_CFG->bgp_entries);
 }
 
-snmp_proto_channel: snmp_channel_start snmp_channel_opt_list channel_end ;
-
-snmp_channel_start: net_type symbol
+snmp_bgp_bond: BGP symbol
 {
-  this_channel = channel_config_get(&channel_snmp, $2->name, $1, this_proto);
-}
-
-snmp_channel_opt_list:
-    /* empty */
-  | '{' snmp_opts '}'
-  ;
+  struct snmp_bond *this_bond = cfg_alloc(sizeof(struct snmp_bond));
+  this_bond->type = SNMP_BGP;
 
-snmp_opts:
-    /* empty */
-  | snmp_opts channel_item ';'
-  | snmp_opts snmp_opt ';'
-  ;
+  struct proto_config *pc;
+  WALK_LIST(pc, this_proto->global->protos)
+    if (!strcmp(pc->name, $2->name) && pc->protocol == &proto_bgp)
+      this_bond->proto = pc;
 
-snmp_opt:
-    PROTOCOL BGP symbol {
-      SNMP_CC->bgp = NULL;
-
-      struct proto_config *pc;
-      WALK_LIST(pc, this_proto->global->protos)
-       if (!strcmp(pc->name, $3->name)
-           && pc->protocol == &proto_bgp)
-         SNMP_CC->bgp = (struct bgp_config *) pc;
-
-      if (!SNMP_CC->bgp) cf_error("BGP protocol %s not found", $3);
-    }
-  ;
+  if (!this_bond->proto) cf_error("BGP protocol %s not found", $2->name);
+  add_tail(&SNMP_CFG->bgp_entries, (node *) this_bond);
+}
 
 CF_CODE
 
index 3e8785fd6cc8eed16124c60f7004caec19c25eff..1943c3a4aa0aa55faf5e7aa1a2a29bb8469f8023 100644 (file)
@@ -5,6 +5,9 @@
  *      (c) 2022 CZ.NIC z.s.p.o.
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
+ *
+ *      Parts of this file were auto-generated using mib2c
+ *      using mib2c.create-dataset.conf
  */
 
 #include "nest/bird.h"
@@ -12,6 +15,8 @@
 #include "nest/cli.h"
 
 #include "proto/snmp/snmp.h"
+#include "proto/snmp/subagent.h"
+#include "proto/snmp/bgp_mib.h"
 
 static struct proto *
 snmp_init(struct proto_config *CF)
@@ -24,17 +29,23 @@ snmp_init(struct proto_config *CF)
   return P;
 }
 
+void start_multihook(void)
+{
+  /* init bgp MIB table */
+  snmp_init_bgp_table();
+
+  /* init ospf MIB table */
+  //snmp_inti_ospf_table();
+}
+
 static int
 snmp_start(struct proto *P)
 {
-  struct channel_config *cc;
-  WALK_LIST(cc, P->cf->channels)
-  {
-    struct channel *c = NULL;
-    proto_configure_channel(P, &c, cc);
-  }
-
-  return PS_UP;
+  /* init MIB tables */
+  if (snmp_start_subagent(start_multihook))
+    return PS_UP;
+  else
+    return PS_DOWN;
 }
 
 static int
@@ -46,42 +57,83 @@ snmp_reconfigure(struct proto *P, struct proto_config *CF)
 static void
 snmp_show_proto_info(struct proto *P)
 {
-  //struct stats_proto *p = (void *) P;
-
-  struct snmp_channel *sc;
+  struct snmp_proto *sp = (void *) P;
+  struct snmp_config *c = (void *) P->cf;
 
-  WALK_LIST(sc, P->channels)
+  cli_msg(-1006, "  BGP peers");
+  struct snmp_bond *bond;
+  WALK_LIST(bond, c->bgp_entries)
   {
-    cli_msg(-1006, "  Channel %s", sc->c.name);
-
-    if (!P->disabled)
-    {
-      cli_msg(-1006, "    enabled");
+    struct proto_config *cf = P->cf;
+    struct bgp_config *bcf = (struct bgp_config *) cf;
+    struct proto_config *pcf = (void *) bond->proto;
+    struct proto *p = cf->proto;
+    struct bgp_proto *bp = (struct bgp_proto *) cf->proto;
+    struct bgp_conn *conn = bp->conn;
+
+    cli_msg(-1006, "    name: %s", cf->name);
+    cli_msg(-1006, "");
+    cli_msg(-1006, "    rem. identifier: %u", bp->remote_id);
+    // learn more !!
+    cli_msg(-1006, "    admin status: %s", (p->disabled) ? "start" :
+             "stop");
+    // version ?
+    cli_msg(-1006, "    version: ??, likely 4");
+    cli_msg(-1006, "    local ip: %u", bcf->local_ip);
+    cli_msg(-1006, "    remote ip: %u", bcf->remote_ip);
+    cli_msg(-1006, "    local port: %u", bcf->local_port);
+    cli_msg(-1006, "    remote port: %u", bcf->remote_port);
+    if (conn) {
+      cli_msg(-1006, "    state: %u", conn->state);
+      cli_msg(-1006, "    remote as: %u", conn->remote_caps->as4_number);
+    }
+    cli_msg(-1006, "    in updates: %u", bp->stats.rx_updates);
+    cli_msg(-1006, "    out updates: %u", bp->stats.tx_updates);
+    cli_msg(-1006, "    in total: %u", bp->stats.rx_messages);
+    cli_msg(-1006, "    out total: %u", bp->stats.tx_messages);
+    cli_msg(-1006, "    fsm transitions: %u",
+bp->stats.fsm_established_transitions);
+
+    // not supported yet
+    cli_msg(-1006, "    fsm total time: --");
+    cli_msg(-1006, "    retry interval: %u", bcf->connect_retry_time);
+
+    if (conn) {
+      cli_msg(-1006, "    hold time: %u", conn->hold_time);
+      cli_msg(-1006, "    keep alive: %u", conn->keepalive_time );
     }
-    else
-      cli_msg(-1006, "    disabled");
+
+    cli_msg(-1006, "    hold configurated: %u", bcf->hold_time );
+    cli_msg(-1006, "    keep alive config: %u", bcf->keepalive_time );
+
+    // unknown
+    cli_msg(-1006, "    min AS origin. int.: --");
+    cli_msg(-1006, "    min route advertisement: %u", 0 );
+    cli_msg(-1006, "    in update elapsed time: %u", 0 );
+
+    if (!conn)
+      cli_msg(-1006, "  no default connection");
+
+    cli_msg(-1006, "  outgoinin_conn state %u", bp->outgoing_conn.state + 1);
+    cli_msg(-1006, "  incoming_conn state: %u", bp->incoming_conn.state + 1);
   }
 }
 
-static int
-snmp_channel_start(struct channel *C)
+
+void
+shutdown_multihook(void)
 {
-  return 0;
+  snmp_del_bgp_table();
+  //snmp_del_ospf_table();
 }
 
-static void
-snmp_channel_shutdown(struct channel *C)
+/* snmp_shutdown already occupied by net-snmp */
+void
+snmp_shutdown_(struct proto *P)
 {
-
+  snmp_stop_subagent(shutdown_multihook); 
 }
 
-struct channel_class channel_snmp = {
-  .channel_size =      sizeof(struct snmp_channel),
-  .config_size =       sizeof(struct snmp_channel_config),
-  .start =             snmp_channel_start,
-  .shutdown =          snmp_channel_shutdown,
-};
-
 struct protocol proto_snmp = {
   .name =              "Snmp",
   .template =          "snmp%d",
@@ -91,11 +143,13 @@ struct protocol proto_snmp = {
   .init =              snmp_init,
   .start =             snmp_start,
   .reconfigure =       snmp_reconfigure,
+  .shutdown =          snmp_shutdown_,
   .show_proto_info =   snmp_show_proto_info,
 };
 
+/* strange name because conflict with net-snmp lib snmp_lib() */
 void
-snmp_build(void)
+snmp_build_(void)
 {
   proto_build(&proto_snmp);
 }
index e3101b8b8721d42b8ee1534369b0c5c5bce3072a..57709f5b1e4111e30d9758a6b8872284d8efe224 100644 (file)
 
 #include "proto/bgp/bgp.h"
 
+#define SNMP_UNDEFINED 0
+#define SNMP_BGP       1
+#define SNMP_OSPF      2
+#define SNMP_INVALID  255
+
+struct snmp_bond {
+  node n;
+  struct proto_config *proto;
+  u8 type;
+};
+
 struct snmp_config {
   struct channel_config c;
+  list bgp_entries;
 };
 
 struct snmp_proto {
@@ -24,6 +36,7 @@ struct snmp_proto {
 struct snmp_channel_config {
   struct channel_config c;
   struct bgp_config *bgp;
+  u8 type;
 };
 
 struct snmp_channel {
diff --git a/proto/snmp/subagent.c b/proto/snmp/subagent.c
new file mode 100644 (file)
index 0000000..af395c5
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *     BIRD -- Simple Network Management Protocol (SNMP)
+ *
+ *      (c) 2022 Vojtech Vilimek <vojtech.vilimek@nic.cz>
+ *      (c) 2022 CZ.NIC z.s.p.o
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ *
+ *      Parts of this file were auto-generated from net-snmp-config
+ */
+
+#include <net-snmp/net-snmp-config.h>
+
+#ifdef HAVE_SIGNAL
+#include <signal.h>
+#endif
+
+#ifdef HAV_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+extern int netsnmp_running;
+
+int
+snmp_start_subagent(void (*hook)(void))
+{
+  /* subagent mode */
+  netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
+                        NETSNMP_DS_AGENT_ROLE, 1);
+
+  /* forking netsnmp mechanism  * /
+    if (netsnmp_daemonize(1, snmp_stderrolog_status()) != 0)
+      return 0;   // start FAILED
+   */
+
+  /* for Win32 only */
+  SOCK_STARTUP; 
+
+  /* init library */
+  init_agent("bird");
+  if (hook) 
+    hook();
+
+  /* used for loading config 'bird-snmp.conf' */
+  init_snmp("bird-snmp");
+
+  return 1;   // SUCCESS
+}
+
+void
+snmp_agent_reconfigure(void)
+{
+  free_config();
+  read_configs();
+}
+
+void
+snmp_shutdown_subagent(void (*hook)(void))
+{
+  /* at shutdown time */
+  snmp_shutdown("bird");
+
+  /* shutdown hook */
+  if (hook)
+    hook();
+
+  /* shutdown the agent library */
+  shutdown_agent();
+
+  /* for Win32 only */
+  SOCK_CLEANUP;
+}
+
+void
+snmp_stop_subagent(void (*hook)(void))
+{
+  /* at shutdown time */
+  snmp_shutdown("bird");
+
+  /* deinitialize MIB code */
+  if (hook)
+    hook();
+
+  /* shutdown the agent library */
+  shutdown_agent();
+}
diff --git a/proto/snmp/subagent.h b/proto/snmp/subagent.h
new file mode 100644 (file)
index 0000000..9cd9235
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _BIRD_SNMP_SUBAGENT_H_
+#define _BIRD_SNMP_SUBAGENT_H_
+
+int snmp_start_subagent(void (*hook)(void));
+void snmp_agent_reconfigure(void);
+void snmp_stop_subagent(void (*hook)(void));
+
+#endif