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
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to