From ff18b7b078e1f195d923db1ad5c1c68f1eb453de Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sun, 13 Nov 2022 21:57:22 +0200 Subject: [PATCH] bgpd: Implement SNMP BGP4V2-MIB (bgp4V2PeerEntry) http://www.circitor.fr/Mibs/Mib/B/BGP4V2-MIB.mib Compared with Arista BGP4V2-MIB implementation, almost identical (despite that Arista has slightly some additional MIBs). Example: ``` iso.3.6.1.3.5.1.1.2.1.1.1.4.192.168.10.64 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.1.1.4.192.168.10.65 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.1.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.1.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.1.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.2.1.4.192.168.10.64 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.2.1.4.192.168.10.65 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.2.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.2.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.2.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.3.1.4.192.168.10.64 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.3.1.4.192.168.10.65 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.3.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 01 23 00 00 00 00 00 00 00 00 00 01 iso.3.6.1.3.5.1.1.2.1.3.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.3.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.4.1.4.192.168.10.64 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.4.1.4.192.168.10.65 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.4.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.4.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.4.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = INTEGER: 0 iso.3.6.1.3.5.1.1.2.1.5.1.4.192.168.10.64 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.5.1.4.192.168.10.65 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.5.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 2A 02 47 80 01 23 00 00 00 00 00 00 00 00 00 02 iso.3.6.1.3.5.1.1.2.1.5.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.5.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.6.1.4.192.168.10.64 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.6.1.4.192.168.10.65 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.6.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Gauge32: 179 iso.3.6.1.3.5.1.1.2.1.6.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.6.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.7.1.4.192.168.10.64 = Gauge32: 65000 iso.3.6.1.3.5.1.1.2.1.7.1.4.192.168.10.65 = Gauge32: 65000 iso.3.6.1.3.5.1.1.2.1.7.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65000 iso.3.6.1.3.5.1.1.2.1.7.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Gauge32: 65000 iso.3.6.1.3.5.1.1.2.1.7.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Gauge32: 65000 iso.3.6.1.3.5.1.1.2.1.8.1.4.192.168.10.64 = Hex-STRING: C0 00 02 FC iso.3.6.1.3.5.1.1.2.1.8.1.4.192.168.10.65 = Hex-STRING: C0 00 02 FC iso.3.6.1.3.5.1.1.2.1.8.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: C0 00 02 FC iso.3.6.1.3.5.1.1.2.1.8.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Hex-STRING: C0 00 02 FC iso.3.6.1.3.5.1.1.2.1.8.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Hex-STRING: C0 00 02 FC iso.3.6.1.3.5.1.1.2.1.9.1.4.192.168.10.64 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.9.1.4.192.168.10.65 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.9.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Gauge32: 54814 iso.3.6.1.3.5.1.1.2.1.9.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.9.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Gauge32: 0 iso.3.6.1.3.5.1.1.2.1.10.1.4.192.168.10.64 = Gauge32: 65002 iso.3.6.1.3.5.1.1.2.1.10.1.4.192.168.10.65 = Gauge32: 65002 iso.3.6.1.3.5.1.1.2.1.10.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Gauge32: 65002 iso.3.6.1.3.5.1.1.2.1.10.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Gauge32: 65001 iso.3.6.1.3.5.1.1.2.1.10.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Gauge32: 65001 iso.3.6.1.3.5.1.1.2.1.11.1.4.192.168.10.64 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.11.1.4.192.168.10.65 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.11.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = STRING: "dddd" iso.3.6.1.3.5.1.1.2.1.11.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.11.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = Hex-STRING: 00 00 00 00 iso.3.6.1.3.5.1.1.2.1.12.1.4.192.168.10.64 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.12.1.4.192.168.10.65 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.12.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.12.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.12.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = INTEGER: 2 iso.3.6.1.3.5.1.1.2.1.13.1.4.192.168.10.64 = INTEGER: 1 iso.3.6.1.3.5.1.1.2.1.13.1.4.192.168.10.65 = INTEGER: 3 iso.3.6.1.3.5.1.1.2.1.13.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = INTEGER: 1 iso.3.6.1.3.5.1.1.2.1.13.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.121 = INTEGER: 3 iso.3.6.1.3.5.1.1.2.1.13.2.16.42.12.47.7.72.150.6.102.0.0.0.0.0.0.177.128 = INTEGER: 1 iso.3.6.1.3.5.1.1.2.1.14.1.4.192.168.10.64 = Hex-STRING: 4F 4B 00 iso.3.6.1.3.5.1.1.2.1.14.1.4.192.168.10.65 = Hex-STRING: 4F 4B 32 00 iso.3.6.1.3.5.1.1.2.1.14.2.16.42.2.71.128.1.35.0.0.0.0.0.0.0.0.0.2 = Hex-STRING: 69 70 76 36 00 ``` Signed-off-by: Donatas Abraitis --- bgpd/bgp_snmp.c | 858 +---------------------------------------- bgpd/bgp_snmp.h | 32 ++ bgpd/bgp_snmp_bgp4.c | 814 ++++++++++++++++++++++++++++++++++++++ bgpd/bgp_snmp_bgp4.h | 90 +++++ bgpd/bgp_snmp_bgp4v2.c | 455 ++++++++++++++++++++++ bgpd/bgp_snmp_bgp4v2.h | 97 +++++ bgpd/subdir.am | 5 +- lib/smux.h | 10 +- 8 files changed, 1505 insertions(+), 856 deletions(-) create mode 100644 bgpd/bgp_snmp.h create mode 100644 bgpd/bgp_snmp_bgp4.c create mode 100644 bgpd/bgp_snmp_bgp4.h create mode 100644 bgpd/bgp_snmp_bgp4v2.c create mode 100644 bgpd/bgp_snmp_bgp4v2.h diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 6bc313464a..b202ec2e17 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -40,864 +40,16 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_route.h" #include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_snmp.h" +#include "bgpd/bgp_snmp_bgp4.h" +#include "bgpd/bgp_snmp_bgp4v2.h" #include "bgpd/bgp_mplsvpn_snmp.h" -/* BGP4-MIB described in RFC1657. */ -#define BGP4MIB 1,3,6,1,2,1,15 - -/* BGP TRAP. */ -#define BGPESTABLISHED 1 -#define BGPBACKWARDTRANSITION 2 - -/* BGP MIB bgpVersion. */ -#define BGPVERSION 0 - -/* BGP MIB bgpLocalAs. */ -#define BGPLOCALAS 0 - -/* BGP MIB bgpPeerTable. */ -#define BGPPEERIDENTIFIER 1 -#define BGPPEERSTATE 2 -#define BGPPEERADMINSTATUS 3 -#define BGPPEERNEGOTIATEDVERSION 4 -#define BGPPEERLOCALADDR 5 -#define BGPPEERLOCALPORT 6 -#define BGPPEERREMOTEADDR 7 -#define BGPPEERREMOTEPORT 8 -#define BGPPEERREMOTEAS 9 -#define BGPPEERINUPDATES 10 -#define BGPPEEROUTUPDATES 11 -#define BGPPEERINTOTALMESSAGES 12 -#define BGPPEEROUTTOTALMESSAGES 13 -#define BGPPEERLASTERROR 14 -#define BGPPEERFSMESTABLISHEDTRANSITIONS 15 -#define BGPPEERFSMESTABLISHEDTIME 16 -#define BGPPEERCONNECTRETRYINTERVAL 17 -#define BGPPEERHOLDTIME 18 -#define BGPPEERKEEPALIVE 19 -#define BGPPEERHOLDTIMECONFIGURED 20 -#define BGPPEERKEEPALIVECONFIGURED 21 -#define BGPPEERMINROUTEADVERTISEMENTINTERVAL 22 -#define BGPPEERINUPDATEELAPSEDTIME 23 - -/* BGP MIB bgpIdentifier. */ -#define BGPIDENTIFIER 0 - -/* BGP MIB bgpRcvdPathAttrTable */ -#define BGPPATHATTRPEER 1 -#define BGPPATHATTRDESTNETWORK 2 -#define BGPPATHATTRORIGIN 3 -#define BGPPATHATTRASPATH 4 -#define BGPPATHATTRNEXTHOP 5 -#define BGPPATHATTRINTERASMETRIC 6 - -/* BGP MIB bgp4PathAttrTable. */ -#define BGP4PATHATTRPEER 1 -#define BGP4PATHATTRIPADDRPREFIXLEN 2 -#define BGP4PATHATTRIPADDRPREFIX 3 -#define BGP4PATHATTRORIGIN 4 -#define BGP4PATHATTRASPATHSEGMENT 5 -#define BGP4PATHATTRNEXTHOP 6 -#define BGP4PATHATTRMULTIEXITDISC 7 -#define BGP4PATHATTRLOCALPREF 8 -#define BGP4PATHATTRATOMICAGGREGATE 9 -#define BGP4PATHATTRAGGREGATORAS 10 -#define BGP4PATHATTRAGGREGATORADDR 11 -#define BGP4PATHATTRCALCLOCALPREF 12 -#define BGP4PATHATTRBEST 13 -#define BGP4PATHATTRUNKNOWN 14 - -/* SNMP value hack. */ -#define INTEGER ASN_INTEGER -#define INTEGER32 ASN_INTEGER -#define COUNTER32 ASN_COUNTER -#define OCTET_STRING ASN_OCTET_STR -#define IPADDRESS ASN_IPADDRESS -#define GAUGE32 ASN_UNSIGNED - -/* Declare static local variables for convenience. */ -SNMP_LOCAL_VARIABLES - -/* BGP-MIB instances. */ -static oid bgp_oid[] = {BGP4MIB}; -static oid bgp_trap_oid[] = {BGP4MIB, 0}; - -/* IP address 0.0.0.0. */ -static struct in_addr bgp_empty_addr = {.s_addr = 0}; - -/* Hook functions. */ -static uint8_t *bgpVersion(struct variable *, oid[], size_t *, int, size_t *, - WriteMethod **); -static uint8_t *bgpLocalAs(struct variable *, oid[], size_t *, int, size_t *, - WriteMethod **); -static uint8_t *bgpPeerTable(struct variable *, oid[], size_t *, int, size_t *, - WriteMethod **); -static uint8_t *bgpRcvdPathAttrTable(struct variable *, oid[], size_t *, int, - size_t *, WriteMethod **); -static uint8_t *bgpIdentifier(struct variable *, oid[], size_t *, int, size_t *, - WriteMethod **); -static uint8_t *bgp4PathAttrTable(struct variable *, oid[], size_t *, int, - size_t *, WriteMethod **); -/* static uint8_t *bgpTraps (); */ - -static struct variable bgp_variables[] = { - /* BGP version. */ - {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, 1, {1}}, - /* BGP local AS. */ - {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, 1, {2}}, - /* BGP peer table. */ - {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 1}}, - {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 2}}, - {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, 3, {3, 1, 3}}, - {BGPPEERNEGOTIATEDVERSION, - INTEGER32, - RONLY, - bgpPeerTable, - 3, - {3, 1, 4}}, - {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 5}}, - {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 6}}, - {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 7}}, - {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 8}}, - {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 9}}, - {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 10}}, - {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 11}}, - {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 12}}, - {BGPPEEROUTTOTALMESSAGES, - COUNTER32, - RONLY, - bgpPeerTable, - 3, - {3, 1, 13}}, - {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, 3, {3, 1, 14}}, - {BGPPEERFSMESTABLISHEDTRANSITIONS, - COUNTER32, - RONLY, - bgpPeerTable, - 3, - {3, 1, 15}}, - {BGPPEERFSMESTABLISHEDTIME, - GAUGE32, - RONLY, - bgpPeerTable, - 3, - {3, 1, 16}}, - {BGPPEERCONNECTRETRYINTERVAL, - INTEGER, - RWRITE, - bgpPeerTable, - 3, - {3, 1, 17}}, - {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 18}}, - {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 19}}, - {BGPPEERHOLDTIMECONFIGURED, - INTEGER, - RWRITE, - bgpPeerTable, - 3, - {3, 1, 20}}, - {BGPPEERKEEPALIVECONFIGURED, - INTEGER, - RWRITE, - bgpPeerTable, - 3, - {3, 1, 21}}, - {BGPPEERMINROUTEADVERTISEMENTINTERVAL, - INTEGER, - RWRITE, - bgpPeerTable, - 3, - {3, 1, 23}}, - {BGPPEERINUPDATEELAPSEDTIME, - GAUGE32, - RONLY, - bgpPeerTable, - 3, - {3, 1, 24}}, - /* BGP identifier. */ - {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, 1, {4}}, - /* BGP received path attribute table. */ - {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 1}}, - {BGPPATHATTRDESTNETWORK, - IPADDRESS, - RONLY, - bgpRcvdPathAttrTable, - 3, - {5, 1, 2}}, - {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 3}}, - {BGPPATHATTRASPATH, - OCTET_STRING, - RONLY, - bgpRcvdPathAttrTable, - 3, - {5, 1, 4}}, - {BGPPATHATTRNEXTHOP, - IPADDRESS, - RONLY, - bgpRcvdPathAttrTable, - 3, - {5, 1, 5}}, - {BGPPATHATTRINTERASMETRIC, - INTEGER32, - RONLY, - bgpRcvdPathAttrTable, - 3, - {5, 1, 6}}, - /* BGP-4 received path attribute table. */ - {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, 3, {6, 1, 1}}, - {BGP4PATHATTRIPADDRPREFIXLEN, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 2}}, - {BGP4PATHATTRIPADDRPREFIX, - IPADDRESS, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 3}}, - {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 4}}, - {BGP4PATHATTRASPATHSEGMENT, - OCTET_STRING, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 5}}, - {BGP4PATHATTRNEXTHOP, - IPADDRESS, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 6}}, - {BGP4PATHATTRMULTIEXITDISC, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 7}}, - {BGP4PATHATTRLOCALPREF, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 8}}, - {BGP4PATHATTRATOMICAGGREGATE, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 9}}, - {BGP4PATHATTRAGGREGATORAS, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 10}}, - {BGP4PATHATTRAGGREGATORADDR, - IPADDRESS, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 11}}, - {BGP4PATHATTRCALCLOCALPREF, - INTEGER, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 12}}, - {BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 13}}, - {BGP4PATHATTRUNKNOWN, - OCTET_STRING, - RONLY, - bgp4PathAttrTable, - 3, - {6, 1, 14}}, -}; - - -static uint8_t *bgpVersion(struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, - WriteMethod **write_method) -{ - static uint8_t version; - - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Return BGP version. Zebra bgpd only support version 4. */ - version = (0x80 >> (BGP_VERSION_4 - 1)); - - /* Return octet string length 1. */ - *var_len = 1; - return &version; -} - -static uint8_t *bgpLocalAs(struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, - WriteMethod **write_method) -{ - struct bgp *bgp; - - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - /* Get BGP structure. */ - bgp = bgp_get_default(); - if (!bgp) - return NULL; - - return SNMP_INTEGER(bgp->as); -} - -static struct peer *peer_lookup_addr_ipv4(struct in_addr *src) -{ - struct bgp *bgp; - struct peer *peer; - struct listnode *node; - struct listnode *bgpnode; - - for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { - for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { - if (sockunion_family(&peer->su) != AF_INET) - continue; - - if (sockunion2ip(&peer->su) == src->s_addr) - return peer; - } - } - - return NULL; -} - -static struct peer *bgp_peer_lookup_next(struct in_addr *src) -{ - struct bgp *bgp; - struct peer *peer; - struct peer *next_peer = NULL; - struct listnode *node; - struct listnode *bgpnode; - - for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { - for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { - if (sockunion_family(&peer->su) != AF_INET) - continue; - if (ntohl(sockunion2ip(&peer->su)) <= ntohl(src->s_addr)) - continue; - - if (!next_peer - || ntohl(sockunion2ip(&next_peer->su)) - > ntohl(sockunion2ip(&peer->su))) { - next_peer = peer; - } - } - } - - if (next_peer) { - src->s_addr = sockunion2ip(&next_peer->su); - return next_peer; - } - - return NULL; -} - -/* 1.3.6.1.2.1.15.3.1.x = 10 */ -#define PEERTAB_NAMELEN 10 - -static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[], - size_t *length, struct in_addr *addr, - int exact) -{ - struct peer *peer = NULL; - size_t namelen = v ? v->namelen : PEERTAB_NAMELEN; - int len; - - if (exact) { - /* Check the length. */ - if (*length - namelen != sizeof(struct in_addr)) - return NULL; - - oid2in_addr(name + namelen, IN_ADDR_SIZE, addr); - - peer = peer_lookup_addr_ipv4(addr); - return peer; - } else { - len = *length - namelen; - if (len > 4) - len = 4; - - oid2in_addr(name + namelen, len, addr); - - peer = bgp_peer_lookup_next(addr); - - if (peer == NULL) - return NULL; - - oid_copy_in_addr(name + namelen, addr); - *length = sizeof(struct in_addr) + namelen; - - return peer; - } - return NULL; -} - -/* BGP write methods. */ -static int write_bgpPeerTable(int action, uint8_t *var_val, - uint8_t var_val_type, size_t var_val_len, - uint8_t *statP, oid *name, size_t length) -{ - struct in_addr addr; - struct peer *peer; - long intval; - - if (var_val_type != ASN_INTEGER) { - return SNMP_ERR_WRONGTYPE; - } - if (var_val_len != sizeof(long)) { - return SNMP_ERR_WRONGLENGTH; - } - - intval = *(long *)var_val; - - memset(&addr, 0, sizeof(addr)); - - peer = bgpPeerTable_lookup(NULL, name, &length, &addr, 1); - if (!peer) - return SNMP_ERR_NOSUCHNAME; - - if (action != SNMP_MSG_INTERNAL_SET_COMMIT) - return SNMP_ERR_NOERROR; - - zlog_info("%s: SNMP write .%ld = %ld", peer->host, - (long)name[PEERTAB_NAMELEN - 1], intval); - - switch (name[PEERTAB_NAMELEN - 1]) { - case BGPPEERADMINSTATUS: -#define BGP_PeerAdmin_stop 1 -#define BGP_PeerAdmin_start 2 - /* When the peer is established, */ - if (intval == BGP_PeerAdmin_stop) - BGP_EVENT_ADD(peer, BGP_Stop); - else if (intval == BGP_PeerAdmin_start) - ; /* Do nothing. */ - else - return SNMP_ERR_NOSUCHNAME; - break; - case BGPPEERCONNECTRETRYINTERVAL: - peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT); - peer->connect = intval; - peer->v_connect = intval; - break; - case BGPPEERHOLDTIMECONFIGURED: - peer_flag_set(peer, PEER_FLAG_TIMER); - peer->holdtime = intval; - peer->v_holdtime = intval; - break; - case BGPPEERKEEPALIVECONFIGURED: - peer_flag_set(peer, PEER_FLAG_TIMER); - peer->keepalive = intval; - peer->v_keepalive = intval; - break; - case BGPPEERMINROUTEADVERTISEMENTINTERVAL: - peer->v_routeadv = intval; - break; - } - return SNMP_ERR_NOERROR; -} - -static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, - WriteMethod **write_method) -{ - static struct in_addr addr; - struct peer *peer; - uint32_t ui, uo; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - memset(&addr, 0, sizeof(addr)); - - peer = bgpPeerTable_lookup(v, name, length, &addr, exact); - if (!peer) - return NULL; - - switch (v->magic) { - case BGPPEERIDENTIFIER: - return SNMP_IPADDRESS(peer->remote_id); - case BGPPEERSTATE: - return SNMP_INTEGER(peer->status); - case BGPPEERADMINSTATUS: - *write_method = write_bgpPeerTable; -#define BGP_PeerAdmin_stop 1 -#define BGP_PeerAdmin_start 2 - if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) - return SNMP_INTEGER(BGP_PeerAdmin_stop); - else - return SNMP_INTEGER(BGP_PeerAdmin_start); - case BGPPEERNEGOTIATEDVERSION: - return SNMP_INTEGER(BGP_VERSION_4); - case BGPPEERLOCALADDR: - if (peer->su_local) - return SNMP_IPADDRESS(peer->su_local->sin.sin_addr); - else - return SNMP_IPADDRESS(bgp_empty_addr); - case BGPPEERLOCALPORT: - if (peer->su_local) - return SNMP_INTEGER( - ntohs(peer->su_local->sin.sin_port)); - else - return SNMP_INTEGER(0); - case BGPPEERREMOTEADDR: - if (peer->su_remote) - return SNMP_IPADDRESS(peer->su_remote->sin.sin_addr); - else - return SNMP_IPADDRESS(bgp_empty_addr); - case BGPPEERREMOTEPORT: - if (peer->su_remote) - return SNMP_INTEGER( - ntohs(peer->su_remote->sin.sin_port)); - else - return SNMP_INTEGER(0); - case BGPPEERREMOTEAS: - return SNMP_INTEGER(peer->as); - case BGPPEERINUPDATES: - ui = atomic_load_explicit(&peer->update_in, - memory_order_relaxed); - return SNMP_INTEGER(ui); - case BGPPEEROUTUPDATES: - uo = atomic_load_explicit(&peer->update_out, - memory_order_relaxed); - return SNMP_INTEGER(uo); - case BGPPEERINTOTALMESSAGES: - return SNMP_INTEGER(PEER_TOTAL_RX(peer)); - case BGPPEEROUTTOTALMESSAGES: - return SNMP_INTEGER(PEER_TOTAL_TX(peer)); - case BGPPEERLASTERROR: { - static uint8_t lasterror[2]; - lasterror[0] = peer->notify.code; - lasterror[1] = peer->notify.subcode; - *var_len = 2; - return (uint8_t *)&lasterror; - } - case BGPPEERFSMESTABLISHEDTRANSITIONS: - return SNMP_INTEGER(peer->established); - case BGPPEERFSMESTABLISHEDTIME: - if (peer->uptime == 0) - return SNMP_INTEGER(0); - else - return SNMP_INTEGER(monotime(NULL) - peer->uptime); - case BGPPEERCONNECTRETRYINTERVAL: - *write_method = write_bgpPeerTable; - return SNMP_INTEGER(peer->v_connect); - case BGPPEERHOLDTIME: - return SNMP_INTEGER(peer->v_holdtime); - case BGPPEERKEEPALIVE: - return SNMP_INTEGER(peer->v_keepalive); - case BGPPEERHOLDTIMECONFIGURED: - *write_method = write_bgpPeerTable; - if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) - return SNMP_INTEGER(peer->holdtime); - else - return SNMP_INTEGER(peer->v_holdtime); - case BGPPEERKEEPALIVECONFIGURED: - *write_method = write_bgpPeerTable; - if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) - return SNMP_INTEGER(peer->keepalive); - else - return SNMP_INTEGER(peer->v_keepalive); - case BGPPEERMINROUTEADVERTISEMENTINTERVAL: - *write_method = write_bgpPeerTable; - return SNMP_INTEGER(peer->v_routeadv); - case BGPPEERINUPDATEELAPSEDTIME: - if (peer->update_time == 0) - return SNMP_INTEGER(0); - else - return SNMP_INTEGER(monotime(NULL) - peer->update_time); - default: - return NULL; - } - return NULL; -} - -static uint8_t *bgpIdentifier(struct variable *v, oid name[], size_t *length, - int exact, size_t *var_len, - WriteMethod **write_method) -{ - struct bgp *bgp; - - if (smux_header_generic(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - - bgp = bgp_get_default(); - if (!bgp) - return NULL; - - return SNMP_IPADDRESS(bgp->router_id); -} - -static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[], - size_t *length, int exact, size_t *var_len, - WriteMethod **write_method) -{ - /* Received Path Attribute Table. This table contains, one entry - per path to a network, path attributes received from all peers - running BGP version 3 or less. This table is obsolete, having - been replaced in functionality with the bgp4PathAttrTable. */ - return NULL; -} - -static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], - size_t *length, struct bgp *bgp, - struct prefix_ipv4 *addr, - int exact) -{ - oid *offset; - int offsetlen; - struct bgp_path_info *path; - struct bgp_path_info *min; - struct bgp_dest *dest; - union sockunion su; - unsigned int len; - struct in_addr paddr; - - sockunion_init(&su); - -#define BGP_PATHATTR_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE) - - if (exact) { - if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET) - return NULL; - - /* Set OID offset for prefix. */ - offset = name + v->namelen; - oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix); - offset += IN_ADDR_SIZE; - - /* Prefix length. */ - addr->prefixlen = *offset; - offset++; - - /* Peer address. */ - su.sin.sin_family = AF_INET; - oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr); - - /* Lookup node. */ - dest = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST], - (struct prefix *)addr); - if (dest) { - for (path = bgp_dest_get_bgp_path_info(dest); path; - path = path->next) - if (sockunion_same(&path->peer->su, &su)) - return path; - - bgp_dest_unlock_node(dest); - } - } else { - offset = name + v->namelen; - offsetlen = *length - v->namelen; - len = offsetlen; - - if (offsetlen == 0) - dest = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]); - else { - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr(offset, len, &addr->prefix); - - offset += IN_ADDR_SIZE; - offsetlen -= IN_ADDR_SIZE; - - if (offsetlen > 0) - addr->prefixlen = *offset; - else - addr->prefixlen = len * 8; - - dest = bgp_node_get(bgp->rib[AFI_IP][SAFI_UNICAST], - (struct prefix *)addr); - - offset++; - offsetlen--; - } - - if (offsetlen > 0) { - len = offsetlen; - if (len > IN_ADDR_SIZE) - len = IN_ADDR_SIZE; - - oid2in_addr(offset, len, &paddr); - } else - paddr.s_addr = INADDR_ANY; - - if (!dest) - return NULL; - - do { - min = NULL; - - for (path = bgp_dest_get_bgp_path_info(dest); path; - path = path->next) { - if (path->peer->su.sin.sin_family == AF_INET - && ntohl(paddr.s_addr) - < ntohl(path->peer->su.sin - .sin_addr - .s_addr)) { - if (min) { - if (ntohl(path->peer->su.sin - .sin_addr - .s_addr) - < ntohl(min->peer->su.sin - .sin_addr - .s_addr)) - min = path; - } else - min = path; - } - } - - if (min) { - const struct prefix *rn_p = - bgp_dest_get_prefix(dest); - - *length = - v->namelen + BGP_PATHATTR_ENTRY_OFFSET; - - offset = name + v->namelen; - oid_copy_in_addr(offset, &rn_p->u.prefix4); - offset += IN_ADDR_SIZE; - *offset = rn_p->prefixlen; - offset++; - oid_copy_in_addr(offset, - &min->peer->su.sin.sin_addr); - addr->prefix = rn_p->u.prefix4; - addr->prefixlen = rn_p->prefixlen; - - bgp_dest_unlock_node(dest); - - return min; - } - - paddr.s_addr = INADDR_ANY; - } while ((dest = bgp_route_next(dest)) != NULL); - } - return NULL; -} - -static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], - size_t *length, int exact, size_t *var_len, - WriteMethod **write_method) -{ - struct bgp *bgp; - struct bgp_path_info *path; - struct prefix_ipv4 addr; - - bgp = bgp_get_default(); - if (!bgp) - return NULL; - - if (smux_header_table(v, name, length, exact, var_len, write_method) - == MATCH_FAILED) - return NULL; - memset(&addr, 0, sizeof(addr)); - - path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact); - if (!path) - return NULL; - - switch (v->magic) { - case BGP4PATHATTRPEER: /* 1 */ - return SNMP_IPADDRESS(path->peer->su.sin.sin_addr); - case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */ - return SNMP_INTEGER(addr.prefixlen); - case BGP4PATHATTRIPADDRPREFIX: /* 3 */ - return SNMP_IPADDRESS(addr.prefix); - case BGP4PATHATTRORIGIN: /* 4 */ - return SNMP_INTEGER(path->attr->origin); - case BGP4PATHATTRASPATHSEGMENT: /* 5 */ - return aspath_snmp_pathseg(path->attr->aspath, var_len); - case BGP4PATHATTRNEXTHOP: /* 6 */ - return SNMP_IPADDRESS(path->attr->nexthop); - case BGP4PATHATTRMULTIEXITDISC: /* 7 */ - return SNMP_INTEGER(path->attr->med); - case BGP4PATHATTRLOCALPREF: /* 8 */ - return SNMP_INTEGER(path->attr->local_pref); - case BGP4PATHATTRATOMICAGGREGATE: /* 9 */ - return SNMP_INTEGER(1); - case BGP4PATHATTRAGGREGATORAS: /* 10 */ - return SNMP_INTEGER(path->attr->aggregator_as); - case BGP4PATHATTRAGGREGATORADDR: /* 11 */ - return SNMP_IPADDRESS(path->attr->aggregator_addr); - case BGP4PATHATTRCALCLOCALPREF: /* 12 */ - return SNMP_INTEGER(-1); - case BGP4PATHATTRBEST: /* 13 */ -#define BGP4_PathAttrBest_false 1 -#define BGP4_PathAttrBest_true 2 - if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) - return SNMP_INTEGER(BGP4_PathAttrBest_true); - else - return SNMP_INTEGER(BGP4_PathAttrBest_false); - case BGP4PATHATTRUNKNOWN: /* 14 */ - *var_len = 0; - return NULL; - } - return NULL; -} - -/* BGP Traps. */ -static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERREMOTEADDR} }, - {3, {3, 1, BGPPEERLASTERROR} }, - {3, {3, 1, BGPPEERSTATE} } }; - -static int bgpTrapEstablished(struct peer *peer) -{ - int ret; - struct in_addr addr; - oid index[sizeof(oid) * IN_ADDR_SIZE]; - - /* Check if this peer just went to Established */ - if ((peer->ostatus != OpenConfirm) || !(peer_established(peer))) - return 0; - - ret = inet_aton(peer->host, &addr); - if (ret == 0) - return 0; - - oid_copy_in_addr(index, &addr); - - smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid, - array_size(bgp_trap_oid), bgp_oid, - sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE, - bgpTrapList, array_size(bgpTrapList), BGPESTABLISHED); - return 0; -} - -static int bgpTrapBackwardTransition(struct peer *peer) -{ - int ret; - struct in_addr addr; - oid index[sizeof(oid) * IN_ADDR_SIZE]; - - ret = inet_aton(peer->host, &addr); - if (ret == 0) - return 0; - - oid_copy_in_addr(index, &addr); - - smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid, - array_size(bgp_trap_oid), bgp_oid, - sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE, - bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION); - return 0; -} - static int bgp_snmp_init(struct thread_master *tm) { smux_init(tm); - REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + bgp_snmp_bgp4_init(tm); + bgp_snmp_bgp4v2_init(tm); bgp_mpls_l3vpn_module_init(); return 0; } diff --git a/bgpd/bgp_snmp.h b/bgpd/bgp_snmp.h new file mode 100644 index 0000000000..a89e82b6c6 --- /dev/null +++ b/bgpd/bgp_snmp.h @@ -0,0 +1,32 @@ +/* Common header file for BGP SNMP implementation. + * + * Copyright (C) 2022 Donatas Abraitis + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_BGP_SNMP_H_ +#define _FRR_BGP_SNMP_H_ + +/* SNMP value hack. */ +#define INTEGER ASN_INTEGER +#define INTEGER32 ASN_INTEGER +#define COUNTER32 ASN_COUNTER +#define OCTET_STRING ASN_OCTET_STR +#define IPADDRESS ASN_IPADDRESS +#define GAUGE32 ASN_UNSIGNED + +#endif /* _FRR_BGP_SNMP_H_ */ diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c new file mode 100644 index 0000000000..bb8b7f4b19 --- /dev/null +++ b/bgpd/bgp_snmp_bgp4.c @@ -0,0 +1,814 @@ +/* BGP4 SNMP support + * Copyright (C) 1999, 2000 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "if.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "thread.h" +#include "smux.h" +#include "filter.h" +#include "hook.h" +#include "libfrr.h" +#include "lib/version.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_table.h" +#include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_snmp.h" +#include "bgpd/bgp_snmp_bgp4.h" +#include "bgpd/bgp_mplsvpn_snmp.h" + +/* Declare static local variables for convenience. */ +SNMP_LOCAL_VARIABLES + +/* BGP-MIB instances. */ +static oid bgp_oid[] = {BGP4MIB}; +static oid bgp_trap_oid[] = {BGP4MIB, 0}; + +/* IP address 0.0.0.0. */ +static struct in_addr bgp_empty_addr = {.s_addr = 0}; + +static uint8_t *bgpVersion(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + static uint8_t version; + + if (smux_header_generic(v, name, length, exact, var_len, + write_method) == MATCH_FAILED) + return NULL; + + /* Return BGP version. Zebra bgpd only support version 4. */ + version = (0x80 >> (BGP_VERSION_4 - 1)); + + /* Return octet string length 1. */ + *var_len = 1; + return &version; +} + +static uint8_t *bgpLocalAs(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct bgp *bgp; + + if (smux_header_generic(v, name, length, exact, var_len, + write_method) == MATCH_FAILED) + return NULL; + + /* Get BGP structure. */ + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + return SNMP_INTEGER(bgp->as); +} + +static struct peer *peer_lookup_addr_ipv4(struct in_addr *src) +{ + struct bgp *bgp; + struct peer *peer; + struct listnode *node; + struct listnode *bgpnode; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + if (sockunion_family(&peer->su) != AF_INET) + continue; + + if (sockunion2ip(&peer->su) == src->s_addr) + return peer; + } + } + + return NULL; +} + +static struct peer *bgp_peer_lookup_next(struct in_addr *src) +{ + struct bgp *bgp; + struct peer *peer; + struct peer *next_peer = NULL; + struct listnode *node; + struct listnode *bgpnode; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + if (sockunion_family(&peer->su) != AF_INET) + continue; + if (ntohl(sockunion2ip(&peer->su)) <= + ntohl(src->s_addr)) + continue; + + if (!next_peer || + ntohl(sockunion2ip(&next_peer->su)) > + ntohl(sockunion2ip(&peer->su))) { + next_peer = peer; + } + } + } + + if (next_peer) { + src->s_addr = sockunion2ip(&next_peer->su); + return next_peer; + } + + return NULL; +} + +/* 1.3.6.1.2.1.15.3.1.x = 10 */ +#define PEERTAB_NAMELEN 10 + +static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[], + size_t *length, struct in_addr *addr, + int exact) +{ + struct peer *peer = NULL; + size_t namelen = v ? v->namelen : PEERTAB_NAMELEN; + int len; + + if (exact) { + /* Check the length. */ + if (*length - namelen != sizeof(struct in_addr)) + return NULL; + + oid2in_addr(name + namelen, IN_ADDR_SIZE, addr); + + peer = peer_lookup_addr_ipv4(addr); + return peer; + } else { + len = *length - namelen; + if (len > 4) + len = 4; + + oid2in_addr(name + namelen, len, addr); + + peer = bgp_peer_lookup_next(addr); + + if (peer == NULL) + return NULL; + + oid_copy_in_addr(name + namelen, addr); + *length = sizeof(struct in_addr) + namelen; + + return peer; + } + return NULL; +} + +/* BGP write methods. */ +static int write_bgpPeerTable(int action, uint8_t *var_val, + uint8_t var_val_type, size_t var_val_len, + uint8_t *statP, oid *name, size_t length) +{ + struct in_addr addr; + struct peer *peer; + long intval; + + if (var_val_type != ASN_INTEGER) { + return SNMP_ERR_WRONGTYPE; + } + if (var_val_len != sizeof(long)) { + return SNMP_ERR_WRONGLENGTH; + } + + intval = *(long *)var_val; + + memset(&addr, 0, sizeof(addr)); + + peer = bgpPeerTable_lookup(NULL, name, &length, &addr, 1); + if (!peer) + return SNMP_ERR_NOSUCHNAME; + + if (action != SNMP_MSG_INTERNAL_SET_COMMIT) + return SNMP_ERR_NOERROR; + + zlog_info("%s: SNMP write .%ld = %ld", peer->host, + (long)name[PEERTAB_NAMELEN - 1], intval); + + switch (name[PEERTAB_NAMELEN - 1]) { + case BGPPEERADMINSTATUS: +#define BGP_PeerAdmin_stop 1 +#define BGP_PeerAdmin_start 2 + /* When the peer is established, */ + if (intval == BGP_PeerAdmin_stop) + BGP_EVENT_ADD(peer, BGP_Stop); + else if (intval == BGP_PeerAdmin_start) + ; /* Do nothing. */ + else + return SNMP_ERR_NOSUCHNAME; + break; + case BGPPEERCONNECTRETRYINTERVAL: + peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT); + peer->connect = intval; + peer->v_connect = intval; + break; + case BGPPEERHOLDTIMECONFIGURED: + peer_flag_set(peer, PEER_FLAG_TIMER); + peer->holdtime = intval; + peer->v_holdtime = intval; + break; + case BGPPEERKEEPALIVECONFIGURED: + peer_flag_set(peer, PEER_FLAG_TIMER); + peer->keepalive = intval; + peer->v_keepalive = intval; + break; + case BGPPEERMINROUTEADVERTISEMENTINTERVAL: + peer->v_routeadv = intval; + break; + } + return SNMP_ERR_NOERROR; +} + +static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + static struct in_addr addr; + struct peer *peer; + uint32_t ui, uo; + + if (smux_header_table(v, name, length, exact, var_len, write_method) == + MATCH_FAILED) + return NULL; + memset(&addr, 0, sizeof(addr)); + + peer = bgpPeerTable_lookup(v, name, length, &addr, exact); + if (!peer) + return NULL; + + switch (v->magic) { + case BGPPEERIDENTIFIER: + return SNMP_IPADDRESS(peer->remote_id); + case BGPPEERSTATE: + return SNMP_INTEGER(peer->status); + case BGPPEERADMINSTATUS: + *write_method = write_bgpPeerTable; +#define BGP_PeerAdmin_stop 1 +#define BGP_PeerAdmin_start 2 + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + return SNMP_INTEGER(BGP_PeerAdmin_stop); + else + return SNMP_INTEGER(BGP_PeerAdmin_start); + case BGPPEERNEGOTIATEDVERSION: + return SNMP_INTEGER(BGP_VERSION_4); + case BGPPEERLOCALADDR: + if (peer->su_local) + return SNMP_IPADDRESS(peer->su_local->sin.sin_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + case BGPPEERLOCALPORT: + if (peer->su_local) + return SNMP_INTEGER( + ntohs(peer->su_local->sin.sin_port)); + else + return SNMP_INTEGER(0); + case BGPPEERREMOTEADDR: + if (peer->su_remote) + return SNMP_IPADDRESS(peer->su_remote->sin.sin_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + case BGPPEERREMOTEPORT: + if (peer->su_remote) + return SNMP_INTEGER( + ntohs(peer->su_remote->sin.sin_port)); + else + return SNMP_INTEGER(0); + case BGPPEERREMOTEAS: + return SNMP_INTEGER(peer->as); + case BGPPEERINUPDATES: + ui = atomic_load_explicit(&peer->update_in, + memory_order_relaxed); + return SNMP_INTEGER(ui); + case BGPPEEROUTUPDATES: + uo = atomic_load_explicit(&peer->update_out, + memory_order_relaxed); + return SNMP_INTEGER(uo); + case BGPPEERINTOTALMESSAGES: + return SNMP_INTEGER(PEER_TOTAL_RX(peer)); + case BGPPEEROUTTOTALMESSAGES: + return SNMP_INTEGER(PEER_TOTAL_TX(peer)); + case BGPPEERLASTERROR: { + static uint8_t lasterror[2]; + lasterror[0] = peer->notify.code; + lasterror[1] = peer->notify.subcode; + *var_len = 2; + return (uint8_t *)&lasterror; + } + case BGPPEERFSMESTABLISHEDTRANSITIONS: + return SNMP_INTEGER(peer->established); + case BGPPEERFSMESTABLISHEDTIME: + if (peer->uptime == 0) + return SNMP_INTEGER(0); + else + return SNMP_INTEGER(monotime(NULL) - peer->uptime); + case BGPPEERCONNECTRETRYINTERVAL: + *write_method = write_bgpPeerTable; + return SNMP_INTEGER(peer->v_connect); + case BGPPEERHOLDTIME: + return SNMP_INTEGER(peer->v_holdtime); + case BGPPEERKEEPALIVE: + return SNMP_INTEGER(peer->v_keepalive); + case BGPPEERHOLDTIMECONFIGURED: + *write_method = write_bgpPeerTable; + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) + return SNMP_INTEGER(peer->holdtime); + else + return SNMP_INTEGER(peer->v_holdtime); + case BGPPEERKEEPALIVECONFIGURED: + *write_method = write_bgpPeerTable; + if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER)) + return SNMP_INTEGER(peer->keepalive); + else + return SNMP_INTEGER(peer->v_keepalive); + case BGPPEERMINROUTEADVERTISEMENTINTERVAL: + *write_method = write_bgpPeerTable; + return SNMP_INTEGER(peer->v_routeadv); + case BGPPEERINUPDATEELAPSEDTIME: + if (peer->update_time == 0) + return SNMP_INTEGER(0); + else + return SNMP_INTEGER(monotime(NULL) - peer->update_time); + default: + return NULL; + } + return NULL; +} + +static uint8_t *bgpIdentifier(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct bgp *bgp; + + if (smux_header_generic(v, name, length, exact, var_len, + write_method) == MATCH_FAILED) + return NULL; + + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + return SNMP_IPADDRESS(bgp->router_id); +} + +static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[], + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) +{ + /* Received Path Attribute Table. This table contains, one entry + per path to a network, path attributes received from all peers + running BGP version 3 or less. This table is obsolete, having + been replaced in functionality with the bgp4PathAttrTable. */ + return NULL; +} + +static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], + size_t *length, struct bgp *bgp, + struct prefix_ipv4 *addr, + int exact) +{ + oid *offset; + int offsetlen; + struct bgp_path_info *path; + struct bgp_path_info *min; + struct bgp_dest *dest; + union sockunion su; + unsigned int len; + struct in_addr paddr; + + sockunion_init(&su); + +#define BGP_PATHATTR_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE) + + if (exact) { + if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET) + return NULL; + + /* Set OID offset for prefix. */ + offset = name + v->namelen; + oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix); + offset += IN_ADDR_SIZE; + + /* Prefix length. */ + addr->prefixlen = *offset; + offset++; + + /* Peer address. */ + su.sin.sin_family = AF_INET; + oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr); + + /* Lookup node. */ + dest = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST], + (struct prefix *)addr); + if (dest) { + for (path = bgp_dest_get_bgp_path_info(dest); path; + path = path->next) + if (sockunion_same(&path->peer->su, &su)) + return path; + + bgp_dest_unlock_node(dest); + } + } else { + offset = name + v->namelen; + offsetlen = *length - v->namelen; + len = offsetlen; + + if (offsetlen == 0) + dest = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]); + else { + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, &addr->prefix); + + offset += IN_ADDR_SIZE; + offsetlen -= IN_ADDR_SIZE; + + if (offsetlen > 0) + addr->prefixlen = *offset; + else + addr->prefixlen = len * 8; + + dest = bgp_node_get(bgp->rib[AFI_IP][SAFI_UNICAST], + (struct prefix *)addr); + + offset++; + offsetlen--; + } + + if (offsetlen > 0) { + len = offsetlen; + if (len > IN_ADDR_SIZE) + len = IN_ADDR_SIZE; + + oid2in_addr(offset, len, &paddr); + } else + paddr.s_addr = INADDR_ANY; + + if (!dest) + return NULL; + + do { + min = NULL; + + for (path = bgp_dest_get_bgp_path_info(dest); path; + path = path->next) { + if (path->peer->su.sin.sin_family == AF_INET && + ntohl(paddr.s_addr) < + ntohl(path->peer->su.sin.sin_addr + .s_addr)) { + if (min) { + if (ntohl(path->peer->su.sin + .sin_addr + .s_addr) < + ntohl(min->peer->su.sin + .sin_addr + .s_addr)) + min = path; + } else + min = path; + } + } + + if (min) { + const struct prefix *rn_p = + bgp_dest_get_prefix(dest); + + *length = + v->namelen + BGP_PATHATTR_ENTRY_OFFSET; + + offset = name + v->namelen; + oid_copy_in_addr(offset, &rn_p->u.prefix4); + offset += IN_ADDR_SIZE; + *offset = rn_p->prefixlen; + offset++; + oid_copy_in_addr(offset, + &min->peer->su.sin.sin_addr); + addr->prefix = rn_p->u.prefix4; + addr->prefixlen = rn_p->prefixlen; + + bgp_dest_unlock_node(dest); + + return min; + } + + paddr.s_addr = INADDR_ANY; + } while ((dest = bgp_route_next(dest)) != NULL); + } + return NULL; +} + +static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct bgp *bgp; + struct bgp_path_info *path; + struct prefix_ipv4 addr; + + bgp = bgp_get_default(); + if (!bgp) + return NULL; + + if (smux_header_table(v, name, length, exact, var_len, write_method) == + MATCH_FAILED) + return NULL; + memset(&addr, 0, sizeof(addr)); + + path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact); + if (!path) + return NULL; + + switch (v->magic) { + case BGP4PATHATTRPEER: /* 1 */ + return SNMP_IPADDRESS(path->peer->su.sin.sin_addr); + case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */ + return SNMP_INTEGER(addr.prefixlen); + case BGP4PATHATTRIPADDRPREFIX: /* 3 */ + return SNMP_IPADDRESS(addr.prefix); + case BGP4PATHATTRORIGIN: /* 4 */ + return SNMP_INTEGER(path->attr->origin); + case BGP4PATHATTRASPATHSEGMENT: /* 5 */ + return aspath_snmp_pathseg(path->attr->aspath, var_len); + case BGP4PATHATTRNEXTHOP: /* 6 */ + return SNMP_IPADDRESS(path->attr->nexthop); + case BGP4PATHATTRMULTIEXITDISC: /* 7 */ + return SNMP_INTEGER(path->attr->med); + case BGP4PATHATTRLOCALPREF: /* 8 */ + return SNMP_INTEGER(path->attr->local_pref); + case BGP4PATHATTRATOMICAGGREGATE: /* 9 */ + return SNMP_INTEGER(1); + case BGP4PATHATTRAGGREGATORAS: /* 10 */ + return SNMP_INTEGER(path->attr->aggregator_as); + case BGP4PATHATTRAGGREGATORADDR: /* 11 */ + return SNMP_IPADDRESS(path->attr->aggregator_addr); + case BGP4PATHATTRCALCLOCALPREF: /* 12 */ + return SNMP_INTEGER(-1); + case BGP4PATHATTRBEST: /* 13 */ +#define BGP4_PathAttrBest_false 1 +#define BGP4_PathAttrBest_true 2 + if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) + return SNMP_INTEGER(BGP4_PathAttrBest_true); + else + return SNMP_INTEGER(BGP4_PathAttrBest_false); + case BGP4PATHATTRUNKNOWN: /* 14 */ + *var_len = 0; + return NULL; + } + return NULL; +} + +/* BGP Traps. */ +static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERREMOTEADDR}}, + {3, {3, 1, BGPPEERLASTERROR}}, + {3, {3, 1, BGPPEERSTATE}}}; + +static struct variable bgp_variables[] = { + /* BGP version. */ + {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, 1, {1}}, + /* BGP local AS. */ + {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, 1, {2}}, + /* BGP peer table. */ + {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 1}}, + {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 2}}, + {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, 3, {3, 1, 3}}, + {BGPPEERNEGOTIATEDVERSION, + INTEGER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 4}}, + {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 5}}, + {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 6}}, + {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 7}}, + {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 8}}, + {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 9}}, + {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 10}}, + {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 11}}, + {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 12}}, + {BGPPEEROUTTOTALMESSAGES, + COUNTER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 13}}, + {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, 3, {3, 1, 14}}, + {BGPPEERFSMESTABLISHEDTRANSITIONS, + COUNTER32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 15}}, + {BGPPEERFSMESTABLISHEDTIME, + GAUGE32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 16}}, + {BGPPEERCONNECTRETRYINTERVAL, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 17}}, + {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 18}}, + {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 19}}, + {BGPPEERHOLDTIMECONFIGURED, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 20}}, + {BGPPEERKEEPALIVECONFIGURED, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 21}}, + {BGPPEERMINROUTEADVERTISEMENTINTERVAL, + INTEGER, + RWRITE, + bgpPeerTable, + 3, + {3, 1, 23}}, + {BGPPEERINUPDATEELAPSEDTIME, + GAUGE32, + RONLY, + bgpPeerTable, + 3, + {3, 1, 24}}, + /* BGP identifier. */ + {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, 1, {4}}, + /* BGP received path attribute table. */ + {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 1}}, + {BGPPATHATTRDESTNETWORK, + IPADDRESS, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 2}}, + {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 3}}, + {BGPPATHATTRASPATH, + OCTET_STRING, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 4}}, + {BGPPATHATTRNEXTHOP, + IPADDRESS, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 5}}, + {BGPPATHATTRINTERASMETRIC, + INTEGER32, + RONLY, + bgpRcvdPathAttrTable, + 3, + {5, 1, 6}}, + /* BGP-4 received path attribute table. */ + {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, 3, {6, 1, 1}}, + {BGP4PATHATTRIPADDRPREFIXLEN, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 2}}, + {BGP4PATHATTRIPADDRPREFIX, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 3}}, + {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 4}}, + {BGP4PATHATTRASPATHSEGMENT, + OCTET_STRING, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 5}}, + {BGP4PATHATTRNEXTHOP, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 6}}, + {BGP4PATHATTRMULTIEXITDISC, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 7}}, + {BGP4PATHATTRLOCALPREF, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 8}}, + {BGP4PATHATTRATOMICAGGREGATE, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 9}}, + {BGP4PATHATTRAGGREGATORAS, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 10}}, + {BGP4PATHATTRAGGREGATORADDR, + IPADDRESS, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 11}}, + {BGP4PATHATTRCALCLOCALPREF, + INTEGER, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 12}}, + {BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 13}}, + {BGP4PATHATTRUNKNOWN, + OCTET_STRING, + RONLY, + bgp4PathAttrTable, + 3, + {6, 1, 14}}, +}; + +int bgpTrapEstablished(struct peer *peer) +{ + int ret; + struct in_addr addr; + oid index[sizeof(oid) * IN_ADDR_SIZE]; + + /* Check if this peer just went to Established */ + if ((peer->ostatus != OpenConfirm) || !(peer_established(peer))) + return 0; + + ret = inet_aton(peer->host, &addr); + if (ret == 0) + return 0; + + oid_copy_in_addr(index, &addr); + + smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid, + array_size(bgp_trap_oid), bgp_oid, + sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE, + bgpTrapList, array_size(bgpTrapList), BGPESTABLISHED); + return 0; +} + +int bgpTrapBackwardTransition(struct peer *peer) +{ + int ret; + struct in_addr addr; + oid index[sizeof(oid) * IN_ADDR_SIZE]; + + ret = inet_aton(peer->host, &addr); + if (ret == 0) + return 0; + + oid_copy_in_addr(index, &addr); + + smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid, + array_size(bgp_trap_oid), bgp_oid, + sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE, + bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION); + return 0; +} + +int bgp_snmp_bgp4_init(struct thread_master *tm) +{ + REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid); + return 0; +} diff --git a/bgpd/bgp_snmp_bgp4.h b/bgpd/bgp_snmp_bgp4.h new file mode 100644 index 0000000000..ac51191660 --- /dev/null +++ b/bgpd/bgp_snmp_bgp4.h @@ -0,0 +1,90 @@ +/* BGP4-MIB SNMP support + * + * Using: http://www.circitor.fr/Mibs/Html/B/BGP4-MIB.php + * + * Copyright (C) 2022 Donatas Abraitis + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_BGP_SNMP_BGP4_H_ +#define _FRR_BGP_SNMP_BGP4_H_ + +#define BGPVERSION 0 +#define BGPLOCALAS 0 +#define BGPIDENTIFIER 0 + +/* bgp */ +#define BGP4MIB 1, 3, 6, 1, 2, 1, 15 + +/* bgpTraps */ +#define BGPESTABLISHED 1 +#define BGPBACKWARDTRANSITION 2 + +/* bgpPeerTable */ +#define BGPPEERIDENTIFIER 1 +#define BGPPEERSTATE 2 +#define BGPPEERADMINSTATUS 3 +#define BGPPEERNEGOTIATEDVERSION 4 +#define BGPPEERLOCALADDR 5 +#define BGPPEERLOCALPORT 6 +#define BGPPEERREMOTEADDR 7 +#define BGPPEERREMOTEPORT 8 +#define BGPPEERREMOTEAS 9 +#define BGPPEERINUPDATES 10 +#define BGPPEEROUTUPDATES 11 +#define BGPPEERINTOTALMESSAGES 12 +#define BGPPEEROUTTOTALMESSAGES 13 +#define BGPPEERLASTERROR 14 +#define BGPPEERFSMESTABLISHEDTRANSITIONS 15 +#define BGPPEERFSMESTABLISHEDTIME 16 +#define BGPPEERCONNECTRETRYINTERVAL 17 +#define BGPPEERHOLDTIME 18 +#define BGPPEERKEEPALIVE 19 +#define BGPPEERHOLDTIMECONFIGURED 20 +#define BGPPEERKEEPALIVECONFIGURED 21 +#define BGPPEERMINROUTEADVERTISEMENTINTERVAL 22 +#define BGPPEERINUPDATEELAPSEDTIME 23 + +/* bgpPathAttrEntry */ +#define BGPPATHATTRPEER 1 +#define BGPPATHATTRDESTNETWORK 2 +#define BGPPATHATTRORIGIN 3 +#define BGPPATHATTRASPATH 4 +#define BGPPATHATTRNEXTHOP 5 +#define BGPPATHATTRINTERASMETRIC 6 + +/* bgp4PathAttrEntry */ +#define BGP4PATHATTRPEER 1 +#define BGP4PATHATTRIPADDRPREFIXLEN 2 +#define BGP4PATHATTRIPADDRPREFIX 3 +#define BGP4PATHATTRORIGIN 4 +#define BGP4PATHATTRASPATHSEGMENT 5 +#define BGP4PATHATTRNEXTHOP 6 +#define BGP4PATHATTRMULTIEXITDISC 7 +#define BGP4PATHATTRLOCALPREF 8 +#define BGP4PATHATTRATOMICAGGREGATE 9 +#define BGP4PATHATTRAGGREGATORAS 10 +#define BGP4PATHATTRAGGREGATORADDR 11 +#define BGP4PATHATTRCALCLOCALPREF 12 +#define BGP4PATHATTRBEST 13 +#define BGP4PATHATTRUNKNOWN 14 + +extern int bgpTrapEstablished(struct peer *peer); +extern int bgpTrapBackwardTransition(struct peer *peer); +extern int bgp_snmp_bgp4_init(struct thread_master *tm); + +#endif /* _FRR_BGP_SNMP_BGP4_H_ */ diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c new file mode 100644 index 0000000000..d59e63d7e0 --- /dev/null +++ b/bgpd/bgp_snmp_bgp4v2.c @@ -0,0 +1,455 @@ +/* BGP4V2-MIB SNMP support + * + * Copyright (C) 2022 Donatas Abraitis + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include + +#include "if.h" +#include "log.h" +#include "prefix.h" +#include "command.h" +#include "thread.h" +#include "smux.h" +#include "filter.h" +#include "hook.h" +#include "libfrr.h" +#include "lib/version.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_table.h" +#include "bgpd/bgp_aspath.h" +#include "bgpd/bgp_attr.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_fsm.h" +#include "bgpd/bgp_snmp.h" +#include "bgpd/bgp_snmp_bgp4v2.h" + +SNMP_LOCAL_VARIABLES + +static oid bgpv2_oid[] = {BGP4V2MIB}; +static struct in_addr bgp_empty_addr = {}; + +static struct peer *peer_lookup_all_vrf(struct ipaddr *addr) +{ + struct bgp *bgp; + struct peer *peer; + struct listnode *node; + struct listnode *bgpnode; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + switch (sockunion_family(&peer->su)) { + case AF_INET: + if (IPV4_ADDR_SAME(&peer->su.sin.sin_addr, + &addr->ip._v4_addr)) + return peer; + break; + case AF_INET6: + if (IPV6_ADDR_SAME(&peer->su.sin6.sin6_addr, + &addr->ip._v6_addr)) + return peer; + break; + default: + break; + } + } + } + + return NULL; +} + +static struct peer *peer_lookup_all_vrf_next(struct ipaddr *addr, oid *offset, + sa_family_t family) +{ + struct bgp *bgp; + struct peer *peer; + struct peer *next_peer = NULL; + struct listnode *node; + struct listnode *bgpnode; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) { + for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) { + sa_family_t peer_family = sockunion_family(&peer->su); + + if (peer_family != family) + continue; + + switch (sockunion_family(&peer->su)) { + case AF_INET: + oid2in_addr(offset, IN_ADDR_SIZE, + &addr->ip._v4_addr); + if (IPV4_ADDR_CMP(&peer->su.sin.sin_addr, + &addr->ip._v4_addr) < 0 || + IPV4_ADDR_SAME(&peer->su.sin.sin_addr, + &addr->ip._v4_addr)) + continue; + + if (!next_peer || + IPV4_ADDR_CMP(&next_peer->su.sin.sin_addr, + &peer->su.sin.sin_addr) > 0) + next_peer = peer; + + break; + case AF_INET6: + oid2in6_addr(offset, &addr->ip._v6_addr); + if (IPV6_ADDR_CMP(&peer->su.sin6.sin6_addr, + &addr->ip._v6_addr) < 0 || + IPV6_ADDR_SAME(&peer->su.sin6.sin6_addr, + &addr->ip._v6_addr)) + continue; + + if (!next_peer || + IPV6_ADDR_CMP(&next_peer->su.sin6.sin6_addr, + &peer->su.sin6.sin6_addr) > 0) + next_peer = peer; + + break; + default: + break; + } + } + } + + if (next_peer) + return next_peer; + + return NULL; +} + +static struct peer *bgpv2PeerTable_lookup(struct variable *v, oid name[], + size_t *length, int exact, + struct ipaddr *addr) +{ + struct peer *peer = NULL; + size_t namelen = v ? v->namelen : BGP4V2_PEER_ENTRY_OFFSET; + oid *offset = name + namelen; + sa_family_t family = name[namelen - 1] == 4 ? AF_INET : AF_INET6; + + if (exact) { + if (family == AF_INET) { + oid2in_addr(offset, IN_ADDR_SIZE, &addr->ip._v4_addr); + peer = peer_lookup_all_vrf(addr); + return peer; + } else if (family == AF_INET6) { + oid2in6_addr(offset, &addr->ip._v6_addr); + return peer_lookup_all_vrf(addr); + } + } else { + peer = peer_lookup_all_vrf_next(addr, offset, family); + if (peer == NULL) + return NULL; + + switch (sockunion_family(&peer->su)) { + case AF_INET: + oid_copy_in_addr(offset, &peer->su.sin.sin_addr); + *length = IN_ADDR_SIZE + namelen; + return peer; + case AF_INET6: + oid_copy_in6_addr(offset, &peer->su.sin6.sin6_addr); + *length = IN6_ADDR_SIZE + namelen; + return peer; + default: + break; + } + } + + return NULL; +} + +static uint8_t *bgpv2PeerTable(struct variable *v, oid name[], size_t *length, + int exact, size_t *var_len, + WriteMethod **write_method) +{ + struct peer *peer; + struct ipaddr addr = {}; + + if (smux_header_table(v, name, length, exact, var_len, write_method) == + MATCH_FAILED) + return NULL; + + peer = bgpv2PeerTable_lookup(v, name, length, exact, &addr); + if (!peer) + return NULL; + + switch (v->magic) { + case BGP4V2_PEER_INSTANCE: + return SNMP_INTEGER(peer->bgp->vrf_id); + case BGP4V2_PEER_LOCAL_ADDR_TYPE: + if (peer->su_local) + return SNMP_INTEGER(peer->su_local->sa.sa_family == + AF_INET + ? AFI_IP + : AFI_IP6); + else + return SNMP_INTEGER(0); + case BGP4V2_PEER_LOCAL_ADDR: + if (peer->su_local) + if (peer->su_local->sa.sa_family == AF_INET) + return SNMP_IPADDRESS( + peer->su_local->sin.sin_addr); + else + return SNMP_IP6ADDRESS( + peer->su_local->sin6.sin6_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + case BGP4V2_PEER_REMOTE_ADDR_TYPE: + if (peer->su_remote) + return SNMP_INTEGER(peer->su_remote->sa.sa_family == + AF_INET + ? AFI_IP + : AFI_IP6); + else + return SNMP_INTEGER(0); + case BGP4V2_PEER_REMOTE_ADDR: + if (peer->su_remote) + if (peer->su_remote->sa.sa_family == AF_INET) + return SNMP_IPADDRESS( + peer->su_remote->sin.sin_addr); + else + return SNMP_IP6ADDRESS( + peer->su_remote->sin6.sin6_addr); + else + return SNMP_IPADDRESS(bgp_empty_addr); + case BGP4V2_PEER_LOCAL_PORT: + if (peer->su_local) + if (peer->su_local->sa.sa_family == AF_INET) + return SNMP_INTEGER( + ntohs(peer->su_local->sin.sin_port)); + else + return SNMP_INTEGER( + ntohs(peer->su_local->sin6.sin6_port)); + else + return SNMP_INTEGER(0); + case BGP4V2_PEER_LOCAL_AS: + return SNMP_INTEGER(peer->local_as); + case BGP4V2_PEER_LOCAL_IDENTIFIER: + return SNMP_IPADDRESS(peer->local_id); + case BGP4V2_PEER_REMOTE_PORT: + if (peer->su_remote) + if (peer->su_remote->sa.sa_family == AF_INET) + return SNMP_INTEGER( + ntohs(peer->su_remote->sin.sin_port)); + else + return SNMP_INTEGER( + ntohs(peer->su_remote->sin6.sin6_port)); + else + return SNMP_INTEGER(0); + case BGP4V2_PEER_REMOTE_AS: + return SNMP_INTEGER(peer->as); + case BGP4V2_PEER_REMOTE_IDENTIFIER: + return SNMP_IPADDRESS(peer->remote_id); + case BGP4V2_PEER_ADMIN_STATUS: +#define BGP_PEER_ADMIN_STATUS_HALTED 1 +#define BGP_PEER_ADMIN_STATUS_RUNNING 2 + if (BGP_PEER_START_SUPPRESSED(peer)) + return SNMP_INTEGER(BGP_PEER_ADMIN_STATUS_HALTED); + else + return SNMP_INTEGER(BGP_PEER_ADMIN_STATUS_RUNNING); + case BGP4V2_PEER_STATE: + return SNMP_INTEGER(peer->status); + case BGP4V2_PEER_DESCRIPTION: + if (peer->desc) + return SNMP_STRING(peer->desc); + default: + break; + } + + return NULL; +} + +static struct variable bgpv2_variables[] = { + {BGP4V2_PEER_INSTANCE, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_INSTANCE, 1, 4}}, + {BGP4V2_PEER_INSTANCE, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_INSTANCE, 2, 16}}, + {BGP4V2_PEER_LOCAL_ADDR_TYPE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_ADDR_TYPE, 1, 4}}, + {BGP4V2_PEER_LOCAL_ADDR_TYPE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_ADDR_TYPE, 2, 16}}, + {BGP4V2_PEER_LOCAL_ADDR, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_ADDR, 1, 4}}, + {BGP4V2_PEER_LOCAL_ADDR, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_ADDR, 2, 16}}, + {BGP4V2_PEER_REMOTE_ADDR_TYPE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_ADDR_TYPE, 1, 4}}, + {BGP4V2_PEER_REMOTE_ADDR_TYPE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_ADDR_TYPE, 2, 16}}, + {BGP4V2_PEER_REMOTE_ADDR, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_ADDR, 1, 4}}, + {BGP4V2_PEER_REMOTE_ADDR, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_ADDR, 2, 16}}, + {BGP4V2_PEER_LOCAL_PORT, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 1, 4}}, + {BGP4V2_PEER_LOCAL_PORT, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_PORT, 2, 16}}, + {BGP4V2_PEER_LOCAL_AS, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_AS, 1, 4}}, + {BGP4V2_PEER_LOCAL_AS, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_AS, 2, 16}}, + {BGP4V2_PEER_LOCAL_IDENTIFIER, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_IDENTIFIER, 1, 4}}, + {BGP4V2_PEER_LOCAL_IDENTIFIER, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_LOCAL_IDENTIFIER, 2, 16}}, + {BGP4V2_PEER_REMOTE_PORT, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 1, 4}}, + {BGP4V2_PEER_REMOTE_PORT, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_PORT, 2, 16}}, + {BGP4V2_PEER_REMOTE_AS, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_AS, 1, 4}}, + {BGP4V2_PEER_REMOTE_AS, + ASN_UNSIGNED, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_AS, 2, 16}}, + {BGP4V2_PEER_REMOTE_IDENTIFIER, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_IDENTIFIER, 1, 4}}, + {BGP4V2_PEER_REMOTE_IDENTIFIER, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_REMOTE_IDENTIFIER, 2, 16}}, + {BGP4V2_PEER_ADMIN_STATUS, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_ADMIN_STATUS, 1, 4}}, + {BGP4V2_PEER_ADMIN_STATUS, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_ADMIN_STATUS, 2, 16}}, + {BGP4V2_PEER_STATE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_STATE, 1, 4}}, + {BGP4V2_PEER_STATE, + ASN_INTEGER, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_STATE, 2, 16}}, + {BGP4V2_PEER_DESCRIPTION, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_DESCRIPTION, 1, 4}}, + {BGP4V2_PEER_DESCRIPTION, + ASN_OCTET_STR, + RONLY, + bgpv2PeerTable, + 6, + {1, 2, 1, BGP4V2_PEER_DESCRIPTION, 2, 16}}, +}; + +int bgp_snmp_bgp4v2_init(struct thread_master *tm) +{ + REGISTER_MIB("mibII/bgpv2", bgpv2_variables, variable, bgpv2_oid); + return 0; +} diff --git a/bgpd/bgp_snmp_bgp4v2.h b/bgpd/bgp_snmp_bgp4v2.h new file mode 100644 index 0000000000..6980db9f8d --- /dev/null +++ b/bgpd/bgp_snmp_bgp4v2.h @@ -0,0 +1,97 @@ +/* BGP4V2-MIB SNMP support + * + * Using: http://www.circitor.fr/Mibs/Html/B/BGP4V2-MIB.php + * + * Copyright (C) 2022 Donatas Abraitis + * + * This file is part of FRRouting (FRR). + * + * FRR is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2, or (at your option) any later version. + * + * FRR is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_BGP_SNMP_BGP4V2_H_ +#define _FRR_BGP_SNMP_BGP4V2_H_ + +/* bgp4V2 */ +#define BGP4V2MIB 1, 3, 6, 1, 3, 5, 1 + +/* bgp4V2PeerEntry: + * offset 1.3.6.1.3.5.1.1.2.1.x.(1|2).(4|16) = 13 + */ +#define BGP4V2_PEER_ENTRY_OFFSET 13 +#define BGP4V2_PEER_INSTANCE 1 +#define BGP4V2_PEER_LOCAL_ADDR_TYPE 2 +#define BGP4V2_PEER_LOCAL_ADDR 3 +#define BGP4V2_PEER_REMOTE_ADDR_TYPE 4 +#define BGP4V2_PEER_REMOTE_ADDR 5 +#define BGP4V2_PEER_LOCAL_PORT 6 +#define BGP4V2_PEER_LOCAL_AS 7 +#define BGP4V2_PEER_LOCAL_IDENTIFIER 8 +#define BGP4V2_PEER_REMOTE_PORT 9 +#define BGP4V2_PEER_REMOTE_AS 10 +#define BGP4V2_PEER_REMOTE_IDENTIFIER 11 +#define BGP4V2_PEER_ADMIN_STATUS 12 +#define BGP4V2_PEER_STATE 13 +#define BGP4V2_PEER_DESCRIPTION 14 + +/* bgp4V2PeerErrorsEntry */ +#define BGP4V2_PEER_LAST_ERROR_CODE_RECEIVED 1 +#define BGP4V2_PEER_LAST_ERROR_SUBCODE_RECEIVED 2 +#define BGP4V2_PEER_LAST_ERROR_RECEIVED_TIME 3 +#define BGP4V2_PEER_LAST_ERROR_RECEIVED_TEXT 4 +#define BGP4V2_PEER_LAST_ERROR_RECEIVED_DATA 5 +#define BGP4V2_PEER_LAST_ERROR_CODE_SENT 6 +#define BGP4V2_PEER_LAST_ERROR_SUBCODE_SENT 7 +#define BGP4V2_PEER_LAST_ERROR_SENT_TIME 8 +#define BGP4V2_PEER_LAST_ERROR_SENT_TEXT 9 +#define BGP4V2_PEER_LAST_ERROR_SENT_DATA 10 + +/* bgp4V2PeerEventTimesEntry */ +#define BGP4V2_PEER_FSM_ESTABLISHED_TIME 1 +#define BGP4V2_PEER_PEER_IN_UPDATES_ELAPSED_TIME 2 + +/* bgp4V2NlriEntry */ +#define BGP4V2_NLRI_INDEX 1 +#define BGP4V2_NLRI_AFI 2 +#define BGP4V2_NLRI_SAFI 3 +#define BGP4V2_NLRI_PREFIX_TYPE 4 +#define BGP4V2_NLRI_PREFIX 5 +#define BGP4V2_NLRI_PREFIX_LEN 6 +#define BGP4V2_NLRI_BEST 7 +#define BGP4V2_NLRI_CALC_LOCAL_PREF 8 +#define BGP4V2_NLRI_ORIGIN 9 +#define BGP4V2_NLRI_NEXT_HOP_ADDR_TYPE 10 +#define BGP4V2_NLRI_NEXT_HOP_ADDR 11 +#define BGP4V2_NLRI_LINK_LOCAL_NEXT_HOP_ADDR_TYPE 12 +#define BGP4V2_NLRI_LINK_LOCAL_NEXT_HOP_ADDR 13 +#define BGP4V2_NLRI_LOCAL_PREF_PRESENT 14 +#define BGP4V2_NLRI_LOCAL_PREF 15 +#define BGP4V2_NLRI_MED_PRESENT 16 +#define BGP4V2_NLRI_MED 17 +#define BGP4V2_NLRI_ATOMIC_AGGREGATE 18 +#define BGP4V2_NLRI_AGGREGATOR_PRESENT 19 +#define BGP4V2_NLRI_AGGREGATOR_AS 20 +#define BGP4V2_NLRI_AGGREGATOR_ADDR 21 +#define BGP4V2_NLRI_AS_PATH_CALC_LENGTH 22 +#define BGP4V2_NLRI_AS_PATH_STRING 23 +#define BGP4V2_NLRI_AS_PATH 24 +#define BGP4V2_NLRI_PATH_ATTR_UNKNOWN 25 + +/* bgp4V2Notifications */ +#define BGP4V2_ESTABLISHED_NOTIFICATION 1 +#define BGP4V2_BACKWARD_TRANSITION_NOTIFICATION 2 + +extern int bgp_snmp_bgp4v2_init(struct thread_master *tm); + +#endif /* _FRR_BGP_SNMP_BGP4V2_H_ */ diff --git a/bgpd/subdir.am b/bgpd/subdir.am index 04fe1f1249..88f53da35e 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -151,6 +151,9 @@ noinst_HEADERS += \ bgpd/bgp_route.h \ bgpd/bgp_routemap_nb.h \ bgpd/bgp_script.h \ + bgpd/bgp_snmp.h \ + bgpd/bgp_snmp_bgp4.h \ + bgpd/bgp_snmp_bgp4v2.h \ bgpd/bgp_table.h \ bgpd/bgp_updgrp.h \ bgpd/bgp_vpn.h \ @@ -189,7 +192,7 @@ bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBYANG_LIBS) $(LIBCAP) $(LIBM) $(UST_LIBS) bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBYANG_LIBS) $(LIBCAP) $(LIBM) $(UST_LIBS) -bgpd_bgpd_snmp_la_SOURCES = bgpd/bgp_snmp.c bgpd/bgp_mplsvpn_snmp.c +bgpd_bgpd_snmp_la_SOURCES = bgpd/bgp_snmp_bgp4.c bgpd/bgp_snmp_bgp4v2.c bgpd/bgp_snmp.c bgpd/bgp_mplsvpn_snmp.c bgpd_bgpd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11 bgpd_bgpd_snmp_la_LDFLAGS = $(MODULE_LDFLAGS) bgpd_bgpd_snmp_la_LIBADD = lib/libfrrsnmp.la diff --git a/lib/smux.h b/lib/smux.h index 74447341d8..48c3374236 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -44,6 +44,7 @@ extern "C" { #define SNMP_INVALID 2 #define IN_ADDR_SIZE sizeof(struct in_addr) +#define IN6_ADDR_SIZE sizeof(struct in6_addr) /* IANAipRouteProtocol */ #define IANAIPROUTEPROTOCOLOTHER 1 @@ -87,8 +88,9 @@ struct index_oid { /* Declare SMUX return value. */ #define SNMP_LOCAL_VARIABLES \ static long snmp_int_val __attribute__((unused)); \ - static struct in_addr snmp_in_addr_val __attribute__((unused)); - static uint8_t snmp_octet_val __attribute__((unused)); + static struct in_addr snmp_in_addr_val __attribute__((unused)); \ + static uint8_t snmp_octet_val __attribute__((unused)); \ + static char snmp_string_val[255] __attribute__((unused)); #define SNMP_INTEGER(V) \ (*var_len = sizeof(snmp_int_val), snmp_int_val = V, \ (uint8_t *)&snmp_int_val) @@ -97,6 +99,10 @@ struct index_oid { (*var_len = sizeof(snmp_octet_val), snmp_octet_val = V, \ (uint8_t *)&snmp_octet_val) +#define SNMP_STRING(V) \ + (*var_len = MIN(sizeof(snmp_string_val), strlen(V) + 1), \ + strlcpy(snmp_string_val, V, *var_len), (uint8_t *)&snmp_string_val) + #define SNMP_IPADDRESS(V) \ (*var_len = sizeof(struct in_addr), snmp_in_addr_val = V, \ (uint8_t *)&snmp_in_addr_val) -- 2.39.5