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

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  *  Interface MIB architecture support
  3.  *
  4.  * $Id: interface_common.c,v 1.20.2.2 2005/02/09 21:02:14 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 "if-mib/ifTable/ifTable_constants.h"
  10. #include <net-snmp/agent/net-snmp-agent-includes.h>
  11. #include <net-snmp/library/snmp_enum.h>
  12. #include "interface.h"
  13. /**---------------------------------------------------------------------*/
  14. /*
  15.  * local static vars
  16.  */
  17. static netsnmp_conf_if_list *conf_list = NULL;
  18. static int need_wrap_check = -1;
  19. static int _access_interface_init = 0;
  20. /*
  21.  * local static prototypes
  22.  */
  23. static int _access_interface_entry_compare_name(const void *lhs,
  24.                                                 const void *rhs);
  25. static void _access_interface_entry_release(netsnmp_interface_entry * entry,
  26.                                             void *unused);
  27. static void _access_interface_entry_save_name(const char *name, oid index);
  28. static void _parse_interface_config(const char *token, char *cptr);
  29. static void _free_interface_config(void);
  30. /**---------------------------------------------------------------------*/
  31. /*
  32.  * external per-architecture functions prototypes
  33.  *
  34.  * These shouldn't be called by the general public, so they aren't in
  35.  * the header file.
  36.  */
  37. #ifndef NETSNMP_ACCESS_INTERFACE_NOARCH
  38. extern void netsnmp_arch_interface_init(void);
  39. extern int
  40. netsnmp_arch_interface_container_load(netsnmp_container* container,
  41.                                       u_int load_flags);
  42. extern int
  43. netsnmp_arch_set_admin_status(netsnmp_interface_entry * entry,
  44.                               int ifAdminStatus);
  45. extern int netsnmp_arch_interface_index_find(const char*name);
  46. #endif
  47. /**---------------------------------------------------------------------*/
  48. /*
  49.  * initialization
  50.  */
  51. void
  52. init_interface_common(void)
  53. {
  54.     snmpd_register_config_handler("interface", _parse_interface_config,
  55.                                   _free_interface_config,
  56.                                   "name type speed");
  57. }
  58. void
  59. netsnmp_access_interface_init(void)
  60. {
  61.     netsnmp_assert(0 == _access_interface_init); /* who is calling twice? */
  62.     if (1 == _access_interface_init)
  63.         return;
  64.     _access_interface_init = 1;
  65. #ifndef NETSNMP_ACCESS_INTERFACE_NOARCH
  66.     {
  67.         netsnmp_container * ifcontainer;
  68.         netsnmp_arch_interface_init();
  69.         
  70.         /*
  71.          * load once to set up ifIndexes
  72.          */
  73.         ifcontainer = netsnmp_access_interface_container_load(NULL, 0);
  74.         if(NULL != ifcontainer)
  75.             netsnmp_access_interface_container_free(ifcontainer, 0);
  76.     }
  77. #endif
  78. }
  79. /**---------------------------------------------------------------------*/
  80. /*
  81.  * container functions
  82.  */
  83. /**
  84.  * initialize interface container
  85.  */
  86. netsnmp_container *
  87. netsnmp_access_interface_container_init(u_int flags)
  88. {
  89.     netsnmp_container *container1;
  90.     DEBUGMSGTL(("access:interface:container", "initn"));
  91.     /*
  92.      * create the containers. one indexed by ifIndex, the other
  93.      * indexed by ifName.
  94.      */
  95.     container1 = netsnmp_container_find("access_interface:table_container");
  96.     if (NULL == container1)
  97.         return NULL;
  98.     if (flags & NETSNMP_ACCESS_INTERFACE_INIT_ADDL_IDX_BY_NAME) {
  99.         netsnmp_container *container2 =
  100.             netsnmp_container_find("access_interface_by_name:access_interface:table_container");
  101.         if (NULL == container2)
  102.             return NULL;
  103.         container2->compare = _access_interface_entry_compare_name;
  104.         
  105.         netsnmp_container_add_index(container1, container2);
  106.     }
  107.     return container1;
  108. }
  109. /**
  110.  * load interface information in specified container
  111.  *
  112.  * @param container empty container, or NULL to have one created for you
  113.  * @param load_flags flags to modify behaviour. Examples:
  114.  *                   NETSNMP_ACCESS_INTERFACE_INIT_ADDL_IDX_BY_NAME
  115.  *
  116.  * @retval NULL  error
  117.  * @retval !NULL pointer to container
  118.  */
  119. #ifndef NETSNMP_ACCESS_INTERFACE_NOARCH
  120. netsnmp_container*
  121. netsnmp_access_interface_container_load(netsnmp_container* container, u_int load_flags)
  122. {
  123.     int rc;
  124.     DEBUGMSGTL(("access:interface:container", "loadn"));
  125.     netsnmp_assert(1 == _access_interface_init);
  126.     if (NULL == container)
  127.         container = netsnmp_access_interface_container_init(load_flags);
  128.     if (NULL == container) {
  129.         snmp_log(LOG_ERR, "no container specified/found for access_interfacen");
  130.         return NULL;
  131.     }
  132.     rc =  netsnmp_arch_interface_container_load(container, load_flags);
  133.     if (0 != rc) {
  134.         netsnmp_access_interface_container_free(container,
  135.                                                 NETSNMP_ACCESS_INTERFACE_FREE_NOFLAGS);
  136.         container = NULL;
  137.     }
  138.     return container;
  139. }
  140. void
  141. netsnmp_access_interface_container_free(netsnmp_container *container, u_int free_flags)
  142. {
  143.     DEBUGMSGTL(("access:interface:container", "freen"));
  144.     if (NULL == container) {
  145.         snmp_log(LOG_ERR, "invalid container for netsnmp_access_interface_freen");
  146.         return;
  147.     }
  148.     if(! (free_flags & NETSNMP_ACCESS_INTERFACE_FREE_DONT_CLEAR)) {
  149.         /*
  150.          * free all items.
  151.          */
  152.         CONTAINER_CLEAR(container,
  153.                         (netsnmp_container_obj_func*)_access_interface_entry_release,
  154.                         NULL);
  155.     }
  156.     CONTAINER_FREE(container);
  157. }
  158. /**
  159.  * @retval 0  interface not found
  160.  */
  161. oid
  162. netsnmp_access_interface_index_find(const char *name)
  163. {
  164.     DEBUGMSGTL(("access:interface:find", "indexn"));
  165.     netsnmp_assert(1 == _access_interface_init);
  166.     return netsnmp_arch_interface_index_find(name);
  167. }
  168. #endif
  169. /**---------------------------------------------------------------------*/
  170. /*
  171.  * ifentry functions
  172.  */
  173. /**
  174.  */
  175. netsnmp_interface_entry *
  176. netsnmp_access_interface_entry_get_by_index(netsnmp_container *container, oid index)
  177. {
  178.     netsnmp_index   tmp;
  179.     DEBUGMSGTL(("access:interface:entry", "by_indexn"));
  180.     netsnmp_assert(1 == _access_interface_init);
  181.     if (NULL == container) {
  182.         snmp_log(LOG_ERR,
  183.                  "invalid container for netsnmp_access_interface_entry_get_by_indexn");
  184.         return NULL;
  185.     }
  186.     tmp.len = 1;
  187.     tmp.oids = &index;
  188.     return (netsnmp_interface_entry *) CONTAINER_FIND(container, &tmp);
  189. }
  190. /**
  191.  */
  192. netsnmp_interface_entry *
  193. netsnmp_access_interface_entry_get_by_name(netsnmp_container *container,
  194.                                 const char *name)
  195. {
  196.     netsnmp_interface_entry tmp;
  197.     DEBUGMSGTL(("access:interface:entry", "by_namen"));
  198.     netsnmp_assert(1 == _access_interface_init);
  199.     if (NULL == container) {
  200.         snmp_log(LOG_ERR,
  201.                  "invalid container for netsnmp_access_interface_entry_get_by_namen");
  202.         return NULL;
  203.     }
  204.     if (NULL == container->next) {
  205.         snmp_log(LOG_ERR,
  206.                  "secondary index missing for netsnmp_access_interface_entry_get_by_namen");
  207.         return NULL;
  208.     }
  209.     tmp.name = name;
  210.     return CONTAINER_FIND(container->next, &tmp);
  211. }
  212. /**
  213.  * @retval NULL  index not found
  214.  */
  215. const char *
  216. netsnmp_access_interface_name_find(oid index)
  217. {
  218.     DEBUGMSGTL(("access:interface:find", "namen"));
  219.     netsnmp_assert(1 == _access_interface_init);
  220.     return se_find_label_in_slist("interfaces", index);
  221. }
  222. /**
  223.  */
  224. netsnmp_interface_entry *
  225. netsnmp_access_interface_entry_create(const char *name, oid if_index)
  226. {
  227.     netsnmp_interface_entry *entry =
  228.         SNMP_MALLOC_TYPEDEF(netsnmp_interface_entry);
  229.     DEBUGMSGTL(("access:interface:entry", "createn"));
  230.     netsnmp_assert(1 == _access_interface_init);
  231.     if(NULL == entry)
  232.         return NULL;
  233.     if(NULL != name)
  234.         entry->name = strdup(name);
  235.     /*
  236.      * get if index, and save name for reverse lookup
  237.      */
  238. #ifndef NETSNMP_ACCESS_INTERFACE_NOARCH
  239.     if (0 == if_index)
  240.         entry->index = netsnmp_access_interface_index_find(name);
  241.     else
  242. #endif
  243.         entry->index = if_index;
  244.     _access_interface_entry_save_name(name, entry->index);
  245.     /*
  246.      * until we can get actual description, leave descr NULL.
  247.      * The end user can decide what to do with it.
  248.      */
  249.     /* entry->descr = strdup("unknown"); */
  250.     /*
  251.      * make some assumptions
  252.      */
  253.     entry->connector_present = 1;
  254.     entry->oid_index.len = 1;
  255.     entry->oid_index.oids = (oid *) & entry->index;
  256.     return entry;
  257. }
  258. /**
  259.  */
  260. void
  261. netsnmp_access_interface_entry_free(netsnmp_interface_entry * entry)
  262. {
  263.     DEBUGMSGTL(("access:interface:entry", "freen"));
  264.     if (NULL == entry)
  265.         return;
  266.     /*
  267.      * SNMP_FREE not needed, for any of these, 
  268.      * since the whole entry is about to be freed
  269.      */
  270.     if (NULL != entry->old_stats)
  271.         free(entry->old_stats);
  272.     if (NULL != entry->name)
  273.         free(entry->name);
  274.     if (NULL != entry->descr)
  275.         free(entry->descr);
  276.     if (NULL != entry->paddr)
  277.         free(entry->paddr);
  278.     free(entry);
  279. }
  280. /**
  281.  *
  282.  * @retval 0   : success
  283.  * @retval < 0 : error
  284.  */
  285. #ifndef NETSNMP_ACCESS_INTERFACE_NOARCH
  286. int
  287. netsnmp_access_interface_entry_set_admin_status(netsnmp_interface_entry * entry,
  288.                                                 int ifAdminStatus)
  289. {
  290.     int rc;
  291.     DEBUGMSGTL(("access:interface:entry", "set_admin_statusn"));
  292.     if (NULL == entry)
  293.         return -1;
  294.     if ((ifAdminStatus < IFADMINSTATUS_UP) ||
  295.          (ifAdminStatus > IFADMINSTATUS_TESTING))
  296.         return -2;
  297.     rc = netsnmp_arch_set_admin_status(entry, ifAdminStatus);
  298.     if (0 == rc) /* success */
  299.         entry->admin_status = ifAdminStatus;
  300.     return rc;
  301. }
  302. #endif
  303. /**---------------------------------------------------------------------*/
  304. /*
  305.  * Utility routines
  306.  */
  307. /**
  308.  */
  309. static int
  310. _access_interface_entry_compare_name(const void *lhs, const void *rhs)
  311. {
  312.     return strcmp(((const netsnmp_interface_entry *) lhs)->name,
  313.                   ((const netsnmp_interface_entry *) rhs)->name);
  314. }
  315. /**
  316.  */
  317. static void
  318. _access_interface_entry_release(netsnmp_interface_entry * entry, void *context)
  319. {
  320.     netsnmp_access_interface_entry_free(entry);
  321. }
  322. /**
  323.  */
  324. static void
  325. _access_interface_entry_save_name(const char *name, oid index)
  326. {
  327.     oid tmp;
  328.     if(NULL == name)
  329.         return;
  330.     tmp = se_find_value_in_slist("interfaces", name);
  331.     if (tmp == SE_DNE) {
  332.         se_add_pair_to_slist("interfaces", strdup(name), index);
  333.         DEBUGMSGTL(("access:interface:ifIndex", "saved ifIndex %d for %sn",
  334.                     index, name));
  335.     }
  336.     else
  337.         netsnmp_assert(index == tmp);
  338. }
  339. /**
  340.  * update stats
  341.  *
  342.  * @retval  0 : success
  343.  * @retval -1 : error
  344.  */
  345. int
  346. netsnmp_access_interface_entry_update_stats(netsnmp_interface_entry * prev_vals,
  347.                                             netsnmp_interface_entry * new_vals)
  348. {
  349.     DEBUGMSGTL(("access:interface", "check_wrapn"));
  350.     
  351.     /*
  352.      * sanity checks
  353.      */
  354.     if ((NULL == prev_vals) || (NULL == new_vals) ||
  355.         (NULL == prev_vals->name) || (NULL == new_vals->name) ||
  356.         (0 != strncmp(prev_vals->name, new_vals->name, strlen(prev_vals->name))))
  357.         return -1;
  358.     /*
  359.      * if we've determined that we have 64 bit counters, just copy them.
  360.      */
  361.     if (0 == need_wrap_check) {
  362.         memcpy(&prev_vals->stats, &new_vals->stats, sizeof(new_vals->stats));
  363.         return 0;
  364.     }
  365.     if (NULL == prev_vals->old_stats) {
  366.         /*
  367.          * if we don't have old stats, copy previous stats
  368.          */
  369.         prev_vals->old_stats = SNMP_MALLOC_TYPEDEF(netsnmp_interface_stats);
  370.         if (NULL == prev_vals->old_stats) {
  371.             return -2;
  372.         }
  373.         memcpy(prev_vals->old_stats, &prev_vals->stats, sizeof(new_vals->stats));
  374.     }
  375.         netsnmp_c64_check32_and_update(&prev_vals->stats.ibytes,
  376.                                        &new_vals->stats.ibytes,
  377.                                        &prev_vals->old_stats->ibytes,
  378.                                        &need_wrap_check);
  379.         netsnmp_c64_check32_and_update(&prev_vals->stats.iucast,
  380.                                        &new_vals->stats.iucast,
  381.                                        &prev_vals->old_stats->iucast,
  382.                                        &need_wrap_check);
  383.         netsnmp_c64_check32_and_update(&prev_vals->stats.imcast,
  384.                                        &new_vals->stats.imcast,
  385.                                        &prev_vals->old_stats->imcast,
  386.                                        &need_wrap_check);
  387.         netsnmp_c64_check32_and_update(&prev_vals->stats.ibcast,
  388.                                        &new_vals->stats.ibcast,
  389.                                        &prev_vals->old_stats->ibcast,
  390.                                        &need_wrap_check);
  391.         netsnmp_c64_check32_and_update(&prev_vals->stats.obytes,
  392.                                        &new_vals->stats.obytes,
  393.                                        &prev_vals->old_stats->obytes,
  394.                                        &need_wrap_check);
  395.         netsnmp_c64_check32_and_update(&prev_vals->stats.oucast,
  396.                                        &new_vals->stats.oucast,
  397.                                        &prev_vals->old_stats->oucast,
  398.                                        &need_wrap_check);
  399.         netsnmp_c64_check32_and_update(&prev_vals->stats.omcast,
  400.                                        &new_vals->stats.omcast,
  401.                                        &prev_vals->old_stats->omcast,
  402.                                        &need_wrap_check);
  403.         netsnmp_c64_check32_and_update(&prev_vals->stats.obcast,
  404.                                        &new_vals->stats.obcast,
  405.                                        &prev_vals->old_stats->obcast,
  406.                                        &need_wrap_check);
  407.     
  408.     /*
  409.      * if we've decided we no longer need to check wraps, free old stats
  410.      */
  411.     if (0 == need_wrap_check) {
  412.         SNMP_FREE(prev_vals->old_stats);
  413.     }
  414.     else {
  415.         /*
  416.          * update old stats from new stats.
  417.          * careful - old_stats is a pointer to stats...
  418.          */
  419.         memcpy(prev_vals->old_stats, &new_vals->stats, sizeof(new_vals->stats));
  420.     }
  421.     
  422.     return 0;
  423. }
  424. /**
  425.  * copy interface entry data (after checking for counter wraps)
  426.  *
  427.  * @retval -2 : malloc failed
  428.  * @retval -1 : interfaces not the same
  429.  * @retval  0 : no error
  430.  */
  431. int
  432. netsnmp_access_interface_entry_copy(netsnmp_interface_entry * lhs,
  433.                                     netsnmp_interface_entry * rhs)
  434. {
  435.     DEBUGMSGTL(("access:interface", "copyn"));
  436.     
  437.     if ((NULL == lhs) || (NULL == rhs) ||
  438.         (NULL == lhs->name) || (NULL == rhs->name) ||
  439.         (0 != strncmp(lhs->name, rhs->name, strlen(rhs->name))))
  440.         return -1;
  441.     /*
  442.      * update stats
  443.      */
  444.     netsnmp_access_interface_entry_update_stats(lhs, rhs);
  445.     /*
  446.      * update data
  447.      */
  448.     lhs->ns_flags = rhs->ns_flags;
  449.     if((NULL != lhs->descr) && (NULL != rhs->descr) &&
  450.        (0 == strcmp(lhs->descr, rhs->descr)))
  451.         ;
  452.     else {
  453.         if (NULL != lhs->descr)
  454.             SNMP_FREE(lhs->descr);
  455.         if (rhs->descr) {
  456.             lhs->descr = strdup(rhs->descr);
  457.             if(NULL == lhs->descr)
  458.                 return -2;
  459.         }
  460.     }
  461.     lhs->type = rhs->type;
  462.     lhs->speed = rhs->speed;
  463.     lhs->speed_high = rhs->speed_high;
  464.     lhs->mtu = rhs->mtu;
  465.     lhs->discontinuity = rhs->discontinuity;
  466.     lhs->oper_status = rhs->oper_status;
  467.     lhs->promiscuous = rhs->promiscuous;
  468.     lhs->connector_present = rhs->connector_present;
  469.     lhs->os_flags = rhs->os_flags;
  470.     if(lhs->paddr_len == rhs->paddr_len) {
  471.         if(rhs->paddr_len)
  472.             memcpy(lhs->paddr,rhs->paddr,rhs->paddr_len);
  473.     } else {
  474.         if (NULL != lhs->paddr)
  475.             SNMP_FREE(lhs->paddr);
  476.         if (rhs->paddr) {
  477.             lhs->paddr = malloc(rhs->paddr_len);
  478.             if(NULL == lhs->paddr)
  479.                 return -2;
  480.             memcpy(lhs->paddr,rhs->paddr,rhs->paddr_len);
  481.         }
  482.     }
  483.     lhs->paddr_len = rhs->paddr_len;
  484.     
  485.     return 0;
  486. }
  487. void
  488. netsnmp_access_interface_entry_guess_speed(netsnmp_interface_entry *entry)
  489. {
  490.     if (entry->type == IANAIFTYPE_ETHERNETCSMACD)
  491.         entry->speed = 10000000;
  492.     else if (entry->type == IANAIFTYPE_SOFTWARELOOPBACK)
  493.         entry->speed = 10000000;
  494.     else if (entry->type == IANAIFTYPE_ISO88025TOKENRING)
  495.         entry->speed = 4000000;
  496.     else
  497.         entry->speed = 0;
  498. }
  499. netsnmp_conf_if_list *
  500. netsnmp_access_interface_entry_overrides_get(const char * name)
  501. {
  502.     netsnmp_conf_if_list * if_ptr;
  503.     netsnmp_assert(1 == _access_interface_init);
  504.     if(NULL == name)
  505.         return NULL;
  506.     for (if_ptr = conf_list; if_ptr; if_ptr = if_ptr->next)
  507.         if (!strcmp(if_ptr->name, name))
  508.             break;
  509.     return if_ptr;
  510. }
  511. void
  512. netsnmp_access_interface_entry_overrides(netsnmp_interface_entry *entry)
  513. {
  514.     netsnmp_conf_if_list * if_ptr;
  515.     netsnmp_assert(1 == _access_interface_init);
  516.     if (NULL == entry)
  517.         return;
  518.     /*
  519.      * enforce mib size limit
  520.      */
  521.     if(entry->descr && (strlen(entry->descr) > 255))
  522.         entry->descr[255] = 0;
  523.     if_ptr =
  524.         netsnmp_access_interface_entry_overrides_get(entry->name);
  525.     if (if_ptr) {
  526.         entry->type = if_ptr->type;
  527.         entry->speed = if_ptr->speed;
  528.     }
  529. }
  530. /**---------------------------------------------------------------------*/
  531. /*
  532.  * interface config token
  533.  */
  534. /**
  535.  */
  536. static void
  537. _parse_interface_config(const char *token, char *cptr)
  538. {
  539.     netsnmp_conf_if_list   *if_ptr, *if_new;
  540.     char                   *name, *type, *speed, *ecp;
  541.     char                   *st;
  542.     name = strtok_r(cptr, " t", &st);
  543.     if (!name) {
  544.         config_perror("Missing NAME parameter");
  545.         return;
  546.     }
  547.     type = strtok_r(NULL, " t", &st);
  548.     if (!type) {
  549.         config_perror("Missing TYPE parameter");
  550.         return;
  551.     }
  552.     speed = strtok_r(NULL, " t", &st);
  553.     if (!speed) {
  554.         config_perror("Missing SPEED parameter");
  555.         return;
  556.     }
  557.     if_ptr = conf_list;
  558.     while (if_ptr)
  559.         if (strcmp(if_ptr->name, name))
  560.             if_ptr = if_ptr->next;
  561.         else
  562.             break;
  563.     if (if_ptr)
  564.         config_pwarn("Duplicate interface specification");
  565.     if_new = SNMP_MALLOC_TYPEDEF(netsnmp_conf_if_list);
  566.     if (!if_new) {
  567.         config_perror("Out of memory");
  568.         return;
  569.     }
  570.     if_new->speed = strtoul(speed, &ecp, 0);
  571.     if (*ecp) {
  572.         config_perror("Bad SPEED value");
  573.         free(if_new);
  574.         return;
  575.     }
  576.     if_new->type = strtol(type, &ecp, 0);
  577.     if (*ecp || if_new->type < 0) {
  578.         config_perror("Bad TYPE");
  579.         free(if_new);
  580.         return;
  581.     }
  582.     if_new->name = strdup(name);
  583.     if (!if_new->name) {
  584.         config_perror("Out of memory");
  585.         free(if_new);
  586.         return;
  587.     }
  588.     if_new->next = conf_list;
  589.     conf_list = if_new;
  590. }
  591. static void
  592. _free_interface_config(void)
  593. {
  594.     netsnmp_conf_if_list   *if_ptr = conf_list, *if_next;
  595.     while (if_ptr) {
  596.         if_next = if_ptr->next;
  597.         free(if_ptr->name);
  598.         free(if_ptr);
  599.         if_ptr = if_next;
  600.     }
  601.     conf_list = NULL;
  602. }