/*@{*/
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);
* 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;
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.
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
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;
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.
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 );
#if defined(_SQUID_NEWSOS6_)
/* Makoto MATSUSHITA <matusita@ics.es.osaka-u.ac.jp> */
- connect(sock, AI->ai_addr, AI->ai_addrlen);
+ connect(sock, (struct sockaddr*)&sas, slen);
if (errno == EINVAL) {
errlen = sizeof(err);
}
-#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)