unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
trace.c (6322B)
1 /* 2 * IRC - Internet Relay Chat, src/modules/trace.c 3 * (C) 2004 The UnrealIRCd Team 4 * 5 * See file AUTHORS in IRC package for additional names of 6 * the programmers. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 1, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 #include "unrealircd.h" 24 25 CMD_FUNC(cmd_trace); 26 27 #define MSG_TRACE "TRACE" 28 29 ModuleHeader MOD_HEADER 30 = { 31 "trace", 32 "5.0", 33 "command /trace", 34 "UnrealIRCd Team", 35 "unrealircd-6", 36 }; 37 38 MOD_INIT() 39 { 40 CommandAdd(modinfo->handle, MSG_TRACE, cmd_trace, MAXPARA, CMD_USER); 41 MARK_AS_OFFICIAL_MODULE(modinfo); 42 return MOD_SUCCESS; 43 } 44 45 MOD_LOAD() 46 { 47 return MOD_SUCCESS; 48 } 49 50 MOD_UNLOAD() 51 { 52 return MOD_SUCCESS; 53 } 54 55 /* 56 ** cmd_trace 57 ** parv[1] = servername 58 */ 59 CMD_FUNC(cmd_trace) 60 { 61 int i; 62 Client *acptr; 63 ConfigItem_class *cltmp; 64 const char *tname; 65 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS]; 66 int cnt = 0, wilds, dow; 67 time_t now; 68 69 /* This is one of the (few) commands that cannot be handled 70 * by labeled-response because responses from multiple servers 71 * are involved. 72 */ 73 labeled_response_inhibit = 1; 74 75 if (parc > 2) 76 if (hunt_server(client, NULL, "TRACE", 2, parc, parv)) 77 return; 78 79 if (parc > 1) 80 tname = parv[1]; 81 else 82 tname = me.name; 83 84 if (!ValidatePermissionsForPath("client:see:trace:global",client,NULL,NULL,NULL)) 85 { 86 if (ValidatePermissionsForPath("client:see:trace:local",client,NULL,NULL,NULL)) 87 { 88 /* local opers may not /TRACE remote servers! */ 89 if (strcasecmp(tname, me.name)) 90 { 91 sendnotice(client, "You can only /TRACE local servers as a locop"); 92 sendnumeric(client, ERR_NOPRIVILEGES); 93 return; 94 } 95 } else { 96 sendnumeric(client, ERR_NOPRIVILEGES); 97 return; 98 } 99 } 100 101 switch (hunt_server(client, NULL, "TRACE", 1, parc, parv)) 102 { 103 case HUNTED_PASS: /* note: gets here only if parv[1] exists */ 104 { 105 Client *ac2ptr; 106 107 ac2ptr = find_client(tname, NULL); 108 sendnumeric(client, RPL_TRACELINK, 109 version, debugmode, tname, ac2ptr->direction->name); 110 return; 111 } 112 case HUNTED_ISME: 113 break; 114 default: 115 return; 116 } 117 118 doall = (parv[1] && (parc > 1)) ? match_simple(tname, me.name) : TRUE; 119 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?'); 120 dow = wilds || doall; 121 122 for (i = 0; i < MAXCONNECTIONS; i++) 123 link_s[i] = 0, link_u[i] = 0; 124 125 126 if (doall) { 127 list_for_each_entry(acptr, &client_list, client_node) 128 { 129 if (acptr->direction->local->fd < 0) 130 continue; 131 if (IsUser(acptr)) 132 link_u[acptr->direction->local->fd]++; 133 else if (IsServer(acptr)) 134 link_s[acptr->direction->local->fd]++; 135 } 136 } 137 138 /* report all direct connections */ 139 140 now = TStime(); 141 list_for_each_entry(acptr, &lclient_list, lclient_node) 142 { 143 const char *name; 144 const char *class; 145 146 if (!ValidatePermissionsForPath("client:see:trace:invisible-users",client,acptr,NULL,NULL) && (acptr != client)) 147 continue; 148 if (!doall && wilds && !match_simple(tname, acptr->name)) 149 continue; 150 if (!dow && mycmp(tname, acptr->name)) 151 continue; 152 name = get_client_name(acptr, FALSE); 153 class = acptr->local->class ? acptr->local->class->name : "default"; 154 switch (acptr->status) 155 { 156 case CLIENT_STATUS_CONNECTING: 157 sendnumeric(client, RPL_TRACECONNECTING, class, name); 158 cnt++; 159 break; 160 161 case CLIENT_STATUS_HANDSHAKE: 162 sendnumeric(client, RPL_TRACEHANDSHAKE, class, name); 163 cnt++; 164 break; 165 166 case CLIENT_STATUS_ME: 167 break; 168 169 case CLIENT_STATUS_UNKNOWN: 170 sendnumeric(client, RPL_TRACEUNKNOWN, class, name); 171 cnt++; 172 break; 173 174 case CLIENT_STATUS_USER: 175 /* Only opers see users if there is a wildcard 176 * but anyone can see all the opers. 177 */ 178 if (ValidatePermissionsForPath("client:see:trace:invisible-users",client,acptr,NULL,NULL) || 179 (!IsInvisible(acptr) && ValidatePermissionsForPath("client:see:trace",client,acptr,NULL,NULL))) 180 { 181 if (ValidatePermissionsForPath("client:see:trace",client,acptr,NULL,NULL) || ValidatePermissionsForPath("client:see:trace:invisible-users",client,acptr,NULL,NULL)) 182 sendnumeric(client, RPL_TRACEOPERATOR, 183 class, acptr->name, 184 GetHost(acptr), 185 (long long)(now - acptr->local->last_msg_received)); 186 else 187 sendnumeric(client, RPL_TRACEUSER, 188 class, acptr->name, 189 acptr->user->realhost, 190 (long long)(now - acptr->local->last_msg_received)); 191 cnt++; 192 } 193 break; 194 195 case CLIENT_STATUS_SERVER: 196 sendnumeric(client, RPL_TRACESERVER, class, acptr->local->fd >= 0 ? link_s[acptr->local->fd] : -1, 197 acptr->local->fd >= 0 ? link_u[acptr->local->fd] : -1, name, *(acptr->server->by) ? 198 acptr->server->by : "*", "*", me.name, 199 (long long)(now - acptr->local->last_msg_received)); 200 cnt++; 201 break; 202 203 case CLIENT_STATUS_LOG: 204 sendnumeric(client, RPL_TRACELOG, LOGFILE, acptr->local->port); 205 cnt++; 206 break; 207 208 case CLIENT_STATUS_TLS_CONNECT_HANDSHAKE: 209 sendnumeric(client, RPL_TRACENEWTYPE, "TLS-Connect-Handshake", name); 210 cnt++; 211 break; 212 213 case CLIENT_STATUS_TLS_ACCEPT_HANDSHAKE: 214 sendnumeric(client, RPL_TRACENEWTYPE, "TLS-Accept-Handshake", name); 215 cnt++; 216 break; 217 218 default: /* ...we actually shouldn't come here... --msa */ 219 sendnumeric(client, RPL_TRACENEWTYPE, "<newtype>", name); 220 cnt++; 221 break; 222 } 223 } 224 /* 225 * Add these lines to summarize the above which can get rather long 226 * and messy when done remotely - Avalon 227 */ 228 if (!ValidatePermissionsForPath("client:see:trace",client,acptr,NULL,NULL) || !cnt) 229 return; 230 231 for (cltmp = conf_class; doall && cltmp; cltmp = cltmp->next) 232 /* if (cltmp->clients > 0) */ 233 sendnumeric(client, RPL_TRACECLASS, cltmp->name ? cltmp->name : "[noname]", cltmp->clients); 234 }