diff --git a/SOURCES/net-snmp-5.7.2-agentx-disconnect-crash-part2.patch b/SOURCES/net-snmp-5.7.2-agentx-disconnect-crash-part2.patch index cfece15..41887a5 100644 --- a/SOURCES/net-snmp-5.7.2-agentx-disconnect-crash-part2.patch +++ b/SOURCES/net-snmp-5.7.2-agentx-disconnect-crash-part2.patch @@ -9,3 +9,4 @@ diff -urNp old/agent/mibgroup/agentx/master.c new/agent/mibgroup/agentx/master.c + return 1; } requests = cache->requests; + diff --git a/SOURCES/net-snmp-5.7.2-client-udp6.patch b/SOURCES/net-snmp-5.7.2-client-udp6.patch new file mode 100644 index 0000000..5405239 --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-client-udp6.patch @@ -0,0 +1,112 @@ +diff -urpN old/snmplib/snmp_api.c new/snmplib/snmp_api.c +--- old/snmplib/snmp_api.c 2017-04-03 09:07:41.795091238 +0200 ++++ new/snmplib/snmp_api.c 2017-04-03 10:54:47.809422106 +0200 +@@ -1553,12 +1553,12 @@ _sess_open(netsnmp_session * in_session) + if (in_session->flags & SNMP_FLAGS_STREAM_SOCKET) { + transport = + netsnmp_tdomain_transport_full("snmp", in_session->peername, +- in_session->local_port, "tcp", ++ in_session->local_port, "tcp,tcp6", + NULL); + } else { + transport = + netsnmp_tdomain_transport_full("snmp", in_session->peername, +- in_session->local_port, "udp", ++ in_session->local_port, "udp,udp6", + NULL); + } + +diff -urpN old/snmplib/snmp_transport.c new/snmplib/snmp_transport.c +--- old/snmplib/snmp_transport.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/snmplib/snmp_transport.c 2017-04-03 11:50:49.158878706 +0200 +@@ -498,6 +498,9 @@ netsnmp_tdomain_transport_full(const cha + const char * const *spec = NULL; + int any_found = 0; + char buf[SNMP_MAXPATH]; ++ char **lspec = 0; ++ char *tokenized_domain = 0; ++ + + DEBUGMSGTL(("tdomain", + "tdomain_transport_full(\"%s\", \"%s\", %d, \"%s\", \"%s\")\n", +@@ -587,7 +590,23 @@ netsnmp_tdomain_transport_full(const cha + DEBUGMSGTL(("tdomain", + "Use user specified default domain \"%s\"\n", + default_domain)); +- match = find_tdomain(default_domain); ++ if (!strchr(default_domain, ',')) ++ match = find_tdomain(default_domain); ++ else { ++ int commas = 0; ++ const char *cp = default_domain; ++ char *ptr = NULL; ++ tokenized_domain = strdup(default_domain); ++ ++ while (*++cp) if (*cp == ',') commas++; ++ lspec = calloc(commas+2, sizeof(char *)); ++ commas = 1; ++ lspec[0] = strtok_r(tokenized_domain, ",", &ptr); ++ while ((lspec[commas++] = strtok_r(NULL, ",", &ptr))) ++ ; ++ spec = (const char * const *)lspec; ++ } ++ + } else { + spec = netsnmp_lookup_default_domains(application); + if (spec == NULL) { +@@ -636,6 +655,10 @@ netsnmp_tdomain_transport_full(const cha + else + t = match->f_create_from_tstring_new(addr, local, addr2); + if (t) { ++ if (lspec) { ++ free(tokenized_domain); ++ free(lspec); ++ } + return t; + } + } +@@ -647,6 +670,10 @@ netsnmp_tdomain_transport_full(const cha + } + if (!any_found) + snmp_log(LOG_ERR, "No support for any checked transport domain\n"); ++ if (lspec) { ++ free(tokenized_domain); ++ free(lspec); ++ } + return NULL; + } + +diff -urpN old/snmplib/system.c new/snmplib/system.c +--- old/snmplib/system.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/snmplib/system.c 2017-04-03 12:02:35.693153449 +0200 +@@ -750,13 +750,6 @@ netsnmp_gethostbyname_v4(const char* nam + + err = netsnmp_getaddrinfo(name, NULL, &hint, &addrs); + if (err != 0) { +-#if HAVE_GAI_STRERROR +- snmp_log(LOG_ERR, "getaddrinfo: %s %s\n", name, +- gai_strerror(err)); +-#else +- snmp_log(LOG_ERR, "getaddrinfo: %s (error %d)\n", name, +- err); +-#endif + return -1; + } + +diff -urpN old/snmplib/transports/snmpIPv6BaseDomain.c new/snmplib/transports/snmpIPv6BaseDomain.c +--- old/snmplib/transports/snmpIPv6BaseDomain.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/snmplib/transports/snmpIPv6BaseDomain.c 2017-04-03 12:00:38.669641503 +0200 +@@ -342,13 +342,6 @@ netsnmp_sockaddr_in6_2(struct sockaddr_i + err = netsnmp_getaddrinfo(peername, NULL, &hint, &addrs); + } + if (err != 0) { +-#if HAVE_GAI_STRERROR +- snmp_log(LOG_ERR, "getaddrinfo(\"%s\", NULL, ...): %s\n", peername, +- gai_strerror(err)); +-#else +- snmp_log(LOG_ERR, "getaddrinfo(\"%s\", NULL, ...): (error %d)\n", +- peername, err); +-#endif + free(peername); + return 0; + } diff --git a/SOURCES/net-snmp-5.7.2-duplicate-ipAddress.patch b/SOURCES/net-snmp-5.7.2-duplicate-ipAddress.patch new file mode 100644 index 0000000..84b527a --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-duplicate-ipAddress.patch @@ -0,0 +1,11 @@ +diff -urNp old/agent/mibgroup/ip-mib/data_access/ipaddress_common.c new/agent/mibgroup/ip-mib/data_access/ipaddress_common.c +--- old/agent/mibgroup/ip-mib/data_access/ipaddress_common.c 2017-04-26 08:46:40.272404217 +0200 ++++ new/agent/mibgroup/ip-mib/data_access/ipaddress_common.c 2017-04-26 08:50:30.681323779 +0200 +@@ -144,6 +144,7 @@ _remove_duplicates(netsnmp_container *co + for (entry = ITERATOR_FIRST(it); entry; entry = ITERATOR_NEXT(it)) { + if (prev_entry && _access_ipaddress_entry_compare_addr(prev_entry, entry) == 0) { + /* 'entry' is duplicate of the previous one -> delete it */ ++ NETSNMP_LOGONCE((LOG_ERR, "Duplicate IPv4 address detected, some interfaces may not be visible in IP-MIB\n")); + netsnmp_access_ipaddress_entry_free(entry); + } else { + CONTAINER_INSERT(ret, entry); diff --git a/SOURCES/net-snmp-5.7.2-ipAddress-faster-load.patch b/SOURCES/net-snmp-5.7.2-ipAddress-faster-load.patch new file mode 100644 index 0000000..e59f896 --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-ipAddress-faster-load.patch @@ -0,0 +1,346 @@ +diff -urNp old/agent/mibgroup/ip-mib/data_access/ipaddress_common.c new/agent/mibgroup/ip-mib/data_access/ipaddress_common.c +--- old/agent/mibgroup/ip-mib/data_access/ipaddress_common.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/agent/mibgroup/ip-mib/data_access/ipaddress_common.c 2017-04-04 11:02:42.391951747 +0200 +@@ -67,6 +67,7 @@ netsnmp_container * + netsnmp_access_ipaddress_container_init(u_int flags) + { + netsnmp_container *container1; ++ int rc; + + DEBUGMSGTL(("access:ipaddress:container", "init\n")); + +@@ -80,6 +81,7 @@ netsnmp_access_ipaddress_container_init( + return NULL; + } + container1->container_name = strdup("ia_index"); ++ CONTAINER_SET_OPTIONS(container1, CONTAINER_KEY_ALLOW_DUPLICATES, rc); + + if (flags & NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR) { + netsnmp_container *container2 = +@@ -92,6 +94,13 @@ netsnmp_access_ipaddress_container_init( + + container2->compare = _access_ipaddress_entry_compare_addr; + container2->container_name = strdup("ia_addr"); ++ ++ /* ++ * With allowed duplicates, CONTAINER_INSERT does not need to sort whole ++ * container and check for duplicates. We remove duplicates manually in ++ * netsnmp_access_ipaddress_container_load. ++ */ ++ CONTAINER_SET_OPTIONS(container2, CONTAINER_KEY_ALLOW_DUPLICATES, rc); + + netsnmp_container_add_index(container1, container2); + } +@@ -100,6 +109,53 @@ netsnmp_access_ipaddress_container_init( + } + + /** ++ * Remove duplicate entries from the container. ++ * This function returns new copy of the container and destroys ++ * the original one. Use like this: ++ * c = _remove_duplicates(c, flags); ++ */ ++static netsnmp_container * ++_remove_duplicates(netsnmp_container *container, u_int container_flags) ++{ ++ netsnmp_container *c; ++ netsnmp_iterator *it; ++ netsnmp_container *ret; ++ netsnmp_ipaddress_entry *entry, *prev_entry; ++ ++ if (! (container_flags & NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR)) { ++ /* We don't have address index, we can't detect duplicates */ ++ return container; ++ } ++ ++ ret = netsnmp_access_ipaddress_container_init(container_flags); ++ ++ /* use the IpAddress index */ ++ c = container->next; ++ it = CONTAINER_ITERATOR(c); ++ /* Sort the address index */ ++ CONTAINER_FIND(c, ITERATOR_FIRST(it)); ++ ++ ++ /* ++ * Sequentially iterate over sorted container and add only unique entries ++ * to 'ret' ++ */ ++ prev_entry = NULL; ++ for (entry = ITERATOR_FIRST(it); entry; entry = ITERATOR_NEXT(it)) { ++ if (prev_entry && _access_ipaddress_entry_compare_addr(prev_entry, entry) == 0) { ++ /* 'entry' is duplicate of the previous one -> delete it */ ++ netsnmp_access_ipaddress_entry_free(entry); ++ } else { ++ CONTAINER_INSERT(ret, entry); ++ prev_entry = entry; ++ } ++ } ++ CONTAINER_FREE(container); ++ free(it); ++ return ret; ++} ++ ++/** + * @retval NULL error + * @retval !NULL pointer to container + */ +@@ -112,9 +168,10 @@ netsnmp_access_ipaddress_container_load( + + DEBUGMSGTL(("access:ipaddress:container", "load\n")); + ++ if (load_flags & NETSNMP_ACCESS_IPADDRESS_LOAD_ADDL_IDX_BY_ADDR) ++ container_flags |= NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR; ++ + if (NULL == container) { +- if (load_flags & NETSNMP_ACCESS_IPADDRESS_LOAD_ADDL_IDX_BY_ADDR) +- container_flags |= NETSNMP_ACCESS_IPADDRESS_INIT_ADDL_IDX_BY_ADDR; + container = netsnmp_access_ipaddress_container_init(container_flags); + } + if (NULL == container) { +@@ -129,6 +186,9 @@ netsnmp_access_ipaddress_container_load( + container = NULL; + } + ++ if (container) ++ container = _remove_duplicates(container, container_flags); ++ + return container; + } + +diff -urNp old/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable_data_access.c new/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable_data_access.c +--- old/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable_data_access.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/agent/mibgroup/ip-mib/ipAddressTable/ipAddressTable_data_access.c 2017-04-04 13:26:34.332529808 +0200 +@@ -137,6 +137,13 @@ ipAddressTable_container_init(netsnmp_co + *container_ptr_ptr = + netsnmp_container_find("ipAddressTable:table_container"); + if (NULL != *container_ptr_ptr) { ++ /* ++ * The container has ALLOW_DUPLICATES flag to speed up CONTAINER_INSERT ++ * operations (it does not need to check for duplicates), however we ++ * (manually) ensure that we won't insert any duplicates there. ++ */ ++ int rc; ++ CONTAINER_SET_OPTIONS(*container_ptr_ptr, CONTAINER_KEY_ALLOW_DUPLICATES, rc); + (*container_ptr_ptr)->container_name = strdup("ipAddressTable"); + ipAddressTable_container_load(*container_ptr_ptr); + CONTAINER_FOR_EACH(*container_ptr_ptr, +@@ -205,8 +212,9 @@ static void + _check_entry_for_updates(ipAddressTable_rowreq_ctx * rowreq_ctx, + void **magic) + { +- netsnmp_container *ipaddress_container = (netsnmp_container*)magic[0]; ++ netsnmp_container *ipaddress_container = magic[0]; + netsnmp_container *to_delete = (netsnmp_container*)magic[1]; ++ netsnmp_container *to_ignore = (netsnmp_container *) magic[2]; + + /* + * check for matching entry using secondary index. +@@ -234,10 +242,21 @@ _check_entry_for_updates(ipAddressTable_ + rowreq_ctx->ipAddressLastChanged = netsnmp_get_agent_uptime(); + + /* +- * remove entry from ifcontainer ++ * Remember not to add this entry from 'ipaddress_container' to 'container' later. ++ * Simple CONTAINER_REMOVE(ipaddress_container, ..) would be slow. + */ +- CONTAINER_REMOVE(ipaddress_container, ipaddress_entry); +- netsnmp_access_ipaddress_entry_free(ipaddress_entry); ++ if (NULL == to_ignore) { ++ magic[2] = to_ignore = netsnmp_container_find("access_ipaddress:table_container"); ++ if (NULL == to_ignore) { ++ snmp_log(LOG_ERR, "couldn't create ignore container\n"); ++ } else { ++ /* to speed up insertion */ ++ int rc; ++ CONTAINER_SET_OPTIONS(to_ignore, CONTAINER_KEY_ALLOW_DUPLICATES, rc); ++ } ++ } ++ if (NULL != to_ignore) ++ CONTAINER_INSERT(to_ignore, ipaddress_entry); + } + } + +@@ -246,8 +265,11 @@ _check_entry_for_updates(ipAddressTable_ + */ + static void + _add_new_entry(netsnmp_ipaddress_entry *ipaddress_entry, +- netsnmp_container *container) ++ void **magic) + { ++ netsnmp_container *container = magic[0]; ++ netsnmp_container *to_ignore = magic[2]; ++ + ipAddressTable_rowreq_ctx *rowreq_ctx; + + DEBUGMSGTL(("ipAddressTable:access", "creating new entry\n")); +@@ -255,6 +277,11 @@ _add_new_entry(netsnmp_ipaddress_entry * + netsnmp_assert(NULL != ipaddress_entry); + netsnmp_assert(NULL != container); + ++ if (to_ignore && CONTAINER_FIND(to_ignore, ipaddress_entry)) { ++ /* this entry already is in 'container', skip it */ ++ return; ++ } ++ + /* + * allocate an row context and set the index(es) + */ +@@ -329,36 +356,44 @@ int + ipAddressTable_container_load(netsnmp_container *container) + { + netsnmp_container *ipaddress_container; +- void *tmp_ptr[2]; ++ void *tmp_ptr[3]; + + DEBUGMSGTL(("verbose:ipAddressTable:ipAddressTable_cache_load", + "called\n")); + + /* +- * TODO:351:M: |-> Load/update data in the ipAddressTable container. ++ * Load/update data in the ipAddressTable container. + * loop over your ipAddressTable data, allocate a rowreq context, + * set the index(es) [and data, optionally] and insert into + * the container. + */ ++ /* ++ * netsnmp_access_ipaddress_container_load makes sure that ++ * ipaddress_container does not contain any duplicate entries, ++ */ ++ + ipaddress_container = + netsnmp_access_ipaddress_container_load(NULL, + NETSNMP_ACCESS_IPADDRESS_LOAD_ADDL_IDX_BY_ADDR); + /* + * we just got a fresh copy of interface data. compare it to + * what we've already got, and make any adjustments, saving +- * missing addresses to be deleted. ++ * missing addresses to be deleted. Also, prune interfaces in ++ * ipaddress_container, so only the new interfaces remain. + */ + tmp_ptr[0] = ipaddress_container->next; +- tmp_ptr[1] = NULL; ++ tmp_ptr[1] = NULL; /* list of interfaces to be removed from 'container' */ ++ tmp_ptr[2] = NULL; /* list of interfaces to be ignored in ipaddress_container */ + CONTAINER_FOR_EACH(container, (netsnmp_container_obj_func *) + _check_entry_for_updates, tmp_ptr); + + /* + * now add any new interfaces + */ ++ tmp_ptr[0] = container; + CONTAINER_FOR_EACH(ipaddress_container, + (netsnmp_container_obj_func *) _add_new_entry, +- container); ++ tmp_ptr); + + /* + * free the container. we've either claimed each entry, or released it, +@@ -396,6 +431,19 @@ ipAddressTable_container_load(netsnmp_co + */ + CONTAINER_REMOVE(tmp_container, NULL); + } ++ CONTAINER_FREE(tmp_container); ++ } ++ ++ if (NULL != tmp_ptr[2]) { ++ /* list of interfaces to be ignored in ipaddress_container - free it */ ++ netsnmp_container *to_ignore = (netsnmp_container *) tmp_ptr[2]; ++ netsnmp_ipaddress_entry *ipaddress_entry; ++ while (CONTAINER_SIZE(to_ignore)) { ++ ipaddress_entry = (netsnmp_ipaddress_entry*)CONTAINER_FIRST(to_ignore); ++ CONTAINER_REMOVE(to_ignore, ipaddress_entry); ++ netsnmp_access_ipaddress_entry_free(ipaddress_entry); ++ } ++ CONTAINER_FREE(to_ignore); + } + + DEBUGMSGT(("verbose:ipAddressTable:ipAddressTable_cache_load", +diff -urNp old/agent/mibgroup/mibII/ipAddr.c new/agent/mibgroup/mibII/ipAddr.c +--- old/agent/mibgroup/mibII/ipAddr.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/agent/mibgroup/mibII/ipAddr.c 2017-04-04 13:28:56.547268946 +0200 +@@ -493,14 +493,16 @@ Address_Scan_Next(Index, Retin_ifaddr) + } + + #elif defined(linux) ++#include + static struct ifreq *ifr; + static int ifr_counter; + + static void + Address_Scan_Init(void) + { +- int num_interfaces = 0; ++ int i; + int fd; ++ int lastlen = 0; + + /* get info about all interfaces */ + +@@ -508,30 +510,45 @@ Address_Scan_Init(void) + SNMP_FREE(ifc.ifc_buf); + ifr_counter = 0; + +- do ++ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { +- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) +- { +- DEBUGMSGTL(("snmpd", "socket open failure in Address_Scan_Init\n")); +- return; +- } +- num_interfaces += 16; +- +- ifc.ifc_len = sizeof(struct ifreq) * num_interfaces; +- ifc.ifc_buf = (char*) realloc(ifc.ifc_buf, ifc.ifc_len); +- +- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) +- { +- ifr=NULL; +- close(fd); +- return; +- } +- close(fd); ++ DEBUGMSGTL(("snmpd", "socket open failure in Address_Scan_Init\n")); ++ return; ++ } ++ ++ /* ++ * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF ++ * on some platforms; see W. R. Stevens, ``Unix Network Programming ++ * Volume I'', p.435... ++ */ ++ ++ for (i = 8;; i *= 2) { ++ ifc.ifc_len = sizeof(struct ifreq) * i; ++ ifc.ifc_req = calloc(i, sizeof(struct ifreq)); ++ ++ if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { ++ if (errno != EINVAL || lastlen != 0) { ++ /* ++ * Something has gone genuinely wrong... ++ */ ++ snmp_log(LOG_ERR, "bad rc from ioctl, errno %d", errno); ++ SNMP_FREE(ifc.ifc_buf); ++ close(fd); ++ return; ++ } ++ } else { ++ if (ifc.ifc_len == lastlen) { ++ /* ++ * The length is the same as the last time; we're done... ++ */ ++ break; ++ } ++ lastlen = ifc.ifc_len; ++ } ++ free(ifc.ifc_buf); /* no SNMP_FREE, getting ready to reassign */ + } +- while (ifc.ifc_len >= (sizeof(struct ifreq) * num_interfaces)); +- +- ifr = ifc.ifc_req; + close(fd); ++ ifr = ifc.ifc_req; + } + + /* diff --git a/SOURCES/net-snmp-5.7.2-large-fdset.patch b/SOURCES/net-snmp-5.7.2-large-fdset.patch new file mode 100644 index 0000000..cef9d46 --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-large-fdset.patch @@ -0,0 +1,215 @@ +diff -urNp old/include/net-snmp/library/large_fd_set.h new/include/net-snmp/library/large_fd_set.h +--- old/include/net-snmp/library/large_fd_set.h 2012-10-10 00:28:58.000000000 +0200 ++++ new/include/net-snmp/library/large_fd_set.h 2017-04-04 14:36:27.307180033 +0200 +@@ -55,8 +55,9 @@ extern "C" { + * Number of bytes needed to store a number of file descriptors as a + * struct fd_set. + */ +-#define NETSNMP_FD_SET_BYTES(setsize) \ +- (sizeof(fd_set) + ((setsize) - FD_SETSIZE) * sizeof(SOCKET)) ++#define NETSNMP_FD_SET_BYTES(setsize) \ ++ (sizeof(fd_set) + ((setsize) > FD_SETSIZE ? \ ++ ((setsize) - FD_SETSIZE) * sizeof(SOCKET) : 0)) + + /** Remove all sockets from the set *fdset. */ + #define NETSNMP_LARGE_FD_ZERO(fdset) \ +@@ -91,9 +92,10 @@ int netsnmp_large_fd_is_set(SOCKET fd + * Number of bytes needed to store a number of file descriptors as a + * struct fd_set. + */ +-#define NETSNMP_FD_SET_BYTES(setsize) \ +- (sizeof(fd_set) + NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \ +- * NETSNMP_FD_MASK_SIZE) ++#define NETSNMP_FD_SET_BYTES(setsize) \ ++ (sizeof(fd_set) + ((setsize) > FD_SETSIZE ? \ ++ NETSNMP_FD_SET_ELEM_COUNT((setsize) - FD_SETSIZE) \ ++ * NETSNMP_FD_MASK_SIZE : 0)) + + /** Remove all file descriptors from the set *fdset. */ + #define NETSNMP_LARGE_FD_ZERO(fdset) \ +diff -urNp old/snmplib/large_fd_set.c new/snmplib/large_fd_set.c +--- old/snmplib/large_fd_set.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/snmplib/large_fd_set.c 2017-04-04 15:03:20.580810774 +0200 +@@ -21,6 +21,10 @@ + + #if !defined(cygwin) && defined(HAVE_WINSOCK_H) + ++#define LFD_SET(n, p) FD_SET(n, p) ++#define LFD_CLR(n, p) FD_CLR(n, p) ++#define LFD_ISSET(n, p) FD_ISSET(n, p) ++ + void + netsnmp_large_fd_setfd(SOCKET fd, netsnmp_large_fd_set * fdset) + { +@@ -28,18 +32,18 @@ netsnmp_large_fd_setfd(SOCKET fd, netsnm + + netsnmp_assert(fd != INVALID_SOCKET); + +- if (fdset->lfs_set.fd_count == fdset->lfs_setsize) ++ if (fdset->lfs_setptr->fd_count == fdset->lfs_setsize) + netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1)); + +- for (i = 0; i < fdset->lfs_set.fd_count; i++) { +- if (fdset->lfs_set.fd_array[i] == (SOCKET) (fd)) ++ for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { ++ if (fdset->lfs_setptr->fd_array[i] == fd) + break; + } + +- if (i == fdset->lfs_set.fd_count +- && fdset->lfs_set.fd_count < fdset->lfs_setsize) { +- fdset->lfs_set.fd_count++; +- fdset->lfs_set.fd_array[i] = fd; ++ if (i == fdset->lfs_setptr->fd_count && ++ fdset->lfs_setptr->fd_count < fdset->lfs_setsize) { ++ fdset->lfs_setptr->fd_count++; ++ fdset->lfs_setptr->fd_array[i] = fd; + } + } + +@@ -50,14 +54,14 @@ netsnmp_large_fd_clr(SOCKET fd, netsnmp_ + + netsnmp_assert(fd != INVALID_SOCKET); + +- for (i = 0; i < fdset->lfs_set.fd_count; i++) { +- if (fdset->lfs_set.fd_array[i] == fd) { +- while (i < fdset->lfs_set.fd_count - 1) { +- fdset->lfs_set.fd_array[i] = +- fdset->lfs_set.fd_array[i + 1]; ++ for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { ++ if (fdset->lfs_setptr->fd_array[i] == fd) { ++ while (i < fdset->lfs_setptr->fd_count - 1) { ++ fdset->lfs_setptr->fd_array[i] = ++ fdset->lfs_setptr->fd_array[i + 1]; + i++; + } +- fdset->lfs_set.fd_count--; ++ fdset->lfs_setptr->fd_count--; + break; + } + } +@@ -70,8 +74,8 @@ netsnmp_large_fd_is_set(SOCKET fd, netsn + + netsnmp_assert(fd != INVALID_SOCKET); + +- for (i = 0; i < fdset->lfs_set.fd_count; i++) { +- if (fdset->lfs_set.fd_array[i] == fd) ++ for (i = 0; i < fdset->lfs_setptr->fd_count; i++) { ++ if (fdset->lfs_setptr->fd_array[i] == fd) + return 1; + } + return 0; +@@ -79,6 +83,43 @@ netsnmp_large_fd_is_set(SOCKET fd, netsn + + #else + ++ /* ++ * Recent versions of glibc trigger abort() if FD_SET(), FD_CLR() or ++ * FD_ISSET() is invoked with n >= FD_SETSIZE. Hence these replacement ++ * functions. However, since NFDBITS != 8 * sizeof(fd_set.fds_bits[0]) for at ++ * least HP-UX on ia64 and since that combination uses big endian, use the ++ * macros from on such systems. ++ */ ++NETSNMP_STATIC_INLINE void LFD_SET(unsigned n, fd_set *p) ++{ ++ enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; ++ ++ if (nfdbits == NFDBITS) ++ p->fds_bits[n / nfdbits] |= (1ULL << (n % nfdbits)); ++ else ++ FD_SET(n, p); ++} ++ ++NETSNMP_STATIC_INLINE void LFD_CLR(unsigned n, fd_set *p) ++{ ++ enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; ++ ++ if (nfdbits == NFDBITS) ++ p->fds_bits[n / nfdbits] &= ~(1ULL << (n % nfdbits)); ++ else ++ FD_CLR(n, p); ++} ++ ++NETSNMP_STATIC_INLINE unsigned LFD_ISSET(unsigned n, const fd_set *p) ++{ ++ enum { nfdbits = 8 * sizeof(p->fds_bits[0]) }; ++ ++ if (nfdbits == NFDBITS) ++ return (p->fds_bits[n / nfdbits] & (1ULL << (n % nfdbits))) != 0; ++ else ++ return FD_ISSET(n, p) != 0; ++} ++ + void + netsnmp_large_fd_setfd(int fd, netsnmp_large_fd_set * fdset) + { +@@ -87,7 +128,7 @@ netsnmp_large_fd_setfd(int fd, netsnmp_l + while (fd >= (int)fdset->lfs_setsize) + netsnmp_large_fd_set_resize(fdset, 2 * (fdset->lfs_setsize + 1)); + +- FD_SET(fd, fdset->lfs_setptr); ++ LFD_SET(fd, fdset->lfs_setptr); + } + + void +@@ -96,7 +137,7 @@ netsnmp_large_fd_clr(int fd, netsnmp_lar + netsnmp_assert(fd >= 0); + + if ((unsigned)fd < fdset->lfs_setsize) +- FD_CLR(fd, fdset->lfs_setptr); ++ LFD_CLR(fd, fdset->lfs_setptr); + } + + int +@@ -104,7 +145,7 @@ netsnmp_large_fd_is_set(int fd, netsnmp_ + { + netsnmp_assert(fd >= 0); + +- return (unsigned)fd < fdset->lfs_setsize && FD_ISSET(fd, fdset->lfs_setptr); ++ return ((unsigned)fd < fdset->lfs_setsize && LFD_ISSET(fd, fdset->lfs_setptr)); + } + + #endif +@@ -174,22 +215,24 @@ netsnmp_large_fd_set_resize(netsnmp_larg + } + + #if defined(cygwin) || !defined(HAVE_WINSOCK_H) +- { ++ /* ++ * Unix: when enlarging, clear the file descriptors defined in the ++ * resized *fdset but that were not defined in the original *fdset. ++ */ ++ if ( fdset->lfs_setsize == 0 && setsize == FD_SETSIZE ) { ++ /* In this case we can use the OS's FD_ZERO */ ++ FD_ZERO(fdset->lfs_setptr); ++ } else { + int i; +- +- /* +- * Unix: when enlarging, clear the file descriptors defined in the +- * resized *fdset but that were not defined in the original *fdset. +- */ + for (i = fdset->lfs_setsize; i < setsize; i++) +- FD_CLR(i, fdset->lfs_setptr); ++ LFD_CLR(i, fdset->lfs_setptr); + } + #endif + + fdset->lfs_setsize = setsize; + #if !defined(cygwin) && defined(HAVE_WINSOCK_H) +- if (setsize < fdset->lfs_set.fd_count) +- fdset->lfs_set.fd_count = setsize; ++ if (setsize < fdset->lfs_setptr->fd_count) ++ fdset->lfs_setptr->fd_count = setsize; + #endif + success: + return 1; +@@ -197,7 +240,7 @@ success: + out_of_mem: + fdset->lfs_setsize = 0; + #if !defined(cygwin) && defined(HAVE_WINSOCK_H) +- fdset->lfs_set.fd_count = 0; ++ fdset->lfs_setptr->fd_count = 0; + #endif + return 0; + } diff --git a/SOURCES/net-snmp-5.7.2-max-msg-size.patch b/SOURCES/net-snmp-5.7.2-max-msg-size.patch new file mode 100644 index 0000000..be08e46 --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-max-msg-size.patch @@ -0,0 +1,12 @@ +diff -Npru old/agent/mibgroup/agentx/protocol.c new/agent/mibgroup/agentx/protocol.c +--- old/agent/mibgroup/agentx/protocol.c 2012-10-10 00:28:58.000000000 +0200 ++++ new/agent/mibgroup/agentx/protocol.c 2017-01-16 10:05:24.419201871 +0100 +@@ -1550,7 +1550,7 @@ agentx_parse(netsnmp_session * session, + size_t len) + { + register u_char *bufp = data; +- u_char buffer[SNMP_MAX_MSG_SIZE]; ++ u_char buffer[65535]; + oid oid_buffer[MAX_OID_LEN], end_oid_buf[MAX_OID_LEN]; + size_t buf_len = sizeof(buffer); + size_t oid_buf_len = MAX_OID_LEN; diff --git a/SOURCES/net-snmp-5.7.2-response-too-long.patch b/SOURCES/net-snmp-5.7.2-response-too-long.patch new file mode 100644 index 0000000..d8c2025 --- /dev/null +++ b/SOURCES/net-snmp-5.7.2-response-too-long.patch @@ -0,0 +1,12 @@ +diff -urNp old/snmplib/snmp_api.c new/snmplib/snmp_api.c +--- old/snmplib/snmp_api.c 2017-01-16 10:11:37.951994525 +0100 ++++ new/snmplib/snmp_api.c 2017-01-16 10:18:42.284631137 +0100 +@@ -4931,7 +4931,7 @@ _sess_async_send(void *sessp, + * specified in the received PDU. + */ + +- if (session->sndMsgMaxSize != 0 && length > session->sndMsgMaxSize) { ++ if (pdu->version == SNMP_VERSION_3 && session->sndMsgMaxSize != 0 && length > session->sndMsgMaxSize) { + DEBUGMSGTL(("sess_async_send", + "length of packet (%lu) exceeds session maximum (%lu)\n", + (unsigned long)length, (unsigned long)session->sndMsgMaxSize)); diff --git a/SPECS/net-snmp.spec b/SPECS/net-snmp.spec index 4364b65..d15029f 100644 --- a/SPECS/net-snmp.spec +++ b/SPECS/net-snmp.spec @@ -11,7 +11,7 @@ Summary: A collection of SNMP protocol tools and libraries Name: net-snmp Version: 5.7.2 -Release: 24%{?dist}.2 +Release: 28%{?dist} Epoch: 1 License: BSD @@ -89,7 +89,13 @@ Patch52: net-snmp-5.5-sensors-duplicate.patch Patch53: net-snmp-5.7.2-extend-close.patch Patch54: net-snmp-5.7.2-python-addr-size.patch Patch55: net-snmp-5.7.2-dot3-leak.patch -Patch56: net-snmp-5.7.2-agentx-disconnect-crash-part2.patch +Patch56: net-snmp-5.7.2-max-msg-size.patch +Patch57: net-snmp-5.7.2-response-too-long.patch +Patch58: net-snmp-5.7.2-agentx-disconnect-crash-part2.patch +Patch59: net-snmp-5.7.2-client-udp6.patch +Patch60: net-snmp-5.7.2-ipAddress-faster-load.patch +Patch61: net-snmp-5.7.2-large-fdset.patch +Patch62: net-snmp-5.7.2-duplicate-ipAddress.patch Requires(post): chkconfig Requires(preun): chkconfig @@ -178,6 +184,7 @@ Group: Development/Libraries Summary: The perl NET-SNMP module and the mib2c tool Requires: %{name}-libs = %{epoch}:%{version}-%{release}, perl Requires: %{name}-agent-libs = %{epoch}:%{version}-%{release} +Requires: %{name}-devel = %{epoch}:%{version}-%{release} BuildRequires: perl %description perl @@ -297,7 +304,13 @@ The net-snmp-sysvinit package provides SysV init scripts for Net-SNMP daemons. %patch53 -p1 -b .extend-close %patch54 -p1 -b .python-addr-size %patch55 -p1 -b .dot3-leak -%patch56 -p1 -b .agentx-disconnect-crash-part-2 +%patch56 -p1 -b .max-msg-size +%patch57 -p1 -b .response-too-long +%patch58 -p1 -b .agentx-crash-part-2 +%patch59 -p1 -b .client-udp6 +%patch60 -p1 -b .ipAddress-faster-load +%patch61 -p1 -b .large-fdset +%patch62 -p1 -b .duplicate-ipAddress %ifarch sparc64 s390 s390x # disable failing test - see https://bugzilla.redhat.com/show_bug.cgi?id=680697 @@ -593,8 +606,21 @@ rm -rf ${RPM_BUILD_ROOT} %{_initrddir}/snmptrapd %changelog -* Thu Mar 30 2017 Josef Ridky - 1:5.7.2-24.2 -- Fixed issue with agentx disconnect crash (#1437346) +* Wed Apr 26 2017 Josef Ridky - 1:5.7.2-28 +- Restored message about duplicate IP address (#1442962) + +* Mon Apr 03 2017 Josef Ridky - 1:5.7.2-27 +- Allow clients to use UDPv6 addresses without 'udp6:' prefix (#1326850) +- snmpd: Speed up ipAddressTable loading. (#1327240) +- Fixed net-snmp segfault in netsnmp_copy_fd_set_to_large_fd_set (#1327200) +- Fixed issue with net-snmp-perl dependency on net-snmp-devel (#1438875) + +* Wed Mar 29 2017 Josef Ridky - 1:5.7.2-26 +- Fixed issue with agentx disconnet crash (#1404600) + +* Mon Jan 16 2017 Josef Ridky - 1:5.7.2-25 +- Fixed message buffer size (#1286693) +- Fixed problem with snmp too long error message (#1324306) * Fri Mar 18 2016 Jan Safranek - 1:5.7.2-24.1 - Fixed memory leak in ETHERLIKE-MIB (#1305933)