Add support for listening on a unix domain socket

So far this is not integrated with ClientCommand.cpp or webadmin.cpp, so
the only way to actually use this is to hand-editing the config with a
<Listener> section like the following:

<Listener 42>
  Path = /tmp/listen
  SSL = false
</Listener>

So far this received only very basic testing. I did not even test SSL support.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter
2017-01-12 12:02:51 +01:00
parent cb94756ec5
commit 811f453efb
4 changed files with 145 additions and 21 deletions
+22
View File
@@ -92,6 +92,28 @@ class CTCPListener : public CListener {
CString m_sBindHost;
};
class CUnixListener : public CListener {
public:
CUnixListener(const CString& sPath, const CString& sURIPrefix, bool bSSL,
EAcceptType eAccept)
: CListener(sURIPrefix, bSSL, eAccept),
m_sPath(sPath) {}
~CUnixListener();
CUnixListener(const CUnixListener&) = delete;
CUnixListener& operator=(const CUnixListener&) = delete;
// Getters
const CString& GetPath() const { return m_sPath; }
// !Getters
bool Listen() override;
CConfig ToConfig() const override;
protected:
CString m_sPath;
};
class CRealListener : public CZNCSock {
public:
CRealListener(CListener& listener) : CZNCSock(), m_Listener(listener) {}
+2
View File
@@ -204,6 +204,8 @@ class CZNC {
bool AddListener(unsigned short uPort, const CString& sBindHost,
const CString& sURIPrefix, bool bSSL, EAddrType eAddr,
CListener::EAcceptType eAccept, CString& sError);
bool AddListener(const CString& sPath, const CString& sURIPrefix, bool bSSL,
CListener::EAcceptType eAccept, CString& sError);
bool DelListener(CListener*);
// Message of the Day
+29
View File
@@ -83,6 +83,35 @@ CConfig CTCPListener::ToConfig() const {
return listenerConfig;
}
CUnixListener::~CUnixListener() {
}
bool CUnixListener::Listen() {
CString sName = "unix:" + m_sPath;
m_pListener = new CRealListener(*this);
#ifdef HAVE_LIBSSL
if (IsSSL()) {
m_pListener->SetSSL(true);
m_pListener->SetPemLocation(CZNC::Get().GetPemLocation());
m_pListener->SetKeyLocation(CZNC::Get().GetKeyLocation());
m_pListener->SetDHParamLocation(CZNC::Get().GetDHParamLocation());
}
#endif
CZNC::Get().GetManager().AddSock(m_pListener, sName);
return m_pListener->ListenUnix(m_sPath);
}
CConfig CUnixListener::ToConfig() const {
CConfig listenerConfig = CListener::ToConfig();
listenerConfig.AddKeyValuePair("Path", GetPath());
return listenerConfig;
}
void CListener::ResetRealListener() { m_pListener = nullptr; }
CRealListener::~CRealListener() { m_Listener.ResetRealListener(); }
+92 -21
View File
@@ -1717,9 +1717,70 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost,
return true;
}
bool CZNC::AddListener(const CString& sPath, const CString& sURIPrefixRaw,
bool bSSL, CListener::EAcceptType eAccept,
CString& sError) {
CUtils::PrintAction("Binding to path [" + sPath + "]");
#ifndef HAVE_LIBSSL
if (bSSL) {
sError = "SSL is not enabled";
CUtils::PrintStatus(false, sError);
return false;
}
#else
CString sPemFile = GetPemLocation();
if (bSSL && !CFile::Exists(sPemFile)) {
sError = "Unable to locate pem file: [" + sPemFile + "]";
CUtils::PrintStatus(false, sError);
// If stdin is e.g. /dev/null and we call GetBoolInput(),
// we are stuck in an endless loop!
if (isatty(0) &&
CUtils::GetBoolInput("Would you like to create a new pem file?",
true)) {
sError.clear();
WritePemFile();
} else {
return false;
}
CUtils::PrintAction("Binding to path [" + sPath + "]");
}
#endif
// URIPrefix must start with a slash and end without one.
CString sURIPrefix = CString(sURIPrefixRaw);
if (!sURIPrefix.empty()) {
if (!sURIPrefix.StartsWith("/")) {
sURIPrefix = "/" + sURIPrefix;
}
if (sURIPrefix.EndsWith("/")) {
sURIPrefix.TrimRight("/");
}
}
CListener* pListener =
new CUnixListener(sPath, sURIPrefix, bSSL, eAccept);
if (!pListener->Listen()) {
sError = FormatBindError();
CUtils::PrintStatus(false, sError);
delete pListener;
return false;
}
m_vpListeners.push_back(pListener);
CUtils::PrintStatus(true);
return true;
}
bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
CString sBindHost;
CString sURIPrefix;
CString sPath;
bool bSSL;
bool b4;
#ifdef HAVE_IPV6
@@ -1730,32 +1791,22 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
bool bIRC;
bool bWeb;
unsigned short uPort;
bool bTcpListener = true;
if (!pConfig->FindUShortEntry("port", uPort)) {
sError = "No port given";
CUtils::PrintError(sError);
return false;
bTcpListener = false;
if (!pConfig->FindStringEntry("path", sPath)) {
sError = "No port and no path given";
CUtils::PrintError(sError);
return false;
}
}
pConfig->FindStringEntry("host", sBindHost);
pConfig->FindBoolEntry("ssl", bSSL, false);
pConfig->FindBoolEntry("ipv4", b4, true);
pConfig->FindBoolEntry("ipv6", b6, b6);
pConfig->FindBoolEntry("allowirc", bIRC, true);
pConfig->FindBoolEntry("allowweb", bWeb, true);
pConfig->FindStringEntry("uriprefix", sURIPrefix);
EAddrType eAddr;
if (b4 && b6) {
eAddr = ADDR_ALL;
} else if (b4 && !b6) {
eAddr = ADDR_IPV4ONLY;
} else if (!b4 && b6) {
eAddr = ADDR_IPV6ONLY;
} else {
sError = "No address family given";
CUtils::PrintError(sError);
return false;
}
CListener::EAcceptType eAccept;
if (bIRC && bWeb) {
eAccept = CListener::ACCEPT_ALL;
@@ -1769,8 +1820,28 @@ bool CZNC::AddListener(CConfig* pConfig, CString& sError) {
return false;
}
return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept,
sError);
if (bTcpListener) {
pConfig->FindStringEntry("host", sBindHost);
pConfig->FindBoolEntry("ipv4", b4, true);
pConfig->FindBoolEntry("ipv6", b6, b6);
EAddrType eAddr;
if (b4 && b6) {
eAddr = ADDR_ALL;
} else if (b4 && !b6) {
eAddr = ADDR_IPV4ONLY;
} else if (!b4 && b6) {
eAddr = ADDR_IPV6ONLY;
} else {
sError = "No address family given";
CUtils::PrintError(sError);
return false;
}
return AddListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept,
sError);
}
return AddListener(sPath, sURIPrefix, bSSL, eAccept, sError);
}
bool CZNC::AddListener(CListener* pListener) {