File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_snmp.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jul 21 23:54:38 2013 UTC (10 years, 11 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, HEAD
0.99.22

    1: /* BGP4 SNMP support
    2:    Copyright (C) 1999, 2000 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: #include <zebra.h>
   22: 
   23: #ifdef HAVE_SNMP
   24: #include <net-snmp/net-snmp-config.h>
   25: #include <net-snmp/net-snmp-includes.h>
   26: 
   27: #include "if.h"
   28: #include "log.h"
   29: #include "prefix.h"
   30: #include "command.h"
   31: #include "thread.h"
   32: #include "smux.h"
   33: 
   34: #include "bgpd/bgpd.h"
   35: #include "bgpd/bgp_table.h"
   36: #include "bgpd/bgp_aspath.h"
   37: #include "bgpd/bgp_attr.h"
   38: #include "bgpd/bgp_route.h"
   39: #include "bgpd/bgp_fsm.h"
   40: #include "bgpd/bgp_snmp.h"
   41: 
   42: /* BGP4-MIB described in RFC1657. */
   43: #define BGP4MIB 1,3,6,1,2,1,15
   44: 
   45: /* BGP TRAP. */
   46: #define BGPESTABLISHED			1
   47: #define BGPBACKWARDTRANSITION		2	
   48: 
   49: /* BGP MIB bgpVersion. */
   50: #define BGPVERSION			      0
   51: 
   52: /* BGP MIB bgpLocalAs. */
   53: #define BGPLOCALAS			      0
   54: 
   55: /* BGP MIB bgpPeerTable. */
   56: #define BGPPEERIDENTIFIER                     1
   57: #define BGPPEERSTATE                          2
   58: #define BGPPEERADMINSTATUS                    3
   59: #define BGPPEERNEGOTIATEDVERSION              4
   60: #define BGPPEERLOCALADDR                      5
   61: #define BGPPEERLOCALPORT                      6
   62: #define BGPPEERREMOTEADDR                     7
   63: #define BGPPEERREMOTEPORT                     8
   64: #define BGPPEERREMOTEAS                       9
   65: #define BGPPEERINUPDATES                     10
   66: #define BGPPEEROUTUPDATES                    11
   67: #define BGPPEERINTOTALMESSAGES               12
   68: #define BGPPEEROUTTOTALMESSAGES              13
   69: #define BGPPEERLASTERROR                     14
   70: #define BGPPEERFSMESTABLISHEDTRANSITIONS     15
   71: #define BGPPEERFSMESTABLISHEDTIME            16
   72: #define BGPPEERCONNECTRETRYINTERVAL          17
   73: #define BGPPEERHOLDTIME                      18
   74: #define BGPPEERKEEPALIVE                     19
   75: #define BGPPEERHOLDTIMECONFIGURED            20
   76: #define BGPPEERKEEPALIVECONFIGURED           21
   77: #define BGPPEERMINASORIGINATIONINTERVAL      22
   78: #define BGPPEERMINROUTEADVERTISEMENTINTERVAL 23
   79: #define BGPPEERINUPDATEELAPSEDTIME           24
   80: 
   81: /* BGP MIB bgpIdentifier. */
   82: #define BGPIDENTIFIER                         0
   83: 
   84: /* BGP MIB bgpRcvdPathAttrTable */
   85: #define BGPPATHATTRPEER                       1
   86: #define BGPPATHATTRDESTNETWORK                2
   87: #define BGPPATHATTRORIGIN                     3
   88: #define BGPPATHATTRASPATH                     4
   89: #define BGPPATHATTRNEXTHOP                    5
   90: #define BGPPATHATTRINTERASMETRIC              6
   91: 
   92: /* BGP MIB bgp4PathAttrTable. */
   93: #define BGP4PATHATTRPEER                      1
   94: #define BGP4PATHATTRIPADDRPREFIXLEN           2
   95: #define BGP4PATHATTRIPADDRPREFIX              3
   96: #define BGP4PATHATTRORIGIN                    4
   97: #define BGP4PATHATTRASPATHSEGMENT             5
   98: #define BGP4PATHATTRNEXTHOP                   6
   99: #define BGP4PATHATTRMULTIEXITDISC             7
  100: #define BGP4PATHATTRLOCALPREF                 8
  101: #define BGP4PATHATTRATOMICAGGREGATE           9
  102: #define BGP4PATHATTRAGGREGATORAS             10
  103: #define BGP4PATHATTRAGGREGATORADDR           11
  104: #define BGP4PATHATTRCALCLOCALPREF            12
  105: #define BGP4PATHATTRBEST                     13
  106: #define BGP4PATHATTRUNKNOWN                  14
  107: 
  108: /* SNMP value hack. */
  109: #define INTEGER ASN_INTEGER
  110: #define INTEGER32 ASN_INTEGER
  111: #define COUNTER32 ASN_COUNTER
  112: #define OCTET_STRING ASN_OCTET_STR
  113: #define IPADDRESS ASN_IPADDRESS
  114: #define GAUGE32 ASN_UNSIGNED
  115: 
  116: /* Declare static local variables for convenience. */
  117: SNMP_LOCAL_VARIABLES
  118: 
  119: /* BGP-MIB instances. */
  120: oid bgp_oid [] = { BGP4MIB };
  121: oid bgp_trap_oid [] = { BGP4MIB, 0 };
  122: 
  123: /* IP address 0.0.0.0. */
  124: static struct in_addr bgp_empty_addr = {0};
  125: 
  126: /* Hook functions. */
  127: static u_char *bgpVersion (struct variable *, oid [], size_t *, int,
  128: 			   size_t *, WriteMethod **);
  129: static u_char *bgpLocalAs (struct variable *, oid [], size_t *,
  130: 			   int, size_t *, WriteMethod **);
  131: static u_char *bgpPeerTable (struct variable *, oid [], size_t *,
  132: 			     int, size_t *, WriteMethod **);
  133: static u_char *bgpRcvdPathAttrTable (struct variable *, oid [], size_t *,
  134: 				     int, size_t *, WriteMethod **);
  135: static u_char *bgpIdentifier (struct variable *, oid [], size_t *,
  136: 			      int, size_t *, WriteMethod **);
  137: static u_char *bgp4PathAttrTable (struct variable *, oid [], size_t *,
  138: 				  int, size_t *, WriteMethod **);
  139: /* static u_char *bgpTraps (); */
  140: 
  141: struct variable bgp_variables[] = 
  142: {
  143:   /* BGP version. */
  144:   {BGPVERSION,                OCTET_STRING, RONLY, bgpVersion,
  145:    1, {1}},
  146:   /* BGP local AS. */
  147:   {BGPLOCALAS,                INTEGER, RONLY, bgpLocalAs,
  148:    1, {2}},
  149:   /* BGP peer table. */
  150:   {BGPPEERIDENTIFIER,         IPADDRESS, RONLY, bgpPeerTable,
  151:    3, {3, 1, 1}},
  152:   {BGPPEERSTATE,              INTEGER, RONLY, bgpPeerTable,
  153:    3, {3, 1, 2}},
  154:   {BGPPEERADMINSTATUS,        INTEGER, RWRITE, bgpPeerTable,
  155:    3, {3, 1, 3}},
  156:   {BGPPEERNEGOTIATEDVERSION,  INTEGER32, RONLY, bgpPeerTable,
  157:    3, {3, 1, 4}},
  158:   {BGPPEERLOCALADDR,          IPADDRESS, RONLY, bgpPeerTable,
  159:    3, {3, 1, 5}},
  160:   {BGPPEERLOCALPORT,          INTEGER, RONLY, bgpPeerTable,
  161:    3, {3, 1, 6}},
  162:   {BGPPEERREMOTEADDR,         IPADDRESS, RONLY, bgpPeerTable,
  163:    3, {3, 1, 7}},
  164:   {BGPPEERREMOTEPORT,         INTEGER, RONLY, bgpPeerTable,
  165:    3, {3, 1, 8}},
  166:   {BGPPEERREMOTEAS,           INTEGER, RONLY, bgpPeerTable,
  167:    3, {3, 1, 9}},
  168:   {BGPPEERINUPDATES,          COUNTER32, RONLY, bgpPeerTable,
  169:    3, {3, 1, 10}},
  170:   {BGPPEEROUTUPDATES,         COUNTER32, RONLY, bgpPeerTable,
  171:    3, {3, 1, 11}},
  172:   {BGPPEERINTOTALMESSAGES,    COUNTER32, RONLY, bgpPeerTable,
  173:    3, {3, 1, 12}},
  174:   {BGPPEEROUTTOTALMESSAGES,   COUNTER32, RONLY, bgpPeerTable,
  175:    3, {3, 1, 13}},
  176:   {BGPPEERLASTERROR,          OCTET_STRING, RONLY, bgpPeerTable,
  177:    3, {3, 1, 14}},
  178:   {BGPPEERFSMESTABLISHEDTRANSITIONS, COUNTER32, RONLY, bgpPeerTable,
  179:    3, {3, 1, 15}},
  180:   {BGPPEERFSMESTABLISHEDTIME, GAUGE32, RONLY, bgpPeerTable,
  181:    3, {3, 1, 16}},
  182:   {BGPPEERCONNECTRETRYINTERVAL, INTEGER, RWRITE, bgpPeerTable,
  183:    3, {3, 1, 17}},
  184:   {BGPPEERHOLDTIME,           INTEGER, RONLY, bgpPeerTable,
  185:    3, {3, 1, 18}},
  186:   {BGPPEERKEEPALIVE,          INTEGER, RONLY, bgpPeerTable,
  187:    3, {3, 1, 19}},
  188:   {BGPPEERHOLDTIMECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
  189:    3, {3, 1, 20}},
  190:   {BGPPEERKEEPALIVECONFIGURED, INTEGER, RWRITE, bgpPeerTable,
  191:    3, {3, 1, 21}},
  192:   {BGPPEERMINASORIGINATIONINTERVAL, INTEGER, RWRITE, bgpPeerTable,
  193:    3, {3, 1, 22}},
  194:   {BGPPEERMINROUTEADVERTISEMENTINTERVAL, INTEGER, RWRITE, bgpPeerTable,
  195:    3, {3, 1, 23}},
  196:   {BGPPEERINUPDATEELAPSEDTIME, GAUGE32, RONLY, bgpPeerTable,
  197:    3, {3, 1, 24}},
  198:   /* BGP identifier. */
  199:   {BGPIDENTIFIER,             IPADDRESS, RONLY, bgpIdentifier,
  200:    1, {4}},
  201:   /* BGP received path attribute table. */
  202:   {BGPPATHATTRPEER,           IPADDRESS, RONLY, bgpRcvdPathAttrTable,
  203:    3, {5, 1, 1}},
  204:   {BGPPATHATTRDESTNETWORK,    IPADDRESS, RONLY, bgpRcvdPathAttrTable,
  205:    3, {5, 1, 2}},
  206:   {BGPPATHATTRORIGIN,         INTEGER, RONLY, bgpRcvdPathAttrTable,
  207:    3, {5, 1, 3}},
  208:   {BGPPATHATTRASPATH,         OCTET_STRING, RONLY, bgpRcvdPathAttrTable,
  209:    3, {5, 1, 4}},
  210:   {BGPPATHATTRNEXTHOP,        IPADDRESS, RONLY, bgpRcvdPathAttrTable,
  211:    3, {5, 1, 5}},
  212:   {BGPPATHATTRINTERASMETRIC,  INTEGER32, RONLY, bgpRcvdPathAttrTable,
  213:    3, {5, 1, 6}},
  214:   /* BGP-4 received path attribute table. */
  215:   {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable,
  216:    3, {6, 1, 1}},
  217:   {BGP4PATHATTRIPADDRPREFIXLEN, INTEGER, RONLY, bgp4PathAttrTable,
  218:    3, {6, 1, 2}},
  219:   {BGP4PATHATTRIPADDRPREFIX,  IPADDRESS, RONLY, bgp4PathAttrTable,
  220:    3, {6, 1, 3}},
  221:   {BGP4PATHATTRORIGIN,        INTEGER, RONLY, bgp4PathAttrTable,
  222:    3, {6, 1, 4}},
  223:   {BGP4PATHATTRASPATHSEGMENT, OCTET_STRING, RONLY, bgp4PathAttrTable,
  224:    3, {6, 1, 5}},
  225:   {BGP4PATHATTRNEXTHOP,       IPADDRESS, RONLY, bgp4PathAttrTable,
  226:    3, {6, 1, 6}},
  227:   {BGP4PATHATTRMULTIEXITDISC, INTEGER, RONLY, bgp4PathAttrTable,
  228:    3, {6, 1, 7}},
  229:   {BGP4PATHATTRLOCALPREF,     INTEGER, RONLY, bgp4PathAttrTable,
  230:    3, {6, 1, 8}},
  231:   {BGP4PATHATTRATOMICAGGREGATE, INTEGER, RONLY, bgp4PathAttrTable,
  232:    3, {6, 1, 9}},
  233:   {BGP4PATHATTRAGGREGATORAS,  INTEGER, RONLY, bgp4PathAttrTable,
  234:    3, {6, 1, 10}},
  235:   {BGP4PATHATTRAGGREGATORADDR, IPADDRESS, RONLY, bgp4PathAttrTable,
  236:    3, {6, 1, 11}},
  237:   {BGP4PATHATTRCALCLOCALPREF, INTEGER, RONLY, bgp4PathAttrTable,
  238:    3, {6, 1, 12}},
  239:   {BGP4PATHATTRBEST,          INTEGER, RONLY, bgp4PathAttrTable,
  240:    3, {6, 1, 13}},
  241:   {BGP4PATHATTRUNKNOWN,       OCTET_STRING, RONLY, bgp4PathAttrTable,
  242:    3, {6, 1, 14}},
  243: };
  244: 
  245: 
  246: static u_char *
  247: bgpVersion (struct variable *v, oid name[], size_t *length, int exact,
  248: 	    size_t *var_len, WriteMethod **write_method)
  249: {
  250:   static u_char version;
  251: 
  252:   if (smux_header_generic(v, name, length, exact, var_len, write_method)
  253:       == MATCH_FAILED)
  254:     return NULL;
  255: 
  256:   /* Retrun BGP version.  Zebra bgpd only support version 4. */
  257:   version = (0x80 >> (BGP_VERSION_4 - 1));
  258: 
  259:   /* Return octet string length 1. */
  260:   *var_len = 1;
  261:   return (u_char *)&version;
  262: }
  263: 
  264: static u_char *
  265: bgpLocalAs (struct variable *v, oid name[], size_t *length,
  266: 	    int exact, size_t *var_len, WriteMethod **write_method)
  267: {
  268:   struct bgp *bgp;
  269: 
  270:   if (smux_header_generic(v, name, length, exact, var_len, write_method)
  271:       == MATCH_FAILED)
  272:     return NULL;
  273: 
  274:   /* Get BGP structure. */
  275:   bgp = bgp_get_default ();
  276:   if (! bgp)
  277:     return NULL;
  278: 
  279:   return SNMP_INTEGER (bgp->as);
  280: }
  281: 
  282: static struct peer *
  283: peer_lookup_addr_ipv4 (struct in_addr *src)
  284: {
  285:   struct bgp *bgp;
  286:   struct peer *peer;
  287:   struct listnode *node;
  288:   struct in_addr addr;
  289:   int ret;
  290: 
  291:   bgp = bgp_get_default ();
  292:   if (! bgp)
  293:     return NULL;
  294: 
  295:   for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
  296:     {
  297:       ret = inet_pton (AF_INET, peer->host, &addr);
  298:       if (ret > 0)
  299: 	{
  300: 	  if (IPV4_ADDR_SAME (&addr, src))
  301: 	    return peer;
  302: 	}
  303:     }
  304:   return NULL;
  305: }
  306: 
  307: static struct peer *
  308: bgp_peer_lookup_next (struct in_addr *src)
  309: {
  310:   struct bgp *bgp;
  311:   struct peer *peer;
  312:   struct listnode *node;
  313:   struct in_addr *p;
  314:   union sockunion su;
  315:   int ret;
  316: 
  317:   memset (&su, 0, sizeof (union sockunion));
  318: 
  319:   bgp = bgp_get_default ();
  320:   if (! bgp)
  321:     return NULL;
  322: 
  323:   for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
  324:     {
  325:       ret = inet_pton (AF_INET, peer->host, &su.sin.sin_addr);
  326:       if (ret > 0)
  327: 	{
  328: 	  p = &su.sin.sin_addr;
  329: 
  330: 	  if (ntohl (p->s_addr) > ntohl (src->s_addr))
  331: 	    {
  332: 	      src->s_addr = p->s_addr;
  333: 	      return peer;
  334: 	    }
  335: 	}
  336:     }
  337:   return NULL;
  338: }
  339: 
  340: static struct peer *
  341: bgpPeerTable_lookup (struct variable *v, oid name[], size_t *length, 
  342: 		     struct in_addr *addr, int exact)
  343: {
  344:   struct peer *peer = NULL;
  345:   int len;
  346: 
  347:   if (exact)
  348:     {
  349:       /* Check the length. */
  350:       if (*length - v->namelen != sizeof (struct in_addr))
  351: 	return NULL;
  352: 
  353:       oid2in_addr (name + v->namelen, IN_ADDR_SIZE, addr);
  354: 
  355:       peer = peer_lookup_addr_ipv4 (addr);
  356:       return peer;
  357:     }
  358:   else
  359:     {
  360:       len = *length - v->namelen;
  361:       if (len > 4) len = 4;
  362:       
  363:       oid2in_addr (name + v->namelen, len, addr);
  364:       
  365:       peer = bgp_peer_lookup_next (addr);
  366: 
  367:       if (peer == NULL)
  368: 	return NULL;
  369: 
  370:       oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  371:       *length = sizeof (struct in_addr) + v->namelen;
  372: 
  373:       return peer;
  374:     }
  375:   return NULL;
  376: }
  377: 
  378: /* BGP write methods. */
  379: static int
  380: write_bgpPeerTable (int action, u_char *var_val,
  381: 		    u_char var_val_type, size_t var_val_len,
  382: 		    u_char *statP, oid *name, size_t length,
  383: 		    struct variable *v)
  384: {
  385:   struct in_addr addr;
  386:   struct peer *peer;
  387:   long intval;
  388:   size_t bigsize = SNMP_MAX_LEN;
  389:   
  390:   if (var_val_type != ASN_INTEGER) 
  391:     {
  392:       return SNMP_ERR_WRONGTYPE;
  393:     }
  394:   if (var_val_len != sizeof (long)) 
  395:     {
  396:       return SNMP_ERR_WRONGLENGTH;
  397:     }
  398: 
  399:   if (! asn_parse_int(var_val, &bigsize, &var_val_type,
  400:                       &intval, sizeof(long)))
  401:     {
  402:       return SNMP_ERR_WRONGENCODING;
  403:     }
  404: 
  405:   memset (&addr, 0, sizeof (struct in_addr));
  406: 
  407:   peer = bgpPeerTable_lookup (v, name, &length, &addr, 1);
  408:   if (! peer)
  409:     return SNMP_ERR_NOSUCHNAME;
  410: 
  411:   printf ("val: %ld\n", intval);
  412: 
  413:   switch (v->magic)
  414:     {
  415:     case BGPPEERADMINSTATUS:
  416: #define BGP_PeerAdmin_stop  1
  417: #define BGP_PeerAdmin_start 2
  418:       /* When the peer is established,   */
  419:       if (intval == BGP_PeerAdmin_stop)
  420: 	BGP_EVENT_ADD (peer, BGP_Stop);
  421:       else if (intval == BGP_PeerAdmin_start)
  422: 	;			/* Do nothing. */
  423:       else
  424: 	return SNMP_ERR_NOSUCHNAME;
  425:       break;
  426:     case BGPPEERCONNECTRETRYINTERVAL:
  427:       SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
  428:       peer->connect = intval;
  429:       peer->v_connect = intval;
  430:       break;
  431:     case BGPPEERHOLDTIMECONFIGURED:
  432:       SET_FLAG (peer->config, PEER_CONFIG_TIMER);
  433:       peer->holdtime = intval;
  434:       peer->v_holdtime = intval;
  435:       break;
  436:     case BGPPEERKEEPALIVECONFIGURED:
  437:       SET_FLAG (peer->config, PEER_CONFIG_TIMER);
  438:       peer->keepalive = intval;
  439:       peer->v_keepalive = intval;
  440:       break;
  441:     case BGPPEERMINASORIGINATIONINTERVAL:
  442:       peer->v_asorig = intval;
  443:       break;
  444:     case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
  445:       peer->v_routeadv = intval;
  446:       break;
  447:     }
  448:   return SNMP_ERR_NOERROR;
  449: }
  450: 
  451: static u_char *
  452: bgpPeerTable (struct variable *v, oid name[], size_t *length,
  453: 	      int exact, size_t *var_len, WriteMethod **write_method)
  454: {
  455:   static struct in_addr addr;
  456:   struct peer *peer;
  457: 
  458:   if (smux_header_table(v, name, length, exact, var_len, write_method)
  459:       == MATCH_FAILED)
  460:     return NULL;
  461:   memset (&addr, 0, sizeof (struct in_addr));
  462: 
  463:   peer = bgpPeerTable_lookup (v, name, length, &addr, exact);
  464:   if (! peer)
  465:     return NULL;
  466: 
  467:   switch (v->magic)
  468:     {
  469:     case BGPPEERIDENTIFIER:
  470:       return SNMP_IPADDRESS (peer->remote_id);
  471:       break;
  472:     case BGPPEERSTATE:
  473:       return SNMP_INTEGER (peer->status);
  474:       break;
  475:     case BGPPEERADMINSTATUS:
  476:       *write_method = write_bgpPeerTable;
  477: #define BGP_PeerAdmin_stop  1
  478: #define BGP_PeerAdmin_start 2
  479:       if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
  480: 	return SNMP_INTEGER (BGP_PeerAdmin_stop);
  481:       else
  482: 	return SNMP_INTEGER (BGP_PeerAdmin_start);
  483:       break;
  484:     case BGPPEERNEGOTIATEDVERSION:
  485:       return SNMP_INTEGER (BGP_VERSION_4);
  486:       break;
  487:     case BGPPEERLOCALADDR:
  488:       if (peer->su_local)
  489: 	return SNMP_IPADDRESS (peer->su_local->sin.sin_addr);
  490:       else
  491: 	return SNMP_IPADDRESS (bgp_empty_addr);
  492:       break;
  493:     case BGPPEERLOCALPORT:
  494:       if (peer->su_local)
  495: 	return SNMP_INTEGER (ntohs (peer->su_local->sin.sin_port));
  496:       else
  497: 	return SNMP_INTEGER (0);
  498:       break;
  499:     case BGPPEERREMOTEADDR:
  500:       if (peer->su_remote)
  501: 	return SNMP_IPADDRESS (peer->su_remote->sin.sin_addr);
  502:       else
  503: 	return SNMP_IPADDRESS (bgp_empty_addr);
  504:       break;
  505:     case BGPPEERREMOTEPORT:
  506:       if (peer->su_remote)
  507: 	return SNMP_INTEGER (ntohs (peer->su_remote->sin.sin_port));
  508:       else
  509: 	return SNMP_INTEGER (0);
  510:       break;
  511:     case BGPPEERREMOTEAS:
  512:       return SNMP_INTEGER (peer->as);
  513:       break;
  514:     case BGPPEERINUPDATES:
  515:       return SNMP_INTEGER (peer->update_in);
  516:       break;
  517:     case BGPPEEROUTUPDATES:
  518:       return SNMP_INTEGER (peer->update_out);
  519:       break;
  520:     case BGPPEERINTOTALMESSAGES:
  521:       return SNMP_INTEGER (peer->open_in + peer->update_in
  522: 			   + peer->keepalive_in + peer->notify_in
  523: 			   + peer->refresh_in + peer->dynamic_cap_in);
  524:       break;
  525:     case BGPPEEROUTTOTALMESSAGES:
  526:       return SNMP_INTEGER (peer->open_out + peer->update_out
  527: 			   + peer->keepalive_out + peer->notify_out
  528: 			   + peer->refresh_out + peer->dynamic_cap_out);
  529:       break;
  530:     case BGPPEERLASTERROR:
  531:       {
  532: 	static u_char lasterror[2];
  533: 	lasterror[0] = peer->notify.code;
  534: 	lasterror[1] = peer->notify.subcode;
  535: 	*var_len = 2;
  536: 	return (u_char *)&lasterror;
  537:       }
  538:       break;
  539:     case BGPPEERFSMESTABLISHEDTRANSITIONS:
  540:       return SNMP_INTEGER (peer->established);
  541:       break;
  542:     case BGPPEERFSMESTABLISHEDTIME:
  543:       if (peer->uptime == 0)
  544: 	return SNMP_INTEGER (0);
  545:       else
  546: 	return SNMP_INTEGER (bgp_clock () - peer->uptime);
  547:       break;
  548:     case BGPPEERCONNECTRETRYINTERVAL:
  549:       *write_method = write_bgpPeerTable;
  550:       return SNMP_INTEGER (peer->v_connect);
  551:       break;
  552:     case BGPPEERHOLDTIME:
  553:       return SNMP_INTEGER (peer->v_holdtime);
  554:       break;
  555:     case BGPPEERKEEPALIVE:
  556:       return SNMP_INTEGER (peer->v_keepalive);
  557:       break;
  558:     case BGPPEERHOLDTIMECONFIGURED:
  559:       *write_method = write_bgpPeerTable;
  560:       if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
  561: 	return SNMP_INTEGER (peer->holdtime);
  562:       else
  563: 	return SNMP_INTEGER (peer->v_holdtime);
  564:       break;
  565:     case BGPPEERKEEPALIVECONFIGURED:
  566:       *write_method = write_bgpPeerTable;
  567:       if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
  568: 	return SNMP_INTEGER (peer->keepalive);
  569:       else
  570: 	return SNMP_INTEGER (peer->v_keepalive);
  571:       break;
  572:     case BGPPEERMINASORIGINATIONINTERVAL:
  573:       *write_method = write_bgpPeerTable;
  574:       return SNMP_INTEGER (peer->v_asorig);
  575:       break;
  576:     case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
  577:       *write_method = write_bgpPeerTable;
  578:       return SNMP_INTEGER (peer->v_routeadv);
  579:       break;
  580:     case BGPPEERINUPDATEELAPSEDTIME:
  581:       if (peer->update_time == 0)
  582: 	return SNMP_INTEGER (0);
  583:       else
  584: 	return SNMP_INTEGER (bgp_clock () - peer->update_time);
  585:       break;
  586:     default:
  587:       return NULL;
  588:       break;
  589:     }  
  590:   return NULL;
  591: }
  592: 
  593: static u_char *
  594: bgpIdentifier (struct variable *v, oid name[], size_t *length,
  595: 	       int exact, size_t *var_len, WriteMethod **write_method)
  596: {
  597:   struct bgp *bgp;
  598: 
  599:   if (smux_header_generic(v, name, length, exact, var_len, write_method)
  600:       == MATCH_FAILED)
  601:     return NULL;
  602: 
  603:   bgp = bgp_get_default ();
  604:   if (!bgp)
  605:     return NULL;
  606: 
  607:   return SNMP_IPADDRESS (bgp->router_id);
  608: }
  609: 
  610: static u_char *
  611: bgpRcvdPathAttrTable (struct variable *v, oid name[], size_t *length,
  612: 		      int exact, size_t *var_len, WriteMethod **write_method)
  613: {
  614:   /* Received Path Attribute Table.  This table contains, one entry
  615:      per path to a network, path attributes received from all peers
  616:      running BGP version 3 or less.  This table is obsolete, having
  617:      been replaced in functionality with the bgp4PathAttrTable.  */
  618:   return NULL;
  619: }
  620: 
  621: static struct bgp_info *
  622: bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
  623: 		    struct bgp *bgp, struct prefix_ipv4 *addr, int exact)
  624: {
  625:   oid *offset;
  626:   int offsetlen;
  627:   struct bgp_info *binfo;
  628:   struct bgp_info *min;
  629:   struct bgp_node *rn;
  630:   union sockunion su;
  631:   unsigned int len;
  632:   struct in_addr paddr;
  633: 
  634: #define BGP_PATHATTR_ENTRY_OFFSET \
  635:           (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
  636: 
  637:   if (exact)
  638:     {
  639:       if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET)
  640: 	return NULL;
  641: 
  642:       /* Set OID offset for prefix. */
  643:       offset = name + v->namelen;
  644:       oid2in_addr (offset, IN_ADDR_SIZE, &addr->prefix);
  645:       offset += IN_ADDR_SIZE;
  646: 
  647:       /* Prefix length. */
  648:       addr->prefixlen = *offset;
  649:       offset++;
  650: 
  651:       /* Peer address. */
  652:       su.sin.sin_family = AF_INET;
  653:       oid2in_addr (offset, IN_ADDR_SIZE, &su.sin.sin_addr);
  654: 
  655:       /* Lookup node. */
  656:       rn = bgp_node_lookup (bgp->rib[AFI_IP][SAFI_UNICAST], 
  657: 			      (struct prefix *) addr);
  658:       if (rn)
  659: 	{
  660: 	  bgp_unlock_node (rn);
  661: 
  662: 	  for (binfo = rn->info; binfo; binfo = binfo->next)
  663: 	    if (sockunion_same (&binfo->peer->su, &su))
  664: 	      return binfo;
  665: 	}
  666:     }
  667:   else
  668:     {
  669:       offset = name + v->namelen;
  670:       offsetlen = *length - v->namelen;
  671:       len = offsetlen;
  672: 
  673:       if (offsetlen == 0)
  674: 	rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_UNICAST]);
  675:       else
  676: 	{
  677: 	  if (len > IN_ADDR_SIZE)
  678: 	    len = IN_ADDR_SIZE;
  679:       
  680: 	  oid2in_addr (offset, len, &addr->prefix);
  681: 
  682: 	  offset += IN_ADDR_SIZE;
  683: 	  offsetlen -= IN_ADDR_SIZE;
  684: 
  685: 	  if (offsetlen > 0)
  686: 	    addr->prefixlen = *offset;
  687: 	  else
  688: 	    addr->prefixlen = len * 8;
  689: 
  690: 	  rn = bgp_node_get (bgp->rib[AFI_IP][SAFI_UNICAST],
  691: 			       (struct prefix *) addr);
  692: 
  693: 	  offset++;
  694: 	  offsetlen--;
  695: 	}
  696: 
  697:       if (offsetlen > 0)
  698: 	{
  699: 	  len = offsetlen;
  700: 	  if (len > IN_ADDR_SIZE)
  701: 	    len = IN_ADDR_SIZE;
  702: 
  703: 	  oid2in_addr (offset, len, &paddr);
  704: 	}
  705:       else
  706: 	paddr.s_addr = 0;
  707: 
  708:       if (! rn)
  709: 	return NULL;
  710: 
  711:       do
  712: 	{
  713: 	  min = NULL;
  714: 
  715: 	  for (binfo = rn->info; binfo; binfo = binfo->next)
  716: 	    {
  717: 	      if (binfo->peer->su.sin.sin_family == AF_INET
  718: 		  && ntohl (paddr.s_addr) 
  719: 		  < ntohl (binfo->peer->su.sin.sin_addr.s_addr))
  720: 		{
  721: 		  if (min)
  722: 		    {
  723: 		      if (ntohl (binfo->peer->su.sin.sin_addr.s_addr) 
  724: 			  < ntohl (min->peer->su.sin.sin_addr.s_addr))
  725: 			min = binfo;
  726: 		    }
  727: 		  else
  728: 		    min = binfo;
  729: 		}
  730: 	    }
  731: 
  732: 	  if (min)
  733: 	    {
  734: 	      *length = v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
  735: 
  736: 	      offset = name + v->namelen;
  737: 	      oid_copy_addr (offset, &rn->p.u.prefix4, IN_ADDR_SIZE);
  738: 	      offset += IN_ADDR_SIZE;
  739: 	      *offset = rn->p.prefixlen;
  740: 	      offset++;
  741: 	      oid_copy_addr (offset, &min->peer->su.sin.sin_addr, 
  742: 			     IN_ADDR_SIZE);
  743: 	      addr->prefix = rn->p.u.prefix4;
  744: 	      addr->prefixlen = rn->p.prefixlen;
  745: 
  746: 	      bgp_unlock_node (rn);
  747: 
  748: 	      return min;
  749: 	    }
  750: 
  751: 	  paddr.s_addr = 0;
  752: 	}
  753:       while ((rn = bgp_route_next (rn)) != NULL);
  754:     }
  755:   return NULL;
  756: }
  757: 
  758: static u_char *
  759: bgp4PathAttrTable (struct variable *v, oid name[], size_t *length,
  760: 		   int exact, size_t *var_len, WriteMethod **write_method)
  761: {
  762:   struct bgp *bgp;
  763:   struct bgp_info *binfo;
  764:   struct prefix_ipv4 addr;
  765:   
  766:   bgp = bgp_get_default ();
  767:   if (! bgp)
  768:     return NULL;
  769: 
  770:   if (smux_header_table(v, name, length, exact, var_len, write_method)
  771:       == MATCH_FAILED)
  772:     return NULL;
  773:   memset (&addr, 0, sizeof (struct prefix_ipv4));
  774: 
  775:   binfo = bgp4PathAttrLookup (v, name, length, bgp, &addr, exact);
  776:   if (! binfo)
  777:     return NULL;
  778: 
  779:   switch (v->magic)
  780:     {
  781:     case BGP4PATHATTRPEER:	/* 1 */
  782:       return SNMP_IPADDRESS (binfo->peer->su.sin.sin_addr);
  783:       break;
  784:     case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
  785:       return SNMP_INTEGER (addr.prefixlen);
  786:       break;
  787:     case BGP4PATHATTRIPADDRPREFIX: /* 3 */
  788:       return SNMP_IPADDRESS (addr.prefix);
  789:       break;
  790:     case BGP4PATHATTRORIGIN:	/* 4 */
  791:       return SNMP_INTEGER (binfo->attr->origin);
  792:       break;
  793:     case BGP4PATHATTRASPATHSEGMENT: /* 5 */
  794:       return aspath_snmp_pathseg (binfo->attr->aspath, var_len);
  795:       break;
  796:     case BGP4PATHATTRNEXTHOP:	/* 6 */
  797:       return SNMP_IPADDRESS (binfo->attr->nexthop);
  798:       break;
  799:     case BGP4PATHATTRMULTIEXITDISC: /* 7 */
  800:       return SNMP_INTEGER (binfo->attr->med);
  801:       break;
  802:     case BGP4PATHATTRLOCALPREF:	/* 8 */
  803:       return SNMP_INTEGER (binfo->attr->local_pref);
  804:       break;
  805:     case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
  806:       return SNMP_INTEGER (1);
  807:       break;
  808:     case BGP4PATHATTRAGGREGATORAS: /* 10 */
  809:       if (binfo->attr->extra)
  810:         return SNMP_INTEGER (binfo->attr->extra->aggregator_as);
  811:       else
  812:         return SNMP_INTEGER (0);
  813:       break;
  814:     case BGP4PATHATTRAGGREGATORADDR: /* 11 */
  815:       if (binfo->attr->extra)
  816:         return SNMP_IPADDRESS (binfo->attr->extra->aggregator_addr);
  817:       else
  818:         return SNMP_INTEGER (0);
  819:       break;
  820:     case BGP4PATHATTRCALCLOCALPREF: /* 12 */
  821:       return SNMP_INTEGER (-1);
  822:       break;
  823:     case BGP4PATHATTRBEST:	/* 13 */
  824: #define BGP4_PathAttrBest_false 1
  825: #define BGP4_PathAttrBest_true  2
  826:       if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
  827: 	return SNMP_INTEGER (BGP4_PathAttrBest_true);
  828:       else
  829: 	return SNMP_INTEGER (BGP4_PathAttrBest_false);
  830:       break;
  831:     case BGP4PATHATTRUNKNOWN:	/* 14 */
  832:       *var_len = 0;
  833:       return NULL;
  834:       break;
  835:     }
  836:   return NULL;
  837: }
  838: 
  839: /* BGP Traps. */
  840: struct trap_object bgpTrapList[] =
  841: {
  842:   {3, {3, 1, BGPPEERLASTERROR}},
  843:   {3, {3, 1, BGPPEERSTATE}}
  844: };
  845: 
  846: void
  847: bgpTrapEstablished (struct peer *peer)
  848: {
  849:   int ret;
  850:   struct in_addr addr;
  851:   oid index[sizeof (oid) * IN_ADDR_SIZE];
  852: 
  853:   ret = inet_aton (peer->host, &addr);
  854:   if (ret == 0)
  855:     return;
  856: 
  857:   oid_copy_addr (index, &addr, IN_ADDR_SIZE);
  858: 
  859:   smux_trap (bgp_variables, sizeof bgp_variables / sizeof (struct variable),
  860: 	     bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid),
  861: 	     bgp_oid, sizeof bgp_oid / sizeof (oid),
  862: 	     index, IN_ADDR_SIZE,
  863: 	     bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
  864: 	     BGPESTABLISHED);
  865: }
  866: 
  867: void
  868: bgpTrapBackwardTransition (struct peer *peer)
  869: {
  870:   int ret;
  871:   struct in_addr addr;
  872:   oid index[sizeof (oid) * IN_ADDR_SIZE];
  873: 
  874:   ret = inet_aton (peer->host, &addr);
  875:   if (ret == 0)
  876:     return;
  877: 
  878:   oid_copy_addr (index, &addr, IN_ADDR_SIZE);
  879: 
  880:   smux_trap (bgp_variables, sizeof bgp_variables / sizeof (struct variable),
  881: 	     bgp_trap_oid, sizeof bgp_trap_oid / sizeof (oid),
  882: 	     bgp_oid, sizeof bgp_oid / sizeof (oid),
  883: 	     index, IN_ADDR_SIZE,
  884: 	     bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
  885: 	     BGPBACKWARDTRANSITION);
  886: }
  887: 
  888: void
  889: bgp_snmp_init (void)
  890: {
  891:   smux_init (bm->master);
  892:   REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
  893: }
  894: #endif /* HAVE_SNMP */

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