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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Interface MIB architecture support
  3.  *
  4.  * $Id: ipaddress_linux.c,v 1.10.2.1 2005/08/17 00:09:16 rstory 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/ipaddress.h>
  11. #include <net-snmp/data_access/interface.h>
  12. #include "ip-mib/ipAddressTable/ipAddressTable_constants.h"
  13. #include <errno.h>
  14. #include <sys/ioctl.h>
  15. #if defined (INET6)
  16. #include <linux/types.h>
  17. #include <asm/types.h>
  18. #include <linux/rtnetlink.h>
  19. #endif
  20. #include "ipaddress_ioctl.h"
  21. int _load_v6(netsnmp_container *container, int idx_offset);
  22. /*
  23.  * initialize arch specific storage
  24.  *
  25.  * @retval  0: success
  26.  * @retval <0: error
  27.  */
  28. int
  29. netsnmp_arch_ipaddress_entry_init(netsnmp_ipaddress_entry *entry)
  30. {
  31.     /*
  32.      * init ipv4 stuff
  33.      */
  34.     if (NULL == netsnmp_ioctl_ipaddress_entry_init(entry))
  35.         return -1;
  36.     /*
  37.      * init ipv6 stuff
  38.      *   so far, we can just share the ipv4 stuff, so nothing to do
  39.      */
  40.     
  41.     return 0;
  42. }
  43. /*
  44.  * cleanup arch specific storage
  45.  */
  46. void
  47. netsnmp_arch_ipaddress_entry_cleanup(netsnmp_ipaddress_entry *entry)
  48. {
  49.     /*
  50.      * cleanup ipv4 stuff
  51.      */
  52.     netsnmp_ioctl_ipaddress_entry_cleanup(entry);
  53.     /*
  54.      * cleanup ipv6 stuff
  55.      *   so far, we can just share the ipv4 stuff, so nothing to do
  56.      */
  57. }
  58. /*
  59.  * copy arch specific storage
  60.  */
  61. int
  62. netsnmp_arch_ipaddress_entry_copy(netsnmp_ipaddress_entry *lhs,
  63.                                   netsnmp_ipaddress_entry *rhs)
  64. {
  65.     int rc;
  66.     /*
  67.      * copy ipv4 stuff
  68.      */
  69.     rc = netsnmp_ioctl_ipaddress_entry_copy(lhs, rhs);
  70.     if (rc)
  71.         return rc;
  72.     /*
  73.      * copy ipv6 stuff
  74.      *   so far, we can just share the ipv4 stuff, so nothing to do
  75.      */
  76.     return rc;
  77. }
  78. /*
  79.  * create a new entry
  80.  */
  81. int
  82. netsnmp_arch_ipaddress_create(netsnmp_ipaddress_entry *entry)
  83. {
  84.     if (NULL == entry)
  85.         return -1;
  86.     if (4 != entry->ia_address_len) {
  87.         DEBUGMSGT(("access:ipaddress:create", "on ipv4 supportedn"));
  88.         return -2;
  89.     }
  90.     return _netsnmp_ioctl_ipaddress_set_v4(entry);
  91. }
  92. /*
  93.  * create a new entry
  94.  */
  95. int
  96. netsnmp_arch_ipaddress_delete(netsnmp_ipaddress_entry *entry)
  97. {
  98.     if (NULL == entry)
  99.         return -1;
  100.     if (4 != entry->ia_address_len) {
  101.         DEBUGMSGT(("access:ipaddress:create", "only ipv4 supportedn"));
  102.         return -2;
  103.     }
  104.     return _netsnmp_ioctl_ipaddress_delete_v4(entry);
  105. }
  106. /**
  107.  *
  108.  * @retval  0 no errors
  109.  * @retval !0 errors
  110.  */
  111. int
  112. netsnmp_arch_ipaddress_container_load(netsnmp_container *container)
  113. {
  114.     int rc = 0, idx_offset = 0;
  115.     rc = _netsnmp_ioctl_ipaddress_container_load_v4(container, idx_offset);
  116.     if(rc < 0) {
  117.         u_int flags = NETSNMP_ACCESS_IPADDRESS_FREE_KEEP_CONTAINER;
  118.         netsnmp_access_ipaddress_container_free(container, flags);
  119.         return rc;
  120.     }
  121. #if defined (INET6)
  122.     idx_offset = rc;
  123.     /*
  124.      * load ipv6, ignoring errors if file not found
  125.      */
  126.     rc = _load_v6(container, idx_offset);
  127.     if (-2 == rc)
  128.         rc = 0;
  129.     else if(rc < 0) {
  130.         u_int flags = NETSNMP_ACCESS_IPADDRESS_FREE_KEEP_CONTAINER;
  131.         netsnmp_access_ipaddress_container_free(container, flags);
  132.     }
  133. #endif
  134.     /*
  135.      * return no errors (0) if we found any interfaces
  136.      */
  137.     if(rc > 0)
  138.         rc = 0;
  139.     return rc;
  140. }
  141. #if defined (INET6)
  142. /**
  143.  */
  144. int
  145. _load_v6(netsnmp_container *container, int idx_offset)
  146. {
  147.     FILE           *in;
  148.     char            line[80], addr[33], if_name[IFNAMSIZ];
  149.     u_char          *buf;
  150.     int             if_index, pfx_len, scope, flags, rc = 0;
  151.     size_t          in_len, out_len;
  152.     netsnmp_ipaddress_entry *entry;
  153.     _ioctl_extras           *extras;
  154.     static int      log_open_err = 1;
  155.     
  156.     netsnmp_assert(NULL != container);
  157. #define PROCFILE "/proc/net/if_inet6"
  158.     if (!(in = fopen(PROCFILE, "r"))) {
  159.         if (1 == log_open_err) {
  160.             snmp_log(LOG_ERR,"could not open " PROCFILE "n");
  161.             log_open_err = 0;
  162.         }
  163.         return -2;
  164.     }
  165.     /*
  166.      * if we hadn't been able to open file and turned of err logging,
  167.      * turn it back on now that we opened the file.
  168.      */
  169.     if (0 == log_open_err)
  170.         log_open_err = 1;
  171.     /*
  172.      * address index prefix_len scope status if_name
  173.      */
  174.     while (fgets(line, sizeof(line), in)) {
  175.         /*
  176.          * fe800000000000000200e8fffe5b5c93 05 40 20 80 eth0
  177.          *             A                    D  P  S  F  I
  178.          * A: address
  179.          * D: device number
  180.          * P: prefix len
  181.          * S: scope (see include/net/ipv6.h, net/ipv6/addrconf.c)
  182.          * F: flags (see include/linux/rtnetlink.h, net/ipv6/addrconf.c)
  183.          * I: interface
  184.          */
  185.         rc = sscanf(line, "%32s %02x %02x %02x %02x %8sn",
  186.                     addr, &if_index, &pfx_len, &scope, &flags, if_name);
  187.         if( 6 != rc ) {
  188.             snmp_log(LOG_ERR, PROCFILE " data format error (%d!=6), line ==|%s|n",
  189.                      rc, line);
  190.             continue;
  191.         }
  192.         DEBUGMSGTL(("access:ipaddress:container",
  193.                     "addr %s, index %d, pfx %d, scope %d, flags 0x%X, name %sn",
  194.                     addr, if_index, pfx_len, scope, flags, if_name));
  195.         /*
  196.          */
  197.         entry = netsnmp_access_ipaddress_entry_create();
  198.         if(NULL == entry) {
  199.             rc = -3;
  200.             break;
  201.         }
  202.         in_len = entry->ia_address_len = sizeof(entry->ia_address);
  203.         netsnmp_assert(16 == in_len);
  204.         out_len = 0;
  205.         buf = entry->ia_address;
  206.         if(1 != snmp_hex_to_binary(&buf,
  207.                                    &in_len, &out_len, 0, addr)) {
  208.             snmp_log(LOG_ERR,"error parsing '%s', skippingn",
  209.                      entry->ia_address);
  210.             netsnmp_access_ipaddress_entry_free(entry);
  211.             continue;
  212.         }
  213.         netsnmp_assert(16 == out_len);
  214.         entry->ia_address_len = out_len;
  215.         entry->ns_ia_index = ++idx_offset;
  216.         /*
  217.          * save if name
  218.          */
  219.         extras = netsnmp_ioctl_ipaddress_extras_get(entry);
  220.         memcpy(extras->name, if_name, sizeof(extras->name));
  221.         extras->flags = flags;
  222.         /*
  223.          * yyy-rks: optimization: create a socket outside the loop and use
  224.          * netsnmp_access_interface_ioctl_ifindex_get() here, since
  225.          * netsnmp_access_interface_index_find will open/close a socket
  226.          * every time it is called.
  227.          */
  228.         entry->if_index = netsnmp_access_interface_index_find(if_name);
  229.         /*
  230.           #define IPADDRESSSTATUSTC_PREFERRED  1
  231.           #define IPADDRESSSTATUSTC_DEPRECATED  2
  232.           #define IPADDRESSSTATUSTC_INVALID  3
  233.           #define IPADDRESSSTATUSTC_INACCESSIBLE  4
  234.           #define IPADDRESSSTATUSTC_UNKNOWN  5
  235.           #define IPADDRESSSTATUSTC_TENTATIVE  6
  236.           #define IPADDRESSSTATUSTC_DUPLICATE  7
  237.         */
  238.         if(flags & IFA_F_PERMANENT)
  239.             entry->ia_status = IPADDRESSSTATUSTC_PREFERRED; /* ?? */
  240.         else if(flags & IFA_F_DEPRECATED)
  241.             entry->ia_status = IPADDRESSSTATUSTC_DEPRECATED;
  242.         else if(flags & IFA_F_TENTATIVE)
  243.             entry->ia_status = IPADDRESSSTATUSTC_TENTATIVE;
  244.         else {
  245.             entry->ia_status = IPADDRESSSTATUSTC_UNKNOWN;
  246.             DEBUGMSGTL(("access:ipaddress:ipv6",
  247.                         "unknown flags 0x%xn", flags));
  248.         }
  249.         /*
  250.          * if it's not multi, it must be uni.
  251.          *  (an ipv6 address is never broadcast)
  252.          */
  253.         if (IN6_IS_ADDR_MULTICAST(entry->ia_address))
  254.             entry->ia_type = IPADDRESSTYPE_ANYCAST;
  255.         else
  256.             entry->ia_type = IPADDRESSTYPE_UNICAST;
  257.         /** entry->ia_prefix_oid ? */
  258.         /*
  259.          * can we figure out if an address is from DHCP?
  260.          * use manual until then...
  261.          *
  262.          *#define IPADDRESSORIGINTC_OTHER  1
  263.          *#define IPADDRESSORIGINTC_MANUAL  2
  264.          *#define IPADDRESSORIGINTC_DHCP  4
  265.          *#define IPADDRESSORIGINTC_LINKLAYER  5
  266.          *#define IPADDRESSORIGINTC_RANDOM  6
  267.          *
  268.          * are 'local' address assigned by link layer??
  269.          */
  270.         if (IN6_IS_ADDR_LINKLOCAL(entry->ia_address) ||
  271.             IN6_IS_ADDR_SITELOCAL(entry->ia_address))
  272.             entry->ia_origin = IPADDRESSORIGINTC_LINKLAYER;
  273.         else
  274.             entry->ia_origin = IPADDRESSORIGINTC_MANUAL;
  275.         /* xxx-rks: what can we do with scope? */
  276.         /*
  277.          * add entry to container
  278.          */
  279.         CONTAINER_INSERT(container, entry);
  280.     }
  281.     fclose(in);
  282.     if(rc<0)
  283.         return rc;
  284.     return idx_offset;
  285. }
  286. #endif