123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- /* RIP SNMP support
- * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
- *
- * 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
- #include <net-snmp/net-snmp-config.h>
- #include <net-snmp/net-snmp-includes.h>
- #include "if.h"
- #include "log.h"
- #include "prefix.h"
- #include "command.h"
- #include "table.h"
- #include "smux.h"
- #include "ripd/ripd.h"
- /* RIPv2-MIB. */
- #define RIPV2MIB 1,3,6,1,2,1,23
- /* RIPv2-MIB rip2Globals values. */
- #define RIP2GLOBALROUTECHANGES 1
- #define RIP2GLOBALQUERIES 2
- /* RIPv2-MIB rip2IfStatEntry. */
- #define RIP2IFSTATENTRY 1
- /* RIPv2-MIB rip2IfStatTable. */
- #define RIP2IFSTATADDRESS 1
- #define RIP2IFSTATRCVBADPACKETS 2
- #define RIP2IFSTATRCVBADROUTES 3
- #define RIP2IFSTATSENTUPDATES 4
- #define RIP2IFSTATSTATUS 5
- /* RIPv2-MIB rip2IfConfTable. */
- #define RIP2IFCONFADDRESS 1
- #define RIP2IFCONFDOMAIN 2
- #define RIP2IFCONFAUTHTYPE 3
- #define RIP2IFCONFAUTHKEY 4
- #define RIP2IFCONFSEND 5
- #define RIP2IFCONFRECEIVE 6
- #define RIP2IFCONFDEFAULTMETRIC 7
- #define RIP2IFCONFSTATUS 8
- #define RIP2IFCONFSRCADDRESS 9
- /* RIPv2-MIB rip2PeerTable. */
- #define RIP2PEERADDRESS 1
- #define RIP2PEERDOMAIN 2
- #define RIP2PEERLASTUPDATE 3
- #define RIP2PEERVERSION 4
- #define RIP2PEERRCVBADPACKETS 5
- #define RIP2PEERRCVBADROUTES 6
- /* SNMP value hack. */
- #define COUNTER ASN_COUNTER
- #define INTEGER ASN_INTEGER
- #define TIMETICKS ASN_TIMETICKS
- #define IPADDRESS ASN_IPADDRESS
- #define STRING ASN_OCTET_STR
- /* Define SNMP local variables. */
- SNMP_LOCAL_VARIABLES
- /* RIP-MIB instances. */
- oid rip_oid [] = { RIPV2MIB };
- /* Interface cache table sorted by interface's address. */
- struct route_table *rip_ifaddr_table;
- /* Hook functions. */
- static u_char *rip2Globals (struct variable *, oid [], size_t *,
- int, size_t *, WriteMethod **);
- static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
- int, size_t *, WriteMethod **);
- static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
- int, size_t *, WriteMethod **);
- static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
- int, size_t *, WriteMethod **);
- struct variable rip_variables[] =
- {
- /* RIP Global Counters. */
- {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
- 2, {1, 1}},
- {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
- 2, {1, 2}},
- /* RIP Interface Tables. */
- {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
- 3, {2, 1, 1}},
- {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
- 3, {2, 1, 2}},
- {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
- 3, {2, 1, 3}},
- {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
- 3, {2, 1, 4}},
- {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
- 3, {2, 1, 5}},
- {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
- /* RIP Interface Configuration Table. */
- 3, {3, 1, 1}},
- {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
- 3, {3, 1, 2}},
- {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
- 3, {3, 1, 3}},
- {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
- 3, {3, 1, 4}},
- {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
- 3, {3, 1, 5}},
- {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
- 3, {3, 1, 6}},
- {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
- 3, {3, 1, 7}},
- {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
- 3, {3, 1, 8}},
- {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
- 3, {3, 1, 9}},
- {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
- /* RIP Peer Table. */
- 3, {4, 1, 1}},
- {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
- 3, {4, 1, 2}},
- {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
- 3, {4, 1, 3}},
- {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
- 3, {4, 1, 4}},
- {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
- 3, {4, 1, 5}},
- {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
- 3, {4, 1, 6}}
- };
- extern struct thread_master *master;
- static u_char *
- rip2Globals (struct variable *v, oid name[], size_t *length,
- int exact, size_t *var_len, WriteMethod **write_method)
- {
- if (smux_header_generic(v, name, length, exact, var_len, write_method)
- == MATCH_FAILED)
- return NULL;
- /* Retrun global counter. */
- switch (v->magic)
- {
- case RIP2GLOBALROUTECHANGES:
- return SNMP_INTEGER (rip_global_route_changes);
- break;
- case RIP2GLOBALQUERIES:
- return SNMP_INTEGER (rip_global_queries);
- break;
- default:
- return NULL;
- break;
- }
- return NULL;
- }
- void
- rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
- {
- struct prefix *p;
- struct route_node *rn;
- p = ifc->address;
- if (p->family != AF_INET)
- return;
- rn = route_node_get (rip_ifaddr_table, p);
- rn->info = ifp;
- }
- void
- rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
- {
- struct prefix *p;
- struct route_node *rn;
- struct interface *i;
- p = ifc->address;
- if (p->family != AF_INET)
- return;
- rn = route_node_lookup (rip_ifaddr_table, p);
- if (! rn)
- return;
- i = rn->info;
- if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
- {
- rn->info = NULL;
- route_unlock_node (rn);
- route_unlock_node (rn);
- }
- }
- static struct interface *
- rip_ifaddr_lookup_next (struct in_addr *addr)
- {
- struct prefix_ipv4 p;
- struct route_node *rn;
- struct interface *ifp;
- p.family = AF_INET;
- p.prefixlen = IPV4_MAX_BITLEN;
- p.prefix = *addr;
- rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
- for (rn = route_next (rn); rn; rn = route_next (rn))
- if (rn->info)
- break;
- if (rn && rn->info)
- {
- ifp = rn->info;
- *addr = rn->p.u.prefix4;
- route_unlock_node (rn);
- return ifp;
- }
- return NULL;
- }
- static struct interface *
- rip2IfLookup (struct variable *v, oid name[], size_t *length,
- struct in_addr *addr, int exact)
- {
- int len;
- struct interface *ifp;
-
- if (exact)
- {
- /* Check the length. */
- if (*length - v->namelen != sizeof (struct in_addr))
- return NULL;
- oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
- return if_lookup_exact_address (*addr);
- }
- else
- {
- len = *length - v->namelen;
- if (len > 4) len = 4;
- oid2in_addr (name + v->namelen, len, addr);
- ifp = rip_ifaddr_lookup_next (addr);
- if (ifp == NULL)
- return NULL;
- oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
- *length = v->namelen + sizeof (struct in_addr);
- return ifp;
- }
- return NULL;
- }
- static struct rip_peer *
- rip2PeerLookup (struct variable *v, oid name[], size_t *length,
- struct in_addr *addr, int exact)
- {
- int len;
- struct rip_peer *peer;
-
- if (exact)
- {
- /* Check the length. */
- if (*length - v->namelen != sizeof (struct in_addr) + 1)
- return NULL;
- oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
- peer = rip_peer_lookup (addr);
- if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)])
- return peer;
- return NULL;
- }
- else
- {
- len = *length - v->namelen;
- if (len > 4) len = 4;
- oid2in_addr (name + v->namelen, len, addr);
- len = *length - v->namelen;
- peer = rip_peer_lookup (addr);
- if (peer)
- {
- if ((len < (int)sizeof (struct in_addr) + 1) ||
- (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)]))
- {
- oid_copy_addr (name + v->namelen, &peer->addr,
- sizeof (struct in_addr));
- name[v->namelen + sizeof (struct in_addr)] = peer->domain;
- *length = sizeof (struct in_addr) + v->namelen + 1;
- return peer;
- }
- }
- peer = rip_peer_lookup_next (addr);
- if (! peer)
- return NULL;
- oid_copy_addr (name + v->namelen, &peer->addr,
- sizeof (struct in_addr));
- name[v->namelen + sizeof (struct in_addr)] = peer->domain;
- *length = sizeof (struct in_addr) + v->namelen + 1;
- return peer;
- }
- return NULL;
- }
- static u_char *
- rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
- int exact, size_t *var_len, WriteMethod **write_method)
- {
- struct interface *ifp;
- struct rip_interface *ri;
- static struct in_addr addr;
- static long valid = SNMP_VALID;
- if (smux_header_table(v, name, length, exact, var_len, write_method)
- == MATCH_FAILED)
- return NULL;
- memset (&addr, 0, sizeof (struct in_addr));
-
- /* Lookup interface. */
- ifp = rip2IfLookup (v, name, length, &addr, exact);
- if (! ifp)
- return NULL;
- /* Fetch rip_interface information. */
- ri = ifp->info;
- switch (v->magic)
- {
- case RIP2IFSTATADDRESS:
- return SNMP_IPADDRESS (addr);
- break;
- case RIP2IFSTATRCVBADPACKETS:
- *var_len = sizeof (long);
- return (u_char *) &ri->recv_badpackets;
- case RIP2IFSTATRCVBADROUTES:
- *var_len = sizeof (long);
- return (u_char *) &ri->recv_badroutes;
- case RIP2IFSTATSENTUPDATES:
- *var_len = sizeof (long);
- return (u_char *) &ri->sent_updates;
- case RIP2IFSTATSTATUS:
- *var_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *) &valid;
- default:
- return NULL;
- }
- return NULL;
- }
- static long
- rip2IfConfSend (struct rip_interface *ri)
- {
- #define doNotSend 1
- #define ripVersion1 2
- #define rip1Compatible 3
- #define ripVersion2 4
- #define ripV1Demand 5
- #define ripV2Demand 6
- if (! ri->running)
- return doNotSend;
-
- if (ri->ri_send & RIPv2)
- return ripVersion2;
- else if (ri->ri_send & RIPv1)
- return ripVersion1;
- else if (rip)
- {
- if (rip->version_send == RIPv2)
- return ripVersion2;
- else if (rip->version_send == RIPv1)
- return ripVersion1;
- }
- return doNotSend;
- }
- static long
- rip2IfConfReceive (struct rip_interface *ri)
- {
- #define rip1 1
- #define rip2 2
- #define rip1OrRip2 3
- #define doNotReceive 4
- int recvv;
- if (! ri->running)
- return doNotReceive;
- recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
- ri->ri_receive;
- if (recvv == RI_RIP_VERSION_1_AND_2)
- return rip1OrRip2;
- else if (recvv & RIPv2)
- return rip2;
- else if (recvv & RIPv1)
- return rip1;
- else
- return doNotReceive;
- }
- static u_char *
- rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
- int exact, size_t *val_len, WriteMethod **write_method)
- {
- static struct in_addr addr;
- static long valid = SNMP_INVALID;
- static long domain = 0;
- static long config = 0;
- static u_int auth = 0;
- struct interface *ifp;
- struct rip_interface *ri;
- if (smux_header_table(v, name, length, exact, val_len, write_method)
- == MATCH_FAILED)
- return NULL;
- memset (&addr, 0, sizeof (struct in_addr));
-
- /* Lookup interface. */
- ifp = rip2IfLookup (v, name, length, &addr, exact);
- if (! ifp)
- return NULL;
- /* Fetch rip_interface information. */
- ri = ifp->info;
- switch (v->magic)
- {
- case RIP2IFCONFADDRESS:
- *val_len = sizeof (struct in_addr);
- return (u_char *) &addr;
- case RIP2IFCONFDOMAIN:
- *val_len = 2;
- return (u_char *) &domain;
- case RIP2IFCONFAUTHTYPE:
- auth = ri->auth_type;
- *val_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *)&auth;
- case RIP2IFCONFAUTHKEY:
- *val_len = 0;
- return (u_char *) &domain;
- case RIP2IFCONFSEND:
- config = rip2IfConfSend (ri);
- *val_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *) &config;
- case RIP2IFCONFRECEIVE:
- config = rip2IfConfReceive (ri);
- *val_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *) &config;
- case RIP2IFCONFDEFAULTMETRIC:
- *val_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *) &ifp->metric;
- case RIP2IFCONFSTATUS:
- *val_len = sizeof (long);
- v->type = ASN_INTEGER;
- return (u_char *) &valid;
- case RIP2IFCONFSRCADDRESS:
- *val_len = sizeof (struct in_addr);
- return (u_char *) &addr;
- default:
- return NULL;
- }
- return NULL;
- }
- static u_char *
- rip2PeerTable (struct variable *v, oid name[], size_t *length,
- int exact, size_t *val_len, WriteMethod **write_method)
- {
- static struct in_addr addr;
- static int domain = 0;
- static int version;
- /* static time_t uptime; */
- struct rip_peer *peer;
- if (smux_header_table(v, name, length, exact, val_len, write_method)
- == MATCH_FAILED)
- return NULL;
- memset (&addr, 0, sizeof (struct in_addr));
-
- /* Lookup interface. */
- peer = rip2PeerLookup (v, name, length, &addr, exact);
- if (! peer)
- return NULL;
- switch (v->magic)
- {
- case RIP2PEERADDRESS:
- *val_len = sizeof (struct in_addr);
- return (u_char *) &peer->addr;
- case RIP2PEERDOMAIN:
- *val_len = 2;
- return (u_char *) &domain;
- case RIP2PEERLASTUPDATE:
- #if 0
- /* We don't know the SNMP agent startup time. We have two choices here:
- * - assume ripd startup time equals SNMP agent startup time
- * - don't support this variable, at all
- * Currently, we do the latter...
- */
- *val_len = sizeof (time_t);
- uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
- return (u_char *) &uptime;
- #else
- return (u_char *) NULL;
- #endif
- case RIP2PEERVERSION:
- *val_len = sizeof (int);
- version = peer->version;
- return (u_char *) &version;
- case RIP2PEERRCVBADPACKETS:
- *val_len = sizeof (int);
- return (u_char *) &peer->recv_badpackets;
- case RIP2PEERRCVBADROUTES:
- *val_len = sizeof (int);
- return (u_char *) &peer->recv_badroutes;
- default:
- return NULL;
- }
- return NULL;
- }
- /* Register RIPv2-MIB. */
- void
- rip_snmp_init ()
- {
- rip_ifaddr_table = route_table_init ();
- smux_init (master);
- REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
- }
- #endif /* HAVE_SNMP */
|