]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/proto-p10.c
oops, broke unsetting the title. fix here
[irc/evilnet/x3.git] / src / proto-p10.c
index 61662bf5de9efe25776ed79f1c35b3e2a7c186d8..544aabae90506167146cd74c2fdbe3a89137dc0b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * This file is part of x3.
  *
- * srvx is free software; you can redistribute it and/or modify
+ * 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
  * (at your option) any later version.
@@ -20,7 +20,9 @@
 
 #include "nickserv.h"
 #include "chanserv.h"
+#include "hosthiding.h"
 #include "proto-common.c"
+#include "opserv.h"
 
 /* Full commands. */
 #define CMD_ACCOUNT            "ACCOUNT"
@@ -90,6 +92,7 @@
 #define CMD_SQUIT               "SQUIT"
 #define CMD_STATS               "STATS"
 #define CMD_SVSNICK             "SVSNICK"
+#define CMD_SWHOIS              "SWHOIS"
 #define CMD_TIME                "TIME"
 #define CMD_TOPIC               "TOPIC"
 #define CMD_TRACE               "TRACE"
 #define TOK_SQUIT               "SQ"
 #define TOK_STATS               "R"
 #define TOK_SVSNICK             "SN"
+#define TOK_SWHOIS              "SW"
 #define TOK_TIME                "TI"
 #define TOK_TOPIC               "T"
 #define TOK_TRACE               "TR"
 #define P10_SQUIT               TYPE(SQUIT)
 #define P10_STATS               TYPE(STATS)
 #define P10_SVSNICK             TYPE(SVSNICK)
+#define P10_SWHOIS              TYPE(SWHOIS)
 #define P10_TIME                TYPE(TIME)
 #define P10_TOPIC               TYPE(TOPIC)
 #define P10_TRACE               TYPE(TRACE)
@@ -376,6 +381,43 @@ privmsg_user_helper(struct userNode *un, void *data)
     }
 }
 
+/* equiv to user doing /connect server port target */
+void irc_connect(struct userNode *user, char *server, unsigned int port, struct server *target)
+{
+    putsock("%s " P10_CONNECT " %s %d %s", user->numeric, server, port, target->numeric);
+}
+
+void
+irc_squit_route(struct server *srv, const char *message, ...)
+{
+    va_list arg_list;
+    char buffer[MAXLEN];
+    va_start(arg_list, message);
+    vsnprintf(buffer, MAXLEN-2, message, arg_list);
+    buffer[MAXLEN-1] = 0;
+
+    /* When would we squit ourselves exactly?? -Rubin */
+    if(srv == self && cManager.uplink->state == CONNECTED ) {
+        unsigned int i;
+
+        /* Quit all clients linked to me. */
+        for(i = 0; i <= self->num_mask; i++) {
+            if(!self->users[i])
+                continue;
+            irc_quit(self->users[i], buffer);
+        }
+    }
+
+    putsock("%s " P10_SQUIT " %s %d :%s", self->numeric, srv->name, 0, buffer);
+
+    if(srv == self) {
+        /* Force a reconnect to the currently selected server. */
+        cManager.uplink->tries = 0;
+        log_module(MAIN_LOG, LOG_INFO, "Squitting from uplink: %s", buffer);
+        close_socket();
+    }
+}
+
 void
 irc_server(struct server *srv)
 {
@@ -594,6 +636,17 @@ irc_wallchops(struct userNode *from, const char *to, const char *message)
     putsock("%s " P10_WALLCHOPS " %s :%s", from->numeric, to, message);
 }
 
+void
+irc_wallops(const char *format, ...)
+{
+    va_list arg_list;
+    char buffer[MAXLEN];
+    va_start(arg_list, format);
+    vsnprintf(buffer, MAXLEN-2, format, arg_list);
+    buffer[MAXLEN-1] = 0;
+    putsock("%s " P10_WALLOPS " :%s", self->numeric, buffer);
+}
+
 void
 irc_notice(struct userNode *from, const char *to, const char *message)
 {
@@ -835,6 +888,7 @@ irc_kill(struct userNode *from, struct userNode *target, const char *message)
 void
 irc_mode(struct userNode *from, struct chanNode *target, const char *modes)
 {
+    call_channel_mode_funcs(from, target, (char **)&modes, 0);
     putsock("%s " P10_MODE " %s %s "FMT_TIME_T,
             (from ? from->numeric : self->numeric),
             target->name, modes, target->timestamp);
@@ -856,6 +910,12 @@ irc_invite(struct userNode *from, struct userNode *who, struct chanNode *to)
     putsock("%s " P10_INVITE " %s %s", from->numeric, who->nick, to->name);
 }
 
+void
+irc_silence(struct userNode *who, const char *mask, int add)
+{
+    putsock("%s " P10_SILENCE " %s %s%s", self->numeric, who->numeric, add ? "+" : "-", mask);
+}
+
 void
 irc_join(struct userNode *who, struct chanNode *what)
 {
@@ -889,6 +949,14 @@ irc_svsnick(struct userNode *from, struct userNode *target, const char *newnick)
     putsock("%s " P10_SVSNICK " %s %s "FMT_TIME_T, from->uplink->numeric, target->numeric, newnick, now);
 }
 
+void
+irc_swhois(struct userNode *from, struct userNode *target, const char *message)
+{
+    putsock("%s " P10_SWHOIS " %s %s%s", from->uplink->numeric, target->numeric, message ? ":" : "",
+                                         message ? message : "");
+
+}
+
 void
 irc_part(struct userNode *who, struct chanNode *what, const char *reason)
 {
@@ -902,13 +970,47 @@ irc_part(struct userNode *who, struct chanNode *what, const char *reason)
 void
 irc_topic(struct userNode *service, struct userNode *who, struct chanNode *what, const char *topic)
 {
-/* UNCOMMENT FOR NEFARIOUS 0.5.0 TOPIC SUPPORT
- *    putsock("%s " P10_TOPIC " %s %s " FMT_TIME_T " " FMT_TIME_T " :%s", service->numeric, what->name, who->nick, what->timestamp, now, topic);
- * UNCOMMENT FOR NEFARIOUS 0.5.0 TOPIC SUPPORT */
-
-    who = service; /* REMOVE LINE FOR NEFARIOUS 0.5.0 */
 
-    putsock("%s " P10_TOPIC " %s :%s", who->numeric, what->name, topic);
+   int type = 4;
+   int host_in_topic = 0;
+   const char *hstr, *tstr;
+   char *host, *hostmask;
+   char shost[MAXLEN];
+   char sident[MAXLEN];
+
+   tstr = conf_get_data("server/type", RECDB_QSTRING);
+   hstr = conf_get_data("server/host_in_topic", RECDB_QSTRING);
+   if(tstr)
+     type = atoi(tstr);
+   else
+     type = 4;/* default to 040 style topics */
+
+   if (hstr) {
+      if (IsFakeHost(who))
+          safestrncpy(shost, who->fakehost, sizeof(shost));
+      else if (IsSetHost(who)) {
+          hostmask = strdup(who->sethost);
+          if ((host = (strrchr(hostmask, '@'))))
+              *host++ = '\0';
+          else
+              host = hostmask;
+
+          safestrncpy(sident, hostmask, sizeof(shost));
+          safestrncpy(shost, host, sizeof(shost));
+      } else
+          safestrncpy(shost, who->hostname, sizeof(shost));
+
+      host_in_topic = atoi(hstr);
+   }
+
+   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);
+   } else {
+     who = service;
+     putsock("%s " P10_TOPIC " %s :%s", who->numeric, what->name, topic);
+   }
 }
 
 void
@@ -1030,6 +1132,7 @@ static CMD_FUNC(cmd_server)
     return 1;
 }
 
+
 static CMD_FUNC(cmd_eob)
 {
     struct server *sender;
@@ -1046,11 +1149,21 @@ static CMD_FUNC(cmd_eob)
         unbursted_channels = NULL;
         irc_eob();
         irc_eob_ack();
+
+        /* now that we know who our uplink is,
+         * we can center the routing map and activate auto-routing.
+         */
+        activate_routing(NULL, NULL, NULL);
     }
     sender->self_burst = 0;
     recalc_bursts(sender);
     for (ii=0; ii<slf_used; ii++)
         slf_list[ii](sender);
+    /* let auto-routing figure out if we were
+     * wating on this server to link a child to it */
+    /* DONT call this if uplink is _US_ */
+    if(sender->uplink != self)
+        routing_handle_connect(sender->name, sender->uplink->name);
     return 1;
 }
 
@@ -1605,6 +1718,49 @@ static CMD_FUNC(cmd_part)
     return 1;
 }
 
+static CMD_FUNC(cmd_silence)
+{
+    struct userNode *user;
+    char *mask;
+    char *new_mask;
+    unsigned int i;
+
+    if (argc < 2)
+        return 0;
+
+    user = GetUserN(argv[1]);
+
+    /* Sanity, go nuts if this happens */
+    if (!user)
+        return 0;
+
+    /*  We can safely ignore this if a user adding a silence is not
+     *  ignored. However this brings up a TODO. If a user logs in and
+     *  they have silences on the IRCd then we need to set them here
+     *  somehow
+     */
+    if (!user->handle_info)
+        return 1;
+
+    mask = argv[2];
+
+    if (*mask == '-') {
+        for (i=0; i<user->handle_info->ignores->used; i++) {
+            if (!irccasecmp(mask+1, user->handle_info->ignores->list[i]))
+                user->handle_info->ignores->list[i] = user->handle_info->ignores->list[--user->handle_info->ignores->used];
+        }
+    } else {
+        for (i=0; i<user->handle_info->ignores->used; i++) {
+            if (!strcmp(mask+1, user->handle_info->ignores->list[i]))
+                return 1; /* Already on the users NickServ ignore list, safely ignore */
+        }
+
+        new_mask = strdup(mask+1);
+        string_list_append(user->handle_info->ignores, new_mask);
+    }
+    return 1;
+}
+
 static CMD_FUNC(cmd_kick)
 {
     if (argc < 3)
@@ -1616,6 +1772,7 @@ static CMD_FUNC(cmd_kick)
 static CMD_FUNC(cmd_squit)
 {
     struct server *server;
+    char *uplink;
 
     if (argc < 4)
         return 0;
@@ -1630,7 +1787,13 @@ static CMD_FUNC(cmd_squit)
         return 1;
     }
 
+    uplink = strdup(server->uplink->name);
     DelServer(server, 0, argv[3]);
+    /* if its a pingout and pingout connecting is enabled
+               or its a read error and readerror connecting is enabled
+               or were doing a "N" and i need to connect that server somewhere */
+    routing_handle_squit(argv[1], uplink, argv[3]);
+    free(uplink);
     return 1;
 }
 
@@ -1651,14 +1814,46 @@ static CMD_FUNC(cmd_privmsg)
 static CMD_FUNC(cmd_notice)
 {
     struct privmsg_desc pd;
+    struct server *srv;
+    int nuser = 0;
+
     if (argc != 3)
         return 0;
+
     pd.user = GetUserH(origin);
-    if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user)))
-        return 1;
-    pd.is_notice = 1;
-    pd.text = argv[2];
-    parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd);
+    if(!pd.user)
+        nuser = 1;
+    if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user))) {
+    }
+    else {
+        pd.is_notice = 1;
+        pd.text = argv[2];
+        parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd);
+    }
+
+    srv = GetServerH(origin);
+    if(srv) {
+        char *sargv[MAXNUMPARAMS];
+        int sargc;
+
+        sargc = split_line(argv[2], true, MAXNUMPARAMS, sargv);
+
+        if(!strcasecmp(sargv[0], "Connect:")) {
+            /* :Connect: Host shoe.loxxin.net not listed in ircd.conf */
+            if(!strcasecmp(sargv[3], "not") && !strcasecmp(sargv[4], "listed")) {
+                routing_handle_connect_failure(srv, sargv[2], unsplit_string(sargv+3, sargc-3, NULL));
+            }
+        }
+        else if(!strcasecmp(sargv[0], "Link")) {
+            /* :Link with mephisto.etheria.cx cancelled: Server mephisto.etheria.cx[216.46.33.71]
+             *
+             * :Link with laptop.afternet.org cancelled: Connection refused
+             */
+            if(!strcasecmp(sargv[3], "cancelled:")) {
+                routing_handle_connect_failure(srv, sargv[2], unsplit_string(sargv+4, sargc-4, NULL));
+            }
+        }
+    }
     return 1;
 }
 
@@ -1839,8 +2034,8 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_TOPIC, cmd_topic);
     dict_insert(irc_func_dict, CMD_AWAY, cmd_away);
     dict_insert(irc_func_dict, TOK_AWAY, cmd_away);
-    dict_insert(irc_func_dict, CMD_SILENCE, cmd_dummy);
-    dict_insert(irc_func_dict, TOK_SILENCE, cmd_dummy);
+    dict_insert(irc_func_dict, CMD_SILENCE, cmd_silence);
+    dict_insert(irc_func_dict, TOK_SILENCE, cmd_silence);
     dict_insert(irc_func_dict, CMD_KICK, cmd_kick);
     dict_insert(irc_func_dict, TOK_KICK, cmd_kick);
     dict_insert(irc_func_dict, CMD_SQUIT, cmd_squit);
@@ -1853,6 +2048,8 @@ init_parse(void)
     dict_insert(irc_func_dict, TOK_STATS, cmd_stats);
     dict_insert(irc_func_dict, CMD_SVSNICK, cmd_svsnick);
     dict_insert(irc_func_dict, TOK_SVSNICK, cmd_svsnick);
+    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);
     dict_insert(irc_func_dict, TOK_WHOIS, cmd_whois);
     dict_insert(irc_func_dict, CMD_GLINE, cmd_gline);
@@ -1903,6 +2100,11 @@ init_parse(void)
     /* We have reliable clock!  Always!  Wraaa! */
     dict_insert(irc_func_dict, CMD_SETTIME, cmd_dummy);
     dict_insert(irc_func_dict, TOK_SETTIME, cmd_dummy);
+
+    /* 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);
+
     /* handle topics */
     dict_insert(irc_func_dict, "331", cmd_num_topic);
     dict_insert(irc_func_dict, "332", cmd_num_topic);
@@ -2256,6 +2458,14 @@ AddUser(struct server* uplink, const char *nick, const char *ident, const char *
     safestrncpy(uNode->hostname, hostname, sizeof(uNode->hostname));
     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);
+    }
+
     uNode->timestamp = timestamp;
     modeList_init(&uNode->channels);
     uNode->uplink = uplink;
@@ -2345,6 +2555,9 @@ void mod_usermode(struct userNode *user, const char *mode_change) {
 
     if (!user || !mode_change)
         return;
+
+    call_user_mode_funcs(user, mode_change);
+
     while (*word != ' ' && *word) word++;
     while (*word == ' ') word++;
     while (1) {