From: Amos Jeffries Date: Sun, 23 Mar 2008 11:47:50 +0000 (+1200) Subject: Fix memory leak in Linux builds. X-Git-Tag: BASIC_TPROXY4~15^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0e1a47f059d0b28878f3a0b0fd56593fe6b7a77a;p=thirdparty%2Fsquid.git Fix memory leak in Linux builds. --- diff --git a/include/IPAddress.h b/include/IPAddress.h index ce7745044b..295001d29d 100644 --- a/include/IPAddress.h +++ b/include/IPAddress.h @@ -123,17 +123,13 @@ public: /*@{*/ IPAddress& operator =(const IPAddress &s); IPAddress& operator =(IPAddress *s); - IPAddress& operator =(struct sockaddr_in const &s); - + IPAddress& operator =(struct sockaddr_storage const &s); IPAddress& operator =(struct in_addr const &s); #if USE_IPV6 - IPAddress& operator =(struct in6_addr const &s); - IPAddress& operator =(struct sockaddr_in6 const &s); #endif - bool operator =(const struct hostent &s); bool operator =(const struct addrinfo &s); bool operator =(const char *s); @@ -359,6 +355,8 @@ public: * these functiosn WILL NOT be in the final public API after transition. */ + void GetSockAddr(struct sockaddr_storage &addr, const int family) const; + /// \deprecated Deprecated for public use. Use IPAddress::GetAddrInfo() void GetSockAddr(struct sockaddr_in &) const; diff --git a/lib/IPAddress.cc b/lib/IPAddress.cc index d248311777..b975eab75b 100644 --- a/lib/IPAddress.cc +++ b/lib/IPAddress.cc @@ -557,6 +557,24 @@ IPAddress& IPAddress::operator =(struct sockaddr_in const &s) return *this; }; +IPAddress& IPAddress::operator =(const sockaddr_storage &s) +{ +#if USE_IPV6 + /* some AF_* magic to tell socket types apart and what we need to do */ + if(s.ss_family == AF_INET6) { + memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in)); + } + else { // convert it to our storage mapping. + struct sockaddr_in *sin = (struct sockaddr_in*)&s; + m_SocketAddr.sin6_port = sin->sin_port; + Map4to6( sin->sin_addr, m_SocketAddr.sin6_addr); + } +#else + memcpy(&m_SocketAddr, &s, sizeof(struct sockaddr_in)); +#endif + return *this; +}; + void IPAddress::check4Mapped() { // obsolete. @@ -1065,6 +1083,36 @@ char* IPAddress::ToURL(char* buf, unsigned int blen) const return buf; } +void IPAddress::GetSockAddr(struct sockaddr_storage &addr, const int family) const +{ + if( family == AF_INET && !IsIPv4()) { + // FIXME INET6: caller using the wrong socket type! + debugs(14, DBG_CRITICAL, HERE << "IPAddress::GetSockAddr : Cannot convert non-IPv4 to IPv4. from " << *this); + assert(false); + } + +#if USE_IPV6 + if( IsIPv6() ) { + memcpy(&addr, &m_SocketAddr, sizeof(struct sockaddr_in6)); + + if(addr.ss_family == 0) + addr.ss_family = AF_INET6; + } + else if( IsIPv4() ) { + struct sockaddr_in *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); + } +#else + struct sockaddr_in *sa = (struct sockaddr_in*)&addr; + memcpy(&addr, &m_SocketAddr, sizeof(struct sockaddr_in)); + + if(addr.sa_family == 0) + addr.sa_family = AF_INET; +#endif +} + void IPAddress::GetSockAddr(struct sockaddr_in &buf) const { #if USE_IPV6 diff --git a/src/comm.cc b/src/comm.cc index 513c71a2ce..5d6e503424 100644 --- a/src/comm.cc +++ b/src/comm.cc @@ -1133,15 +1133,16 @@ comm_connect_addr(int sock, const IPAddress &address) int x = 0; int err = 0; socklen_t errlen; - struct addrinfo *AI = NULL; + struct sockaddr_storage sas; + socklen_t slen = sizeof(struct sockaddr_storage); PROF_start(comm_connect_addr); assert(address.GetPort() != 0); debugs(5, 9, "comm_connect_addr: connecting socket " << sock << " to " << address << " (want family: " << F->sock_family << ")"); - /* FIXME INET6 : Bug 2222: when sock is an IPv4-only socket IPv6 traffic will crash. */ - address.GetAddrInfo(AI, F->sock_family); + memset(&sas, NULL, slen); + address.GetSockAddr(sas, F->sock_family); /* Establish connection. */ errno = 0; @@ -1151,7 +1152,7 @@ comm_connect_addr(int sock, const IPAddress &address) F->flags.called_connect = 1; statCounter.syscalls.sock.connects++; - x = connect(sock, AI->ai_addr, AI->ai_addrlen); + x = connect(sock, (struct sockaddr*)&sas, slen); // XXX: ICAP code refuses callbacks during a pending comm_ call // Async calls development will fix this. @@ -1163,12 +1164,8 @@ comm_connect_addr(int sock, const IPAddress &address) if (x < 0) { debugs(5,5, "comm_connect_addr: sock=" << sock << ", addrinfo( " << - " flags=" << AI->ai_flags << - ", family=" << AI->ai_family << - ", socktype=" << AI->ai_socktype << - ", protocol=" << AI->ai_protocol << - ", &addr=" << AI->ai_addr << - ", addrlen=" << AI->ai_addrlen << + ", family=" << sas.ss_family << + ", addrlen=" << slen << " )" ); debugs(5, 9, "connect FD " << sock << ": (" << x << ") " << xstrerror()); debugs(14,9, "connecting to: " << address ); @@ -1178,7 +1175,7 @@ comm_connect_addr(int sock, const IPAddress &address) #if defined(_SQUID_NEWSOS6_) /* Makoto MATSUSHITA */ - connect(sock, AI->ai_addr, AI->ai_addrlen); + connect(sock, (struct sockaddr*)&sas, slen); if (errno == EINVAL) { errlen = sizeof(err); @@ -1211,20 +1208,6 @@ comm_connect_addr(int sock, const IPAddress &address) } -#ifdef _SQUID_LINUX_ - /* 2007-11-27: - * Linux Debian replaces our allocated AI pointer with garbage when - * connect() fails. This leads to segmentation faults deallocating - * the system-allocated memory when we go to clean up our pointer. - * HACK: is to leak the memory returned since we can't deallocate. - */ - if(errno != 0) { - AI = NULL; - } -#endif - - address.FreeAddrInfo(AI); - PROF_stop(comm_connect_addr); if (errno == 0 || errno == EISCONN)