Annotation of embedaddon/quagga/bgpd/bgp_snmp.c, revision 1.1.1.2

1.1       misho       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 };
1.1.1.2 ! misho     121: oid bgp_trap_oid [] = { BGP4MIB, 0 };
1.1       misho     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: 
1.1.1.2 ! misho     458:   if (smux_header_table(v, name, length, exact, var_len, write_method)
        !           459:       == MATCH_FAILED)
        !           460:     return NULL;
1.1       misho     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: 
1.1.1.2 ! misho     770:   if (smux_header_table(v, name, length, exact, var_len, write_method)
        !           771:       == MATCH_FAILED)
        !           772:     return NULL;
1.1       misho     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: {
1.1.1.2 ! misho     842:   {3, {3, 1, BGPPEERLASTERROR}},
        !           843:   {3, {3, 1, BGPPEERSTATE}}
1.1       misho     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: 
1.1.1.2 ! misho     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),
1.1       misho     862:             index, IN_ADDR_SIZE,
                    863:             bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
1.1.1.2 ! misho     864:             BGPESTABLISHED);
1.1       misho     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: 
1.1.1.2 ! misho     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),
1.1       misho     883:             index, IN_ADDR_SIZE,
                    884:             bgpTrapList, sizeof bgpTrapList / sizeof (struct trap_object),
1.1.1.2 ! misho     885:             BGPBACKWARDTRANSITION);
1.1       misho     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>