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

网络

开发平台:

Unix_Linux

  1. /* FIB SNMP.
  2.  * Copyright (C) 1999 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. #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 "smux.h"
  34. #include "table.h"
  35. #include "zebra/rib.h"
  36. #define IPFWMIB 1,3,6,1,2,1,4,24
  37. #define ZEBRAOID 1,3,6,1,4,1,3317,1,2,1
  38. /* ipForwardTable */
  39. #define IPFORWARDDEST                         1
  40. #define IPFORWARDMASK                         2
  41. #define IPFORWARDPOLICY                       3
  42. #define IPFORWARDNEXTHOP                      4
  43. #define IPFORWARDIFINDEX                      5
  44. #define IPFORWARDTYPE                         6
  45. #define IPFORWARDPROTO                        7
  46. #define IPFORWARDAGE                          8
  47. #define IPFORWARDINFO                         9
  48. #define IPFORWARDNEXTHOPAS                   10
  49. #define IPFORWARDMETRIC1                     11
  50. #define IPFORWARDMETRIC2                     12
  51. #define IPFORWARDMETRIC3                     13
  52. #define IPFORWARDMETRIC4                     14
  53. #define IPFORWARDMETRIC5                     15
  54. /* ipCidrRouteTable */
  55. #define IPCIDRROUTEDEST                       1
  56. #define IPCIDRROUTEMASK                       2
  57. #define IPCIDRROUTETOS                        3
  58. #define IPCIDRROUTENEXTHOP                    4
  59. #define IPCIDRROUTEIFINDEX                    5
  60. #define IPCIDRROUTETYPE                       6
  61. #define IPCIDRROUTEPROTO                      7
  62. #define IPCIDRROUTEAGE                        8
  63. #define IPCIDRROUTEINFO                       9
  64. #define IPCIDRROUTENEXTHOPAS                 10
  65. #define IPCIDRROUTEMETRIC1                   11
  66. #define IPCIDRROUTEMETRIC2                   12
  67. #define IPCIDRROUTEMETRIC3                   13
  68. #define IPCIDRROUTEMETRIC4                   14
  69. #define IPCIDRROUTEMETRIC5                   15
  70. #define IPCIDRROUTESTATUS                    16
  71. #define INTEGER32 ASN_INTEGER
  72. #define GAUGE32 ASN_GAUGE
  73. #define ENUMERATION ASN_INTEGER
  74. #define ROWSTATUS ASN_INTEGER
  75. #define IPADDRESS ASN_IPADDRESS
  76. #define OBJECTIDENTIFIER ASN_OBJECT_ID
  77. oid ipfw_oid [] = { IPFWMIB };
  78. oid zebra_oid [] = { ZEBRAOID };
  79. /* Hook functions. */
  80. u_char * ipFwNumber ();
  81. u_char * ipFwTable ();
  82. u_char * ipCidrNumber ();
  83. u_char * ipCidrTable ();
  84. struct variable zebra_variables[] = 
  85.   {
  86.     {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
  87.     {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
  88.     {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
  89.     {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
  90.     {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
  91.     {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
  92.     {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
  93.     {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
  94.     {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
  95.     {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
  96.     {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
  97.     {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
  98.     {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
  99.     {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
  100.     {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
  101.     {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
  102.     {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
  103.     {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
  104.     {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
  105.     {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
  106.     {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
  107.     {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
  108.     {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
  109.     {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
  110.     {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
  111.     {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
  112.     {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
  113.     {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
  114.     {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
  115.     {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
  116.     {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
  117.     {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
  118.     {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
  119.   };
  120. u_char *
  121. ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
  122.     int exact, size_t *val_len, WriteMethod **write_method)
  123. {
  124.   static int result;
  125.   struct route_table *table;
  126.   struct route_node *rn;
  127.   struct rib *rib;
  128.   if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
  129.     return NULL;
  130.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  131.   if (! table)
  132.     return NULL;
  133.   /* Return number of routing entries. */
  134.   result = 0;
  135.   for (rn = route_top (table); rn; rn = route_next (rn))
  136.     for (rib = rn->info; rib; rib = rib->next)
  137.       result++;
  138.   return (u_char *)&result;
  139. }
  140. u_char *
  141. ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
  142.       int exact, size_t *val_len, WriteMethod **write_method)
  143. {
  144.   static int result;
  145.   struct route_table *table;
  146.   struct route_node *rn;
  147.   struct rib *rib;
  148.   if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
  149.     return NULL;
  150.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  151.   if (! table)
  152.     return 0;
  153.   /* Return number of routing entries. */
  154.   result = 0;
  155.   for (rn = route_top (table); rn; rn = route_next (rn))
  156.     for (rib = rn->info; rib; rib = rib->next)
  157.       result++;
  158.   return (u_char *)&result;
  159. }
  160. int
  161. in_addr_cmp(u_char *p1, u_char *p2)
  162. {
  163.   int i;
  164.   for (i=0; i<4; i++)
  165.     {
  166.       if (*p1 < *p2)
  167.         return -1;
  168.       if (*p1 > *p2)
  169.         return 1;
  170.       p1++; p2++;
  171.     }
  172.   return 0;
  173. }
  174. int 
  175. in_addr_add(u_char *p, int num)
  176. {
  177.   int i, ip0;
  178.   ip0 = *p;
  179.   p += 4;
  180.   for (i = 3; 0 <= i; i--) {
  181.     p--;
  182.     if (*p + num > 255) {
  183.       *p += num;
  184.       num = 1;
  185.     } else {
  186.       *p += num;
  187.       return 1;
  188.     }
  189.   }
  190.   if (ip0 > *p) {
  191.     /* ip + num > 0xffffffff */
  192.     return 0;
  193.   }
  194.   
  195.   return 1;
  196. }
  197. int proto_trans(int type)
  198. {
  199.   switch (type)
  200.     {
  201.     case ZEBRA_ROUTE_SYSTEM:
  202.       return 1; /* other */
  203.     case ZEBRA_ROUTE_KERNEL:
  204.       return 1; /* other */
  205.     case ZEBRA_ROUTE_CONNECT:
  206.       return 2; /* local interface */
  207.     case ZEBRA_ROUTE_STATIC:
  208.       return 3; /* static route */
  209.     case ZEBRA_ROUTE_RIP:
  210.       return 8; /* rip */
  211.     case ZEBRA_ROUTE_RIPNG:
  212.       return 1; /* shouldn't happen */
  213.     case ZEBRA_ROUTE_OSPF:
  214.       return 13; /* ospf */
  215.     case ZEBRA_ROUTE_OSPF6:
  216.       return 1; /* shouldn't happen */
  217.     case ZEBRA_ROUTE_BGP:
  218.       return 14; /* bgp */
  219.     default:
  220.       return 1; /* other */
  221.     }
  222. }
  223. void
  224. check_replace(struct route_node *np2, struct rib *rib2, 
  225.               struct route_node **np, struct rib **rib)
  226. {
  227.   int proto, proto2;
  228.   if (!*np)
  229.     {
  230.       *np = np2;
  231.       *rib = rib2;
  232.       return;
  233.     }
  234.   if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
  235.     return;
  236.   if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
  237.     {
  238.       *np = np2;
  239.       *rib = rib2;
  240.       return;
  241.     }
  242.   proto = proto_trans((*rib)->type);
  243.   proto2 = proto_trans(rib2->type);
  244.   if (proto2 > proto)
  245.     return;
  246.   if (proto2 < proto)
  247.     {
  248.       *np = np2;
  249.       *rib = rib2;
  250.       return;
  251.     }
  252.   if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4, 
  253.                   (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
  254.     return;
  255.   *np = np2;
  256.   *rib = rib2;
  257.   return;
  258. }
  259. void
  260. get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len, 
  261.        int exact, struct route_node **np, struct rib **rib)
  262. {
  263.   struct in_addr dest;
  264.   struct route_table *table;
  265.   struct route_node *np2;
  266.   struct rib *rib2;
  267.   int proto;
  268.   int policy;
  269.   struct in_addr nexthop;
  270.   u_char *pnt;
  271.   int i;
  272.   /* Init index variables */
  273.   pnt = (u_char *) &dest;
  274.   for (i = 0; i < 4; i++)
  275.     *pnt++ = 0;
  276.   pnt = (u_char *) &nexthop;
  277.   for (i = 0; i < 4; i++)
  278.     *pnt++ = 0;
  279.   proto = 0;
  280.   policy = 0;
  281.  
  282.   /* Init return variables */
  283.   *np = NULL;
  284.   *rib = NULL;
  285.   /* Short circuit exact matches of wrong length */
  286.   if (exact && (*objid_len != v->namelen + 10))
  287.     return;
  288.   table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
  289.   if (! table)
  290.     return;
  291.   /* Get INDEX information out of OID.
  292.    * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
  293.    */
  294.   if (*objid_len > v->namelen)
  295.     oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
  296.   if (*objid_len > v->namelen + 4)
  297.     proto = objid[v->namelen + 4];
  298.   if (*objid_len > v->namelen + 5)
  299.     policy = objid[v->namelen + 5];
  300.   if (*objid_len > v->namelen + 6)
  301.     oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
  302.  &nexthop);
  303.   /* Apply GETNEXT on not exact search */
  304.   if (!exact && (*objid_len >= v->namelen + 10))
  305.     {
  306.       if (! in_addr_add((u_char *) &nexthop, 1)) 
  307.         return;
  308.     }
  309.   /* For exact: search matching entry in rib table. */
  310.   if (exact)
  311.     {
  312.       if (policy) /* Not supported (yet?) */
  313.         return;
  314.       for (*np = route_top (table); *np; *np = route_next (*np))
  315. {
  316.   if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
  317.     {
  318.       for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
  319.         {
  320.   if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
  321.    (u_char *)&nexthop))
  322.     if (proto == proto_trans((*rib)->type))
  323.       return;
  324. }
  325.     }
  326. }
  327.       return;
  328.     }
  329.   /* Search next best entry */
  330.   for (np2 = route_top (table); np2; np2 = route_next (np2))
  331.     {
  332.       /* Check destination first */
  333.       if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
  334.         for (rib2 = np2->info; rib2; rib2 = rib2->next)
  335.   check_replace(np2, rib2, np, rib);
  336.       if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
  337.         { /* have to look at each rib individually */
  338.           for (rib2 = np2->info; rib2; rib2 = rib2->next)
  339.     {
  340.       int proto2, policy2;
  341.       proto2 = proto_trans(rib2->type);
  342.       policy2 = 0;
  343.       if ((policy < policy2)
  344.   || ((policy == policy2) && (proto < proto2))
  345.   || ((policy == policy2) && (proto == proto2)
  346.       && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
  347.       (u_char *) &nexthop) >= 0)
  348.       ))
  349. check_replace(np2, rib2, np, rib);
  350.     }
  351. }
  352.     }
  353.   if (!*rib)
  354.     return;
  355.   policy = 0;
  356.   proto = proto_trans((*rib)->type);
  357.   *objid_len = v->namelen + 10;
  358.   pnt = (u_char *) &(*np)->p.u.prefix;
  359.   for (i = 0; i < 4; i++)
  360.     objid[v->namelen + i] = *pnt++;
  361.   objid[v->namelen + 4] = proto;
  362.   objid[v->namelen + 5] = policy;
  363.   {
  364.     struct nexthop *nexthop;
  365.     nexthop = (*rib)->nexthop;
  366.     if (nexthop)
  367.       {
  368. pnt = (u_char *) &nexthop->gate.ipv4;
  369. for (i = 0; i < 4; i++)
  370.   objid[i + v->namelen + 6] = *pnt++;
  371.       }
  372.   }
  373.   return;
  374. }
  375. u_char *
  376. ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
  377.    int exact, size_t *val_len, WriteMethod **write_method)
  378. {
  379.   struct route_node *np;
  380.   struct rib *rib;
  381.   static int result;
  382.   static int resarr[2];
  383.   static struct in_addr netmask;
  384.   struct nexthop *nexthop;
  385.   get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
  386.   if (!np)
  387.     return NULL;
  388.   nexthop = rib->nexthop;
  389.   if (! nexthop)
  390.     return NULL;
  391.   switch (v->magic)
  392.     {
  393.     case IPFORWARDDEST:
  394.       *val_len = 4;
  395.       return &np->p.u.prefix;
  396.       break;
  397.     case IPFORWARDMASK:
  398.       masklen2ip(np->p.prefixlen, &netmask);
  399.       *val_len = 4;
  400.       return (u_char *)&netmask;
  401.       break;
  402.     case IPFORWARDPOLICY:
  403.       result = 0;
  404.       *val_len  = sizeof(int);
  405.       return (u_char *)&result;
  406.       break;
  407.     case IPFORWARDNEXTHOP:
  408.       *val_len = 4;
  409.       return (u_char *)&nexthop->gate.ipv4;
  410.       break;
  411.     case IPFORWARDIFINDEX:
  412.       *val_len = sizeof(int);
  413.       return (u_char *)&nexthop->ifindex;
  414.       break;
  415.     case IPFORWARDTYPE:
  416.       if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  417.   || nexthop->type == NEXTHOP_TYPE_IFNAME)
  418.         result = 3;
  419.       else
  420.         result = 4;
  421.       *val_len  = sizeof(int);
  422.       return (u_char *)&result;
  423.       break;
  424.     case IPFORWARDPROTO:
  425.       result = proto_trans(rib->type);
  426.       *val_len  = sizeof(int);
  427.       return (u_char *)&result;
  428.       break;
  429.     case IPFORWARDAGE:
  430.       result = 0;
  431.       *val_len  = sizeof(int);
  432.       return (u_char *)&result;
  433.       break;
  434.     case IPFORWARDINFO:
  435.       resarr[0] = 0;
  436.       resarr[1] = 0;
  437.       *val_len  = 2 * sizeof(int);
  438.       return (u_char *)resarr;
  439.       break;
  440.     case IPFORWARDNEXTHOPAS:
  441.       result = -1;
  442.       *val_len  = sizeof(int);
  443.       return (u_char *)&result;
  444.       break;
  445.     case IPFORWARDMETRIC1:
  446.       result = 0;
  447.       *val_len  = sizeof(int);
  448.       return (u_char *)&result;
  449.       break;
  450.     case IPFORWARDMETRIC2:
  451.       result = 0;
  452.       *val_len  = sizeof(int);
  453.       return (u_char *)&result;
  454.       break;
  455.     case IPFORWARDMETRIC3:
  456.       result = 0;
  457.       *val_len  = sizeof(int);
  458.       return (u_char *)&result;
  459.       break;
  460.     case IPFORWARDMETRIC4:
  461.       result = 0;
  462.       *val_len  = sizeof(int);
  463.       return (u_char *)&result;
  464.       break;
  465.     case IPFORWARDMETRIC5:
  466.       result = 0;
  467.       *val_len  = sizeof(int);
  468.       return (u_char *)&result;
  469.       break;
  470.     default:
  471.       return NULL;
  472.       break;
  473.     }  
  474.   return NULL;
  475. }
  476. u_char *
  477. ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
  478.      int exact, size_t *val_len, WriteMethod **write_method)
  479. {
  480.   switch (v->magic)
  481.     {
  482.     case IPCIDRROUTEDEST:
  483.       break;
  484.     default:
  485.       return NULL;
  486.       break;
  487.     }  
  488.   return NULL;
  489. }
  490. void
  491. zebra_snmp_init ()
  492. {
  493.   smux_init (zebra_oid, sizeof (zebra_oid) / sizeof (oid));
  494.   REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
  495.   smux_start ();
  496. }
  497. #endif /* HAVE_SNMP */