From: Vojtech Vilimek Date: Tue, 2 Aug 2022 14:04:25 +0000 (+0200) Subject: TMP: proto-snmp compiles and connects to master X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e5a88b584e9f9e205a97854091fa315693f55014;p=thirdparty%2Fbird.git TMP: proto-snmp compiles and connects to master --- diff --git a/proto/snmp/Makefile b/proto/snmp/Makefile index 844f5a03b..f121af257 100644 --- a/proto/snmp/Makefile +++ b/proto/snmp/Makefile @@ -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 index 000000000..09def035c --- /dev/null +++ b/proto/snmp/bgp_mib.c @@ -0,0 +1,133 @@ +/* + * BIRD -- Simple Network Management Protocol (SNMP) + * BGP4-MIB bgpPeerTable + * + * (c) 2022 Vojtech Vilimek + * (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 +#include +#include +#include + +// 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 index 000000000..355ddb2dc --- /dev/null +++ b/proto/snmp/bgp_mib.h @@ -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 diff --git a/proto/snmp/config.Y b/proto/snmp/config.Y index e2d85f195..f50f314b6 100644 --- a/proto/snmp/config.Y +++ b/proto/snmp/config.Y @@ -20,8 +20,6 @@ CF_DECLS CF_KEYWORDS(SNMP, TABLE, PROTOCOL, BPG) -%type 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 diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index 3e8785fd6..1943c3a4a 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -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); } diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index e3101b8b8..57709f5b1 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -12,8 +12,20 @@ #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 index 000000000..af395c5ac --- /dev/null +++ b/proto/snmp/subagent.c @@ -0,0 +1,94 @@ +/* + * BIRD -- Simple Network Management Protocol (SNMP) + * + * (c) 2022 Vojtech Vilimek + * (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 + +#ifdef HAVE_SIGNAL +#include +#endif + +#ifdef HAV_SYS_STAT_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include + +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 index 000000000..9cd923572 --- /dev/null +++ b/proto/snmp/subagent.h @@ -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