Fix clientaddr functionality. Includes further memory leak and newline fixes. Previously, the clientaddr option in snmp.conf was parsed, but the actual clientaddr was used to bind(), yet sendmsg() was still called with 0.0.0.0. This patch alters: - netsnmp_udp_fmtaddr: include both sides of addr_pair for debugging. - netsnmp_udp_transport: Set addr_pair->local_addr in the remote && client_socket path. - netsnmp_udp_transport: Print a debugging error on failure to bind() - netsnmp_udp_transport: Print out the full client open addr_pair data. Signed-off-by: Robin H. Johnson Status: Merged in upstream r16654 Tracking-URL: https://sourceforge.net/tracker/?func=detail&atid=312694&aid=1775124&group_id=12694 Further fixes: Revision 16681 add missing newline in debug msg Revision 16704 CHANGES: snmplib: BUG: Coverity #183: fix memory leak if IP_PKTINFO fails Revision 16716 CHANGES: snmplib: Do not leak memory whenever an udp address is formatted. Fixes bug: bugs.gentoo.org/180266 diff -Naur net-snmp-5.4.1.orig/snmplib/snmpUDPDomain.c net-snmp-5.4.1/snmplib/snmpUDPDomain.c --- net-snmp-5.4.1.orig/snmplib/snmpUDPDomain.c 2007-06-11 02:15:24.000000000 +0400 +++ net-snmp-5.4.1/snmplib/snmpUDPDomain.c 2007-12-27 18:15:56.000000000 +0300 @@ -104,11 +104,13 @@ char tmp[64]; to = (struct sockaddr_in *) &(addr_pair->remote_addr); if (to == NULL) { - return strdup("UDP: unknown"); + sprintf(tmp, "UDP: [%s]->unknown", + inet_ntoa(addr_pair->local_addr)); + } else { + sprintf(tmp, "UDP: [%s]->", inet_ntoa(addr_pair->local_addr)); + sprintf(tmp + strlen(tmp), "[%s]:%hd", + inet_ntoa(to->sin_addr), ntohs(to->sin_port)); } - - sprintf(tmp, "UDP: [%s]:%hu", - inet_ntoa(to->sin_addr), ntohs(to->sin_port)); return strdup(tmp); } } @@ -642,6 +644,7 @@ if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof sockopt) == -1) { DEBUGMSGTL(("netsnmp_udp", "couldn't set IP_PKTINFO: %s\n", strerror(errno))); + netsnmp_transport_free(t); return NULL; } DEBUGMSGTL(("netsnmp_udp", "set IP_PKTINFO\n")); @@ -667,10 +670,24 @@ if (client_socket) { struct sockaddr_in client_addr; netsnmp_sockaddr_in2(&client_addr, client_socket, NULL); + addr_pair.local_addr = client_addr.sin_addr; client_addr.sin_port = 0; - bind(t->sock, (struct sockaddr *)&client_addr, + rc = bind(t->sock, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)); + if ( rc != 0 ) { + DEBUGMSGTL(("netsnmp_udp", "failed to bind for clientaddr: %d %s\n", + errno, strerror(errno))); + netsnmp_udp_close(t); + netsnmp_transport_free(t); + return NULL; + } } + + str = netsnmp_udp_fmtaddr(NULL, (void *)&addr_pair, + sizeof(netsnmp_udp_addr_pair)); + DEBUGMSGTL(("netsnmp_udp", "client open %s\n", str)); + free(str); + /* * Save the (remote) address in the * transport-specific data pointer for later use by netsnmp_udp_send. @@ -839,12 +856,12 @@ if (host == NULL) { DEBUGMSGTL(("netsnmp_sockaddr_in", "servname not numeric, " - "check if it really is a destination)")); + "check if it really is a destination)\n")); host = port; port = NULL; } else { DEBUGMSGTL(("netsnmp_sockaddr_in", - "servname not numeric")); + "servname not numeric\n")); free(peername); return 0; }