diff options
-rw-r--r-- | docs/conf/helpop.conf.example | 23 | ||||
-rw-r--r-- | src/modules/m_cgiirc.cpp | 118 |
2 files changed, 96 insertions, 45 deletions
diff --git a/docs/conf/helpop.conf.example b/docs/conf/helpop.conf.example index df886608d..a2a09fa87 100644 --- a/docs/conf/helpop.conf.example +++ b/docs/conf/helpop.conf.example @@ -32,14 +32,14 @@ parameter for this command. <helpop key="cuser" title="User Commands" value=" ACCEPT ADMIN AWAY COMMANDS CYCLE DCCALLOW -FPART INFO INVITE ISON JOIN KICK -KNOCK LINKS LIST LUSERS MAP MKPASSWD -MODE MODULES MONITOR MOTD NAMES NICK -NOTICE OPER PART PASS PING PONG -PRIVMSG QUIT REMOVE SERVLIST SETNAME SILENCE -SQUERY SSLINFO STATS TBAN TIME TITLE -TOPIC UNINVITE USER USERHOST VERSION VHOST -WATCH WHO WHOIS WHOWAS +FPART HEXIP INFO INVITE ISON JOIN +KICK KNOCK LINKS LIST LUSERS MAP +MKPASSWD MODE MODULES MONITOR MOTD NAMES +NICK NOTICE OPER PART PASS PING +PONG PRIVMSG QUIT REMOVE SERVLIST SETNAME +SILENCE SQUERY SSLINFO STATS TBAN TIME +TITLE TOPIC UNINVITE USER USERHOST VERSION +VHOST WATCH WHO WHOIS WHOWAS "> <helpop key="squery" title="/SQUERY <target> :<message>" value=" @@ -152,6 +152,13 @@ This behaves identically to /REMOVE. /REMOVE is a built-in mIRC command which caused trouble for some users. "> +<helpop key="hexip" title="/HEXIP <hex-ip|raw-ip>" value=" +If the specified argument is an raw IP address then respond with the +hex encoded equivalent as if sent by an ident gateway. Otherwise, if +the specified argument is a hex encoded IP address then respond with +the equivalent raw IP address. +"> + <helpop key="silence" title="/SILENCE [(+|-)<mask> [CcdiNnPpTtx]]" value=" A server-side ignore of the given n!u@h mask. If the optional flags field is specified then it must contain one or more flags which specify what kind of diff --git a/src/modules/m_cgiirc.cpp b/src/modules/m_cgiirc.cpp index 107824985..971826b31 100644 --- a/src/modules/m_cgiirc.cpp +++ b/src/modules/m_cgiirc.cpp @@ -124,6 +124,84 @@ class WebIRCHost } }; +class CommandHexIP : public SplitCommand +{ + public: + CommandHexIP(Module* Creator) + : SplitCommand(Creator, "HEXIP", 1) + { + allow_empty_last_param = false; + Penalty = 2; + syntax = "<hex-ip|raw-ip>"; + } + + CmdResult HandleLocal(LocalUser* user, const Params& parameters) CXX11_OVERRIDE + { + irc::sockets::sockaddrs sa; + if (irc::sockets::aptosa(parameters[0], 0, sa)) + { + if (sa.family() != AF_INET) + { + user->WriteNotice("*** HEXIP: You can only hex encode an IPv4 address!"); + return CMD_FAILURE; + } + + uint32_t addr = sa.in4.sin_addr.s_addr; + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s encodes to %02x%02x%02x%02x.", + sa.addr().c_str(), (addr & 0xFF), ((addr >> 8) & 0xFF), ((addr >> 16) & 0xFF), + ((addr >> 24) & 0xFF))); + return CMD_SUCCESS; + } + + if (ParseIP(parameters[0], sa)) + { + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s decodes to %s.", + parameters[0].c_str(), sa.addr().c_str())); + return CMD_SUCCESS; + } + + user->WriteNotice(InspIRCd::Format("*** HEXIP: %s is not a valid raw or hex encoded IPv4 address.", + parameters[0].c_str())); + return CMD_FAILURE; + } + + static bool ParseIP(const std::string& in, irc::sockets::sockaddrs& out) + { + const char* ident = NULL; + if (in.length() == 8) + { + // The ident is an IPv4 address encoded in hexadecimal with two characters + // per address segment. + ident = in.c_str(); + } + else if (in.length() == 9 && in[0] == '~') + { + // The same as above but m_ident got to this user before we did. Strip the + // ident prefix and continue as normal. + ident = in.c_str() + 1; + } + else + { + // The user either does not have an IPv4 in their ident or the gateway server + // is also running an identd. In the latter case there isn't really a lot we + // can do so we just assume that the client in question is not connecting via + // an ident gateway. + return false; + } + + // Try to convert the IP address to a string. If this fails then the user + // does not have an IPv4 address in their ident. + errno = 0; + unsigned long address = strtoul(ident, NULL, 16); + if (errno) + return false; + + out.in4.sin_family = AF_INET; + out.in4.sin_addr.s_addr = htonl(address); + return true; + } +}; + class CommandWebIRC : public SplitCommand { public: @@ -236,49 +314,15 @@ class ModuleCgiIRC , public Whois::EventListener { private: + CommandHexIP cmdhexip; CommandWebIRC cmdwebirc; std::vector<IdentHost> hosts; - static bool ParseIdent(LocalUser* user, irc::sockets::sockaddrs& out) - { - const char* ident = NULL; - if (user->ident.length() == 8) - { - // The ident is an IPv4 address encoded in hexadecimal with two characters - // per address segment. - ident = user->ident.c_str(); - } - else if (user->ident.length() == 9 && user->ident[0] == '~') - { - // The same as above but m_ident got to this user before we did. Strip the - // ident prefix and continue as normal. - ident = user->ident.c_str() + 1; - } - else - { - // The user either does not have an IPv4 in their ident or the gateway server - // is also running an identd. In the latter case there isn't really a lot we - // can do so we just assume that the client in question is not connecting via - // an ident gateway. - return false; - } - - // Try to convert the IP address to a string. If this fails then the user - // does not have an IPv4 address in their ident. - errno = 0; - unsigned long address = strtoul(ident, NULL, 16); - if (errno) - return false; - - out.in4.sin_family = AF_INET; - out.in4.sin_addr.s_addr = htonl(address); - return true; - } - public: ModuleCgiIRC() : WebIRC::EventListener(this) , Whois::EventListener(this) + , cmdhexip(this) , cmdwebirc(this) { } @@ -392,7 +436,7 @@ class ModuleCgiIRC // We have matched an <cgihost> block! Try to parse the encoded IPv4 address // out of the ident. irc::sockets::sockaddrs address(user->client_sa); - if (!ParseIdent(user, address)) + if (!CommandHexIP::ParseIP(user->ident, address)) return MOD_RES_PASSTHRU; // Store the hostname and IP of the gateway for later use. |