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

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