bgp_snmp.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:24k
源码类别:

网络

开发平台:

Unix_Linux

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