2 * IRC - Internet Relay Chat, ircd/m_server.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * m_functions execute protocol messages on this server:
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
84 * No need to include handlers.h here the signatures must match
85 * and we don't need to force a rebuild of all the handlers everytime
86 * we add a new one to the list. --Bleep
95 #include "ircd_reply.h"
96 #include "ircd_string.h"
102 #include "numnicks.h"
103 #include "querycmds.h"
110 #include "userload.h"
117 * mr_server - registration message handler
119 * parv[0] = sender prefix
120 * parv[1] = servername
122 * parv[3] = start timestamp
123 * parv[4] = link timestamp
124 * parv[5] = major protocol version: P09/P10
125 * parv[parc-1] = serverinfo
127 * parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
128 * numeric nick mask of this server.
129 * parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
131 int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
135 char info[REALLEN + 1];
137 struct Client* acptr;
138 struct Client* bcptr;
139 struct Client* LHcptr = 0;
140 struct ConfItem* aconf = 0;
141 struct ConfItem* cconf;
142 struct ConfItem* lhconf = 0;
143 struct Jupe* ajupe = 0;
146 int active_lh_line = 0;
148 time_t start_timestamp;
149 time_t timestamp = 0;
153 if (IsUserPort(cptr))
154 return exit_client_msg(cptr, cptr, &me,
155 "Cannot connect a server to a user port");
157 recv_time = TStime();
162 return need_more_params(sptr, "SERVER");
163 return exit_client(cptr, cptr, &me, "Need more parameters");
167 if ((ajupe = jupe_find(host)) && JupeIsActive(ajupe))
168 return exit_client_msg(cptr, sptr, &me, "Juped: %s", JupeReason(ajupe));
170 ircd_log(L_NOTICE, "SERVER: %s %s[%s]", parv[1], cptr->sockhost, cptr->sock_ip);
175 if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
176 return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
178 if (!IsServer(cptr)) /* Don't allow silently connecting a server */
181 prot = atoi(parv[5] + 1);
182 if (prot > atoi(MAJOR_PROTOCOL))
183 prot = atoi(MAJOR_PROTOCOL);
185 * Because the previous test is only in 2.10, the following is needed
186 * till all servers are 2.10:
188 if (IsServer(cptr) && prot > Protocol(cptr))
189 prot = Protocol(cptr);
191 start_timestamp = atoi(parv[3]);
192 timestamp = atoi(parv[4]);
193 Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
194 TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
196 if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
198 return exit_client_msg(cptr, sptr, &me,
199 "Bogus timestamps (%s %s)", parv[3], parv[4]);
201 ircd_strncpy(info, parv[parc - 1], REALLEN);
202 info[REALLEN] = '\0';
203 if (prot < atoi(MINOR_PROTOCOL)) {
204 sendto_opmask_butone(0, SNO_OLDSNO, "Got incompatible protocol version "
205 "(%s) from %s", parv[5], cptr->name);
206 return exit_new_server(cptr, sptr, host, timestamp,
207 "Incompatible protocol: %s", parv[5]);
210 * Check for "FRENCH " infection ;-) (actually this should
211 * be replaced with routine to check the hostname syntax in
212 * general). [ This check is still needed, even after the parse
213 * is fixed, because someone can send "SERVER :foo bar " ].
214 * Also, changed to check other "difficult" characters, now
215 * that parse lets all through... --msa
217 if (strlen(host) > HOSTLEN)
218 host[HOSTLEN] = '\0';
220 for (ch = host; *ch; ch++) {
221 if (*ch <= ' ' || *ch > '~')
224 if (*ch || !strchr(host, '.')) {
225 sendto_opmask_butone(0, SNO_OLDSNO, "Bogus server name (%s) from %s",
227 return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
233 * A local server introduces a new server behind this link.
234 * Check if this is allowed according L:, H: and Q: lines.
237 return exit_client_msg(cptr, cptr, &me,
238 "No server info specified for %s", host);
240 * See if the newly found server is behind a guaranteed
241 * leaf (L-line). If so, close the link.
243 if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
244 (!lhconf->port || (hop > lhconf->port)))
247 * L: lines normally come in pairs, here we try to
248 * make sure that the oldest link is squitted, not
252 if (timestamp <= cptr->serv->timestamp)
253 LHcptr = 0; /* Kill incoming server */
255 LHcptr = cptr; /* Squit ourselfs */
257 else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
258 (lhconf->port && (hop > lhconf->port)))
260 struct Client *ac3ptr;
262 /* Look for net junction causing this: */
263 LHcptr = 0; /* incoming server */
264 if (*parv[5] != 'J') {
265 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
266 if (IsJunction(ac3ptr)) {
275 if (IsUnknown(cptr) || IsHandshake(cptr))
280 * A local link that is still in undefined state wants
281 * to be a SERVER. Check if this is allowed and change
282 * status accordingly...
285 * If there is more then one server on the same machine
286 * that we try to connect to, it could be that the /CONNECT
287 * <mask> caused this connect to be put at the wrong place
288 * in the hashtable. --Run
289 * Same thing for Unknown connections that first send NICK.
291 * Better check if the two strings are (caseless) identical
292 * and not mess with hash internals.
295 if (!EmptyString(cptr->name) &&
296 (IsUnknown(cptr) || IsHandshake(cptr)) &&
297 0 != ircd_strcmp(cptr->name, host))
298 hChangeClient(cptr, host);
299 ircd_strncpy(cptr->name, host, HOSTLEN);
300 ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
301 cptr->hopcount = hop;
303 /* check connection rules */
304 for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
305 if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
306 if (crule_eval(cconf->passwd)) {
307 ServerStats->is_ref++;
308 sendto_opmask_butone(0, SNO_OLDSNO, "Refused connection from %s.",
310 return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
314 if (conf_check_server(cptr)) {
315 ++ServerStats->is_ref;
316 sendto_opmask_butone(0, SNO_OLDSNO, "Received unauthorized connection "
317 "from %s.", cptr->name);
318 return exit_client(cptr, cptr, &me, "No C:line");
325 if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
326 ++ServerStats->is_ref;
328 sendto_opmask_butone(0, SNO_OLDSNO, "Access denied. No conf line for "
329 "server %s", cptr->name);
330 return exit_client_msg(cptr, cptr, &me,
331 "Access denied. No conf line for server %s", cptr->name);
333 sendto_opmask_butone(0, SNO_OLDSNO, "General C: line active: No line "
334 "for server %s", cptr->name);
335 aconf = find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
337 sendto_opmask_butone(0, SNO_OLDSNO, "Neither C lines for server %s "
338 "nor \"general.undernet.org\"", cptr->name);
339 return exit_client_msg(cptr, cptr, &me, "No C lines for server %s", cptr->name);
343 #ifdef CRYPT_LINK_PASSWORD
344 /* passwd may be NULL. Head it off at the pass... */
348 salt[0] = aconf->passwd[0];
349 salt[1] = aconf->passwd[1];
351 encr = ircd_crypt(cptr->passwd, salt);
357 #endif /* CRYPT_LINK_PASSWORD */
359 if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
360 ++ServerStats->is_ref;
361 sendto_opmask_butone(0, SNO_OLDSNO, "Access denied (passwd mismatch) %s",
363 return exit_client_msg(cptr, cptr, &me,
364 "No Access (passwd mismatch) %s", cptr->name);
366 #endif /* not GODMODE */
367 memset(cptr->passwd, 0, sizeof(cptr->passwd));
370 for (i = 0; i <= HighestFd; i++)
371 if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
380 * We want to find IsConnecting() and IsHandshake() too,
382 * The second finds collisions with numeric representation of existing
383 * servers - these shouldn't happen anymore when all upgraded to 2.10.
386 while ((acptr = FindClient(host)) ||
387 (parc > 7 && (acptr = FindNServer(parv[6]))))
390 * This link is trying feed me a server that I already have
391 * access through another path
393 * Do not allow Uworld to do this.
394 * Do not allow servers that are juped.
395 * Do not allow servers that have older link timestamps
397 * Do not allow servers that use the same numeric as an existing
398 * server, but have a different name.
400 * If my ircd.conf sucks, I can try to connect to myself:
403 return exit_client_msg(cptr, cptr, &me, "nick collision with me (%s), check server number in M:?", host);
405 * Detect wrong numeric.
407 if (0 != ircd_strcmp(acptr->name, host)) {
408 sendcmdto_serv_butone(&me, CMD_WALLOPS, cptr,
409 ":SERVER Numeric Collision: %s != %s",
411 return exit_client_msg(cptr, cptr, &me,
412 "NUMERIC collision between %s and %s."
413 " Is your server numeric correct ?", host, acptr->name);
416 * Kill our try, if we had one.
418 if (IsConnecting(acptr))
420 if (!active_lh_line && exit_client(cptr, acptr, &me,
421 "Just connected via another link") == CPTR_KILLED)
424 * We can have only ONE 'IsConnecting', 'IsHandshake' or
425 * 'IsServer', because new 'IsConnecting's are refused to
426 * the same server if we already had it.
431 * Avoid other nick collisions...
432 * This is a doubtfull test though, what else would it be
433 * when it has a server.name ?
435 else if (!IsServer(acptr) && !IsHandshake(acptr))
436 return exit_client_msg(cptr, cptr, &me,
437 "Nickname %s already exists!", host);
439 * Our new server might be a juped server,
440 * or someone trying abuse a second Uworld:
442 else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
443 find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
446 return exit_client(cptr, sptr, &me, acptr->info);
447 sendcmdto_serv_butone(&me, CMD_WALLOPS, cptr,
448 ":Received :%s SERVER %s from %s !?!", parv[0],
449 parv[1], cptr->name);
450 return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
453 * Of course we find the handshake this link was before :)
455 else if (IsHandshake(acptr) && acptr == cptr)
458 * Here we have a server nick collision...
459 * We don't want to kill the link that was last /connected,
460 * but we neither want to kill a good (old) link.
461 * Therefor we kill the second youngest link.
465 struct Client* c2ptr = 0;
466 struct Client* c3ptr = acptr;
467 struct Client* ac2ptr;
468 struct Client* ac3ptr;
470 /* Search youngest link: */
471 for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
472 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
476 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
477 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
480 if (timestamp > c3ptr->serv->timestamp)
483 c2ptr = acptr; /* Make sure they differ */
485 /* Search second youngest link: */
486 for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
487 if (ac2ptr != c3ptr &&
488 ac2ptr->serv->timestamp >
489 (c2ptr ? c2ptr->serv->timestamp : timestamp))
493 for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
494 if (ac2ptr != c3ptr &&
495 ac2ptr->serv->timestamp >
496 (c2ptr ? c2ptr->serv->timestamp : timestamp))
499 if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
501 /* If timestamps are equal, decide which link to break
504 if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
505 (c3ptr ? c3ptr->serv->timestamp : timestamp))
514 n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
519 n2up = IsServer(sptr) ? sptr->name : me.name;
524 n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
529 n3up = IsServer(sptr) ? sptr->name : me.name;
531 if (strcmp(n2, n2up) > 0)
533 if (strcmp(n3, n3up) > 0)
535 if (strcmp(n3, n2) > 0)
542 /* Now squit the second youngest link: */
544 return exit_new_server(cptr, sptr, host, timestamp,
545 "server %s already exists and is %ld seconds younger.",
546 host, (long)acptr->serv->timestamp - (long)timestamp);
547 else if (c2ptr->from == cptr || IsServer(sptr))
549 struct Client *killedptrfrom = c2ptr->from;
553 * If the L: or H: line also gets rid of this link,
554 * we sent just one squit.
556 if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
559 * If breaking the loop here solves the L: or H:
560 * line problem, we don't squit that.
562 if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
567 * If we still have a L: or H: line problem,
568 * we prefer to squit the new server, solving
569 * loop and L:/H: line problem with only one squit.
576 * If the new server was introduced by a server that caused a
577 * Ghost less then 20 seconds ago, this is probably also
578 * a Ghost... (20 seconds is more then enough because all
579 * SERVER messages are at the beginning of a net.burst). --Run
581 if (CurrentTime - cptr->serv->ghost < 20)
583 killedptrfrom = acptr->from;
584 if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
587 else if (exit_client_msg(cptr, c2ptr, &me,
588 "Loop <-- %s (new link is %ld seconds younger)", host,
589 (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
590 (long)c2ptr->serv->timestamp) == CPTR_KILLED)
593 * Did we kill the incoming server off already ?
595 if (killedptrfrom == cptr)
602 if (LHcptr && a_kills_b_too(LHcptr, acptr))
604 if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
613 * We can't believe it is a lagged server message
614 * when it directly connects to us...
615 * kill the older link at the ghost, rather then
616 * at the second youngest link, assuming it isn't
619 ghost = CurrentTime; /* Mark that it caused a ghost */
620 if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
630 return exit_new_server(cptr, sptr, host, timestamp,
631 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s), check H:" :
632 "Leaf-only link %s <- %s(%s), check L:",
634 lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
638 int killed = a_kills_b_too(LHcptr, sptr);
639 if (active_lh_line < 3)
641 if (exit_client_msg(cptr, LHcptr, &me,
642 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s), check H:" :
643 "Leaf-only link %s <- %s(%s), check L:",
645 lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
650 ServerStats->is_ref++;
651 if (exit_client(cptr, LHcptr, &me, "I'm a leaf, define HUB") == CPTR_KILLED)
655 * Did we kill the incoming server off already ?
665 * Server is informing about a new server behind
666 * this link. Create REMOTE server structure,
667 * add it to list and propagate word to my other
671 acptr = make_client(cptr, STAT_SERVER);
673 acptr->serv->prot = prot;
674 acptr->serv->timestamp = timestamp;
675 acptr->hopcount = hop;
676 ircd_strncpy(acptr->name, host, HOSTLEN);
677 ircd_strncpy(acptr->info, info, REALLEN);
678 acptr->serv->up = sptr;
679 acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
680 /* Use cptr, because we do protocol 9 -> 10 translation
681 for numeric nicks ! */
682 SetServerYXX(cptr, acptr, parv[6]);
684 Count_newremoteserver(UserStats);
685 if (Protocol(acptr) < 10)
686 acptr->flags |= FLAGS_TS8;
687 add_client_to_list(acptr);
692 sendto_opmask_butone(0, SNO_NETWORK, "Net junction: %s %s",
693 sptr->name, acptr->name);
697 * Old sendto_serv_but_one() call removed because we now need to send
698 * different names to different servers (domain name matching).
700 * Personally, I think this is bogus; it's a feature we don't use here.
703 for (i = 0; i <= HighestFd; i++)
705 if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
706 bcptr == cptr || IsMe(bcptr))
708 if (0 == match(me.name, acptr->name))
710 sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s 0 :%s",
711 acptr->name, hop + 1, parv[4], parv[5], NumServCap(acptr),
717 if (IsUnknown(cptr) || IsHandshake(cptr))
720 cptr->serv->timestamp = timestamp;
721 cptr->serv->prot = prot;
722 cptr->serv->ghost = ghost;
723 SetServerYXX(cptr, cptr, parv[6]);
724 if (start_timestamp > OLDEST_TS)
726 #ifndef RELIABLE_CLOCK
728 sendto_opmask_butone(0, SNO_OLDSNO, "Debug: my start time: %Tu ; "
729 "others start time: %Tu", me.serv->timestamp,
731 sendto_opmask_butone(0, SNO_OLDSNO, "Debug: receive time: %Tu ; "
732 "received timestamp: %Tu ; difference %ld",
733 recv_time, timestamp, timestamp - recv_time);
735 if (start_timestamp < me.serv->timestamp)
737 sendto_opmask_butone(0, SNO_OLDSNO, "got earlier start time: "
738 "%Tu < %Tu", start_timestamp, me.serv->timestamp);
739 me.serv->timestamp = start_timestamp;
740 TSoffset += timestamp - recv_time;
741 sendto_opmask_butone(0, SNO_OLDSNO, "clock adjusted by adding %d",
742 (int)(timestamp - recv_time));
744 else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
745 cptr->serv->timestamp = TStime();
747 else if (timestamp != recv_time)
750 * Equal start times, we have a collision. Let the connected-to server
751 * decide. This assumes leafs issue more than half of the connection
755 cptr->serv->timestamp = TStime();
756 else if (IsHandshake(cptr))
758 sendto_opmask_butone(0, SNO_OLDSNO, "clock adjusted by adding %d",
759 (int)(timestamp - recv_time));
760 TSoffset += timestamp - recv_time;
763 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
764 if (start_timestamp < me.serv->timestamp)
765 me.serv->timestamp = start_timestamp;
767 cptr->serv->timestamp = TStime();
771 ret = server_estab(cptr, aconf, ajupe);
775 #ifdef RELIABLE_CLOCK
776 if (abs(cptr->serv->timestamp - recv_time) > 30)
778 sendto_opmask_butone(0, SNO_OLDSNO, "Connected to a net with a "
779 "timestamp-clock difference of %Td seconds! "
780 "Used SETTIME to correct this.",
781 timestamp - recv_time);
782 sendcmdto_one(&me, CMD_SETTIME, cptr, "%Tu :%s", TStime(), me.name);
790 * ms_server - server message handler
792 * parv[0] = sender prefix
793 * parv[1] = servername
795 * parv[3] = start timestamp
796 * parv[4] = link timestamp
797 * parv[5] = major protocol version: P09/P10
798 * parv[parc-1] = serverinfo
800 * parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
801 * numeric nick mask of this server.
802 * parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
803 * parv[8] = %<lastmod> - optional parameter only present if there's an
804 * outstanding JUPE; specifies the JUPE's lastmod field
806 int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
810 char info[REALLEN + 1];
812 struct Client* acptr;
813 struct Client* bcptr;
814 struct Client* LHcptr = 0;
815 struct ConfItem* aconf = 0;
816 struct ConfItem* cconf;
817 struct ConfItem* lhconf = 0;
818 struct Jupe* ajupe = 0;
821 int active_lh_line = 0;
823 time_t start_timestamp;
824 time_t timestamp = 0;
829 if (IsUserPort(cptr))
830 return exit_client_msg(cptr, cptr, &me,
831 "Cannot connect a server to a user port");
833 recv_time = TStime();
837 return need_more_params(sptr, "SERVER");
838 return exit_client(cptr, cptr, &me, "Need more parameters");
845 if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
846 return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
848 if (!IsServer(cptr)) /* Don't allow silently connecting a server */
851 prot = atoi(parv[5] + 1);
852 if (prot > atoi(MAJOR_PROTOCOL))
853 prot = atoi(MAJOR_PROTOCOL);
855 * Because the previous test is only in 2.10, the following is needed
856 * till all servers are 2.10:
858 if (IsServer(cptr) && prot > Protocol(cptr))
859 prot = Protocol(cptr);
861 start_timestamp = atoi(parv[3]);
862 timestamp = atoi(parv[4]);
863 Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
864 TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
865 if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
867 return exit_client_msg(cptr, sptr, &me,
868 "Bogus timestamps (%s %s)", parv[3], parv[4]);
870 ircd_strncpy(info, parv[parc - 1], REALLEN);
871 info[REALLEN] = '\0';
872 if (prot < atoi(MINOR_PROTOCOL)) {
873 sendto_opmask_butone(0, SNO_OLDSNO, "Got incompatible protocol version "
874 "(%s) from %s", parv[5], cptr->name);
875 return exit_new_server(cptr, sptr, host, timestamp,
876 "Incompatible protocol: %s", parv[5]);
878 if (parc > 9 && *parv[8] == '%')
879 lastmod = atoi(parv[8] + 1);
880 /* If there's a jupe that matches, and it's a global jupe, and the
881 * introducer didn't indicate it knew of the jupe or has an older
882 * version of the jupe, and the connection isn't in a BURST, resynch
885 if ((ajupe = jupe_find(host)) && !JupeIsLocal(ajupe) &&
886 JupeLastMod(ajupe) > lastmod && !IsBurstOrBurstAck(cptr))
887 jupe_resend(cptr, ajupe);
889 * Check for "FRENCH " infection ;-) (actually this should
890 * be replaced with routine to check the hostname syntax in
891 * general). [ This check is still needed, even after the parse
892 * is fixed, because someone can send "SERVER :foo bar " ].
893 * Also, changed to check other "difficult" characters, now
894 * that parse lets all through... --msa
896 if (strlen(host) > HOSTLEN)
897 host[HOSTLEN] = '\0';
898 for (ch = host; *ch; ch++)
899 if (*ch <= ' ' || *ch > '~')
901 if (*ch || !strchr(host, '.')) {
902 sendto_opmask_butone(0, SNO_OLDSNO, "Bogus server name (%s) from %s",
904 return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
910 * A local server introduces a new server behind this link.
911 * Check if this is allowed according L:, H: and Q: lines.
914 return exit_client_msg(cptr, cptr, &me,
915 "No server info specified for %s", host);
917 * See if the newly found server is behind a guaranteed
918 * leaf (L-line). If so, close the link.
920 if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
921 (!lhconf->port || (hop > lhconf->port)))
924 * L: lines normally come in pairs, here we try to
925 * make sure that the oldest link is squitted, not
929 if (timestamp <= cptr->serv->timestamp)
930 LHcptr = 0; /* Kill incoming server */
932 LHcptr = cptr; /* Squit ourselfs */
934 else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
935 (lhconf->port && (hop > lhconf->port)))
937 struct Client *ac3ptr;
939 /* Look for net junction causing this: */
940 LHcptr = 0; /* incoming server */
941 if (*parv[5] != 'J') {
942 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
943 if (IsJunction(ac3ptr)) {
952 if (IsUnknown(cptr) || IsHandshake(cptr))
957 * A local link that is still in undefined state wants
958 * to be a SERVER. Check if this is allowed and change
959 * status accordingly...
962 * If there is more then one server on the same machine
963 * that we try to connect to, it could be that the /CONNECT
964 * <mask> caused this connect to be put at the wrong place
965 * in the hashtable. --Run
966 * Same thing for Unknown connections that first send NICK.
968 * Better check if the two strings are (caseless) identical
969 * and not mess with hash internals.
972 if ((!(EmptyString(cptr->name)))
973 && (IsUnknown(cptr) || IsHandshake(cptr))
974 && 0 != ircd_strcmp(cptr->name, host))
975 hChangeClient(cptr, host);
976 ircd_strncpy(cptr->name, host, HOSTLEN);
977 ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
978 cptr->hopcount = hop;
980 /* check connection rules */
981 for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
982 if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
983 if (crule_eval(cconf->passwd))
985 ServerStats->is_ref++;
986 sendto_opmask_butone(0, SNO_OLDSNO, "Refused connection from %s.",
988 return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
992 if (conf_check_server(cptr)) {
993 ++ServerStats->is_ref;
994 sendto_opmask_butone(0, SNO_OLDSNO, "Received unauthorized connection "
995 "from %s.", cptr->name);
996 return exit_client(cptr, cptr, &me, "No C conf lines");
1003 if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
1004 ++ServerStats->is_ref;
1006 sendto_opmask_butone(0, SNO_OLDSNO, "Access denied. No conf line for "
1007 "server %s", cptr->name);
1008 return exit_client_msg(cptr, cptr, &me,
1009 "Access denied. No conf line for server %s", cptr->name);
1011 sendto_opmask_butone(0, SNO_OLDSNO, "General C line active: No line "
1012 "for server %s", cptr->name);
1014 find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
1016 sendto_opmask_butone(0, SNO_OLDSNO, "Neither C lines for server %s "
1017 "nor \"general.undernet.org\"", cptr->name);
1018 return exit_client_msg(cptr, cptr, &me,
1019 "No C lines for server %s", cptr->name);
1021 #endif /* GODMODE */
1023 #ifdef CRYPT_LINK_PASSWORD
1024 /* passwd may be NULL. Head it off at the pass... */
1029 salt[0] = aconf->passwd[0];
1030 salt[1] = aconf->passwd[1];
1032 encr = ircd_crypt(cptr->passwd, salt);
1037 encr = cptr->passwd;
1038 #endif /* CRYPT_LINK_PASSWORD */
1040 if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1041 ++ServerStats->is_ref;
1042 sendto_opmask_butone(0, SNO_OLDSNO, "Access denied (passwd mismatch) %s",
1044 return exit_client_msg(cptr, cptr, &me,
1045 "No Access (passwd mismatch) %s", cptr->name);
1047 #endif /* not GODMODE */
1048 memset(cptr->passwd, 0, sizeof(cptr->passwd));
1051 for (i = 0; i <= HighestFd; i++)
1052 if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1061 * We want to find IsConnecting() and IsHandshake() too,
1063 * The second finds collisions with numeric representation of existing
1064 * servers - these shouldn't happen anymore when all upgraded to 2.10.
1067 while ((acptr = FindClient(host)) ||
1068 (parc > 7 && (acptr = FindNServer(parv[6]))))
1071 * This link is trying feed me a server that I already have
1072 * access through another path
1074 * Do not allow Uworld to do this.
1075 * Do not allow servers that are juped.
1076 * Do not allow servers that have older link timestamps
1078 * Do not allow servers that use the same numeric as an existing
1079 * server, but have a different name.
1081 * If my ircd.conf sucks, I can try to connect to myself:
1084 return exit_client_msg(cptr, cptr, &me,
1085 "nick collision with me, check server number in M:? (%s)", host);
1087 * Detect wrong numeric.
1089 if (0 != ircd_strcmp(acptr->name, host))
1091 sendcmdto_serv_butone(&me, CMD_WALLOPS, cptr,
1092 ":SERVER Numeric Collision: %s != %s", acptr->name,
1094 return exit_client_msg(cptr, cptr, &me,
1095 "NUMERIC collision between %s and %s."
1096 " Is your server numeric correct ?", host, acptr->name);
1099 * Kill our try, if we had one.
1101 if (IsConnecting(acptr))
1103 if (!active_lh_line && exit_client(cptr, acptr, &me,
1104 "Just connected via another link") == CPTR_KILLED)
1107 * We can have only ONE 'IsConnecting', 'IsHandshake' or
1108 * 'IsServer', because new 'IsConnecting's are refused to
1109 * the same server if we already had it.
1114 * Avoid other nick collisions...
1115 * This is a doubtfull test though, what else would it be
1116 * when it has a server.name ?
1118 else if (!IsServer(acptr) && !IsHandshake(acptr))
1119 return exit_client_msg(cptr, cptr, &me,
1120 "Nickname %s already exists!", host);
1122 * Our new server might be a juped server,
1123 * or someone trying abuse a second Uworld:
1125 else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1126 find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1128 if (!IsServer(sptr))
1129 return exit_client(cptr, sptr, &me, acptr->info);
1130 sendcmdto_one(&me, CMD_WALLOPS, cptr, ":Received :%s SERVER %s "
1131 "from %s !?!", parv[0], parv[1], cptr->name);
1132 return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1135 * Of course we find the handshake this link was before :)
1137 else if (IsHandshake(acptr) && acptr == cptr)
1140 * Here we have a server nick collision...
1141 * We don't want to kill the link that was last /connected,
1142 * but we neither want to kill a good (old) link.
1143 * Therefor we kill the second youngest link.
1147 struct Client* c2ptr = 0;
1148 struct Client* c3ptr = acptr;
1149 struct Client* ac2ptr;
1150 struct Client* ac3ptr;
1152 /* Search youngest link: */
1153 for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1154 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1158 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1159 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1162 if (timestamp > c3ptr->serv->timestamp)
1165 c2ptr = acptr; /* Make sure they differ */
1167 /* Search second youngest link: */
1168 for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1169 if (ac2ptr != c3ptr &&
1170 ac2ptr->serv->timestamp >
1171 (c2ptr ? c2ptr->serv->timestamp : timestamp))
1175 for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1176 if (ac2ptr != c3ptr &&
1177 ac2ptr->serv->timestamp >
1178 (c2ptr ? c2ptr->serv->timestamp : timestamp))
1181 if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1183 /* If timestamps are equal, decide which link to break
1186 if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1187 (c3ptr ? c3ptr->serv->timestamp : timestamp))
1196 n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1201 n2up = IsServer(sptr) ? sptr->name : me.name;
1206 n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1211 n3up = IsServer(sptr) ? sptr->name : me.name;
1213 if (strcmp(n2, n2up) > 0)
1215 if (strcmp(n3, n3up) > 0)
1217 if (strcmp(n3, n2) > 0)
1224 /* Now squit the second youngest link: */
1226 return exit_new_server(cptr, sptr, host, timestamp,
1227 "server %s already exists and is %ld seconds younger.",
1228 host, (long)acptr->serv->timestamp - (long)timestamp);
1229 else if (c2ptr->from == cptr || IsServer(sptr))
1231 struct Client *killedptrfrom = c2ptr->from;
1235 * If the L: or H: line also gets rid of this link,
1236 * we sent just one squit.
1238 if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1241 * If breaking the loop here solves the L: or H:
1242 * line problem, we don't squit that.
1244 if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1249 * If we still have a L: or H: line problem,
1250 * we prefer to squit the new server, solving
1251 * loop and L:/H: line problem with only one squit.
1258 * If the new server was introduced by a server that caused a
1259 * Ghost less then 20 seconds ago, this is probably also
1260 * a Ghost... (20 seconds is more then enough because all
1261 * SERVER messages are at the beginning of a net.burst). --Run
1263 if (CurrentTime - cptr->serv->ghost < 20)
1265 killedptrfrom = acptr->from;
1266 if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1269 else if (exit_client_msg(cptr, c2ptr, &me,
1270 "Loop <-- %s (new link is %ld seconds younger)", host,
1271 (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1272 (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1275 * Did we kill the incoming server off already ?
1277 if (killedptrfrom == cptr)
1284 if (LHcptr && a_kills_b_too(LHcptr, acptr))
1286 if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1295 * We can't believe it is a lagged server message
1296 * when it directly connects to us...
1297 * kill the older link at the ghost, rather then
1298 * at the second youngest link, assuming it isn't
1301 ghost = CurrentTime; /* Mark that it caused a ghost */
1302 if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1312 return exit_new_server(cptr, sptr, host, timestamp,
1313 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1315 lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1319 int killed = a_kills_b_too(LHcptr, sptr);
1320 if (active_lh_line < 3)
1322 if (exit_client_msg(cptr, LHcptr, &me,
1323 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1325 lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1330 ServerStats->is_ref++;
1331 if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
1335 * Did we kill the incoming server off already ?
1345 * Server is informing about a new server behind
1346 * this link. Create REMOTE server structure,
1347 * add it to list and propagate word to my other
1351 acptr = make_client(cptr, STAT_SERVER);
1353 acptr->serv->prot = prot;
1354 acptr->serv->timestamp = timestamp;
1355 acptr->hopcount = hop;
1356 ircd_strncpy(acptr->name, host, HOSTLEN);
1357 ircd_strncpy(acptr->info, info, REALLEN);
1358 acptr->serv->up = sptr;
1359 acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
1360 /* Use cptr, because we do protocol 9 -> 10 translation
1361 for numeric nicks ! */
1362 SetServerYXX(cptr, acptr, parv[6]);
1364 Count_newremoteserver(UserStats);
1365 if (Protocol(acptr) < 10)
1366 acptr->flags |= FLAGS_TS8;
1367 add_client_to_list(acptr);
1369 if (*parv[5] == 'J')
1372 sendto_opmask_butone(0, SNO_NETWORK, "Net junction: %s %s",
1373 sptr->name, acptr->name);
1377 * Old sendto_serv_but_one() call removed because we now need to send
1378 * different names to different servers (domain name matching).
1380 for (i = 0; i <= HighestFd; i++)
1382 if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
1383 bcptr == cptr || IsMe(bcptr))
1385 if (0 == match(me.name, acptr->name))
1387 sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s 0 :%s",
1388 acptr->name, hop + 1, parv[4], parv[5], NumServCap(acptr),
1394 if (IsUnknown(cptr) || IsHandshake(cptr))
1397 cptr->serv->timestamp = timestamp;
1398 cptr->serv->prot = prot;
1399 cptr->serv->ghost = ghost;
1400 SetServerYXX(cptr, cptr, parv[6]);
1401 if (start_timestamp > OLDEST_TS)
1403 #ifndef RELIABLE_CLOCK
1405 sendto_opmask_butone(0, SNO_OLDSNO, "Debug: my start time: %Tu ; "
1406 "others start time: %Tu", me.serv->timestamp,
1408 sendto_opmask_butone(0, SNO_OLDSNO, "Debug: receive time: %Tu ; "
1409 "received timestamp: %Tu ; difference %ld",
1410 recv_time, timestamp, timestamp - recv_time);
1412 if (start_timestamp < me.serv->timestamp)
1414 sendto_opmask_butone(0, SNO_OLDSNO, "got earlier start time: "
1415 "%Tu < %Tu", start_timestamp, me.serv->timestamp);
1416 me.serv->timestamp = start_timestamp;
1417 TSoffset += timestamp - recv_time;
1418 sendto_opmask_butone(0, SNO_OLDSNO, "clock adjusted by adding %d",
1419 (int)(timestamp - recv_time));
1421 else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
1422 cptr->serv->timestamp = TStime();
1424 else if (timestamp != recv_time)
1427 * Equal start times, we have a collision. Let the connected-to server
1428 * decide. This assumes leafs issue more than half of the connection
1431 if (IsUnknown(cptr))
1432 cptr->serv->timestamp = TStime();
1433 else if (IsHandshake(cptr))
1435 sendto_opmask_butone(0, SNO_OLDSNO, "clock adjusted by adding %d",
1436 (int)(timestamp - recv_time));
1437 TSoffset += timestamp - recv_time;
1440 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
1441 if (start_timestamp < me.serv->timestamp)
1442 me.serv->timestamp = start_timestamp;
1443 if (IsUnknown(cptr))
1444 cptr->serv->timestamp = TStime();
1448 ret = server_estab(cptr, aconf, ajupe);
1452 #ifdef RELIABLE_CLOCK
1453 if (abs(cptr->serv->timestamp - recv_time) > 30)
1455 sendto_opmask_butone(0, SNO_OLDSNO, "Connected to a net with a "
1456 "timestamp-clock difference of %Td seconds! Used "
1457 "SETTIME to correct this.", timestamp - recv_time);
1458 sendcmdto_one(&me, CMD_SETTIME, cptr, "%Tu :%s", TStime(), me.name);
1470 * parv[0] = sender prefix
1471 * parv[1] = servername
1472 * parv[2] = hopcount
1473 * parv[3] = start timestamp
1474 * parv[4] = link timestamp
1475 * parv[5] = major protocol version: P09/P10
1476 * parv[parc-1] = serverinfo
1478 * parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
1479 * numeric nick mask of this server.
1480 * parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
1482 int m_server(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
1486 char info[REALLEN + 1];
1488 struct Client* acptr;
1489 struct Client* bcptr;
1490 struct Client* LHcptr = 0;
1491 struct ConfItem* aconf = 0;
1492 struct ConfItem* cconf;
1493 struct ConfItem* lhconf = 0;
1494 struct Jupe* ajupe = 0;
1497 int active_lh_line = 0;
1498 unsigned short prot;
1499 time_t start_timestamp;
1500 time_t timestamp = 0;
1506 sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]); /* XXX DEAD */
1510 if (IsUserPort(cptr))
1511 return exit_client_msg(cptr, cptr, &me,
1512 "You cannot connect a server to a user port; connect to %s port %u",
1513 me.name, server_port);
1515 recv_time = TStime();
1519 return need_more_params(sptr, "SERVER");
1520 return exit_client(cptr, cptr, &me, "Need more parameters");
1526 if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
1527 return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
1529 if (!IsServer(cptr)) /* Don't allow silently connecting a server */
1532 prot = atoi(parv[5] + 1);
1533 if (prot > atoi(MAJOR_PROTOCOL))
1534 prot = atoi(MAJOR_PROTOCOL);
1536 * Because the previous test is only in 2.10, the following is needed
1537 * till all servers are 2.10:
1539 if (IsServer(cptr) && prot > Protocol(cptr))
1540 prot = Protocol(cptr);
1541 hop = atoi(parv[2]);
1542 start_timestamp = atoi(parv[3]);
1543 timestamp = atoi(parv[4]);
1544 Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
1545 TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
1546 if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
1548 return exit_client_msg(cptr, sptr, &me,
1549 "Bogus timestamps (%s %s)", parv[3], parv[4]);
1551 ircd_strncpy(info, parv[parc - 1], REALLEN);
1552 info[REALLEN] = '\0';
1553 if (prot < atoi(MINOR_PROTOCOL)) {
1554 sendto_ops("Got incompatible protocol version (%s) from %s", /* XXX DEAD */
1555 parv[5], cptr->name);
1556 return exit_new_server(cptr, sptr, host, timestamp,
1557 "Incompatible protocol: %s", parv[5]);
1560 * Check for "FRENCH " infection ;-) (actually this should
1561 * be replaced with routine to check the hostname syntax in
1562 * general). [ This check is still needed, even after the parse
1563 * is fixed, because someone can send "SERVER :foo bar " ].
1564 * Also, changed to check other "difficult" characters, now
1565 * that parse lets all through... --msa
1567 if (strlen(host) > HOSTLEN)
1568 host[HOSTLEN] = '\0';
1569 for (ch = host; *ch; ch++)
1570 if (*ch <= ' ' || *ch > '~')
1572 if (*ch || !strchr(host, '.'))
1574 sendto_ops("Bogus server name (%s) from %s", host, cptr->name); /* XXX DEAD */
1575 return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
1581 * A local server introduces a new server behind this link.
1582 * Check if this is allowed according L:, H: and Q: lines.
1584 if (info[0] == '\0')
1585 return exit_client_msg(cptr, cptr, &me,
1586 "No server info specified for %s", host);
1588 * See if the newly found server is behind a guaranteed
1589 * leaf (L-line). If so, close the link.
1591 if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
1592 (!lhconf->port || (hop > lhconf->port)))
1595 * L: lines normally come in pairs, here we try to
1596 * make sure that the oldest link is squitted, not
1600 if (timestamp <= cptr->serv->timestamp)
1601 LHcptr = 0; /* Kill incoming server */
1603 LHcptr = cptr; /* Squit ourselfs */
1605 else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
1606 (lhconf->port && (hop > lhconf->port)))
1608 struct Client *ac3ptr;
1610 /* Look for net junction causing this: */
1611 LHcptr = 0; /* incoming server */
1612 if (*parv[5] != 'J') {
1613 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
1614 if (IsJunction(ac3ptr)) {
1623 if (IsUnknown(cptr) || IsHandshake(cptr))
1628 * A local link that is still in undefined state wants
1629 * to be a SERVER. Check if this is allowed and change
1630 * status accordingly...
1633 * If there is more then one server on the same machine
1634 * that we try to connect to, it could be that the /CONNECT
1635 * <mask> caused this connect to be put at the wrong place
1636 * in the hashtable. --Run
1637 * Same thing for Unknown connections that first send NICK.
1639 * Better check if the two strings are (caseless) identical
1640 * and not mess with hash internals.
1643 if ((!(EmptyString(cptr->name)))
1644 && (IsUnknown(cptr) || IsHandshake(cptr))
1645 && 0 != ircd_strcmp(cptr->name, host))
1646 hChangeClient(cptr, host);
1647 ircd_strncpy(cptr->name, host, HOSTLEN);
1648 ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
1649 cptr->hopcount = hop;
1651 /* check connection rules */
1652 for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
1653 if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
1654 if (crule_eval(cconf->passwd))
1656 ServerStats->is_ref++;
1657 sendto_ops("Refused connection from %s.", cptr->name); /* XXX DEAD */
1658 return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
1662 if (conf_check_server(cptr)) {
1663 ++ServerStats->is_ref;
1664 sendto_ops("Received unauthorized connection from %s.", cptr->name); /* XXX DEAD */
1665 return exit_client(cptr, cptr, &me, "No C/N conf lines");
1672 if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
1673 ++ServerStats->is_ref;
1675 sendto_ops("Access denied. No conf line for server %s", cptr->name); /* XXX DEAD */
1676 return exit_client_msg(cptr, cptr, &me,
1677 "Access denied. No conf line for server %s", cptr->name);
1679 sendto_ops("General C/N: line active: No line for server %s", cptr->name); /* XXX DEAD */
1681 find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
1683 sendto_ops("Neither C/N lines for server %s nor " /* XXX DEAD */
1684 "\"general.undernet.org\"", cptr->name);
1685 return exit_client_msg(cptr, cptr, &me,
1686 "No C/N lines for server %s", cptr->name);
1688 #endif /* GODMODE */
1690 #ifdef CRYPT_LINK_PASSWORD
1691 /* passwd may be NULL. Head it off at the pass... */
1696 salt[0] = aconf->passwd[0];
1697 salt[1] = aconf->passwd[1];
1699 encr = ircd_crypt(cptr->passwd, salt);
1704 encr = cptr->passwd;
1705 #endif /* CRYPT_LINK_PASSWORD */
1707 if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1708 ++ServerStats->is_ref;
1709 sendto_ops("Access denied (passwd mismatch) %s", cptr->name); /* XXX DEAD */
1710 return exit_client_msg(cptr, cptr, &me,
1711 "No Access (passwd mismatch) %s", cptr->name);
1713 #endif /* not GODMODE */
1714 memset(cptr->passwd, 0, sizeof(cptr->passwd));
1717 for (i = 0; i <= HighestFd; i++)
1718 if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1727 * We want to find IsConnecting() and IsHandshake() too,
1729 * The second finds collisions with numeric representation of existing
1730 * servers - these shouldn't happen anymore when all upgraded to 2.10.
1733 while ((acptr = FindClient(host)) ||
1734 (parc > 7 && (acptr = FindNServer(parv[6]))))
1737 * This link is trying feed me a server that I already have
1738 * access through another path
1740 * Do not allow Uworld to do this.
1741 * Do not allow servers that are juped.
1742 * Do not allow servers that have older link timestamps
1744 * Do not allow servers that use the same numeric as an existing
1745 * server, but have a different name.
1747 * If my ircd.conf sucks, I can try to connect to myself:
1750 return exit_client_msg(cptr, cptr, &me,
1751 "nick collision with me, check server number in M:? (%s)", host);
1753 * Detect wrong numeric.
1755 if (0 != ircd_strcmp(acptr->name, host))
1757 sendto_serv_butone(cptr, /* XXX DEAD */
1758 ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
1759 me.name, acptr->name, host);
1760 return exit_client_msg(cptr, cptr, &me,
1761 "NUMERIC collision between %s and %s."
1762 " Is your server numeric correct ?", host, acptr->name);
1765 * Kill our try, if we had one.
1767 if (IsConnecting(acptr))
1769 if (!active_lh_line && exit_client(cptr, acptr, &me,
1770 "Just connected via another link") == CPTR_KILLED)
1773 * We can have only ONE 'IsConnecting', 'IsHandshake' or
1774 * 'IsServer', because new 'IsConnecting's are refused to
1775 * the same server if we already had it.
1780 * Avoid other nick collisions...
1781 * This is a doubtfull test though, what else would it be
1782 * when it has a server.name ?
1784 else if (!IsServer(acptr) && !IsHandshake(acptr))
1785 return exit_client_msg(cptr, cptr, &me,
1786 "Nickname %s already exists!", host);
1788 * Our new server might be a juped server,
1789 * or someone trying abuse a second Uworld:
1791 else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1792 find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1794 if (!IsServer(sptr))
1795 return exit_client(cptr, sptr, &me, acptr->info);
1796 sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!", /* XXX DEAD */
1797 me.name, parv[0], parv[1], cptr->name);
1798 return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1801 * Of course we find the handshake this link was before :)
1803 else if (IsHandshake(acptr) && acptr == cptr)
1806 * Here we have a server nick collision...
1807 * We don't want to kill the link that was last /connected,
1808 * but we neither want to kill a good (old) link.
1809 * Therefor we kill the second youngest link.
1813 struct Client* c2ptr = 0;
1814 struct Client* c3ptr = acptr;
1815 struct Client* ac2ptr;
1816 struct Client* ac3ptr;
1818 /* Search youngest link: */
1819 for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1820 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1824 for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1825 if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1828 if (timestamp > c3ptr->serv->timestamp)
1831 c2ptr = acptr; /* Make sure they differ */
1833 /* Search second youngest link: */
1834 for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1835 if (ac2ptr != c3ptr &&
1836 ac2ptr->serv->timestamp >
1837 (c2ptr ? c2ptr->serv->timestamp : timestamp))
1841 for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1842 if (ac2ptr != c3ptr &&
1843 ac2ptr->serv->timestamp >
1844 (c2ptr ? c2ptr->serv->timestamp : timestamp))
1847 if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1849 /* If timestamps are equal, decide which link to break
1852 if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1853 (c3ptr ? c3ptr->serv->timestamp : timestamp))
1862 n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1867 n2up = IsServer(sptr) ? sptr->name : me.name;
1872 n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1877 n3up = IsServer(sptr) ? sptr->name : me.name;
1879 if (strcmp(n2, n2up) > 0)
1881 if (strcmp(n3, n3up) > 0)
1883 if (strcmp(n3, n2) > 0)
1890 /* Now squit the second youngest link: */
1892 return exit_new_server(cptr, sptr, host, timestamp,
1893 "server %s already exists and is %ld seconds younger.",
1894 host, (long)acptr->serv->timestamp - (long)timestamp);
1895 else if (c2ptr->from == cptr || IsServer(sptr))
1897 struct Client *killedptrfrom = c2ptr->from;
1901 * If the L: or H: line also gets rid of this link,
1902 * we sent just one squit.
1904 if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1907 * If breaking the loop here solves the L: or H:
1908 * line problem, we don't squit that.
1910 if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1915 * If we still have a L: or H: line problem,
1916 * we prefer to squit the new server, solving
1917 * loop and L:/H: line problem with only one squit.
1924 * If the new server was introduced by a server that caused a
1925 * Ghost less then 20 seconds ago, this is probably also
1926 * a Ghost... (20 seconds is more then enough because all
1927 * SERVER messages are at the beginning of a net.burst). --Run
1929 if (CurrentTime - cptr->serv->ghost < 20)
1931 killedptrfrom = acptr->from;
1932 if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1935 else if (exit_client_msg(cptr, c2ptr, &me,
1936 "Loop <-- %s (new link is %ld seconds younger)", host,
1937 (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1938 (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1941 * Did we kill the incoming server off already ?
1943 if (killedptrfrom == cptr)
1950 if (LHcptr && a_kills_b_too(LHcptr, acptr))
1952 if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1961 * We can't believe it is a lagged server message
1962 * when it directly connects to us...
1963 * kill the older link at the ghost, rather then
1964 * at the second youngest link, assuming it isn't
1967 ghost = CurrentTime; /* Mark that it caused a ghost */
1968 if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1978 return exit_new_server(cptr, sptr, host, timestamp,
1979 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1981 lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1985 int killed = a_kills_b_too(LHcptr, sptr);
1986 if (active_lh_line < 3)
1988 if (exit_client_msg(cptr, LHcptr, &me,
1989 (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1991 lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1996 ServerStats->is_ref++;
1997 if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
2001 * Did we kill the incoming server off already ?
2011 * Server is informing about a new server behind
2012 * this link. Create REMOTE server structure,
2013 * add it to list and propagate word to my other
2017 acptr = make_client(cptr, STAT_SERVER);
2019 acptr->serv->prot = prot;
2020 acptr->serv->timestamp = timestamp;
2021 acptr->hopcount = hop;
2022 ircd_strncpy(acptr->name, host, HOSTLEN);
2023 ircd_strncpy(acptr->info, info, REALLEN);
2024 acptr->serv->up = sptr;
2025 acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
2026 /* Use cptr, because we do protocol 9 -> 10 translation
2027 for numeric nicks ! */
2028 SetServerYXX(cptr, acptr, parv[6]);
2030 Count_newremoteserver(UserStats);
2031 if (Protocol(acptr) < 10)
2032 acptr->flags |= FLAGS_TS8;
2033 add_client_to_list(acptr);
2035 if (*parv[5] == 'J')
2038 sendto_op_mask(SNO_NETWORK, "Net junction: %s %s", /* XXX DEAD */
2039 sptr->name, acptr->name);
2043 * Old sendto_serv_but_one() call removed because we now need to send
2044 * different names to different servers (domain name matching).
2046 for (i = 0; i <= HighestFd; i++)
2048 if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
2049 bcptr == cptr || IsMe(bcptr))
2051 if (0 == match(me.name, acptr->name))
2053 sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s", /* XXX DEAD */
2054 NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
2055 NumServCap(acptr), acptr->info);
2060 if (IsUnknown(cptr) || IsHandshake(cptr))
2063 cptr->serv->timestamp = timestamp;
2064 cptr->serv->prot = prot;
2065 cptr->serv->ghost = ghost;
2066 SetServerYXX(cptr, cptr, parv[6]);
2067 if (start_timestamp > OLDEST_TS)
2069 #ifndef RELIABLE_CLOCK
2071 sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: " /* XXX DEAD */
2072 TIME_T_FMT, me.serv->timestamp, start_timestamp);
2073 sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: " /* XXX DEAD */
2074 TIME_T_FMT " ; difference %ld",
2075 recv_time, timestamp, timestamp - recv_time);
2077 if (start_timestamp < me.serv->timestamp)
2079 sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT, /* XXX DEAD */
2080 start_timestamp, me.serv->timestamp);
2081 me.serv->timestamp = start_timestamp;
2082 TSoffset += timestamp - recv_time;
2083 sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time)); /* XXX DEAD */
2085 else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
2086 cptr->serv->timestamp = TStime();
2088 else if (timestamp != recv_time)
2091 * Equal start times, we have a collision. Let the connected-to server
2092 * decide. This assumes leafs issue more than half of the connection
2095 if (IsUnknown(cptr))
2096 cptr->serv->timestamp = TStime();
2097 else if (IsHandshake(cptr))
2099 sendto_ops("clock adjusted by adding %d", /* XXX DEAD */
2100 (int)(timestamp - recv_time));
2101 TSoffset += timestamp - recv_time;
2104 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
2105 if (start_timestamp < me.serv->timestamp)
2106 me.serv->timestamp = start_timestamp;
2107 if (IsUnknown(cptr))
2108 cptr->serv->timestamp = TStime();
2112 ret = server_estab(cptr, aconf); /* XXX DEAD */
2116 #ifdef RELIABLE_CLOCK
2117 if (abs(cptr->serv->timestamp - recv_time) > 30)
2119 sendto_ops("Connected to a net with a timestamp-clock" /* XXX DEAD */
2120 " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
2121 " this.", timestamp - recv_time);
2122 sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s", /* XXX DEAD */
2123 me.name, TStime(), me.name);