diff options
Diffstat (limited to 'snmp_mibII/mibII.c')
-rw-r--r-- | snmp_mibII/mibII.c | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/snmp_mibII/mibII.c b/snmp_mibII/mibII.c index 6c35d926c593..2a4e3756bdc5 100644 --- a/snmp_mibII/mibII.c +++ b/snmp_mibII/mibII.c @@ -411,7 +411,7 @@ mibif_reset_hc_timer(void) hc_update_timer = NULL; } update_hc_counters(NULL); - if ((hc_update_timer = timer_start_repeat(ticks * 10, ticks * 10, + if ((hc_update_timer = timer_start_repeat(ticks, ticks, update_hc_counters, NULL, module)) == NULL) { syslog(LOG_ERR, "timer_start(%u): %m", ticks); return; @@ -439,11 +439,15 @@ mibif_restart_mibII_poll_timer(void) int mib_fetch_ifmib(struct mibif *ifp) { + static int kmib[2] = { -1, 0 }; /* for sysctl net.ifdescr_maxlen */ + int name[6]; + size_t kmiblen = nitems(kmib); size_t len; void *newmib; struct ifmibdata oldmib = ifp->mib; struct ifreq irr; + u_int alias_maxlen = MIBIF_ALIAS_SIZE_MAX; if (fetch_generic_mib(ifp, &oldmib) == -1) return (-1); @@ -515,18 +519,68 @@ mib_fetch_ifmib(struct mibif *ifp) } out: + /* + * Find sysctl mib for net.ifdescr_maxlen (one time). + * kmib[0] == -1 at first call to mib_fetch_ifmib(). + * Then kmib[0] > 0 if we found sysctl mib for net.ifdescr_maxlen. + * Else, kmib[0] == 0 (unexpected error from a kernel). + */ + if (kmib[0] < 0 && + sysctlnametomib("net.ifdescr_maxlen", kmib, &kmiblen) < 0) { + kmib[0] = 0; + syslog(LOG_WARNING, "sysctlnametomib net.ifdescr_maxlen: %m"); + } + + /* + * Fetch net.ifdescr_maxlen value every time to catch up with changes. + */ + len = sizeof(alias_maxlen); + if (kmib[0] > 0 && sysctl(kmib, 2, &alias_maxlen, &len, NULL, 0) < 0) { + /* unexpected error from the kernel, use default value */ + alias_maxlen = MIBIF_ALIAS_SIZE_MAX; + syslog(LOG_WARNING, "sysctl net.ifdescr_maxlen: %m"); + } + + /* + * Kernel limit might be decreased after interfaces got + * their descriptions assigned. Try to obtain them anyway. + */ + if (alias_maxlen == 0) + alias_maxlen = MIBIF_ALIAS_SIZE_MAX; + + /* + * Allocate maximum memory for a buffer and later reallocate + * to free extra memory. + */ + if ((ifp->alias = malloc(alias_maxlen)) == NULL) { + syslog(LOG_WARNING, "malloc(%d) failed: %m", (int)alias_maxlen); + goto fin; + } + strlcpy(irr.ifr_name, ifp->name, sizeof(irr.ifr_name)); - irr.ifr_buffer.buffer = MIBIF_PRIV(ifp)->alias; - irr.ifr_buffer.length = sizeof(MIBIF_PRIV(ifp)->alias); + irr.ifr_buffer.buffer = ifp->alias; + irr.ifr_buffer.length = alias_maxlen; if (ioctl(mib_netsock, SIOCGIFDESCR, &irr) == -1) { - MIBIF_PRIV(ifp)->alias[0] = 0; + free(ifp->alias); + ifp->alias = NULL; if (errno != ENOMSG) syslog(LOG_WARNING, "SIOCGIFDESCR (%s): %m", ifp->name); } else if (irr.ifr_buffer.buffer == NULL) { - MIBIF_PRIV(ifp)->alias[0] = 0; + free(ifp->alias); + ifp->alias = NULL; syslog(LOG_WARNING, "SIOCGIFDESCR (%s): too long (%zu)", ifp->name, irr.ifr_buffer.length); + } else { + ifp->alias_size = strnlen(ifp->alias, alias_maxlen) + 1; + + if (ifp->alias_size > MIBIF_ALIAS_SIZE) + ifp->alias_size = MIBIF_ALIAS_SIZE; + + if (ifp->alias_size < alias_maxlen) + ifp->alias = realloc(ifp->alias, ifp->alias_size); } + + fin: ifp->mibtick = get_ticks(); return (0); } @@ -706,6 +760,10 @@ mibif_free(struct mibif *ifp) mibif_reset_hc_timer(); } + if (ifp->alias != NULL) { + free(ifp->alias); + ifp->alias = NULL; + } free(ifp->private); ifp->private = NULL; free(ifp->physaddr); @@ -1772,8 +1830,7 @@ mibII_loading(const struct lmodule *mod, int loaded) mib_unregister_newif(mod); } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-variable-declarations" +extern const struct snmp_module config; const struct snmp_module config = { "This module implements the interface and ip groups.", mibII_init, @@ -1787,7 +1844,6 @@ const struct snmp_module config = { mibII_CTREE_SIZE, mibII_loading }; -#pragma GCC diagnostic push /* * Should have a list of these attached to each interface. |