24 |
|
|
25 |
|
#include "stdinc.h" |
26 |
|
#include "list.h" /* dlink_node/dlink_list */ |
27 |
– |
#include "balloc.h" |
27 |
|
#include "client.h" /* Client */ |
28 |
|
#include "irc_string.h" |
29 |
|
#include "ircd.h" /* me */ |
52 |
|
|
53 |
|
const char *from, *to; |
54 |
|
|
55 |
+ |
static const struct shared_flags |
56 |
+ |
{ |
57 |
+ |
const unsigned int type; |
58 |
+ |
const unsigned char letter; |
59 |
+ |
} flag_table[] = { |
60 |
+ |
{ SHARED_KLINE, 'K' }, |
61 |
+ |
{ SHARED_UNKLINE, 'U' }, |
62 |
+ |
{ SHARED_XLINE, 'X' }, |
63 |
+ |
{ SHARED_UNXLINE, 'Y' }, |
64 |
+ |
{ SHARED_RESV, 'Q' }, |
65 |
+ |
{ SHARED_UNRESV, 'R' }, |
66 |
+ |
{ SHARED_LOCOPS, 'L' }, |
67 |
+ |
{ SHARED_DLINE, 'D' }, |
68 |
+ |
{ SHARED_UNDLINE, 'E' }, |
69 |
+ |
{ 0, '\0' } |
70 |
+ |
}; |
71 |
+ |
|
72 |
+ |
/* |
73 |
+ |
* inputs - pointer to client requesting confitem report |
74 |
+ |
* - ConfType to report |
75 |
+ |
* output - none |
76 |
+ |
* side effects - |
77 |
+ |
*/ |
78 |
+ |
static void |
79 |
+ |
report_confitem_types(struct Client *source_p, enum maskitem_type type) |
80 |
+ |
{ |
81 |
+ |
dlink_node *ptr = NULL, *dptr = NULL; |
82 |
+ |
struct MaskItem *conf = NULL; |
83 |
+ |
const struct ClassItem *class = NULL; |
84 |
+ |
const struct shared_flags *shared = NULL; |
85 |
+ |
char buf[12]; |
86 |
+ |
char *p = NULL; |
87 |
+ |
|
88 |
+ |
switch (type) |
89 |
+ |
{ |
90 |
+ |
case CONF_XLINE: |
91 |
+ |
DLINK_FOREACH(ptr, xconf_items.head) |
92 |
+ |
{ |
93 |
+ |
conf = ptr->data; |
94 |
+ |
|
95 |
+ |
sendto_one(source_p, form_str(RPL_STATSXLINE), |
96 |
+ |
me.name, source_p->name, |
97 |
+ |
conf->until ? 'x': 'X', conf->count, |
98 |
+ |
conf->name, conf->reason); |
99 |
+ |
} |
100 |
+ |
break; |
101 |
+ |
|
102 |
+ |
case CONF_ULINE: |
103 |
+ |
shared = flag_table; |
104 |
+ |
DLINK_FOREACH(ptr, uconf_items.head) |
105 |
+ |
{ |
106 |
+ |
conf = ptr->data; |
107 |
+ |
|
108 |
+ |
p = buf; |
109 |
+ |
|
110 |
+ |
*p++ = 'c'; |
111 |
+ |
for (; shared->type; ++shared) |
112 |
+ |
if (shared->type & conf->flags) |
113 |
+ |
*p++ = shared->letter; |
114 |
+ |
else |
115 |
+ |
*p++ = ToLower(shared->letter); |
116 |
+ |
|
117 |
+ |
sendto_one(source_p, form_str(RPL_STATSULINE), |
118 |
+ |
me.name, source_p->name, conf->name, |
119 |
+ |
conf->user?conf->user: "*", |
120 |
+ |
conf->host?conf->host: "*", buf); |
121 |
+ |
} |
122 |
+ |
|
123 |
+ |
shared = flag_table; |
124 |
+ |
DLINK_FOREACH(ptr, cluster_items.head) |
125 |
+ |
{ |
126 |
+ |
conf = ptr->data; |
127 |
+ |
|
128 |
+ |
p = buf; |
129 |
+ |
|
130 |
+ |
*p++ = 'C'; |
131 |
+ |
for (; shared->type; ++shared) |
132 |
+ |
if (shared->type & conf->flags) |
133 |
+ |
*p++ = shared->letter; |
134 |
+ |
else |
135 |
+ |
*p++ = ToLower(shared->letter); |
136 |
+ |
|
137 |
+ |
sendto_one(source_p, form_str(RPL_STATSULINE), |
138 |
+ |
me.name, source_p->name, conf->name, |
139 |
+ |
"*", "*", buf); |
140 |
+ |
} |
141 |
+ |
|
142 |
+ |
break; |
143 |
+ |
|
144 |
+ |
case CONF_OPER: |
145 |
+ |
DLINK_FOREACH(ptr, oconf_items.head) |
146 |
+ |
{ |
147 |
+ |
conf = ptr->data; |
148 |
+ |
|
149 |
+ |
/* Don't allow non opers to see oper privs */ |
150 |
+ |
if (HasUMode(source_p, UMODE_OPER)) |
151 |
+ |
sendto_one(source_p, form_str(RPL_STATSOLINE), |
152 |
+ |
me.name, source_p->name, 'O', conf->count, conf->user, conf->host, |
153 |
+ |
conf->name, oper_privs_as_string(conf->port), |
154 |
+ |
conf->class ? conf->class->name : "<default>"); |
155 |
+ |
else |
156 |
+ |
sendto_one(source_p, form_str(RPL_STATSOLINE), |
157 |
+ |
me.name, source_p->name, 'O', conf->count, conf->user, conf->host, |
158 |
+ |
conf->name, "0", |
159 |
+ |
conf->class ? conf->class->name : "<default>"); |
160 |
+ |
} |
161 |
+ |
break; |
162 |
+ |
|
163 |
+ |
case CONF_CLASS: |
164 |
+ |
DLINK_FOREACH(ptr, class_get_list()->head) |
165 |
+ |
{ |
166 |
+ |
class = ptr->data; |
167 |
+ |
sendto_one(source_p, form_str(RPL_STATSYLINE), |
168 |
+ |
me.name, source_p->name, 'Y', |
169 |
+ |
class->name, class->ping_freq, |
170 |
+ |
class->con_freq, |
171 |
+ |
class->max_total, class->max_sendq, |
172 |
+ |
class->max_recvq, |
173 |
+ |
class->ref_count, |
174 |
+ |
class->number_per_cidr, class->cidr_bitlen_ipv4, |
175 |
+ |
class->number_per_cidr, class->cidr_bitlen_ipv6, |
176 |
+ |
class->active ? "active" : "disabled"); |
177 |
+ |
} |
178 |
+ |
break; |
179 |
+ |
|
180 |
+ |
case CONF_SERVICE: |
181 |
+ |
DLINK_FOREACH(ptr, service_items.head) |
182 |
+ |
{ |
183 |
+ |
conf = ptr->data; |
184 |
+ |
sendto_one(source_p, form_str(RPL_STATSSERVICE), |
185 |
+ |
me.name, source_p->name, 'S', "*", conf->name, 0, 0); |
186 |
+ |
} |
187 |
+ |
break; |
188 |
+ |
|
189 |
+ |
case CONF_SERVER: |
190 |
+ |
DLINK_FOREACH(ptr, server_items.head) |
191 |
+ |
{ |
192 |
+ |
p = buf; |
193 |
+ |
conf = ptr->data; |
194 |
+ |
|
195 |
+ |
buf[0] = '\0'; |
196 |
+ |
|
197 |
+ |
if (IsConfAllowAutoConn(conf)) |
198 |
+ |
*p++ = 'A'; |
199 |
+ |
if (IsConfSSL(conf)) |
200 |
+ |
*p++ = 'S'; |
201 |
+ |
if (buf[0] == '\0') |
202 |
+ |
*p++ = '*'; |
203 |
+ |
|
204 |
+ |
*p = '\0'; |
205 |
+ |
|
206 |
+ |
/* |
207 |
+ |
* Allow admins to see actual ips unless hide_server_ips is enabled |
208 |
+ |
*/ |
209 |
+ |
if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN)) |
210 |
+ |
sendto_one(source_p, form_str(RPL_STATSCLINE), |
211 |
+ |
me.name, source_p->name, 'C', conf->host, |
212 |
+ |
buf, conf->name, conf->port, |
213 |
+ |
conf->class ? conf->class->name : "<default>"); |
214 |
+ |
else |
215 |
+ |
sendto_one(source_p, form_str(RPL_STATSCLINE), |
216 |
+ |
me.name, source_p->name, 'C', |
217 |
+ |
"*@127.0.0.1", buf, conf->name, conf->port, |
218 |
+ |
conf->class ? conf->class->name : "<default>"); |
219 |
+ |
} |
220 |
+ |
break; |
221 |
+ |
|
222 |
+ |
case CONF_HUB: |
223 |
+ |
DLINK_FOREACH(ptr, server_items.head) |
224 |
+ |
{ |
225 |
+ |
conf = ptr->data; |
226 |
+ |
|
227 |
+ |
DLINK_FOREACH(dptr, conf->hub_list.head) |
228 |
+ |
sendto_one(source_p, form_str(RPL_STATSHLINE), me.name, |
229 |
+ |
source_p->name, 'H', dptr->data, conf->name, 0, "*"); |
230 |
+ |
} |
231 |
+ |
|
232 |
+ |
DLINK_FOREACH(ptr, server_items.head) |
233 |
+ |
{ |
234 |
+ |
conf = ptr->data; |
235 |
+ |
|
236 |
+ |
DLINK_FOREACH(dptr, conf->leaf_list.head) |
237 |
+ |
sendto_one(source_p, form_str(RPL_STATSLLINE), me.name, |
238 |
+ |
source_p->name, 'L', dptr->data, conf->name, 0, "*"); |
239 |
+ |
} |
240 |
+ |
|
241 |
+ |
break; |
242 |
+ |
|
243 |
+ |
default: |
244 |
+ |
break; |
245 |
+ |
} |
246 |
+ |
} |
247 |
+ |
|
248 |
+ |
/* report_resv() |
249 |
+ |
* |
250 |
+ |
* inputs - pointer to client pointer to report to. |
251 |
+ |
* output - NONE |
252 |
+ |
* side effects - report all resvs to client. |
253 |
+ |
*/ |
254 |
+ |
static void |
255 |
+ |
report_resv(struct Client *source_p) |
256 |
+ |
{ |
257 |
+ |
dlink_node *ptr = NULL; |
258 |
+ |
struct MaskItem *conf = NULL; |
259 |
+ |
|
260 |
+ |
DLINK_FOREACH(ptr, resv_channel_list.head) |
261 |
+ |
{ |
262 |
+ |
conf = ptr->data; |
263 |
+ |
sendto_one(source_p, form_str(RPL_STATSQLINE), |
264 |
+ |
me.name, source_p->name, |
265 |
+ |
conf->until ? 'q' : 'Q', conf->count, |
266 |
+ |
conf->name, conf->reason); |
267 |
+ |
} |
268 |
+ |
|
269 |
+ |
DLINK_FOREACH(ptr, nresv_items.head) |
270 |
+ |
{ |
271 |
+ |
conf = ptr->data; |
272 |
+ |
sendto_one(source_p, form_str(RPL_STATSQLINE), |
273 |
+ |
me.name, source_p->name, |
274 |
+ |
conf->until ? 'q' : 'Q', conf->count, |
275 |
+ |
conf->name, conf->reason); |
276 |
+ |
} |
277 |
+ |
} |
278 |
+ |
|
279 |
|
/* |
280 |
|
* This is part of the STATS replies. There is no offical numeric for this |
281 |
|
* since this isnt an official command, in much the same way as HASH isnt. |
317 |
|
rup = 1; |
318 |
|
|
319 |
|
sendto_one(source_p, |
320 |
< |
":%s %d %s R :CPU Secs %d:%d User %d:%d System %d:%d", |
320 |
> |
":%s %d %s R :CPU Secs %d:%02d User %d:%02d System %d:%02d", |
321 |
|
me.name, RPL_STATSDEBUG, source_p->name, (int)(secs/60), (int)(secs%60), |
322 |
|
(int)(rus.ru_utime.tv_sec/60), (int)(rus.ru_utime.tv_sec%60), |
323 |
|
(int)(rus.ru_stime.tv_sec/60), (int)(rus.ru_stime.tv_sec%60)); |
494 |
|
count_whowas_memory(&wwu, &wwm); |
495 |
|
watch_count_memory(&watch_list_headers, &watch_list_memory); |
496 |
|
|
497 |
< |
sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%u) entries %d(%u)", |
497 |
> |
sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%llu) entries %d(%u)", |
498 |
|
me.name, RPL_STATSDEBUG, source_p->name, watch_list_headers, |
499 |
|
watch_list_memory, watch_list_entries, |
500 |
|
watch_list_entries * sizeof(dlink_node) * 2); |
523 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
524 |
|
class_count, (unsigned long long)(class_count * sizeof(struct ClassItem))); |
525 |
|
|
526 |
< |
sendto_one(source_p, ":%s %d %s z :Channels %uu(%llu) Topics %u(%u)", |
526 |
> |
sendto_one(source_p, ":%s %d %s z :Channels %u(%llu) Topics %u(%u)", |
527 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
528 |
|
dlink_list_length(&global_channel_list), |
529 |
|
channel_memory, topic_count, topic_count * |
588 |
|
me.name, RPL_STATSDEBUG, source_p->name, remote_client_count, |
589 |
|
remote_client_memory_used); |
590 |
|
|
368 |
– |
block_heap_report_stats(source_p); |
369 |
– |
|
591 |
|
sendto_one(source_p, |
592 |
|
":%s %d %s z :TOTAL: %llu", |
593 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
708 |
|
|
709 |
|
conf = arec->conf; |
710 |
|
|
711 |
< |
sendto_one(source_p, form_str(RPL_STATSDLINE), |
712 |
< |
from, to, 'e', conf->host, conf->reason /* XXX */); |
711 |
> |
sendto_one(source_p, form_str(RPL_STATSDLINE), from, to, 'e', |
712 |
> |
conf->host, ""); |
713 |
|
} |
714 |
|
} |
715 |
|
} |
839 |
|
const struct MaskItem *conf = arec->conf; |
840 |
|
|
841 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), |
842 |
< |
from, to, "G", |
842 |
> |
from, to, 'G', |
843 |
|
conf->host ? conf->host : "*", |
844 |
|
conf->user ? conf->user : "*", |
845 |
< |
conf->reason ? conf->reason : "No reason"); |
845 |
> |
conf->reason ? conf->reason : CONF_NOREASON); |
846 |
|
} |
847 |
|
} |
848 |
|
} |
866 |
|
static const char * |
867 |
|
show_iline_prefix(const struct Client *sptr, const struct MaskItem *conf) |
868 |
|
{ |
869 |
< |
static char prefix_of_host[USERLEN + 14]; |
869 |
> |
static char prefix_of_host[USERLEN + 15]; |
870 |
|
char *prefix_ptr = prefix_of_host; |
871 |
|
|
872 |
+ |
if (IsConfWebIRC(conf)) |
873 |
+ |
*prefix_ptr++ = '<'; |
874 |
|
if (IsNoTilde(conf)) |
875 |
|
*prefix_ptr++ = '-'; |
876 |
|
if (IsLimitIp(conf)) |
994 |
|
{ |
995 |
|
struct MaskItem *conf = NULL; |
996 |
|
unsigned int i = 0; |
997 |
< |
const char *p = NULL; |
997 |
> |
char c = '\0'; |
998 |
|
dlink_node *ptr = NULL; |
999 |
|
|
1000 |
|
if (tkline) |
1001 |
< |
p = "k"; |
1001 |
> |
c = 'k'; |
1002 |
|
else |
1003 |
< |
p = "K"; |
1003 |
> |
c = 'K'; |
1004 |
|
|
1005 |
|
for (i = 0; i < ATABLE_SIZE; ++i) |
1006 |
|
{ |
1019 |
|
|
1020 |
|
if (HasUMode(client_p, UMODE_OPER)) |
1021 |
|
sendto_one(client_p, form_str(RPL_STATSKLINE), me.name, |
1022 |
< |
client_p->name, p, conf->host, conf->user, |
1022 |
> |
client_p->name, c, conf->host, conf->user, |
1023 |
|
conf->reason); |
1024 |
|
else |
1025 |
|
sendto_one(client_p, form_str(RPL_STATSKLINE), me.name, |
1026 |
< |
client_p->name, p, conf->host, conf->user, |
1026 |
> |
client_p->name, c, conf->host, conf->user, |
1027 |
|
conf->reason); |
1028 |
|
} |
1029 |
|
} |
1060 |
|
return; |
1061 |
|
|
1062 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), from, |
1063 |
< |
to, "k", conf->host, conf->user, conf->reason); |
1063 |
> |
to, 'k', conf->host, conf->user, conf->reason); |
1064 |
|
} |
1065 |
|
/* Theyre opered, or allowed to see all klines */ |
1066 |
|
else { |
1100 |
|
return; |
1101 |
|
|
1102 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), from, |
1103 |
< |
to, "K", conf->host, conf->user, conf->reason); |
1103 |
> |
to, 'K', conf->host, conf->user, conf->reason); |
1104 |
|
} |
1105 |
|
/* Theyre opered, or allowed to see all klines */ |
1106 |
< |
else { |
1106 |
> |
else |
1107 |
|
report_Klines(source_p, 0); |
885 |
– |
report_confitem_types(source_p, CONF_RKLINE); |
886 |
– |
} |
1108 |
|
} |
1109 |
|
|
1110 |
|
static void |
1142 |
|
continue; |
1143 |
|
|
1144 |
|
if (MyClient(source_p) && HasUMode(source_p, UMODE_OPER)) |
1145 |
< |
sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %d", |
1145 |
> |
sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %u", |
1146 |
|
from, RPL_STATSDEBUG, to, |
1147 |
|
HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O', |
1148 |
|
oper_privs_as_string(target_p->localClient->operflags), |
1149 |
|
target_p->name, target_p->username, target_p->host, |
1150 |
< |
(int)(CurrentTime - target_p->localClient->last_privmsg)); |
1150 |
> |
idle_time_get(source_p, target_p)); |
1151 |
|
else |
1152 |
< |
sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %d", |
1152 |
> |
sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %u", |
1153 |
|
from, RPL_STATSDEBUG, to, |
1154 |
|
HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O', |
1155 |
|
target_p->name, target_p->username, target_p->host, |
1156 |
< |
(int)(CurrentTime - target_p->localClient->last_privmsg)); |
1156 |
> |
idle_time_get(source_p, target_p)); |
1157 |
|
} |
1158 |
|
|
1159 |
< |
sendto_one(source_p, ":%s %d %s p :%lu OPER(s)", |
1159 |
> |
sendto_one(source_p, ":%s %d %s p :%u OPER(s)", |
1160 |
|
from, RPL_STATSDEBUG, to, dlink_list_length(&oper_list)); |
1161 |
|
} |
1162 |
|
|
1187 |
|
{ |
1188 |
|
const struct Client *target_p = NULL; |
1189 |
|
const dlink_node *ptr = NULL; |
969 |
– |
struct ServerStatistics *sp; |
1190 |
|
struct ServerStatistics tmp; |
1191 |
+ |
struct ServerStatistics *sp = &tmp; |
1192 |
|
|
972 |
– |
sp = &tmp; |
1193 |
|
memcpy(sp, &ServerStats, sizeof(struct ServerStatistics)); |
1194 |
|
|
1195 |
|
/* |
1300 |
|
stats_gecos(struct Client *source_p, int parc, char *parv[]) |
1301 |
|
{ |
1302 |
|
report_confitem_types(source_p, CONF_XLINE); |
1083 |
– |
report_confitem_types(source_p, CONF_RXLINE); |
1303 |
|
} |
1304 |
|
|
1305 |
|
static void |
1326 |
|
{ |
1327 |
|
struct Client *target_p = ptr->data; |
1328 |
|
|
1329 |
+ |
if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services) |
1330 |
+ |
if (!HasUMode(source_p, UMODE_OPER)) |
1331 |
+ |
continue; |
1332 |
+ |
|
1333 |
|
sendB += target_p->localClient->send.bytes; |
1334 |
|
recvB += target_p->localClient->recv.bytes; |
1335 |
|
|
1397 |
|
|
1398 |
|
if (!irccmp(name, from)) |
1399 |
|
*doall = 2; |
1400 |
< |
else if (match(name, from)) |
1400 |
> |
else if (!match(name, from)) |
1401 |
|
*doall = 1; |
1402 |
|
|
1403 |
|
*wilds = has_wildcards(name); |
1429 |
|
!(MyConnect(source_p) && HasUMode(source_p, UMODE_OPER)) && |
1430 |
|
!HasUMode(target_p, UMODE_OPER) && (target_p != source_p)) |
1431 |
|
continue; |
1432 |
< |
if (!doall && wilds && !match(name, target_p->name)) |
1432 |
> |
if (!doall && wilds && match(name, target_p->name)) |
1433 |
|
continue; |
1434 |
|
if (!(doall || wilds) && irccmp(name, target_p->name)) |
1435 |
|
continue; |
1564 |
|
{ 'Q', stats_resv, 1, 0 }, |
1565 |
|
{ 'r', stats_usage, 1, 0 }, |
1566 |
|
{ 'R', stats_usage, 1, 0 }, |
1567 |
+ |
{ 's', stats_service, 1, 0 }, |
1568 |
|
{ 'S', stats_service, 1, 0 }, |
1569 |
|
{ 't', stats_tstats, 1, 0 }, |
1570 |
|
{ 'T', stats_tstats, 1, 0 }, |