route_linux.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:11k
- /*
- * Interface MIB architecture support
- *
- * $Id: route_linux.c,v 1.9.2.1 2005/02/08 21:57:48 nba Exp $
- */
- #include <net-snmp/net-snmp-config.h>
- #include <net-snmp/net-snmp-includes.h>
- #include "mibII/mibII_common.h"
- #include <net-snmp/agent/net-snmp-agent-includes.h>
- #include <net-snmp/data_access/interface.h>
- #include <net-snmp/data_access/route.h>
- #include "ip-forward-mib/inetCidrRouteTable/inetCidrRouteTable_constants.h"
- #include "if-mib/data_access/interface_ioctl.h"
- static int
- _type_from_flags(unsigned int flags)
- {
- /*
- * RTF_GATEWAY RTF_UP RTF_DYNAMIC RTF_CACHE
- * RTF_MODIFIED RTF_EXPIRES RTF_NONEXTHOP
- * RTF_DYNAMIC RTF_LOCAL RTF_PREFIX_RT
- *
- * xxx: can we distinguish between reject & blackhole?
- */
- if (flags & RTF_UP) {
- if (flags & RTF_GATEWAY)
- return INETCIDRROUTETYPE_REMOTE;
- else /*if (flags & RTF_LOCAL) */
- return INETCIDRROUTETYPE_LOCAL;
- } else
- return 0; /* route not up */
- }
- static int
- _load_ipv4(netsnmp_container* container, u_long *index )
- {
- FILE *in;
- char line[256];
- netsnmp_route_entry *entry = NULL;
- char name[16];
- int fd;
- DEBUGMSGTL(("access:route:container",
- "route_container_arch_load ipv4n"));
- netsnmp_assert(NULL != container);
- /*
- * fetch routes from the proc file-system:
- */
- if (!(in = fopen("/proc/net/route", "r"))) {
- snmp_log(LOG_ERR, "cannot open /proc/net/routen");
- return -2;
- }
- /*
- * create socket for ioctls (see NOTE[1], below)
- */
- fd = socket(AF_INET, SOCK_DGRAM, 0);
- if(fd < 0) {
- snmp_log(LOG_ERR, "could not create socketn");
- fclose(in);
- return -2;
- }
- fgets(line, sizeof(line), in); /* skip header */
- while (fgets(line, sizeof(line), in)) {
- char rtent_name[32];
- int refcnt, flags, rc;
- uint32_t dest, nexthop, mask;
- unsigned use;
- entry = netsnmp_access_route_entry_create();
- /*
- * as with 1.99.14:
- * Iface Dest GW Flags RefCnt Use Metric Mask MTU Win IRTT
- * eth0 0A0A0A0A 00000000 05 0 0 0 FFFFFFFF 1500 0 0
- */
- rc = sscanf(line, "%s %x %x %x %u %d %d %x %*d %*d %*dn",
- rtent_name, &dest, &nexthop,
- /*
- * XXX: fix type of the args
- */
- &flags, &refcnt, &use, &entry->rt_metric1,
- &mask);
- DEBUGMSGTL(("9:access:route:container", "line |%s|n", line));
- if (8 != rc) {
- snmp_log(LOG_ERR,
- "/proc/net/route data format error (%d!=8), line ==|%s|",
- rc, line);
- continue;
- }
- /*
- * temporary null terminated name
- */
- strncpy(name, rtent_name, sizeof(name));
- name[ sizeof(name)-1 ] = 0;
- /*
- * don't bother to try and get the ifindex for routes with
- * no interface name.
- * NOTE[1]: normally we'd use netsnmp_access_interface_index_find,
- * but since that will open/close a socket, and we might
- * have a lot of routes, call the ioctl routine directly.
- */
- if ('*' != name[0])
- entry->if_index =
- netsnmp_access_interface_ioctl_ifindex_get(fd,name);
- /*
- * arbitrary index
- */
- entry->ns_rt_index = ++(*index);
- #ifdef USING_IP_FORWARD_MIB_IPCIDRROUTETABLE_IPCIDRROUTETABLE_MODULE
- entry->rt_mask = mask;
- /** entry->rt_tos = XXX; */
- /** rt info ?? */
- #endif
- /*
- * copy dest & next hop
- */
- entry->rt_dest_type = INETADDRESSTYPE_IPV4;
- entry->rt_dest_len = 4;
- memcpy(entry->rt_dest, &dest, 4);
- entry->rt_nexthop_type = INETADDRESSTYPE_IPV4;
- entry->rt_nexthop_len = 4;
- memcpy(entry->rt_nexthop, &nexthop, 4);
- /*
- * count bits in mask
- */
- while (0x1 & mask) {
- ++entry->rt_pfx_len;
- mask = mask >> 1;
- }
- #ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
- /*
- inetCidrRoutePolicy OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- MAX-ACCESS not-accessible
- STATUS current
- DESCRIPTION
- "This object is an opaque object without any defined
- semantics. Its purpose is to serve as an additional
- index which may delineate between multiple entries to
- the same destination. The value { 0 0 } shall be used
- as the default value for this object."
- */
- /*
- * on linux, default routes all look alike, and would have the same
- * indexed based on dest and next hop. So we use our arbitrary index
- * as the policy, to distinguise between them.
- */
- entry->rt_policy = &entry->ns_rt_index;
- entry->rt_policy_len = 1;
- entry->flags |= NETSNMP_ROUTE_ENTRY_POLICY_STATIC;
- #endif
- /*
- * get protocol and type from flags
- */
- entry->rt_type = _type_from_flags(flags);
-
- entry->rt_proto = (flags & RTF_DYNAMIC)
- ? IANAIPROUTEPROTOCOL_ICMP : IANAIPROUTEPROTOCOL_LOCAL;
- /*
- * insert into container
- */
- CONTAINER_INSERT(container, entry);
- }
- fclose(in);
- close(fd);
- return 0;
- }
- #ifdef INET6
- static int
- _load_ipv6(netsnmp_container* container, u_long *index )
- {
- FILE *in;
- char line[256];
- netsnmp_route_entry *entry = NULL;
- char name[16];
- static int log_open_err = 1;
- DEBUGMSGTL(("access:route:container",
- "route_container_arch_load ipv6n"));
- netsnmp_assert(NULL != container);
- /*
- * fetch routes from the proc file-system:
- */
- if (!(in = fopen("/proc/net/ipv6_route", "r"))) {
- if (1 == log_open_err) {
- snmp_log(LOG_ERR, "cannot open /proc/net/ipv6_routen");
- log_open_err = 0;
- }
- return -2;
- }
- /*
- * if we turned off logging of open errors, turn it back on now that
- * we have been able to open the file.
- */
- if (0 == log_open_err)
- log_open_err = 1;
- fgets(line,sizeof(line),in); /* skip header */
- while (fgets(line, sizeof(line), in)) {
- char c_name[9], c_dest[33], c_src[33], c_next[33];
- int rc;
- unsigned int dest_pfx, flags;
- size_t buf_len, buf_offset;
- u_char *temp_uchar_ptr;
- entry = netsnmp_access_route_entry_create();
- /*
- * based on /usr/src/linux/net/ipv6/route.c, kernel 2.6.7:
- *
- * [ Dest addr / plen ]
- * fe80000000000000025056fffec00008 80
- *
- * [ (?subtree) : src addr/plen : 0/0]
- * 00000000000000000000000000000000 00
- *
- * [ next hop ][ metric ][ref ctn][ use ]
- * 00000000000000000000000000000000 00000000 00000000 00000000
- *
- * [ flags ][dev name]
- * 80200001 lo
- */
- rc = sscanf(line, "%32s %2x %32s %*x %32s %x %*x %*x %x %8sn",
- c_dest, &dest_pfx, c_src, /*src_pfx,*/ c_next,
- &entry->rt_metric1, /** ref,*/ /* use, */ &flags, c_name);
- DEBUGMSGTL(("9:access:route:container", "line |%s|n", line));
- if (7 != rc) {
- snmp_log(LOG_ERR,
- "/proc/net/ipv6_route data format error (%d!=8), "
- "line ==|%s|", rc, line);
- continue;
- }
- /*
- * temporary null terminated name
- */
- c_name[ sizeof(c_name)-1 ] = 0;
- entry->if_index = se_find_value_in_slist("interfaces", c_name);
- if(SE_DNE == entry->if_index) {
- snmp_log(LOG_ERR,"unknown interface in /proc/net/ipv6_route "
- "('%s')n", name);
- netsnmp_access_route_entry_free(entry);
- continue;
- }
- /*
- * arbitrary index
- */
- entry->ns_rt_index = ++(*index);
- #ifdef USING_IP_FORWARD_MIB_IPCIDRROUTETABLE_IPCIDRROUTETABLE_MODULE
- /** entry->rt_mask = mask; */ /* IPv4 only */
- /** entry->rt_tos = XXX; */
- /** rt info ?? */
- #endif
- /*
- * convert hex addresses to binary
- */
- entry->rt_dest_type = INETADDRESSTYPE_IPV6;
- entry->rt_dest_len = 16;
- buf_len = sizeof(entry->rt_dest);
- buf_offset = 0;
- temp_uchar_ptr = entry->rt_dest;
- netsnmp_hex_to_binary(&temp_uchar_ptr, &buf_len, &buf_offset, 0,
- c_dest, NULL);
- entry->rt_nexthop_type = INETADDRESSTYPE_IPV6;
- entry->rt_nexthop_len = 16;
- buf_len = sizeof(entry->rt_nexthop);
- buf_offset = 0;
- temp_uchar_ptr = entry->rt_nexthop;
- netsnmp_hex_to_binary(&temp_uchar_ptr, &buf_len, &buf_offset, 0,
- c_next, NULL);
- entry->rt_pfx_len = dest_pfx;
- #ifdef USING_IP_FORWARD_MIB_INETCIDRROUTETABLE_INETCIDRROUTETABLE_MODULE
- /*
- inetCidrRoutePolicy OBJECT-TYPE
- SYNTAX OBJECT IDENTIFIER
- MAX-ACCESS not-accessible
- STATUS current
- DESCRIPTION
- "This object is an opaque object without any defined
- semantics. Its purpose is to serve as an additional
- index which may delineate between multiple entries to
- the same destination. The value { 0 0 } shall be used
- as the default value for this object."
- */
- /*
- * on linux, default routes all look alike, and would have the same
- * indexed based on dest and next hop. So we use our arbitrary index
- * as the policy, to distinguise between them.
- */
- entry->rt_policy = &entry->ns_rt_index;
- entry->rt_policy_len = 1;
- entry->flags |= NETSNMP_ROUTE_ENTRY_POLICY_STATIC;
- #endif
- /*
- * get protocol and type from flags
- */
- entry->rt_type = _type_from_flags(flags);
-
- entry->rt_proto = (flags & RTF_DYNAMIC)
- ? IANAIPROUTEPROTOCOL_ICMP : IANAIPROUTEPROTOCOL_LOCAL;
- /*
- * insert into container
- */
- CONTAINER_INSERT(container, entry);
- }
- fclose(in);
- return 0;
- }
- #endif
- /** arch specific load
- * @internal
- *
- * @retval 0 success
- * @retval -1 no container specified
- * @retval -2 could not open data file
- */
- int
- netsnmp_access_route_container_arch_load(netsnmp_container* container,
- u_int load_flags)
- {
- u_long count = 0;
- int rc;
- DEBUGMSGTL(("access:route:container",
- "route_container_arch_load (flags %p)n", load_flags));
- if (NULL == container) {
- snmp_log(LOG_ERR, "no container specified/found for access_routen");
- return -1;
- }
- rc = _load_ipv4(container, &count);
-
- #ifdef INET6
- if((0 != rc) || (load_flags & NETSNMP_ACCESS_ROUTE_LOAD_IPV4_ONLY))
- return rc;
- /*
- * load ipv6. ipv6 module might not be loaded,
- * so ignore -2 err (file not found)
- */
- rc = _load_ipv6(container, &count);
- if (-2 == rc)
- rc = 0;
- #endif
- return rc;
- }