route_linux.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:11k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Interface MIB architecture support
  3.  *
  4.  * $Id: route_linux.c,v 1.9.2.1 2005/02/08 21:57:48 nba Exp $
  5.  */
  6. #include <net-snmp/net-snmp-config.h>
  7. #include <net-snmp/net-snmp-includes.h>
  8. #include "mibII/mibII_common.h"
  9. #include <net-snmp/agent/net-snmp-agent-includes.h>
  10. #include <net-snmp/data_access/interface.h>
  11. #include <net-snmp/data_access/route.h>
  12. #include "ip-forward-mib/inetCidrRouteTable/inetCidrRouteTable_constants.h"
  13. #include "if-mib/data_access/interface_ioctl.h"
  14. static int
  15. _type_from_flags(unsigned int flags)
  16. {
  17.     /*
  18.      *  RTF_GATEWAY RTF_UP RTF_DYNAMIC RTF_CACHE
  19.      *  RTF_MODIFIED RTF_EXPIRES RTF_NONEXTHOP
  20.      *  RTF_DYNAMIC RTF_LOCAL RTF_PREFIX_RT
  21.      *
  22.      * xxx: can we distinguish between reject & blackhole?
  23.      */
  24.     if (flags & RTF_UP) {
  25.         if (flags & RTF_GATEWAY)
  26.             return INETCIDRROUTETYPE_REMOTE;
  27.         else /*if (flags & RTF_LOCAL) */
  28.             return INETCIDRROUTETYPE_LOCAL;
  29.     } else 
  30.         return 0; /* route not up */
  31. }
  32. static int
  33. _load_ipv4(netsnmp_container* container, u_long *index )
  34. {
  35.     FILE           *in;
  36.     char            line[256];
  37.     netsnmp_route_entry *entry = NULL;
  38.     char            name[16];
  39.     int             fd;
  40.     DEBUGMSGTL(("access:route:container",
  41.                 "route_container_arch_load ipv4n"));
  42.     netsnmp_assert(NULL != container);
  43.     /*
  44.      * fetch routes from the proc file-system:
  45.      */
  46.     if (!(in = fopen("/proc/net/route", "r"))) {
  47.         snmp_log(LOG_ERR, "cannot open /proc/net/routen");
  48.         return -2;
  49.     }
  50.     /*
  51.      * create socket for ioctls (see NOTE[1], below)
  52.      */
  53.     fd = socket(AF_INET, SOCK_DGRAM, 0);
  54.     if(fd < 0) {
  55.         snmp_log(LOG_ERR, "could not create socketn");
  56.         fclose(in);
  57.         return -2;
  58.     }
  59.     fgets(line, sizeof(line), in); /* skip header */
  60.     while (fgets(line, sizeof(line), in)) {
  61.         char            rtent_name[32];
  62.         int             refcnt, flags, rc;
  63.         uint32_t        dest, nexthop, mask;
  64.         unsigned        use;
  65.         entry = netsnmp_access_route_entry_create();
  66.         /*
  67.          * as with 1.99.14:
  68.          * Iface Dest     GW       Flags RefCnt Use Metric Mask     MTU  Win IRTT
  69.          * eth0  0A0A0A0A 00000000 05    0      0   0      FFFFFFFF 1500 0   0 
  70.          */
  71.         rc = sscanf(line, "%s %x %x %x %u %d %d %x %*d %*d %*dn",
  72.                     rtent_name, &dest, &nexthop,
  73.                     /*
  74.                      * XXX: fix type of the args 
  75.                      */
  76.                     &flags, &refcnt, &use, &entry->rt_metric1,
  77.                     &mask);
  78.         DEBUGMSGTL(("9:access:route:container", "line |%s|n", line));
  79.         if (8 != rc) {
  80.             snmp_log(LOG_ERR,
  81.                      "/proc/net/route data format error (%d!=8), line ==|%s|",
  82.                      rc, line);
  83.             continue;
  84.         }
  85.         /*
  86.          * temporary null terminated name
  87.          */
  88.         strncpy(name, rtent_name, sizeof(name));
  89.         name[ sizeof(name)-1 ] = 0;
  90.         /*
  91.          * don't bother to try and get the ifindex for routes with
  92.          * no interface name.
  93.          * NOTE[1]: normally we'd use netsnmp_access_interface_index_find,
  94.          * but since that will open/close a socket, and we might
  95.          * have a lot of routes, call the ioctl routine directly.
  96.          */
  97.         if ('*' != name[0])
  98.             entry->if_index =
  99.                 netsnmp_access_interface_ioctl_ifindex_get(fd,name);
  100.         /*
  101.          * arbitrary index
  102.          */
  103.         entry->ns_rt_index = ++(*index);
  104. #ifdef USING_IP_FORWARD_MIB_IPCIDRROUTETABLE_IPCIDRROUTETABLE_MODULE
  105.         entry->rt_mask = mask;
  106.         /** entry->rt_tos = XXX; */
  107.         /** rt info ?? */
  108. #endif
  109.         /*
  110.          * copy dest & next hop
  111.          */
  112.         entry->rt_dest_type = INETADDRESSTYPE_IPV4;
  113.         entry->rt_dest_len = 4;
  114.         memcpy(entry->rt_dest, &dest, 4);
  115.         entry->rt_nexthop_type = INETADDRESSTYPE_IPV4;
  116.         entry->rt_nexthop_len = 4;
  117.         memcpy(entry->rt_nexthop, &nexthop, 4);
  118.         /*
  119.          * count bits in mask
  120.          */
  121.         while (0x1 & mask) {
  122.             ++entry->rt_pfx_len;
  123.             mask = mask >> 1;
  124.         }
  125. #ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
  126.         /*
  127.     inetCidrRoutePolicy OBJECT-TYPE 
  128.         SYNTAX     OBJECT IDENTIFIER 
  129.         MAX-ACCESS not-accessible 
  130.         STATUS     current 
  131.         DESCRIPTION 
  132.                "This object is an opaque object without any defined 
  133.                 semantics.  Its purpose is to serve as an additional 
  134.                 index which may delineate between multiple entries to 
  135.                 the same destination.  The value { 0 0 } shall be used 
  136.                 as the default value for this object."
  137.         */
  138.         /*
  139.          * on linux, default routes all look alike, and would have the same
  140.          * indexed based on dest and next hop. So we use our arbitrary index
  141.          * as the policy, to distinguise between them.
  142.          */
  143.         entry->rt_policy = &entry->ns_rt_index;
  144.         entry->rt_policy_len = 1;
  145.         entry->flags |= NETSNMP_ROUTE_ENTRY_POLICY_STATIC;
  146. #endif
  147.         /*
  148.          * get protocol and type from flags
  149.          */
  150.         entry->rt_type = _type_from_flags(flags);
  151.         
  152.         entry->rt_proto = (flags & RTF_DYNAMIC)
  153.             ? IANAIPROUTEPROTOCOL_ICMP : IANAIPROUTEPROTOCOL_LOCAL;
  154.         /*
  155.          * insert into container
  156.          */
  157.         CONTAINER_INSERT(container, entry);
  158.     }
  159.     fclose(in);
  160.     close(fd);
  161.     return 0;
  162. }
  163. #ifdef INET6
  164. static int
  165. _load_ipv6(netsnmp_container* container, u_long *index )
  166. {
  167.     FILE           *in;
  168.     char            line[256];
  169.     netsnmp_route_entry *entry = NULL;
  170.     char            name[16];
  171.     static int      log_open_err = 1;
  172.     DEBUGMSGTL(("access:route:container",
  173.                 "route_container_arch_load ipv6n"));
  174.     netsnmp_assert(NULL != container);
  175.     /*
  176.      * fetch routes from the proc file-system:
  177.      */
  178.     if (!(in = fopen("/proc/net/ipv6_route", "r"))) {
  179.         if (1 == log_open_err) {
  180.             snmp_log(LOG_ERR, "cannot open /proc/net/ipv6_routen");
  181.             log_open_err = 0;
  182.         }
  183.         return -2;
  184.     }
  185.     /*
  186.      * if we turned off logging of open errors, turn it back on now that
  187.      * we have been able to open the file.
  188.      */
  189.     if (0 == log_open_err)
  190.         log_open_err = 1;
  191.     fgets(line,sizeof(line),in); /* skip header */
  192.     while (fgets(line, sizeof(line), in)) {
  193.         char            c_name[9], c_dest[33], c_src[33], c_next[33];
  194.         int             rc;
  195.         unsigned int    dest_pfx, flags;
  196.         size_t          buf_len, buf_offset;
  197.         u_char          *temp_uchar_ptr;
  198.         entry = netsnmp_access_route_entry_create();
  199.         /*
  200.          * based on /usr/src/linux/net/ipv6/route.c, kernel 2.6.7:
  201.          *
  202.          * [        Dest addr /         plen ]
  203.          * fe80000000000000025056fffec00008 80 
  204.          *
  205.          * [ (?subtree) : src addr/plen : 0/0]
  206.          * 00000000000000000000000000000000 00 
  207.          *
  208.          * [        next hop              ][ metric ][ref ctn][ use   ]
  209.          * 00000000000000000000000000000000 00000000 00000000 00000000 
  210.          *
  211.          * [ flags ][dev name]
  212.          * 80200001       lo
  213.          */
  214.         rc = sscanf(line, "%32s %2x %32s %*x %32s %x %*x %*x %x %8sn",
  215.                     c_dest, &dest_pfx, c_src, /*src_pfx,*/ c_next,
  216.                     &entry->rt_metric1, /** ref,*/ /* use, */ &flags, c_name);
  217.         DEBUGMSGTL(("9:access:route:container", "line |%s|n", line));
  218.         if (7 != rc) {
  219.             snmp_log(LOG_ERR,
  220.                      "/proc/net/ipv6_route data format error (%d!=8), "
  221.                      "line ==|%s|", rc, line);
  222.             continue;
  223.         }
  224.         /*
  225.          * temporary null terminated name
  226.          */
  227.         c_name[ sizeof(c_name)-1 ] = 0;
  228.         entry->if_index = se_find_value_in_slist("interfaces", c_name);
  229.         if(SE_DNE == entry->if_index) {
  230.             snmp_log(LOG_ERR,"unknown interface in /proc/net/ipv6_route "
  231.                      "('%s')n", name);
  232.             netsnmp_access_route_entry_free(entry);
  233.             continue;
  234.         }
  235.         /*
  236.          * arbitrary index
  237.          */
  238.         entry->ns_rt_index = ++(*index);
  239. #ifdef USING_IP_FORWARD_MIB_IPCIDRROUTETABLE_IPCIDRROUTETABLE_MODULE
  240.         /** entry->rt_mask = mask; */ /* IPv4 only */
  241.         /** entry->rt_tos = XXX; */
  242.         /** rt info ?? */
  243. #endif
  244.         /*
  245.          * convert hex addresses to binary
  246.          */
  247.         entry->rt_dest_type = INETADDRESSTYPE_IPV6;
  248.         entry->rt_dest_len = 16;
  249.         buf_len = sizeof(entry->rt_dest);
  250.         buf_offset = 0;
  251.         temp_uchar_ptr = entry->rt_dest;
  252.         netsnmp_hex_to_binary(&temp_uchar_ptr, &buf_len, &buf_offset, 0,
  253.                               c_dest, NULL);
  254.         entry->rt_nexthop_type = INETADDRESSTYPE_IPV6;
  255.         entry->rt_nexthop_len = 16;
  256.         buf_len = sizeof(entry->rt_nexthop);
  257.         buf_offset = 0;
  258.         temp_uchar_ptr = entry->rt_nexthop;
  259.         netsnmp_hex_to_binary(&temp_uchar_ptr, &buf_len, &buf_offset, 0,
  260.                               c_next, NULL);
  261.         entry->rt_pfx_len = dest_pfx;
  262. #ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
  263.         /*
  264.     inetCidrRoutePolicy OBJECT-TYPE 
  265.         SYNTAX     OBJECT IDENTIFIER 
  266.         MAX-ACCESS not-accessible 
  267.         STATUS     current 
  268.         DESCRIPTION 
  269.                "This object is an opaque object without any defined 
  270.                 semantics.  Its purpose is to serve as an additional 
  271.                 index which may delineate between multiple entries to 
  272.                 the same destination.  The value { 0 0 } shall be used 
  273.                 as the default value for this object."
  274.         */
  275.         /*
  276.          * on linux, default routes all look alike, and would have the same
  277.          * indexed based on dest and next hop. So we use our arbitrary index
  278.          * as the policy, to distinguise between them.
  279.          */
  280.         entry->rt_policy = &entry->ns_rt_index;
  281.         entry->rt_policy_len = 1;
  282.         entry->flags |= NETSNMP_ROUTE_ENTRY_POLICY_STATIC;
  283. #endif
  284.         /*
  285.          * get protocol and type from flags
  286.          */
  287.         entry->rt_type = _type_from_flags(flags);
  288.         
  289.         entry->rt_proto = (flags & RTF_DYNAMIC)
  290.             ? IANAIPROUTEPROTOCOL_ICMP : IANAIPROUTEPROTOCOL_LOCAL;
  291.         /*
  292.          * insert into container
  293.          */
  294.         CONTAINER_INSERT(container, entry);
  295.     }
  296.     fclose(in);
  297.     return 0;
  298. }
  299. #endif
  300. /** arch specific load
  301.  * @internal
  302.  *
  303.  * @retval  0 success
  304.  * @retval -1 no container specified
  305.  * @retval -2 could not open data file
  306.  */
  307. int
  308. netsnmp_access_route_container_arch_load(netsnmp_container* container,
  309.                                          u_int load_flags)
  310. {
  311.     u_long          count = 0;
  312.     int             rc;
  313.     DEBUGMSGTL(("access:route:container",
  314.                 "route_container_arch_load (flags %p)n", load_flags));
  315.     if (NULL == container) {
  316.         snmp_log(LOG_ERR, "no container specified/found for access_routen");
  317.         return -1;
  318.     }
  319.     rc = _load_ipv4(container, &count);
  320.     
  321. #ifdef INET6
  322.     if((0 != rc) || (load_flags & NETSNMP_ACCESS_ROUTE_LOAD_IPV4_ONLY))
  323.         return rc;
  324.     /*
  325.      * load ipv6. ipv6 module might not be loaded,
  326.      * so ignore -2 err (file not found)
  327.      */
  328.     rc = _load_ipv6(container, &count);
  329.     if (-2 == rc)
  330.         rc = 0;
  331. #endif
  332.     return rc;
  333. }