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

# User Rev Content
1 adx 30 /*
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 knight 31 * $Id$
23 adx 30 */
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 knight 31 const char *_version = "$Revision$";
57 adx 30 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"