]> jfr.im git - irc/quakenet/newserv.git/blob - miscreply/trace.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / miscreply / trace.c
1 /* trace.c */
2
3 #include "miscreply.h"
4 #include "../core/error.h"
5 #include "../irc/irc.h"
6 #include "../lib/irc_string.h"
7 #include "../server/server.h"
8
9 #include <string.h>
10
11
12
13 /* trace_user
14 *
15 */
16 static 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,
25 tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
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,
32 tnick->ident[0] != '~' ? tnick->ident : "", IPtostr(tnick->ipaddress));
33 }
34 }
35
36
37
38 /* trace_server
39 * return number of matched servers
40 */
41 static 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
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 */
73 int handletracemsg(void *source, int cargc, char **cargv) {
74
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 */
85
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];
95
96 /* find source user */
97 if (!(snick = miscreply_finduser(sourcenum, "TRACE")))
98 return CMD_OK;
99
100 /* doall, wilds, dow */
101 doall = match2strings(target, myserver->content);
102 wilds = strchr(target, '*') || strchr(target, '?');
103 dow = wilds || doall;
104
105
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 */
129 continue;
130
131 /* target is invisible (mode +i), target is not an operator */
132 if (IsInvisible(lnick[c]) && dow && !IsOper(lnick[c]))
133 continue;
134
135 /* dont show all, do wildcards and no match */
136 if (!doall && wilds && !match2strings(target, lnick[c]->nick))
137 continue;
138
139 if (IsOper(lnick[c]))
140 opers++;
141 else
142 users++;
143 trace_user(sourcenum, lnick[c]);
144 }
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);
158 }
159 }
160
161
162 /*
163 * 262 RPL_TRACEEND "source 262 target :End of TRACE"
164 * "irc.netsplit.net 262 foobar :End of TRACE"
165 */
166 irc_send("%s 262 %s :End of TRACE", getmynumeric(), sourcenum);
167
168 return CMD_OK;
169 }