https://issues.shibboleth.net/jira/browse/SSPCPP-552
authorScott Cantor <cantor.2@osu.edu>
Mon, 6 May 2013 03:20:34 +0000 (03:20 +0000)
committerScott Cantor <cantor.2@osu.edu>
Mon, 6 May 2013 03:20:34 +0000 (03:20 +0000)
shibsp/remoting/impl/TCPListener.cpp

index 5f07611..02df8e4 100644 (file)
@@ -88,6 +88,7 @@ namespace shibsp {
         string m_address;
         unsigned short m_port;
         vector<IPRange> m_acl;
+        size_t m_sockaddrlen;
 #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
         struct sockaddr_storage m_sockaddr;
 #else
@@ -157,15 +158,16 @@ bool TCPListener::setup_tcp_sockaddr()
         return false;
     }
 
+    m_sockaddrlen = ret->ai_addrlen;
     if (ret->ai_family == AF_INET) {
-        memcpy(&m_sockaddr, ret->ai_addr, ret->ai_addrlen);
+        memcpy(&m_sockaddr, ret->ai_addr, m_sockaddrlen);
         freeaddrinfo(ret);
         ((struct sockaddr_in*)&m_sockaddr)->sin_port=htons(m_port);
         return true;
     }
 #if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_STORAGE)
     else if (ret->ai_family == AF_INET6) {
-        memcpy(&m_sockaddr, ret->ai_addr, ret->ai_addrlen);
+        memcpy(&m_sockaddr, ret->ai_addr, m_sockaddrlen);
         freeaddrinfo(ret);
         ((struct sockaddr_in6*)&m_sockaddr)->sin6_port=htons(m_port);
         return true;
@@ -200,14 +202,14 @@ bool TCPListener::bind(ShibSocket& s, bool force) const
     ::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt));
 
 #ifdef WIN32
-    if (SOCKET_ERROR==::bind(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) || SOCKET_ERROR==::listen(s, 3)) {
+    if (SOCKET_ERROR==::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddrlen) || SOCKET_ERROR==::listen(s, 3)) {
         log_error("bind");
         close(s);
         return false;
     }
 #else
-    // Newer BSDs require the struct length be passed based on the socket address.
-    // Others have no field for that and take the whole struct size like Windows does.
+    // Newer BSDs, and Solaris, require the struct length be passed based on the socket address.
+    // All but Solaris seem to have an ss_len field in the sockaddr_storage struct.
 # ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
 #  ifdef HAVE_STRUCT_SOCKADDR_STORAGE
     if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.ss_len) < 0) {
@@ -215,7 +217,7 @@ bool TCPListener::bind(ShibSocket& s, bool force) const
     if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.sin_len) < 0) {
 #  endif
 # else
-    if (::bind(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) < 0) {
+    if (::bind(s, (const struct sockaddr*)&m_sockaddr, m_sockaddrlen) < 0) {
 # endif
         log_error("bind");
         close(s);
@@ -229,7 +231,7 @@ bool TCPListener::bind(ShibSocket& s, bool force) const
 bool TCPListener::connect(ShibSocket& s) const
 {
 #ifdef WIN32
-    if(SOCKET_ERROR==::connect(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)))
+    if(SOCKET_ERROR==::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddrlen))
         return log_error("connect");
 #else
     // Newer BSDs require the struct length be passed based on the socket address.
@@ -241,7 +243,7 @@ bool TCPListener::connect(ShibSocket& s) const
     if (::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddr.sin_len) < 0)
 #  endif
 # else
-    if (::connect(s, (const struct sockaddr*)&m_sockaddr, sizeof(m_sockaddr)) < 0)
+    if (::connect(s, (const struct sockaddr*)&m_sockaddr, m_sockaddrlen) < 0)
 # endif
         return log_error("connect");
 #endif