| 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 |
|
/* |
| 249 |
|
* This is part of the STATS replies. There is no offical numeric for this |
| 250 |
|
* since this isnt an official command, in much the same way as HASH isnt. |
| 463 |
|
count_whowas_memory(&wwu, &wwm); |
| 464 |
|
watch_count_memory(&watch_list_headers, &watch_list_memory); |
| 465 |
|
|
| 466 |
< |
sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%u) entries %d(%u)", |
| 466 |
> |
sendto_one(source_p, ":%s %d %s z :WATCH headers %u(%llu) entries %d(%u)", |
| 467 |
|
me.name, RPL_STATSDEBUG, source_p->name, watch_list_headers, |
| 468 |
|
watch_list_memory, watch_list_entries, |
| 469 |
|
watch_list_entries * sizeof(dlink_node) * 2); |
| 492 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
| 493 |
|
class_count, (unsigned long long)(class_count * sizeof(struct ClassItem))); |
| 494 |
|
|
| 495 |
< |
sendto_one(source_p, ":%s %d %s z :Channels %uu(%llu) Topics %u(%u)", |
| 495 |
> |
sendto_one(source_p, ":%s %d %s z :Channels %u(%llu) Topics %u(%u)", |
| 496 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
| 497 |
|
dlink_list_length(&global_channel_list), |
| 498 |
|
channel_memory, topic_count, topic_count * |
| 557 |
|
me.name, RPL_STATSDEBUG, source_p->name, remote_client_count, |
| 558 |
|
remote_client_memory_used); |
| 559 |
|
|
| 368 |
– |
block_heap_report_stats(source_p); |
| 369 |
– |
|
| 560 |
|
sendto_one(source_p, |
| 561 |
|
":%s %d %s z :TOTAL: %llu", |
| 562 |
|
me.name, RPL_STATSDEBUG, source_p->name, |
| 677 |
|
|
| 678 |
|
conf = arec->conf; |
| 679 |
|
|
| 680 |
< |
sendto_one(source_p, form_str(RPL_STATSDLINE), |
| 681 |
< |
from, to, 'e', conf->host, conf->reason /* XXX */); |
| 680 |
> |
sendto_one(source_p, form_str(RPL_STATSDLINE), from, to, 'e', |
| 681 |
> |
conf->host, ""); |
| 682 |
|
} |
| 683 |
|
} |
| 684 |
|
} |
| 808 |
|
const struct MaskItem *conf = arec->conf; |
| 809 |
|
|
| 810 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), |
| 811 |
< |
from, to, "G", |
| 811 |
> |
from, to, 'G', |
| 812 |
|
conf->host ? conf->host : "*", |
| 813 |
|
conf->user ? conf->user : "*", |
| 814 |
< |
conf->reason ? conf->reason : "No reason"); |
| 814 |
> |
conf->reason ? conf->reason : CONF_NOREASON); |
| 815 |
|
} |
| 816 |
|
} |
| 817 |
|
} |
| 835 |
|
static const char * |
| 836 |
|
show_iline_prefix(const struct Client *sptr, const struct MaskItem *conf) |
| 837 |
|
{ |
| 838 |
< |
static char prefix_of_host[USERLEN + 14]; |
| 838 |
> |
static char prefix_of_host[USERLEN + 15]; |
| 839 |
|
char *prefix_ptr = prefix_of_host; |
| 840 |
|
|
| 841 |
+ |
if (IsConfWebIRC(conf)) |
| 842 |
+ |
*prefix_ptr++ = '<'; |
| 843 |
|
if (IsNoTilde(conf)) |
| 844 |
|
*prefix_ptr++ = '-'; |
| 845 |
|
if (IsLimitIp(conf)) |
| 963 |
|
{ |
| 964 |
|
struct MaskItem *conf = NULL; |
| 965 |
|
unsigned int i = 0; |
| 966 |
< |
const char *p = NULL; |
| 966 |
> |
char c = '\0'; |
| 967 |
|
dlink_node *ptr = NULL; |
| 968 |
|
|
| 969 |
|
if (tkline) |
| 970 |
< |
p = "k"; |
| 970 |
> |
c = 'k'; |
| 971 |
|
else |
| 972 |
< |
p = "K"; |
| 972 |
> |
c = 'K'; |
| 973 |
|
|
| 974 |
|
for (i = 0; i < ATABLE_SIZE; ++i) |
| 975 |
|
{ |
| 988 |
|
|
| 989 |
|
if (HasUMode(client_p, UMODE_OPER)) |
| 990 |
|
sendto_one(client_p, form_str(RPL_STATSKLINE), me.name, |
| 991 |
< |
client_p->name, p, conf->host, conf->user, |
| 991 |
> |
client_p->name, c, conf->host, conf->user, |
| 992 |
|
conf->reason); |
| 993 |
|
else |
| 994 |
|
sendto_one(client_p, form_str(RPL_STATSKLINE), me.name, |
| 995 |
< |
client_p->name, p, conf->host, conf->user, |
| 995 |
> |
client_p->name, c, conf->host, conf->user, |
| 996 |
|
conf->reason); |
| 997 |
|
} |
| 998 |
|
} |
| 1029 |
|
return; |
| 1030 |
|
|
| 1031 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), from, |
| 1032 |
< |
to, "k", conf->host, conf->user, conf->reason); |
| 1032 |
> |
to, 'k', conf->host, conf->user, conf->reason); |
| 1033 |
|
} |
| 1034 |
|
/* Theyre opered, or allowed to see all klines */ |
| 1035 |
|
else { |
| 1069 |
|
return; |
| 1070 |
|
|
| 1071 |
|
sendto_one(source_p, form_str(RPL_STATSKLINE), from, |
| 1072 |
< |
to, "K", conf->host, conf->user, conf->reason); |
| 1072 |
> |
to, 'K', conf->host, conf->user, conf->reason); |
| 1073 |
|
} |
| 1074 |
|
/* Theyre opered, or allowed to see all klines */ |
| 1075 |
< |
else { |
| 1075 |
> |
else |
| 1076 |
|
report_Klines(source_p, 0); |
| 885 |
– |
report_confitem_types(source_p, CONF_RKLINE); |
| 886 |
– |
} |
| 1077 |
|
} |
| 1078 |
|
|
| 1079 |
|
static void |
| 1111 |
|
continue; |
| 1112 |
|
|
| 1113 |
|
if (MyClient(source_p) && HasUMode(source_p, UMODE_OPER)) |
| 1114 |
< |
sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %d", |
| 1114 |
> |
sendto_one(source_p, ":%s %d %s p :[%c][%s] %s (%s@%s) Idle: %u", |
| 1115 |
|
from, RPL_STATSDEBUG, to, |
| 1116 |
|
HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O', |
| 1117 |
|
oper_privs_as_string(target_p->localClient->operflags), |
| 1118 |
|
target_p->name, target_p->username, target_p->host, |
| 1119 |
< |
(int)(CurrentTime - target_p->localClient->last_privmsg)); |
| 1119 |
> |
idle_time_get(source_p, target_p)); |
| 1120 |
|
else |
| 1121 |
< |
sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %d", |
| 1121 |
> |
sendto_one(source_p, ":%s %d %s p :[%c] %s (%s@%s) Idle: %u", |
| 1122 |
|
from, RPL_STATSDEBUG, to, |
| 1123 |
|
HasUMode(target_p, UMODE_ADMIN) ? 'A' : 'O', |
| 1124 |
|
target_p->name, target_p->username, target_p->host, |
| 1125 |
< |
(int)(CurrentTime - target_p->localClient->last_privmsg)); |
| 1125 |
> |
idle_time_get(source_p, target_p)); |
| 1126 |
|
} |
| 1127 |
|
|
| 1128 |
< |
sendto_one(source_p, ":%s %d %s p :%lu OPER(s)", |
| 1128 |
> |
sendto_one(source_p, ":%s %d %s p :%u OPER(s)", |
| 1129 |
|
from, RPL_STATSDEBUG, to, dlink_list_length(&oper_list)); |
| 1130 |
|
} |
| 1131 |
|
|
| 1156 |
|
{ |
| 1157 |
|
const struct Client *target_p = NULL; |
| 1158 |
|
const dlink_node *ptr = NULL; |
| 969 |
– |
struct ServerStatistics *sp; |
| 1159 |
|
struct ServerStatistics tmp; |
| 1160 |
+ |
struct ServerStatistics *sp = &tmp; |
| 1161 |
|
|
| 972 |
– |
sp = &tmp; |
| 1162 |
|
memcpy(sp, &ServerStats, sizeof(struct ServerStatistics)); |
| 1163 |
|
|
| 1164 |
|
/* |
| 1269 |
|
stats_gecos(struct Client *source_p, int parc, char *parv[]) |
| 1270 |
|
{ |
| 1271 |
|
report_confitem_types(source_p, CONF_XLINE); |
| 1083 |
– |
report_confitem_types(source_p, CONF_RXLINE); |
| 1272 |
|
} |
| 1273 |
|
|
| 1274 |
|
static void |
| 1295 |
|
{ |
| 1296 |
|
struct Client *target_p = ptr->data; |
| 1297 |
|
|
| 1298 |
+ |
if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services) |
| 1299 |
+ |
if (!HasUMode(source_p, UMODE_OPER)) |
| 1300 |
+ |
continue; |
| 1301 |
+ |
|
| 1302 |
|
sendB += target_p->localClient->send.bytes; |
| 1303 |
|
recvB += target_p->localClient->recv.bytes; |
| 1304 |
|
|
| 1533 |
|
{ 'Q', stats_resv, 1, 0 }, |
| 1534 |
|
{ 'r', stats_usage, 1, 0 }, |
| 1535 |
|
{ 'R', stats_usage, 1, 0 }, |
| 1536 |
+ |
{ 's', stats_service, 1, 0 }, |
| 1537 |
|
{ 'S', stats_service, 1, 0 }, |
| 1538 |
|
{ 't', stats_tstats, 1, 0 }, |
| 1539 |
|
{ 'T', stats_tstats, 1, 0 }, |