2 * IRC - Internet Relay Chat, ircd/m_trace.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * m_functions execute protocol messages on this server:
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
84 * No need to include handlers.h here the signatures must match
85 * and we don't need to force a rebuild of all the handlers everytime
86 * we add a new one to the list. --Bleep
94 #include "ircd_reply.h"
95 #include "ircd_string.h"
110 * m_trace - generic message handler
112 * parv[0] = sender prefix
113 * parv[1] = nick or servername
114 * parv[2] = 'target' servername
116 int m_trace(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
119 struct Client *acptr;
120 struct ConfClass *cltmp;
122 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
123 int cnt = 0, wilds, dow;
125 if (parc < 2 || BadPtr(parv[1])) {
126 /* just "TRACE" without parameters. Must be from local client */
131 } else if (parc < 3 || BadPtr(parv[2])) {
132 /* No target specified. Make one before propagating. */
135 if ((acptr = find_match_server(parv[1])) ||
136 ((acptr = FindClient(parv[1])) && !MyUser(acptr))) {
138 parv[2] = acptr->user->server->name;
140 parv[2] = acptr->name;
143 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr),
144 "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH)
149 /* Got "TRACE <tname> :<target>" */
151 if (MyUser(sptr) || Protocol(cptr) < 10)
152 acptr = find_match_server(parv[2]);
154 acptr = FindNServer(parv[2]);
155 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc,
156 parv)) == HUNTED_NOSUCH)
161 if (i == HUNTED_PASS) {
163 acptr = next_client(GlobalClientList, tname);
166 send_reply(sptr, RPL_TRACELINK,
168 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>"
170 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>",
171 (acptr && acptr->from->serv) ? acptr->from->serv->timestamp : 0
173 ); /* I really could do without GODMODE */
177 doall = (parv[1] && (parc > 1)) ? !match(tname, me.name) : 1;
178 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
179 dow = wilds || doall;
181 /* Don't give (long) remote listings to lusers */
182 if (dow && !MyConnect(sptr) && !IsAnOper(sptr))
185 for (i = 0; i < MAXCONNECTIONS; i++)
186 link_s[i] = 0, link_u[i] = 0;
189 for (acptr = GlobalClientList; acptr; acptr = acptr->next) {
191 link_u[acptr->from->fd]++;
192 else if (IsServer(acptr))
193 link_s[acptr->from->fd]++;
197 /* report all direct connections */
199 for (i = 0; i <= HighestFd; i++) {
200 unsigned int conClass;
202 if (!(acptr = LocalClientArray[i])) /* Local Connection? */
204 if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
205 !IsAnOper(acptr) && (acptr != sptr))
207 if (!doall && wilds && match(tname, acptr->name))
209 if (!dow && 0 != ircd_strcmp(tname, acptr->name))
212 conClass = get_client_class(acptr);
214 switch (acptr->status) {
215 case STAT_CONNECTING:
216 send_reply(sptr, RPL_TRACECONNECTING, conClass, acptr->name);
220 send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, acptr->name);
226 case STAT_UNKNOWN_USER:
227 send_reply(sptr, RPL_TRACEUNKNOWN, conClass,
228 get_client_name(acptr, HIDE_IP));
231 case STAT_UNKNOWN_SERVER:
232 send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server");
236 /* Only opers see users if there is a wildcard
237 but anyone can see all the opers. */
238 if ((IsAnOper(sptr) && (MyUser(sptr) ||
239 !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) {
241 send_reply(sptr, RPL_TRACEOPERATOR, conClass,
242 get_client_name(acptr, HIDE_IP),
243 CurrentTime - acptr->lasttime);
245 send_reply(sptr, RPL_TRACEUSER, conClass,
246 get_client_name(acptr, HIDE_IP),
247 CurrentTime - acptr->lasttime);
252 * Connection is a server
254 * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
256 * class Class the server is in
257 * nS Number of servers reached via this link
258 * nC Number of clients reached via this link
259 * name Name of the server linked
260 * ConnBy Who established this link
261 * last Seconds since we got something from this link
262 * age Seconds this link has been alive
264 * Additional comments etc...... -Cym-<cym@acrux.net>
268 if (acptr->serv->user)
269 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
270 link_u[i], acptr->name,
271 (*acptr->serv->by) ? acptr->serv->by : "*",
272 acptr->serv->user->username, acptr->serv->user->host,
273 CurrentTime - acptr->lasttime,
274 CurrentTime - acptr->serv->timestamp);
276 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
277 link_u[i], acptr->name,
278 (*acptr->serv->by) ? acptr->serv->by : "*", "*",
279 me.name, CurrentTime - acptr->lasttime,
280 CurrentTime - acptr->serv->timestamp);
283 default: /* We actually shouldn't come here, -msa */
284 send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP));
290 * Add these lines to summarize the above which can get rather long
291 * and messy when done remotely - Avalon
293 if (!IsAnOper(sptr) || !cnt) {
295 /* let the user have some idea that its at the end of the trace */
296 send_reply(sptr, RPL_TRACESERVER, 0, link_s[me.fd],
297 link_u[me.fd], "<No_match>", *(me.serv->by) ?
298 me.serv->by : "*", "*", me.name, 0, 0);
301 for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
302 if (Links(cltmp) > 0)
303 send_reply(sptr, RPL_TRACECLASS, ConClass(cltmp), Links(cltmp));
308 * ms_trace - server message handler
310 * parv[0] = sender prefix
311 * parv[1] = nick or servername
312 * parv[2] = 'target' servername
314 int ms_trace(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
317 struct Client *acptr;
318 struct ConfClass *cltmp;
320 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
321 int cnt = 0, wilds, dow;
323 if (parc < 2 || BadPtr(parv[1])) {
324 /* just "TRACE" without parameters. Must be from local client */
329 } else if (parc < 3 || BadPtr(parv[2])) {
330 /* No target specified. Make one before propagating. */
333 if ((acptr = find_match_server(parv[1])) ||
334 ((acptr = FindClient(parv[1])) && !MyUser(acptr))) {
336 parv[2] = acptr->user->server->name;
338 parv[2] = acptr->name;
342 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr),
343 "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH)
348 /* Got "TRACE <tname> :<target>" */
350 if (MyUser(sptr) || Protocol(cptr) < 10)
351 acptr = find_match_server(parv[2]);
353 acptr = FindNServer(parv[2]);
354 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc,
355 parv)) == HUNTED_NOSUCH)
360 if (i == HUNTED_PASS) {
362 acptr = next_client(GlobalClientList, tname);
365 send_reply(sptr, RPL_TRACELINK,
367 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>"
369 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>",
370 (acptr && acptr->from->serv) ? acptr->from->serv->timestamp : 0
372 ); /* I really could do without GODMODE */
376 doall = (parv[1] && (parc > 1)) ? !match(tname, me.name) : 1;
377 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
378 dow = wilds || doall;
380 /* Don't give (long) remote listings to lusers */
381 if (dow && !MyConnect(sptr) && !IsAnOper(sptr))
384 for (i = 0; i < MAXCONNECTIONS; i++)
385 link_s[i] = 0, link_u[i] = 0;
388 for (acptr = GlobalClientList; acptr; acptr = acptr->next) {
390 link_u[acptr->from->fd]++;
391 else if (IsServer(acptr))
392 link_s[acptr->from->fd]++;
396 /* report all direct connections */
398 for (i = 0; i <= HighestFd; i++) {
399 unsigned int conClass;
401 if (!(acptr = LocalClientArray[i])) /* Local Connection? */
403 if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
404 !IsAnOper(acptr) && (acptr != sptr))
406 if (!doall && wilds && match(tname, acptr->name))
408 if (!dow && 0 != ircd_strcmp(tname, acptr->name))
410 conClass = get_client_class(acptr);
412 switch (acptr->status) {
413 case STAT_CONNECTING:
414 send_reply(sptr, RPL_TRACECONNECTING, conClass, acptr->name);
418 send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, acptr->name);
424 case STAT_UNKNOWN_USER:
425 send_reply(sptr, RPL_TRACEUNKNOWN, conClass,
426 get_client_name(acptr, HIDE_IP));
429 case STAT_UNKNOWN_SERVER:
430 send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server");
434 /* Only opers see users if there is a wildcard
435 but anyone can see all the opers. */
436 if ((IsAnOper(sptr) && (MyUser(sptr) ||
437 !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) {
439 send_reply(sptr, RPL_TRACEOPERATOR, conClass,
440 get_client_name(acptr, HIDE_IP),
441 CurrentTime - acptr->lasttime);
443 send_reply(sptr, RPL_TRACEUSER, conClass,
444 get_client_name(acptr, HIDE_IP),
445 CurrentTime - acptr->lasttime);
450 * Connection is a server
452 * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
454 * class Class the server is in
455 * nS Number of servers reached via this link
456 * nC Number of clients reached via this link
457 * name Name of the server linked
458 * ConnBy Who established this link
459 * last Seconds since we got something from this link
460 * age Seconds this link has been alive
462 * Additional comments etc...... -Cym-<cym@acrux.net>
466 if (acptr->serv->user)
467 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
468 link_u[i], acptr->name,
469 (*acptr->serv->by) ? acptr->serv->by : "*",
470 acptr->serv->user->username, acptr->serv->user->host,
471 CurrentTime - acptr->lasttime,
472 CurrentTime - acptr->serv->timestamp);
474 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
475 link_u[i], acptr->name,
476 (*acptr->serv->by) ? acptr->serv->by : "*", "*",
477 me.name, CurrentTime - acptr->lasttime,
478 CurrentTime - acptr->serv->timestamp);
481 default: /* We actually shouldn't come here, -msa */
482 send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP));
488 * Add these lines to summarize the above which can get rather long
489 * and messy when done remotely - Avalon
491 if (!IsAnOper(sptr) || !cnt) {
493 /* let the user have some idea that its at the end of the trace */
494 send_reply(sptr, RPL_TRACESERVER, 0, link_s[me.fd],
495 link_u[me.fd], "<No_match>", *(me.serv->by) ?
496 me.serv->by : "*", "*", me.name, 0, 0);
499 for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
500 if (Links(cltmp) > 0)
501 send_reply(sptr, RPL_TRACECLASS, ConClass(cltmp), Links(cltmp));
506 * mo_trace - oper message handler
508 * parv[0] = sender prefix
509 * parv[1] = nick or servername
510 * parv[2] = 'target' servername
512 int mo_trace(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
515 struct Client *acptr;
516 struct ConfClass *cltmp;
518 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
519 int cnt = 0, wilds, dow;
521 if (parc < 2 || BadPtr(parv[1])) {
522 /* just "TRACE" without parameters. Must be from local client */
527 } else if (parc < 3 || BadPtr(parv[2])) {
528 /* No target specified. Make one before propagating. */
531 if ((acptr = find_match_server(parv[1])) ||
532 ((acptr = FindClient(parv[1])) && !MyUser(acptr))) {
534 parv[2] = acptr->user->server->name;
536 parv[2] = acptr->name;
539 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, IsServer(acptr),
540 "%s :%C", 2, parc, parv)) == HUNTED_NOSUCH)
545 /* Got "TRACE <tname> :<target>" */
547 if (MyUser(sptr) || Protocol(cptr) < 10)
548 acptr = find_match_server(parv[2]);
550 acptr = FindNServer(parv[2]);
551 if ((i = hunt_server_cmd(sptr, CMD_TRACE, cptr, 0, "%s :%C", 2, parc,
552 parv)) == HUNTED_NOSUCH)
557 if (i == HUNTED_PASS) {
559 acptr = next_client(GlobalClientList, tname);
562 send_reply(sptr, RPL_TRACELINK,
564 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>"
566 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>",
567 (acptr && acptr->from->serv) ? acptr->from->serv->timestamp : 0
569 ); /* I really could do without GODMODE */
573 doall = (parv[1] && (parc > 1)) ? !match(tname, me.name) : 1;
574 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
575 dow = wilds || doall;
577 /* Don't give (long) remote listings to lusers */
578 if (dow && !MyConnect(sptr) && !IsAnOper(sptr))
581 for (i = 0; i < MAXCONNECTIONS; i++)
582 link_s[i] = 0, link_u[i] = 0;
585 for (acptr = GlobalClientList; acptr; acptr = acptr->next) {
587 link_u[acptr->from->fd]++;
588 else if (IsServer(acptr))
589 link_s[acptr->from->fd]++;
593 /* report all direct connections */
595 for (i = 0; i <= HighestFd; i++) {
596 unsigned int conClass;
598 if (!(acptr = LocalClientArray[i])) /* Local Connection? */
600 if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
601 !IsAnOper(acptr) && (acptr != sptr))
603 if (!doall && wilds && match(tname, acptr->name))
605 if (!dow && 0 != ircd_strcmp(tname, acptr->name))
607 conClass = get_client_class(acptr);
609 switch (acptr->status) {
610 case STAT_CONNECTING:
611 send_reply(sptr, RPL_TRACECONNECTING, conClass, acptr->name);
615 send_reply(sptr, RPL_TRACEHANDSHAKE, conClass, acptr->name);
621 case STAT_UNKNOWN_USER:
622 send_reply(sptr, RPL_TRACEUNKNOWN, conClass,
623 get_client_name(acptr, HIDE_IP));
626 case STAT_UNKNOWN_SERVER:
627 send_reply(sptr, RPL_TRACEUNKNOWN, conClass, "Unknown Server");
631 /* Only opers see users if there is a wildcard
632 but anyone can see all the opers. */
633 if ((IsAnOper(sptr) && (MyUser(sptr) ||
634 !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr)) {
636 send_reply(sptr, RPL_TRACEOPERATOR, conClass,
637 get_client_name(acptr, HIDE_IP),
638 CurrentTime - acptr->lasttime);
640 send_reply(sptr, RPL_TRACEUSER, conClass,
641 get_client_name(acptr, HIDE_IP),
642 CurrentTime - acptr->lasttime);
647 * Connection is a server
649 * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
651 * class Class the server is in
652 * nS Number of servers reached via this link
653 * nC Number of clients reached via this link
654 * name Name of the server linked
655 * ConnBy Who established this link
656 * last Seconds since we got something from this link
657 * age Seconds this link has been alive
659 * Additional comments etc...... -Cym-<cym@acrux.net>
663 if (acptr->serv->user)
664 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
665 link_u[i], acptr->name,
666 (*acptr->serv->by) ? acptr->serv->by : "*",
667 acptr->serv->user->username, acptr->serv->user->host,
668 CurrentTime - acptr->lasttime,
669 CurrentTime - acptr->serv->timestamp);
671 send_reply(sptr, RPL_TRACESERVER, conClass, link_s[i],
672 link_u[i], acptr->name,
673 (*acptr->serv->by) ? acptr->serv->by : "*", "*",
674 me.name, CurrentTime - acptr->lasttime,
675 CurrentTime - acptr->serv->timestamp);
678 default: /* We actually shouldn't come here, -msa */
679 send_reply(sptr, RPL_TRACENEWTYPE, get_client_name(acptr, HIDE_IP));
685 * Add these lines to summarize the above which can get rather long
686 * and messy when done remotely - Avalon
688 if (!IsAnOper(sptr) || !cnt) {
690 /* let the user have some idea that its at the end of the trace */
691 send_reply(sptr, RPL_TRACESERVER, 0, link_s[me.fd],
692 link_u[me.fd], "<No_match>", *(me.serv->by) ?
693 me.serv->by : "*", "*", me.name, 0, 0);
696 for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
697 if (Links(cltmp) > 0)
698 send_reply(sptr, RPL_TRACECLASS, ConClass(cltmp), Links(cltmp));
707 * parv[0] = sender prefix
708 * parv[1] = nick or servername
709 * parv[2] = 'target' servername
711 int m_trace(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
714 struct Client *acptr;
715 struct ConfClass *cltmp;
717 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
718 int cnt = 0, wilds, dow;
720 if (parc < 2 || BadPtr(parv[1]))
722 /* just "TRACE" without parameters. Must be from local client */
728 else if (parc < 3 || BadPtr(parv[2]))
730 /* No target specified. Make one before propagating. */
733 if ((acptr = find_match_server(parv[1])) ||
734 ((acptr = FindClient(parv[1])) && !MyUser(acptr)))
737 parv[2] = acptr->user->server->name;
739 parv[2] = acptr->name;
742 if ((i = hunt_server(IsServer(acptr), cptr, sptr, /* XXX DEAD */
743 "%s%s " TOK_TRACE " %s :%s", 2, parc, parv)) == HUNTED_NOSUCH)
751 /* Got "TRACE <tname> :<target>" */
753 if (MyUser(sptr) || Protocol(cptr) < 10)
754 acptr = find_match_server(parv[2]);
756 acptr = FindNServer(parv[2]);
757 if ((i = hunt_server(0, cptr, sptr, /* XXX DEAD */
758 "%s%s " TOK_TRACE " %s :%s", 2, parc, parv)) == HUNTED_NOSUCH)
763 if (i == HUNTED_PASS)
766 acptr = next_client(GlobalClientList, tname);
769 sendto_one(sptr, rpl_str(RPL_TRACELINK), me.name, parv[0], /* XXX DEAD */
771 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>");
773 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>",
774 (acptr && acptr->from->serv) ? acptr->from->serv->timestamp : 0);
779 doall = (parv[1] && (parc > 1)) ? !match(tname, me.name) : TRUE;
780 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
781 dow = wilds || doall;
783 /* Don't give (long) remote listings to lusers */
784 if (dow && !MyConnect(sptr) && !IsAnOper(sptr))
787 for (i = 0; i < MAXCONNECTIONS; i++)
788 link_s[i] = 0, link_u[i] = 0;
792 for (acptr = GlobalClientList; acptr; acptr = acptr->next) {
794 link_u[acptr->from->fd]++;
795 else if (IsServer(acptr))
796 link_s[acptr->from->fd]++;
800 /* report all direct connections */
802 for (i = 0; i <= HighestFd; i++)
805 unsigned int conClass;
807 if (!(acptr = LocalClientArray[i])) /* Local Connection? */
809 if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
810 !IsAnOper(acptr) && (acptr != sptr))
812 if (!doall && wilds && match(tname, acptr->name))
814 if (!dow && 0 != ircd_strcmp(tname, acptr->name))
816 conClass = get_client_class(acptr);
818 switch (acptr->status)
820 case STAT_CONNECTING:
821 sendto_one(sptr, rpl_str(RPL_TRACECONNECTING), /* XXX DEAD */
822 me.name, parv[0], conClass, name);
826 sendto_one(sptr, rpl_str(RPL_TRACEHANDSHAKE), /* XXX DEAD */
827 me.name, parv[0], conClass, name);
833 case STAT_UNKNOWN_USER:
834 case STAT_UNKNOWN_SERVER:
835 sendto_one(sptr, rpl_str(RPL_TRACEUNKNOWN), /* XXX DEAD */
836 me.name, parv[0], conClass, name);
840 /* Only opers see users if there is a wildcard
841 but anyone can see all the opers. */
842 if ((IsAnOper(sptr) && (MyUser(sptr) ||
843 !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr))
846 sendto_one(sptr, rpl_str(RPL_TRACEOPERATOR), /* XXX DEAD */
847 me.name, parv[0], conClass, name, CurrentTime - acptr->lasttime);
849 sendto_one(sptr, rpl_str(RPL_TRACEUSER), /* XXX DEAD */
850 me.name, parv[0], conClass, name, CurrentTime - acptr->lasttime);
855 * Connection is a server
857 * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
859 * class Class the server is in
860 * nS Number of servers reached via this link
861 * nC Number of clients reached via this link
862 * name Name of the server linked
863 * ConnBy Who established this link
864 * last Seconds since we got something from this link
865 * age Seconds this link has been alive
867 * Additional comments etc...... -Cym-<cym@acrux.net>
871 if (acptr->serv->user)
872 sendto_one(sptr, rpl_str(RPL_TRACESERVER), /* XXX DEAD */
873 me.name, parv[0], conClass, link_s[i],
874 link_u[i], name, (*acptr->serv->by) ? acptr->serv->by : "*",
875 acptr->serv->user->username, acptr->serv->user->host,
876 CurrentTime - acptr->lasttime,
877 CurrentTime - acptr->serv->timestamp);
879 sendto_one(sptr, rpl_str(RPL_TRACESERVER), /* XXX DEAD */
880 me.name, parv[0], conClass, link_s[i],
881 link_u[i], name, (*acptr->serv->by) ? acptr->serv->by : "*", "*",
882 me.name, CurrentTime - acptr->lasttime,
883 CurrentTime - acptr->serv->timestamp);
886 default: /* We actually shouldn't come here, -msa */
887 sendto_one(sptr, rpl_str(RPL_TRACENEWTYPE), me.name, parv[0], name); /* XXX DEAD */
893 * Add these lines to summarize the above which can get rather long
894 * and messy when done remotely - Avalon
896 if (!IsAnOper(sptr) || !cnt)
899 /* let the user have some idea that its at the end of the trace */
900 sendto_one(sptr, rpl_str(RPL_TRACESERVER), /* XXX DEAD */
901 me.name, parv[0], 0, link_s[me.fd],
902 link_u[me.fd], "<No_match>", *(me.serv->by) ?
903 me.serv->by : "*", "*", me.name, 0, 0);
906 for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
907 if (Links(cltmp) > 0)
908 sendto_one(sptr, rpl_str(RPL_TRACECLASS), me.name, /* XXX DEAD */
909 parv[0], ConClass(cltmp), Links(cltmp));