The only functional change in this patch is that it is now allowed
to surround IPv4 addresses and hostnames with square brackets in
transport endpoint definitions.
---
include/net-snmp/library/snmpIPBaseDomain.h | 16 ++
include/net-snmp/library/snmpIPv4BaseDomain.h | 2 +
include/net-snmp/library/snmpIPv6BaseDomain.h | 2 +
snmplib/transports/snmpIPBaseDomain.c | 79 +++++++
snmplib/transports/snmpIPv4BaseDomain.c | 92 ++------
snmplib/transports/snmpIPv6BaseDomain.c | 204 ++----------------
win32/libsnmp/Makefile.in | 1 +
win32/libsnmp_dll/Makefile.in | 1 +
8 files changed, 134 insertions(+), 263 deletions(-)
create mode 100644 include/net-snmp/library/snmpIPBaseDomain.h
create mode 100644 snmplib/transports/snmpIPBaseDomain.c
diff --git a/include/net-snmp/library/snmpIPBaseDomain.h
b/include/net-snmp/library/snmpIPBaseDomain.h
new file mode 100644
index 000000000000..fb79a9365c4e
--- /dev/null
+++ b/include/net-snmp/library/snmpIPBaseDomain.h
@@ -0,0 +1,16 @@
+#ifndef _SNMPIPBASEDOMAIN_H_
+#define _SNMPIPBASEDOMAIN_H_
+
+/**
+ * SNMP endpoint with the network name in ASCII format.
+ * @addr: Network address or host name as an ASCII string.
+ * @port: Port number in host byte format.
+ */
+struct netsnmp_ep_str {
+ char addr[64];
+ uint16_t port;
+};
+
+int netsnmp_parse_ep_str(struct netsnmp_ep_str *ep_str, const char *endpoint);
+
+#endif /* _SNMPIPBASEDOMAIN_H_ */
diff --git a/include/net-snmp/library/snmpIPv4BaseDomain.h
b/include/net-snmp/library/snmpIPv4BaseDomain.h
index cb6a4585cf48..71804e3b1d72 100644
--- a/include/net-snmp/library/snmpIPv4BaseDomain.h
+++ b/include/net-snmp/library/snmpIPv4BaseDomain.h
@@ -9,6 +9,8 @@
#include <net-snmp/library/snmp_transport.h>
+config_require(IPBase)
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/include/net-snmp/library/snmpIPv6BaseDomain.h
b/include/net-snmp/library/snmpIPv6BaseDomain.h
index 5c7d11cfd560..2f44e6a1b088 100644
--- a/include/net-snmp/library/snmpIPv6BaseDomain.h
+++ b/include/net-snmp/library/snmpIPv6BaseDomain.h
@@ -7,6 +7,8 @@
#include <netinet/in.h>
#endif
+config_require(IPBase)
+
#include <net-snmp/library/snmp_transport.h>
#ifdef __cplusplus
diff --git a/snmplib/transports/snmpIPBaseDomain.c
b/snmplib/transports/snmpIPBaseDomain.c
new file mode 100644
index 000000000000..ac94ba73840d
--- /dev/null
+++ b/snmplib/transports/snmpIPBaseDomain.c
@@ -0,0 +1,79 @@
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/types.h>
+#include <net-snmp/library/system.h>
+#include <net-snmp/library/snmpIPBaseDomain.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+static int isnumber(const char *cp)
+{
+ while (isdigit((uint8_t)*cp))
+ cp++;
+ return *cp == '\0';
+}
+
+/**
+ * Parse a Net-SNMP endpoint name.
+ * @ep_str: Parsed endpoint name.
+ * @endpoint: Endpoint specification in the format [<address>]:[<port>] or
+ * <port>.
+ *
+ * Only overwrite those fields of *@ep_str that have been set in
+ * @endpoint. Returns 1 upon success and 0 upon failure.
+ */
+int netsnmp_parse_ep_str(struct netsnmp_ep_str *ep_str, const char *endpoint)
+{
+ char *dup, *cp, *addrstr = NULL, *portstr = NULL;
+ unsigned port;
+
+ if (!endpoint)
+ return 0;
+
+ dup = strdup(endpoint);
+ if (!dup)
+ return 0;
+
+ cp = dup;
+ if (isnumber(cp)) {
+ portstr = cp;
+ } else {
+ if (*cp == '[') {
+ addrstr = cp + 1;
+ cp = strchr(cp, ']');
+ if (cp) {
+ cp[0] = '\0';
+ cp++;
+ } else {
+ goto invalid;
+ }
+ } else if (*cp != ':') {
+ addrstr = cp;
+ cp = strrchr(cp, ':');
+ }
+ if (cp && *cp == ':') {
+ *cp++ = '\0';
+ portstr = cp;
+ if (!isnumber(cp))
+ goto invalid;
+ } else if (cp && *cp) {
+ goto invalid;
+ }
+ }
+
+ if (addrstr)
+ strlcpy(ep_str->addr, addrstr, sizeof(ep_str->addr));
+ if (portstr) {
+ port = atoi(portstr);
+ if (port > 0 && port <= 0xffff)
+ ep_str->port = port;
+ else
+ goto invalid;
+ }
+
+ free(dup);
+ return 1;
+
+invalid:
+ free(dup);
+ return 0;
+}
diff --git a/snmplib/transports/snmpIPv4BaseDomain.c
b/snmplib/transports/snmpIPv4BaseDomain.c
index 37ef72d4ed42..003e53a49e45 100644
--- a/snmplib/transports/snmpIPv4BaseDomain.c
+++ b/snmplib/transports/snmpIPv4BaseDomain.c
@@ -4,6 +4,7 @@
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/types.h>
+#include <net-snmp/library/snmpIPBaseDomain.h>
#include <net-snmp/library/snmpIPv4BaseDomain.h>
#include <net-snmp/library/snmp_assert.h>
@@ -56,6 +57,7 @@ int
netsnmp_sockaddr_in2(struct sockaddr_in *addr,
const char *inpeername, const char *default_target)
{
+ struct netsnmp_ep_str ep_str;
int ret;
if (addr == NULL) {
@@ -72,106 +74,42 @@ netsnmp_sockaddr_in2(struct sockaddr_in *addr,
addr->sin_family = AF_INET;
addr->sin_port = htons((u_short)SNMP_PORT);
+ memset(&ep_str, 0, sizeof(ep_str));
{
int port = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
NETSNMP_DS_LIB_DEFAULT_PORT);
if (port != 0) {
- addr->sin_port = htons((u_short)port);
- } else if (default_target != NULL)
+ ep_str.port = port;
+ } else if (default_target != NULL) {
netsnmp_sockaddr_in2(addr, default_target, NULL);
- }
-
- if (inpeername != NULL && *inpeername != '\0') {
- const char *host, *port;
- char *peername = NULL;
- char *cp;
- /*
- * Duplicate the peername because we might want to mank around with
- * it.
- */
-
- peername = strdup(inpeername);
- if (peername == NULL) {
- return 0;
- }
-
- /*
- * Try and extract an appended port number.
- */
- cp = strchr(peername, ':');
- if (cp != NULL) {
- *cp = '\0';
- port = cp + 1;
- host = peername;
- } else {
- host = NULL;
- port = peername;
+ strlcpy(ep_str.addr, inet_ntoa(addr->sin_addr),
sizeof(ep_str.addr));
+ ep_str.port = ntohs(addr->sin_port);
}
+ }
- /*
- * Try to convert the user port specifier
- */
- if (port && *port == '\0')
- port = NULL;
-
- if (port != NULL) {
- long int l;
- char* ep;
-
- DEBUGMSGTL(("netsnmp_sockaddr_in", "check user service %s\n",
- port));
-
- l = strtol(port, &ep, 10);
- if (ep != port && *ep == '\0' && 0 <= l && l <= 0x0ffff)
- addr->sin_port = htons((u_short)l);
- else {
- if (host == NULL) {
- DEBUGMSGTL(("netsnmp_sockaddr_in",
- "servname not numeric, "
- "check if it really is a destination)\n"));
- host = port;
- port = NULL;
- } else {
- DEBUGMSGTL(("netsnmp_sockaddr_in",
- "servname not numeric\n"));
- free(peername);
- return 0;
- }
- }
- }
-
- /*
- * Try to convert the user host specifier
- */
- if (host && *host == '\0')
- host = NULL;
-
- if (host != NULL) {
- DEBUGMSGTL(("netsnmp_sockaddr_in",
- "check destination %s\n", host));
-
-
- if (strcmp(peername, "255.255.255.255") == 0 ) {
+ if (inpeername && *inpeername != '\0') {
+ if (netsnmp_parse_ep_str(&ep_str, inpeername)) {
+ if (ep_str.port)
+ addr->sin_port = htons(ep_str.port);
+ if (strcmp(ep_str.addr, "255.255.255.255") == 0 ) {
/*
* The explicit broadcast address hack
*/
DEBUGMSGTL(("netsnmp_sockaddr_in", "Explicit UDP
broadcast\n"));
addr->sin_addr.s_addr = INADDR_NONE;
} else {
- ret =
- netsnmp_gethostbyname_v4(peername, &addr->sin_addr.s_addr);
+ ret = netsnmp_gethostbyname_v4(ep_str.addr,
+ &addr->sin_addr.s_addr);
if (ret < 0) {
DEBUGMSGTL(("netsnmp_sockaddr_in",
"couldn't resolve hostname\n"));
- free(peername);
return 0;
}
DEBUGMSGTL(("netsnmp_sockaddr_in",
"hostname (resolved okay)\n"));
}
}
- free(peername);
}
/*
diff --git a/snmplib/transports/snmpIPv6BaseDomain.c
b/snmplib/transports/snmpIPv6BaseDomain.c
index b1c1afce3ded..600bc602428b 100644
--- a/snmplib/transports/snmpIPv6BaseDomain.c
+++ b/snmplib/transports/snmpIPv6BaseDomain.c
@@ -15,6 +15,7 @@
#ifdef NETSNMP_ENABLE_IPV6
#include <net-snmp/types.h>
+#include <net-snmp/library/snmpIPBaseDomain.h>
#include <net-snmp/library/snmpIPv6BaseDomain.h>
#include <net-snmp/library/system.h>
#include <net-snmp/library/snmp_assert.h>
@@ -247,9 +248,7 @@ int
netsnmp_sockaddr_in6_2(struct sockaddr_in6 *addr,
const char *inpeername, const char *default_target)
{
- char *cp = NULL, *peername = NULL;
char debug_addr[INET6_ADDRSTRLEN];
- int portno;
if (addr == NULL) {
return 0;
@@ -275,205 +274,38 @@ netsnmp_sockaddr_in6_2(struct sockaddr_in6 *addr,
}
if (inpeername != NULL) {
- /*
- * Duplicate the peername because we might want to mank around with
- * it.
- */
-
- peername = strdup(inpeername);
- if (peername == NULL) {
- return 0;
- }
-
- cp = peername;
- if (*cp == ':') cp++;
- portno = atoi(cp);
- while (*cp && isdigit((unsigned char) *cp)) cp++;
- if (!*cp && portno != 0) {
- /*
- * Okay, it looks like JUST a port number.
- */
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "totally numeric: %d\n",
- portno));
- addr->sin6_port = htons((u_short)portno);
- goto resolved;
- }
-
- /*
- * See if it is an IPv6 address covered with square brackets. Also
check
- * for an appended :port.
- */
- if (*peername == '[') {
- cp = strchr(peername, ']');
- if (cp != NULL) {
- /*
- * See if it is an IPv6 link-local address with interface
- * name as <zone_id>, like fe80::1234%eth0.
- * Please refer to the internet draft, IPv6 Scoped Address
Architecture
- *
http://www.ietf.org/internet-drafts/draft-ietf-ipngwg-scoping-arch-04.txt
- *
- */
- char *scope_id;
-#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- unsigned int if_index = 0;
-#endif
- *cp = '\0';
- scope_id = strchr(peername + 1, '%');
- if (scope_id != NULL) {
- *scope_id = '\0';
-#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- if_index = netsnmp_if_nametoindex(scope_id + 1);
-#endif
- }
- if (*(cp + 1) == ':') {
- portno = atoi(cp+2);
- if (portno != 0 &&
- inet_pton(AF_INET6, peername + 1,
- (void *) &(addr->sin6_addr))) {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2",
- "IPv6 address with port suffix :%d\n",
- portno));
- if (portno > 0 && portno <= 0xffff) {
- addr->sin6_port = htons((u_short)portno);
- } else {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "invalid
port number: %d", portno));
- free(peername);
- return 0;
- }
-
-#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID)
- addr->sin6_scope_id = if_index;
-#endif
- goto resolved;
- }
- } else {
- if (inet_pton
- (AF_INET6, peername + 1,
- (void *) &(addr->sin6_addr))) {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2",
- "IPv6 address with square brackets\n"));
- portno = ntohs(addr->sin6_port);
- if (portno == 0)
- portno = netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID,
-
NETSNMP_DS_LIB_DEFAULT_PORT);
- if (portno <= 0)
- portno = SNMP_PORT;
- addr->sin6_port = htons((u_short)portno);
+ struct netsnmp_ep_str ep_str;
+
+ memset(&ep_str, 0, sizeof(ep_str));
+ if (netsnmp_parse_ep_str(&ep_str, inpeername)) {
+ DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "split: [%s]:%d",
+ ep_str.addr, ep_str.port));
+ if (ep_str.addr[0]) {
+ char *scope_id;
+
+ scope_id = strchr(ep_str.addr, '%');
+ if (scope_id) {
+ *scope_id = '0';
#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID)
- addr->sin6_scope_id = if_index;
-#endif
- goto resolved;
- }
- }
- if (scope_id != NULL) {
- *scope_id = '%';
- }
- *cp = ']';
- }
- }
-
- cp = strrchr(peername, ':');
- if (cp != NULL) {
- char *scope_id;
-#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- unsigned int if_index = 0;
-#endif
- *cp = '\0';
- scope_id = strchr(peername + 1, '%');
- if (scope_id != NULL) {
- *scope_id = '\0';
-#if HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- if_index = netsnmp_if_nametoindex(scope_id + 1);
+ addr->sin6_scope_id = netsnmp_if_nametoindex(scope_id + 1);
#endif
- }
- portno = atoi(cp + 1);
- if (portno != 0 &&
- inet_pton(AF_INET6, peername,
- (void *) &(addr->sin6_addr))) {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2",
- "IPv6 address with port suffix :%d\n",
- atoi(cp + 1)));
- if (portno > 0 && portno <= 0xffff) {
- addr->sin6_port = htons((u_short)portno);
- } else {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "invalid port
number: %d", portno));
- free(peername);
- return 0;
}
-
-#if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID)
- addr->sin6_scope_id = if_index;
-#endif
- goto resolved;
- }
- if (scope_id != NULL) {
- *scope_id = '%';
- }
- *cp = ':';
- }
-
- /*
- * See if it is JUST an IPv6 address.
- */
- if (inet_pton(AF_INET6, peername, (void *) &(addr->sin6_addr))) {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "just IPv6 address\n"));
- goto resolved;
- }
-
- /*
- * Well, it must be a hostname then, possibly with an appended :port.
- * Sort that out first.
- */
-
- cp = strrchr(peername, ':');
- if (cp != NULL) {
- *cp = '\0';
- portno = atoi(cp + 1);
- if (portno != 0) {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2",
- "hostname(?) with port suffix :%d\n",
- portno));
- if (portno > 0 && portno <= 0xffff) {
- addr->sin6_port = htons((u_short)portno);
- } else {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "invalid port
number: %d", portno));
- free(peername);
+ if (!inet_pton(AF_INET6, ep_str.addr, &addr->sin6_addr) &&
+ !netsnmp_resolve_v6_hostname(&addr->sin6_addr,
ep_str.addr))
return 0;
- }
-
- } else {
- /*
- * No idea, looks bogus but we might as well pass the full
thing to
- * the name resolver below.
- */
- *cp = ':';
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2",
- "hostname(?) with embedded ':'?\n"));
}
- /*
- * Fall through.
- */
+ if (ep_str.port)
+ addr->sin6_port = htons(ep_str.port);
}
- if (peername[0] == '\0') {
- DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "empty hostname\n"));
- free(peername);
- return 0;
- }
- if (!netsnmp_resolve_v6_hostname(&addr->sin6_addr, peername)) {
- free(peername);
- return 0;
- }
} else {
DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "NULL peername"));
return 0;
}
- resolved:
DEBUGMSGTL(("netsnmp_sockaddr_in6_2", "return { AF_INET6, [%s]:%hu }\n",
inet_ntop(AF_INET6, &addr->sin6_addr, debug_addr,
sizeof(debug_addr)), ntohs(addr->sin6_port)));
- free(peername);
return 1;
}
diff --git a/win32/libsnmp/Makefile.in b/win32/libsnmp/Makefile.in
index d5e173e9a124..88d24533abf6 100644
--- a/win32/libsnmp/Makefile.in
+++ b/win32/libsnmp/Makefile.in
@@ -55,6 +55,7 @@ LIB32_OBJS= \
"$(INTDIR)\snmp-tc.obj" \
"$(INTDIR)\snmp.obj" \
"$(INTDIR)\snmpCallbackDomain.obj" \
+ "$(INTDIR)\snmpIPBaseDomain.obj" \
"$(INTDIR)\snmpIPv4BaseDomain.obj" \
"$(INTDIR)\snmpSocketBaseDomain.obj" \
"$(INTDIR)\snmpTCPBaseDomain.obj" \
diff --git a/win32/libsnmp_dll/Makefile.in b/win32/libsnmp_dll/Makefile.in
index 3d05633b8856..bd36672dcdf4 100644
--- a/win32/libsnmp_dll/Makefile.in
+++ b/win32/libsnmp_dll/Makefile.in
@@ -55,6 +55,7 @@ LINK32_OBJS= \
"$(INTDIR)\snmp-tc.obj" \
"$(INTDIR)\snmp.obj" \
"$(INTDIR)\snmpCallbackDomain.obj" \
+ "$(INTDIR)\snmpIPBaseDomain.obj" \
"$(INTDIR)\snmpIPv4BaseDomain.obj" \
"$(INTDIR)\snmpSocketBaseDomain.obj" \
"$(INTDIR)\snmpTCPBaseDomain.obj" \
--
2.19.1
_______________________________________________
Net-snmp-coders mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders