| 1 |
|
/* |
| 2 |
|
* ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd) |
| 3 |
|
* |
| 4 |
< |
* Copyright (c) 1997-2014 ircd-hybrid development team |
| 4 |
> |
* Copyright (c) 1997-2015 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 |
| 83 |
|
struct Client * |
| 84 |
|
make_client(struct Client *from) |
| 85 |
|
{ |
| 86 |
< |
struct Client *client_p = mp_pool_get(client_pool); |
| 86 |
> |
struct Client *const client_p = mp_pool_get(client_pool); |
| 87 |
|
|
| 88 |
|
if (!from) |
| 89 |
|
{ |
| 90 |
< |
client_p->from = client_p; /* 'from' of local client is self! */ |
| 91 |
< |
client_p->connection = mp_pool_get(connection_pool); |
| 92 |
< |
client_p->connection->since = CurrentTime; |
| 93 |
< |
client_p->connection->lasttime = CurrentTime; |
| 94 |
< |
client_p->connection->firsttime = CurrentTime; |
| 90 |
> |
client_p->from = client_p; /* 'from' of local client is self! */ |
| 91 |
> |
client_p->connection = mp_pool_get(connection_pool); |
| 92 |
> |
client_p->connection->since = CurrentTime; |
| 93 |
> |
client_p->connection->lasttime = CurrentTime; |
| 94 |
> |
client_p->connection->firsttime = CurrentTime; |
| 95 |
|
client_p->connection->registration = REG_INIT; |
| 96 |
|
|
| 97 |
|
/* as good a place as any... */ |
| 98 |
|
dlinkAdd(client_p, &client_p->connection->lclient_node, &unknown_list); |
| 99 |
|
} |
| 100 |
|
else |
| 101 |
< |
client_p->from = from; /* 'from' of local client is self! */ |
| 101 |
> |
client_p->from = from; |
| 102 |
|
|
| 103 |
|
client_p->idhnext = client_p; |
| 104 |
< |
client_p->hnext = client_p; |
| 104 |
> |
client_p->hnext = client_p; |
| 105 |
|
SetUnknown(client_p); |
| 106 |
|
strcpy(client_p->username, "unknown"); |
| 107 |
< |
strcpy(client_p->svid, "0"); |
| 107 |
> |
strcpy(client_p->account, "0"); |
| 108 |
|
|
| 109 |
|
return client_p; |
| 110 |
|
} |
| 119 |
|
static void |
| 120 |
|
free_client(struct Client *client_p) |
| 121 |
|
{ |
| 122 |
– |
assert(client_p); |
| 122 |
|
assert(client_p != &me); |
| 123 |
|
assert(client_p->hnext == client_p); |
| 124 |
|
assert(client_p->idhnext == client_p); |
| 125 |
|
assert(client_p->channel.head == NULL); |
| 126 |
|
assert(dlink_list_length(&client_p->channel) == 0); |
| 127 |
|
assert(dlink_list_length(&client_p->whowas) == 0); |
| 128 |
< |
assert(!IsServer(client_p) || client_p->serv); |
| 128 |
> |
assert(dlink_list_length(&client_p->svstags) == 0); |
| 129 |
|
|
| 130 |
|
MyFree(client_p->serv); |
| 131 |
|
MyFree(client_p->certfp); |
| 138 |
|
assert(IsClosing(client_p) && IsDead(client_p)); |
| 139 |
|
|
| 140 |
|
MyFree(client_p->connection->challenge_response); |
| 142 |
– |
MyFree(client_p->connection->challenge_operator); |
| 141 |
|
client_p->connection->challenge_response = NULL; |
| 142 |
+ |
MyFree(client_p->connection->challenge_operator); |
| 143 |
|
client_p->connection->challenge_operator = NULL; |
| 144 |
|
|
| 145 |
|
/* |
| 146 |
< |
* clean up extra sockets from P-lines which have been discarded. |
| 146 |
> |
* Clean up extra sockets from listen {} blocks which have been discarded. |
| 147 |
|
*/ |
| 148 |
|
if (client_p->connection->listener) |
| 149 |
|
{ |
| 160 |
|
mp_pool_release(client_p); |
| 161 |
|
} |
| 162 |
|
|
| 163 |
+ |
void |
| 164 |
+ |
client_attach_svstag(struct Client *client_p, unsigned int numeric, |
| 165 |
+ |
const char *umodes, const char *const tag) |
| 166 |
+ |
{ |
| 167 |
+ |
struct ServicesTag *svstag = NULL; |
| 168 |
+ |
const struct user_modes *tab = NULL; |
| 169 |
+ |
|
| 170 |
+ |
if (numeric >= ERR_LAST_ERR_MSG || *umodes != '+') |
| 171 |
+ |
return; |
| 172 |
+ |
|
| 173 |
+ |
svstag = MyCalloc(sizeof(*svstag)); |
| 174 |
+ |
svstag->numeric = numeric; |
| 175 |
+ |
svstag->tag = xstrdup(tag); |
| 176 |
+ |
|
| 177 |
+ |
for (const char *m = umodes + 1; *m; ++m) |
| 178 |
+ |
if ((tab = umode_map[(unsigned char)*m])) |
| 179 |
+ |
svstag->umodes |= tab->flag; |
| 180 |
+ |
|
| 181 |
+ |
if (numeric != RPL_WHOISOPERATOR) |
| 182 |
+ |
dlinkAddTail(svstag, &svstag->node, &client_p->svstags); |
| 183 |
+ |
else |
| 184 |
+ |
dlinkAdd(svstag, &svstag->node, &client_p->svstags); |
| 185 |
+ |
} |
| 186 |
+ |
|
| 187 |
+ |
void |
| 188 |
+ |
client_clear_svstags(struct Client *client_p) |
| 189 |
+ |
{ |
| 190 |
+ |
dlink_node *node = NULL, *node_next = NULL; |
| 191 |
+ |
|
| 192 |
+ |
DLINK_FOREACH_SAFE(node, node_next, client_p->svstags.head) |
| 193 |
+ |
{ |
| 194 |
+ |
struct ServicesTag *svstag = node->data; |
| 195 |
+ |
|
| 196 |
+ |
dlinkDelete(&svstag->node, &client_p->svstags); |
| 197 |
+ |
MyFree(svstag->tag); |
| 198 |
+ |
MyFree(svstag); |
| 199 |
+ |
} |
| 200 |
+ |
} |
| 201 |
+ |
|
| 202 |
|
/* check_pings_list() |
| 203 |
|
* |
| 204 |
|
* inputs - pointer to list to check |
| 341 |
|
{ |
| 342 |
|
struct Client *client_p = node->data; |
| 343 |
|
|
| 344 |
< |
/* If a client is already being exited |
| 307 |
< |
*/ |
| 344 |
> |
/* If a client is already being exited */ |
| 345 |
|
if (IsDead(client_p)) |
| 346 |
|
continue; |
| 347 |
|
|
| 475 |
|
if (IsClient(client_p)) |
| 476 |
|
{ |
| 477 |
|
assert(Count.total > 0); |
| 478 |
+ |
|
| 479 |
|
--Count.total; |
| 480 |
|
if (HasUMode(client_p, UMODE_OPER)) |
| 481 |
|
--Count.oper; |
| 521 |
|
struct Client * |
| 522 |
|
find_chasing(struct Client *source_p, const char *name) |
| 523 |
|
{ |
| 524 |
< |
struct Client *who = find_person(source_p, name); |
| 524 |
> |
struct Client *target_p = find_person(source_p, name); |
| 525 |
|
|
| 526 |
< |
if (who) |
| 527 |
< |
return who; |
| 526 |
> |
if (target_p) |
| 527 |
> |
return target_p; |
| 528 |
|
|
| 529 |
|
if (IsDigit(*name)) |
| 530 |
|
return NULL; |
| 531 |
|
|
| 532 |
< |
if ((who = whowas_get_history(name, |
| 533 |
< |
(time_t)ConfigGeneral.kill_chase_time_limit)) |
| 534 |
< |
== NULL) |
| 532 |
> |
target_p = whowas_get_history(name, (time_t)ConfigGeneral.kill_chase_time_limit); |
| 533 |
> |
|
| 534 |
> |
if (!target_p) |
| 535 |
|
{ |
| 536 |
|
sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name); |
| 537 |
|
return NULL; |
| 538 |
|
} |
| 539 |
|
|
| 540 |
< |
return who; |
| 540 |
> |
return target_p; |
| 541 |
|
} |
| 542 |
|
|
| 543 |
|
/* |
| 563 |
|
{ |
| 564 |
|
static char buf[HOSTLEN * 2 + USERLEN + 5]; |
| 565 |
|
|
| 528 |
– |
assert(client_p); |
| 529 |
– |
|
| 566 |
|
if (!MyConnect(client_p)) |
| 567 |
|
return client_p->name; |
| 568 |
|
|
| 574 |
|
type = MASK_IP; |
| 575 |
|
} |
| 576 |
|
|
| 541 |
– |
if (ConfigGeneral.hide_spoof_ips) |
| 542 |
– |
if (IsIPSpoof(client_p) && type == SHOW_IP) |
| 543 |
– |
type = MASK_IP; |
| 544 |
– |
|
| 577 |
|
/* And finally, let's get the host information, ip or name */ |
| 578 |
|
switch (type) |
| 579 |
|
{ |
| 640 |
|
sendto_common_channels_local(source_p, 0, 0, ":%s!%s@%s QUIT :%s", |
| 641 |
|
source_p->name, source_p->username, |
| 642 |
|
source_p->host, comment); |
| 643 |
+ |
|
| 644 |
|
DLINK_FOREACH_SAFE(node, node_next, source_p->channel.head) |
| 645 |
|
remove_user_from_channel(node->data); |
| 646 |
|
|
| 670 |
|
/* Remove source_p from the client lists */ |
| 671 |
|
if (source_p->id[0]) |
| 672 |
|
hash_del_id(source_p); |
| 673 |
+ |
|
| 674 |
|
if (source_p->name[0]) |
| 675 |
|
hash_del_client(source_p); |
| 676 |
|
|
| 767 |
|
else if (IsClient(source_p)) |
| 768 |
|
{ |
| 769 |
|
time_t on_for = CurrentTime - source_p->connection->firsttime; |
| 770 |
+ |
|
| 771 |
|
assert(Count.local > 0); |
| 772 |
< |
Count.local--; |
| 772 |
> |
|
| 773 |
> |
--Count.local; |
| 774 |
|
|
| 775 |
|
if (HasUMode(source_p, UMODE_OPER)) |
| 776 |
|
if ((node = dlinkFindDelete(&oper_list, source_p))) |
| 783 |
|
free_list_task(source_p); |
| 784 |
|
|
| 785 |
|
watch_del_watch_list(source_p); |
| 786 |
+ |
client_clear_svstags(source_p); |
| 787 |
+ |
|
| 788 |
|
sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE, |
| 789 |
|
"Client exiting: %s (%s@%s) [%s] [%s]", |
| 790 |
|
source_p->name, source_p->username, source_p->host, comment, |
| 791 |
< |
ConfigGeneral.hide_spoof_ips && IsIPSpoof(source_p) ? |
| 792 |
< |
"255.255.255.255" : source_p->sockhost); |
| 791 |
> |
source_p->sockhost); |
| 792 |
> |
|
| 793 |
|
ilog(LOG_TYPE_USER, "%s (%3u:%02u:%02u): %s!%s@%s %llu/%llu", |
| 794 |
|
myctime(source_p->connection->firsttime), (unsigned int)(on_for / 3600), |
| 795 |
|
(unsigned int)((on_for % 3600)/60), (unsigned int)(on_for % 60), |
| 800 |
|
else if (IsServer(source_p)) |
| 801 |
|
{ |
| 802 |
|
assert(Count.myserver > 0); |
| 803 |
+ |
|
| 804 |
|
--Count.myserver; |
| 805 |
|
|
| 806 |
|
assert(dlinkFind(&local_server_list, source_p)); |
| 835 |
|
{ |
| 836 |
|
char splitstr[HOSTLEN + HOSTLEN + 2] = ""; |
| 837 |
|
|
| 838 |
< |
/* This shouldn't ever happen */ |
| 839 |
< |
assert(source_p->serv && source_p->servptr); |
| 838 |
> |
assert(source_p->serv); |
| 839 |
> |
assert(source_p->servptr); |
| 840 |
|
|
| 841 |
|
if (ConfigServerHide.hide_servers) |
| 842 |
|
/* |
| 850 |
|
|
| 851 |
|
/* Send SQUIT for source_p in every direction. source_p is already off of local_server_list here */ |
| 852 |
|
if (!HasFlag(source_p, FLAGS_SQUIT)) |
| 853 |
< |
sendto_server(NULL, NOCAPS, NOCAPS, "SQUIT %s :%s", source_p->id, comment); |
| 853 |
> |
sendto_server(NULL, 0, 0, "SQUIT %s :%s", source_p->id, comment); |
| 854 |
|
|
| 855 |
|
/* Now exit the clients internally */ |
| 856 |
|
recurse_remove_clients(source_p, splitstr); |
| 866 |
|
source_p->connection->recv.bytes >> 10); |
| 867 |
|
ilog(LOG_TYPE_IRCD, "%s was connected for %d day%s, %2d:%02d:%02d. %llu/%llu sendK/recvK.", |
| 868 |
|
source_p->name, connected/86400, (connected/86400 == 1) ? "" : "s", |
| 869 |
< |
(connected % 86400) / 3600, (connected % 3600) / 60, connected % 60, |
| 870 |
< |
source_p->connection->send.bytes >> 10, |
| 871 |
< |
source_p->connection->recv.bytes >> 10); |
| 869 |
> |
(connected % 86400) / 3600, (connected % 3600) / 60, connected % 60, |
| 870 |
> |
source_p->connection->send.bytes >> 10, |
| 871 |
> |
source_p->connection->recv.bytes >> 10); |
| 872 |
|
} |
| 873 |
|
} |
| 874 |
|
else if (IsClient(source_p) && !HasFlag(source_p, FLAGS_KILLED)) |
| 875 |
< |
sendto_server(source_p->from, NOCAPS, NOCAPS, ":%s QUIT :%s", |
| 875 |
> |
sendto_server(source_p->from, 0, 0, ":%s QUIT :%s", |
| 876 |
|
source_p->id, comment); |
| 877 |
|
|
| 878 |
|
/* The client *better* be off all of the lists */ |
| 1060 |
|
{ |
| 1061 |
|
dlink_node *node = NULL; |
| 1062 |
|
|
| 1063 |
+ |
if (HasFlag(source, FLAGS_SERVICE) || |
| 1064 |
+ |
(HasUMode(source, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid)) |
| 1065 |
+ |
return 1; |
| 1066 |
+ |
|
| 1067 |
|
if (source == target || find_accept(source->name, source->username, |
| 1068 |
|
source->host, target, match)) |
| 1069 |
|
return 1; |
| 1092 |
|
} |
| 1093 |
|
|
| 1094 |
|
unsigned int |
| 1095 |
< |
idle_time_get(const struct Client *source_p, const struct Client *target_p) |
| 1095 |
> |
client_get_idle_time(const struct Client *source_p, |
| 1096 |
> |
const struct Client *target_p) |
| 1097 |
|
{ |
| 1098 |
|
unsigned int idle = 0; |
| 1099 |
|
unsigned int min_idle = 0; |
| 1100 |
|
unsigned int max_idle = 0; |
| 1101 |
< |
const struct ClassItem *class = get_class_ptr(&target_p->connection->confs); |
| 1101 |
> |
const struct ClassItem *const class = get_class_ptr(&target_p->connection->confs); |
| 1102 |
|
|
| 1103 |
|
if (!(class->flags & CLASS_FLAGS_FAKE_IDLE) || target_p == source_p) |
| 1104 |
|
return CurrentTime - target_p->connection->last_privmsg; |
| 1105 |
+ |
|
| 1106 |
|
if (HasUMode(source_p, UMODE_OPER) && |
| 1107 |
|
!(class->flags & CLASS_FLAGS_HIDE_IDLE_FROM_OPERS)) |
| 1108 |
|
return CurrentTime - target_p->connection->last_privmsg; |