]> jfr.im git - irc/quakenet/newserv.git/blobdiff - miscreply/trace.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / miscreply / trace.c
index 48489d7651e57e87e328d9e224e8c3ed71b03970..81f675a730f5b08fd7354fa69d22943e0da97eb1 100644 (file)
@@ -1,22 +1,65 @@
 /* trace.c */
 
 #include "miscreply.h"
-#include "numeric.h"
 #include "../core/error.h"
 #include "../irc/irc.h"
 #include "../lib/irc_string.h"
-#include "../nick/nick.h"
 #include "../server/server.h"
 
 #include <string.h>
 
 
 
-/* TODO: make server module keep state of link TS ? */
-/* TODO: make trace_server and trace_user function */
-/* TODO: trace link,
- * loop back from target server til we find ourself, send trace links along the way
+/* trace_user
+ *
  */
+static void trace_user(char *sourcenum, nick *tnick) {
+  if (IsOper(tnick)) {
+    /*
+     * 204 RPL_TRACEOPERATOR "source 204 target Oper class nick[user@IP] last_parse"
+     *                       "irc.netsplit.net 204 foobar Oper barfoo[fish@127.0.0.1] 0"
+     *
+     *  note: no info available on how long ago we last parsed something from this user -> 0 (not idle time)
+     */
+    irc_send("%s 204 %s Oper opers %s[%s@%s] 0", getmynumeric(), sourcenum, tnick->nick,
+      tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
+  } else {
+    /*
+     * 205 RPL_TRACEUSER "source 205 target User class nick[user@IP] last_parse"
+     *                   "irc.netsplit.net 205 foobar User barfoo[fish@127.0.0.1] 0"
+     */
+    irc_send("%s 205 %s User users %s[%s@%s] 0", getmynumeric(), sourcenum, tnick->nick,
+      tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
+  }
+}
+
+
+
+/* trace_server
+ *   return number of matched servers
+ */
+static int trace_server(char *sourcenum, char *target, int doall) {
+
+  /* do not show all and no match for my hub */
+  if (!doall && !match2strings(target, serverlist[myhub].name->content))
+    return 0;
+
+  /*
+   * 206 RPL_TRACESERVER "source 206 target Serv class NS NC server connected_by last_parse connected_for"
+   *                     "irc.netsplit.net 206 foobar Server 2S 6C irc.netsplit.net *!user@host 34 92988"
+   *
+   *  note: no info available on how many servers or clients are linked through this server link -> 0S 0C
+   *        no info available on who/what established the link, pretend it is by us -> *!*@myservername
+   *        no info available on how long ago we last parsed something from this link -> 0
+   *        no info available on how long this server has been linked -> 0
+   */
+  irc_send("%s 206 %s Serv servers 0S 0C %s *!*@%s 0 0", getmynumeric(), sourcenum,
+    serverlist[myhub].name->content, myserver->content);
+
+  return 1;
+}
+
+
 
 /* handle remote trace request
  *
  */
 int handletracemsg(void *source, int cargc, char **cargv) {
 
-  nick *snick;                           /* struct nick for source nick */
-  nick *tnick;                           /* struct nick for target nick */
-  nick **lnick;                          /* struct nick for looping local users */
+  nick *snick;                        /* struct nick for source nick */
+  nick *tnick;                        /* struct nick for target nick */
+  nick **lnick;                       /* struct nick for looping local users */
+  int c;                              /* loop variable */
+  int opers = 0;                      /* number of operators */
+  int users = 0;                      /* number of users */
+  int servers = 0;                    /* number of servers */
+  int doall, wilds, dow;              /* determine what to show */
+  char *sourcenum = (char *)source;   /* source user numeric */
+  char *target;                       /* target parameter - as given by the source user */
 
-  int i;                                 /* index for serverlist[] */
-  int showall = 0;                       /* show all local server links */
-  int opers = 0;                         /* number of opers */
-  int users = 0;                         /* number of users */
-  int servers = 0;                       /* number of servers */
-  char *sourcenum = (char *)source;      /* source user numeric */
-  char *targetnum = getmynumeric();      /* target server numeric */
-  char *target;                          /* target parameter - as given by the source user */
-  char *servernum;                       /* destination server numeric parameter */
 
   /* check parameters */
   if (cargc < 2) {
@@ -51,126 +92,78 @@ int handletracemsg(void *source, int cargc, char **cargv) {
 
   /* get the parameters */
   target = cargv[0];
-  servernum = cargv[1];
-
-  /* from a server? */
-  if (IsServer(sourcenum))
-    return CMD_OK;
 
   /* find source user */ 
   if (!(snick = miscreply_finduser(sourcenum, "TRACE")))
     return CMD_OK;
 
-  /* TODO: trace here down to target server first? */
-
-  /* for me */
-  if (IsMeNum(servernum)) {
-
-    /* find target user */
-    if ((tnick = getnickbynick(target))) {
-
-      /* my user? */
-      if (MyUser(tnick)) {
-        if (IsOper(tnick)) {
-          /*
-           * 204 RPL_TRACEOPERATOR "source 204 target Oper class nick[user@IP] last_parse"
-           *                       "irc.netsplit.net 204 foobar Oper barfoo[fish@127.0.0.1] 0"
-           *
-           *  note: no info available on how long ago we last parsed something from this user -> 0 (not idle time)
-           */
-          send_reply(targetnum, RPL_TRACEOPERATOR, sourcenum, "Oper opers %s[%s@%s] 0", tnick->nick,
-            tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->p_ipaddr));
-        } else {
-          /*
-           * 205 RPL_TRACEUSER "source 205 target User class nick[user@IP] last_parse"
-           *                   "irc.netsplit.net 205 foobar User barfoo[fish@127.0.0.1] 0"
-           */
-          send_reply(targetnum, RPL_TRACEUSER, sourcenum, "User users %s[%s@%s] 0", tnick->nick,
-            tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->p_ipaddr));
-        }
-      }
-    }
-    else {
+  /* doall, wilds, dow */
+  doall = match2strings(target, myserver->content);
+  wilds = strchr(target, '*') || strchr(target, '?');
+  dow = wilds || doall;
 
-      /* target is my server,
-       *   show all local server links
-       */
-      if (match2strings(target, myserver->content))
-        showall = 1;
 
-      /* go over all servers */
-      for (i = 0; i < MAXSERVERS; i++) {
-        if (serverlist[i].maxusernum == 0)   /* not linked */
+  /* find target user */
+  if ((tnick = getnickbynick(target))) {
+
+    /* my user */
+    if (mylongnum == homeserver(tnick->numeric))
+      trace_user(sourcenum, tnick);
+  }
+
+
+  /* source user is an operator */
+  else if (IsOper(snick)) {
+
+    /* show servers */
+    servers = trace_server(sourcenum, target, doall);
+
+    /* do all or wilds */
+    if (dow) {
+
+      /* loop over all local users */
+      lnick = servernicks[mylongnum];
+      for (c = 0; c < serverlist[mylongnum].maxusernum; c++) {
+
+        if (lnick[c] == NULL)   /* no user */
           continue;
-        if (!IsMeLong(serverlist[i].parent) && i != myhub)   /* not my server and not my hub */
+
+        /* target is invisible (mode +i), target is not an operator */
+        if (IsInvisible(lnick[c]) && dow && !IsOper(lnick[c]))
           continue;
-        servers++;
-        if (!showall && !match2strings(target, serverlist[i].name->content))   /* do not show all and no match */
+
+        /* dont show all, do wildcards and no match */
+        if (!doall && wilds && !match2strings(target, lnick[c]->nick))
           continue;
-        /*
-         * 206 RPL_TRACESERVER "source 206 target Serv class NS NC server connected_by last_parse connected_for"
-         *                     "irc.netsplit.net 206 foobar Server 2S 6C irc.netsplit.net *!user@host 34 92988"
-         *
-         *  note: no info available on how many servers or clients are linked through this server link -> 0S 0C
-         *        no info available on who/what established the link, pretend it is by us -> *!*@myservername
-         *        no info available on how long ago we last parsed something from this link -> 0
-         *        no info available on how long this server has been linked -> 0
-         */
-        send_reply(targetnum, RPL_TRACESERVER, sourcenum, "Serv servers 0S 0C %s *!*@%s 0 0",
-          serverlist[i].name->content, myserver->content);
-      }
 
-      /* show my users, show class total */
-      if (showall) {
-
-        /* loop over all local users */
-        lnick = servernicks[mylongnum];
-        for (i = 0; i < MAXLOCALUSER; i++) {
-
-          if (lnick[i] == NULL)   /* no user */
-            continue;
-
-          if (!match2strings(target, lnick[i]->nick))   /* no match */
-            continue;
-
-          if (IsOper(lnick[i])) {
-            opers++;
-            /* 204 RPL_TRACEOPERATOR see above */
-            send_reply(targetnum, RPL_TRACEOPERATOR, sourcenum, "Oper opers %s[%s@%s] 0", lnick[i]->nick,
-              lnick[i]->ident[0] != '~' ? lnick[i]->ident : "", IPtostr(lnick[i]->p_ipaddr));
-          } else {
-            users++;
-            /* TODO: perhaps do show +k and/or +X clients? */
-            /* ircd does not show all local users in remote trace - might be too many users with trojan scan / nickjupes? */
-            continue;
-            /* 205 RPL_TRACEUSER see above */
-            send_reply(targetnum, RPL_TRACEUSER, sourcenum, "User users %s[%s@%s] 0", lnick[i]->nick,
-              lnick[i]->ident[0] != '~' ? lnick[i]->ident : "", IPtostr(lnick[i]->p_ipaddr));
-          }
-        }
-        /*
-         * class has no meaning here,
-         * but showing the total count for users/opers/servers might be useful anyway
-         *
-         * 209 RPL_TRACECLASS "source 209 target Class class count"
-         *                    "irc.netsplit.net 209 foobar Class users 2"
-         */
-        if (users)
-          send_reply(targetnum, RPL_TRACECLASS, sourcenum, "Class users %d", users);
-        if (opers)
-          send_reply(targetnum, RPL_TRACECLASS, sourcenum, "Class opers %d", opers);
-        /* should always be true - we are connected so at least 1 local server link */
-        if (servers)
-          send_reply(targetnum, RPL_TRACECLASS, sourcenum, "Class servers %d", servers);
+        if (IsOper(lnick[c]))
+          opers++;
+        else
+          users++;
+        trace_user(sourcenum, lnick[c]);
       }
+      /*
+       * class has no meaning here,
+       * but showing the total count for users/opers/servers might be useful anyway
+       *
+       * 209 RPL_TRACECLASS "source 209 target Class class count"
+       *                    "irc.netsplit.net 209 foobar Class users 2"
+       */
+      if (users)
+        irc_send("%s 209 %s Class users %d", getmynumeric(), sourcenum, users);
+      if (opers)
+        irc_send("%s 209 %s Class opers %d", getmynumeric(), sourcenum, opers);
+      if (servers)
+        irc_send("%s 209 %s Class servers %d", getmynumeric(), sourcenum, servers);
     }
   }
 
+
   /*
    * 262 RPL_TRACEEND "source 262 target :End of TRACE"
    *                  "irc.netsplit.net 262 foobar :End of TRACE"
    */
-  send_reply(targetnum, RPL_TRACEEND, sourcenum, ":End of TRACE");
+  irc_send("%s 262 %s :End of TRACE", getmynumeric(), sourcenum);
 
   return CMD_OK;
 }