27 |
|
#include <openssl/rsa.h> |
28 |
|
#include "rsa.h" |
29 |
|
#endif |
30 |
< |
#include "tools.h" |
30 |
> |
#include "list.h" |
31 |
|
#include "channel.h" |
32 |
|
#include "channel_mode.h" |
33 |
|
#include "client.h" |
37 |
|
#include "fdlist.h" |
38 |
|
#include "hash.h" |
39 |
|
#include "irc_string.h" |
40 |
– |
#include "inet_misc.h" |
40 |
|
#include "sprintf_irc.h" |
41 |
|
#include "ircd.h" |
42 |
|
#include "ircd_defs.h" |
43 |
|
#include "s_bsd.h" |
45 |
– |
#include "irc_getnameinfo.h" |
46 |
– |
#include "list.h" |
44 |
|
#include "numeric.h" |
45 |
|
#include "packet.h" |
46 |
|
#include "irc_res.h" |
47 |
|
#include "s_conf.h" |
48 |
|
#include "s_serv.h" |
49 |
|
#include "s_log.h" |
53 |
– |
#include "s_stats.h" |
50 |
|
#include "s_user.h" |
51 |
|
#include "send.h" |
52 |
|
#include "memory.h" |
124 |
|
struct Client *server_p) |
125 |
|
{ |
126 |
|
struct ZipStats zipstats; |
127 |
< |
unsigned long in = 0, in_wire = 0, out = 0, out_wire = 0; |
127 |
> |
uint64_t in = 0, in_wire = 0, out = 0, out_wire = 0; |
128 |
|
int i = 0; |
129 |
|
|
130 |
|
assert(rpl == SLINKRPL_ZIPSTATS); |
184 |
|
else |
185 |
|
zipstats.out_ratio = 0; |
186 |
|
|
187 |
< |
memcpy(&server_p->localClient->zipstats, &zipstats, sizeof (struct ZipStats)); |
187 |
> |
memcpy(&server_p->localClient->zipstats, &zipstats, sizeof(struct ZipStats)); |
188 |
|
} |
189 |
|
|
190 |
|
void |
191 |
|
collect_zipstats(void *unused) |
192 |
|
{ |
193 |
< |
dlink_node *ptr; |
198 |
< |
struct Client *target_p; |
193 |
> |
dlink_node *ptr = NULL; |
194 |
|
|
195 |
|
DLINK_FOREACH(ptr, serv_list.head) |
196 |
|
{ |
197 |
< |
target_p = ptr->data; |
197 |
> |
struct Client *target_p = ptr->data; |
198 |
|
|
199 |
|
if (IsCapable(target_p, CAP_ZIP)) |
200 |
|
{ |
234 |
|
} |
235 |
|
#endif /* HAVE_LIBCRYPTO */ |
236 |
|
|
242 |
– |
/* my_name_for_link() |
243 |
– |
* return wildcard name of my server name |
244 |
– |
* according to given config entry --Jto |
245 |
– |
*/ |
246 |
– |
const char * |
247 |
– |
my_name_for_link(struct ConfItem *conf) |
248 |
– |
{ |
249 |
– |
struct AccessItem *aconf; |
250 |
– |
|
251 |
– |
aconf = (struct AccessItem *)map_to_conf(conf); |
252 |
– |
if (aconf->fakename != NULL) |
253 |
– |
return aconf->fakename; |
254 |
– |
else |
255 |
– |
return me.name; |
256 |
– |
} |
257 |
– |
|
237 |
|
/* |
238 |
|
* write_links_file |
239 |
|
* |
473 |
|
DLINK_FOREACH(ptr, server_items.head) |
474 |
|
{ |
475 |
|
conf = ptr->data; |
476 |
< |
aconf = (struct AccessItem *)map_to_conf(conf); |
476 |
> |
aconf = map_to_conf(conf); |
477 |
|
|
478 |
|
/* Also when already connecting! (update holdtimes) --SRB |
479 |
|
*/ |
480 |
< |
if (!(aconf->status & CONF_SERVER) || aconf->port <= 0 || |
480 |
> |
if (!(aconf->status & CONF_SERVER) || !aconf->port || |
481 |
|
!(IsConfAllowAutoConn(aconf))) |
482 |
|
continue; |
483 |
|
|
484 |
< |
cltmp = (struct ClassItem *)map_to_conf(aconf->class_ptr); |
484 |
> |
cltmp = map_to_conf(aconf->class_ptr); |
485 |
|
|
486 |
|
/* Skip this entry if the use of it is still on hold until |
487 |
|
* future. Otherwise handle this entry (and set it on hold |
544 |
|
} |
545 |
|
|
546 |
|
int |
547 |
+ |
valid_servname(const char *name) |
548 |
+ |
{ |
549 |
+ |
unsigned int length = 0; |
550 |
+ |
unsigned int dots = 0; |
551 |
+ |
const char *p = name; |
552 |
+ |
|
553 |
+ |
for (; *p; ++p) |
554 |
+ |
{ |
555 |
+ |
if (!IsServChar(*p)) |
556 |
+ |
return 0; |
557 |
+ |
|
558 |
+ |
++length; |
559 |
+ |
|
560 |
+ |
if (*p == '.') |
561 |
+ |
++dots; |
562 |
+ |
} |
563 |
+ |
|
564 |
+ |
return dots != 0 && length <= HOSTLEN; |
565 |
+ |
} |
566 |
+ |
|
567 |
+ |
int |
568 |
|
check_server(const char *name, struct Client *client_p, int cryptlink) |
569 |
|
{ |
570 |
|
dlink_node *ptr; |
586 |
|
DLINK_FOREACH(ptr, server_items.head) |
587 |
|
{ |
588 |
|
conf = ptr->data; |
589 |
< |
aconf = (struct AccessItem *)map_to_conf(conf); |
589 |
> |
aconf = map_to_conf(conf); |
590 |
|
|
591 |
|
if (!match(name, conf->name)) |
592 |
|
continue; |
670 |
|
ClearCap(client_p, CAP_TBURST); |
671 |
|
} |
672 |
|
|
673 |
– |
/* Don't unset CAP_HUB here even if the server isn't a hub, |
674 |
– |
* it only indicates if the server thinks it's lazylinks are |
675 |
– |
* leafs or not.. if you unset it, bad things will happen |
676 |
– |
*/ |
673 |
|
if (aconf != NULL) |
674 |
|
{ |
675 |
|
struct sockaddr_in *v4; |
750 |
|
} |
751 |
|
} |
752 |
|
|
753 |
< |
return(0); |
753 |
> |
return 0; |
754 |
|
} |
755 |
|
|
756 |
|
/* |
763 |
|
int |
764 |
|
find_capability(const char *capab) |
765 |
|
{ |
766 |
< |
dlink_node *ptr; |
771 |
< |
struct Capability *cap; |
766 |
> |
const dlink_node *ptr = NULL; |
767 |
|
|
768 |
|
DLINK_FOREACH(ptr, cap_list.head) |
769 |
|
{ |
770 |
< |
cap = ptr->data; |
770 |
> |
const struct Capability *cap = ptr->data; |
771 |
|
|
772 |
< |
if (cap->cap != 0) |
773 |
< |
{ |
779 |
< |
if (irccmp(cap->name, capab) == 0) |
780 |
< |
return(cap->cap); |
781 |
< |
} |
772 |
> |
if (cap->cap && !irccmp(cap->name, capab)) |
773 |
> |
return cap->cap; |
774 |
|
} |
775 |
< |
return(0); |
775 |
> |
|
776 |
> |
return 0; |
777 |
|
} |
778 |
|
|
779 |
|
/* send_capabilities() |
955 |
|
char *host; |
956 |
|
const char *inpath; |
957 |
|
static char inpath_ip[HOSTLEN * 2 + USERLEN + 6]; |
965 |
– |
dlink_node *m; |
958 |
|
dlink_node *ptr; |
959 |
|
|
960 |
|
assert(client_p != NULL); |
987 |
|
{ |
988 |
|
if (client_p != serv_list.head->data || serv_list.head->next) |
989 |
|
{ |
990 |
< |
ServerStats->is_ref++; |
990 |
> |
++ServerStats.is_ref; |
991 |
|
sendto_one(client_p, "ERROR :I'm a leaf not a hub"); |
992 |
|
exit_client(client_p, &me, "I'm a leaf"); |
993 |
|
return; |
994 |
|
} |
995 |
|
} |
996 |
|
|
997 |
< |
aconf = (struct AccessItem *)map_to_conf(conf); |
997 |
> |
aconf = map_to_conf(conf); |
998 |
|
|
999 |
|
if (IsUnknown(client_p) && !IsConfCryptLink(aconf)) |
1000 |
|
{ |
1002 |
|
* 2. Check aconf->spasswd, not aconf->passwd. |
1003 |
|
*/ |
1004 |
|
if (!EmptyString(aconf->spasswd)) |
1005 |
< |
{ |
1006 |
< |
/* only send ts6 format PASS if we have ts6 enabled */ |
1015 |
< |
if (me.id[0] != '\0') /* Send TS 6 form only if id */ |
1016 |
< |
sendto_one(client_p, "PASS %s TS %d %s", |
1017 |
< |
aconf->spasswd, TS_CURRENT, me.id); |
1018 |
< |
else |
1019 |
< |
sendto_one(client_p, "PASS %s TS 5", |
1020 |
< |
aconf->spasswd); |
1021 |
< |
} |
1005 |
> |
sendto_one(client_p, "PASS %s TS %d %s", |
1006 |
> |
aconf->spasswd, TS_CURRENT, me.id); |
1007 |
|
|
1008 |
|
/* Pass my info to the new server |
1009 |
|
* |
1025 |
– |
* If this is a HUB, pass on CAP_HUB |
1010 |
|
* Pass on ZIP if supported |
1011 |
|
* Pass on TB if supported. |
1012 |
|
* - Dianora |
1013 |
|
*/ |
1014 |
|
|
1015 |
< |
send_capabilities(client_p, aconf, (ServerInfo.hub ? CAP_HUB : 0) |
1016 |
< |
| (IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1015 |
> |
send_capabilities(client_p, aconf, |
1016 |
> |
(IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1017 |
|
| (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0), 0); |
1018 |
|
|
1019 |
|
/* SERVER is the last command sent before switching to ziplinks. |
1027 |
|
* Nagle is already disabled at this point --adx |
1028 |
|
*/ |
1029 |
|
sendto_one(client_p, "SERVER %s 1 :%s%s", |
1030 |
< |
my_name_for_link(conf), |
1047 |
< |
ConfigServerHide.hidden ? "(H) " : "", |
1048 |
< |
(me.info[0]) ? (me.info) : "IRCers United"); |
1030 |
> |
me.name, ConfigServerHide.hidden ? "(H) " : "", me.info); |
1031 |
|
send_queued_write(client_p); |
1032 |
|
} |
1033 |
|
|
1051 |
|
SetServlink(client_p); |
1052 |
|
} |
1053 |
|
|
1054 |
< |
/* only send ts6 format SVINFO if we have ts6 enabled */ |
1073 |
< |
sendto_one(client_p, "SVINFO %d %d 0 :%lu", |
1074 |
< |
(me.id[0] ? TS_CURRENT : 5), TS_MIN, |
1054 |
> |
sendto_one(client_p, "SVINFO %d %d 0 :%lu", TS_CURRENT, TS_MIN, |
1055 |
|
(unsigned long)CurrentTime); |
1056 |
|
|
1057 |
|
/* assumption here is if they passed the correct TS version, they also passed an SID */ |
1085 |
|
/* Some day, all these lists will be consolidated *sigh* */ |
1086 |
|
dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list); |
1087 |
|
|
1088 |
< |
m = dlinkFind(&unknown_list, client_p); |
1109 |
< |
assert(NULL != m); |
1088 |
> |
assert(dlinkFind(&unknown_list, client_p)); |
1089 |
|
|
1090 |
< |
dlinkDelete(m, &unknown_list); |
1091 |
< |
dlinkAdd(client_p, m, &serv_list); |
1090 |
> |
dlink_move_node(&client_p->localClient->lclient_node, |
1091 |
> |
&unknown_list, &serv_list); |
1092 |
|
|
1093 |
|
Count.myserver++; |
1094 |
|
|
1101 |
|
/* fixing eob timings.. -gnp */ |
1102 |
|
client_p->firsttime = CurrentTime; |
1103 |
|
|
1104 |
+ |
|
1105 |
+ |
if (find_matching_name_conf(SERVICE_TYPE, client_p->name, NULL, NULL, 0)) |
1106 |
+ |
SetService(client_p); |
1107 |
+ |
|
1108 |
|
/* Show the real host/IP to admins */ |
1109 |
|
sendto_realops_flags(UMODE_ALL, L_ADMIN, |
1110 |
|
"Link with %s established: (%s) link", |
1140 |
|
if (target_p == client_p) |
1141 |
|
continue; |
1142 |
|
|
1160 |
– |
if ((conf = target_p->serv->sconf) && |
1161 |
– |
match(my_name_for_link(conf), client_p->name)) |
1162 |
– |
continue; |
1163 |
– |
|
1143 |
|
if (IsCapable(target_p, CAP_TS6) && HasID(client_p)) |
1144 |
|
sendto_one(target_p, ":%s SID %s 2 %s :%s%s", |
1145 |
|
me.id, client_p->name, client_p->id, |
1170 |
|
** is destroyed...) |
1171 |
|
*/ |
1172 |
|
|
1194 |
– |
conf = client_p->serv->sconf; |
1195 |
– |
|
1173 |
|
DLINK_FOREACH_PREV(ptr, global_serv_list.tail) |
1174 |
|
{ |
1175 |
|
target_p = ptr->data; |
1176 |
|
|
1177 |
|
/* target_p->from == target_p for target_p == client_p */ |
1178 |
< |
if (target_p->from == client_p) |
1202 |
< |
continue; |
1203 |
< |
|
1204 |
< |
if (match(my_name_for_link(conf), target_p->name)) |
1178 |
> |
if (IsMe(target_p) || target_p->from == client_p) |
1179 |
|
continue; |
1180 |
|
|
1181 |
|
if (IsCapable(client_p, CAP_TS6)) |
1528 |
|
} |
1529 |
|
} |
1530 |
|
|
1557 |
– |
/* set_autoconn() |
1558 |
– |
* |
1559 |
– |
* inputs - struct Client pointer to oper requesting change |
1560 |
– |
* output - none |
1561 |
– |
* side effects - set autoconnect mode |
1562 |
– |
*/ |
1563 |
– |
void |
1564 |
– |
set_autoconn(struct Client *source_p, const char *name, int newval) |
1565 |
– |
{ |
1566 |
– |
struct ConfItem *conf; |
1567 |
– |
struct AccessItem *aconf; |
1568 |
– |
|
1569 |
– |
if (name != NULL) |
1570 |
– |
{ |
1571 |
– |
conf = find_exact_name_conf(SERVER_TYPE, name, NULL, NULL); |
1572 |
– |
if (conf != NULL) |
1573 |
– |
{ |
1574 |
– |
aconf = (struct AccessItem *)map_to_conf(conf); |
1575 |
– |
if (newval) |
1576 |
– |
SetConfAllowAutoConn(aconf); |
1577 |
– |
else |
1578 |
– |
ClearConfAllowAutoConn(aconf); |
1579 |
– |
|
1580 |
– |
sendto_realops_flags(UMODE_ALL, L_ALL, |
1581 |
– |
"%s has changed AUTOCONN for %s to %i", |
1582 |
– |
source_p->name, name, newval); |
1583 |
– |
sendto_one(source_p, |
1584 |
– |
":%s NOTICE %s :AUTOCONN for %s is now set to %i", |
1585 |
– |
me.name, source_p->name, name, newval); |
1586 |
– |
} |
1587 |
– |
else |
1588 |
– |
{ |
1589 |
– |
sendto_one(source_p, ":%s NOTICE %s :Can't find %s", |
1590 |
– |
me.name, source_p->name, name); |
1591 |
– |
} |
1592 |
– |
} |
1593 |
– |
else |
1594 |
– |
{ |
1595 |
– |
sendto_one(source_p, ":%s NOTICE %s :Please specify a server name!", |
1596 |
– |
me.name, source_p->name); |
1597 |
– |
} |
1598 |
– |
} |
1599 |
– |
|
1531 |
|
/* New server connection code |
1532 |
|
* Based upon the stuff floating about in s_bsd.c |
1533 |
|
* -- adrian |
1568 |
|
conf = unmap_conf_item(aconf); |
1569 |
|
|
1570 |
|
/* log */ |
1571 |
< |
irc_getnameinfo((struct sockaddr*)&aconf->ipnum, aconf->ipnum.ss_len, |
1572 |
< |
buf, HOSTIPLEN, NULL, 0, NI_NUMERICHOST); |
1571 |
> |
getnameinfo((struct sockaddr *)&aconf->ipnum, aconf->ipnum.ss_len, |
1572 |
> |
buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); |
1573 |
|
ilog(L_NOTICE, "Connect to %s[%s] @%s", aconf->user, aconf->host, |
1574 |
|
buf); |
1575 |
|
|
1576 |
|
/* Still processing a DNS lookup? -> exit */ |
1577 |
< |
if (aconf->dns_query != NULL) |
1577 |
> |
if (aconf->dns_pending) |
1578 |
|
{ |
1579 |
< |
sendto_realops_flags(UMODE_ALL, L_OPER, |
1580 |
< |
"Error connecting to %s: Error during DNS lookup", conf->name); |
1579 |
> |
sendto_realops_flags(UMODE_ALL, L_ALL, |
1580 |
> |
"Error connecting to %s: DNS lookup for connect{} in progress.", |
1581 |
> |
conf->name); |
1582 |
> |
return (0); |
1583 |
> |
} |
1584 |
> |
|
1585 |
> |
if (aconf->dns_failed) |
1586 |
> |
{ |
1587 |
> |
sendto_realops_flags(UMODE_ALL, L_ALL, |
1588 |
> |
"Error connecting to %s: DNS lookup for connect{} failed.", |
1589 |
> |
conf->name); |
1590 |
|
return (0); |
1591 |
|
} |
1592 |
|
|
1616 |
|
strlcpy(client_p->host, aconf->host, sizeof(client_p->host)); |
1617 |
|
|
1618 |
|
/* We already converted the ip once, so lets use it - stu */ |
1619 |
< |
strlcpy(client_p->sockhost, buf, HOSTIPLEN); |
1619 |
> |
strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost)); |
1620 |
|
|
1621 |
|
/* create a socket for the server connection */ |
1622 |
|
if (comm_open(&client_p->localClient->fd, aconf->ipnum.ss.ss_family, |
1826 |
|
#endif |
1827 |
|
|
1828 |
|
/* jdc -- Check and send spasswd, not passwd. */ |
1829 |
< |
if (!EmptyString(aconf->spasswd) && (me.id[0] != '\0')) |
1829 |
> |
if (!EmptyString(aconf->spasswd)) |
1830 |
|
/* Send TS 6 form only if id */ |
1831 |
|
sendto_one(client_p, "PASS %s TS %d %s", |
1832 |
|
aconf->spasswd, TS_CURRENT, me.id); |
1893 |
– |
else |
1894 |
– |
sendto_one(client_p, "PASS %s TS 5", |
1895 |
– |
aconf->spasswd); |
1833 |
|
|
1834 |
|
/* Pass my info to the new server |
1835 |
|
* |
1899 |
– |
* If this is a HUB, pass on CAP_HUB |
1836 |
|
* Pass on ZIP if supported |
1837 |
|
* Pass on TB if supported. |
1838 |
|
* - Dianora |
1839 |
|
*/ |
1840 |
< |
send_capabilities(client_p, aconf, (ServerInfo.hub ? CAP_HUB : 0) |
1841 |
< |
| (IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1840 |
> |
send_capabilities(client_p, aconf, |
1841 |
> |
(IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1842 |
|
| (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0), 0); |
1843 |
|
|
1844 |
|
sendto_one(client_p, "SERVER %s 1 :%s%s", |
1845 |
< |
my_name_for_link(conf), |
1910 |
< |
ConfigServerHide.hidden ? "(H) " : "", |
1845 |
> |
me.name, ConfigServerHide.hidden ? "(H) " : "", |
1846 |
|
me.info); |
1847 |
|
|
1848 |
|
/* If we've been marked dead because a send failed, just exit |
1875 |
|
cptr = ptr->data; |
1876 |
|
|
1877 |
|
if (cptr && cptr->name[0]) |
1878 |
< |
if (match(cptr->name, name) || match(name, cptr->name)) |
1878 |
> |
if (match(name, cptr->name)) |
1879 |
|
return cptr; |
1880 |
|
} |
1881 |
|
|
1946 |
|
return; |
1947 |
|
} |
1948 |
|
|
1949 |
< |
send_capabilities(client_p, aconf, (ServerInfo.hub ? CAP_HUB : 0) |
1950 |
< |
| (IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1949 |
> |
send_capabilities(client_p, aconf, |
1950 |
> |
(IsConfCompressed(aconf) ? CAP_ZIP : 0) |
1951 |
|
| (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0), CAP_ENC_MASK); |
1952 |
|
|
1953 |
< |
if (me.id[0]) |
2019 |
< |
sendto_one(client_p, "PASS . TS %d %s", TS_CURRENT, me.id); |
2020 |
< |
|
1953 |
> |
sendto_one(client_p, "PASS . TS %d %s", TS_CURRENT, me.id); |
1954 |
|
sendto_one(client_p, "CRYPTLINK SERV %s %s :%s%s", |
1955 |
< |
my_name_for_link(conf), key_to_send, |
1955 |
> |
me.name, key_to_send, |
1956 |
|
ConfigServerHide.hidden ? "(H) " : "", me.info); |
1957 |
|
|
1958 |
|
SetHandshake(client_p); |