summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Powell <petpow@saberuk.com>2019-02-07 15:34:41 +0000
committerPeter Powell <petpow@saberuk.com>2019-04-15 12:21:12 +0100
commitc2c4de7267db9835e36132364f422ba7d93f25d6 (patch)
treec165dda97b90d713cf25ddd7ddd000839c2e3405
parente7b65ef5355d75dd32ea387da716a765090aff0e (diff)
Fix linking servers with UNIX sockets.
- Remove the address/port overloads of BeginConnect. - Change DoConnect to take a sockaddrs instead of an address/port.
-rw-r--r--include/inspsocket.h8
-rw-r--r--src/inspsocket.cpp25
-rw-r--r--src/modules/m_spanningtree/main.cpp32
-rw-r--r--src/modules/m_spanningtree/resolvers.cpp10
-rw-r--r--src/modules/m_spanningtree/treesocket.h2
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp14
-rw-r--r--src/modules/m_spanningtree/utils.cpp2
7 files changed, 43 insertions, 50 deletions
diff --git a/include/inspsocket.h b/include/inspsocket.h
index 69fdaac8b..a41c3ebc7 100644
--- a/include/inspsocket.h
+++ b/include/inspsocket.h
@@ -380,12 +380,11 @@ class CoreExport BufferedSocket : public StreamSocket
* This will create a socket, register with socket engine, and start the asynchronous
* connection process. If an error is detected at this point (such as out of file descriptors),
* OnError will be called; otherwise, the state will become CONNECTING.
- * @param ipaddr Address to connect to
- * @param aport Port to connect on
+ * @param dest Remote endpoint to connect to.
+ * @param bind Local endpoint to connect from.
* @param maxtime Time to wait for connection
- * @param connectbindip Address to bind to (if NULL, no bind will be done)
*/
- void DoConnect(const std::string& ipaddr, int aport, unsigned int maxtime, const std::string& connectbindip);
+ void DoConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned int maxtime);
/** This method is called when an outbound connection on your socket is
* completed.
@@ -412,7 +411,6 @@ class CoreExport BufferedSocket : public StreamSocket
protected:
void OnEventHandlerWrite() CXX11_OVERRIDE;
BufferedSocketError BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned int timeout);
- BufferedSocketError BeginConnect(const std::string& ipaddr, int aport, unsigned int maxtime, const std::string& connectbindip);
};
inline IOHook* StreamSocket::GetIOHook() const { return iohook; }
diff --git a/src/inspsocket.cpp b/src/inspsocket.cpp
index ebbff448e..59d9558a4 100644
--- a/src/inspsocket.cpp
+++ b/src/inspsocket.cpp
@@ -48,9 +48,9 @@ BufferedSocket::BufferedSocket(int newfd)
SocketEngine::AddFd(this, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE);
}
-void BufferedSocket::DoConnect(const std::string& ipaddr, int aport, unsigned int maxtime, const std::string& connectbindip)
+void BufferedSocket::DoConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned int maxtime)
{
- BufferedSocketError err = BeginConnect(ipaddr, aport, maxtime, connectbindip);
+ BufferedSocketError err = BeginConnect(dest, bind, maxtime);
if (err != I_ERR_NONE)
{
state = I_ERROR;
@@ -59,27 +59,6 @@ void BufferedSocket::DoConnect(const std::string& ipaddr, int aport, unsigned in
}
}
-BufferedSocketError BufferedSocket::BeginConnect(const std::string& ipaddr, int aport, unsigned int maxtime, const std::string& connectbindip)
-{
- irc::sockets::sockaddrs addr, bind;
- if (!irc::sockets::aptosa(ipaddr, aport, addr))
- {
- ServerInstance->Logs->Log("SOCKET", LOG_DEBUG, "BUG: Hostname passed to BufferedSocket, rather than an IP address!");
- return I_ERR_CONNECT;
- }
-
- bind.sa.sa_family = 0;
- if (!connectbindip.empty())
- {
- if (!irc::sockets::aptosa(connectbindip, 0, bind))
- {
- return I_ERR_BIND;
- }
- }
-
- return BeginConnect(addr, bind, maxtime);
-}
-
BufferedSocketError BufferedSocket::BeginConnect(const irc::sockets::sockaddrs& dest, const irc::sockets::sockaddrs& bind, unsigned int timeout)
{
if (fd < 0)
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 920840f9b..8b24b1e22 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -198,40 +198,38 @@ void ModuleSpanningTree::ConnectServer(Autoconnect* a, bool on_timer)
void ModuleSpanningTree::ConnectServer(Link* x, Autoconnect* y)
{
- bool ipvalid = true;
-
if (InspIRCd::Match(ServerInstance->Config->ServerName, x->Name, ascii_case_insensitive_map))
{
ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Not connecting to myself.");
return;
}
+ irc::sockets::sockaddrs sa;
#ifndef _WIN32
if (x->IPAddr.find('/') != std::string::npos)
{
struct stat sb;
- if (stat(x->IPAddr.c_str(), &sb) == -1 || !S_ISSOCK(sb.st_mode))
- ipvalid = false;
- }
-#endif
- if (x->IPAddr.find(':') != std::string::npos)
- {
- in6_addr n;
- if (inet_pton(AF_INET6, x->IPAddr.c_str(), &n) < 1)
- ipvalid = false;
+ if (stat(x->IPAddr.c_str(), &sb) == -1 || !S_ISSOCK(sb.st_mode) || !irc::sockets::untosa(x->IPAddr, sa))
+ {
+ // We don't use the family() != AF_UNSPEC check below for UNIX sockets as
+ // that results in a DNS lookup.
+ ServerInstance->SNO->WriteToSnoMask('l', "CONNECT: Error connecting \002%s\002: %s is not a UNIX socket!",
+ x->Name.c_str(), x->IPAddr.c_str());
+ return;
+ }
}
else
+#endif
{
- in_addr n;
- if (inet_pton(AF_INET, x->IPAddr.c_str(),&n) < 1)
- ipvalid = false;
+ // If this fails then the IP sa will be AF_UNSPEC.
+ irc::sockets::aptosa(x->IPAddr, x->Port, sa);
}
-
+
/* Do we already have an IP? If so, no need to resolve it. */
- if (ipvalid)
+ if (sa.family() != AF_UNSPEC)
{
// Create a TreeServer object that will start connecting immediately in the background
- TreeSocket* newsocket = new TreeSocket(x, y, x->IPAddr);
+ TreeSocket* newsocket = new TreeSocket(x, y, sa);
if (newsocket->GetFd() > -1)
{
/* Handled automatically on success */
diff --git a/src/modules/m_spanningtree/resolvers.cpp b/src/modules/m_spanningtree/resolvers.cpp
index ded0573af..b20b100dd 100644
--- a/src/modules/m_spanningtree/resolvers.cpp
+++ b/src/modules/m_spanningtree/resolvers.cpp
@@ -49,6 +49,14 @@ void ServernameResolver::OnLookupComplete(const DNS::Query *r)
return;
}
+ irc::sockets::sockaddrs sa;
+ if (!irc::sockets::aptosa(ans_record->rdata, MyLink->Port, sa))
+ {
+ // We had a result but it wasn't a valid IPv4/IPv6.
+ OnError(r);
+ return;
+ }
+
/* Initiate the connection, now that we have an IP to use.
* Passing a hostname directly to BufferedSocket causes it to
* just bail and set its FD to -1.
@@ -56,7 +64,7 @@ void ServernameResolver::OnLookupComplete(const DNS::Query *r)
TreeServer* CheckDupe = Utils->FindServer(MyLink->Name);
if (!CheckDupe) /* Check that nobody tried to connect it successfully while we were resolving */
{
- TreeSocket* newsocket = new TreeSocket(MyLink, myautoconnect, ans_record->rdata);
+ TreeSocket* newsocket = new TreeSocket(MyLink, myautoconnect, sa);
if (newsocket->GetFd() > -1)
{
/* We're all OK */
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index 6206448c1..547c87195 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -164,7 +164,7 @@ class TreeSocket : public BufferedSocket
* most of the action, and append a few of our own values
* to it.
*/
- TreeSocket(Link* link, Autoconnect* myac, const std::string& ipaddr);
+ TreeSocket(Link* link, Autoconnect* myac, const irc::sockets::sockaddrs& sa);
/** When a listening socket gives us a new file descriptor,
* we must associate it with a socket without creating a new
diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp
index 062d04222..fd20d04c4 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -36,7 +36,7 @@
* BufferedSocket, we just call DoConnect() for most of the action,
* and only do minor initialization tasks ourselves.
*/
-TreeSocket::TreeSocket(Link* link, Autoconnect* myac, const std::string& ipaddr)
+TreeSocket::TreeSocket(Link* link, Autoconnect* myac, const irc::sockets::sockaddrs& dest)
: linkID(link->Name), LinkState(CONNECTING), MyRoot(NULL), proto_version(0)
, burstsent(false), age(ServerInstance->Time())
{
@@ -45,7 +45,17 @@ TreeSocket::TreeSocket(Link* link, Autoconnect* myac, const std::string& ipaddr)
capab->ac = myac;
capab->capab_phase = 0;
- DoConnect(ipaddr, link->Port, link->Timeout, link->Bind);
+ irc::sockets::sockaddrs bind;
+ memset(&bind, 0, sizeof(bind));
+ if ((dest.family() == AF_INET || dest.family() == AF_INET6) && !irc::sockets::aptosa(link->Bind, 0, bind))
+ {
+ state = I_ERROR;
+ SetError("Bind address '" + link->Bind + "' is not an valid IPv4 or IPv6 address");
+ TreeSocket::OnError(I_ERR_BIND);
+ return;
+ }
+
+ DoConnect(dest, bind, link->Timeout);
Utils->timeoutlist[this] = std::pair<std::string, unsigned int>(linkID, link->Timeout);
SendCapabilities(1);
}
diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp
index 1f2ed9c90..f78b8d4c0 100644
--- a/src/modules/m_spanningtree/utils.cpp
+++ b/src/modules/m_spanningtree/utils.cpp
@@ -303,7 +303,7 @@ void SpanningTreeUtilities::ReadConfiguration()
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Configuration warning: Link block '" + L->Name + "' has no IP defined! This will allow any IP to connect as this server, and MAY not be what you want.");
}
- if (!L->Port)
+ if (!L->Port && L->IPAddr.find('/') == std::string::npos)
ServerInstance->Logs->Log(MODNAME, LOG_DEFAULT, "Configuration warning: Link block '" + L->Name + "' has no port defined, you will not be able to /connect it.");
L->Fingerprint.erase(std::remove(L->Fingerprint.begin(), L->Fingerprint.end(), ':'), L->Fingerprint.end());