File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / ripd / rip_snmp.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    1: /* RIP SNMP support
    2:  * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
    3:  *
    4:  * This file is part of GNU Zebra.
    5:  *
    6:  * GNU Zebra is free software; you can redistribute it and/or modify it
    7:  * under the terms of the GNU General Public License as published by the
    8:  * Free Software Foundation; either version 2, or (at your option) any
    9:  * later version.
   10:  *
   11:  * GNU Zebra is distributed in the hope that it will be useful, but
   12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
   13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:  * General Public License for more details.
   15:  *
   16:  * You should have received a copy of the GNU General Public License
   17:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
   18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   19:  * 02111-1307, USA.  
   20:  */
   21: 
   22: #include <zebra.h>
   23: 
   24: #ifdef HAVE_SNMP
   25: #include <net-snmp/net-snmp-config.h>
   26: #include <net-snmp/net-snmp-includes.h>
   27: 
   28: #include "if.h"
   29: #include "log.h"
   30: #include "prefix.h"
   31: #include "command.h"
   32: #include "table.h"
   33: #include "smux.h"
   34: 
   35: #include "ripd/ripd.h"
   36: 
   37: /* RIPv2-MIB. */
   38: #define RIPV2MIB 1,3,6,1,2,1,23
   39: 
   40: /* RIPv2-MIB rip2Globals values. */
   41: #define RIP2GLOBALROUTECHANGES  1
   42: #define RIP2GLOBALQUERIES       2
   43: 
   44: /* RIPv2-MIB rip2IfStatEntry. */
   45: #define RIP2IFSTATENTRY         1
   46: 
   47: /* RIPv2-MIB rip2IfStatTable. */
   48: #define RIP2IFSTATADDRESS       1
   49: #define RIP2IFSTATRCVBADPACKETS 2
   50: #define RIP2IFSTATRCVBADROUTES  3
   51: #define RIP2IFSTATSENTUPDATES   4
   52: #define RIP2IFSTATSTATUS        5
   53: 
   54: /* RIPv2-MIB rip2IfConfTable. */
   55: #define RIP2IFCONFADDRESS       1
   56: #define RIP2IFCONFDOMAIN        2
   57: #define RIP2IFCONFAUTHTYPE      3
   58: #define RIP2IFCONFAUTHKEY       4
   59: #define RIP2IFCONFSEND          5
   60: #define RIP2IFCONFRECEIVE       6
   61: #define RIP2IFCONFDEFAULTMETRIC 7
   62: #define RIP2IFCONFSTATUS        8
   63: #define RIP2IFCONFSRCADDRESS    9
   64: 
   65: /* RIPv2-MIB rip2PeerTable. */
   66: #define RIP2PEERADDRESS         1
   67: #define RIP2PEERDOMAIN          2
   68: #define RIP2PEERLASTUPDATE      3
   69: #define RIP2PEERVERSION         4
   70: #define RIP2PEERRCVBADPACKETS   5
   71: #define RIP2PEERRCVBADROUTES    6
   72: 
   73: /* SNMP value hack. */
   74: #define COUNTER     ASN_COUNTER
   75: #define INTEGER     ASN_INTEGER
   76: #define TIMETICKS   ASN_TIMETICKS
   77: #define IPADDRESS   ASN_IPADDRESS
   78: #define STRING      ASN_OCTET_STR
   79: 
   80: /* Define SNMP local variables. */
   81: SNMP_LOCAL_VARIABLES
   82: 
   83: /* RIP-MIB instances. */
   84: oid rip_oid [] = { RIPV2MIB };
   85: 
   86: /* Interface cache table sorted by interface's address. */
   87: struct route_table *rip_ifaddr_table;
   88: 
   89: /* Hook functions. */
   90: static u_char *rip2Globals (struct variable *, oid [], size_t *,
   91: 			    int, size_t *, WriteMethod **);
   92: static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
   93: 				int, size_t *, WriteMethod **);
   94: static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
   95: 				  int, size_t *, WriteMethod **);
   96: static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
   97: 			      int, size_t *, WriteMethod **);
   98: 
   99: struct variable rip_variables[] = 
  100: {
  101:   /* RIP Global Counters. */
  102:   {RIP2GLOBALROUTECHANGES,    COUNTER, RONLY, rip2Globals,
  103:    2, {1, 1}},
  104:   {RIP2GLOBALQUERIES,         COUNTER, RONLY, rip2Globals,
  105:    2, {1, 2}},
  106:   /* RIP Interface Tables. */
  107:   {RIP2IFSTATADDRESS,         IPADDRESS, RONLY, rip2IfStatEntry,
  108:    3, {2, 1, 1}},
  109:   {RIP2IFSTATRCVBADPACKETS,   COUNTER, RONLY, rip2IfStatEntry,
  110:    3, {2, 1, 2}},
  111:   {RIP2IFSTATRCVBADROUTES,    COUNTER, RONLY, rip2IfStatEntry,
  112:    3, {2, 1, 3}},
  113:   {RIP2IFSTATSENTUPDATES,     COUNTER, RONLY, rip2IfStatEntry,
  114:    3, {2, 1, 4}},
  115:   {RIP2IFSTATSTATUS,          COUNTER, RWRITE, rip2IfStatEntry,
  116:    3, {2, 1, 5}},
  117:   {RIP2IFCONFADDRESS,         IPADDRESS, RONLY, rip2IfConfAddress,
  118:    /* RIP Interface Configuration Table. */
  119:    3, {3, 1, 1}},
  120:   {RIP2IFCONFDOMAIN,          STRING, RONLY, rip2IfConfAddress,
  121:    3, {3, 1, 2}},
  122:   {RIP2IFCONFAUTHTYPE,        COUNTER, RONLY, rip2IfConfAddress,
  123:    3, {3, 1, 3}},
  124:   {RIP2IFCONFAUTHKEY,         STRING, RONLY, rip2IfConfAddress,
  125:    3, {3, 1, 4}},
  126:   {RIP2IFCONFSEND,            COUNTER, RONLY, rip2IfConfAddress,
  127:    3, {3, 1, 5}},
  128:   {RIP2IFCONFRECEIVE,         COUNTER, RONLY, rip2IfConfAddress,
  129:    3, {3, 1, 6}},
  130:   {RIP2IFCONFDEFAULTMETRIC,   COUNTER, RONLY, rip2IfConfAddress,
  131:    3, {3, 1, 7}},
  132:   {RIP2IFCONFSTATUS,          COUNTER, RONLY, rip2IfConfAddress,
  133:    3, {3, 1, 8}},
  134:   {RIP2IFCONFSRCADDRESS,      IPADDRESS, RONLY, rip2IfConfAddress,
  135:    3, {3, 1, 9}},
  136:   {RIP2PEERADDRESS,           IPADDRESS, RONLY, rip2PeerTable,
  137:    /* RIP Peer Table. */
  138:    3, {4, 1, 1}},
  139:   {RIP2PEERDOMAIN,            STRING, RONLY, rip2PeerTable,
  140:    3, {4, 1, 2}},
  141:   {RIP2PEERLASTUPDATE,        TIMETICKS, RONLY, rip2PeerTable,
  142:    3, {4, 1, 3}},
  143:   {RIP2PEERVERSION,           INTEGER, RONLY, rip2PeerTable,
  144:    3, {4, 1, 4}},
  145:   {RIP2PEERRCVBADPACKETS,     COUNTER, RONLY, rip2PeerTable,
  146:    3, {4, 1, 5}},
  147:   {RIP2PEERRCVBADROUTES,      COUNTER, RONLY, rip2PeerTable,
  148:    3, {4, 1, 6}}
  149: };
  150: 
  151: extern struct thread_master *master;
  152: 
  153: static u_char *
  154: rip2Globals (struct variable *v, oid name[], size_t *length,
  155: 	     int exact, size_t *var_len, WriteMethod **write_method)
  156: {
  157:   if (smux_header_generic(v, name, length, exact, var_len, write_method)
  158:       == MATCH_FAILED)
  159:     return NULL;
  160: 
  161:   /* Retrun global counter. */
  162:   switch (v->magic)
  163:     {
  164:     case RIP2GLOBALROUTECHANGES:
  165:       return SNMP_INTEGER (rip_global_route_changes);
  166:       break;
  167:     case RIP2GLOBALQUERIES:
  168:       return SNMP_INTEGER (rip_global_queries);
  169:       break;
  170:     default:
  171:       return NULL;
  172:       break;
  173:     }
  174:   return NULL;
  175: }
  176: 
  177: void
  178: rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
  179: {
  180:   struct prefix *p;
  181:   struct route_node *rn;
  182: 
  183:   p = ifc->address;
  184: 
  185:   if (p->family != AF_INET)
  186:     return;
  187: 
  188:   rn = route_node_get (rip_ifaddr_table, p);
  189:   rn->info = ifp;
  190: }
  191: 
  192: void
  193: rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
  194: {
  195:   struct prefix *p;
  196:   struct route_node *rn;
  197:   struct interface *i;
  198: 
  199:   p = ifc->address;
  200: 
  201:   if (p->family != AF_INET)
  202:     return;
  203: 
  204:   rn = route_node_lookup (rip_ifaddr_table, p);
  205:   if (! rn)
  206:     return;
  207:   i = rn->info;
  208:   if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
  209:     {
  210:       rn->info = NULL;
  211:       route_unlock_node (rn);
  212:       route_unlock_node (rn);
  213:     }
  214: }
  215: 
  216: static struct interface *
  217: rip_ifaddr_lookup_next (struct in_addr *addr)
  218: {
  219:   struct prefix_ipv4 p;
  220:   struct route_node *rn;
  221:   struct interface *ifp;
  222: 
  223:   p.family = AF_INET;
  224:   p.prefixlen = IPV4_MAX_BITLEN;
  225:   p.prefix = *addr;
  226: 
  227:   rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
  228: 
  229:   for (rn = route_next (rn); rn; rn = route_next (rn))
  230:     if (rn->info)
  231:       break;
  232: 
  233:   if (rn && rn->info)
  234:     {
  235:       ifp = rn->info;
  236:       *addr = rn->p.u.prefix4;
  237:       route_unlock_node (rn);
  238:       return ifp;
  239:     }
  240:   return NULL;
  241: }
  242: 
  243: static struct interface *
  244: rip2IfLookup (struct variable *v, oid name[], size_t *length, 
  245: 	      struct in_addr *addr, int exact)
  246: {
  247:   int len;
  248:   struct interface *ifp;
  249:   
  250:   if (exact)
  251:     {
  252:       /* Check the length. */
  253:       if (*length - v->namelen != sizeof (struct in_addr))
  254: 	return NULL;
  255: 
  256:       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  257: 
  258:       return if_lookup_exact_address (*addr);
  259:     }
  260:   else
  261:     {
  262:       len = *length - v->namelen;
  263:       if (len > 4) len = 4;
  264: 
  265:       oid2in_addr (name + v->namelen, len, addr);
  266: 
  267:       ifp = rip_ifaddr_lookup_next (addr);
  268: 
  269:       if (ifp == NULL)
  270: 	return NULL;
  271: 
  272:       oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  273: 
  274:       *length = v->namelen + sizeof (struct in_addr);
  275: 
  276:       return ifp;
  277:     }
  278:   return NULL;
  279: }
  280: 
  281: static struct rip_peer *
  282: rip2PeerLookup (struct variable *v, oid name[], size_t *length, 
  283: 		struct in_addr *addr, int exact)
  284: {
  285:   int len;
  286:   struct rip_peer *peer;
  287:   
  288:   if (exact)
  289:     {
  290:       /* Check the length. */
  291:       if (*length - v->namelen != sizeof (struct in_addr) + 1)
  292: 	return NULL;
  293: 
  294:       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  295: 
  296:       peer = rip_peer_lookup (addr);
  297: 
  298:       if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)])
  299: 	return peer;
  300: 
  301:       return NULL;
  302:     }
  303:   else
  304:     {
  305:       len = *length - v->namelen;
  306:       if (len > 4) len = 4;
  307: 
  308:       oid2in_addr (name + v->namelen, len, addr);
  309: 
  310:       len = *length - v->namelen;
  311:       peer = rip_peer_lookup (addr);
  312:       if (peer)
  313: 	{
  314: 	  if ((len < (int)sizeof (struct in_addr) + 1) ||
  315: 	      (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)]))
  316: 	    {
  317: 	      oid_copy_addr (name + v->namelen, &peer->addr,
  318: 			     sizeof (struct in_addr));
  319: 	      name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  320: 	      *length = sizeof (struct in_addr) + v->namelen + 1;
  321: 	      return peer;
  322: 	    }
  323:         } 
  324:       peer = rip_peer_lookup_next (addr);
  325: 
  326:       if (! peer)
  327: 	return NULL;
  328: 
  329:       oid_copy_addr (name + v->namelen, &peer->addr,
  330: 		     sizeof (struct in_addr));
  331:       name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  332:       *length = sizeof (struct in_addr) + v->namelen + 1;
  333: 
  334:       return peer;
  335:     }
  336:   return NULL;
  337: }
  338: 
  339: static u_char *
  340: rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
  341: 	         int exact, size_t *var_len, WriteMethod **write_method)
  342: {
  343:   struct interface *ifp;
  344:   struct rip_interface *ri;
  345:   static struct in_addr addr;
  346:   static long valid = SNMP_VALID;
  347: 
  348:   if (smux_header_table(v, name, length, exact, var_len, write_method)
  349:       == MATCH_FAILED)
  350:     return NULL;
  351: 
  352:   memset (&addr, 0, sizeof (struct in_addr));
  353:   
  354:   /* Lookup interface. */
  355:   ifp = rip2IfLookup (v, name, length, &addr, exact);
  356:   if (! ifp)
  357:     return NULL;
  358: 
  359:   /* Fetch rip_interface information. */
  360:   ri = ifp->info;
  361: 
  362:   switch (v->magic)
  363:     {
  364:     case RIP2IFSTATADDRESS:
  365:       return SNMP_IPADDRESS (addr);
  366:       break;
  367:     case RIP2IFSTATRCVBADPACKETS:
  368:       *var_len = sizeof (long);
  369:       return (u_char *) &ri->recv_badpackets;
  370: 
  371:     case RIP2IFSTATRCVBADROUTES:
  372:       *var_len = sizeof (long);
  373:       return (u_char *) &ri->recv_badroutes;
  374: 
  375:     case RIP2IFSTATSENTUPDATES:
  376:       *var_len = sizeof (long);
  377:       return (u_char *) &ri->sent_updates;
  378: 
  379:     case RIP2IFSTATSTATUS:
  380:       *var_len = sizeof (long);
  381:       v->type = ASN_INTEGER;
  382:       return (u_char *) &valid;
  383: 
  384:     default:
  385:       return NULL;
  386: 
  387:     }
  388:   return NULL;
  389: }
  390: 
  391: static long
  392: rip2IfConfSend (struct rip_interface *ri)
  393: {
  394: #define doNotSend       1
  395: #define ripVersion1     2
  396: #define rip1Compatible  3
  397: #define ripVersion2     4
  398: #define ripV1Demand     5
  399: #define ripV2Demand     6
  400: 
  401:   if (! ri->running)
  402:     return doNotSend;
  403:     
  404:   if (ri->ri_send & RIPv2)
  405:     return ripVersion2;
  406:   else if (ri->ri_send & RIPv1)
  407:     return ripVersion1;
  408:   else if (rip)
  409:     {
  410:       if (rip->version_send == RIPv2)
  411: 	return ripVersion2;
  412:       else if (rip->version_send == RIPv1)
  413: 	return ripVersion1;
  414:     }
  415:   return doNotSend;
  416: }
  417: 
  418: static long
  419: rip2IfConfReceive (struct rip_interface *ri)
  420: {
  421: #define rip1            1
  422: #define rip2            2
  423: #define rip1OrRip2      3
  424: #define doNotReceive    4
  425: 
  426:   int recvv;
  427: 
  428:   if (! ri->running)
  429:     return doNotReceive;
  430: 
  431:   recvv = (ri->ri_receive == RI_RIP_UNSPEC) ?  rip->version_recv :
  432:                                                ri->ri_receive;
  433:   if (recvv == RI_RIP_VERSION_1_AND_2)
  434:     return rip1OrRip2;
  435:   else if (recvv & RIPv2)
  436:     return rip2;
  437:   else if (recvv & RIPv1)
  438:     return rip1;
  439:   else
  440:     return doNotReceive;
  441: }
  442: 
  443: static u_char *
  444: rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
  445: 	           int exact, size_t *val_len, WriteMethod **write_method)
  446: {
  447:   static struct in_addr addr;
  448:   static long valid = SNMP_INVALID;
  449:   static long domain = 0;
  450:   static long config = 0;
  451:   static u_int auth = 0;
  452:   struct interface *ifp;
  453:   struct rip_interface *ri;
  454: 
  455:   if (smux_header_table(v, name, length, exact, val_len, write_method)
  456:       == MATCH_FAILED)
  457:     return NULL;
  458: 
  459:   memset (&addr, 0, sizeof (struct in_addr));
  460:   
  461:   /* Lookup interface. */
  462:   ifp = rip2IfLookup (v, name, length, &addr, exact);
  463:   if (! ifp)
  464:     return NULL;
  465: 
  466:   /* Fetch rip_interface information. */
  467:   ri = ifp->info;
  468: 
  469:   switch (v->magic)
  470:     {
  471:     case RIP2IFCONFADDRESS:
  472:       *val_len = sizeof (struct in_addr);
  473:       return (u_char *) &addr;
  474: 
  475:     case RIP2IFCONFDOMAIN:
  476:       *val_len = 2;
  477:       return (u_char *) &domain;
  478: 
  479:     case RIP2IFCONFAUTHTYPE:
  480:       auth = ri->auth_type;
  481:       *val_len = sizeof (long);
  482:       v->type = ASN_INTEGER;
  483:       return (u_char *)&auth;
  484: 
  485:     case RIP2IFCONFAUTHKEY:
  486:       *val_len = 0;
  487:       return (u_char *) &domain;
  488:     case RIP2IFCONFSEND:
  489:       config = rip2IfConfSend (ri);
  490:       *val_len = sizeof (long);
  491:       v->type = ASN_INTEGER;
  492:       return (u_char *) &config;
  493:     case RIP2IFCONFRECEIVE:
  494:       config = rip2IfConfReceive (ri);
  495:       *val_len = sizeof (long);
  496:       v->type = ASN_INTEGER;
  497:       return (u_char *) &config;
  498: 
  499:     case RIP2IFCONFDEFAULTMETRIC:
  500:       *val_len = sizeof (long);
  501:       v->type = ASN_INTEGER;
  502:       return (u_char *) &ifp->metric;
  503:     case RIP2IFCONFSTATUS:
  504:       *val_len = sizeof (long);
  505:       v->type = ASN_INTEGER;
  506:       return (u_char *) &valid;
  507:     case RIP2IFCONFSRCADDRESS:
  508:       *val_len = sizeof (struct in_addr);
  509:       return (u_char *) &addr;
  510: 
  511:     default:
  512:       return NULL;
  513: 
  514:     }
  515:   return NULL;
  516: }
  517: 
  518: static u_char *
  519: rip2PeerTable (struct variable *v, oid name[], size_t *length,
  520: 	       int exact, size_t *val_len, WriteMethod **write_method)
  521: {
  522:   static struct in_addr addr;
  523:   static int domain = 0;
  524:   static int version;
  525:   /* static time_t uptime; */
  526: 
  527:   struct rip_peer *peer;
  528: 
  529:   if (smux_header_table(v, name, length, exact, val_len, write_method)
  530:       == MATCH_FAILED)
  531:     return NULL;
  532: 
  533:   memset (&addr, 0, sizeof (struct in_addr));
  534:   
  535:   /* Lookup interface. */
  536:   peer = rip2PeerLookup (v, name, length, &addr, exact);
  537:   if (! peer)
  538:     return NULL;
  539: 
  540:   switch (v->magic)
  541:     {
  542:     case RIP2PEERADDRESS:
  543:       *val_len = sizeof (struct in_addr);
  544:       return (u_char *) &peer->addr;
  545: 
  546:     case RIP2PEERDOMAIN:
  547:       *val_len = 2;
  548:       return (u_char *) &domain;
  549: 
  550:     case RIP2PEERLASTUPDATE:
  551: #if 0 
  552:       /* We don't know the SNMP agent startup time. We have two choices here:
  553:        * - assume ripd startup time equals SNMP agent startup time
  554:        * - don't support this variable, at all
  555:        * Currently, we do the latter...
  556:        */
  557:       *val_len = sizeof (time_t);
  558:       uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
  559:       return (u_char *) &uptime;
  560: #else
  561:       return (u_char *) NULL;
  562: #endif
  563: 
  564:     case RIP2PEERVERSION:
  565:       *val_len = sizeof (int);
  566:       version = peer->version;
  567:       return (u_char *) &version;
  568: 
  569:     case RIP2PEERRCVBADPACKETS:
  570:       *val_len = sizeof (int);
  571:       return (u_char *) &peer->recv_badpackets;
  572: 
  573:     case RIP2PEERRCVBADROUTES:
  574:       *val_len = sizeof (int);
  575:       return (u_char *) &peer->recv_badroutes;
  576: 
  577:     default:
  578:       return NULL;
  579: 
  580:     }
  581:   return NULL;
  582: }
  583: 
  584: /* Register RIPv2-MIB. */
  585: void
  586: rip_snmp_init ()
  587: {
  588:   rip_ifaddr_table = route_table_init ();
  589: 
  590:   smux_init (master);
  591:   REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
  592: }
  593: #endif /* HAVE_SNMP */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>