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

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

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