blob: 5ac7846d2247701033f8637d6af0bc98abbb0668 [file] [log] [blame]
/* OSPFv3 SNMP support
* Copyright (C) 2004 Yasuhiro Ohara
*
* 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 GNU Zebra; see the file COPYING. If not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <zebra.h>
#ifdef HAVE_SNMP
#ifdef HAVE_NETSNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#else
#include <asn1.h>
#include <snmp.h>
#include <snmp_impl.h>
#endif
#include "log.h"
#include "vty.h"
#include "linklist.h"
#include "smux.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 "ospf6d.h"
#include "ospf6_snmp.h"
/* OSPFv3-MIB */
#define OSPFv3MIB 1,3,6,1,3,102
/* 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 OSPFv3MULTICASTEXTENSIONS 12
#define OSPFv3EXITOVERFLOWINTERVAL 13
#define OSPFv3DEMANDEXTENSIONS 14
#define OSPFv3TRAFFICENGINEERINGSUPPORT 15
#define OSPFv3REFERENCEBANDWIDTH 16
#define OSPFv3RESTARTSUPPORT 17
#define OSPFv3RESTARTINTERVAL 18
#define OSPFv3RESTARTSTATUS 19
#define OSPFv3RESTARTAGE 20
#define OSPFv3RESTARTEXITREASON 21
/* OSPFv3 MIB Area Table values. */
#define OSPFv3AREAID 1
#define OSPFv3IMPORTASEXTERN 2
#define OSPFv3AREASPFRUNS 3
#define OSPFv3AREABDRRTRCOUNT 4
#define OSPFv3AREAASBDRRTRCOUNT 5
#define OSPFv3AREASCOPELSACOUNT 6
#define OSPFv3AREASCOPELSACKSUMSUM 7
#define OSPFv3AREASUMMARY 8
#define OSPFv3AREASTATUS 9
#define OSPFv3STUBMETRIC 10
#define OSPFv3AREANSSATRANSLATORROLE 11
#define OSPFv3AREANSSATRANSLATORSTATE 12
#define OSPFv3AREANSSATRANSLATORSTABILITYINTERVAL 13
#define OSPFv3AREANSSATRANSLATOREVENTS 14
#define OSPFv3AREASTUBMETRICTYPE 15
/* OSPFv3 MIB Area Lsdb Table values. */
#define OSPFv3AREALSDBAREAID 1
#define OSPFv3AREALSDBTYPE 2
#define OSPFv3AREALSDBROUTERID 3
#define OSPFv3AREALSDBLSID 4
#define OSPFv3AREALSDBSEQUENCE 5
#define OSPFv3AREALSDBAGE 6
#define OSPFv3AREALSDBCHECKSUM 7
#define OSPFv3AREALSDBADVERTISEMENT 8
#define OSPFv3AREALSDBTYPEKNOWN 9
/* 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 TIMETICKS ASN_TIMETICKS
#define IPADDRESS ASN_IPADDRESS
#define STRING ASN_OCTET_STR
/* For return values e.g. SNMP_INTEGER macro */
SNMP_LOCAL_VARIABLES
static struct in_addr tmp;
#define INT32_INADDR(x) \
(tmp.s_addr = (x), tmp)
/* OSPFv3-MIB instances. */
oid ospfv3_oid [] = { OSPFv3MIB };
/* empty ID 0.0.0.0 e.g. empty router-id */
static struct in_addr ospf6_empty_id = {0};
/* Hook functions. */
static u_char *ospfv3GeneralGroup (struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
static u_char *ospfv3AreaEntry (struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
static u_char *ospfv3AreaLsdbEntry (struct variable *, oid *, size_t *,
int, size_t *, WriteMethod **);
struct variable ospfv3_variables[] =
{
/* OSPF general variables */
{OSPFv3ROUTERID, IPADDRESS, 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, INTEGER, 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}},
{OSPFv3MULTICASTEXTENSIONS, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 12}},
{OSPFv3EXITOVERFLOWINTERVAL, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 13}},
{OSPFv3DEMANDEXTENSIONS, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 14}},
{OSPFv3TRAFFICENGINEERINGSUPPORT, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 15}},
{OSPFv3REFERENCEBANDWIDTH, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 16}},
{OSPFv3RESTARTSUPPORT, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 17}},
{OSPFv3RESTARTINTERVAL, INTEGER, RWRITE, ospfv3GeneralGroup,
3, {1, 1, 18}},
{OSPFv3RESTARTSTATUS, INTEGER, RONLY, ospfv3GeneralGroup,
3, {1, 1, 19}},
{OSPFv3RESTARTAGE, INTEGER, RONLY, ospfv3GeneralGroup,
3, {1, 1, 20}},
{OSPFv3RESTARTEXITREASON, INTEGER, RONLY, ospfv3GeneralGroup,
3, {1, 1, 21}},
/* OSPFv3 Area Data Structure */
{OSPFv3AREAID, IPADDRESS, RONLY, ospfv3AreaEntry,
4, {1, 2, 1, 1}},
{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, INTEGER, RONLY, ospfv3AreaEntry,
4, {1, 2, 1, 7}},
{OSPFv3AREASUMMARY, INTEGER, RWRITE, ospfv3AreaEntry,
4, {1, 2, 1, 8}},
{OSPFv3AREASTATUS, INTEGER, RWRITE, ospfv3AreaEntry,
4, {1, 2, 1, 9}},
{OSPFv3STUBMETRIC, 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}},
{OSPFv3AREANSSATRANSLATORSTABILITYINTERVAL, INTEGER, 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}},
{OSPFv3AREALSDBAREAID, IPADDRESS, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 1}},
{OSPFv3AREALSDBTYPE, GAUGE, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 2}},
{OSPFv3AREALSDBROUTERID, IPADDRESS, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 3}},
{OSPFv3AREALSDBLSID, IPADDRESS, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 4}},
{OSPFv3AREALSDBSEQUENCE, INTEGER, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 5}},
{OSPFv3AREALSDBAGE, INTEGER, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 6}},
{OSPFv3AREALSDBCHECKSUM, INTEGER, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 7}},
{OSPFv3AREALSDBADVERTISEMENT, STRING, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 8}},
{OSPFv3AREALSDBTYPEKNOWN, INTEGER, RONLY, ospfv3AreaLsdbEntry,
4, {1, 4, 1, 9}},
};
static u_char *
ospfv3GeneralGroup (struct variable *v, oid *name, size_t *length,
int exact, size_t *var_len, WriteMethod **write_method)
{
/* 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: /* 1*/
/* Router-ID of this OSPF instance. */
if (ospf6)
return SNMP_IPADDRESS (INT32_INADDR (ospf6->router_id));
else
return SNMP_IPADDRESS (ospf6_empty_id);
break;
case OSPFv3ADMINSTAT: /* 2*/
break;
case OSPFv3VERSIONNUMBER: /* 3*/
break;
case OSPFv3AREABDRRTRSTATUS: /* 4*/
break;
case OSPFv3ASBDRRTRSTATUS: /* 5*/
break;
case OSPFv3ASSCOPELSACOUNT: /* 6*/
break;
case OSPFv3ASSCOPELSACHECKSUMSUM: /* 7*/
break;
case OSPFv3ORIGINATENEWLSAS: /* 8*/
break;
case OSPFv3RXNEWLSAS: /* 9*/
break;
case OSPFv3EXTLSACOUNT: /*10*/
break;
case OSPFv3EXTAREALSDBLIMIT: /*11*/
break;
case OSPFv3MULTICASTEXTENSIONS: /*12*/
break;
case OSPFv3EXITOVERFLOWINTERVAL: /*13*/
break;
case OSPFv3DEMANDEXTENSIONS: /*14*/
break;
case OSPFv3TRAFFICENGINEERINGSUPPORT: /*15*/
break;
case OSPFv3REFERENCEBANDWIDTH: /*16*/
break;
case OSPFv3RESTARTSUPPORT: /*17*/
break;
case OSPFv3RESTARTINTERVAL: /*18*/
break;
case OSPFv3RESTARTSTATUS: /*19*/
break;
case OSPFv3RESTARTAGE: /*20*/
break;
case OSPFv3RESTARTEXITREASON: /*21*/
break;
default:
return NULL;
}
return NULL;
}
static u_char *
ospfv3AreaEntry (struct variable *v, oid *name, size_t *length,
int exact, size_t *var_len, WriteMethod **write_method)
{
struct ospf6_area *oa, *area = NULL;
u_int32_t area_id = 0;
struct listnode *node;
unsigned int len;
if (ospf6 == NULL)
return NULL;
len = *length - v->namelen;
len = (len >= sizeof (u_int32_t) ? sizeof (u_int32_t) : 0);
if (exact && len != sizeof (u_int32_t))
return NULL;
if (len)
oid2in_addr (name + v->namelen, len, (struct in_addr *) &area_id);
zlog_debug ("SNMP access by area: %s, exact=%d len=%d length=%lu",
inet_ntoa (* (struct in_addr *) &area_id),
exact, len, (u_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 + sizeof (u_int32_t);
oid_copy_addr (name + v->namelen, (struct in_addr *) &area->area_id,
sizeof (u_int32_t));
zlog_debug ("SNMP found area: %s, exact=%d len=%d length=%lu",
inet_ntoa (* (struct in_addr *) &area->area_id),
exact, len, (u_long)*length);
switch (v->magic)
{
case OSPFv3AREAID: /* 1*/
return SNMP_IPADDRESS (INT32_INADDR (area->area_id));
break;
case OSPFv3IMPORTASEXTERN: /* 2*/
return SNMP_INTEGER (ospf6->external_table->count);
break;
default:
return NULL;
break;
}
return NULL;
}
static u_char *
ospfv3AreaLsdbEntry (struct variable *v, oid *name, size_t *length,
int exact, size_t *var_len, WriteMethod **write_method)
{
struct ospf6_lsa *lsa = NULL;
struct in_addr area_id;
u_int16_t type;
struct in_addr id;
struct in_addr adv_router;
int len;
oid *offset;
int offsetlen;
char a[16], b[16], c[16];
struct ospf6_area *oa;
struct listnode *node;
memset (&area_id, 0, sizeof (struct in_addr));
type = 0;
memset (&id, 0, sizeof (struct in_addr));
memset (&adv_router, 0, sizeof (struct in_addr));
/* Check OSPFv3 instance. */
if (ospf6 == NULL)
return NULL;
/* Get variable length. */
offset = name + v->namelen;
offsetlen = *length - v->namelen;
#define OSPFV3_AREA_LSDB_ENTRY_EXACT_OFFSET \
(IN_ADDR_SIZE + 1 + IN_ADDR_SIZE + IN_ADDR_SIZE)
if (exact && offsetlen != OSPFV3_AREA_LSDB_ENTRY_EXACT_OFFSET)
return NULL;
/* Parse area-id */
len = (offsetlen < IN_ADDR_SIZE ? offsetlen : IN_ADDR_SIZE);
if (len)
oid2in_addr (offset, len, &area_id);
offset += len;
offsetlen -= len;
/* Parse type */
len = (offsetlen < 1 ? offsetlen : 1);
if (len)
type = htons (*offset);
offset += len;
offsetlen -= len;
/* Parse Router-ID */
len = (offsetlen < IN_ADDR_SIZE ? offsetlen : IN_ADDR_SIZE);
if (len)
oid2in_addr (offset, len, &adv_router);
offset += len;
offsetlen -= len;
/* Parse LS-ID */
len = (offsetlen < IN_ADDR_SIZE ? offsetlen : IN_ADDR_SIZE);
if (len)
oid2in_addr (offset, len, &id);
offset += len;
offsetlen -= len;
inet_ntop (AF_INET, &area_id, a, sizeof (a));
inet_ntop (AF_INET, &adv_router, b, sizeof (b));
inet_ntop (AF_INET, &id, c, sizeof (c));
zlog_debug ("SNMP access by lsdb: area=%s exact=%d length=%lu magic=%d"
" type=%#x adv_router=%s id=%s",
a, exact, (u_long)*length, v->magic, ntohs (type), b, c);
if (exact)
{
oa = ospf6_area_lookup (area_id.s_addr, ospf6);
lsa = ospf6_lsdb_lookup (type, id.s_addr, adv_router.s_addr, oa->lsdb);
}
else
{
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
{
if (lsa)
continue;
if (ntohl (oa->area_id) < ntohl (area_id.s_addr))
continue;
lsa = ospf6_lsdb_lookup_next (type, id.s_addr, adv_router.s_addr,
oa->lsdb);
if (! lsa)
{
type = 0;
memset (&id, 0, sizeof (struct in_addr));
memset (&adv_router, 0, sizeof (struct in_addr));
}
}
}
if (! lsa)
{
zlog_debug ("SNMP respond: No LSA to return");
return NULL;
}
oa = OSPF6_AREA (lsa->lsdb->data);
zlog_debug ("SNMP respond: area: %s lsa: %s", oa->name, lsa->name);
/* Add Index (AreaId, Type, RouterId, Lsid) */
*length = v->namelen + OSPFV3_AREA_LSDB_ENTRY_EXACT_OFFSET;
offset = name + v->namelen;
oid_copy_addr (offset, (struct in_addr *) &oa->area_id, IN_ADDR_SIZE);
offset += IN_ADDR_SIZE;
*offset = ntohs (lsa->header->type);
offset++;
oid_copy_addr (offset, (struct in_addr *) &lsa->header->adv_router,
IN_ADDR_SIZE);
offset += IN_ADDR_SIZE;
oid_copy_addr (offset, (struct in_addr *) &lsa->header->id, IN_ADDR_SIZE);
offset += IN_ADDR_SIZE;
/* Return the current value of the variable */
switch (v->magic)
{
case OSPFv3AREALSDBAREAID: /* 1 */
area_id.s_addr = OSPF6_AREA (lsa->lsdb->data)->area_id;
return SNMP_IPADDRESS (area_id);
break;
case OSPFv3AREALSDBTYPE: /* 2 */
return SNMP_INTEGER (ntohs (lsa->header->type));
break;
case OSPFv3AREALSDBROUTERID: /* 3 */
adv_router.s_addr = lsa->header->adv_router;
return SNMP_IPADDRESS (adv_router);
break;
case OSPFv3AREALSDBLSID: /* 4 */
id.s_addr = lsa->header->id;
return SNMP_IPADDRESS (id);
break;
case OSPFv3AREALSDBSEQUENCE: /* 5 */
return SNMP_INTEGER (lsa->header->seqnum);
break;
case OSPFv3AREALSDBAGE: /* 6 */
ospf6_lsa_age_current (lsa);
return SNMP_INTEGER (lsa->header->age);
break;
case OSPFv3AREALSDBCHECKSUM: /* 7 */
return SNMP_INTEGER (lsa->header->checksum);
break;
case OSPFv3AREALSDBADVERTISEMENT: /* 8 */
*var_len = ntohs (lsa->header->length);
return (u_char *) lsa->header;
break;
case OSPFv3AREALSDBTYPEKNOWN: /* 9 */
return SNMP_INTEGER (OSPF6_LSA_IS_KNOWN (lsa->header->type) ?
SNMP_TRUE : SNMP_FALSE);
break;
default:
return NULL;
break;
}
return NULL;
}
/* Register OSPFv3-MIB. */
void
ospf6_snmp_init (struct thread_master *master)
{
smux_init (master);
REGISTER_MIB ("OSPFv3MIB", ospfv3_variables, variable, ospfv3_oid);
}
#endif /* HAVE_SNMP */