ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_trace.c
Revision: 1783
Committed: Thu Jan 24 19:26:51 2013 UTC (12 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 12345 byte(s)
Log Message:
- Forward-port -r1774:
  - Configuration parser now does support 'year' and 'month' units
  - Add support for fake idle times to /whois. Known from csircd, this
    adds min_idle, and max_idle configuration directives to class{} blocks

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_trace.c: Traces a path to a client/server.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h"
27 #include "client.h"
28 #include "hash.h"
29 #include "irc_string.h"
30 #include "ircd.h"
31 #include "numeric.h"
32 #include "s_bsd.h"
33 #include "s_serv.h"
34 #include "send.h"
35 #include "parse.h"
36 #include "modules.h"
37 #include "conf.h"
38 #include "conf_class.h"
39
40
41 static void do_actual_trace(struct Client *, int, char *[]);
42 static void report_this_status(struct Client *, struct Client *, int);
43
44 static void
45 trace_get_dependent(int *const server,
46 int *const client, const struct Client *target_p)
47 {
48 const dlink_node *ptr = NULL;
49
50 (*server)++;
51 (*client) += dlink_list_length(&target_p->serv->client_list);
52
53 DLINK_FOREACH(ptr, target_p->serv->server_list.head)
54 trace_get_dependent(server, client, ptr->data);
55 }
56
57 /*
58 * m_trace()
59 *
60 * parv[0] = sender prefix
61 * parv[1] = target client/server to trace
62 */
63 static void
64 m_trace(struct Client *client_p, struct Client *source_p,
65 int parc, char *parv[])
66 {
67 const char *tname;
68
69 if (parc > 1)
70 tname = parv[1];
71 else
72 tname = me.name;
73
74 sendto_one(source_p, form_str(RPL_ENDOFTRACE),
75 me.name, source_p->name, tname);
76 }
77
78
79 /* mo_trace()
80 * parv[0] = sender prefix
81 * parv[1] = servername
82 */
83 static void
84 mo_trace(struct Client *client_p, struct Client *source_p,
85 int parc, char *parv[])
86 {
87 dlink_node *ptr;
88 const char *tname;
89 const char *from, *to;
90
91 if (parc > 2)
92 if (hunt_server(client_p, source_p, ":%s TRACE %s :%s", 2, parc, parv))
93 return;
94
95 if (parc > 1)
96 tname = parv[1];
97 else
98 tname = me.name;
99
100 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
101 {
102 from = me.id;
103 to = source_p->id;
104 }
105 else
106 {
107 from = me.name;
108 to = source_p->name;
109 }
110
111 switch (hunt_server(client_p, source_p, ":%s TRACE :%s", 1, parc, parv))
112 {
113 case HUNTED_PASS: /* note: gets here only if parv[1] exists */
114 {
115 struct Client *ac2ptr = NULL;
116
117 if ((ac2ptr = hash_find_client(tname)) == NULL)
118 {
119 DLINK_FOREACH(ptr, global_client_list.head)
120 {
121 ac2ptr = ptr->data;
122
123 if (!match(tname, ac2ptr->name))
124 break;
125 else
126 ac2ptr = NULL;
127 }
128 }
129
130 if (ac2ptr != NULL)
131 sendto_one(source_p, form_str(RPL_TRACELINK), from, to,
132 ircd_version, tname, ac2ptr->from->name);
133 else
134 sendto_one(source_p, form_str(RPL_TRACELINK), from, to,
135 ircd_version, tname, "ac2ptr_is_NULL!!");
136 return;
137 }
138
139 case HUNTED_ISME:
140 do_actual_trace(source_p, parc, parv);
141 break;
142 default:
143 return;
144 }
145 }
146
147 /*
148 ** ms_trace
149 ** parv[0] = sender prefix
150 ** parv[1] = servername
151 */
152 static void
153 ms_trace(struct Client *client_p, struct Client *source_p,
154 int parc, char *parv[])
155 {
156 if (hunt_server(client_p, source_p, ":%s TRACE %s :%s", 2, parc, parv))
157 return;
158
159 if (HasUMode(source_p, UMODE_OPER))
160 mo_trace(client_p, source_p, parc, parv);
161 }
162
163 static void
164 do_actual_trace(struct Client *source_p, int parc, char *parv[])
165 {
166 struct Client *target_p = NULL;
167 int doall = 0;
168 int wilds, dow;
169 dlink_node *ptr;
170 const char *from, *to, *tname;
171
172 if (parc > 1)
173 tname = parv[1];
174 else
175 tname = me.name;
176
177 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
178 {
179 from = me.id;
180 to = source_p->id;
181 }
182 else
183 {
184 from = me.name;
185 to = source_p->name;
186 }
187
188 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
189 "TRACE requested by %s (%s@%s) [%s]",
190 source_p->name, source_p->username,
191 source_p->host, source_p->servptr->name);
192
193 if (!match(tname, me.name))
194 doall = 1;
195 else if (!MyClient(source_p) && !strcmp(tname, me.id))
196 {
197 doall = 1;
198 tname = me.name;
199 }
200
201 wilds = !parv[1] || has_wildcards(tname);
202 dow = wilds || doall;
203
204 set_time();
205 if (!HasUMode(source_p, UMODE_OPER) || !dow) /* non-oper traces must be full nicks */
206 /* lets also do this for opers tracing nicks */
207 {
208 const char *name;
209 target_p = hash_find_client(tname);
210
211 if (target_p && IsClient(target_p))
212 {
213 name = get_client_name(target_p, HIDE_IP);
214
215 if (HasUMode(target_p, UMODE_OPER))
216 {
217 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
218 from, to, get_client_class(&target_p->localClient->confs), name,
219 IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost,
220 CurrentTime - target_p->localClient->lasttime,
221 idle_time_get(source_p, target_p));
222 }
223 else
224 {
225 sendto_one(source_p,form_str(RPL_TRACEUSER),
226 from, to, get_client_class(&target_p->localClient->confs), name,
227 IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost,
228 CurrentTime - target_p->localClient->lasttime,
229 idle_time_get(source_p, target_p));
230 }
231 }
232
233 sendto_one(source_p, form_str(RPL_ENDOFTRACE),
234 from, to, tname);
235 return;
236 }
237
238 /* report all direct connections */
239 DLINK_FOREACH(ptr, local_client_list.head)
240 {
241 target_p = ptr->data;
242
243 if (HasUMode(target_p, UMODE_INVISIBLE) && dow &&
244 !(MyConnect(source_p) && HasUMode(source_p, UMODE_OPER)) &&
245 !HasUMode(target_p, UMODE_OPER) && (target_p != source_p))
246 continue;
247 if (!doall && wilds && match(tname, target_p->name))
248 continue;
249 if (!dow && irccmp(tname, target_p->name))
250 continue;
251
252 report_this_status(source_p, target_p, dow);
253 }
254
255 DLINK_FOREACH(ptr, serv_list.head)
256 {
257 target_p = ptr->data;
258
259 if (!doall && wilds && match(tname, target_p->name))
260 continue;
261 if (!dow && irccmp(tname, target_p->name))
262 continue;
263
264 report_this_status(source_p, target_p, dow);
265 }
266
267 /* This section is to report the unknowns */
268 DLINK_FOREACH(ptr, unknown_list.head)
269 {
270 target_p = ptr->data;
271
272 if (!doall && wilds && match(tname, target_p->name))
273 continue;
274 if (!dow && irccmp(tname, target_p->name))
275 continue;
276
277 report_this_status(source_p, target_p, dow);
278 }
279
280 DLINK_FOREACH(ptr, class_get_list()->head)
281 {
282 const struct ClassItem *class = ptr->data;
283
284 if (class->ref_count > 0)
285 sendto_one(source_p, form_str(RPL_TRACECLASS),
286 from, to, class->name, class->ref_count);
287 }
288
289 sendto_one(source_p, form_str(RPL_ENDOFTRACE), from, to, tname);
290 }
291
292 /* report_this_status()
293 *
294 * inputs - pointer to client to report to
295 * - pointer to client to report about
296 * output - counter of number of hits
297 * side effects - NONE
298 */
299 static void
300 report_this_status(struct Client *source_p, struct Client *target_p, int dow)
301 {
302 const char *name;
303 const char *class_name;
304 const char *from, *to;
305
306 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
307 {
308 from = me.id;
309 to = source_p->id;
310 }
311 else
312 {
313 from = me.name;
314 to = source_p->name;
315 }
316
317 name = get_client_name(target_p, HIDE_IP);
318 class_name = get_client_class(&target_p->localClient->confs);
319
320 set_time();
321
322 switch (target_p->status)
323 {
324 case STAT_CONNECTING:
325 sendto_one(source_p, form_str(RPL_TRACECONNECTING),
326 from, to, class_name,
327 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
328 break;
329 case STAT_HANDSHAKE:
330 sendto_one(source_p, form_str(RPL_TRACEHANDSHAKE),
331 from, to, class_name,
332 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
333 break;
334 case STAT_ME:
335 break;
336 case STAT_UNKNOWN:
337 /* added time -Taner */
338 sendto_one(source_p, form_str(RPL_TRACEUNKNOWN),
339 from, to, class_name, name, target_p->sockhost,
340 target_p->localClient->firsttime ? /* TBD: can't be 0 */
341 CurrentTime - target_p->localClient->firsttime : -1);
342 break;
343 case STAT_CLIENT:
344 /*
345 * Only opers see users if there is a wildcard
346 * but anyone can see all the opers.
347 */
348 if ((HasUMode(source_p, UMODE_OPER) &&
349 (MyClient(source_p) || !(dow && HasUMode(target_p, UMODE_INVISIBLE))))
350 || !dow || HasUMode(target_p, UMODE_OPER))
351 {
352 if (HasUMode(target_p, UMODE_ADMIN) && !ConfigFileEntry.hide_spoof_ips)
353 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
354 from, to, class_name, name,
355 HasUMode(source_p, UMODE_ADMIN) ? target_p->sockhost : "255.255.255.255",
356 CurrentTime - target_p->localClient->lasttime,
357 idle_time_get(source_p, target_p));
358
359 else if (HasUMode(target_p, UMODE_OPER))
360 {
361 if (ConfigFileEntry.hide_spoof_ips)
362 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
363 from, to, class_name, name,
364 IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost,
365 CurrentTime - target_p->localClient->lasttime,
366 idle_time_get(source_p, target_p));
367 else
368 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
369 from, to, class_name, name,
370 MyOper(source_p) ? target_p->sockhost :
371 (IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost),
372 CurrentTime - target_p->localClient->lasttime,
373 idle_time_get(source_p, target_p));
374 }
375 else
376 {
377 if (ConfigFileEntry.hide_spoof_ips)
378 sendto_one(source_p, form_str(RPL_TRACEUSER),
379 from, to, class_name, name,
380 IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost,
381 CurrentTime - target_p->localClient->lasttime,
382 idle_time_get(source_p, target_p));
383 else
384 sendto_one(source_p, form_str(RPL_TRACEUSER),
385 from, to, class_name, name,
386 MyOper(source_p) ? target_p->sockhost :
387 (IsIPSpoof(target_p) ? "255.255.255.255" : target_p->sockhost),
388 CurrentTime - target_p->localClient->lasttime,
389 idle_time_get(source_p, target_p));
390 }
391 }
392 break;
393 case STAT_SERVER:
394 {
395 int clients = 0;
396 int servers = 0;
397
398 trace_get_dependent(&servers, &clients, target_p);
399
400 if (!HasUMode(source_p, UMODE_ADMIN))
401 name = get_client_name(target_p, MASK_IP);
402
403 sendto_one(source_p, form_str(RPL_TRACESERVER),
404 from, to, class_name, servers,
405 clients, name, *(target_p->serv->by) ?
406 target_p->serv->by : "*", "*",
407 me.name, CurrentTime - target_p->localClient->lasttime);
408 break;
409 }
410
411 default: /* ...we actually shouldn't come here... --msa */
412 sendto_one(source_p, form_str(RPL_TRACENEWTYPE),
413 from, to, name);
414 break;
415 }
416 }
417
418 static struct Message trace_msgtab = {
419 "TRACE", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
420 { m_unregistered, m_trace, ms_trace, m_ignore, mo_trace, m_ignore }
421 };
422
423 static void
424 module_init(void)
425 {
426 mod_add_cmd(&trace_msgtab);
427 }
428
429 static void
430 module_exit(void)
431 {
432 mod_del_cmd(&trace_msgtab);
433 }
434
435 struct module module_entry = {
436 .node = { NULL, NULL, NULL },
437 .name = NULL,
438 .version = "$Revision$",
439 .handle = NULL,
440 .modinit = module_init,
441 .modexit = module_exit,
442 .flags = 0
443 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision