/* NeoStats - IRC Statistical Services ** Copyright (c) 1999-2004 Adam Rutter, Justin Hammond ** http://www.neostats.net/ ** ** Portions Copyright (c) 2000-2001 ^Enigma^ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ** USA ** ** NeoStats CVS Identification ** $Id$ */ #include #include #include #include #include #include "stats.h" #include "Unreal.h" #include "ircd.h" static void m_version (char *origin, char **argv, int argc, int srv); static void m_motd (char *origin, char **argv, int argc, int srv); static void m_admin (char *origin, char **argv, int argc, int srv); static void m_credits (char *origin, char **argv, int argc, int srv); static void m_server (char *origin, char **argv, int argc, int srv); static void m_squit (char *origin, char **argv, int argc, int srv); static void m_quit (char *origin, char **argv, int argc, int srv); static void m_mode (char *origin, char **argv, int argc, int srv); static void m_umode2 (char *origin, char **argv, int argc, int srv); static void m_svsmode (char *origin, char **argv, int argc, int srv); static void m_kill (char *origin, char **argv, int argc, int srv); static void m_pong (char *origin, char **argv, int argc, int srv); static void m_away (char *origin, char **argv, int argc, int srv); static void m_nick (char *origin, char **argv, int argc, int srv); static void m_topic (char *origin, char **argv, int argc, int srv); static void m_kick (char *origin, char **argv, int argc, int srv); static void m_join (char *origin, char **argv, int argc, int srv); static void m_part (char *origin, char **argv, int argc, int srv); static void m_stats (char *origin, char **argv, int argc, int srv); static void m_vhost (char *origin, char **argv, int argc, int srv); #ifdef UNREAL32 static void m_eos (char *origin, char **argv, int argc, int srv); #endif static void m_ping (char *origin, char **argv, int argc, int srv); static void m_netinfo (char *origin, char **argv, int argc, int srv); static void m_sjoin (char *origin, char **argv, int argc, int srv); static void m_pass (char *origin, char **argv, int argc, int srv); static void m_svsnick (char *origin, char **argv, int argc, int srv); static void m_protocol (char *origin, char **argv, int argc, int srv); static void m_whois (char *origin, char **argv, int argc, int srv); static void m_smo (char *origin, char **argv, int argc, int srv); static void m_swhois (char *origin, char **argv, int argc, int srv); static void m_tkl (char *origin, char **argv, int argc, int srv); static int decode_ip(char *buf); #define NICKV2 #ifdef UNREAL32 const char ircd_version[] = "(U32)"; #else const char ircd_version[] = "(U31)"; #endif const char services_bot_modes[]= "+oSq"; ircd_cmd cmd_list[] = { /*Message Token Function usage */ {MSG_PRIVATE, TOK_PRIVATE, m_private, 0}, {MSG_NOTICE, TOK_NOTICE, m_notice, 0}, {MSG_STATS, TOK_STATS, m_stats, 0}, {MSG_SETHOST, TOK_SETHOST, m_vhost, 0}, {MSG_VERSION, TOK_VERSION, m_version, 0}, {MSG_MOTD, TOK_MOTD, m_motd, 0}, {MSG_ADMIN, TOK_ADMIN, m_admin, 0}, {MSG_CREDITS, TOK_CREDITS, m_credits, 0}, {MSG_SERVER, TOK_SERVER, m_server, 0}, {MSG_SQUIT, TOK_SQUIT, m_squit, 0}, {MSG_QUIT, TOK_QUIT, m_quit, 0}, {MSG_MODE, TOK_MODE, m_mode, 0}, {MSG_UMODE2, TOK_UMODE2, m_umode2, 0}, {MSG_SVSMODE, TOK_SVSMODE, m_svsmode, 0}, {MSG_SVS2MODE, TOK_SVS2MODE, m_svsmode, 0}, {MSG_KILL, TOK_KILL, m_kill, 0}, {MSG_PONG, TOK_PONG, m_pong, 0}, {MSG_AWAY, TOK_AWAY, m_away, 0}, {MSG_NICK, TOK_NICK, m_nick, 0}, {MSG_TOPIC, TOK_TOPIC, m_topic, 0}, {MSG_KICK, TOK_KICK, m_kick, 0}, {MSG_JOIN, TOK_JOIN, m_join, 0}, {MSG_PART, TOK_PART, m_part, 0}, {MSG_PING, TOK_PING, m_ping, 0}, {MSG_NETINFO, TOK_NETINFO, m_netinfo, 0}, {MSG_SJOIN, TOK_SJOIN, m_sjoin, 0}, {MSG_PASS, TOK_PASS, m_pass, 0}, {MSG_SVSNICK, TOK_SVSNICK, m_svsnick, 0}, {MSG_PROTOCTL, TOK_PROTOCTL, m_protocol, 0}, {MSG_WHOIS, TOK_WHOIS, m_whois, 0}, {MSG_SWHOIS, TOK_SWHOIS, m_swhois, 0}, {MSG_SMO, TOK_SMO, m_smo, 0}, #ifdef UNREAL32 {MSG_EOS, TOK_EOS, m_eos, 0}, #endif {MSG_TKL, TOK_TKL, m_tkl, 0}, }; ChanModes chan_modes[] = { {CMODE_VOICE, 'v', 1, 0, '+'}, {CMODE_HALFOP, 'h', 1, 0, '%'}, {CMODE_CHANOP, 'o', 1, 0, '@'}, {CMODE_CHANPROT, 'a', 1, 0, '*'}, {CMODE_CHANOWNER, 'q', 1, 0, '~'}, {CMODE_LIMIT, 'l', 0, 1}, {CMODE_PRIVATE, 'p', 0, 0}, {CMODE_SECRET, 's', 0, 0}, {CMODE_MODERATED, 'm', 0, 0}, {CMODE_NOPRIVMSGS, 'n', 0, 0}, {CMODE_TOPICLIMIT, 't', 0, 0}, {CMODE_INVITEONLY, 'i', 0, 0}, {CMODE_KEY, 'k', 0, 1}, {CMODE_RGSTR, 'r', 0, 0}, {CMODE_RGSTRONLY, 'R', 0, 0}, {CMODE_NOCOLOR, 'c', 0, 0}, {CMODE_OPERONLY, 'O', 0, 0}, {CMODE_ADMONLY, 'A', 0, 0}, {CMODE_LINK, 'L', 0, 1}, {CMODE_NOKICKS, 'Q', 0, 0}, {CMODE_BAN, 'b', 0, 1}, {CMODE_STRIP, 'S', 0, 0}, /* works? */ {CMODE_EXCEPT, 'e', 0, 1}, /* exception ban */ {CMODE_NOKNOCK, 'K', 0, 0}, /* knock knock (no way!) */ {CMODE_NOINVITE, 'V', 0, 0}, /* no invites */ {CMODE_FLOODLIMIT, 'f', 0, 1}, /* flood limiter */ {CMODE_MODREG, 'M', 0, 0}, /* need umode +r to talk */ {CMODE_STRIPBADWORDS, 'G', 0, 0}, /* no badwords */ {CMODE_NOCTCP, 'C', 0, 0}, /* no CTCPs */ {CMODE_AUDITORIUM, 'u', 0, 0}, {CMODE_ONLYSECURE, 'z', 0, 0}, {CMODE_NONICKCHANGE, 'N', 0, 0}, }; UserModes user_umodes[] = { {UMODE_SERVICES, 'S', NS_ULEVEL_ROOT}, {UMODE_NETADMIN, 'N', NS_ULEVEL_ADMIN}, {UMODE_SADMIN, 'a', NS_ULEVEL_ADMIN}, {UMODE_ADMIN, 'A', NS_ULEVEL_OPER}, {UMODE_COADMIN, 'C', NS_ULEVEL_OPER}, {UMODE_OPER, 'o', NS_ULEVEL_OPER}, {UMODE_LOCOP, 'O', NS_ULEVEL_LOCOPER}, {UMODE_REGNICK, 'r', NS_ULEVEL_REG}, {UMODE_INVISIBLE, 'i', 0}, {UMODE_WALLOP, 'w', 0}, {UMODE_FAILOP, 'g', 0}, {UMODE_HELPOP, 'h', 0}, {UMODE_SERVNOTICE, 's', 0}, {UMODE_KIX, 'q', 0}, {UMODE_BOT, 'B', 0}, /* temp removal of deaf for SVSMODE Services Stamp */ /* {UMODE_DEAF, 'd', 0},*/ #ifdef UNREAL32 {UMODE_RGSTRONLY, 'R', 0}, {UMODE_NOCTCP, 'T', 0}, {UMODE_WEBTV, 'V', 0}, {UMODE_HIDEWHOIS, 'p', 0}, {UMODE_HIDEOPER, 'H', 0}, #else {UMODE_KILLS, 'k', 0}, {UMODE_EYES, 'e', 0}, {UMODE_FCLIENT, 'F', 0}, {UMODE_CLIENT, 'c', 0}, {UMODE_FLOOD, 'f', 0}, {UMODE_JUNK, 'j', 0}, #endif {UMODE_STRIPBADWORDS, 'G', 0}, {UMODE_SETHOST, 't', 0}, {UMODE_HIDE, 'x', 0}, /*{UMODE_CHATOP, 'b', 0},*/ {UMODE_WHOIS, 'W', 0}, {UMODE_SECURE, 'z', 0}, {UMODE_VICTIM, 'v', 0}, }; const int ircd_cmdcount = ((sizeof (cmd_list) / sizeof (cmd_list[0]))); const int ircd_umodecount = ((sizeof (user_umodes) / sizeof (user_umodes[0]))); const int ircd_cmodecount = ((sizeof (chan_modes) / sizeof (chan_modes[0]))); void send_server (const char *sender, const char *name, const int numeric, const char *infoline) { send_cmd (":%s %s %s %d :%s", sender, (ircd_srv.token ? TOK_SERVER : MSG_SERVER), name, numeric, infoline); } void send_server_connect (const char *name, const int numeric, const char *infoline, const char *pass, unsigned long tsboot, unsigned long tslink) { /* PROTOCTL NOQUIT TOKEN NICKv2 SJOIN SJOIN2 UMODE2 VL SJ3 NS SJB64 */ send_cmd ("%s TOKEN NICKv2 VHP SJOIN SJOIN2 SJ3 UMODE2 NICKIP", (ircd_srv.token ? TOK_PROTOCTL : MSG_PROTOCTL)); send_cmd ("%s %s", (ircd_srv.token ? TOK_PASS : MSG_PASS), pass); send_cmd ("%s %s %d :%s", (ircd_srv.token ? TOK_SERVER : MSG_SERVER), name, numeric, infoline); } void send_squit (const char *server, const char *quitmsg) { send_cmd ("%s %s :%s", (ircd_srv.token ? TOK_SQUIT : MSG_SQUIT), server, quitmsg); } void send_quit (const char *who, const char *quitmsg) { send_cmd (":%s %s :%s", who, (ircd_srv.token ? TOK_QUIT : MSG_QUIT), quitmsg); } void send_part (const char *who, const char *chan) { send_cmd (":%s %s %s", who, (ircd_srv.token ? TOK_PART : MSG_PART), chan); } void send_join (const char *sender, const char *who, const char *chan, const unsigned long ts) { send_cmd (":%s %s %s", who, (ircd_srv.token ? TOK_JOIN : MSG_JOIN), chan); } void send_sjoin (const char *sender, const char *who, const char *chan, const unsigned long ts) { send_cmd (":%s %s %lu %s + :%s", sender, (ircd_srv.token ? TOK_SJOIN : MSG_SJOIN), ts, chan, who); } void send_cmode (const char *sender, const char *who, const char *chan, const char *mode, const char *args, unsigned long ts) { send_cmd (":%s %s %s %s %s %lu", who, (ircd_srv.token ? TOK_MODE : MSG_MODE), chan, mode, args, ts); } void send_nick (const char *nick, const unsigned long ts, const char* newmode, const char *ident, const char *host, const char* server, const char *realname) { send_cmd ("%s %s 1 %lu %s %s %s 0 :%s", (ircd_srv.token ? TOK_NICK : MSG_NICK), nick, ts, ident, host, server, realname); } void send_ping (const char *from, const char *reply, const char *to) { send_cmd (":%s %s %s :%s", from, (ircd_srv.token ? TOK_PING : MSG_PING), reply, to); } void send_umode (const char *who, const char *target, const char *mode) { send_cmd (":%s %s %s :%s", who, (ircd_srv.token ? TOK_MODE : MSG_MODE), target, mode); } void send_numeric (const char *from, const int numeric, const char *target, const char *buf) { send_cmd (":%s %d %s :%s", from, numeric, target, buf); } void send_pong (const char *reply) { send_cmd ("%s %s", (ircd_srv.token ? TOK_PONG : MSG_PONG), reply); } void send_netinfo (const char* from, const int prot, const char* cloak, const char* netname, const unsigned long ts) { send_cmd (":%s %s 0 %lu %d %s 0 0 0 :%s", from, (ircd_srv.token ? TOK_NETINFO : MSG_NETINFO), ts, prot, cloak, netname); } void send_kill (const char *from, const char *target, const char *reason) { send_cmd (":%s %s %s :%s", from, (ircd_srv.token ? TOK_KILL : MSG_KILL), target, reason); } void send_smo (const char *from, const char *umodetarget, const char *msg) { send_cmd (":%s %s %s :%s", from, (ircd_srv.token ? TOK_SMO : MSG_SMO), umodetarget, msg); } void send_nickchange (const char *oldnick, const char *newnick, const unsigned long ts) { send_cmd (":%s %s %s %lu", oldnick, (ircd_srv.token ? TOK_NICK : MSG_NICK), newnick, ts); } void send_swhois (const char *sender, const char *target, const char *swhois) { send_cmd ("%s %s :%s", (ircd_srv.token ? TOK_SWHOIS : MSG_SWHOIS), target, swhois); } void send_svsnick (const char *sender, const char *target, const char *newnick, const unsigned long ts) { send_cmd ("%s %s %s :%lu", (ircd_srv.token ? TOK_SVSNICK : MSG_SVSNICK), target, newnick, ts); } void send_svsjoin (const char *sender, const char *target, const char *chan) { send_cmd ("%s %s %s", (ircd_srv.token ? TOK_SVSJOIN : MSG_SVSJOIN), target, chan); } void send_svspart (const char *sender, const char *target, const char *chan) { send_cmd ("%s %s %s", (ircd_srv.token ? TOK_SVSPART : MSG_SVSPART), target, chan); } void send_kick (const char *who, const char *chan, const char *target, const char *reason) { send_cmd (":%s %s %s %s :%s", who, (ircd_srv.token ? TOK_KICK : MSG_KICK), chan, target, (reason ? reason : "No Reason Given")); } void send_wallops (const char *who, const char *buf) { send_cmd (":%s %s :%s", who, (ircd_srv.token ? TOK_WALLOPS : MSG_WALLOPS), buf); } void send_svshost (const char *sender, const char *who, const char *vhost) { send_cmd (":%s %s %s %s", sender, (ircd_srv.token ? TOK_CHGHOST : MSG_CHGHOST), who, vhost); } void send_invite (const char *from, const char *to, const char *chan) { send_cmd (":%s %s %s %s", from, (ircd_srv.token ? TOK_INVITE : MSG_INVITE), to, chan); } void send_svsmode (const char *sender, const char *target, const char *modes) { send_cmd (":%s %s %s %s", sender, (ircd_srv.token ? TOK_SVSMODE : MSG_SVSMODE), target, modes); } void send_svskill (const char *sender, const char *target, const char *reason) { send_cmd (":%s %s %s :%s", sender, (ircd_srv.token ? TOK_SVSKILL : MSG_SVSKILL), target, reason); } /* akill is gone in the latest Unreals, so we set Glines instead */ void send_akill (const char *sender, const char *host, const char *ident, const char *setby, const int length, const char *reason, unsigned long ts) { send_cmd (":%s %s + G %s %s %s %lu %lu :%s", sender, (ircd_srv.token ? TOK_TKL : MSG_TKL), ident, host, setby, (ts + length), ts, reason); } void send_rakill (const char *sender, const char *host, const char *ident) { send_cmd (":%s %s - G %s %s %s", sender, (ircd_srv.token ? TOK_TKL : MSG_TKL), ident, host, sender); } void send_privmsg (const char *from, const char *to, const char *buf) { send_cmd (":%s %s %s :%s", from, (ircd_srv.token ? TOK_PRIVATE : MSG_PRIVATE), to, buf); } void send_notice (const char *from, const char *to, const char *buf) { send_cmd (":%s %s %s :%s", from, (ircd_srv.token ? TOK_NOTICE : MSG_NOTICE), to, buf); } void send_globops (const char *from, const char *buf) { send_cmd (":%s %s :%s", from, (ircd_srv.token ? TOK_GLOBOPS : MSG_GLOBOPS), buf); } void send_svstime (const char *sender, const unsigned long ts) { send_cmd (":%s %s SVSTIME %lu", sender, (ircd_srv.token ? TOK_TSCTL : MSG_TSCTL), ts); } static void m_protocol (char *origin, char **argv, int argc, int srv) { do_protocol (origin, argv, argc); } static void m_stats (char *origin, char **argv, int argc, int srv) { do_stats (origin, argv[0]); } /* * m_version * argv[0] = remote server */ static void m_version (char *origin, char **argv, int argc, int srv) { do_version (origin, argv[0]); } static void m_motd (char *origin, char **argv, int argc, int srv) { do_motd (origin, argv[0]); } /* m_admin * argv[0] = servername */ static void m_admin (char *origin, char **argv, int argc, int srv) { do_admin (origin, argv[0]); } /*m_credits * argv[0] = servername */ static void m_credits (char *origin, char **argv, int argc, int srv) { do_credits (origin, argv[0]); } /* m_server * argv[0] = servername * argv[1] = hopcount * argv[2] = numeric * argv[3] = serverinfo * on old protocols, serverinfo is argv[2], and numeric is left out */ /*SERVER servername hopcount :U-flags-numeric serverdesc*/ static void m_server (char *origin, char **argv, int argc, int srv) { char* s = argv[argc-1]; if (*origin== 0) { /* server desc from uplink includes extra info so we need to strip protocol, flags and numeric. We can use the first space to do this*/ while(*s != ' ') s++; /* Strip the now leading space */ s++; } if(argc > 3) { do_server (argv[0], origin, argv[1], argv[2], s, srv); } else { do_server (argv[0], origin, argv[1], NULL, s, srv); } } /* m_squit * argv[0] = server name * argv[argc-1] = comment */ static void m_squit (char *origin, char **argv, int argc, int srv) { do_squit (argv[0], argv[1]); } /* m_quit * argv[0] = comment */ static void m_quit (char *origin, char **argv, int argc, int srv) { do_quit (origin, argv[0]); } /* m_svsmode * argv[0] - username to change mode for * argv[1] - modes to change * argv[2] - Service Stamp (if mode == d) */ static void m_svsmode (char *origin, char **argv, int argc, int srv) { if (argv[0][0] == '#') { do_svsmode_channel (origin, argv, argc); } else { do_svsmode_user (argv[0], argv[1], argv[2]); } } /* m_mode * argv[0] - channel * m_umode * argv[0] - username to change mode for * argv[1] - modes to change */ /* MODE * :nick MODE nick :+modestring * :servername MODE #channel +modes parameter list TS */ static void m_mode (char *origin, char **argv, int argc, int srv) { if (argv[0][0] == '#') { do_mode_channel (origin, argv, argc); } else { do_mode_user (argv[0], argv[1]); } } /* m_umode2 * argv[0] - modes to change */ static void m_umode2 (char *origin, char **argv, int argc, int srv) { do_mode_user (origin, argv[0]); } /* m_kill * argv[0] = kill victim(s) - comma separated list * argv[1] = kill path */ static void m_kill (char *origin, char **argv, int argc, int srv) { do_kill (argv[0], argv[1]); } static void m_vhost (char *origin, char **argv, int argc, int srv) { do_vhost (origin, argv[0]); } /* m_pong * argv[0] = origin * argv[1] = destination */ static void m_pong (char *origin, char **argv, int argc, int srv) { do_pong (argv[0], argv[1]); } /* m_away * argv[0] = away message */ static void m_away (char *origin, char **argv, int argc, int srv) { do_away (origin, (argc > 0) ? argv[0] : NULL); } /* m_nick * argv[0] = nickname * if from new client * argv[1] = nick password * if from server: * argv[1] = hopcount * argv[2] = timestamp * argv[3] = username * argv[4] = hostname * argv[5] = servername * if NICK version 1: * argv[6] = servicestamp * argv[7] = info * if NICK version 2: * argv[6] = servicestamp * argv[7] = umodes * argv[8] = virthost, * if none * argv[9] = info * if NICKIP * argv[9] = nickip * argv[10] = info */ static void m_nick (char *origin, char **argv, int argc, int srv) { char tmpbuf[25]; if(!srv) { #ifdef NICKV2 if (ircd_srv.nickip) { snprintf(tmpbuf, 25, "%d", ntohl (decode_ip(argv[9]))); do_nick (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], tmpbuf /* NICKIP */, argv[6], argv[7], argv[8], argv[10], NULL); } else { do_nick (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL, argv[6], argv[7], argv[8], argv[9], NULL); } #else do_nick (argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], NULL, argv[6], NULL, NULL, argv[9], NULL); #endif } else { do_nickchange (origin, argv[0], NULL); } } /* m_topic * argv[0] = topic text * For servers using TS: * argv[0] = channel name * argv[1] = topic nickname * argv[2] = topic time * argv[3] = topic text */ /* TOPIC #channel owner TS :topic */ static void m_topic (char *origin, char **argv, int argc, int srv) { do_topic (argv[0], argv[1], argv[2], argv[3]); } /* m_kick * argv[0] = channel * argv[1] = client to kick * argv[2] = kick comment */ static void m_kick (char *origin, char **argv, int argc, int srv) { do_kick (origin, argv[0], argv[1], argv[2]); } /* m_join * argv[0] = channel * argv[1] = channel password (key) */ static void m_join (char *origin, char **argv, int argc, int srv) { do_join (origin, argv[0], argv[1]); } /* m_part * argv[0] = channel * argv[1] = comment */ static void m_part (char *origin, char **argv, int argc, int srv) { do_part (origin, argv[0], argv[1]); } /* m_ping * argv[0] = origin * argv[1] = destination */ static void m_ping (char *origin, char **argv, int argc, int srv) { do_ping (argv[0], argv[1]); } /* m_netinfo * argv[0] = max global count * argv[1] = time of end sync * argv[2] = unreal protocol using (numeric) * argv[3] = cloak-crc (> u2302) * argv[4] = free(**) * argv[5] = free(**) * argv[6] = free(**) * argv[7] = ircnet */ static void m_netinfo (char *origin, char **argv, int argc, int srv) { do_netinfo(argv[0], argv[1], argv[2], argv[3], argv[7]); } #ifdef UNREAL32 /* EOS * :servername EOS */ static void m_eos (char *origin, char **argv, int argc, int srv) { do_eos (origin); } #endif /* m_sjoin * argv[0] = channel timestamp * char *argv[], pvar[MAXMODEPARAMS][MODEBUFLEN + 3]; * argv[1] = channel name * "ts chname :" * if (argc == 3) * argv[2] = nick names + modes - all in one parameter * "ts chname modebuf :" * "ts chname :"@/"""name" OPT_SJ3 * if (argc == 4) * argv[2] = channel modes * argv[3] = nick names + modes - all in one parameter * "ts chname modebuf parabuf :" * if (argc > 4) * argv[2] = channel modes * argv[3 to argc - 2] = mode parameters * argv[argc - 1] = nick names + modes * "ts parabuf :parv[parc - 1]" OPT_SJOIN | OPT_SJ3 */ /* MSG_SJOIN creationtime chname modebuf parabuf :member list */ /* R: ~ 1073861298 #services + :Mark */ static void m_sjoin (char *origin, char **argv, int argc, int srv) { do_sjoin (argv[0], argv[1], ((argc >= 4) ? argv[2] : ""), origin, argv, argc); } /* m_pass * argv[0] = password */ static void m_pass (char *origin, char **argv, int argc, int srv) { } /* m_svsnick * argv[0] = old nickname * argv[1] = new nickname * argv[2] = timestamp */ static void m_svsnick (char *origin, char **argv, int argc, int srv) { do_nickchange (argv[0], argv[1], argv[2]); } /* m_whois * argv[0] = nickname masklist */ static void m_whois (char *origin, char **argv, int argc, int srv) { /* TODO */ } /* m_swhois * argv[0] = nickname * argv[1] = new swhois */ static void m_swhois (char *origin, char **argv, int argc, int srv) { do_swhois (argv[0], argv[1]); } static void m_smo (char *origin, char **argv, int argc, int srv) { /* TODO */ } /* * argv[0] +|- * argv[1] G * argv[2] user * argv[3] host * argv[4] setby * argv[5] expire_at * argv[6] set_at * argv[7] reason R: :server BD + G * mask setter 1074811259 1074206459 :reason R: :server BD + Z * mask setter 0 1070062390 :reason R: :server c dos_bot* :Reserved nickname: Dosbot */ static void m_tkl (char *origin, char **argv, int argc, int srv) { do_tkl(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]); } static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ int b64_encode(unsigned char const *src, size_t srclength, char *target, size_t targsize) { size_t datalength = 0; u_char input[3]; u_char output[4]; size_t i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int b64_decode(char const *src, unsigned char *target, size_t targsize) { int tarindex, state, ch; char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isspace(ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); if (pos == 0) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] = (pos - Base64) << 2; } state = 1; break; case 1: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = ((pos - Base64) & 0x0f) << 4 ; } tarindex++; state = 2; break; case 2: if (target) { if ((size_t)tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = ((pos - Base64) & 0x03) << 6; } tarindex++; state = 3; break; case 3: if (target) { if ((size_t)tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; default: abort(); } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace(ch)) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for ((void)NULL; ch != '\0'; ch = *src++) if (!isspace(ch)) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } char *encode_ip(u_char *ip) { static char buf[25]; u_char *cp; struct in_addr ia; /* For IPv4 */ if (!ip) return "*"; if (strchr(ip, ':')) { return NULL; } else { ia.s_addr = inet_addr(ip); cp = (u_char *)ia.s_addr; b64_encode((char *)&cp, sizeof(struct in_addr), buf, 25); } return buf; } int decode_ip(char *buf) { int len = strlen(buf); char targ[25]; struct in_addr ia; b64_decode(buf, targ, 25); ia = *( struct in_addr *)targ; if (len == 24) /* IPv6 */ { return 0; } else if (len == 8) /* IPv4 */ return ia.s_addr; else /* Error?? */ return 0; }