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