X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/d9d33535b1c4723eaad2f4a684706bfd4ba57641..6ff42e24fe8c562c92bff3a1ee1e17d606d69411:/src/proto-p10.c diff --git a/src/proto-p10.c b/src/proto-p10.c index e3fa69e..140e2d5 100644 --- a/src/proto-p10.c +++ b/src/proto-p10.c @@ -5,7 +5,7 @@ * * x3 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 + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -20,6 +20,8 @@ #include "nickserv.h" #include "chanserv.h" +#include "hash.h" +#include "helpfile.h" #include "hosthiding.h" #include "proto-common.c" #include "opserv.h" @@ -27,6 +29,7 @@ /* Full commands. */ #define CMD_ACCOUNT "ACCOUNT" #define CMD_ADMIN "ADMIN" +#define CMD_ALIST "ALIST" #define CMD_ASLL "ASLL" #define CMD_AWAY "AWAY" #define CMD_BURST "BURST" @@ -88,10 +91,14 @@ #define CMD_SETTIME "SETTIME" #define CMD_SHUN "SHUN" #define CMD_SILENCE "SILENCE" +#define CMD_SNO "SNO" #define CMD_SQUERY "SQUERY" #define CMD_SQUIT "SQUIT" #define CMD_STATS "STATS" +#define CMD_SVSJOIN "SVSJOIN" #define CMD_SVSNICK "SVSNICK" +#define CMD_SVSPART "SVSPART" +#define CMD_SVSQUIT "SVSQUIT" #define CMD_SWHOIS "SWHOIS" #define CMD_TIME "TIME" #define CMD_TOPIC "TOPIC" @@ -114,6 +121,7 @@ /* Tokenized commands. */ #define TOK_ACCOUNT "AC" #define TOK_ADMIN "AD" +#define TOK_ALIST "AL" #define TOK_ASLL "LL" #define TOK_AWAY "A" #define TOK_BURST "B" @@ -176,10 +184,14 @@ #define TOK_SETTIME "SE" #define TOK_SHUN "SU" #define TOK_SILENCE "U" +#define TOK_SNO "SNO" #define TOK_SQUERY "SQUERY" #define TOK_SQUIT "SQ" #define TOK_STATS "R" +#define TOK_SVSJOIN "SJ" #define TOK_SVSNICK "SN" +#define TOK_SVSPART "SP" +#define TOK_SVSQUIT "SX" #define TOK_SWHOIS "SW" #define TOK_TIME "TI" #define TOK_TOPIC "T" @@ -274,10 +286,14 @@ #define P10_SETTIME TYPE(SETTIME) #define P10_SHUN TYPE(SHUN) #define P10_SILENCE TYPE(SILENCE) +#define P10_SNO TYPE(SNO) #define P10_SQUERY TYPE(SQUERY) #define P10_SQUIT TYPE(SQUIT) #define P10_STATS TYPE(STATS) +#define P10_SVSJOIN TYPE(SVSJOIN) #define P10_SVSNICK TYPE(SVSNICK) +#define P10_SVSPART TYPE(SVSPART) +#define P10_SVSQUIT TYPE(SVSQUIT) #define P10_SWHOIS TYPE(SWHOIS) #define P10_TIME TYPE(TIME) #define P10_TOPIC TYPE(TOPIC) @@ -303,6 +319,8 @@ */ #define PREHISTORY 780000000 +#define MODELEN 40 + KEYLEN + static struct server *servers_num[64*64]; static privmsg_func_t *privmsg_funcs; static unsigned int num_privmsg_funcs; @@ -316,9 +334,14 @@ static int extended_accounts; static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, time_t timestamp, const char *realip); extern int off_channel; +extern int DefConLevel; +extern int DefConTimeOut; +extern char *DefConChanModes; static int parse_oplevel(char *str); +char privbuf[512] = ""; + /* Numerics can be XYY, XYYY, or XXYYY; with X's identifying the * server and Y's indentifying the client on that server. */ struct server* @@ -365,6 +388,32 @@ GetUserN(const char *numeric) /* using numeric */ return un; } +extern struct userNode *opserv; +static void +check_ctcp(struct userNode *user, struct userNode *bot, char *text, UNUSED_ARG(int server_qualified)) +{ + char *cmd; + /* if its a version reply, do an alert check (only alerts with version=something) */ + if(bot == opserv) { + if(text[0] == '\001') { + text++; + cmd = mysep(&text, " "); + if(!irccasecmp(cmd, "VERSION")) { + char *version = mysep(&text, "\n"); + if(!version) + version = ""; + /* opserv_debug("Opserv got CTCP VERSION Notice from %s: %s", user->nick, version); */ + /* TODO: setup a ctcp_funcs thing to handle this and other CTCPS properly */ + user->version_reply = strdup(version); + /* TODO: put this in the db */ + if(match_ircglob(version, "WebTV;*")) + user->no_notice = true; /* webbies cant see notices */ + } + } + } +} + + static void privmsg_user_helper(struct userNode *un, void *data) { @@ -376,6 +425,7 @@ privmsg_user_helper(struct userNode *un, void *data) } } else { if ((num < num_notice_funcs) && notice_funcs[num]) { + check_ctcp(pd->user, un, pd->text, pd->is_qualified); notice_funcs[num](pd->user, un, pd->text, pd->is_qualified); } } @@ -433,7 +483,7 @@ irc_server(struct server *srv) } } -static void +void irc_p10_pton(irc_in_addr_t *ip, const char *input) { if (strlen(input) == 6) { @@ -460,7 +510,7 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input) } } -static void +void irc_p10_ntop(char *output, const irc_in_addr_t *ip) { if (!irc_in_addr_is_valid(*ip)) { @@ -542,6 +592,15 @@ irc_user(struct userNode *user) modes[modelen++] = 'f'; if (IsHiddenHost(user)) modes[modelen++] = 'x'; + if (IsBotM(user)) + modes[modelen++] = 'B'; + if (IsHideChans(user)) + modes[modelen++] = 'n'; + if (IsHideIdle(user)) + modes[modelen++] = 'I'; + if (IsXtraOp(user)) + modes[modelen++] = 'X'; + modes[modelen] = 0; /* we don't need to put the + in modes because it's in the format string. */ @@ -647,6 +706,7 @@ irc_wallops(const char *format, ...) putsock("%s " P10_WALLOPS " :%s", self->numeric, buffer); } + void irc_notice(struct userNode *from, const char *to, const char *message) { @@ -665,6 +725,18 @@ irc_privmsg(struct userNode *from, const char *to, const char *message) putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to, message); } +void +irc_privmsg_user(struct userNode *from, struct userNode *to, const char *message) +{ + putsock("%s " P10_PRIVMSG " %s :%s", from->numeric, to->numeric, message); +} + +void +irc_version_user(struct userNode *from, struct userNode *to) +{ + irc_privmsg_user(from, to, "\001VERSION\001"); +} + void irc_eob(void) { @@ -675,6 +747,24 @@ void irc_eob_ack(void) { putsock("%s " P10_EOB_ACK, self->numeric); + + char *nick; + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + nick = strdup(str); + + if (nick && (DefConLevel < 5)) { + DefConProcess(GetUserH(nick)); + + if (DefConTimeOut > 0) + timeq_add(now + DefConTimeOut, defcon_timeout, NULL); + } +} + +void +irc_rpong(const char *from1, const char *from2, const char *pingtime, const char *clientinfo) +{ + putsock("%s " P10_RPONG " %s %s %s :%s", self->numeric, from1, from2, pingtime, clientinfo); } void @@ -725,8 +815,8 @@ irc_introduce(const char *passwd) void irc_gline(struct server *srv, struct gline *gline, int silent) { - putsock("%s " P10_GLINE " %s +%s %ld :%s<%s> %s", - self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, silent ? "AUTO " : "", gline->issuer, gline->reason); + putsock("%s " P10_GLINE " %s +%s %ld %ld :%s<%s> %s", + self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, now, silent ? "AUTO " : "", gline->issuer, gline->reason); } void @@ -786,6 +876,7 @@ irc_burst(struct chanNode *chan) pos = base_len; last_mode = -1; } + memcpy(burst_line+pos, mn->user->numeric, strlen(mn->user->numeric)); pos += strlen(mn->user->numeric); if (mn->modes && (mn->modes != last_mode)) { @@ -929,6 +1020,24 @@ irc_join(struct userNode *who, struct chanNode *what) } } +void +irc_svsjoin(struct userNode *from, struct userNode *who, struct chanNode *to) +{ + putsock("%s " P10_SVSJOIN " %s %s "FMT_TIME_T, from->uplink->numeric, who->numeric, to->name, now); +} + +void +irc_svspart(struct userNode *from, struct userNode *who, struct chanNode *to) +{ + putsock("%s " P10_SVSPART " %s %s", from->uplink->numeric, who->numeric, to->name); +} + +void +irc_svsquit(struct userNode *from, struct userNode *who, char *reason) +{ + putsock("%s " P10_SVSQUIT " %s :%s", from->uplink->numeric, who->numeric, reason); +} + void irc_kick(struct userNode *who, struct userNode *target, struct chanNode *channel, const char *msg) { @@ -1005,7 +1114,7 @@ irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, host_in_topic = atoi(hstr); } - if (type == 5) { + if (type >= 5) { putsock("%s " P10_TOPIC " %s %s%s%s%s%s " FMT_TIME_T " " FMT_TIME_T " :%s", service->numeric, what->name, who->nick, host_in_topic ? "!" : "", host_in_topic ? (IsSetHost(who) ? sident : who->ident) : "", host_in_topic ? "@" : "", host_in_topic ? shost : "", what->timestamp, now, topic); @@ -1032,6 +1141,48 @@ irc_numeric(struct userNode *user, unsigned int num, const char *format, ...) putsock(":%s %03d %s %s", self->name, num, user->nick, buffer); } +void +irc_mark(struct userNode *user, char *mark) +{ + char *host = user->hostname; + + /* TODO: Allow mark overwrite. If they are marked, and their fakehost is oldmark.hostname, update it to newmark.hostname so mark can be called multiple times. Probably requires ircd modification also */ + if(user->mark) + return; + + /* if the mark will put us over the host length, clip some off the left hand side + * to make room... + */ + if(strlen(host) + 1 + strlen(mark) > HOSTLEN) + host += 1 + ( (strlen(host) + 1 + strlen(mark)) - HOSTLEN ); + putsock("%s " CMD_MARK " %s DNSBL +m %s.%s", self->numeric, user->nick, mark, host); + putsock("%s " CMD_MARK " %s DNSBL_DATA %s", self->numeric, user->nick, mark); + + /* Save it in the user */ + user->mark = strdup(mark); + + /* If they are not otherwise marked, mark their host with fakehost */ + if(!IsFakeHost(user) && !IsSetHost(user) && !(IsHiddenHost(user) && user->handle_info) ) + { + struct modeNode *mn = NULL; + char fakehost[HOSTLEN]; + unsigned int count = 0; + unsigned int n = 0; + + putsock("%s " CMD_FAKEHOST " %s %s.%s", self->numeric, user->numeric, mark, host); + putsock("%s " CMD_MODE " %s +x", self->numeric, user->nick); + + snprintf(fakehost, sizeof(fakehost), "%s.%s", mark, host); + safestrncpy(user->fakehost, fakehost, sizeof(user->fakehost)); + + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + if (strlen(mn->channel->name) >= 1) /* Sanity */ + check_bans(user, mn->channel->name); + } + } +} + static void send_burst(void); static void @@ -1155,7 +1306,8 @@ static CMD_FUNC(cmd_eob) /* now that we know who our uplink is, * we can center the routing map and activate auto-routing. */ - activate_routing(NULL, NULL, NULL); + //activate_routing(NULL, NULL, NULL); + routing_init(); } sender->self_burst = 0; recalc_bursts(sender); @@ -1181,6 +1333,19 @@ static CMD_FUNC(cmd_eob_ack) return 1; } +static CMD_FUNC(cmd_rping) +{ + struct server *dest; + + if (!(dest = GetServerN(argv[1]))) + return 1; /* if its a jupe or something, return 1 so its silently ignored */ + + if (dest == self) + irc_rpong(argv[2], argv[3], argv[4], argv[5]); + + return 1; +} + static CMD_FUNC(cmd_ping) { struct server *srv; @@ -1265,6 +1430,22 @@ static CMD_FUNC(cmd_join) return 1; } +static CMD_FUNC(cmd_svsjoin) +{ + struct create_desc cd; + + if (!(cd.user = GetUserH(argv[1]))) + return 0; + if (argc < 3) + return 0; + else if (argc < 4) + cd.when = now; + else + cd.when = atoi(argv[3]); + parse_foreach(argv[2], join_helper, create_helper, NULL, NULL, &cd); + return 1; +} + static CMD_FUNC(cmd_pong) { if (argc < 3) @@ -1288,6 +1469,7 @@ static CMD_FUNC(cmd_nick) NickChange(user, argv[1], 1); } else { struct server *serv; + struct userNode *nuser; char modes[MAXLEN]; /* new nick */ if (argc < 9) @@ -1297,7 +1479,7 @@ static CMD_FUNC(cmd_nick) unsplit_string(argv+6, argc-9, modes); else strcpy(modes, "+"); - AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); + nuser = AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]); } return 1; } @@ -1321,7 +1503,22 @@ static CMD_FUNC(cmd_account) if(!strcmp(argv[2],"C")) { - if((hi = loc_auth(argv[4], argv[5]))) + if((hi = loc_auth(argv[4], argv[5], NULL))) + { + /* Return a AC A */ + putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered); + + } + else + { + /* Return a AC D */ + putsock("%s " P10_ACCOUNT " %s D %s", self->numeric, server->numeric , argv[3]); + } + return 1; + } + else if(!strcmp(argv[2],"H")) /* New enhanced (host) version of C */ + { + if((hi = loc_auth(argv[5], argv[6], argv[4] ))) { /* Return a AC A */ putsock("%s " P10_ACCOUNT " %s A %s %lu", self->numeric, server->numeric , argv[3], hi->registered); @@ -1353,6 +1550,119 @@ static CMD_FUNC(cmd_fakehost) return 1; } +static struct { + char *name; + unsigned int priv; +} privtab[] = { +#define P(priv) { #priv, PRIV_ ## priv } + P(CHAN_LIMIT), P(MODE_LCHAN), P(WALK_LCHAN), P(DEOP_LCHAN), + P(SHOW_INVIS), P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL), + P(LOCAL_KILL), P(REHASH), P(RESTART), P(DIE), + P(GLINE), P(LOCAL_GLINE), P(JUPE), P(LOCAL_JUPE), + P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX), + P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), + P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(FORCE_OPMODE), + P(FORCE_LOCAL_OPMODE), P(REMOTEREHASH), P(CHECK), P(SEE_SECRET_CHAN), + P(SHUN), P(LOCAL_SHUN), P(WIDE_SHUN), P(ZLINE), + P(LOCAL_ZLINE), P(WIDE_ZLINE), P(LIST_CHAN), +#undef P + { 0, 0 } +}; + +char *client_report_privs(struct userNode *client) +{ + int i; + + privbuf[0] = '\0'; + for (i = 0; privtab[i].name; i++) { + if (HasPriv(client, privtab[i].priv)) { + strcat(privbuf, privtab[i].name); + strcat(privbuf, " "); + } + } + + privbuf[strlen(privbuf)] = 0; + + return privbuf; +} + +int client_modify_priv_by_name(struct userNode *who, char *priv, int what) { + int i = 0; + assert(0 != priv); + assert(0 != who); + + for (i = 0; privtab[i].name; i++) { + if (0 == strcmp(privtab[i].name, priv)) { + if (what == PRIV_ADD) + GrantPriv(who, privtab[i].priv); + else if (what == PRIV_DEL) { + RevokePriv(who, privtab[i].priv); + } + } + } + return 0; +} + +int check_priv(char *priv) +{ + int i; + + for (i = 0; privtab[i].name; i++) { + if (0 == strcmp(privtab[i].name, priv)) { + return 1; + } + } + return 0; +} + +void +irc_privs(struct userNode *target, char *flag, int add) +{ + client_modify_priv_by_name(target, flag, add); + putsock("%s " P10_PRIVS " %s %s%s", self->numeric, target->numeric, (add == PRIV_ADD) ? "+" : "-", flag); +} + +static CMD_FUNC(cmd_privs) +{ + char *tstr = NULL; + int type = 0; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) + type = atoi(tstr); + + if (type < 6) + return 1; /* silently ignore */ + + struct userNode *user = argc > 1 ? GetUserN(argv[1]) : NULL; + char buf[512] = ""; + int what = PRIV_ADD; + char *p = 0; + char *tmp; + unsigned int i; + + if (argc < 3) + return 0; + + if (!user) + return 0; + + for (i=1; ichannel_info; + + if (!cData) { + if (cNode->modes & MODE_REGISTERED) { + irc_join(opserv, cNode); + irc_mode(opserv, cNode, "-z"); + irc_part(opserv, cNode, ""); + } + } /* Burst channel members in now. */ for (user = members, sep = *members, mode = 0; sep; user = end) { @@ -1486,6 +1806,57 @@ static CMD_FUNC(cmd_burst) return res; } +/* TODO: + * This is a stub that doesn't actually do anything. It should be completed + * so that bans on *!*@markname.* match users as it does in nefarious + */ +static CMD_FUNC(cmd_mark) +{ + struct userNode *target; + /* + * log_module(MAIN_LOG, LOG_ERROR, "DEBUG: mark, user %s, type %s, arg %s", argv[1], argv[2], argv[3]); + */ + + if(argc < 4) + return 0; + if(!strcasecmp(argv[2], "DNSBL")) { + /* DNSBL */ + return 1; + } + else if(!strcasecmp(argv[2], "DNSBL_DATA")) { + /* DNSBL_DATA name */ + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose dnsbl mark is changing.", argv[1]); + return 0; + } + target->mark = strdup(argv[3]); + return 1; + + } + else if(!strcasecmp(argv[2], "CVERSION")) { + /* DNSBL_DATA name */ + target = GetUserH(argv[1]); + if(!target) { + log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s whose version mark is changing.", argv[1]); + return 0; + } + + char *version = unsplit_string(argv + 3, argc - 3, NULL); + if(!version) + version = ""; + + target->version_reply = strdup(version); + + if(match_ircglob(version, "WebTV;*")) + target->no_notice = true; /* webbies cant see notices */ + + return 1; + } + /* unknown type of mark */ + return 1; +} + static CMD_FUNC(cmd_mode) { struct chanNode *cn; @@ -1531,6 +1902,22 @@ static CMD_FUNC(cmd_mode) cn->timestamp = atoi(argv[argc-1]); } + if (checkDefCon(DEFCON_NO_MODE_CHANGE) && !IsOper(un)) { + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + if (str) { + char modes[MODELEN]; + struct userNode *opserv = GetUserH(str); + + send_message_type(4, un, opserv, "Channel modes cannot be changed due to DefCon level %d in effect, please try again soon", DefConLevel); + irc_make_chanmode(cn, modes); + irc_mode(opserv, cn, modes); + irc_mode(opserv, cn, DefConChanModes); + } + return 1; + } + + return mod_chanmode(un, cn, argv+2, argc-2, MCP_ALLOW_OVB|MCP_FROM_SERVER|(un ? MC_NOTIFY : 0)); } @@ -1720,6 +2107,19 @@ static CMD_FUNC(cmd_part) return 1; } +static CMD_FUNC(cmd_svspart) +{ + struct userNode *user; + + if (argc < 3) + return 0; + user = GetUserN(argv[1]); + if (!user) + return 0; + parse_foreach(argv[2], part_helper, NULL, NULL, NULL, user); + return 1; +} + static CMD_FUNC(cmd_silence) { struct userNode *user; @@ -1807,9 +2207,22 @@ static CMD_FUNC(cmd_privmsg) pd.user = GetUserH(origin); if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) return 1; + + if (checkDefCon(DEFCON_OPER_ONLY) && !IsOper(pd.user)) { + const char *str; + str = conf_get_data("services/opserv/nick", RECDB_QSTRING); + if (str) + send_message_type(4, pd.user, GetUserH(str), "Services are currently not available, please try again soon"); + return 1; + } + + if (checkDefCon(DEFCON_SILENT_OPER_ONLY) && !IsOper(pd.user)) + return 1; /* Silently Ignore */ + pd.is_notice = 0; pd.text = argv[2]; parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd); + return 1; } @@ -2008,6 +2421,8 @@ init_parse(void) dict_insert(irc_func_dict, TOK_EOB_ACK, cmd_eob_ack); dict_insert(irc_func_dict, CMD_MODE, cmd_mode); dict_insert(irc_func_dict, TOK_MODE, cmd_mode); + dict_insert(irc_func_dict, CMD_MARK, cmd_mark); + dict_insert(irc_func_dict, TOK_MARK, cmd_mark); dict_insert(irc_func_dict, CMD_NICK, cmd_nick); dict_insert(irc_func_dict, TOK_NICK, cmd_nick); dict_insert(irc_func_dict, CMD_ACCOUNT, cmd_account); @@ -2048,8 +2463,12 @@ init_parse(void) dict_insert(irc_func_dict, TOK_NOTICE, cmd_notice); dict_insert(irc_func_dict, CMD_STATS, cmd_stats); dict_insert(irc_func_dict, TOK_STATS, cmd_stats); + dict_insert(irc_func_dict, CMD_SVSJOIN, cmd_svsjoin); + dict_insert(irc_func_dict, TOK_SVSJOIN, cmd_svsjoin); dict_insert(irc_func_dict, CMD_SVSNICK, cmd_svsnick); dict_insert(irc_func_dict, TOK_SVSNICK, cmd_svsnick); + dict_insert(irc_func_dict, CMD_SVSPART, cmd_svspart); + dict_insert(irc_func_dict, TOK_SVSPART, cmd_svspart); dict_insert(irc_func_dict, CMD_SWHOIS, cmd_dummy); dict_insert(irc_func_dict, TOK_SWHOIS, cmd_dummy); dict_insert(irc_func_dict, CMD_WHOIS, cmd_whois); @@ -2066,6 +2485,13 @@ init_parse(void) dict_insert(irc_func_dict, TOK_VERSION, cmd_version); dict_insert(irc_func_dict, CMD_ADMIN, cmd_admin); dict_insert(irc_func_dict, TOK_ADMIN, cmd_admin); + dict_insert(irc_func_dict, CMD_SNO, cmd_dummy); + dict_insert(irc_func_dict, TOK_SNO, cmd_dummy); + + dict_insert(irc_func_dict, CMD_RPING, cmd_rping); + dict_insert(irc_func_dict, TOK_RPING, cmd_rping); + dict_insert(irc_func_dict, CMD_RPONG, cmd_dummy); + dict_insert(irc_func_dict, TOK_RPONG, cmd_dummy); /* In P10, DESTRUCT doesn't do anything except be broadcast to servers. * Apparently to obliterate channels from any servers that think they @@ -2094,9 +2520,11 @@ init_parse(void) dict_insert(irc_func_dict, TOK_WALLUSERS, cmd_dummy); /* Ignore dnsbl exemptions */ dict_insert(irc_func_dict, TOK_EXEMPT, cmd_dummy); - dict_insert(irc_func_dict, TOK_MARK, cmd_dummy); - /* Ignore privs */ - dict_insert(irc_func_dict, TOK_PRIVS, cmd_dummy); + dict_insert(irc_func_dict, CMD_PRIVS, cmd_privs); + dict_insert(irc_func_dict, TOK_PRIVS, cmd_privs); + /* ignore ALIST for now */ + dict_insert(irc_func_dict, TOK_ALIST, cmd_dummy); + dict_insert(irc_func_dict, CMD_ALIST, cmd_dummy); /* Ignore remote luser */ dict_insert(irc_func_dict, TOK_LUSERS, cmd_dummy); /* We have reliable clock! Always! Wraaa! */ @@ -2106,6 +2534,7 @@ init_parse(void) /* ignore /trace and /motd commands targetted at us */ dict_insert(irc_func_dict, TOK_TRACE, cmd_dummy); dict_insert(irc_func_dict, TOK_MOTD, cmd_dummy); + dict_insert(irc_func_dict, TOK_UPING, cmd_dummy); /* handle topics */ dict_insert(irc_func_dict, "331", cmd_num_topic); @@ -2140,6 +2569,7 @@ init_parse(void) userList_init(&dead_users); reg_del_channel_func(remove_unbursted_channel); reg_exit_func(parse_cleanup); + // reg_notice_func(opserv, check_ctcp); } int @@ -2413,6 +2843,8 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * { struct userNode *oldUser, *uNode; unsigned int n, ignore_user; + char *tstr; + int type; if ((strlen(numeric) < 3) || (strlen(numeric) > 5)) { log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): numeric %s wrong length!", uplink, nick, numeric); @@ -2461,13 +2893,20 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * safestrncpy(uNode->numeric, numeric, sizeof(uNode->numeric)); irc_p10_pton(&uNode->ip, realip); - if (irc_in_addr_is_ipv4(uNode->ip)) { - make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip); - make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); - } else if (irc_in_addr_is_ipv6(uNode->ip)) { - make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + tstr = conf_get_data("server/type", RECDB_QSTRING); + type = atoi(tstr); + if (type > 6) { + if (irc_in_addr_is_ipv4(uNode->ip)) { + make_virtip((char*)irc_ntoa(&uNode->ip), (char*)irc_ntoa(&uNode->ip), uNode->cryptip); + make_virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + } else if (irc_in_addr_is_ipv6(uNode->ip)) { + make_ipv6virthost((char*)irc_ntoa(&uNode->ip), uNode->hostname, uNode->crypthost); + } } + if (!uNode->crypthost && uNode->cryptip) + snprintf(uNode->crypthost, sizeof(uNode->crypthost), "%s", strdup(uNode->cryptip)); + uNode->timestamp = timestamp; modeList_init(&uNode->channels); uNode->uplink = uplink; @@ -2477,6 +2916,9 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char * uNode->num_local = base64toint(numeric+strlen(uNode->uplink->numeric), 3) & uNode->uplink->num_mask; uNode->uplink->users[uNode->num_local] = uNode; mod_usermode(uNode, modes); + + set_geoip_info(uNode); + if (ignore_user) return uNode; @@ -2539,6 +2981,25 @@ DelUser(struct userNode* user, struct userNode *killer, int announce, const char } modeList_clean(&user->channels); + + /* Clean up version data */ + if(user->version_reply) { + free(user->version_reply); + user->version_reply = NULL; + } + + /* clean up mark */ + if(user->mark) { + free(user->mark); + user->mark = NULL; + } + + /* clean up geoip data if any */ + if(user->country_code) free(user->country_code); + if(user->city) free(user->city); + if(user->region) free(user->region); + if(user->postal_code) free(user->postal_code); + /* We don't free them, in case we try to privmsg them or something * (like when a stupid oper kills themself). We just put them onto * a list of clients that get freed after processing each line. @@ -2591,6 +3052,34 @@ void mod_usermode(struct userNode *user, const char *mode_change) { case 'd': do_user_mode(FLAGS_DEAF); break; case 'k': do_user_mode(FLAGS_SERVICE); break; case 'g': do_user_mode(FLAGS_GLOBAL); break; + case 'B': do_user_mode(FLAGS_BOT); break; + case 'n': do_user_mode(FLAGS_HIDECHANS); break; + case 'I': do_user_mode(FLAGS_HIDEIDLE); break; + case 'X': do_user_mode(FLAGS_XTRAOP); break; + case 'C': do_user_mode(FLAGS_CLOAKHOST); + if (*word) { + char cloakhost[MAXLEN]; + unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) + cloakhost[ii++] = *word++; + cloakhost[ii] = 0; + while (*word == ' ') + word++; + safestrncpy(user->crypthost, cloakhost, sizeof(user->crypthost)); + } + break; + case 'c': do_user_mode(FLAGS_CLOAKIP); + if (*word) { + char cloakip[MAXLEN]; + unsigned int ii; + for (ii=0; (*word != ' ') && (*word != '\0'); ) + cloakip[ii++] = *word++; + cloakip[ii] = 0; + while (*word == ' ') + word++; + safestrncpy(user->cryptip, cloakip, sizeof(user->cryptip)); + } + break; // sethost - reed/apples // case 'h': do_user_mode(FLAGS_HELPER); break; // I check if there's an 'h' in the first part, and if there,