From: Amos Jeffries Date: Thu, 3 Apr 2008 09:39:06 +0000 (+1200) Subject: Attempted fix for FreeBSD run-time socket error "(22) Invalid Object" on connects X-Git-Tag: BASIC_TPROXY4~4^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8c37ea44b2a64ebea1c84b35d005fd00cdef06b2;p=thirdparty%2Fsquid.git Attempted fix for FreeBSD run-time socket error "(22) Invalid Object" on connects - Sets the ss_len / sin_len / sin6_len fields of sockaddr_* objects when retrieved for connection setup. - Tests the OS at compile time for each of these fields existence to cope with some OS (ie Linux) not using or providing them. --- diff --git a/configure.in b/configure.in index 6df159b07e..348da3a5b0 100644 --- a/configure.in +++ b/configure.in @@ -1798,6 +1798,60 @@ AC_ARG_WITH(dns-cname, [AC_DEFINE(DNS_CNAME, 0, [ 0 == Disable expermental CNAME recursion inside Squid DNS resolver stub]) AC_MSG_RESULT(no)] ) +dnl Check whether this OS defines ss_len as a member of sockaddr_storage +AC_CACHE_CHECK([for ss_len field in struct sockaddr_storage], + ac_cv_have_ss_len_in_struct_ss, [ + AC_TRY_COMPILE([ +#include +#include + ], + [ struct sockaddr_storage s; s.ss_len = 1; ], + [ ac_cv_have_ss_len_in_struct_ss="yes" ], + [ ac_cv_have_ss_len_in_struct_ss="no" ] + ) +]) +if test "x$ac_cv_have_ss_len_in_struct_ss" = "xyes" ; then + AC_DEFINE(HAVE_SS_LEN_IN_SS, 1, [Does struct sockaddr_storage have ss_len? 1: Yes, 0: No]) +else + AC_DEFINE(HAVE_SS_LEN_IN_SS, 0, [Does struct sockaddr_storage have ss_len? 1: Yes, 0: No]) +fi + +dnl Check whether this OS defines sin_len as a member of sockaddr_in as a backup to ss_len +AC_CACHE_CHECK([for sin_len field in struct sockaddr_in], + ac_cv_have_sin_len_in_struct_sai, [ + AC_TRY_COMPILE([ +#include +#include + ], + [ struct sockaddr_in s; s.sin_len = 1; ], + [ ac_cv_have_sin_len_in_struct_sai="yes" ], + [ ac_cv_have_sin_len_in_struct_sai="no" ] + ) +]) +if test "x$ac_cv_have_sin_len_in_struct_sai" = "xyes" ; then + AC_DEFINE(HAVE_SIN_LEN_IN_SAI, 1, [Does struct sockaddr_in have sin_len? 1: Yes, 0: No]) +else + AC_DEFINE(HAVE_SIN_LEN_IN_SAI, 0, [Does struct sockaddr_in have sin_len? 1: Yes, 0: No]) +fi + +dnl Check whether this OS defines sin6_len as a member of sockaddr_in6 as a backup to ss_len +AC_CACHE_CHECK([for sin6_len field in struct sockaddr_in6], + ac_cv_have_sin6_len_in_struct_sai, [ + AC_TRY_COMPILE([ +#include +#include + ], + [ struct sockaddr_in6 s; s.sin6_len = 1; ], + [ ac_cv_have_sin6_len_in_struct_sai="yes" ], + [ ac_cv_have_sin6_len_in_struct_sai="no" ] + ) +]) +if test "x$ac_cv_have_sin6_len_in_struct_sai" = "xyes" ; then + AC_DEFINE(HAVE_SIN6_LEN_IN_SAI, 1, [Does struct sockaddr_in6 have sin6_len? 1: Yes, 0: No]) +else + AC_DEFINE(HAVE_SIN6_LEN_IN_SAI, 0, [Does struct sockaddr_in6 have sin6_len? 1: Yes, 0: No]) +fi + AC_ARG_WITH(filedescriptors, [ --with-filedescriptors=NUMBER diff --git a/lib/IPAddress.cc b/lib/IPAddress.cc index d0ca2fb5e0..bad2403be7 100644 --- a/lib/IPAddress.cc +++ b/lib/IPAddress.cc @@ -1100,20 +1100,40 @@ void IPAddress::GetSockAddr(struct sockaddr_storage &addr, const int family) con if(addr.ss_family == 0) { addr.ss_family = AF_INET6; } +#if HAVE_SS_LEN_IN_SS + /* not all OS have this field, BUT when they do it can be a problem if set wrong */ + addr.ss_len = htons(sizeof(struct sockaddr_in6)); +#elif HAVE_SIN6_LEN_IN_SAI + sin->sin6_len = htons(sizeof(struct sockaddr_in6)); +#endif } else if( family == AF_INET || family == AF_UNSPEC && IsIPv4() ) { sin = (struct sockaddr_in*)&addr; addr.ss_family = AF_INET; sin->sin_port = m_SocketAddr.sin6_port; Map6to4( m_SocketAddr.sin6_addr, sin->sin_addr); +#if HAVE_SS_LEN_IN_SS + /* not all OS have this field, BUT when they do it can be a problem if set wrong */ + addr.ss_len = htons(sizeof(struct sockaddr_in)); +#elif HAVE_SIN_LEN_IN_SAI + sin->sin_len = htons(sizeof(struct sockaddr_in)); +#endif } else { IASSERT("false",false); } -#else +#else /* not USE_IPV6 */ sin = (struct sockaddr_in*)&addr; memcpy(sin, &m_SocketAddr, sizeof(struct sockaddr_in)); addr.ss_family = AF_INET; + +#if HAVE_SS_LEN_IN_SS + /* not all OS have this field, BUT when they do it can be a problem if set wrong */ + addr.ss_len = htons(sizeof(struct sockaddr_in)); +#elif HAVE_SIN_LEN_IN_SAI + sin->sin_len = htons(sizeof(struct sockaddr_in)); #endif + +#endif /* USE_IPV6 */ } void IPAddress::GetSockAddr(struct sockaddr_in &buf) const