Annotation of embedaddon/quagga/ripd/rip_snmp.c, revision 1.1.1.2

1.1       misho       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 == 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 < sizeof (struct in_addr) + 1) ||
                    315:              (peer->domain > 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: 
1.1.1.2 ! misho     348:   if (smux_header_table(v, name, length, exact, var_len, write_method)
        !           349:       == MATCH_FAILED)
        !           350:     return NULL;
        !           351: 
1.1       misho     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: 
1.1.1.2 ! misho     455:   if (smux_header_table(v, name, length, exact, val_len, write_method)
        !           456:       == MATCH_FAILED)
        !           457:     return NULL;
        !           458: 
1.1       misho     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: 
1.1.1.2 ! misho     529:   if (smux_header_table(v, name, length, exact, val_len, write_method)
        !           530:       == MATCH_FAILED)
        !           531:     return NULL;
        !           532: 
1.1       misho     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>