File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / zebra_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, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    1: /* FIB SNMP.
    2:  * Copyright (C) 1999 Kunihiro Ishiguro
    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: /*
   23:  * Currently SNMP is only running properly for MIBs in the default VRF.
   24:  */
   25: 
   26: #include <zebra.h>
   27: 
   28: #ifdef HAVE_SNMP
   29: #include <net-snmp/net-snmp-config.h>
   30: #include <net-snmp/net-snmp-includes.h>
   31: 
   32: #include "if.h"
   33: #include "log.h"
   34: #include "prefix.h"
   35: #include "command.h"
   36: #include "smux.h"
   37: #include "table.h"
   38: #include "vrf.h"
   39: 
   40: #include "zebra/rib.h"
   41: #include "zebra/zserv.h"
   42: 
   43: #define IPFWMIB 1,3,6,1,2,1,4,24
   44: 
   45: /* ipForwardTable */
   46: #define IPFORWARDDEST                         1
   47: #define IPFORWARDMASK                         2
   48: #define IPFORWARDPOLICY                       3
   49: #define IPFORWARDNEXTHOP                      4
   50: #define IPFORWARDIFINDEX                      5
   51: #define IPFORWARDTYPE                         6
   52: #define IPFORWARDPROTO                        7
   53: #define IPFORWARDAGE                          8
   54: #define IPFORWARDINFO                         9
   55: #define IPFORWARDNEXTHOPAS                   10
   56: #define IPFORWARDMETRIC1                     11
   57: #define IPFORWARDMETRIC2                     12
   58: #define IPFORWARDMETRIC3                     13
   59: #define IPFORWARDMETRIC4                     14
   60: #define IPFORWARDMETRIC5                     15
   61: 
   62: /* ipCidrRouteTable */
   63: #define IPCIDRROUTEDEST                       1
   64: #define IPCIDRROUTEMASK                       2
   65: #define IPCIDRROUTETOS                        3
   66: #define IPCIDRROUTENEXTHOP                    4
   67: #define IPCIDRROUTEIFINDEX                    5
   68: #define IPCIDRROUTETYPE                       6
   69: #define IPCIDRROUTEPROTO                      7
   70: #define IPCIDRROUTEAGE                        8
   71: #define IPCIDRROUTEINFO                       9
   72: #define IPCIDRROUTENEXTHOPAS                 10
   73: #define IPCIDRROUTEMETRIC1                   11
   74: #define IPCIDRROUTEMETRIC2                   12
   75: #define IPCIDRROUTEMETRIC3                   13
   76: #define IPCIDRROUTEMETRIC4                   14
   77: #define IPCIDRROUTEMETRIC5                   15
   78: #define IPCIDRROUTESTATUS                    16
   79: 
   80: #define INTEGER32 ASN_INTEGER
   81: #define GAUGE32 ASN_GAUGE
   82: #define ENUMERATION ASN_INTEGER
   83: #define ROWSTATUS ASN_INTEGER
   84: #define IPADDRESS ASN_IPADDRESS
   85: #define OBJECTIDENTIFIER ASN_OBJECT_ID
   86: 
   87: extern struct zebra_t zebrad;
   88: 
   89: oid ipfw_oid [] = { IPFWMIB };
   90: 
   91: /* Hook functions. */
   92: static u_char * ipFwNumber (struct variable *, oid [], size_t *,
   93: 		     int, size_t *, WriteMethod **);
   94: static u_char * ipFwTable (struct variable *, oid [], size_t *,
   95: 			   int, size_t *, WriteMethod **);
   96: static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
   97: 			      int, size_t *, WriteMethod **);
   98: static u_char * ipCidrTable (struct variable *, oid [], size_t *,
   99: 			     int, size_t *, WriteMethod **);
  100: 
  101: struct variable zebra_variables[] = 
  102:   {
  103:     {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
  104:     {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
  105:     {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
  106:     {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
  107:     {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
  108:     {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
  109:     {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
  110:     {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
  111:     {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
  112:     {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
  113:     {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
  114:     {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
  115:     {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
  116:     {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
  117:     {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
  118:     {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
  119:     {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
  120:     {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
  121:     {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
  122:     {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
  123:     {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
  124:     {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
  125:     {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
  126:     {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
  127:     {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
  128:     {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
  129:     {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
  130:     {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
  131:     {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
  132:     {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
  133:     {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
  134:     {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
  135:     {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
  136:   };
  137: 
  138: 
  139: static u_char *
  140: ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
  141: 	    int exact, size_t *val_len, WriteMethod **write_method)
  142: {
  143:   static int result;
  144:   struct route_table *table;
  145:   struct route_node *rn;
  146:   struct rib *rib;
  147: 
  148:   if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
  149:     return NULL;
  150: 
  151:   table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
  152:   if (! table)
  153:     return NULL;
  154: 
  155:   /* Return number of routing entries. */
  156:   result = 0;
  157:   for (rn = route_top (table); rn; rn = route_next (rn))
  158:     RNODE_FOREACH_RIB (rn, rib)
  159:       result++;
  160: 
  161:   return (u_char *)&result;
  162: }
  163: 
  164: static u_char *
  165: ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
  166: 	      int exact, size_t *val_len, WriteMethod **write_method)
  167: {
  168:   static int result;
  169:   struct route_table *table;
  170:   struct route_node *rn;
  171:   struct rib *rib;
  172: 
  173:   if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
  174:     return NULL;
  175: 
  176:   table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
  177:   if (! table)
  178:     return 0;
  179: 
  180:   /* Return number of routing entries. */
  181:   result = 0;
  182:   for (rn = route_top (table); rn; rn = route_next (rn))
  183:     RNODE_FOREACH_RIB (rn, rib)
  184:       result++;
  185: 
  186:   return (u_char *)&result;
  187: }
  188: 
  189: static int
  190: in_addr_cmp(u_char *p1, u_char *p2)
  191: {
  192:   int i;
  193: 
  194:   for (i=0; i<4; i++)
  195:     {
  196:       if (*p1 < *p2)
  197:         return -1;
  198:       if (*p1 > *p2)
  199:         return 1;
  200:       p1++; p2++;
  201:     }
  202:   return 0;
  203: }
  204: 
  205: static int 
  206: in_addr_add(u_char *p, int num)
  207: {
  208:   int i, ip0;
  209: 
  210:   ip0 = *p;
  211:   p += 4;
  212:   for (i = 3; 0 <= i; i--) {
  213:     p--;
  214:     if (*p + num > 255) {
  215:       *p += num;
  216:       num = 1;
  217:     } else {
  218:       *p += num;
  219:       return 1;
  220:     }
  221:   }
  222:   if (ip0 > *p) {
  223:     /* ip + num > 0xffffffff */
  224:     return 0;
  225:   }
  226:   
  227:   return 1;
  228: }
  229: 
  230: static int
  231: proto_trans(int type)
  232: {
  233:   switch (type)
  234:     {
  235:     case ZEBRA_ROUTE_SYSTEM:
  236:       return 1; /* other */
  237:     case ZEBRA_ROUTE_KERNEL:
  238:       return 1; /* other */
  239:     case ZEBRA_ROUTE_CONNECT:
  240:       return 2; /* local interface */
  241:     case ZEBRA_ROUTE_STATIC:
  242:       return 3; /* static route */
  243:     case ZEBRA_ROUTE_RIP:
  244:       return 8; /* rip */
  245:     case ZEBRA_ROUTE_RIPNG:
  246:       return 1; /* shouldn't happen */
  247:     case ZEBRA_ROUTE_OSPF:
  248:       return 13; /* ospf */
  249:     case ZEBRA_ROUTE_OSPF6:
  250:       return 1; /* shouldn't happen */
  251:     case ZEBRA_ROUTE_BGP:
  252:       return 14; /* bgp */
  253:     default:
  254:       return 1; /* other */
  255:     }
  256: }
  257: 
  258: static void
  259: check_replace(struct route_node *np2, struct rib *rib2, 
  260:               struct route_node **np, struct rib **rib)
  261: {
  262:   int proto, proto2;
  263: 
  264:   if (!*np)
  265:     {
  266:       *np = np2;
  267:       *rib = rib2;
  268:       return;
  269:     }
  270: 
  271:   if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
  272:     return;
  273:   if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
  274:     {
  275:       *np = np2;
  276:       *rib = rib2;
  277:       return;
  278:     }
  279: 
  280:   proto = proto_trans((*rib)->type);
  281:   proto2 = proto_trans(rib2->type);
  282: 
  283:   if (proto2 > proto)
  284:     return;
  285:   if (proto2 < proto)
  286:     {
  287:       *np = np2;
  288:       *rib = rib2;
  289:       return;
  290:     }
  291: 
  292:   if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4, 
  293:                   (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
  294:     return;
  295: 
  296:   *np = np2;
  297:   *rib = rib2;
  298:   return;
  299: }
  300: 
  301: static void
  302: get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len, 
  303: 		       int exact, struct route_node **np, struct rib **rib)
  304: {
  305:   struct in_addr dest;
  306:   struct route_table *table;
  307:   struct route_node *np2;
  308:   struct rib *rib2;
  309:   int proto;
  310:   int policy;
  311:   struct in_addr nexthop;
  312:   u_char *pnt;
  313:   int i;
  314: 
  315:   /* Init index variables */
  316: 
  317:   pnt = (u_char *) &dest;
  318:   for (i = 0; i < 4; i++)
  319:     *pnt++ = 0;
  320: 
  321:   pnt = (u_char *) &nexthop;
  322:   for (i = 0; i < 4; i++)
  323:     *pnt++ = 0;
  324: 
  325:   proto = 0;
  326:   policy = 0;
  327:  
  328:   /* Init return variables */
  329: 
  330:   *np = NULL;
  331:   *rib = NULL;
  332: 
  333:   /* Short circuit exact matches of wrong length */
  334: 
  335:   if (exact && (*objid_len != (unsigned) v->namelen + 10))
  336:     return;
  337: 
  338:   table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
  339:   if (! table)
  340:     return;
  341: 
  342:   /* Get INDEX information out of OID.
  343:    * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
  344:    */
  345: 
  346:   if (*objid_len > (unsigned) v->namelen)
  347:     oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
  348: 
  349:   if (*objid_len > (unsigned) v->namelen + 4)
  350:     proto = objid[v->namelen + 4];
  351: 
  352:   if (*objid_len > (unsigned) v->namelen + 5)
  353:     policy = objid[v->namelen + 5];
  354: 
  355:   if (*objid_len > (unsigned) v->namelen + 6)
  356:     oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
  357: 		 &nexthop);
  358: 
  359:   /* Apply GETNEXT on not exact search */
  360: 
  361:   if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
  362:     {
  363:       if (! in_addr_add((u_char *) &nexthop, 1)) 
  364:         return;
  365:     }
  366: 
  367:   /* For exact: search matching entry in rib table. */
  368: 
  369:   if (exact)
  370:     {
  371:       if (policy) /* Not supported (yet?) */
  372:         return;
  373:       for (*np = route_top (table); *np; *np = route_next (*np))
  374: 	{
  375: 	  if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
  376: 	    {
  377: 	      RNODE_FOREACH_RIB (*np, *rib)
  378: 	        {
  379: 		  if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
  380: 				   (u_char *)&nexthop))
  381: 		    if (proto == proto_trans((*rib)->type))
  382: 		      return;
  383: 		}
  384: 	    }
  385: 	}
  386:       return;
  387:     }
  388: 
  389:   /* Search next best entry */
  390: 
  391:   for (np2 = route_top (table); np2; np2 = route_next (np2))
  392:     {
  393: 
  394:       /* Check destination first */
  395:       if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
  396: 	RNODE_FOREACH_RIB (np2, rib2)
  397: 	  check_replace(np2, rib2, np, rib);
  398: 
  399:       if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
  400:         { /* have to look at each rib individually */
  401: 	  RNODE_FOREACH_RIB (np2, rib2)
  402: 	    {
  403: 	      int proto2, policy2;
  404: 
  405: 	      proto2 = proto_trans(rib2->type);
  406: 	      policy2 = 0;
  407: 
  408: 	      if ((policy < policy2)
  409: 		  || ((policy == policy2) && (proto < proto2))
  410: 		  || ((policy == policy2) && (proto == proto2)
  411: 		      && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
  412: 				      (u_char *) &nexthop) >= 0)
  413: 		      ))
  414: 		check_replace(np2, rib2, np, rib);
  415: 	    }
  416: 	}
  417:     }
  418: 
  419:   if (!*rib)
  420:     return;
  421: 
  422:   policy = 0;
  423:   proto = proto_trans((*rib)->type);
  424: 
  425:   *objid_len = v->namelen + 10;
  426:   pnt = (u_char *) &(*np)->p.u.prefix;
  427:   for (i = 0; i < 4; i++)
  428:     objid[v->namelen + i] = *pnt++;
  429: 
  430:   objid[v->namelen + 4] = proto;
  431:   objid[v->namelen + 5] = policy;
  432: 
  433:   {
  434:     struct nexthop *nexthop;
  435: 
  436:     nexthop = (*rib)->nexthop;
  437:     if (nexthop)
  438:       {
  439: 	pnt = (u_char *) &nexthop->gate.ipv4;
  440: 	for (i = 0; i < 4; i++)
  441: 	  objid[i + v->namelen + 6] = *pnt++;
  442:       }
  443:   }
  444: 
  445:   return;
  446: }
  447: 
  448: static u_char *
  449: ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
  450: 	   int exact, size_t *val_len, WriteMethod **write_method)
  451: {
  452:   struct route_node *np;
  453:   struct rib *rib;
  454:   static int result;
  455:   static int resarr[2];
  456:   static struct in_addr netmask;
  457:   struct nexthop *nexthop;
  458: 
  459:   if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
  460:       == MATCH_FAILED)
  461:     return NULL;
  462: 
  463:   get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
  464:   if (!np)
  465:     return NULL;
  466: 
  467:   nexthop = rib->nexthop;
  468:   if (! nexthop)
  469:     return NULL;
  470: 
  471:   switch (v->magic)
  472:     {
  473:     case IPFORWARDDEST:
  474:       *val_len = 4;
  475:       return &np->p.u.prefix;
  476:       break;
  477:     case IPFORWARDMASK:
  478:       masklen2ip(np->p.prefixlen, &netmask);
  479:       *val_len = 4;
  480:       return (u_char *)&netmask;
  481:       break;
  482:     case IPFORWARDPOLICY:
  483:       result = 0;
  484:       *val_len  = sizeof(int);
  485:       return (u_char *)&result;
  486:       break;
  487:     case IPFORWARDNEXTHOP:
  488:       *val_len = 4;
  489:       return (u_char *)&nexthop->gate.ipv4;
  490:       break;
  491:     case IPFORWARDIFINDEX:
  492:       *val_len = sizeof(int);
  493:       return (u_char *)&nexthop->ifindex;
  494:       break;
  495:     case IPFORWARDTYPE:
  496:       if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  497: 	  || nexthop->type == NEXTHOP_TYPE_IFNAME)
  498:         result = 3;
  499:       else
  500:         result = 4;
  501:       *val_len  = sizeof(int);
  502:       return (u_char *)&result;
  503:       break;
  504:     case IPFORWARDPROTO:
  505:       result = proto_trans(rib->type);
  506:       *val_len  = sizeof(int);
  507:       return (u_char *)&result;
  508:       break;
  509:     case IPFORWARDAGE:
  510:       result = 0;
  511:       *val_len  = sizeof(int);
  512:       return (u_char *)&result;
  513:       break;
  514:     case IPFORWARDINFO:
  515:       resarr[0] = 0;
  516:       resarr[1] = 0;
  517:       *val_len  = 2 * sizeof(int);
  518:       return (u_char *)resarr;
  519:       break;
  520:     case IPFORWARDNEXTHOPAS:
  521:       result = -1;
  522:       *val_len  = sizeof(int);
  523:       return (u_char *)&result;
  524:       break;
  525:     case IPFORWARDMETRIC1:
  526:       result = 0;
  527:       *val_len  = sizeof(int);
  528:       return (u_char *)&result;
  529:       break;
  530:     case IPFORWARDMETRIC2:
  531:       result = 0;
  532:       *val_len  = sizeof(int);
  533:       return (u_char *)&result;
  534:       break;
  535:     case IPFORWARDMETRIC3:
  536:       result = 0;
  537:       *val_len  = sizeof(int);
  538:       return (u_char *)&result;
  539:       break;
  540:     case IPFORWARDMETRIC4:
  541:       result = 0;
  542:       *val_len  = sizeof(int);
  543:       return (u_char *)&result;
  544:       break;
  545:     case IPFORWARDMETRIC5:
  546:       result = 0;
  547:       *val_len  = sizeof(int);
  548:       return (u_char *)&result;
  549:       break;
  550:     default:
  551:       return NULL;
  552:       break;
  553:     }  
  554:   return NULL;
  555: }
  556: 
  557: static u_char *
  558: ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
  559: 	     int exact, size_t *val_len, WriteMethod **write_method)
  560: {
  561:   if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
  562:       == MATCH_FAILED)
  563:     return NULL;
  564: 
  565:   switch (v->magic)
  566:     {
  567:     case IPCIDRROUTEDEST:
  568:       break;
  569:     default:
  570:       return NULL;
  571:       break;
  572:     }  
  573:   return NULL;
  574: }
  575: 
  576: void
  577: zebra_snmp_init ()
  578: {
  579:   smux_init (zebrad.master);
  580:   REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
  581: }
  582: #endif /* HAVE_SNMP */

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