From aad6c4e5096d4059712ce8671d7ec6af1f6d621c Mon Sep 17 00:00:00 2001 From: brain Date: Tue, 6 Feb 2007 17:36:06 +0000 Subject: Fixes to allow inspsocket connects to be protocol transparent git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@6515 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/inspsocket.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 157 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp index d8d4438fe..c9c5ba4ec 100644 --- a/src/inspsocket.cpp +++ b/src/inspsocket.cpp @@ -95,7 +95,26 @@ InspSocket::InspSocket(InspIRCd* SI, const std::string &ipaddr, int aport, bool strlcpy(this->host,ipaddr.c_str(),MAXBUF); this->port = aport; - if (insp_aton(host,&addy) < 1) + bool ipvalid = true; +#ifdef IPV6 + if (strchr(host,':')) + { + in6_addr addy; + if (inet_ntop(AF_INET6, host, &n) < 1) + ipvalid = false; + } + else + { + in_addr addy; + if (inet_aton(host,&addy) < 1) + ipvalid = false; + } +#else + in_addr addy; + if (inet_aton(host,&addy) < 1) + ipvalid = false; +#endif + if (!ipvalid) { this->Instance->Log(DEBUG,"BUG: Hostname passed to InspSocket, rather than an IP address!"); this->Close(); @@ -138,8 +157,15 @@ void InspSocket::SetQueues(int nfd) */ bool InspSocket::BindAddr() { - insp_inaddr n; ConfigReader Conf(this->Instance); + bool bindfail = false; + socklen_t size = sizeof(sockaddr_in); +#ifdef IPV6 + bool v6 = false; + /* Are we looking for a binding to fit an ipv6 host? */ + if ((!*this->host) || strchr(this->host, ':')) + v6 = true; +#endif for (int j =0; j < Conf.Enumerate("bind"); j++) { std::string Type = Conf.ReadValue("bind","type",j); @@ -148,26 +174,58 @@ bool InspSocket::BindAddr() { if ((IP != "*") && (IP != "127.0.0.1") && (IP != "") && (IP != "::1")) { - insp_sockaddr s; - - if (insp_aton(IP.c_str(),&n) > 0) - { + sockaddr* s = new sockaddr[2]; #ifdef IPV6 - memcpy(&s.sin6_addr, &n, sizeof(n)); - s.sin6_family = AF_FAMILY; -#else - s.sin_addr = n; - s.sin_family = AF_FAMILY; -#endif - if (bind(this->fd,(struct sockaddr*)&s,sizeof(s)) < 0) + if (v6) + { + in6_addr n; + if (inet_pton(AF_INET6, IP.c_str(), &n) > 0) { - this->state = I_ERROR; - this->OnError(I_ERR_BIND); - this->fd = -1; - return false; + memcpy(((sockaddr_in6*)s)->sin6_addr, &n, sizeof(n)); + s.sin6_family = AF_INET6; + size = sizeof(sockaddr_in6); } - return true; + else + bindfail = true; + } + else + { + in_addr n; + if (inet_aton(IP.c_str(), &n) > 0) + { + ((sockaddr_in*)s)->sin_addr = n; + ((sockaddr_in*)s)->sin_family = AF_INET; + } + else + bindfail = true; + } +#else + in_addr n; + if (insp_aton(IP.c_str(), &n) > 0) + { + ((sockaddr_in*)s)->sin_addr = n; + ((sockaddr_in*)s)->sin_family = AF_INET; } + else + bindfail = true; +#endif + if (bindfail) + { + delete[] s; + return false; + } + + if (bind(this->fd, s, size) < 0) + { + this->state = I_ERROR; + this->OnError(I_ERR_BIND); + this->fd = -1; + delete[] s; + return false; + } + + delete[] s; + return true; } } } @@ -176,34 +234,77 @@ bool InspSocket::BindAddr() bool InspSocket::DoConnect() { - if ((this->fd = socket(AF_FAMILY, SOCK_STREAM, 0)) == -1) + sockaddr* addr = new sockaddr[2]; + socklen_t size = sizeof(sockaddr_in); +#ifdef IPV6 + bool v6 = false; + if ((!*this->host) || strchr(this->host, ':')) + v6 = true; + + if (v6) + { + this->fd = socket(AF_INET6, SOCK_STREAM, 0); + if ((this->fd > -1) && ((strstr(this->IP,"::ffff:") != (char*)&this->IP) && (strstr(this->IP,"::FFFF:") != (char*)&this->IP))) + { + if (!this->BindAddr()) + { + delete[] addr; + return false; + } + } + } + else + { + this->fd = socket(AF_INET, SOCK_STREAM, 0); + } +#else + this->fd = socket(AF_INET, SOCK_STREAM, 0); +#endif + + if (this->fd == -1) { this->state = I_ERROR; this->OnError(I_ERR_SOCKET); + delete[] addr; return false; } - if ((strstr(this->IP,"::ffff:") != (char*)&this->IP) && (strstr(this->IP,"::FFFF:") != (char*)&this->IP)) +#ifdef IPV6 + if (v6) { - if (!this->BindAddr()) - return false; + in6_addr addy; + if (inet_pton(AF_INET6, this->host, &addy) > 0) + { + ((sockaddr_in6*)addr)->sin6_family = AF_INET6; + memcpy(&((sockaddr_in6*)addr)->sin6_addr, &addy, sizeof(addy)); + ((sockaddr_in6*)addr)->sin6_port = htons(this->port); + size = sizeof(sockaddr_in6); + } + } + else + { + in_addr addy; + if (inet_aton(this->host, &addy) > 0) + { + ((sockaddr_in*)addr)->sin_family = AF_INET; + ((sockaddr_in*)addr)->sin_addr = addy; + ((sockaddr_in*)addr)->sin_port = htons(this->port); + } } - - insp_aton(this->IP,&addy); -#ifdef IPV6 - addr.sin6_family = AF_FAMILY; - memcpy(&addr.sin6_addr, &addy, sizeof(addy)); - addr.sin6_port = htons(this->port); #else - addr.sin_family = AF_FAMILY; - addr.sin_addr = addy; - addr.sin_port = htons(this->port); + in_addr addy; + if (inet_aton(this->host, &addy) > 0) + { + ((sockaddr_in*)addr)->sin_family = AF_INET; + ((sockaddr_in*)addr)->sin_addr = addy; + ((sockaddr_in*)addr)->sin_port = htons(this->port); + } #endif int flags = fcntl(this->fd, F_GETFL, 0); fcntl(this->fd, F_SETFL, flags | O_NONBLOCK); - if (connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1) + if (connect(this->fd, (sockaddr*)addr, size) == -1) { if (errno != EINPROGRESS) { @@ -486,24 +587,36 @@ bool InspSocket::Poll() return this->OnConnected(); break; case I_LISTENING: - length = sizeof (client); - incoming = accept (this->fd, (sockaddr*)&client,&length); + { + sockaddr* client = new sockaddr[2]; + length = sizeof (sockaddr_in); + std::string recvip; +#ifdef IPV6 + if ((!*this->host) || strchr(this->host, ':')) + length = sizeof(sockaddr_in6); +#endif + incoming = accept (this->fd, client, &length); #ifdef IPV6 - this->OnIncomingConnection(incoming, (char*)insp_ntoa(client.sin6_addr)); + if ((!*this->host) || strchr(this->host, ':')) + { + char buf[1024]; + recvip = inet_ntop(AF_INET6, ((sockaddr_in6*)client)->sin6_addr, buf, sizeof(buf)); + } + else + { + recvip = insp_ntoa(((sockaddr_in*)client)->sin_addr); + } #else - this->OnIncomingConnection(incoming, (char*)insp_ntoa(client.sin_addr)); + recvip = insp_ntoa(((sockaddr_in*)client)->sin_addr); #endif + this->OnIncomingConnection(incoming, (char*)recvip.c_str()); if (this->IsIOHooked) { try { -#ifdef IPV6 - Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, insp_ntoa(client.sin6_addr), this->port); -#else - Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, insp_ntoa(client.sin_addr), this->port); -#endif + Instance->Config->GetIOHook(this)->OnRawSocketAccept(incoming, recvip.c_str(), this->port); } catch (CoreException& modexcept) { @@ -512,7 +625,10 @@ bool InspSocket::Poll() } this->SetQueues(incoming); + + delete[] client; return true; + } break; case I_CONNECTED: /* Process the read event */ -- cgit v1.2.3