ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_trace.c
Revision: 3347
Committed: Sun Apr 20 14:03:06 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 11559 byte(s)
Log Message:
- Moved files:
  s_user.c -> user.c
  s_misc.c -> misc.c
  s_serv.c -> server.c

File Contents

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

Properties

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