]>
Commit | Line | Data |
---|---|---|
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 | } |