diff --git a/include/znc/Listener.h b/include/znc/Listener.h index a6b05353..92d2f581 100644 --- a/include/znc/Listener.h +++ b/include/znc/Listener.h @@ -29,27 +29,19 @@ class CListener { public: typedef enum { ACCEPT_IRC, ACCEPT_HTTP, ACCEPT_ALL } EAcceptType; - CListener(unsigned short uPort, const CString& sBindHost, - const CString& sURIPrefix, bool bSSL, EAddrType eAddr, - EAcceptType eAccept) + CListener(const CString& sURIPrefix, bool bSSL, EAcceptType eAccept) : m_bSSL(bSSL), - m_eAddr(eAddr), - m_uPort(uPort), - m_sBindHost(sBindHost), m_sURIPrefix(sURIPrefix), m_pListener(nullptr), m_eAcceptType(eAccept) {} - ~CListener(); + virtual ~CListener(); CListener(const CListener&) = delete; CListener& operator=(const CListener&) = delete; // Getters bool IsSSL() const { return m_bSSL; } - EAddrType GetAddrType() const { return m_eAddr; } - unsigned short GetPort() const { return m_uPort; } - const CString& GetBindHost() const { return m_sBindHost; } CRealListener* GetRealListener() const { return m_pListener; } const CString& GetURIPrefix() const { return m_sURIPrefix; } EAcceptType GetAcceptType() const { return m_eAcceptType; } @@ -59,21 +51,47 @@ class CListener { // except this one, so don't add other setters! void SetAcceptType(EAcceptType eType) { m_eAcceptType = eType; } - bool Listen(); + virtual bool Listen() = 0; void ResetRealListener(); - CConfig ToConfig() const; + virtual CConfig ToConfig() const = 0; private: protected: bool m_bSSL; - EAddrType m_eAddr; - unsigned short m_uPort; - CString m_sBindHost; CString m_sURIPrefix; CRealListener* m_pListener; EAcceptType m_eAcceptType; }; +class CTCPListener : public CListener { + public: + CTCPListener(unsigned short uPort, const CString& sBindHost, + const CString& sURIPrefix, bool bSSL, EAddrType eAddr, + EAcceptType eAccept) + : CListener(sURIPrefix, bSSL, eAccept), + m_eAddr(eAddr), + m_uPort(uPort), + m_sBindHost(sBindHost) {} + ~CTCPListener(); + + CTCPListener(const CTCPListener&) = delete; + CTCPListener& operator=(const CTCPListener&) = delete; + + // Getters + EAddrType GetAddrType() const { return m_eAddr; } + unsigned short GetPort() const { return m_uPort; } + const CString& GetBindHost() const { return m_sBindHost; } + // !Getters + + bool Listen() override; + CConfig ToConfig() const override; + + protected: + EAddrType m_eAddr; + unsigned short m_uPort; + CString m_sBindHost; +}; + class CRealListener : public CZNCSock { public: CRealListener(CListener& listener) : CZNCSock(), m_Listener(listener) {} diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index b44342a6..722c45a6 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -161,7 +161,7 @@ class CWebAdminMod : public CModule { } // Now turn that into a listener instance - CListener* pListener = new CListener( + CListener* pListener = new CTCPListener( uPort, sListenHost, sURIPrefix, bSSL, (!bIPv6 ? ADDR_IPV4ONLY : ADDR_ALL), CListener::ACCEPT_HTTP); @@ -1883,8 +1883,18 @@ class CWebAdminMod : public CModule { for (const CListener* pListener : vpListeners) { CTemplate& l = Tmpl.AddRow("ListenLoop"); - l["Port"] = CString(pListener->GetPort()); - l["BindHost"] = pListener->GetBindHost(); + const CTCPListener* pTCPListener = dynamic_cast(pListener); + if (pTCPListener != nullptr) { + l["Port"] = CString(pTCPListener->GetPort()); + l["BindHost"] = pTCPListener->GetBindHost(); + + // simple protection for user from shooting his own foot + // TODO check also for hosts/families + // such check is only here, user still can forge HTTP request to + // delete web port + l["SuggestDeletion"] = + CString(pTCPListener->GetPort() != WebSock.GetLocalPort()); + } l["IsHTTP"] = CString(pListener->GetAcceptType() != CListener::ACCEPT_IRC); @@ -1893,13 +1903,6 @@ class CWebAdminMod : public CModule { l["URIPrefix"] = pListener->GetURIPrefix() + "/"; - // simple protection for user from shooting his own foot - // TODO check also for hosts/families - // such check is only here, user still can forge HTTP request to - // delete web port - l["SuggestDeletion"] = - CString(pListener->GetPort() != WebSock.GetLocalPort()); - #ifdef HAVE_LIBSSL if (pListener->IsSSL()) { l["IsSSL"] = "true"; @@ -1907,20 +1910,24 @@ class CWebAdminMod : public CModule { #endif #ifdef HAVE_IPV6 - switch (pListener->GetAddrType()) { - case ADDR_IPV4ONLY: - l["IsIPV4"] = "true"; - break; - case ADDR_IPV6ONLY: - l["IsIPV6"] = "true"; - break; - case ADDR_ALL: - l["IsIPV4"] = "true"; - l["IsIPV6"] = "true"; - break; + if (pTCPListener != nullptr) { + switch (pTCPListener->GetAddrType()) { + case ADDR_IPV4ONLY: + l["IsIPV4"] = "true"; + break; + case ADDR_IPV6ONLY: + l["IsIPV6"] = "true"; + break; + case ADDR_ALL: + l["IsIPV4"] = "true"; + l["IsIPV6"] = "true"; + break; + } } #else - l["IsIPV4"] = "true"; + if (pTCPListener != nullptr) { + l["IsIPV4"] = "true"; + } #endif } diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp index fa728d66..cdd8c9e0 100644 --- a/src/ClientCommand.cpp +++ b/src/ClientCommand.cpp @@ -1543,17 +1543,25 @@ void CClient::UserPortCommand(CString& sLine) { for (const CListener* pListener : vpListeners) { Table.AddRow(); - Table.SetCell("Port", CString(pListener->GetPort())); - Table.SetCell("BindHost", (pListener->GetBindHost().empty() - ? CString("*") - : pListener->GetBindHost())); - Table.SetCell("SSL", CString(pListener->IsSSL())); - EAddrType eAddr = pListener->GetAddrType(); - Table.SetCell("Proto", - (eAddr == ADDR_ALL - ? "All" - : (eAddr == ADDR_IPV4ONLY ? "IPv4" : "IPv6"))); + const CTCPListener* pTCPListener = dynamic_cast(pListener); + + if (pTCPListener != nullptr) { + Table.SetCell("Port", CString(pTCPListener->GetPort())); + Table.SetCell("BindHost", (pTCPListener->GetBindHost().empty() + ? CString("*") + : pTCPListener->GetBindHost())); + + EAddrType eAddr = pTCPListener->GetAddrType(); + Table.SetCell("Proto", + (eAddr == ADDR_ALL + ? "All" + : (eAddr == ADDR_IPV4ONLY ? "IPv4" : "IPv6"))); + } else { + Table.SetCell("Port", "unknown"); + } + + Table.SetCell("SSL", CString(pListener->IsSSL())); CListener::EAcceptType eAccept = pListener->GetAcceptType(); Table.SetCell( @@ -1608,7 +1616,7 @@ void CClient::UserPortCommand(CString& sLine) { const CString sBindHost = sLine.Token(4); const CString sURIPrefix = sLine.Token(5); - CListener* pListener = new CListener(uPort, sBindHost, sURIPrefix, + CListener* pListener = new CTCPListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept); if (!pListener->Listen()) { diff --git a/src/Listener.cpp b/src/Listener.cpp index 50023018..a8cce98a 100644 --- a/src/Listener.cpp +++ b/src/Listener.cpp @@ -22,7 +22,10 @@ CListener::~CListener() { if (m_pListener) CZNC::Get().GetManager().DelSockByAddr(m_pListener); } -bool CListener::Listen() { +CTCPListener::~CTCPListener() { +} + +bool CTCPListener::Listen() { if (!m_uPort || m_pListener) { errno = EINVAL; return false; @@ -49,7 +52,7 @@ bool CListener::Listen() { m_pListener, 0, m_eAddr); } -CConfig CListener::ToConfig() const { +CConfig CTCPListener::ToConfig() const { CConfig listenerConfig; listenerConfig.AddKeyValuePair("Host", GetBindHost()); diff --git a/src/znc.cpp b/src/znc.cpp index 810f065d..1f6de301 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -669,7 +669,7 @@ bool CZNC::WriteNewConfig(const CString& sConfigFile) { // Don't ask for listen host, it may be configured later if needed. CUtils::PrintAction("Verifying the listener"); - CListener* pListener = new CListener( + CListener* pListener = new CTCPListener( (unsigned short int)uListenPort, sListenHost, sURIPrefix, bListenSSL, b6 ? ADDR_ALL : ADDR_IPV4ONLY, CListener::ACCEPT_ALL); if (!pListener->Listen()) { @@ -1568,9 +1568,11 @@ bool CZNC::AddUser(CUser* pUser, CString& sErrorRet, bool bStartup) { CListener* CZNC::FindListener(u_short uPort, const CString& sBindHost, EAddrType eAddr) { for (CListener* pListener : m_vpListeners) { - if (pListener->GetPort() != uPort) continue; - if (pListener->GetBindHost() != sBindHost) continue; - if (pListener->GetAddrType() != eAddr) continue; + CTCPListener* pTCPListener = dynamic_cast(pListener); + if (!pTCPListener) continue; + if (pTCPListener->GetPort() != uPort) continue; + if (pTCPListener->GetBindHost() != sBindHost) continue; + if (pTCPListener->GetAddrType() != eAddr) continue; return pListener; } return nullptr; @@ -1700,7 +1702,7 @@ bool CZNC::AddListener(unsigned short uPort, const CString& sBindHost, } CListener* pListener = - new CListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept); + new CTCPListener(uPort, sBindHost, sURIPrefix, bSSL, eAddr, eAccept); if (!pListener->Listen()) { sError = FormatBindError();