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: 6444
Committed: Fri Aug 28 18:29:58 2015 UTC (9 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 8789 byte(s)
Log Message:
- m_trace.c: allow remote operators to request a full client list; various other cleanups

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
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 *, const struct Client *);
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 *node = NULL;
50
51 (*server)++;
52 (*client) += dlink_list_length(&target_p->serv->client_list);
53
54 DLINK_FOREACH(node, target_p->serv->server_list.head)
55 trace_get_dependent(server, client, node->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 *name = NULL;
68
69 if (parc > 1)
70 name = parv[1];
71 else
72 name = me.name;
73
74 sendto_one_numeric(source_p, &me, RPL_ENDOFTRACE, name);
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 *node = NULL;
86 const char *name = 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 name = parv[1];
94 else
95 name = 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(name)) == NULL)
104 {
105 DLINK_FOREACH(node, global_client_list.head)
106 {
107 ac2ptr = node->data;
108
109 if (!match(name, 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, name, ac2ptr->from->name);
119 else
120 sendto_one_numeric(source_p, &me, RPL_TRACELINK,
121 ircd_version, name, "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", 2, parc, parv) != HUNTED_ISME)
144 return 0;
145
146 if (HasUMode(source_p, UMODE_OPER))
147 return mo_trace(source_p, parc, parv);
148 return 0;
149 }
150
151 static void
152 do_actual_trace(struct Client *source_p, int parc, char *parv[])
153 {
154 const struct Client *target_p = NULL;
155 int doall = 0;
156 int wilds, dow;
157 dlink_node *node;
158 const char *name;
159
160 assert(HasUMode(source_p, UMODE_OPER));
161
162 if (parc > 1)
163 name = parv[1];
164 else
165 name = me.name;
166
167 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
168 "TRACE requested by %s (%s@%s) [%s]",
169 source_p->name, source_p->username,
170 source_p->host, source_p->servptr->name);
171
172 if (!match(name, me.name))
173 doall = 1;
174 else if (!MyClient(source_p) && !strcmp(name, me.id))
175 {
176 doall = 1;
177 name = me.name;
178 }
179
180 wilds = !parv[1] || has_wildcards(name);
181 dow = wilds || doall;
182
183 if (!dow) /* lets also do this for opers tracing nicks */
184 {
185 if ((target_p = hash_find_client(name)) && IsClient(target_p))
186 report_this_status(source_p, target_p);
187
188 sendto_one_numeric(source_p, &me, RPL_ENDOFTRACE, name);
189 return;
190 }
191
192 /* report all direct connections */
193 DLINK_FOREACH(node, local_client_list.head)
194 {
195 target_p = node->data;
196
197 if (!doall && wilds && match(name, target_p->name))
198 continue;
199 if (!dow && irccmp(name, target_p->name))
200 continue;
201
202 report_this_status(source_p, target_p);
203 }
204
205 DLINK_FOREACH(node, local_server_list.head)
206 {
207 target_p = node->data;
208
209 if (!doall && wilds && match(name, target_p->name))
210 continue;
211 if (!dow && irccmp(name, target_p->name))
212 continue;
213
214 report_this_status(source_p, target_p);
215 }
216
217 /* This section is to report the unknowns */
218 DLINK_FOREACH(node, unknown_list.head)
219 {
220 target_p = node->data;
221
222 if (!doall && wilds && match(name, target_p->name))
223 continue;
224 if (!dow && irccmp(name, target_p->name))
225 continue;
226
227 report_this_status(source_p, target_p);
228 }
229
230 DLINK_FOREACH(node, class_get_list()->head)
231 {
232 const struct ClassItem *class = node->data;
233
234 if (class->ref_count > 0)
235 sendto_one_numeric(source_p, &me, RPL_TRACECLASS, class->name, class->ref_count);
236 }
237
238 sendto_one_numeric(source_p, &me, RPL_ENDOFTRACE, name);
239 }
240
241 /* report_this_status()
242 *
243 * inputs - pointer to client to report to
244 * - pointer to client to report about
245 * output - counter of number of hits
246 * side effects - NONE
247 */
248 static void
249 report_this_status(struct Client *source_p, const struct Client *target_p)
250 {
251 const char *name;
252 const char *class_name;
253
254 name = get_client_name(target_p, HIDE_IP);
255 class_name = get_client_class(&target_p->connection->confs);
256
257 switch (target_p->status)
258 {
259 case STAT_CONNECTING:
260 sendto_one_numeric(source_p, &me, RPL_TRACECONNECTING, class_name,
261 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
262 break;
263 case STAT_HANDSHAKE:
264 sendto_one_numeric(source_p, &me, RPL_TRACEHANDSHAKE, class_name,
265 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
266 break;
267 case STAT_ME:
268 break;
269 case STAT_UNKNOWN:
270 sendto_one_numeric(source_p, &me, RPL_TRACEUNKNOWN, class_name,
271 name, target_p->sockhost,
272 CurrentTime - target_p->connection->firsttime);
273 break;
274 case STAT_CLIENT:
275 if (HasUMode(target_p, UMODE_OPER))
276 sendto_one_numeric(source_p, &me, RPL_TRACEOPERATOR, class_name, name,
277 target_p->sockhost,
278 CurrentTime - target_p->connection->lasttime,
279 client_get_idle_time(source_p, target_p));
280 else
281 sendto_one_numeric(source_p, &me, RPL_TRACEUSER, class_name, name,
282 target_p->sockhost,
283 CurrentTime - target_p->connection->lasttime,
284 client_get_idle_time(source_p, target_p));
285 break;
286 case STAT_SERVER:
287 {
288 unsigned int clients = 0;
289 unsigned int servers = 0;
290
291 trace_get_dependent(&servers, &clients, target_p);
292
293 if (!HasUMode(source_p, UMODE_ADMIN))
294 name = get_client_name(target_p, MASK_IP);
295
296 sendto_one_numeric(source_p, &me, RPL_TRACESERVER, class_name, servers,
297 clients, name, *(target_p->serv->by) ?
298 target_p->serv->by : "*", "*",
299 me.name, CurrentTime - target_p->connection->lasttime);
300 break;
301 }
302
303 default: /* ...we actually shouldn't come here... --msa */
304 sendto_one_numeric(source_p, &me, RPL_TRACENEWTYPE, name);
305 break;
306 }
307 }
308
309 static struct Message trace_msgtab =
310 {
311 .cmd = "TRACE",
312 .args_max = MAXPARA,
313 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
314 .handlers[CLIENT_HANDLER] = m_trace,
315 .handlers[SERVER_HANDLER] = ms_trace,
316 .handlers[ENCAP_HANDLER] = m_ignore,
317 .handlers[OPER_HANDLER] = mo_trace
318 };
319
320 static void
321 module_init(void)
322 {
323 mod_add_cmd(&trace_msgtab);
324 }
325
326 static void
327 module_exit(void)
328 {
329 mod_del_cmd(&trace_msgtab);
330 }
331
332 struct module module_entry =
333 {
334 .version = "$Revision$",
335 .modinit = module_init,
336 .modexit = module_exit,
337 };

Properties

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