[PATCH / request for votes] SNMP-TARGET-MIB: Fix snmpTargetAddrTAddress

Bart Van Assche <[email protected]>
Newsgroups gmane.network.net-snmp.devel
Message-ID <[email protected]>
When I fixed the fmtaddr implementation in several Net-SNMP transports I
hadn't noticed that these changes broke the target MIB. Hence this patch
that fixes the target MIB.

See also https://sourceforge.net/p/net-snmp/bugs/2871/.

Reported-by: Anders Wallin <[email protected]>
Fixes: 3bd8dc8b2d90 ("snmplib/transports: Avoid that the create_from_ostring methods truncate IPv6 addresses")
---
 .../notification/snmpNotifyTable_data.c       |  6 ++-
 agent/mibgroup/target/snmpTargetAddrEntry.c   |  6 +--
 .../target/snmpTargetAddrEntry_data.h         |  2 +-
 include/net-snmp/library/snmpIPv4BaseDomain.h |  4 ++
 include/net-snmp/library/snmpIPv6BaseDomain.h |  6 +++
 include/net-snmp/library/snmp_transport.h     |  9 +++-
 snmplib/transports/snmpAAL5PVCDomain.c        | 41 ++++++++++++++++++-
 snmplib/transports/snmpDTLSUDPDomain.c        | 13 ++++--
 snmplib/transports/snmpIPXDomain.c            | 34 +++++++++++++--
 snmplib/transports/snmpIPv4BaseDomain.c       | 26 ++++++++++++
 snmplib/transports/snmpIPv6BaseDomain.c       | 27 ++++++++++++
 snmplib/transports/snmpSSHDomain.c            | 22 +++++++++-
 snmplib/transports/snmpSTDDomain.c            |  8 +++-
 snmplib/transports/snmpTCPDomain.c            |  7 +++-
 snmplib/transports/snmpTCPIPv6Domain.c        |  7 +++-
 snmplib/transports/snmpTLSTCPDomain.c         |  9 ++++
 snmplib/transports/snmpUDPDomain.c            |  7 +++-
 snmplib/transports/snmpUDPIPv6Domain.c        |  7 +++-
 snmplib/transports/snmpUDPsharedDomain.c      | 17 ++++++--
 snmplib/transports/snmpUnixDomain.c           |  8 +++-
 20 files changed, 238 insertions(+), 28 deletions(-)

diff --git a/agent/mibgroup/notification/snmpNotifyTable_data.c b/agent/mibgroup/notification/snmpNotifyTable_data.c
index c14b892ffcf7..9a2b42f98734 100644
--- a/agent/mibgroup/notification/snmpNotifyTable_data.c
+++ b/agent/mibgroup/notification/snmpNotifyTable_data.c
@@ -344,8 +344,10 @@ notifyTable_register_notifications(int major, int minor,
     ptr->nameData = netsnmp_memdup_nt(name, nameLen, &ptr->nameLen);
     memcpy(ptr->tDomain, t->domain, t->domain_length * sizeof(oid));
     ptr->tDomainLen = t->domain_length;
-    ptr->tAddressLen = t->remote_length;
-    ptr->tAddress = t->remote;
+    if (t->f_get_taddr)
+        t->f_get_taddr(t, &ptr->tAddress, &ptr->tAddressLen);
+    else
+        netsnmp_assert(0);
 
     ptr->timeout = ss->timeout / 1000;
     ptr->retryCount = ss->retries;
diff --git a/agent/mibgroup/target/snmpTargetAddrEntry.c b/agent/mibgroup/target/snmpTargetAddrEntry.c
index 66d186633073..03adb2610ec2 100644
--- a/agent/mibgroup/target/snmpTargetAddrEntry.c
+++ b/agent/mibgroup/target/snmpTargetAddrEntry.c
@@ -385,9 +385,9 @@ write_snmpTargetAddrTAddress(int action,
                 return SNMP_ERR_INCONSISTENTVALUE;
             }
 
-            old_addr = (char *) target->tAddress;
+            old_addr = target->tAddress;
             old_len = target->tAddressLen;
-            target->tAddress = (u_char *) malloc(var_val_len);
+            target->tAddress = malloc(var_val_len);
             if (target->tAddress == NULL) {
                 return SNMP_ERR_RESOURCEUNAVAILABLE;
             }
@@ -419,7 +419,7 @@ write_snmpTargetAddrTAddress(int action,
             if (target->storageType != SNMP_STORAGE_READONLY
                 && target->rowStatus != SNMP_ROW_ACTIVE) {
                 SNMP_FREE(target->tAddress);
-                target->tAddress = (u_char *) old_addr;
+                target->tAddress = old_addr;
                 target->tAddressLen = old_len;
                 if (target->rowStatus == SNMP_ROW_NOTINSERVICE &&
                     snmpTargetAddr_rowStatusCheck(target) == 0) {
diff --git a/agent/mibgroup/target/snmpTargetAddrEntry_data.h b/agent/mibgroup/target/snmpTargetAddrEntry_data.h
index 4d0e23d7a545..0af434e8d7e4 100644
--- a/agent/mibgroup/target/snmpTargetAddrEntry_data.h
+++ b/agent/mibgroup/target/snmpTargetAddrEntry_data.h
@@ -44,7 +44,7 @@
          size_t          nameLen;
          oid             tDomain[MAX_OID_LEN];
          int             tDomainLen;
-         unsigned char  *tAddress;
+         void           *tAddress;
          size_t          tAddressLen;
          int             timeout;      /* Timeout in centiseconds */
          int             retryCount;
diff --git a/include/net-snmp/library/snmpIPv4BaseDomain.h b/include/net-snmp/library/snmpIPv4BaseDomain.h
index cbeee85641ba..cb6a4585cf48 100644
--- a/include/net-snmp/library/snmpIPv4BaseDomain.h
+++ b/include/net-snmp/library/snmpIPv4BaseDomain.h
@@ -19,6 +19,10 @@ extern          "C" {
 
     char *netsnmp_ipv4_fmtaddr(const char *prefix, netsnmp_transport *t,
                                const void *data, int len);
+    void netsnmp_ipv4_get_taddr(struct netsnmp_transport_s *t, void **addr,
+                                size_t *addr_len);
+    int netsnmp_ipv4_ostring_to_sockaddr(struct sockaddr_in *sin,
+                                         const void *o, size_t o_len);
 
 /*
  * Convert a "traditional" peername into a sockaddr_in structure which is
diff --git a/include/net-snmp/library/snmpIPv6BaseDomain.h b/include/net-snmp/library/snmpIPv6BaseDomain.h
index cf424eb16655..8f67ee62f7f4 100644
--- a/include/net-snmp/library/snmpIPv6BaseDomain.h
+++ b/include/net-snmp/library/snmpIPv6BaseDomain.h
@@ -21,6 +21,12 @@ extern          "C" {
     char *netsnmp_ipv6_fmtaddr(const char *prefix, netsnmp_transport *t,
                                const void *data, int len);
     NETSNMP_IMPORT
+    void netsnmp_ipv6_get_taddr(struct netsnmp_transport_s *t, void **addr,
+                                size_t *addr_len);
+    NETSNMP_IMPORT
+    int netsnmp_ipv6_ostring_to_sockaddr(struct sockaddr_in6 *sin6,
+                                         const void *o, size_t o_len);
+    NETSNMP_IMPORT
     int netsnmp_sockaddr_in6_2(struct sockaddr_in6 *addr,
                                const char *inpeername,
                                const char *default_target);
diff --git a/include/net-snmp/library/snmp_transport.h b/include/net-snmp/library/snmp_transport.h
index a514c581181d..e361624a4566 100644
--- a/include/net-snmp/library/snmp_transport.h
+++ b/include/net-snmp/library/snmp_transport.h
@@ -213,6 +213,11 @@ typedef struct netsnmp_transport_s {
     /* allocated host name identifier; used by configuration system
        to load localhost.conf for host-specific configuration */
     u_char         *identifier; /* udp:localhost:161 -> "localhost" */
+
+    /* Get the remote address in the format required by SNMP-TARGET-MIB */
+    void           (*f_get_taddr)(struct netsnmp_transport_s *t,
+                                  void **addr, size_t *addr_len);
+
 } netsnmp_transport;
 
 typedef struct netsnmp_transport_list_s {
@@ -232,7 +237,9 @@ typedef struct netsnmp_tdomain_s {
      */
     netsnmp_transport *(*f_create_from_tstring) (const char *, int);
 
-    netsnmp_transport *(*f_create_from_ostring) (const void *, size_t, int);
+    /* @o and @o_len define an address in the format used by SNMP-TARGET-MIB */
+    netsnmp_transport *(*f_create_from_ostring) (const void *o, size_t o_len,
+                                                 int local);
 
     struct netsnmp_tdomain_s *next;
 
diff --git a/snmplib/transports/snmpAAL5PVCDomain.c b/snmplib/transports/snmpAAL5PVCDomain.c
index ccc550031555..2d28f268b505 100644
--- a/snmplib/transports/snmpAAL5PVCDomain.c
+++ b/snmplib/transports/snmpAAL5PVCDomain.c
@@ -67,7 +67,25 @@ netsnmp_aal5pvc_fmtaddr(netsnmp_transport *t, const void *data, int len)
     }
 }
 
-
+static void
+netsnmp_aal5pvc_get_taddr(netsnmp_transport *t, void **addr, size_t *addr_len)
+{
+    struct sockaddr_atmpvc *sa = t->remote;
+    unsigned char *p;
+
+    *addr_len = 8;
+    if (!(*addr = malloc(*addr_len)))
+        return;
+    p = *addr;
+    p[0] = sa->sap_addr.itf >> 8;
+    p[1] = sa->sap_addr.itf >> 0;
+    p[2] = sa->sap_addr.vpi >> 8;
+    p[3] = sa->sap_addr.vpi >> 0;
+    p[4] = sa->sap_addr.vci >> 24;
+    p[5] = sa->sap_addr.vci >> 16;
+    p[6] = sa->sap_addr.vci >> 8;
+    p[7] = sa->sap_addr.vci >> 0;
+}
 
 /*
  * You can write something into opaque that will subsequently get passed back 
@@ -285,6 +303,7 @@ netsnmp_aal5pvc_transport(const struct sockaddr_atmpvc *addr, int local)
     t->f_close    = netsnmp_aal5pvc_close;
     t->f_accept   = NULL;
     t->f_fmtaddr  = netsnmp_aal5pvc_fmtaddr;
+    t->f_get_taddr = netsnmp_aal5pvc_get_taddr;
 
     return t;
 }
@@ -322,12 +341,30 @@ netsnmp_aal5pvc_create_tstring(const char *str, int local,
     }
 }
 
+static int netsnmp_aal5pvc_ostring_to_sockaddr(struct sockaddr_atmpvc *sa,
+                                               const void *o, size_t o_len)
+{
+    const unsigned char *p = o;
 
+    if (o_len != 8)
+        return 0;
+
+    memset(sa, 0, sizeof(*sa));
+    sa->sap_family = AF_ATMPVC;
+    sa->sap_addr.itf = (p[0] << 8) + (p[1] << 0);
+    sa->sap_addr.vpi = (p[2] << 8) + (p[3] << 0);
+    sa->sap_addr.vci = (p[4] << 24) + (p[5] << 16) + (p[6] << 8) + (p[7] << 0);
+    return 1;
+}
 
 netsnmp_transport *
 netsnmp_aal5pvc_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_aal5pvc_transport(o, local);
+    struct sockaddr_atmpvc sa;
+
+    if (netsnmp_aal5pvc_ostring_to_sockaddr(&sa, o, o_len))
+        return netsnmp_aal5pvc_transport(&sa, local);
+    return NULL;
 }
 
 
diff --git a/snmplib/transports/snmpDTLSUDPDomain.c b/snmplib/transports/snmpDTLSUDPDomain.c
index 7df7af90b76d..96860b8358d0 100644
--- a/snmplib/transports/snmpDTLSUDPDomain.c
+++ b/snmplib/transports/snmpDTLSUDPDomain.c
@@ -1486,6 +1486,7 @@ _transport_common(netsnmp_transport *t, int local)
     t->f_setup_session = netsnmp_tlsbase_session_init;
     t->f_accept        = NULL;
     t->f_fmtaddr       = netsnmp_dtlsudp4_fmtaddr;
+    t->f_get_taddr     = netsnmp_ipv4_get_taddr;
 
     t->flags = NETSNMP_TRANSPORT_FLAG_TUNNELED;
 
@@ -1553,6 +1554,7 @@ netsnmp_dtlsudp6_transport(const struct sockaddr_in6 *addr, int local)
     /* XXX: and buf size */        
 
     t->f_fmtaddr       = netsnmp_dtlsudp6_fmtaddr;
+    t->f_get_taddr     = netsnmp_ipv6_get_taddr;
 
     return t;
 }
@@ -1601,11 +1603,14 @@ netsnmp_dtlsudp_create_tstring(const char *str, int isserver,
 netsnmp_transport *
 netsnmp_dtlsudp_create_ostring(const void *o, size_t o_len, int local)
 {
-    if (o_len == sizeof(struct sockaddr_in))
-        return netsnmp_dtlsudp_transport(o, local);
+    struct sockaddr_in sin;
+    struct sockaddr_in6 sin6;
+
+    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
+        return netsnmp_dtlsudp_transport(&sin, local);
 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
-    else if (o_len == sizeof(struct sockaddr_in6))
-        return netsnmp_dtlsudp6_transport(o, local);
+    else if (netsnmp_ipv6_ostring_to_sockaddr(&sin6, o, o_len))
+        return netsnmp_dtlsudp6_transport(&sin6, local);
 #endif
     else
         return NULL;
diff --git a/snmplib/transports/snmpIPXDomain.c b/snmplib/transports/snmpIPXDomain.c
index ce5b85e0bd8d..55070476ce1e 100644
--- a/snmplib/transports/snmpIPXDomain.c
+++ b/snmplib/transports/snmpIPXDomain.c
@@ -33,6 +33,7 @@
 #include <net-snmp/output_api.h>
 #include <net-snmp/config_api.h>
 
+#include <net-snmp/library/snmp_assert.h>
 #include <net-snmp/library/snmp_transport.h>
 #include <net-snmp/library/tools.h>
 
@@ -69,7 +70,19 @@ netsnmp_ipx_fmtaddr(netsnmp_transport *t, const void *data, int len)
     }
 }
 
-
+static void netsnmp_ipx_get_taddr(struct netsnmp_transport_s *t,
+                                  void **addr, size_t *addr_len)
+{
+    struct sockaddr_ipx *sa = t->remote;
+
+    netsnmp_assert(t->remote_length == sizeof(*sa));
+    *addr_len = 12;
+    if ((*addr = malloc(*addr_len))) {
+        memcpy(*addr + 0,  &sa->sipx_network, 4);
+        memcpy(*addr + 4,  &sa->sipx_node,    6);
+        memcpy(*addr + 10, &sa->sipx_port,    2);
+    }
+}
 
 /*
  * You can write something into opaque that will subsequently get passed back 
@@ -276,6 +289,7 @@ netsnmp_ipx_transport(const struct sockaddr_ipx *addr, int local)
     t->f_close    = netsnmp_ipx_close;
     t->f_accept   = NULL;
     t->f_fmtaddr  = netsnmp_ipx_fmtaddr;
+    t->f_get_taddr = netsnmp_ipx_get_taddr;
 
     return t;
 }
@@ -430,13 +444,27 @@ netsnmp_ipx_create_tstring(const char *str, int local,
     }
 }
 
+static int netsnmp_ipx_ostring_to_sockaddr(struct sockaddr_ipx *sa,
+                                           const void *o, size_t o_len)
+{
+    if (o_len != 12)
+        return 0;
 
+    memset(sa, 0, sizeof(*sa));
+    sa->sipx_family = AF_IPX;
+    memcpy(&sa->sipx_network, o + 0, 4);
+    memcpy(&sa->sipx_node,    o + 4, 6);
+    memcpy(&sa->sipx_port,    o + 10, 2);
+    return 1;
+}
 
 netsnmp_transport *
 netsnmp_ipx_create_ostring(const void *o, size_t o_len, int local)
 {
-    if (o_len == sizeof(struct sockaddr_ipx))
-        return netsnmp_ipx_transport(o, local);
+    struct sockaddr_ipx sa;
+
+    if (netsnmp_ipx_ostring_to_sockaddr(&sa, o, o_len))
+        return netsnmp_ipx_transport(&sa, local);
 
     return NULL;
 }
diff --git a/snmplib/transports/snmpIPv4BaseDomain.c b/snmplib/transports/snmpIPv4BaseDomain.c
index 910bb56234db..fafc1ab8045c 100644
--- a/snmplib/transports/snmpIPv4BaseDomain.c
+++ b/snmplib/transports/snmpIPv4BaseDomain.c
@@ -242,3 +242,29 @@ netsnmp_ipv4_fmtaddr(const char *prefix, netsnmp_transport *t,
     return tmp;
 }
 
+void netsnmp_ipv4_get_taddr(struct netsnmp_transport_s *t, void **addr,
+                            size_t *addr_len)
+{
+    struct sockaddr_in *sin = t->remote;
+
+    netsnmp_assert(t->remote_length == sizeof(*sin));
+
+    *addr_len = 6;
+    if ((*addr = malloc(*addr_len))) {
+        memcpy(*addr,     &sin->sin_addr, 4);
+        memcpy(*addr + 4, &sin->sin_port, 2);
+    }
+}
+
+int netsnmp_ipv4_ostring_to_sockaddr(struct sockaddr_in *sin, const void *o,
+                                     size_t o_len)
+{
+    if (o_len != 6)
+        return 0;
+
+    memset(sin, 0, sizeof(*sin));
+    sin->sin_family = AF_INET;
+    memcpy(&sin->sin_addr, o + 0, 4);
+    memcpy(&sin->sin_port, o + 4, 2);
+    return 1;
+}
diff --git a/snmplib/transports/snmpIPv6BaseDomain.c b/snmplib/transports/snmpIPv6BaseDomain.c
index 4336b6a6ae9d..c4a801f87228 100644
--- a/snmplib/transports/snmpIPv6BaseDomain.c
+++ b/snmplib/transports/snmpIPv6BaseDomain.c
@@ -151,6 +151,33 @@ netsnmp_ipv6_fmtaddr(const char *prefix, netsnmp_transport *t,
     return tmp;
 }
 
+void netsnmp_ipv6_get_taddr(struct netsnmp_transport_s *t, void **addr,
+                            size_t *addr_len)
+{
+    struct sockaddr_in6 *sin6 = t->remote;
+
+    netsnmp_assert(t->remote_length == sizeof(*sin6));
+
+    *addr_len = 18;
+    if ((*addr = malloc(*addr_len))) {
+        memcpy(*addr,      &sin6->sin6_addr, 16);
+        memcpy(*addr + 16, &sin6->sin6_port, 2);
+    }
+}
+
+int netsnmp_ipv6_ostring_to_sockaddr(struct sockaddr_in6 *sin6, const void *o,
+                                     size_t o_len)
+{
+    if (o_len != 18)
+        return 0;
+
+    memset(sin6, 0, sizeof(*sin6));
+    sin6->sin6_family = AF_INET6;
+    memcpy(&sin6->sin6_addr, o + 0,  16);
+    memcpy(&sin6->sin6_port, o + 16, 2);
+    return 1;
+}
+
 int
 netsnmp_sockaddr_in6_2(struct sockaddr_in6 *addr,
                        const char *inpeername, const char *default_target)
diff --git a/snmplib/transports/snmpSSHDomain.c b/snmplib/transports/snmpSSHDomain.c
index 3ca4f81c9f93..3854e00b2889 100644
--- a/snmplib/transports/snmpSSHDomain.c
+++ b/snmplib/transports/snmpSSHDomain.c
@@ -123,7 +123,18 @@ netsnmp_ssh_fmtaddr(netsnmp_transport *t, const void *data, int len)
     }
 }
 
-
+static void netsnmp_ssh_get_taddr(struct netsnmp_transport_s *t,
+                                  void **addr, size_t *addr_len)
+{
+    switch (t->remote_length) {
+    case sizeof(sockaddr_in):
+        netsnmp_ipv4_get_taddr(t, addr, addr_len);
+        break;
+    default:
+        *addr = NULL;
+        netsnmp_assert(0);
+    }
+}
 
 /*
  * You can write something into opaque that will subsequently get passed back 
@@ -883,6 +894,7 @@ netsnmp_ssh_transport(const struct sockaddr_in *addr, int local)
     t->f_close    = netsnmp_ssh_close;
     t->f_accept   = netsnmp_ssh_accept;
     t->f_fmtaddr  = netsnmp_ssh_fmtaddr;
+    t->f_get_taddr = netsnmp_ssh_get_taddr;
 
     return t;
 }
@@ -907,7 +919,13 @@ netsnmp_ssh_create_tstring(const char *str, int local,
 netsnmp_transport *
 netsnmp_ssh_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_ssh_transport(o, local);
+    struct sockaddr_in sin;
+
+    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
+        return netsnmp_ssh_transport(&sin, local);
+    else
+        netsnmp_assert(0);
+    return NULL;
 }
 
 void
diff --git a/snmplib/transports/snmpSTDDomain.c b/snmplib/transports/snmpSTDDomain.c
index 5845f25937c6..d85eb9e85a5e 100644
--- a/snmplib/transports/snmpSTDDomain.c
+++ b/snmplib/transports/snmpSTDDomain.c
@@ -53,7 +53,12 @@ netsnmp_std_fmtaddr(netsnmp_transport *t, const void *data, int len)
     return strdup("STDInOut");
 }
 
-
+static void
+netsnmp_std_get_taddr(netsnmp_transport *t, void **addr, size_t *addr_len)
+{
+    *addr_len = t->remote_length;
+    *addr = netsnmp_memdup(t->remote, *addr_len);
+}
 
 /*
  * You can write something into opaque that will subsequently get passed back 
@@ -176,6 +181,7 @@ netsnmp_std_transport(const char *instring, size_t instring_len,
     t->f_close    = netsnmp_std_close;
     t->f_accept   = netsnmp_std_accept;
     t->f_fmtaddr  = netsnmp_std_fmtaddr;
+    t->f_get_taddr = netsnmp_std_get_taddr;
 
     /*
      * if instring is not null length, it specifies a path to a prog
diff --git a/snmplib/transports/snmpTCPDomain.c b/snmplib/transports/snmpTCPDomain.c
index 00ad39af03cf..edfecdd6360c 100644
--- a/snmplib/transports/snmpTCPDomain.c
+++ b/snmplib/transports/snmpTCPDomain.c
@@ -310,6 +310,7 @@ netsnmp_tcp_transport(const struct sockaddr_in *addr, int local)
     t->f_close    = netsnmp_socketbase_close;
     t->f_accept   = netsnmp_tcp_accept;
     t->f_fmtaddr  = netsnmp_tcp_fmtaddr;
+    t->f_get_taddr = netsnmp_ipv4_get_taddr;
 
     return t;
 }
@@ -334,7 +335,11 @@ netsnmp_tcp_create_tstring(const char *str, int local,
 netsnmp_transport *
 netsnmp_tcp_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_tcp_transport(o, local);
+    struct sockaddr_in sin;
+
+    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
+        return netsnmp_tcp_transport(&sin, local);
+    return NULL;
 }
 
 
diff --git a/snmplib/transports/snmpTCPIPv6Domain.c b/snmplib/transports/snmpTCPIPv6Domain.c
index bdd5c2906835..07fa6af51278 100644
--- a/snmplib/transports/snmpTCPIPv6Domain.c
+++ b/snmplib/transports/snmpTCPIPv6Domain.c
@@ -316,6 +316,7 @@ netsnmp_tcp6_transport(const struct sockaddr_in6 *addr, int local)
     t->f_close    = netsnmp_socketbase_close;
     t->f_accept   = netsnmp_tcp6_accept;
     t->f_fmtaddr  = netsnmp_tcp6_fmtaddr;
+    t->f_get_taddr = netsnmp_ipv6_get_taddr;
 
     return t;
 }
@@ -346,7 +347,11 @@ netsnmp_tcp6_create_tstring(const char *str, int local,
 netsnmp_transport *
 netsnmp_tcp6_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_tcp6_transport(o, local);
+    struct sockaddr_in6 sin6;
+
+    if (netsnmp_ipv6_ostring_to_sockaddr(&sin6, o, o_len))
+        return netsnmp_tcp6_transport(&sin6, local);
+    return NULL;
 }
 
 
diff --git a/snmplib/transports/snmpTLSTCPDomain.c b/snmplib/transports/snmpTLSTCPDomain.c
index 550dcad61431..df7086ed8d98 100644
--- a/snmplib/transports/snmpTLSTCPDomain.c
+++ b/snmplib/transports/snmpTLSTCPDomain.c
@@ -124,6 +124,14 @@ netsnmp_tlstcp_fmtaddr(netsnmp_transport *t, const void *data, int len)
     }
     }
 }
+
+static void netsnmp_tlstcp_get_taddr(struct netsnmp_transport_s *t,
+                                     void **addr, size_t *addr_len)
+{
+    *addr_len = t->remote_length;
+    *addr = netsnmp_memdup(t->remote, *addr_len);
+}
+
 /*
  * You can write something into opaque that will subsequently get passed back 
  * to your send function if you like.  For instance, you might want to
@@ -986,6 +994,7 @@ netsnmp_tlstcp_transport(const char *addr_string, int isserver)
     t->f_config        = netsnmp_tlsbase_config;
     t->f_setup_session = netsnmp_tlsbase_session_init;
     t->f_fmtaddr       = netsnmp_tlstcp_fmtaddr;
+    t->f_get_taddr     = netsnmp_tlstcp_get_taddr;
 
     t->flags |= NETSNMP_TRANSPORT_FLAG_TUNNELED | NETSNMP_TRANSPORT_FLAG_STREAM;
 
diff --git a/snmplib/transports/snmpUDPDomain.c b/snmplib/transports/snmpUDPDomain.c
index 7543b3419a7a..2dd812d40b48 100644
--- a/snmplib/transports/snmpUDPDomain.c
+++ b/snmplib/transports/snmpUDPDomain.c
@@ -146,6 +146,7 @@ netsnmp_udp_transport_base(netsnmp_transport *t)
     t->f_close    = netsnmp_socketbase_close;
     t->f_accept   = NULL;
     t->f_fmtaddr  = netsnmp_udp_fmtaddr;
+    t->f_get_taddr = netsnmp_ipv4_get_taddr;
 
     return t;
 }
@@ -628,7 +629,11 @@ netsnmp_udp_create_tspec(netsnmp_tdomain_spec *tspec)
 netsnmp_transport *
 netsnmp_udp_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_udp_transport(o, local);
+    struct sockaddr_in sin;
+
+    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
+        return netsnmp_udp_transport(&sin, local);
+    return NULL;
 }
 
 
diff --git a/snmplib/transports/snmpUDPIPv6Domain.c b/snmplib/transports/snmpUDPIPv6Domain.c
index 5b9313165296..3d003f208763 100644
--- a/snmplib/transports/snmpUDPIPv6Domain.c
+++ b/snmplib/transports/snmpUDPIPv6Domain.c
@@ -263,6 +263,7 @@ netsnmp_udp6_transport_init(const struct sockaddr_in6 *addr, int flags)
     t->f_close    = netsnmp_socketbase_close;
     t->f_accept   = NULL;
     t->f_fmtaddr  = netsnmp_udp6_fmtaddr;
+    t->f_get_taddr = netsnmp_ipv6_get_taddr;
 
     t->domain = netsnmp_UDPIPv6Domain;
     t->domain_length =
@@ -951,7 +952,11 @@ netsnmp_udp6_create_tspec(netsnmp_tdomain_spec *tspec)
 netsnmp_transport *
 netsnmp_udp6_create_ostring(const void *o, size_t o_len, int local)
 {
-    return netsnmp_udp6_transport(o, local);
+    struct sockaddr_in6 sin6;
+
+    if (netsnmp_ipv6_ostring_to_sockaddr(&sin6, o, o_len))
+        return netsnmp_udp6_transport(&sin6, local);
+    return NULL;
 }
 
 
diff --git a/snmplib/transports/snmpUDPsharedDomain.c b/snmplib/transports/snmpUDPsharedDomain.c
index 5e77f6a43548..d84dd4ee1cb8 100644
--- a/snmplib/transports/snmpUDPsharedDomain.c
+++ b/snmplib/transports/snmpUDPsharedDomain.c
@@ -178,6 +178,12 @@ _transport_common(netsnmp_transport *t)
     t->f_fmtaddr       = _udpshared_fmtaddr;
     t->f_setup_session = _setup_session;
     t->flags = NETSNMP_TRANSPORT_FLAG_SHARED;
+    if (t->base_transport->domain == netsnmpUDPDomain)
+        t->f_get_taddr = netsnmp_ipv4_get_taddr;
+    else if (t->base_transport->domain == netsnmp_UDPIPv6Domain)
+        t->f_get_taddr = netsnmp_ipv6_get_taddr;
+    else
+        netsnmp_assert(0);
 
     return t;
 }
@@ -340,13 +346,16 @@ netsnmp_udpshared6_transport_with_source(const struct sockaddr_in6 *addr6,
 netsnmp_transport *
 netsnmp_udpshared_create_ostring(const void *o, size_t o_len, int local)
 {
+    struct sockaddr_in sin;
+    struct sockaddr_in6 sin6;
+
     DEBUGMSGTL(("udpshared:create", "from ostring\n"));
 
-    if (o_len == sizeof(struct sockaddr_in))
-        return netsnmp_udpshared_transport(o, local);
+    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
+        return netsnmp_udpshared_transport(&sin, local);
 #ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
-    else if (o_len == sizeof(struct sockaddr_in6))
-        return netsnmp_udpshared6_transport(o, local);
+    else if (netsnmp_ipv6_ostring_to_sockaddr(&sin6, o, o_len))
+        return netsnmp_udpshared6_transport(&sin6, local);
 #endif
     return NULL;
 }
diff --git a/snmplib/transports/snmpUnixDomain.c b/snmplib/transports/snmpUnixDomain.c
index ab57accac16e..2d4a452b38c7 100644
--- a/snmplib/transports/snmpUnixDomain.c
+++ b/snmplib/transports/snmpUnixDomain.c
@@ -107,7 +107,12 @@ netsnmp_unix_fmtaddr(netsnmp_transport *t, const void *data, int len)
     }
 }
 
-
+static void
+netsnmp_unix_get_taddr(netsnmp_transport *t, void **addr, size_t *addr_len)
+{
+    *addr_len = t->remote_length;
+    *addr = netsnmp_memdup(t->remote, *addr_len);
+}
 
 /*
  * You can write something into opaque that will subsequently get passed back
@@ -459,6 +464,7 @@ netsnmp_unix_transport(const struct sockaddr_un *addr, int local)
     t->f_close    = netsnmp_unix_close;
     t->f_accept   = netsnmp_unix_accept;
     t->f_fmtaddr  = netsnmp_unix_fmtaddr;
+    t->f_get_taddr = netsnmp_unix_get_taddr;
 
     return t;
 }
-- 
2.17.1



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.