// SPDX-License-Identifier: GPL-2.0-or-later /* OSPFv3 SNMP support * Copyright (C) 2004 Yasuhiro Ohara */ #include #include #include #include "log.h" #include "vty.h" #include "linklist.h" #include "vector.h" #include "vrf.h" #include "smux.h" #include "libfrr.h" #include "lib/version.h" #include "ospf6_proto.h" #include "ospf6_lsa.h" #include "ospf6_lsdb.h" #include "ospf6_route.h" #include "ospf6_top.h" #include "ospf6_area.h" #include "ospf6_interface.h" #include "ospf6_message.h" #include "ospf6_neighbor.h" #include "ospf6_abr.h" #include "ospf6_asbr.h" #include "ospf6d.h" /* OSPFv3-MIB */ #define OSPFv3MIB 1,3,6,1,2,1,191 /* OSPFv3 MIB General Group values. */ #define OSPFv3ROUTERID 1 #define OSPFv3ADMINSTAT 2 #define OSPFv3VERSIONNUMBER 3 #define OSPFv3AREABDRRTRSTATUS 4 #define OSPFv3ASBDRRTRSTATUS 5 #define OSPFv3ASSCOPELSACOUNT 6 #define OSPFv3ASSCOPELSACHECKSUMSUM 7 #define OSPFv3ORIGINATENEWLSAS 8 #define OSPFv3RXNEWLSAS 9 #define OSPFv3EXTLSACOUNT 10 #define OSPFv3EXTAREALSDBLIMIT 11 #define OSPFv3EXITOVERFLOWINTERVAL 12 #define OSPFv3DEMANDEXTENSIONS 13 #define OSPFv3REFERENCEBANDWIDTH 14 #define OSPFv3RESTARTSUPPORT 15 #define OSPFv3RESTARTINTERVAL 16 #define OSPFv3RESTARTSTRICTLSACHECKING 17 #define OSPFv3RESTARTSTATUS 18 #define OSPFv3RESTARTAGE 19 #define OSPFv3RESTARTEXITREASON 20 #define OSPFv3NOTIFICATIONENABLE 21 #define OSPFv3STUBROUTERSUPPORT 22 #define OSPFv3STUBROUTERADVERTISEMENT 23 #define OSPFv3DISCONTINUITYTIME 24 #define OSPFv3RESTARTTIME 25 /* OSPFv3 MIB Area Table values: ospfv3AreaTable */ #define OSPFv3IMPORTASEXTERN 2 #define OSPFv3AREASPFRUNS 3 #define OSPFv3AREABDRRTRCOUNT 4 #define OSPFv3AREAASBDRRTRCOUNT 5 #define OSPFv3AREASCOPELSACOUNT 6 #define OSPFv3AREASCOPELSACKSUMSUM 7 #define OSPFv3AREASUMMARY 8 #define OSPFv3AREAROWSTATUS 9 #define OSPFv3AREASTUBMETRIC 10 #define OSPFv3AREANSSATRANSLATORROLE 11 #define OSPFv3AREANSSATRANSLATORSTATE 12 #define OSPFv3AREANSSATRANSLATORSTABINTERVAL 13 #define OSPFv3AREANSSATRANSLATOREVENTS 14 #define OSPFv3AREASTUBMETRICTYPE 15 #define OSPFv3AREATEENABLED 16 /* OSPFv3 MIB * Lsdb Table values: ospfv3*LsdbTable */ #define OSPFv3WWLSDBSEQUENCE 1 #define OSPFv3WWLSDBAGE 2 #define OSPFv3WWLSDBCHECKSUM 3 #define OSPFv3WWLSDBADVERTISEMENT 4 #define OSPFv3WWLSDBTYPEKNOWN 5 /* Three first bits are to identify column */ #define OSPFv3WWCOLUMN 0x7 /* Then we use other bits to identify table */ #define OSPFv3WWASTABLE (1 << 3) #define OSPFv3WWAREATABLE (1 << 4) #define OSPFv3WWLINKTABLE (1 << 5) #define OSPFv3WWVIRTLINKTABLE (1 << 6) /* OSPFv3 MIB Host Table values: ospfv3HostTable */ #define OSPFv3HOSTMETRIC 3 #define OSPFv3HOSTROWSTATUS 4 #define OSPFv3HOSTAREAID 5 /* OSPFv3 MIB Interface Table values: ospfv3IfTable */ #define OSPFv3IFAREAID 3 #define OSPFv3IFTYPE 4 #define OSPFv3IFADMINSTATUS 5 #define OSPFv3IFRTRPRIORITY 6 #define OSPFv3IFTRANSITDELAY 7 #define OSPFv3IFRETRANSINTERVAL 8 #define OSPFv3IFHELLOINTERVAL 9 #define OSPFv3IFRTRDEADINTERVAL 10 #define OSPFv3IFPOLLINTERVAL 11 #define OSPFv3IFSTATE 12 #define OSPFv3IFDESIGNATEDROUTER 13 #define OSPFv3IFBACKUPDESIGNATEDROUTER 14 #define OSPFv3IFEVENTS 15 #define OSPFv3IFROWSTATUS 16 #define OSPFv3IFDEMAND 17 #define OSPFv3IFMETRICVALUE 18 #define OSPFv3IFLINKSCOPELSACOUNT 19 #define OSPFv3IFLINKLSACKSUMSUM 20 #define OSPFv3IFDEMANDNBRPROBE 21 #define OSPFv3IFDEMANDNBRPROBERETRANSLIMIT 22 #define OSPFv3IFDEMANDNBRPROBEINTERVAL 23 #define OSPFv3IFTEDISABLED 24 #define OSPFv3IFLINKLSASUPPRESSION 25 /* OSPFv3 MIB Virtual Interface Table values: ospfv3VirtIfTable */ #define OSPFv3VIRTIFINDEX 3 #define OSPFv3VIRTIFINSTID 4 #define OSPFv3VIRTIFTRANSITDELAY 5 #define OSPFv3VIRTIFRETRANSINTERVAL 6 #define OSPFv3VIRTIFHELLOINTERVAL 7 #define OSPFv3VIRTIFRTRDEADINTERVAL 8 #define OSPFv3VIRTIFSTATE 9 #define OSPFv3VIRTIFEVENTS 10 #define OSPFv3VIRTIFROWSTATUS 11 #define OSPFv3VIRTIFLINKSCOPELSACOUNT 12 #define OSPFv3VIRTIFLINKLSACKSUMSUM 13 /* OSPFv3 MIB Neighbors Table values: ospfv3NbrTable */ #define OSPFv3NBRADDRESSTYPE 4 #define OSPFv3NBRADDRESS 5 #define OSPFv3NBROPTIONS 6 #define OSPFv3NBRPRIORITY 7 #define OSPFv3NBRSTATE 8 #define OSPFv3NBREVENTS 9 #define OSPFv3NBRLSRETRANSQLEN 10 #define OSPFv3NBRHELLOSUPPRESSED 11 #define OSPFv3NBRIFID 12 #define OSPFv3NBRRESTARTHELPERSTATUS 13 #define OSPFv3NBRRESTARTHELPERAGE 14 #define OSPFv3NBRRESTARTHELPEREXITREASON 15 /* OSPFv3 MIB Configured Neighbors Table values: ospfv3CfgNbrTable */ #define OSPFv3CFGNBRPRIORITY 5 #define OSPFv3CFGNBRROWSTATUS 6 /* OSPFv3 MIB Virtual Neighbors Table values: ospfv3VirtNbrTable */ #define OSPFv3VIRTNBRIFINDEX 3 #define OSPFv3VIRTNBRIFINSTID 4 #define OSPFv3VIRTNBRADDRESSTYPE 5 #define OSPFv3VIRTNBRADDRESS 6 #define OSPFv3VIRTNBROPTIONS 7 #define OSPFv3VIRTNBRSTATE 8 #define OSPFv3VIRTNBREVENTS 9 #define OSPFv3VIRTNBRLSRETRANSQLEN 10 #define OSPFv3VIRTNBRHELLOSUPPRESSED 11 #define OSPFv3VIRTNBRIFID 12 #define OSPFv3VIRTNBRRESTARTHELPERSTATUS 13 #define OSPFv3VIRTNBRRESTARTHELPERAGE 14 #define OSPFv3VIRTNBRRESTARTHELPEREXITREASON 15 /* OSPFv3 MIB Area Aggregate Table values: ospfv3AreaAggregateTable */ #define OSPFv3AREAAGGREGATEROWSTATUS 6 #define OSPFv3AREAAGGREGATEEFFECT 7 #define OSPFv3AREAAGGREGATEROUTETAG 8 /* SYNTAX Status from OSPF-MIB. */ #define OSPF_STATUS_ENABLED 1 #define OSPF_STATUS_DISABLED 2 /* SNMP value hack. */ #define COUNTER ASN_COUNTER #define INTEGER ASN_INTEGER #define GAUGE ASN_GAUGE #define UNSIGNED ASN_UNSIGNED #define TIMETICKS ASN_TIMETICKS #define IPADDRESS ASN_IPADDRESS #define STRING ASN_OCTET_STR /* For return values e.g. SNMP_INTEGER macro */ SNMP_LOCAL_VARIABLES /* OSPFv3-MIB instances. */ static oid ospfv3_oid[] = {OSPFv3MIB}; static oid ospfv3_trap_oid[] = {OSPFv3MIB, 0}; /* Hook functions. */ static uint8_t *ospfv3GeneralGroup(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); static uint8_t *ospfv3AreaEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); static uint8_t *ospfv3WwLsdbEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); static uint8_t *ospfv3NbrEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); static uint8_t *ospfv3IfEntry(struct variable *, oid *, size_t *, int, size_t *, WriteMethod **); static struct variable ospfv3_variables[] = { /* OSPF general variables */ {OSPFv3ROUTERID, UNSIGNED, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 1}}, {OSPFv3ADMINSTAT, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 2}}, {OSPFv3VERSIONNUMBER, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 3}}, {OSPFv3AREABDRRTRSTATUS, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 4}}, {OSPFv3ASBDRRTRSTATUS, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 5}}, {OSPFv3ASSCOPELSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, 3, {1, 1, 6}}, {OSPFv3ASSCOPELSACHECKSUMSUM, UNSIGNED, RONLY, ospfv3GeneralGroup, 3, {1, 1, 7}}, {OSPFv3ORIGINATENEWLSAS, COUNTER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 8}}, {OSPFv3RXNEWLSAS, COUNTER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 9}}, {OSPFv3EXTLSACOUNT, GAUGE, RONLY, ospfv3GeneralGroup, 3, {1, 1, 10}}, {OSPFv3EXTAREALSDBLIMIT, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 11}}, {OSPFv3EXITOVERFLOWINTERVAL, UNSIGNED, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 12}}, {OSPFv3DEMANDEXTENSIONS, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 13}}, {OSPFv3REFERENCEBANDWIDTH, UNSIGNED, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 14}}, {OSPFv3RESTARTSUPPORT, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 15}}, {OSPFv3RESTARTINTERVAL, UNSIGNED, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 16}}, {OSPFv3RESTARTSTRICTLSACHECKING, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 17}}, {OSPFv3RESTARTSTATUS, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 18}}, {OSPFv3RESTARTAGE, UNSIGNED, RONLY, ospfv3GeneralGroup, 3, {1, 1, 19}}, {OSPFv3RESTARTEXITREASON, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 20}}, {OSPFv3NOTIFICATIONENABLE, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 21}}, {OSPFv3STUBROUTERSUPPORT, INTEGER, RONLY, ospfv3GeneralGroup, 3, {1, 1, 22}}, {OSPFv3STUBROUTERADVERTISEMENT, INTEGER, RWRITE, ospfv3GeneralGroup, 3, {1, 1, 23}}, {OSPFv3DISCONTINUITYTIME, TIMETICKS, RONLY, ospfv3GeneralGroup, 3, {1, 1, 24}}, {OSPFv3RESTARTTIME, TIMETICKS, RONLY, ospfv3GeneralGroup, 3, {1, 1, 25}}, /* OSPFv3 Area Data Structure */ {OSPFv3IMPORTASEXTERN, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 2}}, {OSPFv3AREASPFRUNS, COUNTER, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 3}}, {OSPFv3AREABDRRTRCOUNT, GAUGE, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 4}}, {OSPFv3AREAASBDRRTRCOUNT, GAUGE, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 5}}, {OSPFv3AREASCOPELSACOUNT, GAUGE, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 6}}, {OSPFv3AREASCOPELSACKSUMSUM, UNSIGNED, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 7}}, {OSPFv3AREASUMMARY, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 8}}, {OSPFv3AREAROWSTATUS, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 9}}, {OSPFv3AREASTUBMETRIC, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 10}}, {OSPFv3AREANSSATRANSLATORROLE, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 11}}, {OSPFv3AREANSSATRANSLATORSTATE, INTEGER, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 12}}, {OSPFv3AREANSSATRANSLATORSTABINTERVAL, UNSIGNED, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 13}}, {OSPFv3AREANSSATRANSLATOREVENTS, COUNTER, RONLY, ospfv3AreaEntry, 4, {1, 2, 1, 14}}, {OSPFv3AREASTUBMETRICTYPE, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 15}}, {OSPFv3AREATEENABLED, INTEGER, RWRITE, ospfv3AreaEntry, 4, {1, 2, 1, 16}}, /* OSPFv3 AS LSDB */ {OSPFv3WWLSDBSEQUENCE | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 3, 1, 4}}, {OSPFv3WWLSDBAGE | OSPFv3WWASTABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, 4, {1, 3, 1, 5}}, {OSPFv3WWLSDBCHECKSUM | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 3, 1, 6}}, {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWASTABLE, STRING, RONLY, ospfv3WwLsdbEntry, 4, {1, 3, 1, 7}}, {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWASTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 3, 1, 8}}, /* OSPFv3 Area LSDB */ {OSPFv3WWLSDBSEQUENCE | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 4, 1, 5}}, {OSPFv3WWLSDBAGE | OSPFv3WWAREATABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, 4, {1, 4, 1, 6}}, {OSPFv3WWLSDBCHECKSUM | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 4, 1, 7}}, {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWAREATABLE, STRING, RONLY, ospfv3WwLsdbEntry, 4, {1, 4, 1, 8}}, {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWAREATABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 4, 1, 9}}, /* OSPFv3 Link LSDB */ {OSPFv3WWLSDBSEQUENCE | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 5, 1, 6}}, {OSPFv3WWLSDBAGE | OSPFv3WWLINKTABLE, UNSIGNED, RONLY, ospfv3WwLsdbEntry, 4, {1, 5, 1, 7}}, {OSPFv3WWLSDBCHECKSUM | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 5, 1, 8}}, {OSPFv3WWLSDBADVERTISEMENT | OSPFv3WWLINKTABLE, STRING, RONLY, ospfv3WwLsdbEntry, 4, {1, 5, 1, 9}}, {OSPFv3WWLSDBTYPEKNOWN | OSPFv3WWLINKTABLE, INTEGER, RONLY, ospfv3WwLsdbEntry, 4, {1, 5, 1, 10}}, /* OSPFv3 interfaces */ {OSPFv3IFAREAID, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 3}}, {OSPFv3IFTYPE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 4}}, {OSPFv3IFADMINSTATUS, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 5}}, {OSPFv3IFRTRPRIORITY, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 6}}, {OSPFv3IFTRANSITDELAY, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 7}}, {OSPFv3IFRETRANSINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 8}}, {OSPFv3IFHELLOINTERVAL, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 9}}, {OSPFv3IFRTRDEADINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 10}}, {OSPFv3IFPOLLINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 11}}, {OSPFv3IFSTATE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 12}}, {OSPFv3IFDESIGNATEDROUTER, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 13}}, {OSPFv3IFBACKUPDESIGNATEDROUTER, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 14}}, {OSPFv3IFEVENTS, COUNTER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 15}}, {OSPFv3IFROWSTATUS, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 16}}, {OSPFv3IFDEMAND, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 17}}, {OSPFv3IFMETRICVALUE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 18}}, {OSPFv3IFLINKSCOPELSACOUNT, GAUGE, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 19}}, {OSPFv3IFLINKLSACKSUMSUM, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 20}}, {OSPFv3IFDEMANDNBRPROBE, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 21}}, {OSPFv3IFDEMANDNBRPROBERETRANSLIMIT, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 22}}, {OSPFv3IFDEMANDNBRPROBEINTERVAL, UNSIGNED, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 23}}, {OSPFv3IFTEDISABLED, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 24}}, {OSPFv3IFLINKLSASUPPRESSION, INTEGER, RONLY, ospfv3IfEntry, 4, {1, 7, 1, 25}}, /* OSPFv3 neighbors */ {OSPFv3NBRADDRESSTYPE, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 4}}, {OSPFv3NBRADDRESS, STRING, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 5}}, {OSPFv3NBROPTIONS, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 6}}, {OSPFv3NBRPRIORITY, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 7}}, {OSPFv3NBRSTATE, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 8}}, {OSPFv3NBREVENTS, COUNTER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 9}}, {OSPFv3NBRLSRETRANSQLEN, GAUGE, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 10}}, {OSPFv3NBRHELLOSUPPRESSED, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 11}}, {OSPFv3NBRIFID, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 12}}, {OSPFv3NBRRESTARTHELPERSTATUS, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 13}}, {OSPFv3NBRRESTARTHELPERAGE, UNSIGNED, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 14}}, {OSPFv3NBRRESTARTHELPEREXITREASON, INTEGER, RONLY, ospfv3NbrEntry, 4, {1, 9, 1, 15}}, }; static uint8_t *ospfv3GeneralGroup(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { uint16_t sum; uint32_t count; struct ospf6_lsa *lsa = NULL, *lsanext; struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_id(VRF_DEFAULT); /* Check whether the instance identifier is valid */ if (smux_header_generic(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; /* Return the current value of the variable */ switch (v->magic) { case OSPFv3ROUTERID: /* Router-ID of this OSPF instance. */ if (ospf6) return SNMP_INTEGER(ntohl(ospf6->router_id)); return SNMP_INTEGER(0); case OSPFv3ADMINSTAT: if (ospf6) return SNMP_INTEGER( CHECK_FLAG(ospf6->flag, OSPF6_DISABLED) ? OSPF_STATUS_DISABLED : OSPF_STATUS_ENABLED); return SNMP_INTEGER(OSPF_STATUS_DISABLED); case OSPFv3VERSIONNUMBER: return SNMP_INTEGER(3); case OSPFv3AREABDRRTRSTATUS: if (ospf6) return SNMP_INTEGER( ospf6_check_and_set_router_abr(ospf6) ? SNMP_TRUE : SNMP_FALSE); return SNMP_INTEGER(SNMP_FALSE); case OSPFv3ASBDRRTRSTATUS: if (ospf6) return SNMP_INTEGER(ospf6_asbr_is_asbr(ospf6) ? SNMP_TRUE : SNMP_FALSE); return SNMP_INTEGER(SNMP_FALSE); case OSPFv3ASSCOPELSACOUNT: if (ospf6) return SNMP_INTEGER(ospf6->lsdb->count); return SNMP_INTEGER(0); case OSPFv3ASSCOPELSACHECKSUMSUM: if (ospf6) { sum = 0; for (ALL_LSDB(ospf6->lsdb, lsa, lsanext)) sum += ntohs(lsa->header->checksum); return SNMP_INTEGER(sum); } return SNMP_INTEGER(0); case OSPFv3ORIGINATENEWLSAS: return SNMP_INTEGER( 0); /* Don't know where to get this value... */ case OSPFv3RXNEWLSAS: return SNMP_INTEGER( 0); /* Don't know where to get this value... */ case OSPFv3EXTLSACOUNT: if (ospf6) { count = 0; for (ALL_LSDB_TYPED(ospf6->lsdb, htons(OSPF6_LSTYPE_AS_EXTERNAL), lsa)) count += 1; return SNMP_INTEGER(count); } return SNMP_INTEGER(0); case OSPFv3EXTAREALSDBLIMIT: return SNMP_INTEGER(-1); case OSPFv3EXITOVERFLOWINTERVAL: return SNMP_INTEGER(0); /* Not supported */ case OSPFv3DEMANDEXTENSIONS: return SNMP_INTEGER(0); /* Not supported */ case OSPFv3REFERENCEBANDWIDTH: if (ospf6) return SNMP_INTEGER(ospf6->ref_bandwidth); /* Otherwise, like for "not implemented". */ return NULL; case OSPFv3RESTARTSUPPORT: case OSPFv3RESTARTINTERVAL: case OSPFv3RESTARTSTRICTLSACHECKING: case OSPFv3RESTARTSTATUS: case OSPFv3RESTARTAGE: case OSPFv3RESTARTEXITREASON: case OSPFv3NOTIFICATIONENABLE: case OSPFv3STUBROUTERSUPPORT: case OSPFv3STUBROUTERADVERTISEMENT: case OSPFv3DISCONTINUITYTIME: case OSPFv3RESTARTTIME: /* TODO: Not implemented */ return NULL; } return NULL; } static uint8_t *ospfv3AreaEntry(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct ospf6_area *oa, *area = NULL; struct ospf6_lsa *lsa = NULL, *lsanext; uint32_t area_id = 0; uint32_t count; uint16_t sum; struct listnode *node; unsigned int len; char a[16]; struct ospf6_route *ro; struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_id(VRF_DEFAULT); if (ospf6 == NULL) return NULL; if (smux_header_table(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; len = *length - v->namelen; len = (len >= 1 ? 1 : 0); if (exact && len != 1) return NULL; if (len) area_id = htonl(name[v->namelen]); inet_ntop(AF_INET, &area_id, a, sizeof(a)); zlog_debug("SNMP access by area: %s, exact=%d len=%d length=%lu", a, exact, len, (unsigned long)*length); for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { if (area == NULL) { if (len == 0) /* return first area entry */ area = oa; else if (exact && ntohl(oa->area_id) == ntohl(area_id)) area = oa; else if (ntohl(oa->area_id) > ntohl(area_id)) area = oa; } } if (area == NULL) return NULL; *length = v->namelen + 1; name[v->namelen] = ntohl(area->area_id); inet_ntop(AF_INET, &area->area_id, a, sizeof(a)); zlog_debug("SNMP found area: %s, exact=%d len=%d length=%lu", a, exact, len, (unsigned long)*length); switch (v->magic) { case OSPFv3IMPORTASEXTERN: /* No NSSA support */ return SNMP_INTEGER(IS_AREA_STUB(area) ? 2 : 1); case OSPFv3AREASPFRUNS: return SNMP_INTEGER(area->spf_calculation); case OSPFv3AREABDRRTRCOUNT: case OSPFv3AREAASBDRRTRCOUNT: count = 0; for (ro = ospf6_route_head(ospf6->brouter_table); ro; ro = ospf6_route_next(ro)) { if (ntohl(ro->path.area_id) != ntohl(area->area_id)) continue; if (v->magic == OSPFv3AREABDRRTRCOUNT && CHECK_FLAG(ro->path.router_bits, OSPF6_ROUTER_BIT_B)) count++; if (v->magic == OSPFv3AREAASBDRRTRCOUNT && CHECK_FLAG(ro->path.router_bits, OSPF6_ROUTER_BIT_E)) count++; } return SNMP_INTEGER(count); case OSPFv3AREASCOPELSACOUNT: return SNMP_INTEGER(area->lsdb->count); case OSPFv3AREASCOPELSACKSUMSUM: sum = 0; for (ALL_LSDB(area->lsdb, lsa, lsanext)) sum += ntohs(lsa->header->checksum); return SNMP_INTEGER(sum); case OSPFv3AREASUMMARY: return SNMP_INTEGER(2); /* sendAreaSummary */ case OSPFv3AREAROWSTATUS: return SNMP_INTEGER(1); /* Active */ case OSPFv3AREASTUBMETRIC: case OSPFv3AREANSSATRANSLATORROLE: case OSPFv3AREANSSATRANSLATORSTATE: case OSPFv3AREANSSATRANSLATORSTABINTERVAL: case OSPFv3AREANSSATRANSLATOREVENTS: case OSPFv3AREASTUBMETRICTYPE: case OSPFv3AREATEENABLED: /* Not implemented. */ return NULL; } return NULL; } static int if_icmp_func(struct interface *ifp1, struct interface *ifp2) { return (ifp1->ifindex - ifp2->ifindex); } static uint8_t *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct vrf *vrf; struct ospf6_lsa *lsa = NULL; ifindex_t ifindex; uint32_t area_id, id, instid, adv_router; uint16_t type; int len; oid *offset; int offsetlen; struct ospf6_area *oa = NULL; struct listnode *node; struct interface *iif; struct ospf6_interface *oi = NULL; struct list *ifslist; struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_id(VRF_DEFAULT); if (smux_header_table(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; instid = ifindex = area_id = type = id = adv_router = 0; /* Check OSPFv3 instance. */ if (ospf6 == NULL) return NULL; vrf = vrf_lookup_by_id(ospf6->vrf_id); /* Get variable length. */ offset = name + v->namelen; offsetlen = *length - v->namelen; if (exact && (v->magic & OSPFv3WWASTABLE) && offsetlen != 3) return NULL; if (exact && (v->magic & OSPFv3WWAREATABLE) && offsetlen != 4) return NULL; if (exact && (v->magic & OSPFv3WWLINKTABLE) && offsetlen != 5) return NULL; if (v->magic & OSPFv3WWLINKTABLE) { /* Parse ifindex */ len = (offsetlen < 1 ? 0 : 1); if (len) ifindex = *offset; offset += len; offsetlen -= len; /* Parse instance ID */ len = (offsetlen < 1 ? 0 : 1); if (len) instid = *offset; offset += len; offsetlen -= len; } else if (v->magic & OSPFv3WWAREATABLE) { /* Parse area-id */ len = (offsetlen < 1 ? 0 : 1); if (len) area_id = htonl(*offset); offset += len; offsetlen -= len; } /* Parse type */ len = (offsetlen < 1 ? 0 : 1); if (len) type = htons(*offset); offset += len; offsetlen -= len; /* Parse Router-ID */ len = (offsetlen < 1 ? 0 : 1); if (len) adv_router = htonl(*offset); offset += len; offsetlen -= len; /* Parse LS-ID */ len = (offsetlen < 1 ? 0 : 1); if (len) id = htonl(*offset); offset += len; // offsetlen -= len; // Add back in if we need it again if (exact) { if (v->magic & OSPFv3WWASTABLE) { lsa = ospf6_lsdb_lookup(type, id, adv_router, ospf6->lsdb); } else if (v->magic & OSPFv3WWAREATABLE) { oa = ospf6_area_lookup(area_id, ospf6); if (!oa) return NULL; lsa = ospf6_lsdb_lookup(type, id, adv_router, oa->lsdb); } else if (v->magic & OSPFv3WWLINKTABLE) { oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id); if (!oi || oi->instance_id != instid) return NULL; lsa = ospf6_lsdb_lookup(type, id, adv_router, oi->lsdb); } } else { if (v->magic & OSPFv3WWASTABLE) { if (ospf6->lsdb->count) lsa = ospf6_lsdb_lookup_next( type, id, adv_router, ospf6->lsdb); } else if (v->magic & OSPFv3WWAREATABLE) for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) { if (oa->area_id < area_id) continue; if (oa->lsdb->count) lsa = ospf6_lsdb_lookup_next( type, id, adv_router, oa->lsdb); if (lsa) break; type = 0; id = 0; adv_router = 0; } else if (v->magic & OSPFv3WWLINKTABLE) { /* We build a sorted list of interfaces */ ifslist = list_new(); ifslist->cmp = (int (*)(void *, void *))if_icmp_func; FOR_ALL_INTERFACES (vrf, iif) listnode_add_sort(ifslist, iif); for (ALL_LIST_ELEMENTS_RO(ifslist, node, iif)) { if (!iif->ifindex) continue; oi = iif->info; if (!oi) continue; if (iif->ifindex < ifindex) continue; if (oi->instance_id < instid) continue; if (oi->lsdb->count) lsa = ospf6_lsdb_lookup_next( type, id, adv_router, oi->lsdb); if (lsa) break; type = 0; id = 0; adv_router = 0; oi = NULL; } list_delete_all_node(ifslist); list_delete(&ifslist); } } if (!lsa) return NULL; /* Add indexes */ if (v->magic & OSPFv3WWASTABLE) { *length = v->namelen + 3; offset = name + v->namelen; } else if (v->magic & OSPFv3WWAREATABLE) { *length = v->namelen + 4; offset = name + v->namelen; *offset = ntohl(oa->area_id); offset++; } else if (v->magic & OSPFv3WWLINKTABLE) { *length = v->namelen + 5; offset = name + v->namelen; *offset = oi->interface->ifindex; offset++; *offset = oi->instance_id; offset++; } *offset = ntohs(lsa->header->type); offset++; *offset = ntohl(lsa->header->adv_router); offset++; *offset = ntohl(lsa->header->id); offset++; /* Return the current value of the variable */ switch (v->magic & OSPFv3WWCOLUMN) { case OSPFv3WWLSDBSEQUENCE: return SNMP_INTEGER(ntohl(lsa->header->seqnum)); case OSPFv3WWLSDBAGE: ospf6_lsa_age_current(lsa); return SNMP_INTEGER(ntohs(lsa->header->age)); case OSPFv3WWLSDBCHECKSUM: return SNMP_INTEGER(ntohs(lsa->header->checksum)); case OSPFv3WWLSDBADVERTISEMENT: *var_len = ntohs(lsa->header->length); return (uint8_t *)lsa->header; case OSPFv3WWLSDBTYPEKNOWN: return SNMP_INTEGER(OSPF6_LSA_IS_KNOWN(lsa->header->type) ? SNMP_TRUE : SNMP_FALSE); } return NULL; } static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct vrf *vrf; ifindex_t ifindex = 0; unsigned int instid = 0; struct ospf6_interface *oi = NULL; struct ospf6_lsa *lsa = NULL, *lsanext; struct interface *iif; struct listnode *i; struct list *ifslist; oid *offset; int offsetlen, len; uint32_t sum; struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_id(VRF_DEFAULT); if (smux_header_table(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; /* Check OSPFv3 instance. */ if (ospf6 == NULL) return NULL; vrf = vrf_lookup_by_id(ospf6->vrf_id); /* Get variable length. */ offset = name + v->namelen; offsetlen = *length - v->namelen; if (exact && offsetlen != 2) return NULL; /* Parse if index */ len = (offsetlen < 1 ? 0 : 1); if (len) ifindex = *offset; offset += len; offsetlen -= len; /* Parse instance ID */ len = (offsetlen < 1 ? 0 : 1); if (len) instid = *offset; // offset += len; // Add back in if we ever start using again // offsetlen -= len; if (exact) { oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id); if (!oi || oi->instance_id != instid) return NULL; } else { /* We build a sorted list of interfaces */ ifslist = list_new(); ifslist->cmp = (int (*)(void *, void *))if_icmp_func; FOR_ALL_INTERFACES (vrf, iif) listnode_add_sort(ifslist, iif); for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) { if (!iif->ifindex) continue; oi = iif->info; if (!oi) continue; if (iif->ifindex > ifindex || (iif->ifindex == ifindex && (oi->instance_id > instid))) break; oi = NULL; } list_delete_all_node(ifslist); list_delete(&ifslist); } if (!oi) return NULL; /* Add Index (IfIndex, IfInstId) */ *length = v->namelen + 2; offset = name + v->namelen; *offset = oi->interface->ifindex; offset++; *offset = oi->instance_id; offset++; /* Return the current value of the variable */ switch (v->magic) { case OSPFv3IFAREAID: if (oi->area) return SNMP_INTEGER(ntohl(oi->area->area_id)); break; case OSPFv3IFTYPE: if (oi->type == OSPF_IFTYPE_BROADCAST) return SNMP_INTEGER(1); else if (oi->type == OSPF_IFTYPE_POINTOPOINT) return SNMP_INTEGER(3); else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) return SNMP_INTEGER(5); else break; /* Unknown, don't put anything */ case OSPFv3IFADMINSTATUS: if (oi->area) return SNMP_INTEGER(OSPF_STATUS_ENABLED); return SNMP_INTEGER(OSPF_STATUS_DISABLED); case OSPFv3IFRTRPRIORITY: return SNMP_INTEGER(oi->priority); case OSPFv3IFTRANSITDELAY: return SNMP_INTEGER(oi->transdelay); case OSPFv3IFRETRANSINTERVAL: return SNMP_INTEGER(oi->rxmt_interval); case OSPFv3IFHELLOINTERVAL: return SNMP_INTEGER(oi->hello_interval); case OSPFv3IFRTRDEADINTERVAL: return SNMP_INTEGER(oi->dead_interval); case OSPFv3IFPOLLINTERVAL: /* No support for NBMA */ break; case OSPFv3IFSTATE: return SNMP_INTEGER(oi->state); case OSPFv3IFDESIGNATEDROUTER: return SNMP_INTEGER(ntohl(oi->drouter)); case OSPFv3IFBACKUPDESIGNATEDROUTER: return SNMP_INTEGER(ntohl(oi->bdrouter)); case OSPFv3IFEVENTS: return SNMP_INTEGER(oi->state_change); case OSPFv3IFROWSTATUS: return SNMP_INTEGER(1); case OSPFv3IFDEMAND: return SNMP_INTEGER(SNMP_FALSE); case OSPFv3IFMETRICVALUE: return SNMP_INTEGER(oi->cost); case OSPFv3IFLINKSCOPELSACOUNT: return SNMP_INTEGER(oi->lsdb->count); case OSPFv3IFLINKLSACKSUMSUM: sum = 0; for (ALL_LSDB(oi->lsdb, lsa, lsanext)) sum += ntohs(lsa->header->checksum); return SNMP_INTEGER(sum); case OSPFv3IFDEMANDNBRPROBE: case OSPFv3IFDEMANDNBRPROBERETRANSLIMIT: case OSPFv3IFDEMANDNBRPROBEINTERVAL: case OSPFv3IFTEDISABLED: case OSPFv3IFLINKLSASUPPRESSION: /* Not implemented. Only works if all the last ones are not implemented! */ return NULL; } /* Try an internal getnext. Some columns are missing in this table. */ if (!exact && (name[*length - 1] < MAX_SUBID)) return ospfv3IfEntry(v, name, length, exact, var_len, write_method); return NULL; } static uint8_t *ospfv3NbrEntry(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { struct vrf *vrf; ifindex_t ifindex = 0; unsigned int instid, rtrid; struct ospf6_interface *oi = NULL; struct ospf6_neighbor *on = NULL; struct interface *iif; struct listnode *i, *j; struct list *ifslist; oid *offset; int offsetlen, len; struct ospf6 *ospf6; ospf6 = ospf6_lookup_by_vrf_id(VRF_DEFAULT); if (smux_header_table(v, name, length, exact, var_len, write_method) == MATCH_FAILED) return NULL; instid = rtrid = 0; /* Check OSPFv3 instance. */ if (ospf6 == NULL) return NULL; vrf = vrf_lookup_by_id(ospf6->vrf_id); /* Get variable length. */ offset = name + v->namelen; offsetlen = *length - v->namelen; if (exact && offsetlen != 3) return NULL; /* Parse if index */ len = (offsetlen < 1 ? 0 : 1); if (len) ifindex = *offset; offset += len; offsetlen -= len; /* Parse instance ID */ len = (offsetlen < 1 ? 0 : 1); if (len) instid = *offset; offset += len; offsetlen -= len; /* Parse router ID */ len = (offsetlen < 1 ? 0 : 1); if (len) rtrid = htonl(*offset); // offset += len; // Add back in if we ever start looking at data // offsetlen -= len; if (exact) { oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id); if (!oi || oi->instance_id != instid) return NULL; on = ospf6_neighbor_lookup(rtrid, oi); } else { /* We build a sorted list of interfaces */ ifslist = list_new(); ifslist->cmp = (int (*)(void *, void *))if_icmp_func; FOR_ALL_INTERFACES (vrf, iif) listnode_add_sort(ifslist, iif); for (ALL_LIST_ELEMENTS_RO(ifslist, i, iif)) { if (!iif->ifindex) continue; oi = iif->info; if (!oi) continue; for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) { if (iif->ifindex > ifindex || (iif->ifindex == ifindex && (oi->instance_id > instid || (oi->instance_id == instid && ntohl(on->router_id) > ntohl(rtrid))))) break; } if (on) break; oi = NULL; on = NULL; } list_delete_all_node(ifslist); list_delete(&ifslist); } if (!oi || !on) return NULL; /* Add Index (IfIndex, IfInstId, RtrId) */ *length = v->namelen + 3; offset = name + v->namelen; *offset = oi->interface->ifindex; offset++; *offset = oi->instance_id; offset++; *offset = ntohl(on->router_id); offset++; /* Return the current value of the variable */ switch (v->magic) { case OSPFv3NBRADDRESSTYPE: return SNMP_INTEGER(2); /* IPv6 only */ case OSPFv3NBRADDRESS: *var_len = sizeof(struct in6_addr); return (uint8_t *)&on->linklocal_addr; case OSPFv3NBROPTIONS: return SNMP_INTEGER(on->options[2]); case OSPFv3NBRPRIORITY: return SNMP_INTEGER(on->priority); case OSPFv3NBRSTATE: return SNMP_INTEGER(on->state); case OSPFv3NBREVENTS: return SNMP_INTEGER(on->state_change); case OSPFv3NBRLSRETRANSQLEN: return SNMP_INTEGER(on->retrans_list->count); case OSPFv3NBRHELLOSUPPRESSED: return SNMP_INTEGER(SNMP_FALSE); case OSPFv3NBRIFID: return SNMP_INTEGER(on->ifindex); case OSPFv3NBRRESTARTHELPERSTATUS: case OSPFv3NBRRESTARTHELPERAGE: case OSPFv3NBRRESTARTHELPEREXITREASON: /* Not implemented. Only works if all the last ones are not implemented! */ return NULL; } return NULL; } /* OSPF Traps. */ #define NBRSTATECHANGE 2 #define IFSTATECHANGE 10 static struct trap_object ospf6NbrTrapList[] = { {-3, {1, 1, OSPFv3ROUTERID}}, {4, {1, 9, 1, OSPFv3NBRADDRESSTYPE}}, {4, {1, 9, 1, OSPFv3NBRADDRESS}}, {4, {1, 9, 1, OSPFv3NBRSTATE}}}; static struct trap_object ospf6IfTrapList[] = { {-3, {1, 1, OSPFv3ROUTERID}}, {4, {1, 7, 1, OSPFv3IFSTATE}}, {4, {1, 7, 1, OSPFv3IFADMINSTATUS}}, {4, {1, 7, 1, OSPFv3IFAREAID}}}; static int ospf6TrapNbrStateChange(struct ospf6_neighbor *on, int next_state, int prev_state) { oid index[3]; /* Terminal state or regression */ if ((next_state != OSPF6_NEIGHBOR_FULL) && (next_state != OSPF6_NEIGHBOR_TWOWAY) && (next_state >= prev_state)) return 0; index[0] = on->ospf6_if->interface->ifindex; index[1] = on->ospf6_if->instance_id; index[2] = ntohl(on->router_id); smux_trap(ospfv3_variables, array_size(ospfv3_variables), ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid, sizeof(ospfv3_oid) / sizeof(oid), index, 3, ospf6NbrTrapList, array_size(ospf6NbrTrapList), NBRSTATECHANGE); return 0; } static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state, int prev_state) { oid index[2]; /* Terminal state or regression */ if ((next_state != OSPF6_INTERFACE_POINTTOPOINT) && (next_state != OSPF6_INTERFACE_POINTTOMULTIPOINT) && (next_state != OSPF6_INTERFACE_DROTHER) && (next_state != OSPF6_INTERFACE_BDR) && (next_state != OSPF6_INTERFACE_DR) && (next_state >= prev_state)) return 0; index[0] = oi->interface->ifindex; index[1] = oi->instance_id; smux_trap(ospfv3_variables, array_size(ospfv3_variables), ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid, sizeof(ospfv3_oid) / sizeof(oid), index, 2, ospf6IfTrapList, array_size(ospf6IfTrapList), IFSTATECHANGE); return 0; } /* Register OSPFv3-MIB. */ static int ospf6_snmp_init(struct event_loop *master) { smux_init(master); REGISTER_MIB("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid); return 0; } static int ospf6_snmp_module_init(void) { hook_register(ospf6_interface_change, ospf6TrapIfStateChange); hook_register(ospf6_neighbor_change, ospf6TrapNbrStateChange); hook_register(frr_late_init, ospf6_snmp_init); return 0; } FRR_MODULE_SETUP(.name = "ospf6d_snmp", .version = FRR_VERSION, .description = "ospf6d AgentX SNMP module", .init = ospf6_snmp_module_init, );