ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/m_trace.c
Revision: 1230
Committed: Thu Sep 22 19:41:19 2011 UTC (12 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 12596 byte(s)
Log Message:
- cleanup module loader. Make module api more flexible

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

Properties

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