ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_trace.c
Revision: 9857
Committed: Fri Jan 1 04:43:22 2021 UTC (4 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 7757 byte(s)
Log Message:
- Bump copyright years

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2021 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 #include "patchlevel.h"
41
42
43 static void
44 trace_get_dependent(unsigned int *const server,
45 unsigned int *const client, const struct Client *target_p)
46 {
47 dlink_node *node;
48
49 (*server)++;
50 (*client) += dlink_list_length(&target_p->serv->client_list);
51
52 DLINK_FOREACH(node, target_p->serv->server_list.head)
53 trace_get_dependent(server, client, node->data);
54 }
55
56 /* report_this_status()
57 *
58 * inputs - pointer to client to report to
59 * - pointer to client to report about
60 * output - counter of number of hits
61 * side effects - NONE
62 */
63 static void
64 report_this_status(struct Client *source_p, const struct Client *target_p)
65 {
66 const char *name;
67 const char *class_name;
68
69 name = client_get_name(target_p, HIDE_IP);
70 class_name = get_client_class(&target_p->connection->confs);
71
72 switch (target_p->status)
73 {
74 case STAT_CONNECTING:
75 sendto_one_numeric(source_p, &me, RPL_TRACECONNECTING, class_name,
76 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
77 break;
78 case STAT_HANDSHAKE:
79 sendto_one_numeric(source_p, &me, RPL_TRACEHANDSHAKE, class_name,
80 HasUMode(source_p, UMODE_ADMIN) ? name : target_p->name);
81 break;
82 case STAT_ME:
83 break;
84 case STAT_UNKNOWN:
85 sendto_one_numeric(source_p, &me, RPL_TRACEUNKNOWN, class_name,
86 name, target_p->sockhost,
87 event_base->time.sec_monotonic - target_p->connection->created_monotonic);
88 break;
89 case STAT_CLIENT:
90 if (HasUMode(target_p, UMODE_OPER))
91 sendto_one_numeric(source_p, &me, RPL_TRACEOPERATOR, class_name, name,
92 target_p->sockhost,
93 event_base->time.sec_monotonic - target_p->connection->last_data,
94 client_get_idle_time(source_p, target_p));
95 else
96 sendto_one_numeric(source_p, &me, RPL_TRACEUSER, class_name, name,
97 target_p->sockhost,
98 event_base->time.sec_monotonic - target_p->connection->last_data,
99 client_get_idle_time(source_p, target_p));
100 break;
101 case STAT_SERVER:
102 {
103 unsigned int clients = 0;
104 unsigned int servers = 0;
105
106 trace_get_dependent(&servers, &clients, target_p);
107
108 if (!HasUMode(source_p, UMODE_ADMIN))
109 name = client_get_name(target_p, MASK_IP);
110
111 sendto_one_numeric(source_p, &me, RPL_TRACESERVER, class_name, servers,
112 clients, name, *(target_p->serv->by) ?
113 target_p->serv->by : "*", "*",
114 me.name, event_base->time.sec_monotonic - target_p->connection->last_data);
115 break;
116 }
117
118 default: /* ...we actually shouldn't come here... --msa */
119 sendto_one_numeric(source_p, &me, RPL_TRACENEWTYPE, name);
120 break;
121 }
122 }
123
124 static void
125 do_trace(struct Client *source_p, const char *name)
126 {
127 bool doall = false;
128 const dlink_node *node;
129 const dlink_list *tab[] = { &local_client_list,
130 &local_server_list, &unknown_list, NULL };
131
132 assert(HasUMode(source_p, UMODE_OPER));
133
134 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
135 "TRACE requested by %s (%s@%s) [%s]",
136 source_p->name, source_p->username,
137 source_p->host, source_p->servptr->name);
138
139 if (EmptyString(name))
140 doall = true;
141 else if (match(name, me.name) == 0)
142 doall = true;
143 else if (!MyClient(source_p) && strcmp(name, me.id) == 0)
144 doall = true;
145
146 for (const dlink_list **list = tab; *list; ++list)
147 {
148 DLINK_FOREACH(node, (*list)->head)
149 {
150 const struct Client *target_p = node->data;
151
152 if (doall == true || match(name, target_p->name) == 0)
153 report_this_status(source_p, target_p);
154 }
155 }
156
157 if (doall == true)
158 {
159 DLINK_FOREACH(node, class_get_list()->head)
160 {
161 const struct ClassItem *class = node->data;
162
163 if (class->ref_count)
164 sendto_one_numeric(source_p, &me, RPL_TRACECLASS, class->name, class->ref_count);
165 }
166 }
167
168 sendto_one_numeric(source_p, &me, RPL_TRACEEND, me.name);
169 }
170
171 /*! \brief TRACE command handler
172 *
173 * \param source_p Pointer to allocated Client struct from which the message
174 * originally comes from. This can be a local or remote client.
175 * \param parc Integer holding the number of supplied arguments.
176 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
177 * pointers.
178 * \note Valid arguments for this command are:
179 * - parv[0] = command
180 */
181 static void
182 m_trace(struct Client *source_p, int parc, char *parv[])
183 {
184 sendto_one_numeric(source_p, &me, RPL_TRACEEND, me.name);
185 }
186
187 /*! \brief TRACE command handler
188 *
189 * \param source_p Pointer to allocated Client struct from which the message
190 * originally comes from. This can be a local or remote client.
191 * \param parc Integer holding the number of supplied arguments.
192 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
193 * pointers.
194 * \note Valid arguments for this command are:
195 * - parv[0] = command
196 * - parv[1] = nick or server name to trace
197 * - parv[2] = nick or server name to forward the trace to
198 */
199 static void
200 mo_trace(struct Client *source_p, int parc, char *parv[])
201 {
202 if (parc > 2)
203 if (server_hunt(source_p, ":%s TRACE %s :%s", 2, parv)->ret != HUNTED_ISME)
204 return;
205
206 const struct server_hunt *hunt = server_hunt(source_p, ":%s TRACE :%s", 1, parv);
207 switch (hunt->ret)
208 {
209 case HUNTED_PASS:
210 sendto_one_numeric(source_p, &me, RPL_TRACELINK,
211 PATCHLEVEL, hunt->target_p->name, hunt->target_p->from->name);
212 break;
213 case HUNTED_ISME:
214 do_trace(source_p, parv[1]);
215 break;
216 default:
217 break;
218 }
219 }
220
221 static struct Message trace_msgtab =
222 {
223 .cmd = "TRACE",
224 .handlers[UNREGISTERED_HANDLER] = { .handler = m_unregistered },
225 .handlers[CLIENT_HANDLER] = { .handler = m_trace },
226 .handlers[SERVER_HANDLER] = { .handler = mo_trace },
227 .handlers[ENCAP_HANDLER] = { .handler = m_ignore },
228 .handlers[OPER_HANDLER] = { .handler = mo_trace }
229 };
230
231 static void
232 module_init(void)
233 {
234 mod_add_cmd(&trace_msgtab);
235 }
236
237 static void
238 module_exit(void)
239 {
240 mod_del_cmd(&trace_msgtab);
241 }
242
243 struct module module_entry =
244 {
245 .version = "$Revision$",
246 .modinit = module_init,
247 .modexit = module_exit,
248 };

Properties

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