]> jfr.im git - irc/quakenet/newserv.git/blame - miscreply/trace.c
CHANSERV: better batcher error handling for expired accounts/accounts with no email.
[irc/quakenet/newserv.git] / miscreply / trace.c
CommitLineData
7bec4aeb 1/* trace.c */
2
3#include "miscreply.h"
7bec4aeb 4#include "../core/error.h"
5#include "../irc/irc.h"
6#include "../lib/irc_string.h"
7bec4aeb 7#include "../server/server.h"
8
9#include <string.h>
10
11
12
a7697869 13/* trace_user
14 *
7bec4aeb 15 */
a7697869 16static void trace_user(char *sourcenum, nick *tnick) {
17 if (IsOper(tnick)) {
18 /*
19 * 204 RPL_TRACEOPERATOR "source 204 target Oper class nick[user@IP] last_parse"
20 * "irc.netsplit.net 204 foobar Oper barfoo[fish@127.0.0.1] 0"
21 *
22 * note: no info available on how long ago we last parsed something from this user -> 0 (not idle time)
23 */
24 irc_send("%s 204 %s Oper opers %s[%s@%s] 0", getmynumeric(), sourcenum, tnick->nick,
fdcb5d66 25 tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
a7697869 26 } else {
27 /*
28 * 205 RPL_TRACEUSER "source 205 target User class nick[user@IP] last_parse"
29 * "irc.netsplit.net 205 foobar User barfoo[fish@127.0.0.1] 0"
30 */
31 irc_send("%s 205 %s User users %s[%s@%s] 0", getmynumeric(), sourcenum, tnick->nick,
fdcb5d66 32 tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
a7697869 33 }
34}
35
36
37
38/* trace_server
39 * return number of matched servers
40 */
41static int trace_server(char *sourcenum, char *target, int doall) {
42
43 /* do not show all and no match for my hub */
44 if (!doall && !match2strings(target, serverlist[myhub].name->content))
45 return 0;
46
47 /*
48 * 206 RPL_TRACESERVER "source 206 target Serv class NS NC server connected_by last_parse connected_for"
49 * "irc.netsplit.net 206 foobar Server 2S 6C irc.netsplit.net *!user@host 34 92988"
50 *
51 * note: no info available on how many servers or clients are linked through this server link -> 0S 0C
52 * no info available on who/what established the link, pretend it is by us -> *!*@myservername
53 * no info available on how long ago we last parsed something from this link -> 0
54 * no info available on how long this server has been linked -> 0
55 */
56 irc_send("%s 206 %s Serv servers 0S 0C %s *!*@%s 0 0", getmynumeric(), sourcenum,
57 serverlist[myhub].name->content, myserver->content);
58
59 return 1;
60}
61
62
7bec4aeb 63
64/* handle remote trace request
65 *
66 * <source numeric> TRACE/TR <target> <target server numeric>
67 *
68 * cargv[0] = target
69 * as given by source, can be a nick or a server (may contain wildcards)
70 * cargv[1] = target server numeric
71 *
72 */
73int handletracemsg(void *source, int cargc, char **cargv) {
74
a7697869 75 nick *snick; /* struct nick for source nick */
76 nick *tnick; /* struct nick for target nick */
77 nick **lnick; /* struct nick for looping local users */
78 int c; /* loop variable */
79 int opers = 0; /* number of operators */
80 int users = 0; /* number of users */
81 int servers = 0; /* number of servers */
82 int doall, wilds, dow; /* determine what to show */
83 char *sourcenum = (char *)source; /* source user numeric */
84 char *target; /* target parameter - as given by the source user */
7bec4aeb 85
7bec4aeb 86
87 /* check parameters */
88 if (cargc < 2) {
89 miscreply_needmoreparams(sourcenum, "TRACE");
90 return CMD_OK;
91 }
92
93 /* get the parameters */
94 target = cargv[0];
7bec4aeb 95
96 /* find source user */
97 if (!(snick = miscreply_finduser(sourcenum, "TRACE")))
98 return CMD_OK;
99
a7697869 100 /* doall, wilds, dow */
101 doall = match2strings(target, myserver->content);
102 wilds = strchr(target, '*') || strchr(target, '?');
103 dow = wilds || doall;
7bec4aeb 104
7bec4aeb 105
a7697869 106 /* find target user */
107 if ((tnick = getnickbynick(target))) {
108
109 /* my user */
110 if (mylongnum == homeserver(tnick->numeric))
111 trace_user(sourcenum, tnick);
112 }
113
114
115 /* source user is an operator */
116 else if (IsOper(snick)) {
117
118 /* show servers */
119 servers = trace_server(sourcenum, target, doall);
120
121 /* do all or wilds */
122 if (dow) {
123
124 /* loop over all local users */
125 lnick = servernicks[mylongnum];
126 for (c = 0; c < serverlist[mylongnum].maxusernum; c++) {
127
128 if (lnick[c] == NULL) /* no user */
7bec4aeb 129 continue;
a7697869 130
131 /* target is invisible (mode +i), target is not an operator */
132 if (IsInvisible(lnick[c]) && dow && !IsOper(lnick[c]))
7bec4aeb 133 continue;
a7697869 134
135 /* dont show all, do wildcards and no match */
136 if (!doall && wilds && !match2strings(target, lnick[c]->nick))
7bec4aeb 137 continue;
7bec4aeb 138
a7697869 139 if (IsOper(lnick[c]))
140 opers++;
141 else
142 users++;
143 trace_user(sourcenum, lnick[c]);
7bec4aeb 144 }
a7697869 145 /*
146 * class has no meaning here,
147 * but showing the total count for users/opers/servers might be useful anyway
148 *
149 * 209 RPL_TRACECLASS "source 209 target Class class count"
150 * "irc.netsplit.net 209 foobar Class users 2"
151 */
152 if (users)
153 irc_send("%s 209 %s Class users %d", getmynumeric(), sourcenum, users);
154 if (opers)
155 irc_send("%s 209 %s Class opers %d", getmynumeric(), sourcenum, opers);
156 if (servers)
157 irc_send("%s 209 %s Class servers %d", getmynumeric(), sourcenum, servers);
7bec4aeb 158 }
159 }
160
a7697869 161
7bec4aeb 162 /*
163 * 262 RPL_TRACEEND "source 262 target :End of TRACE"
164 * "irc.netsplit.net 262 foobar :End of TRACE"
165 */
a7697869 166 irc_send("%s 262 %s :End of TRACE", getmynumeric(), sourcenum);
7bec4aeb 167
168 return CMD_OK;
169}