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

网络

开发平台:

Unix_Linux

  1. /* RIP SNMP support
  2.  * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
  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. #ifdef HAVE_SNMP
  23. #ifdef HAVE_NETSNMP
  24. #include <net-snmp/net-snmp-config.h>
  25. #endif /* HAVE_NETSNMP */
  26. #include <asn1.h>
  27. #include <snmp.h>
  28. #include <snmp_impl.h>
  29. #include "if.h"
  30. #include "log.h"
  31. #include "prefix.h"
  32. #include "command.h"
  33. #include "table.h"
  34. #include "smux.h"
  35. #include "ripd/ripd.h"
  36. /* RIPv2-MIB. */
  37. #define RIPV2MIB 1,3,6,1,2,1,23
  38. /* Zebra enterprise RIP MIB.  This variable is used for register
  39.    RIPv2-MIB to SNMP agent under SMUX protocol.  */
  40. #define RIPDOID 1,3,6,1,4,1,3317,1,2,3
  41. /* RIPv2-MIB rip2Globals values. */
  42. #define RIP2GLOBALROUTECHANGES  1
  43. #define RIP2GLOBALQUERIES       2
  44. /* RIPv2-MIB rip2IfStatEntry. */
  45. #define RIP2IFSTATENTRY         1
  46. /* RIPv2-MIB rip2IfStatTable. */
  47. #define RIP2IFSTATADDRESS       1
  48. #define RIP2IFSTATRCVBADPACKETS 2
  49. #define RIP2IFSTATRCVBADROUTES  3
  50. #define RIP2IFSTATSENTUPDATES   4
  51. #define RIP2IFSTATSTATUS        5
  52. /* RIPv2-MIB rip2IfConfTable. */
  53. #define RIP2IFCONFADDRESS       1
  54. #define RIP2IFCONFDOMAIN        2
  55. #define RIP2IFCONFAUTHTYPE      3
  56. #define RIP2IFCONFAUTHKEY       4
  57. #define RIP2IFCONFSEND          5
  58. #define RIP2IFCONFRECEIVE       6
  59. #define RIP2IFCONFDEFAULTMETRIC 7
  60. #define RIP2IFCONFSTATUS        8
  61. #define RIP2IFCONFSRCADDRESS    9
  62. /* RIPv2-MIB rip2PeerTable. */
  63. #define RIP2PEERADDRESS         1
  64. #define RIP2PEERDOMAIN          2
  65. #define RIP2PEERLASTUPDATE      3
  66. #define RIP2PEERVERSION         4
  67. #define RIP2PEERRCVBADPACKETS   5
  68. #define RIP2PEERRCVBADROUTES    6
  69. /* SNMP value hack. */
  70. #define COUNTER     ASN_COUNTER
  71. #define INTEGER     ASN_INTEGER
  72. #define TIMETICKS   ASN_TIMETICKS
  73. #define IPADDRESS   ASN_IPADDRESS
  74. #define STRING      ASN_OCTET_STR
  75. /* Define SNMP local variables. */
  76. SNMP_LOCAL_VARIABLES
  77. /* RIP-MIB instances. */
  78. oid rip_oid [] = { RIPV2MIB };
  79. oid ripd_oid [] = { RIPDOID };
  80. /* Interface cache table sorted by interface's address. */
  81. struct route_table *rip_ifaddr_table;
  82. /* Hook functions. */
  83. static u_char *rip2Globals ();
  84. static u_char *rip2IfStatEntry ();
  85. static u_char *rip2IfConfAddress ();
  86. static u_char *rip2PeerTable ();
  87. struct variable rip_variables[] = 
  88. {
  89.   /* RIP Global Counters. */
  90.   {RIP2GLOBALROUTECHANGES,    COUNTER, RONLY, rip2Globals,
  91.    2, {1, 1}},
  92.   {RIP2GLOBALQUERIES,         COUNTER, RONLY, rip2Globals,
  93.    2, {1, 2}},
  94.   /* RIP Interface Tables. */
  95.   {RIP2IFSTATADDRESS,         IPADDRESS, RONLY, rip2IfStatEntry,
  96.    3, {2, 1, 1}},
  97.   {RIP2IFSTATRCVBADPACKETS,   COUNTER, RONLY, rip2IfStatEntry,
  98.    3, {2, 1, 2}},
  99.   {RIP2IFSTATRCVBADROUTES,    COUNTER, RONLY, rip2IfStatEntry,
  100.    3, {2, 1, 3}},
  101.   {RIP2IFSTATSENTUPDATES,     COUNTER, RONLY, rip2IfStatEntry,
  102.    3, {2, 1, 4}},
  103.   {RIP2IFSTATSTATUS,          COUNTER, RWRITE, rip2IfStatEntry,
  104.    3, {2, 1, 5}},
  105.   {RIP2IFCONFADDRESS,         IPADDRESS, RONLY, rip2IfConfAddress,
  106.    /* RIP Interface Configuration Table. */
  107.    3, {3, 1, 1}},
  108.   {RIP2IFCONFDOMAIN,          STRING, RONLY, rip2IfConfAddress,
  109.    3, {3, 1, 2}},
  110.   {RIP2IFCONFAUTHTYPE,        COUNTER, RONLY, rip2IfConfAddress,
  111.    3, {3, 1, 3}},
  112.   {RIP2IFCONFAUTHKEY,         STRING, RONLY, rip2IfConfAddress,
  113.    3, {3, 1, 4}},
  114.   {RIP2IFCONFSEND,            COUNTER, RONLY, rip2IfConfAddress,
  115.    3, {3, 1, 5}},
  116.   {RIP2IFCONFRECEIVE,         COUNTER, RONLY, rip2IfConfAddress,
  117.    3, {3, 1, 6}},
  118.   {RIP2IFCONFDEFAULTMETRIC,   COUNTER, RONLY, rip2IfConfAddress,
  119.    3, {3, 1, 7}},
  120.   {RIP2IFCONFSTATUS,          COUNTER, RONLY, rip2IfConfAddress,
  121.    3, {3, 1, 8}},
  122.   {RIP2IFCONFSRCADDRESS,      IPADDRESS, RONLY, rip2IfConfAddress,
  123.    3, {3, 1, 9}},
  124.   {RIP2PEERADDRESS,           IPADDRESS, RONLY, rip2PeerTable,
  125.    /* RIP Peer Table. */
  126.    3, {4, 1, 1}},
  127.   {RIP2PEERDOMAIN,            INTEGER, RONLY, rip2PeerTable,
  128.    3, {4, 1, 2}},
  129.   {RIP2PEERLASTUPDATE,        TIMETICKS, RONLY, rip2PeerTable,
  130.    3, {4, 1, 3}},
  131.   {RIP2PEERVERSION,           INTEGER, RONLY, rip2PeerTable,
  132.    3, {4, 1, 4}},
  133.   {RIP2PEERRCVBADPACKETS,     COUNTER, RONLY, rip2PeerTable,
  134.    3, {4, 1, 5}},
  135.   {RIP2PEERRCVBADROUTES,      COUNTER, RONLY, rip2PeerTable,
  136.    3, {4, 1, 6}}
  137. };
  138. static u_char *
  139. rip2Globals (struct variable *v, oid name[], size_t *length,
  140.      int exact, size_t *var_len, WriteMethod **write_method)
  141. {
  142.   if (smux_header_generic(v, name, length, exact, var_len, write_method)
  143.       == MATCH_FAILED)
  144.     return NULL;
  145.   /* Retrun global counter. */
  146.   switch (v->magic)
  147.     {
  148.     case RIP2GLOBALROUTECHANGES:
  149.       return SNMP_INTEGER (rip_global_route_changes);
  150.       break;
  151.     case RIP2GLOBALQUERIES:
  152.       return SNMP_INTEGER (rip_global_queries);
  153.       break;
  154.     default:
  155.       return NULL;
  156.       break;
  157.     }
  158.   return NULL;
  159. }
  160. void
  161. rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
  162. {
  163.   struct prefix *p;
  164.   struct route_node *rn;
  165.   p = ifc->address;
  166.   if (p->family != AF_INET)
  167.     return;
  168.   rn = route_node_get (rip_ifaddr_table, p);
  169.   rn->info = ifp;
  170. }
  171. void
  172. rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
  173. {
  174.   struct prefix *p;
  175.   struct route_node *rn;
  176.   struct interface *i;
  177.   p = ifc->address;
  178.   if (p->family != AF_INET)
  179.     return;
  180.   rn = route_node_lookup (rip_ifaddr_table, p);
  181.   if (! rn)
  182.     return;
  183.   i = rn->info;
  184.   if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
  185.     {
  186.       rn->info = NULL;
  187.       route_unlock_node (rn);
  188.       route_unlock_node (rn);
  189.     }
  190. }
  191. struct interface *
  192. rip_ifaddr_lookup_next (struct in_addr *addr)
  193. {
  194.   struct prefix_ipv4 p;
  195.   struct route_node *rn;
  196.   struct interface *ifp;
  197.   p.family = AF_INET;
  198.   p.prefixlen = IPV4_MAX_BITLEN;
  199.   p.prefix = *addr;
  200.   rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
  201.   for (rn = route_next (rn); rn; rn = route_next (rn))
  202.     if (rn->info)
  203.       break;
  204.   if (rn && rn->info)
  205.     {
  206.       ifp = rn->info;
  207.       *addr = rn->p.u.prefix4;
  208.       route_unlock_node (rn);
  209.       return ifp;
  210.     }
  211.   return NULL;
  212. }
  213. static struct interface *
  214. rip2IfLookup (struct variable *v, oid name[], size_t *length, 
  215.       struct in_addr *addr, int exact)
  216. {
  217.   int len;
  218.   struct interface *ifp;
  219.   
  220.   if (exact)
  221.     {
  222.       /* Check the length. */
  223.       if (*length - v->namelen != sizeof (struct in_addr))
  224. return NULL;
  225.       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  226.       return if_lookup_exact_address (*addr);
  227.     }
  228.   else
  229.     {
  230.       len = *length - v->namelen;
  231.       if (len > 4) len = 4;
  232.       oid2in_addr (name + v->namelen, len, addr);
  233.       ifp = rip_ifaddr_lookup_next (addr);
  234.       if (ifp == NULL)
  235. return NULL;
  236.       oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
  237.       *length = v->namelen + sizeof (struct in_addr);
  238.       return ifp;
  239.     }
  240.   return NULL;
  241. }
  242. static struct rip_peer *
  243. rip2PeerLookup (struct variable *v, oid name[], size_t *length, 
  244. struct in_addr *addr, int exact)
  245. {
  246.   int len;
  247.   struct rip_peer *peer;
  248.   
  249.   if (exact)
  250.     {
  251.       /* Check the length. */
  252.       if (*length - v->namelen != sizeof (struct in_addr) + 1)
  253. return NULL;
  254.       oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
  255.       peer = rip_peer_lookup (addr);
  256.       if (peer->domain == name[v->namelen + sizeof (struct in_addr)])
  257. return peer;
  258.       return NULL;
  259.     }
  260.   else
  261.     {
  262.       len = *length - v->namelen;
  263.       if (len > 4) len = 4;
  264.       oid2in_addr (name + v->namelen, len, addr);
  265.       len = *length - v->namelen;
  266.       peer = rip_peer_lookup (addr);
  267.       if (peer)
  268. {
  269.   if ((len < sizeof (struct in_addr) + 1) ||
  270.       (peer->domain > name[v->namelen + sizeof (struct in_addr)]))
  271.     {
  272.       oid_copy_addr (name + v->namelen, &peer->addr,
  273.      sizeof (struct in_addr));
  274.       name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  275.       *length = sizeof (struct in_addr) + v->namelen + 1;
  276.       return peer;
  277.     }
  278.         } 
  279.       peer = rip_peer_lookup_next (addr);
  280.       if (! peer)
  281. return NULL;
  282.       oid_copy_addr (name + v->namelen, &peer->addr,
  283.      sizeof (struct in_addr));
  284.       name[v->namelen + sizeof (struct in_addr)] = peer->domain;
  285.       *length = sizeof (struct in_addr) + v->namelen + 1;
  286.       return peer;
  287.     }
  288.   return NULL;
  289. }
  290. static u_char *
  291. rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
  292.          int exact, size_t *var_len, WriteMethod **write_method)
  293. {
  294.   struct interface *ifp;
  295.   struct rip_interface *ri;
  296.   static struct in_addr addr;
  297.   static long valid = SNMP_VALID;
  298.   memset (&addr, 0, sizeof (struct in_addr));
  299.   
  300.   /* Lookup interface. */
  301.   ifp = rip2IfLookup (v, name, length, &addr, exact);
  302.   if (! ifp)
  303.     return NULL;
  304.   /* Fetch rip_interface information. */
  305.   ri = ifp->info;
  306.   switch (v->magic)
  307.     {
  308.     case RIP2IFSTATADDRESS:
  309.       return SNMP_IPADDRESS (addr);
  310.       break;
  311.     case RIP2IFSTATRCVBADPACKETS:
  312.       *var_len = sizeof (long);
  313.       return (u_char *) &ri->recv_badpackets;
  314.     case RIP2IFSTATRCVBADROUTES:
  315.       *var_len = sizeof (long);
  316.       return (u_char *) &ri->recv_badroutes;
  317.     case RIP2IFSTATSENTUPDATES:
  318.       *var_len = sizeof (long);
  319.       return (u_char *) &ri->sent_updates;
  320.     case RIP2IFSTATSTATUS:
  321.       *var_len = sizeof (long);
  322.       v->type = ASN_INTEGER;
  323.       return (u_char *) &valid;
  324.     default:
  325.       return NULL;
  326.     }
  327.   return NULL;
  328. }
  329. static long
  330. rip2IfConfSend (struct rip_interface *ri)
  331. {
  332. #define doNotSend       1
  333. #define ripVersion1     2
  334. #define rip1Compatible  3
  335. #define ripVersion2     4
  336. #define ripV1Demand     5
  337. #define ripV2Demand     6
  338.   if (! ri->running)
  339.     return doNotSend;
  340.     
  341.   if (ri->ri_send & RIPv2)
  342.     return ripVersion2;
  343.   else if (ri->ri_send & RIPv1)
  344.     return ripVersion1;
  345.   else if (rip)
  346.     {
  347.       if (rip->version == RIPv2)
  348. return ripVersion2;
  349.       else if (rip->version == RIPv1)
  350. return ripVersion1;
  351.     }
  352.   return doNotSend;
  353. }
  354. static long
  355. rip2IfConfReceive (struct rip_interface *ri)
  356. {
  357. #define rip1            1
  358. #define rip2            2
  359. #define rip1OrRip2      3
  360. #define doNotReceive    4
  361.   if (! ri->running)
  362.     return doNotReceive;
  363.   if (ri->ri_receive == RI_RIP_VERSION_1_AND_2)
  364.     return rip1OrRip2;
  365.   else if (ri->ri_receive & RIPv2)
  366.     return ripVersion2;
  367.   else if (ri->ri_receive & RIPv1)
  368.     return ripVersion1;
  369.   else
  370.     return doNotReceive;
  371. }
  372. static u_char *
  373. rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
  374.            int exact, size_t *val_len, WriteMethod **write_method)
  375. {
  376.   static struct in_addr addr;
  377.   static long valid = SNMP_INVALID;
  378.   static long domain = 0;
  379.   static long config = 0;
  380.   static u_int auth = 0;
  381.   struct interface *ifp;
  382.   struct rip_interface *ri;
  383.   memset (&addr, 0, sizeof (struct in_addr));
  384.   
  385.   /* Lookup interface. */
  386.   ifp = rip2IfLookup (v, name, length, &addr, exact);
  387.   if (! ifp)
  388.     return NULL;
  389.   /* Fetch rip_interface information. */
  390.   ri = ifp->info;
  391.   switch (v->magic)
  392.     {
  393.     case RIP2IFCONFADDRESS:
  394.       *val_len = sizeof (struct in_addr);
  395.       return (u_char *) &addr;
  396.     case RIP2IFCONFDOMAIN:
  397.       *val_len = 2;
  398.       return (u_char *) &domain;
  399.     case RIP2IFCONFAUTHTYPE:
  400.       auth = ri->auth_type;
  401.       *val_len = sizeof (long);
  402.       v->type = ASN_INTEGER;
  403.       return (u_char *)&auth;
  404.     case RIP2IFCONFAUTHKEY:
  405.       *val_len = 0;
  406.       return (u_char *) &domain;
  407.     case RIP2IFCONFSEND:
  408.       config = rip2IfConfSend (ri);
  409.       *val_len = sizeof (long);
  410.       v->type = ASN_INTEGER;
  411.       return (u_char *) &config;
  412.     case RIP2IFCONFRECEIVE:
  413.       config = rip2IfConfReceive (ri);
  414.       *val_len = sizeof (long);
  415.       v->type = ASN_INTEGER;
  416.       return (u_char *) &config;
  417.     case RIP2IFCONFDEFAULTMETRIC:
  418.       *val_len = sizeof (long);
  419.       v->type = ASN_INTEGER;
  420.       return (u_char *) &ifp->metric;
  421.     case RIP2IFCONFSTATUS:
  422.       *val_len = sizeof (long);
  423.       v->type = ASN_INTEGER;
  424.       return (u_char *) &valid;
  425.     case RIP2IFCONFSRCADDRESS:
  426.       *val_len = sizeof (struct in_addr);
  427.       return (u_char *) &addr;
  428.     default:
  429.       return NULL;
  430.     }
  431.   return NULL;
  432. }
  433. static u_char *
  434. rip2PeerTable (struct variable *v, oid name[], size_t *length,
  435.        int exact, size_t *val_len, WriteMethod **write_method)
  436. {
  437.   static struct in_addr addr;
  438.   static int version;
  439.   static time_t uptime;
  440.   struct rip_peer *peer;
  441.   memset (&addr, 0, sizeof (struct in_addr));
  442.   
  443.   /* Lookup interface. */
  444.   peer = rip2PeerLookup (v, name, length, &addr, exact);
  445.   if (! peer)
  446.     return NULL;
  447.   switch (v->magic)
  448.     {
  449.     case RIP2PEERADDRESS:
  450.       *val_len = sizeof (struct in_addr);
  451.       return (u_char *) &peer->addr;
  452.     case RIP2PEERDOMAIN:
  453.       *val_len = sizeof (int);
  454.       return (u_char *) &peer->domain;
  455.     case RIP2PEERLASTUPDATE:
  456.       *val_len = sizeof (time_t);
  457.       uptime = peer->uptime;
  458.       return (u_char *) &uptime;
  459.     case RIP2PEERVERSION:
  460.       *val_len = sizeof (int);
  461.       version = peer->version;
  462.       return (u_char *) &version;
  463.     case RIP2PEERRCVBADPACKETS:
  464.       *val_len = sizeof (int);
  465.       return (u_char *) &peer->recv_badpackets;
  466.     case RIP2PEERRCVBADROUTES:
  467.       *val_len = sizeof (int);
  468.       return (u_char *) &peer->recv_badroutes;
  469.     default:
  470.       return NULL;
  471.     }
  472.   return NULL;
  473. }
  474. /* Register RIPv2-MIB. */
  475. void
  476. rip_snmp_init ()
  477. {
  478.   rip_ifaddr_table = route_table_init ();
  479.   smux_init (ripd_oid, sizeof (ripd_oid) / sizeof (oid));
  480.   REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
  481.   smux_start ();
  482. }
  483. #endif /* HAVE_SNMP */