ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/m_trace.c
Revision: 891
Committed: Thu Nov 1 13:44:50 2007 UTC (16 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 12642 byte(s)
Log Message:
- Avoid useless irc_getnameinfo calls in several places

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

Properties

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