ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/m_trace.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (18 years, 5 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_trace.c
File size: 12807 byte(s)
Log Message:
- Fix svn:keywords

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 "handlers.h"
27 #include "tools.h"
28 #include "hook.h"
29 #include "client.h"
30 #include "hash.h"
31 #include "common.h"
32 #include "irc_string.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "fdlist.h"
36 #include "s_bsd.h"
37 #include "s_serv.h"
38 #include "send.h"
39 #include "msg.h"
40 #include "parse.h"
41 #include "modules.h"
42 #include "s_conf.h"
43 #include "irc_getnameinfo.h"
44
45 static void m_trace(struct Client *, struct Client *, int, char **);
46 static void ms_trace(struct Client*, struct Client*, int, char**);
47 static void mo_trace(struct Client*, struct Client*, int, char**);
48 static void do_actual_trace(struct Client *, int, char **);
49
50 struct Message trace_msgtab = {
51 "TRACE", 0, 0, 0, 0, MFLG_SLOW, 0,
52 {m_unregistered, m_trace, ms_trace, m_ignore, mo_trace, m_ignore}
53 };
54
55 #ifndef STATIC_MODULES
56 const char *_version = "$Revision$";
57 static struct Callback *trace_cb;
58
59 static void *
60 va_actual_trace(va_list args)
61 {
62 struct Client *source_p = va_arg(args, struct Client *);
63 int parc = va_arg(args, int);
64 char **parv = va_arg(args, char **);
65
66 do_actual_trace(source_p, parc, parv);
67 return NULL;
68 }
69
70 void
71 _modinit(void)
72 {
73 trace_cb = register_callback("doing_trace", va_actual_trace);
74 mod_add_cmd(&trace_msgtab);
75 }
76
77 void
78 _moddeinit(void)
79 {
80 mod_del_cmd(&trace_msgtab);
81 uninstall_hook(trace_cb, va_actual_trace);
82 }
83 #endif
84
85 static int report_this_status(struct Client *source_p, struct Client *target_p,
86 int dow, int link_u_p, int link_u_s);
87
88 /*
89 * m_trace()
90 *
91 * parv[0] = sender prefix
92 * parv[1] = target client/server to trace
93 */
94 static void
95 m_trace(struct Client *client_p, struct Client *source_p,
96 int parc, char *parv[])
97 {
98 const char *tname;
99
100 if (parc > 1)
101 tname = parv[1];
102 else
103 tname = me.name;
104
105 sendto_one(source_p, form_str(RPL_ENDOFTRACE),
106 me.name, source_p->name, tname);
107 }
108
109
110 /* mo_trace()
111 * parv[0] = sender prefix
112 * parv[1] = servername
113 */
114 static void
115 mo_trace(struct Client *client_p, struct Client *source_p,
116 int parc, char *parv[])
117 {
118 dlink_node *ptr;
119 const char *tname;
120 const char *from, *to;
121
122 if (parc > 2)
123 if (hunt_server(client_p, source_p, ":%s TRACE %s :%s", 2, parc, parv))
124 return;
125
126 if (parc > 1)
127 tname = parv[1];
128 else
129 tname = me.name;
130
131 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
132 {
133 from = me.id;
134 to = source_p->id;
135 }
136 else
137 {
138 from = me.name;
139 to = source_p->name;
140 }
141
142 switch (hunt_server(client_p, source_p, ":%s TRACE :%s", 1, parc, parv))
143 {
144 case HUNTED_PASS: /* note: gets here only if parv[1] exists */
145 {
146 struct Client *ac2ptr = NULL;
147
148 if ((ac2ptr = find_client(tname)) == NULL)
149 {
150 DLINK_FOREACH(ptr, global_client_list.head)
151 {
152 ac2ptr = ptr->data;
153
154 if (match(tname, ac2ptr->name) || match(ac2ptr->name, tname))
155 break;
156 else
157 ac2ptr = NULL;
158 }
159 }
160
161 if (ac2ptr != NULL)
162 sendto_one(source_p, form_str(RPL_TRACELINK), from, to,
163 ircd_version, tname, ac2ptr->from->name);
164 else
165 sendto_one(source_p, form_str(RPL_TRACELINK), from, to,
166 ircd_version, tname, "ac2ptr_is_NULL!!");
167 return;
168 }
169 case HUNTED_ISME:
170 #ifdef STATIC_MODULES
171 do_actual_trace(source_p, parc, parv);
172 #else
173 execute_callback(trace_cb, source_p, parc, parv);
174 #endif
175 break;
176 default:
177 return;
178 }
179 }
180
181 static void
182 do_actual_trace(struct Client *source_p, int parc, char **parv)
183 {
184 struct Client *target_p = NULL;
185 struct ConfItem *conf;
186 struct ClassItem *cltmp;
187 int doall = 0;
188 int cnt = 0, wilds, dow;
189 dlink_node *ptr;
190 const char *from, *to, *tname;
191
192 if (parc > 1)
193 tname = parv[1];
194 else
195 tname = me.name;
196
197 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
198 {
199 from = me.id;
200 to = source_p->id;
201 }
202 else
203 {
204 from = me.name;
205 to = source_p->name;
206 }
207
208 if (match(tname, me.name))
209 doall = TRUE;
210 else if (!MyClient(source_p) && !strcmp(tname, me.id))
211 {
212 doall = TRUE;
213 tname = me.name;
214 }
215
216 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
217 dow = wilds || doall;
218
219 set_time();
220 if (!IsOper(source_p) || !dow) /* non-oper traces must be full nicks */
221 /* lets also do this for opers tracing nicks */
222 {
223 const char *name;
224 const char *class_name;
225 char ipaddr[HOSTIPLEN];
226
227 target_p = find_client(tname);
228
229 if (target_p && IsClient(target_p))
230 {
231 name = get_client_name(target_p, HIDE_IP);
232 /* should we not use sockhost here? - stu */
233 irc_getnameinfo((struct sockaddr*)&target_p->localClient->ip,
234 target_p->localClient->ip.ss_len, ipaddr, HOSTIPLEN, NULL, 0,
235 NI_NUMERICHOST);
236
237 class_name = get_client_class(target_p);
238
239 if (IsOper(target_p))
240 {
241 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
242 from, to, class_name, name,
243 IsIPSpoof(target_p) ? "255.255.255.255" : ipaddr,
244 CurrentTime - target_p->lasttime,
245 CurrentTime - target_p->localClient->last);
246 }
247 else
248 {
249 sendto_one(source_p,form_str(RPL_TRACEUSER),
250 from, to, class_name, name,
251 IsIPSpoof(target_p) ? "255.255.255.255" : ipaddr,
252 CurrentTime - target_p->lasttime,
253 CurrentTime - target_p->localClient->last);
254 }
255 }
256
257 sendto_one(source_p, form_str(RPL_ENDOFTRACE),
258 from, to, tname);
259 return;
260 }
261
262 /* report all direct connections */
263 DLINK_FOREACH(ptr, local_client_list.head)
264 {
265 target_p = ptr->data;
266
267 if (IsInvisible(target_p) && dow &&
268 !(MyConnect(source_p) && IsOper(source_p)) &&
269 !IsOper(target_p) && (target_p != source_p))
270 continue;
271 if (!doall && wilds && !match(tname, target_p->name))
272 continue;
273 if (!dow && irccmp(tname, target_p->name))
274 continue;
275
276 cnt = report_this_status(source_p, target_p, dow, 0, 0);
277 }
278
279 DLINK_FOREACH(ptr, serv_list.head)
280 {
281 target_p = ptr->data;
282
283 if (!doall && wilds && !match(tname, target_p->name))
284 continue;
285 if (!dow && irccmp(tname, target_p->name))
286 continue;
287
288 cnt = report_this_status(source_p, target_p, dow,
289 target_p->serv->dep_users, target_p->serv->dep_servers);
290 }
291
292 /* This section is to report the unknowns */
293 DLINK_FOREACH(ptr, unknown_list.head)
294 {
295 target_p = ptr->data;
296
297 if (!doall && wilds && !match(tname, target_p->name))
298 continue;
299 if (!dow && irccmp(tname, target_p->name))
300 continue;
301
302 cnt = report_this_status(source_p, target_p, dow, 0, 0);
303 }
304
305 DLINK_FOREACH(ptr, class_items.head)
306 {
307 conf = ptr->data;
308 cltmp = (struct ClassItem *)map_to_conf(conf);
309 if (CurrUserCount(cltmp) > 0)
310 sendto_one(source_p, form_str(RPL_TRACECLASS),
311 from, to, conf->name, CurrUserCount(cltmp));
312 }
313
314 sendto_one(source_p, form_str(RPL_ENDOFTRACE), from, to, tname);
315 }
316
317
318 /*
319 ** ms_trace
320 ** parv[0] = sender prefix
321 ** parv[1] = servername
322 */
323 static void
324 ms_trace(struct Client *client_p, struct Client *source_p,
325 int parc, char *parv[])
326 {
327 if (hunt_server(client_p, source_p, ":%s TRACE %s :%s", 2, parc, parv))
328 return;
329
330 if (IsOper(source_p))
331 mo_trace(client_p, source_p, parc, parv);
332 }
333
334 /* report_this_status()
335 *
336 * inputs - pointer to client to report to
337 * - pointer to client to report about
338 * output - counter of number of hits
339 * side effects - NONE
340 */
341 static int
342 report_this_status(struct Client *source_p, struct Client *target_p,
343 int dow, int link_u_p, int link_s_p)
344 {
345 const char *name;
346 const char *class_name;
347 const char *from, *to;
348 char ip[HOSTIPLEN];
349 int cnt = 0;
350
351 if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
352 {
353 from = me.id;
354 to = source_p->id;
355 }
356 else
357 {
358 from = me.name;
359 to = source_p->name;
360 }
361
362 /* Should this be sockhost? - stu */
363 irc_getnameinfo((struct sockaddr*)&target_p->localClient->ip,
364 target_p->localClient->ip.ss_len, ip, HOSTIPLEN, NULL, 0,
365 NI_NUMERICHOST);
366 name = get_client_name(target_p, HIDE_IP);
367 class_name = get_client_class(target_p);
368
369 set_time();
370
371 switch(target_p->status)
372 {
373 case STAT_CONNECTING:
374 sendto_one(source_p, form_str(RPL_TRACECONNECTING),
375 from, to, class_name,
376 IsOperAdmin(source_p) ? name : target_p->name);
377
378 cnt++;
379 break;
380 case STAT_HANDSHAKE:
381 sendto_one(source_p, form_str(RPL_TRACEHANDSHAKE),
382 from, to, class_name,
383 IsOperAdmin(source_p) ? name : target_p->name);
384
385 cnt++;
386 break;
387 case STAT_ME:
388 break;
389 case STAT_UNKNOWN:
390 /* added time -Taner */
391 sendto_one(source_p, form_str(RPL_TRACEUNKNOWN),
392 from, to, class_name, name, ip,
393 target_p->firsttime ? CurrentTime - target_p->firsttime : -1);
394 cnt++;
395 break;
396 case STAT_CLIENT:
397 /* Only opers see users if there is a wildcard
398 * but anyone can see all the opers.
399 */
400 if ((IsOper(source_p) &&
401 (MyClient(source_p) || !(dow && IsInvisible(target_p))))
402 || !dow || IsOper(target_p))
403 {
404 if (IsAdmin(target_p) && !ConfigFileEntry.hide_spoof_ips)
405 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
406 from, to, class_name, name,
407 IsOperAdmin(source_p) ? ip : "255.255.255.255",
408 CurrentTime - target_p->lasttime,
409 CurrentTime - target_p->localClient->last);
410
411 else if (IsOper(target_p))
412 {
413 if (ConfigFileEntry.hide_spoof_ips)
414 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
415 from, to, class_name, name,
416 IsIPSpoof(target_p) ? "255.255.255.255" : ip,
417 CurrentTime - target_p->lasttime,
418 CurrentTime - target_p->localClient->last);
419 else
420 sendto_one(source_p, form_str(RPL_TRACEOPERATOR),
421 from, to, class_name, name,
422 MyOper(source_p) ? ip :
423 (IsIPSpoof(target_p) ? "255.255.255.255" : ip),
424 CurrentTime - target_p->lasttime,
425 CurrentTime - target_p->localClient->last);
426 }
427 else
428 {
429 const char *format_str=NULL;
430 if (IsOper(source_p) && IsCaptured(target_p))
431 format_str = form_str(RPL_TRACECAPTURED);
432 else
433 format_str = form_str(RPL_TRACEUSER);
434
435 if (ConfigFileEntry.hide_spoof_ips)
436 sendto_one(source_p, format_str,
437 from, to, class_name, name,
438 IsIPSpoof(target_p) ? "255.255.255.255" : ip,
439 CurrentTime - target_p->lasttime,
440 CurrentTime - target_p->localClient->last);
441 else
442 sendto_one(source_p, format_str,
443 from, to, class_name, name,
444 MyOper(source_p) ? ip :
445 (IsIPSpoof(target_p) ? "255.255.255.255" : ip),
446 CurrentTime - target_p->lasttime,
447 CurrentTime - target_p->localClient->last);
448 }
449 cnt++;
450 }
451 break;
452 case STAT_SERVER:
453 if(!IsOperAdmin(source_p))
454 name = get_client_name(target_p, MASK_IP);
455
456 sendto_one(source_p, form_str(RPL_TRACESERVER),
457 from, to, class_name, link_s_p,
458 link_u_p, name, *(target_p->serv->by) ?
459 target_p->serv->by : "*", "*",
460 me.name, CurrentTime - target_p->lasttime);
461 cnt++;
462 break;
463
464 default: /* ...we actually shouldn't come here... --msa */
465 sendto_one(source_p, form_str(RPL_TRACENEWTYPE),
466 from, to, name);
467 cnt++;
468 break;
469 }
470
471 return cnt;
472 }

Properties

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