Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / m_server.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_server.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  *
23  * $Id$
24  */
25
26 /*
27  * m_functions execute protocol messages on this server:
28  *
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...).
34  *
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.
38  *
39  *            (!IsServer(cptr)) => (cptr == sptr), because
40  *            prefixes are taken *only* from servers...
41  *
42  *            (IsServer(cptr))
43  *                    (sptr == cptr) => the message didn't
44  *                    have the prefix.
45  *
46  *                    (sptr != cptr && IsServer(sptr) means
47  *                    the prefix specified servername. (?)
48  *
49  *                    (sptr != cptr && !IsServer(sptr) means
50  *                    that message originated from a remote
51  *                    user (not local).
52  *
53  *            combining
54  *
55  *            (!IsServer(sptr)) means that, sptr can safely
56  *            taken as defining the target structure of the
57  *            message in this server.
58  *
59  *    *Always* true (if 'parse' and others are working correct):
60  *
61  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
62  *
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 ]
67  *
68  *    parc    number of variable parameter strings (if zero,
69  *            parv is allowed to be NULL)
70  *
71  *    parv    a NULL terminated list of parameter pointers,
72  *
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*
78  *
79  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
80  *                    non-NULL pointers.
81  */
82 #if 0
83 /*
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
87  */
88 #include "handlers.h"
89 #endif /* 0 */
90 #include "client.h"
91 #include "crule.h"
92 #include "hash.h"
93 #include "ircd.h"
94 #include "ircd_log.h"
95 #include "ircd_reply.h"
96 #include "ircd_string.h"
97 #include "list.h"
98 #include "match.h"
99 #include "msg.h"
100 #include "numeric.h"
101 #include "numnicks.h"
102 #include "querycmds.h"
103 #include "s_bsd.h"
104 #include "s_conf.h"
105 #include "s_debug.h"
106 #include "s_misc.h"
107 #include "s_serv.h"
108 #include "send.h"
109 #include "userload.h"
110
111 #include <assert.h>
112 #include <stdlib.h>
113 #include <string.h>
114
115 /*
116  * mr_server - registration message handler
117  *
118  *    parv[0] = sender prefix
119  *    parv[1] = servername
120  *    parv[2] = hopcount
121  *    parv[3] = start timestamp
122  *    parv[4] = link timestamp
123  *    parv[5] = major protocol version: P09/P10
124  *    parv[parc-1] = serverinfo
125  *  If cptr is P10:
126  *    parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
127  *              numeric nick mask of this server.
128  *    parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
129  */
130 int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
131 {
132   char*            ch;
133   int              i;
134   char             info[REALLEN + 1];
135   char*            host;
136   struct Client*   acptr;
137   struct Client*   bcptr;
138   struct Client*   LHcptr = 0;
139   struct ConfItem* aconf = 0;
140   struct ConfItem* cconf;
141   struct ConfItem* lhconf = 0;
142   int              hop;
143   int              ret;
144   int              active_lh_line = 0;
145   unsigned short   prot;
146   time_t           start_timestamp;
147   time_t           timestamp = 0;
148   time_t           recv_time;
149   time_t           ghost = 0;
150
151   if (IsUser(cptr))
152   {
153     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
154     return 0;
155   }
156
157   if (IsUserPort(cptr))
158     return exit_client_msg(cptr, cptr, &me, 
159                            "Cannot connect a server to a user port");
160
161   recv_time = TStime();
162   info[0] = '\0';
163
164   if (parc < 7)
165   {
166     return need_more_params(sptr, "SERVER");
167     return exit_client(cptr, cptr, &me, "Need more parameters");
168   }
169   ircd_log(L_NOTICE, "SERVER: %s %s[%s]", parv[1], cptr->sockhost, cptr->sock_ip);
170   host = parv[1];
171   /*
172    * Detect protocol
173    */
174   if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
175     return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
176
177   if (!IsServer(cptr))          /* Don't allow silently connecting a server */
178     *parv[5] = 'J';
179
180   prot = atoi(parv[5] + 1);
181   if (prot > atoi(MAJOR_PROTOCOL))
182     prot = atoi(MAJOR_PROTOCOL);
183   /*
184    * Because the previous test is only in 2.10, the following is needed
185    * till all servers are 2.10:
186    */
187   if (IsServer(cptr) && prot > Protocol(cptr))
188     prot = Protocol(cptr);
189   hop = atoi(parv[2]);
190   start_timestamp = atoi(parv[3]);
191   timestamp = atoi(parv[4]);
192   Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
193         TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
194
195   if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
196   {
197     return exit_client_msg(cptr, sptr, &me,
198         "Bogus timestamps (%s %s)", parv[3], parv[4]);
199   }
200   ircd_strncpy(info, parv[parc - 1], REALLEN);
201   info[REALLEN] = '\0';
202   if (prot < atoi(MINOR_PROTOCOL)) {
203     sendto_ops("Got incompatible protocol version (%s) from %s",
204                parv[5], cptr->name);
205     return exit_new_server(cptr, sptr, host, timestamp,
206                            "Incompatible protocol: %s", parv[5]);
207   }
208   /*
209    * Check for "FRENCH " infection ;-) (actually this should
210    * be replaced with routine to check the hostname syntax in
211    * general). [ This check is still needed, even after the parse
212    * is fixed, because someone can send "SERVER :foo bar " ].
213    * Also, changed to check other "difficult" characters, now
214    * that parse lets all through... --msa
215    */
216   if (strlen(host) > HOSTLEN)
217     host[HOSTLEN] = '\0';
218
219   for (ch = host; *ch; ch++) {
220     if (*ch <= ' ' || *ch > '~')
221       break;
222   }
223   if (*ch || !strchr(host, '.')) {
224     sendto_ops("Bogus server name (%s) from %s", host, cptr->name);
225     return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
226   }
227
228   if (IsServer(cptr))
229   {
230     /*
231      * A local server introduces a new server behind this link.
232      * Check if this is allowed according L:, H: and Q: lines.
233      */
234     if (info[0] == '\0')
235       return exit_client_msg(cptr, cptr, &me,
236                              "No server info specified for %s", host);
237     /*
238      * See if the newly found server is behind a guaranteed
239      * leaf (L-line). If so, close the link.
240      */
241     if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
242         (!lhconf->port || (hop > lhconf->port)))
243     {
244       /*
245        * L: lines normally come in pairs, here we try to
246        * make sure that the oldest link is squitted, not
247        * both.
248        */
249       active_lh_line = 1;
250       if (timestamp <= cptr->serv->timestamp)
251         LHcptr = 0;          /* Kill incoming server */
252       else
253         LHcptr = cptr;          /* Squit ourselfs */
254     }
255     else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
256              (lhconf->port && (hop > lhconf->port)))
257     {
258       struct Client *ac3ptr;
259       active_lh_line = 2;
260       /* Look for net junction causing this: */
261       LHcptr = 0;            /* incoming server */
262       if (*parv[5] != 'J') {
263         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
264           if (IsJunction(ac3ptr)) {
265             LHcptr = ac3ptr;
266             break;
267           }
268         }
269       }
270     }
271   }
272
273   if (IsUnknown(cptr) || IsHandshake(cptr))
274   {
275     const char* encr;
276
277     /*
278      * A local link that is still in undefined state wants
279      * to be a SERVER. Check if this is allowed and change
280      * status accordingly...
281      */
282     /*
283      * If there is more then one server on the same machine
284      * that we try to connect to, it could be that the /CONNECT
285      * <mask> caused this connect to be put at the wrong place
286      * in the hashtable.        --Run
287      * Same thing for Unknown connections that first send NICK.
288      *                          --Xorath
289      * Better check if the two strings are (caseless) identical 
290      * and not mess with hash internals. 
291      *                          --Nemesi
292      */
293     if (!EmptyString(cptr->name) && 
294         (IsUnknown(cptr) || IsHandshake(cptr)) &&
295         0 != ircd_strcmp(cptr->name, host))
296       hChangeClient(cptr, host);
297     ircd_strncpy(cptr->name, host, HOSTLEN);
298     ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
299     cptr->hopcount = hop;
300
301     /* check connection rules */
302     for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
303       if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
304         if (crule_eval(cconf->passwd)) {
305           ServerStats->is_ref++;
306           sendto_ops("Refused connection from %s.", cptr->name);
307           return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
308         }
309       }
310     }
311     if (conf_check_server(cptr)) {
312       ++ServerStats->is_ref;
313       sendto_ops("Received unauthorized connection from %s.", cptr->name);
314       return exit_client(cptr, cptr, &me, "No C:line");
315     }
316
317     host = cptr->name;
318
319     update_load();
320
321     if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
322       ++ServerStats->is_ref;
323 #ifndef GODMODE
324       sendto_ops("Access denied. No conf line for server %s", cptr->name);
325       return exit_client_msg(cptr, cptr, &me,
326           "Access denied. No conf line for server %s", cptr->name);
327 #else /* GODMODE */
328       sendto_ops("General C: line active: No line for server %s", cptr->name);
329       aconf = find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
330       if (!aconf) {
331         sendto_ops("Neither C lines for server %s nor "
332             "\"general.undernet.org\"", cptr->name);
333         return exit_client_msg(cptr, cptr, &me, "No C lines for server %s", cptr->name);
334       }
335 #endif /* GODMODE */
336     }
337 #ifdef CRYPT_LINK_PASSWORD
338     /* passwd may be NULL. Head it off at the pass... */
339     if (*cptr->passwd) {
340       char salt[3];
341
342       salt[0] = aconf->passwd[0];
343       salt[1] = aconf->passwd[1];
344       salt[2] = '\0';
345       encr = ircd_crypt(cptr->passwd, salt);
346     }
347     else
348       encr = "";
349 #else
350     encr = cptr->passwd;
351 #endif /* CRYPT_LINK_PASSWORD */
352 #ifndef GODMODE
353     if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
354       ++ServerStats->is_ref;
355       sendto_ops("Access denied (passwd mismatch) %s", cptr->name);
356       return exit_client_msg(cptr, cptr, &me,
357           "No Access (passwd mismatch) %s", cptr->name);
358     }
359 #endif /* not GODMODE */
360     memset(cptr->passwd, 0, sizeof(cptr->passwd));
361
362 #ifndef HUB
363     for (i = 0; i <= HighestFd; i++)
364       if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
365         active_lh_line = 3;
366         LHcptr = 0;
367         break;
368       }
369 #endif
370   }
371
372   /*
373    *  We want to find IsConnecting() and IsHandshake() too,
374    *  use FindClient().
375    *  The second finds collisions with numeric representation of existing
376    *  servers - these shouldn't happen anymore when all upgraded to 2.10.
377    *  -- Run
378    */
379   while ((acptr = FindClient(host)) || 
380          (parc > 7 && (acptr = FindNServer(parv[6]))))
381   {
382     /*
383      *  This link is trying feed me a server that I already have
384      *  access through another path
385      *
386      *  Do not allow Uworld to do this.
387      *  Do not allow servers that are juped.
388      *  Do not allow servers that have older link timestamps
389      *    then this try.
390      *  Do not allow servers that use the same numeric as an existing
391      *    server, but have a different name.
392      *
393      *  If my ircd.conf sucks, I can try to connect to myself:
394      */
395     if (acptr == &me)
396       return exit_client_msg(cptr, cptr, &me, "nick collision with me (%s)", host);
397     /*
398      * Detect wrong numeric.
399      */
400     if (0 != ircd_strcmp(acptr->name, host)) {
401       sendto_serv_butone(cptr,
402           ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
403           me.name, acptr->name, host);
404       return exit_client_msg(cptr, cptr, &me,
405           "NUMERIC collision between %s and %s."
406           " Is your server numeric correct ?", host, acptr->name);
407     }
408     /*
409      *  Kill our try, if we had one.
410      */
411     if (IsConnecting(acptr))
412     {
413       if (!active_lh_line && exit_client(cptr, acptr, &me,
414           "Just connected via another link") == CPTR_KILLED)
415         return CPTR_KILLED;
416       /*
417        * We can have only ONE 'IsConnecting', 'IsHandshake' or
418        * 'IsServer', because new 'IsConnecting's are refused to
419        * the same server if we already had it.
420        */
421       break;
422     }
423     /*
424      * Avoid other nick collisions...
425      * This is a doubtfull test though, what else would it be
426      * when it has a server.name ?
427      */
428     else if (!IsServer(acptr) && !IsHandshake(acptr))
429       return exit_client_msg(cptr, cptr, &me,
430                              "Nickname %s already exists!", host);
431     /*
432      * Our new server might be a juped server,
433      * or someone trying abuse a second Uworld:
434      */
435     else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
436         find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
437     {
438       if (!IsServer(sptr))
439         return exit_client(cptr, sptr, &me, acptr->info);
440       sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
441           me.name, parv[0], parv[1], cptr->name);
442       return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
443     }
444     /*
445      * Of course we find the handshake this link was before :)
446      */
447     else if (IsHandshake(acptr) && acptr == cptr)
448       break;
449     /*
450      * Here we have a server nick collision...
451      * We don't want to kill the link that was last /connected,
452      * but we neither want to kill a good (old) link.
453      * Therefor we kill the second youngest link.
454      */
455     if (1)
456     {
457       struct Client* c2ptr = 0;
458       struct Client* c3ptr = acptr;
459       struct Client* ac2ptr;
460       struct Client* ac3ptr;
461
462       /* Search youngest link: */
463       for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
464         if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
465           c3ptr = ac3ptr;
466       if (IsServer(sptr))
467       {
468         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
469           if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
470             c3ptr = ac3ptr;
471       }
472       if (timestamp > c3ptr->serv->timestamp)
473       {
474         c3ptr = 0;
475         c2ptr = acptr;          /* Make sure they differ */
476       }
477       /* Search second youngest link: */
478       for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
479         if (ac2ptr != c3ptr &&
480             ac2ptr->serv->timestamp >
481             (c2ptr ? c2ptr->serv->timestamp : timestamp))
482           c2ptr = ac2ptr;
483       if (IsServer(sptr))
484       {
485         for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
486           if (ac2ptr != c3ptr &&
487               ac2ptr->serv->timestamp >
488               (c2ptr ? c2ptr->serv->timestamp : timestamp))
489             c2ptr = ac2ptr;
490       }
491       if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
492         c2ptr = 0;
493       /* If timestamps are equal, decide which link to break
494        *  by name.
495        */
496       if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
497           (c3ptr ? c3ptr->serv->timestamp : timestamp))
498       {
499         char* n2;
500         char* n2up;
501         char* n3;
502         char* n3up;
503         if (c2ptr)
504         {
505           n2 = c2ptr->name;
506           n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
507         }
508         else
509         {
510           n2 = host;
511           n2up = IsServer(sptr) ? sptr->name : me.name;
512         }
513         if (c3ptr)
514         {
515           n3 = c3ptr->name;
516           n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
517         }
518         else
519         {
520           n3 = host;
521           n3up = IsServer(sptr) ? sptr->name : me.name;
522         }
523         if (strcmp(n2, n2up) > 0)
524           n2 = n2up;
525         if (strcmp(n3, n3up) > 0)
526           n3 = n3up;
527         if (strcmp(n3, n2) > 0)
528         {
529           ac2ptr = c2ptr;
530           c2ptr = c3ptr;
531           c3ptr = ac2ptr;
532         }
533       }
534       /* Now squit the second youngest link: */
535       if (!c2ptr)
536         return exit_new_server(cptr, sptr, host, timestamp,
537                                "server %s already exists and is %ld seconds younger.",
538                                host, (long)acptr->serv->timestamp - (long)timestamp);
539       else if (c2ptr->from == cptr || IsServer(sptr))
540       {
541         struct Client *killedptrfrom = c2ptr->from;
542         if (active_lh_line)
543         {
544           /*
545            * If the L: or H: line also gets rid of this link,
546            * we sent just one squit.
547            */
548           if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
549             break;
550           /*
551            * If breaking the loop here solves the L: or H:
552            * line problem, we don't squit that.
553            */
554           if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
555             active_lh_line = 0;
556           else
557           {
558             /*
559              * If we still have a L: or H: line problem,
560              * we prefer to squit the new server, solving
561              * loop and L:/H: line problem with only one squit.
562              */
563             LHcptr = 0;
564             break;
565           }
566         }
567         /*
568          * If the new server was introduced by a server that caused a
569          * Ghost less then 20 seconds ago, this is probably also
570          * a Ghost... (20 seconds is more then enough because all
571          * SERVER messages are at the beginning of a net.burst). --Run
572          */
573         if (CurrentTime - cptr->serv->ghost < 20)
574         {
575           killedptrfrom = acptr->from;
576           if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
577             return CPTR_KILLED;
578         }
579         else if (exit_client_msg(cptr, c2ptr, &me,
580             "Loop <-- %s (new link is %ld seconds younger)", host,
581             (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
582             (long)c2ptr->serv->timestamp) == CPTR_KILLED)
583           return CPTR_KILLED;
584         /*
585          * Did we kill the incoming server off already ?
586          */
587         if (killedptrfrom == cptr)
588           return 0;
589       }
590       else
591       {
592         if (active_lh_line)
593         {
594           if (LHcptr && a_kills_b_too(LHcptr, acptr))
595             break;
596           if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
597             active_lh_line = 0;
598           else
599           {
600             LHcptr = 0;
601             break;
602           }
603         }
604         /*
605          * We can't believe it is a lagged server message
606          * when it directly connects to us...
607          * kill the older link at the ghost, rather then
608          * at the second youngest link, assuming it isn't
609          * a REAL loop.
610          */
611         ghost = CurrentTime;            /* Mark that it caused a ghost */
612         if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
613           return CPTR_KILLED;
614         break;
615       }
616     }
617   }
618
619   if (active_lh_line)
620   {
621     if (LHcptr == 0) {
622       return exit_new_server(cptr, sptr, host, timestamp,
623           (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
624           cptr->name, host, 
625           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
626     }
627     else
628     {
629       int killed = a_kills_b_too(LHcptr, sptr);
630       if (active_lh_line < 3)
631       {
632         if (exit_client_msg(cptr, LHcptr, &me,
633             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
634             cptr->name, host,
635             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
636           return CPTR_KILLED;
637       }
638       else
639       {
640         ServerStats->is_ref++;
641         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
642           return CPTR_KILLED;
643       }
644       /*
645        * Did we kill the incoming server off already ?
646        */
647       if (killed)
648         return 0;
649     }
650   }
651
652   if (IsServer(cptr))
653   {
654     /*
655      * Server is informing about a new server behind
656      * this link. Create REMOTE server structure,
657      * add it to list and propagate word to my other
658      * server links...
659      */
660
661     acptr = make_client(cptr, STAT_SERVER);
662     make_server(acptr);
663     acptr->serv->prot = prot;
664     acptr->serv->timestamp = timestamp;
665     acptr->hopcount = hop;
666     ircd_strncpy(acptr->name, host, HOSTLEN);
667     ircd_strncpy(acptr->info, info, REALLEN);
668     acptr->serv->up = sptr;
669     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
670     /* Use cptr, because we do protocol 9 -> 10 translation
671        for numeric nicks ! */
672     SetServerYXX(cptr, acptr, parv[6]);
673
674     Count_newremoteserver(UserStats);
675     if (Protocol(acptr) < 10)
676       acptr->flags |= FLAGS_TS8;
677     add_client_to_list(acptr);
678     hAddClient(acptr);
679     if (*parv[5] == 'J')
680     {
681       SetBurst(acptr);
682       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
683           sptr->name, acptr->name);
684       SetJunction(acptr);
685     }
686     /*
687      * Old sendto_serv_but_one() call removed because we now need to send
688      * different names to different servers (domain name matching).
689      */
690     for (i = 0; i <= HighestFd; i++)
691     {
692       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
693           bcptr == cptr || IsMe(bcptr))
694         continue;
695       if (0 == match(me.name, acptr->name))
696         continue;
697         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
698             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
699             NumServCap(acptr), acptr->info);
700     }
701     return 0;
702   }
703
704   if (IsUnknown(cptr) || IsHandshake(cptr))
705   {
706     make_server(cptr);
707     cptr->serv->timestamp = timestamp;
708     cptr->serv->prot = prot;
709     cptr->serv->ghost = ghost;
710     SetServerYXX(cptr, cptr, parv[6]);
711     if (start_timestamp > OLDEST_TS)
712     {
713 #ifndef RELIABLE_CLOCK
714 #ifdef TESTNET
715       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
716           TIME_T_FMT, me.serv->timestamp, start_timestamp);
717       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
718           TIME_T_FMT " ; difference %ld",
719           recv_time, timestamp, timestamp - recv_time);
720 #endif
721       if (start_timestamp < me.serv->timestamp)
722       {
723         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
724             start_timestamp, me.serv->timestamp);
725         me.serv->timestamp = start_timestamp;
726         TSoffset += timestamp - recv_time;
727         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
728       }
729       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
730         cptr->serv->timestamp = TStime();
731
732       else if (timestamp != recv_time)
733       {
734         /*
735          * Equal start times, we have a collision.  Let the connected-to server
736          * decide. This assumes leafs issue more than half of the connection
737          * attempts.
738          */
739         if (IsUnknown(cptr))
740           cptr->serv->timestamp = TStime();
741         else if (IsHandshake(cptr))
742         {
743           sendto_ops("clock adjusted by adding %d",
744               (int)(timestamp - recv_time));
745           TSoffset += timestamp - recv_time;
746         }
747       }
748 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
749       if (start_timestamp < me.serv->timestamp)
750         me.serv->timestamp = start_timestamp;
751       if (IsUnknown(cptr))
752         cptr->serv->timestamp = TStime();
753 #endif
754     }
755
756     ret = server_estab(cptr, aconf);
757   }
758   else
759     ret = 0;
760 #ifdef RELIABLE_CLOCK
761   if (abs(cptr->serv->timestamp - recv_time) > 30)
762   {
763     sendto_ops("Connected to a net with a timestamp-clock"
764         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
765         " this.", timestamp - recv_time);
766     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
767         me.name, TStime(), me.name);
768   }
769 #endif
770
771   return ret;
772 }
773
774 /*
775  * ms_server - server message handler
776  *
777  *    parv[0] = sender prefix
778  *    parv[1] = servername
779  *    parv[2] = hopcount
780  *    parv[3] = start timestamp
781  *    parv[4] = link timestamp
782  *    parv[5] = major protocol version: P09/P10
783  *    parv[parc-1] = serverinfo
784  *  If cptr is P10:
785  *    parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
786  *              numeric nick mask of this server.
787  *    parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
788  */
789 int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
790 {
791   char*            ch;
792   int              i;
793   char             info[REALLEN + 1];
794   char*            host;
795   struct Client*   acptr;
796   struct Client*   bcptr;
797   struct Client*   LHcptr = 0;
798   struct ConfItem* aconf = 0;
799   struct ConfItem* cconf;
800   struct ConfItem* lhconf = 0;
801   int              hop;
802   int              ret;
803   int              active_lh_line = 0;
804   unsigned short   prot;
805   time_t           start_timestamp;
806   time_t           timestamp = 0;
807   time_t           recv_time;
808   time_t           ghost = 0;
809
810   if (IsUser(cptr))
811   {
812     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
813     return 0;
814   }
815
816   if (IsUserPort(cptr))
817     return exit_client_msg(cptr, cptr, &me,
818                            "Cannot connect a server to a user port");
819
820   recv_time = TStime();
821   info[0] = '\0';
822   if (parc < 7)
823   {
824     return need_more_params(sptr, "SERVER");
825     return exit_client(cptr, cptr, &me, "Need more parameters");
826   }
827   host = parv[1];
828   /*
829    * Detect protocol
830    */
831   if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
832     return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
833
834   if (!IsServer(cptr))          /* Don't allow silently connecting a server */
835     *parv[5] = 'J';
836
837   prot = atoi(parv[5] + 1);
838   if (prot > atoi(MAJOR_PROTOCOL))
839     prot = atoi(MAJOR_PROTOCOL);
840   /*
841    * Because the previous test is only in 2.10, the following is needed
842    * till all servers are 2.10:
843    */
844   if (IsServer(cptr) && prot > Protocol(cptr))
845     prot = Protocol(cptr);
846   hop = atoi(parv[2]);
847   start_timestamp = atoi(parv[3]);
848   timestamp = atoi(parv[4]);
849   Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
850       TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
851   if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
852   {
853     return exit_client_msg(cptr, sptr, &me,
854         "Bogus timestamps (%s %s)", parv[3], parv[4]);
855   }
856   ircd_strncpy(info, parv[parc - 1], REALLEN);
857   info[REALLEN] = '\0';
858   if (prot < atoi(MINOR_PROTOCOL)) {
859     sendto_ops("Got incompatible protocol version (%s) from %s",
860                parv[5], cptr->name);
861     return exit_new_server(cptr, sptr, host, timestamp,
862                            "Incompatible protocol: %s", parv[5]);
863   }
864   /*
865    * Check for "FRENCH " infection ;-) (actually this should
866    * be replaced with routine to check the hostname syntax in
867    * general). [ This check is still needed, even after the parse
868    * is fixed, because someone can send "SERVER :foo bar " ].
869    * Also, changed to check other "difficult" characters, now
870    * that parse lets all through... --msa
871    */
872   if (strlen(host) > HOSTLEN)
873     host[HOSTLEN] = '\0';
874   for (ch = host; *ch; ch++)
875     if (*ch <= ' ' || *ch > '~')
876       break;
877   if (*ch || !strchr(host, '.')) {
878     sendto_ops("Bogus server name (%s) from %s", host, cptr->name);
879     return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
880   }
881
882   if (IsServer(cptr))
883   {
884     /*
885      * A local server introduces a new server behind this link.
886      * Check if this is allowed according L:, H: and Q: lines.
887      */
888     if (info[0] == '\0')
889       return exit_client_msg(cptr, cptr, &me,
890           "No server info specified for %s", host);
891     /*
892      * See if the newly found server is behind a guaranteed
893      * leaf (L-line). If so, close the link.
894      */
895     if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
896         (!lhconf->port || (hop > lhconf->port)))
897     {
898       /*
899        * L: lines normally come in pairs, here we try to
900        * make sure that the oldest link is squitted, not
901        * both.
902        */
903       active_lh_line = 1;
904       if (timestamp <= cptr->serv->timestamp)
905         LHcptr = 0;          /* Kill incoming server */
906       else
907         LHcptr = cptr;          /* Squit ourselfs */
908     }
909     else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
910              (lhconf->port && (hop > lhconf->port)))
911     {
912       struct Client *ac3ptr;
913       active_lh_line = 2;
914       /* Look for net junction causing this: */
915       LHcptr = 0;            /* incoming server */
916       if (*parv[5] != 'J') {
917         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
918           if (IsJunction(ac3ptr)) {
919             LHcptr = ac3ptr;
920             break;
921           }
922         }
923       }
924     }
925   }
926
927   if (IsUnknown(cptr) || IsHandshake(cptr))
928   {
929     const char* encr;
930
931     /*
932      * A local link that is still in undefined state wants
933      * to be a SERVER. Check if this is allowed and change
934      * status accordingly...
935      */
936     /*
937      * If there is more then one server on the same machine
938      * that we try to connect to, it could be that the /CONNECT
939      * <mask> caused this connect to be put at the wrong place
940      * in the hashtable.        --Run
941      * Same thing for Unknown connections that first send NICK.
942      *                          --Xorath
943      * Better check if the two strings are (caseless) identical 
944      * and not mess with hash internals. 
945      *                          --Nemesi
946      */
947     if ((!(EmptyString(cptr->name)))
948         && (IsUnknown(cptr) || IsHandshake(cptr))
949         && 0 != ircd_strcmp(cptr->name, host))
950       hChangeClient(cptr, host);
951     ircd_strncpy(cptr->name, host, HOSTLEN);
952     ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
953     cptr->hopcount = hop;
954
955     /* check connection rules */
956     for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
957       if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
958         if (crule_eval(cconf->passwd))
959         {
960           ServerStats->is_ref++;
961           sendto_ops("Refused connection from %s.", cptr->name);
962           return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
963         }
964       }
965     }
966     if (conf_check_server(cptr)) {
967       ++ServerStats->is_ref;
968       sendto_ops("Received unauthorized connection from %s.", cptr->name);
969       return exit_client(cptr, cptr, &me, "No C conf lines");
970     }
971
972     host = cptr->name;
973
974     update_load();
975
976     if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
977       ++ServerStats->is_ref;
978 #ifndef GODMODE
979       sendto_ops("Access denied. No conf line for server %s", cptr->name);
980       return exit_client_msg(cptr, cptr, &me,
981                              "Access denied. No conf line for server %s", cptr->name);
982 #else /* GODMODE */
983       sendto_ops("General C line active: No line for server %s", cptr->name);
984       aconf =
985           find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
986       if (!aconf) {
987         sendto_ops("Neither C lines for server %s nor "
988             "\"general.undernet.org\"", cptr->name);
989         return exit_client_msg(cptr, cptr, &me,
990             "No C lines for server %s", cptr->name);
991       }
992 #endif /* GODMODE */
993     }
994 #ifdef CRYPT_LINK_PASSWORD
995     /* passwd may be NULL. Head it off at the pass... */
996     if (*cptr->passwd)
997     {
998       char salt[3];
999
1000       salt[0] = aconf->passwd[0];
1001       salt[1] = aconf->passwd[1];
1002       salt[2] = '\0';
1003       encr = ircd_crypt(cptr->passwd, salt);
1004     }
1005     else
1006       encr = "";
1007 #else
1008     encr = cptr->passwd;
1009 #endif /* CRYPT_LINK_PASSWORD */
1010 #ifndef GODMODE
1011     if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1012       ++ServerStats->is_ref;
1013       sendto_ops("Access denied (passwd mismatch) %s", cptr->name);
1014       return exit_client_msg(cptr, cptr, &me,
1015                              "No Access (passwd mismatch) %s", cptr->name);
1016     }
1017 #endif /* not GODMODE */
1018     memset(cptr->passwd, 0, sizeof(cptr->passwd));
1019
1020 #ifndef HUB
1021     for (i = 0; i <= HighestFd; i++)
1022       if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1023         active_lh_line = 3;
1024         LHcptr = 0;
1025         break;
1026       }
1027 #endif
1028   }
1029
1030   /*
1031    *  We want to find IsConnecting() and IsHandshake() too,
1032    *  use FindClient().
1033    *  The second finds collisions with numeric representation of existing
1034    *  servers - these shouldn't happen anymore when all upgraded to 2.10.
1035    *  -- Run
1036    */
1037   while ((acptr = FindClient(host)) || 
1038          (parc > 7 && (acptr = FindNServer(parv[6]))))
1039   {
1040     /*
1041      *  This link is trying feed me a server that I already have
1042      *  access through another path
1043      *
1044      *  Do not allow Uworld to do this.
1045      *  Do not allow servers that are juped.
1046      *  Do not allow servers that have older link timestamps
1047      *    then this try.
1048      *  Do not allow servers that use the same numeric as an existing
1049      *    server, but have a different name.
1050      *
1051      *  If my ircd.conf sucks, I can try to connect to myself:
1052      */
1053     if (acptr == &me)
1054       return exit_client_msg(cptr, cptr, &me,
1055           "nick collision with me (%s)", host);
1056     /*
1057      * Detect wrong numeric.
1058      */
1059     if (0 != ircd_strcmp(acptr->name, host))
1060     {
1061       sendto_serv_butone(cptr,
1062           ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
1063           me.name, acptr->name, host);
1064       return exit_client_msg(cptr, cptr, &me,
1065           "NUMERIC collision between %s and %s."
1066           " Is your server numeric correct ?", host, acptr->name);
1067     }
1068     /*
1069      *  Kill our try, if we had one.
1070      */
1071     if (IsConnecting(acptr))
1072     {
1073       if (!active_lh_line && exit_client(cptr, acptr, &me,
1074           "Just connected via another link") == CPTR_KILLED)
1075         return CPTR_KILLED;
1076       /*
1077        * We can have only ONE 'IsConnecting', 'IsHandshake' or
1078        * 'IsServer', because new 'IsConnecting's are refused to
1079        * the same server if we already had it.
1080        */
1081       break;
1082     }
1083     /*
1084      * Avoid other nick collisions...
1085      * This is a doubtfull test though, what else would it be
1086      * when it has a server.name ?
1087      */
1088     else if (!IsServer(acptr) && !IsHandshake(acptr))
1089       return exit_client_msg(cptr, cptr, &me,
1090           "Nickname %s already exists!", host);
1091     /*
1092      * Our new server might be a juped server,
1093      * or someone trying abuse a second Uworld:
1094      */
1095     else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1096         find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1097     {
1098       if (!IsServer(sptr))
1099         return exit_client(cptr, sptr, &me, acptr->info);
1100       sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
1101           me.name, parv[0], parv[1], cptr->name);
1102       return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1103     }
1104     /*
1105      * Of course we find the handshake this link was before :)
1106      */
1107     else if (IsHandshake(acptr) && acptr == cptr)
1108       break;
1109     /*
1110      * Here we have a server nick collision...
1111      * We don't want to kill the link that was last /connected,
1112      * but we neither want to kill a good (old) link.
1113      * Therefor we kill the second youngest link.
1114      */
1115     if (1)
1116     {
1117       struct Client* c2ptr = 0;
1118       struct Client* c3ptr = acptr;
1119       struct Client* ac2ptr;
1120       struct Client* ac3ptr;
1121
1122       /* Search youngest link: */
1123       for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1124         if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1125           c3ptr = ac3ptr;
1126       if (IsServer(sptr))
1127       {
1128         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1129           if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1130             c3ptr = ac3ptr;
1131       }
1132       if (timestamp > c3ptr->serv->timestamp)
1133       {
1134         c3ptr = 0;
1135         c2ptr = acptr;          /* Make sure they differ */
1136       }
1137       /* Search second youngest link: */
1138       for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1139         if (ac2ptr != c3ptr &&
1140             ac2ptr->serv->timestamp >
1141             (c2ptr ? c2ptr->serv->timestamp : timestamp))
1142           c2ptr = ac2ptr;
1143       if (IsServer(sptr))
1144       {
1145         for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1146           if (ac2ptr != c3ptr &&
1147               ac2ptr->serv->timestamp >
1148               (c2ptr ? c2ptr->serv->timestamp : timestamp))
1149             c2ptr = ac2ptr;
1150       }
1151       if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1152         c2ptr = 0;
1153       /* If timestamps are equal, decide which link to break
1154        *  by name.
1155        */
1156       if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1157           (c3ptr ? c3ptr->serv->timestamp : timestamp))
1158       {
1159         char* n2;
1160         char* n2up;
1161         char* n3;
1162         char* n3up;
1163         if (c2ptr)
1164         {
1165           n2 = c2ptr->name;
1166           n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1167         }
1168         else
1169         {
1170           n2 = host;
1171           n2up = IsServer(sptr) ? sptr->name : me.name;
1172         }
1173         if (c3ptr)
1174         {
1175           n3 = c3ptr->name;
1176           n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1177         }
1178         else
1179         {
1180           n3 = host;
1181           n3up = IsServer(sptr) ? sptr->name : me.name;
1182         }
1183         if (strcmp(n2, n2up) > 0)
1184           n2 = n2up;
1185         if (strcmp(n3, n3up) > 0)
1186           n3 = n3up;
1187         if (strcmp(n3, n2) > 0)
1188         {
1189           ac2ptr = c2ptr;
1190           c2ptr = c3ptr;
1191           c3ptr = ac2ptr;
1192         }
1193       }
1194       /* Now squit the second youngest link: */
1195       if (!c2ptr)
1196         return exit_new_server(cptr, sptr, host, timestamp,
1197             "server %s already exists and is %ld seconds younger.",
1198             host, (long)acptr->serv->timestamp - (long)timestamp);
1199       else if (c2ptr->from == cptr || IsServer(sptr))
1200       {
1201         struct Client *killedptrfrom = c2ptr->from;
1202         if (active_lh_line)
1203         {
1204           /*
1205            * If the L: or H: line also gets rid of this link,
1206            * we sent just one squit.
1207            */
1208           if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1209             break;
1210           /*
1211            * If breaking the loop here solves the L: or H:
1212            * line problem, we don't squit that.
1213            */
1214           if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1215             active_lh_line = 0;
1216           else
1217           {
1218             /*
1219              * If we still have a L: or H: line problem,
1220              * we prefer to squit the new server, solving
1221              * loop and L:/H: line problem with only one squit.
1222              */
1223             LHcptr = 0;
1224             break;
1225           }
1226         }
1227         /*
1228          * If the new server was introduced by a server that caused a
1229          * Ghost less then 20 seconds ago, this is probably also
1230          * a Ghost... (20 seconds is more then enough because all
1231          * SERVER messages are at the beginning of a net.burst). --Run
1232          */
1233         if (CurrentTime - cptr->serv->ghost < 20)
1234         {
1235           killedptrfrom = acptr->from;
1236           if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1237             return CPTR_KILLED;
1238         }
1239         else if (exit_client_msg(cptr, c2ptr, &me,
1240             "Loop <-- %s (new link is %ld seconds younger)", host,
1241             (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1242             (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1243           return CPTR_KILLED;
1244         /*
1245          * Did we kill the incoming server off already ?
1246          */
1247         if (killedptrfrom == cptr)
1248           return 0;
1249       }
1250       else
1251       {
1252         if (active_lh_line)
1253         {
1254           if (LHcptr && a_kills_b_too(LHcptr, acptr))
1255             break;
1256           if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1257             active_lh_line = 0;
1258           else
1259           {
1260             LHcptr = 0;
1261             break;
1262           }
1263         }
1264         /*
1265          * We can't believe it is a lagged server message
1266          * when it directly connects to us...
1267          * kill the older link at the ghost, rather then
1268          * at the second youngest link, assuming it isn't
1269          * a REAL loop.
1270          */
1271         ghost = CurrentTime;            /* Mark that it caused a ghost */
1272         if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1273           return CPTR_KILLED;
1274         break;
1275       }
1276     }
1277   }
1278
1279   if (active_lh_line)
1280   {
1281     if (LHcptr == 0) {
1282       return exit_new_server(cptr, sptr, host, timestamp,
1283           (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1284           cptr->name, host,
1285           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1286     }
1287     else
1288     {
1289       int killed = a_kills_b_too(LHcptr, sptr);
1290       if (active_lh_line < 3)
1291       {
1292         if (exit_client_msg(cptr, LHcptr, &me,
1293             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1294             cptr->name, host,
1295             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1296           return CPTR_KILLED;
1297       }
1298       else
1299       {
1300         ServerStats->is_ref++;
1301         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
1302           return CPTR_KILLED;
1303       }
1304       /*
1305        * Did we kill the incoming server off already ?
1306        */
1307       if (killed)
1308         return 0;
1309     }
1310   }
1311
1312   if (IsServer(cptr))
1313   {
1314     /*
1315      * Server is informing about a new server behind
1316      * this link. Create REMOTE server structure,
1317      * add it to list and propagate word to my other
1318      * server links...
1319      */
1320
1321     acptr = make_client(cptr, STAT_SERVER);
1322     make_server(acptr);
1323     acptr->serv->prot = prot;
1324     acptr->serv->timestamp = timestamp;
1325     acptr->hopcount = hop;
1326     ircd_strncpy(acptr->name, host, HOSTLEN);
1327     ircd_strncpy(acptr->info, info, REALLEN);
1328     acptr->serv->up = sptr;
1329     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
1330     /* Use cptr, because we do protocol 9 -> 10 translation
1331        for numeric nicks ! */
1332     SetServerYXX(cptr, acptr, parv[6]);
1333
1334     Count_newremoteserver(UserStats);
1335     if (Protocol(acptr) < 10)
1336       acptr->flags |= FLAGS_TS8;
1337     add_client_to_list(acptr);
1338     hAddClient(acptr);
1339     if (*parv[5] == 'J')
1340     {
1341       SetBurst(acptr);
1342       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
1343           sptr->name, acptr->name);
1344       SetJunction(acptr);
1345     }
1346     /*
1347      * Old sendto_serv_but_one() call removed because we now need to send
1348      * different names to different servers (domain name matching).
1349      */
1350     for (i = 0; i <= HighestFd; i++)
1351     {
1352       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
1353           bcptr == cptr || IsMe(bcptr))
1354         continue;
1355       if (0 == match(me.name, acptr->name))
1356         continue;
1357         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
1358             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
1359             NumServCap(acptr), acptr->info);
1360     }
1361     return 0;
1362   }
1363
1364   if (IsUnknown(cptr) || IsHandshake(cptr))
1365   {
1366     make_server(cptr);
1367     cptr->serv->timestamp = timestamp;
1368     cptr->serv->prot = prot;
1369     cptr->serv->ghost = ghost;
1370     SetServerYXX(cptr, cptr, parv[6]);
1371     if (start_timestamp > OLDEST_TS)
1372     {
1373 #ifndef RELIABLE_CLOCK
1374 #ifdef TESTNET
1375       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
1376           TIME_T_FMT, me.serv->timestamp, start_timestamp);
1377       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
1378           TIME_T_FMT " ; difference %ld",
1379           recv_time, timestamp, timestamp - recv_time);
1380 #endif
1381       if (start_timestamp < me.serv->timestamp)
1382       {
1383         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
1384             start_timestamp, me.serv->timestamp);
1385         me.serv->timestamp = start_timestamp;
1386         TSoffset += timestamp - recv_time;
1387         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
1388       }
1389       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
1390         cptr->serv->timestamp = TStime();
1391
1392       else if (timestamp != recv_time)
1393       {
1394         /*
1395          * Equal start times, we have a collision.  Let the connected-to server
1396          * decide. This assumes leafs issue more than half of the connection
1397          * attempts.
1398          */
1399         if (IsUnknown(cptr))
1400           cptr->serv->timestamp = TStime();
1401         else if (IsHandshake(cptr))
1402         {
1403           sendto_ops("clock adjusted by adding %d",
1404               (int)(timestamp - recv_time));
1405           TSoffset += timestamp - recv_time;
1406         }
1407       }
1408 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
1409       if (start_timestamp < me.serv->timestamp)
1410         me.serv->timestamp = start_timestamp;
1411       if (IsUnknown(cptr))
1412         cptr->serv->timestamp = TStime();
1413 #endif
1414     }
1415
1416     ret = server_estab(cptr, aconf);
1417   }
1418   else
1419     ret = 0;
1420 #ifdef RELIABLE_CLOCK
1421   if (abs(cptr->serv->timestamp - recv_time) > 30)
1422   {
1423     sendto_ops("Connected to a net with a timestamp-clock"
1424         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
1425         " this.", timestamp - recv_time);
1426     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
1427         me.name, TStime(), me.name);
1428   }
1429 #endif
1430
1431   return ret;
1432 }
1433
1434
1435 #if 0
1436 /*
1437  *  m_server
1438  *
1439  *    parv[0] = sender prefix
1440  *    parv[1] = servername
1441  *    parv[2] = hopcount
1442  *    parv[3] = start timestamp
1443  *    parv[4] = link timestamp
1444  *    parv[5] = major protocol version: P09/P10
1445  *    parv[parc-1] = serverinfo
1446  *  If cptr is P10:
1447  *    parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
1448  *              numeric nick mask of this server.
1449  *    parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
1450  */
1451 int m_server(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
1452 {
1453   char*            ch;
1454   int              i;
1455   char             info[REALLEN + 1];
1456   char*            host;
1457   struct Client*   acptr;
1458   struct Client*   bcptr;
1459   struct Client*   LHcptr = 0;
1460   struct ConfItem* aconf = 0;
1461   struct ConfItem* cconf;
1462   struct ConfItem* lhconf = 0;
1463   int              hop;
1464   int              ret;
1465   int              active_lh_line = 0;
1466   unsigned short   prot;
1467   time_t           start_timestamp;
1468   time_t           timestamp = 0;
1469   time_t           recv_time;
1470   time_t           ghost = 0;
1471
1472   if (IsUser(cptr))
1473   {
1474     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
1475     return 0;
1476   }
1477
1478   if (IsUserPort(cptr))
1479     return exit_client_msg(cptr, cptr, &me,
1480         "You cannot connect a server to a user port; connect to %s port %u",
1481         me.name, server_port);
1482
1483   recv_time = TStime();
1484   info[0] = '\0';
1485   if (parc < 7)
1486   {
1487     return need_more_params(sptr, "SERVER");
1488     return exit_client(cptr, cptr, &me, "Need more parameters");
1489   }
1490   host = parv[1];
1491   /*
1492    * Detect protocol
1493    */
1494   if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
1495     return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
1496
1497   if (!IsServer(cptr))          /* Don't allow silently connecting a server */
1498     *parv[5] = 'J';
1499
1500   prot = atoi(parv[5] + 1);
1501   if (prot > atoi(MAJOR_PROTOCOL))
1502     prot = atoi(MAJOR_PROTOCOL);
1503   /*
1504    * Because the previous test is only in 2.10, the following is needed
1505    * till all servers are 2.10:
1506    */
1507   if (IsServer(cptr) && prot > Protocol(cptr))
1508     prot = Protocol(cptr);
1509   hop = atoi(parv[2]);
1510   start_timestamp = atoi(parv[3]);
1511   timestamp = atoi(parv[4]);
1512   Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
1513       TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
1514   if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
1515   {
1516     return exit_client_msg(cptr, sptr, &me,
1517         "Bogus timestamps (%s %s)", parv[3], parv[4]);
1518   }
1519   ircd_strncpy(info, parv[parc - 1], REALLEN);
1520   info[REALLEN] = '\0';
1521   if (prot < atoi(MINOR_PROTOCOL)) {
1522     sendto_ops("Got incompatible protocol version (%s) from %s",
1523                parv[5], cptr->name);
1524     return exit_new_server(cptr, sptr, host, timestamp,
1525         "Incompatible protocol: %s", parv[5]);
1526   }
1527   /*
1528    * Check for "FRENCH " infection ;-) (actually this should
1529    * be replaced with routine to check the hostname syntax in
1530    * general). [ This check is still needed, even after the parse
1531    * is fixed, because someone can send "SERVER :foo bar " ].
1532    * Also, changed to check other "difficult" characters, now
1533    * that parse lets all through... --msa
1534    */
1535   if (strlen(host) > HOSTLEN)
1536     host[HOSTLEN] = '\0';
1537   for (ch = host; *ch; ch++)
1538     if (*ch <= ' ' || *ch > '~')
1539       break;
1540   if (*ch || !strchr(host, '.'))
1541   {
1542     sendto_ops("Bogus server name (%s) from %s", host, cptr->name);
1543     return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
1544   }
1545
1546   if (IsServer(cptr))
1547   {
1548     /*
1549      * A local server introduces a new server behind this link.
1550      * Check if this is allowed according L:, H: and Q: lines.
1551      */
1552     if (info[0] == '\0')
1553       return exit_client_msg(cptr, cptr, &me,
1554           "No server info specified for %s", host);
1555     /*
1556      * See if the newly found server is behind a guaranteed
1557      * leaf (L-line). If so, close the link.
1558      */
1559     if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
1560         (!lhconf->port || (hop > lhconf->port)))
1561     {
1562       /*
1563        * L: lines normally come in pairs, here we try to
1564        * make sure that the oldest link is squitted, not
1565        * both.
1566        */
1567       active_lh_line = 1;
1568       if (timestamp <= cptr->serv->timestamp)
1569         LHcptr = 0;          /* Kill incoming server */
1570       else
1571         LHcptr = cptr;          /* Squit ourselfs */
1572     }
1573     else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
1574              (lhconf->port && (hop > lhconf->port)))
1575     {
1576       struct Client *ac3ptr;
1577       active_lh_line = 2;
1578       /* Look for net junction causing this: */
1579       LHcptr = 0;            /* incoming server */
1580       if (*parv[5] != 'J') {
1581         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
1582           if (IsJunction(ac3ptr)) {
1583             LHcptr = ac3ptr;
1584             break;
1585           }
1586         }
1587       }
1588     }
1589   }
1590
1591   if (IsUnknown(cptr) || IsHandshake(cptr))
1592   {
1593     const char* encr;
1594
1595     /*
1596      * A local link that is still in undefined state wants
1597      * to be a SERVER. Check if this is allowed and change
1598      * status accordingly...
1599      */
1600     /*
1601      * If there is more then one server on the same machine
1602      * that we try to connect to, it could be that the /CONNECT
1603      * <mask> caused this connect to be put at the wrong place
1604      * in the hashtable.        --Run
1605      * Same thing for Unknown connections that first send NICK.
1606      *                          --Xorath
1607      * Better check if the two strings are (caseless) identical 
1608      * and not mess with hash internals. 
1609      *                          --Nemesi
1610      */
1611     if ((!(EmptyString(cptr->name)))
1612         && (IsUnknown(cptr) || IsHandshake(cptr))
1613         && 0 != ircd_strcmp(cptr->name, host))
1614       hChangeClient(cptr, host);
1615     ircd_strncpy(cptr->name, host, HOSTLEN);
1616     ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
1617     cptr->hopcount = hop;
1618
1619     /* check connection rules */
1620     for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
1621       if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
1622         if (crule_eval(cconf->passwd))
1623         {
1624           ServerStats->is_ref++;
1625           sendto_ops("Refused connection from %s.", cptr->name);
1626           return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
1627         }
1628       }
1629     }
1630     if (conf_check_server(cptr)) {
1631       ++ServerStats->is_ref;
1632       sendto_ops("Received unauthorized connection from %s.", cptr->name);
1633       return exit_client(cptr, cptr, &me, "No C/N conf lines");
1634     }
1635
1636     host = cptr->name;
1637
1638     update_load();
1639
1640     if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
1641       ++ServerStats->is_ref;
1642 #ifndef GODMODE
1643       sendto_ops("Access denied. No conf line for server %s", cptr->name);
1644       return exit_client_msg(cptr, cptr, &me,
1645           "Access denied. No conf line for server %s", cptr->name);
1646 #else /* GODMODE */
1647       sendto_ops("General C/N: line active: No line for server %s", cptr->name);
1648       aconf =
1649           find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
1650       if (!aconf) {
1651         sendto_ops("Neither C/N lines for server %s nor "
1652             "\"general.undernet.org\"", cptr->name);
1653         return exit_client_msg(cptr, cptr, &me,
1654             "No C/N lines for server %s", cptr->name);
1655       }
1656 #endif /* GODMODE */
1657     }
1658 #ifdef CRYPT_LINK_PASSWORD
1659     /* passwd may be NULL. Head it off at the pass... */
1660     if (*cptr->passwd)
1661     {
1662       char salt[3];
1663
1664       salt[0] = aconf->passwd[0];
1665       salt[1] = aconf->passwd[1];
1666       salt[2] = '\0';
1667       encr = ircd_crypt(cptr->passwd, salt);
1668     }
1669     else
1670       encr = "";
1671 #else
1672     encr = cptr->passwd;
1673 #endif /* CRYPT_LINK_PASSWORD */
1674 #ifndef GODMODE
1675     if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1676       ++ServerStats->is_ref;
1677       sendto_ops("Access denied (passwd mismatch) %s", cptr->name);
1678       return exit_client_msg(cptr, cptr, &me,
1679           "No Access (passwd mismatch) %s", cptr->name);
1680     }
1681 #endif /* not GODMODE */
1682     memset(cptr->passwd, 0, sizeof(cptr->passwd));
1683
1684 #ifndef HUB
1685     for (i = 0; i <= HighestFd; i++)
1686       if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1687         active_lh_line = 3;
1688         LHcptr = 0;
1689         break;
1690       }
1691 #endif
1692   }
1693
1694   /*
1695    *  We want to find IsConnecting() and IsHandshake() too,
1696    *  use FindClient().
1697    *  The second finds collisions with numeric representation of existing
1698    *  servers - these shouldn't happen anymore when all upgraded to 2.10.
1699    *  -- Run
1700    */
1701   while ((acptr = FindClient(host)) || 
1702          (parc > 7 && (acptr = FindNServer(parv[6]))))
1703   {
1704     /*
1705      *  This link is trying feed me a server that I already have
1706      *  access through another path
1707      *
1708      *  Do not allow Uworld to do this.
1709      *  Do not allow servers that are juped.
1710      *  Do not allow servers that have older link timestamps
1711      *    then this try.
1712      *  Do not allow servers that use the same numeric as an existing
1713      *    server, but have a different name.
1714      *
1715      *  If my ircd.conf sucks, I can try to connect to myself:
1716      */
1717     if (acptr == &me)
1718       return exit_client_msg(cptr, cptr, &me,
1719           "nick collision with me (%s)", host);
1720     /*
1721      * Detect wrong numeric.
1722      */
1723     if (0 != ircd_strcmp(acptr->name, host))
1724     {
1725       sendto_serv_butone(cptr,
1726           ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
1727           me.name, acptr->name, host);
1728       return exit_client_msg(cptr, cptr, &me,
1729           "NUMERIC collision between %s and %s."
1730           " Is your server numeric correct ?", host, acptr->name);
1731     }
1732     /*
1733      *  Kill our try, if we had one.
1734      */
1735     if (IsConnecting(acptr))
1736     {
1737       if (!active_lh_line && exit_client(cptr, acptr, &me,
1738           "Just connected via another link") == CPTR_KILLED)
1739         return CPTR_KILLED;
1740       /*
1741        * We can have only ONE 'IsConnecting', 'IsHandshake' or
1742        * 'IsServer', because new 'IsConnecting's are refused to
1743        * the same server if we already had it.
1744        */
1745       break;
1746     }
1747     /*
1748      * Avoid other nick collisions...
1749      * This is a doubtfull test though, what else would it be
1750      * when it has a server.name ?
1751      */
1752     else if (!IsServer(acptr) && !IsHandshake(acptr))
1753       return exit_client_msg(cptr, cptr, &me,
1754           "Nickname %s already exists!", host);
1755     /*
1756      * Our new server might be a juped server,
1757      * or someone trying abuse a second Uworld:
1758      */
1759     else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1760         find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1761     {
1762       if (!IsServer(sptr))
1763         return exit_client(cptr, sptr, &me, acptr->info);
1764       sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
1765           me.name, parv[0], parv[1], cptr->name);
1766       return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1767     }
1768     /*
1769      * Of course we find the handshake this link was before :)
1770      */
1771     else if (IsHandshake(acptr) && acptr == cptr)
1772       break;
1773     /*
1774      * Here we have a server nick collision...
1775      * We don't want to kill the link that was last /connected,
1776      * but we neither want to kill a good (old) link.
1777      * Therefor we kill the second youngest link.
1778      */
1779     if (1)
1780     {
1781       struct Client* c2ptr = 0;
1782       struct Client* c3ptr = acptr;
1783       struct Client* ac2ptr;
1784       struct Client* ac3ptr;
1785
1786       /* Search youngest link: */
1787       for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1788         if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1789           c3ptr = ac3ptr;
1790       if (IsServer(sptr))
1791       {
1792         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1793           if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1794             c3ptr = ac3ptr;
1795       }
1796       if (timestamp > c3ptr->serv->timestamp)
1797       {
1798         c3ptr = 0;
1799         c2ptr = acptr;          /* Make sure they differ */
1800       }
1801       /* Search second youngest link: */
1802       for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1803         if (ac2ptr != c3ptr &&
1804             ac2ptr->serv->timestamp >
1805             (c2ptr ? c2ptr->serv->timestamp : timestamp))
1806           c2ptr = ac2ptr;
1807       if (IsServer(sptr))
1808       {
1809         for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1810           if (ac2ptr != c3ptr &&
1811               ac2ptr->serv->timestamp >
1812               (c2ptr ? c2ptr->serv->timestamp : timestamp))
1813             c2ptr = ac2ptr;
1814       }
1815       if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1816         c2ptr = 0;
1817       /* If timestamps are equal, decide which link to break
1818        *  by name.
1819        */
1820       if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1821           (c3ptr ? c3ptr->serv->timestamp : timestamp))
1822       {
1823         char* n2;
1824         char* n2up;
1825         char* n3;
1826         char* n3up;
1827         if (c2ptr)
1828         {
1829           n2 = c2ptr->name;
1830           n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1831         }
1832         else
1833         {
1834           n2 = host;
1835           n2up = IsServer(sptr) ? sptr->name : me.name;
1836         }
1837         if (c3ptr)
1838         {
1839           n3 = c3ptr->name;
1840           n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1841         }
1842         else
1843         {
1844           n3 = host;
1845           n3up = IsServer(sptr) ? sptr->name : me.name;
1846         }
1847         if (strcmp(n2, n2up) > 0)
1848           n2 = n2up;
1849         if (strcmp(n3, n3up) > 0)
1850           n3 = n3up;
1851         if (strcmp(n3, n2) > 0)
1852         {
1853           ac2ptr = c2ptr;
1854           c2ptr = c3ptr;
1855           c3ptr = ac2ptr;
1856         }
1857       }
1858       /* Now squit the second youngest link: */
1859       if (!c2ptr)
1860         return exit_new_server(cptr, sptr, host, timestamp,
1861             "server %s already exists and is %ld seconds younger.",
1862             host, (long)acptr->serv->timestamp - (long)timestamp);
1863       else if (c2ptr->from == cptr || IsServer(sptr))
1864       {
1865         struct Client *killedptrfrom = c2ptr->from;
1866         if (active_lh_line)
1867         {
1868           /*
1869            * If the L: or H: line also gets rid of this link,
1870            * we sent just one squit.
1871            */
1872           if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1873             break;
1874           /*
1875            * If breaking the loop here solves the L: or H:
1876            * line problem, we don't squit that.
1877            */
1878           if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1879             active_lh_line = 0;
1880           else
1881           {
1882             /*
1883              * If we still have a L: or H: line problem,
1884              * we prefer to squit the new server, solving
1885              * loop and L:/H: line problem with only one squit.
1886              */
1887             LHcptr = 0;
1888             break;
1889           }
1890         }
1891         /*
1892          * If the new server was introduced by a server that caused a
1893          * Ghost less then 20 seconds ago, this is probably also
1894          * a Ghost... (20 seconds is more then enough because all
1895          * SERVER messages are at the beginning of a net.burst). --Run
1896          */
1897         if (CurrentTime - cptr->serv->ghost < 20)
1898         {
1899           killedptrfrom = acptr->from;
1900           if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1901             return CPTR_KILLED;
1902         }
1903         else if (exit_client_msg(cptr, c2ptr, &me,
1904             "Loop <-- %s (new link is %ld seconds younger)", host,
1905             (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1906             (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1907           return CPTR_KILLED;
1908         /*
1909          * Did we kill the incoming server off already ?
1910          */
1911         if (killedptrfrom == cptr)
1912           return 0;
1913       }
1914       else
1915       {
1916         if (active_lh_line)
1917         {
1918           if (LHcptr && a_kills_b_too(LHcptr, acptr))
1919             break;
1920           if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1921             active_lh_line = 0;
1922           else
1923           {
1924             LHcptr = 0;
1925             break;
1926           }
1927         }
1928         /*
1929          * We can't believe it is a lagged server message
1930          * when it directly connects to us...
1931          * kill the older link at the ghost, rather then
1932          * at the second youngest link, assuming it isn't
1933          * a REAL loop.
1934          */
1935         ghost = CurrentTime;            /* Mark that it caused a ghost */
1936         if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1937           return CPTR_KILLED;
1938         break;
1939       }
1940     }
1941   }
1942
1943   if (active_lh_line)
1944   {
1945     if (LHcptr == 0) {
1946       return exit_new_server(cptr, sptr, host, timestamp,
1947           (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1948           cptr->name, host,
1949           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1950     }
1951     else
1952     {
1953       int killed = a_kills_b_too(LHcptr, sptr);
1954       if (active_lh_line < 3)
1955       {
1956         if (exit_client_msg(cptr, LHcptr, &me,
1957             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1958             cptr->name, host,
1959             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1960           return CPTR_KILLED;
1961       }
1962       else
1963       {
1964         ServerStats->is_ref++;
1965         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
1966           return CPTR_KILLED;
1967       }
1968       /*
1969        * Did we kill the incoming server off already ?
1970        */
1971       if (killed)
1972         return 0;
1973     }
1974   }
1975
1976   if (IsServer(cptr))
1977   {
1978     /*
1979      * Server is informing about a new server behind
1980      * this link. Create REMOTE server structure,
1981      * add it to list and propagate word to my other
1982      * server links...
1983      */
1984
1985     acptr = make_client(cptr, STAT_SERVER);
1986     make_server(acptr);
1987     acptr->serv->prot = prot;
1988     acptr->serv->timestamp = timestamp;
1989     acptr->hopcount = hop;
1990     ircd_strncpy(acptr->name, host, HOSTLEN);
1991     ircd_strncpy(acptr->info, info, REALLEN);
1992     acptr->serv->up = sptr;
1993     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
1994     /* Use cptr, because we do protocol 9 -> 10 translation
1995        for numeric nicks ! */
1996     SetServerYXX(cptr, acptr, parv[6]);
1997
1998     Count_newremoteserver(UserStats);
1999     if (Protocol(acptr) < 10)
2000       acptr->flags |= FLAGS_TS8;
2001     add_client_to_list(acptr);
2002     hAddClient(acptr);
2003     if (*parv[5] == 'J')
2004     {
2005       SetBurst(acptr);
2006       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
2007           sptr->name, acptr->name);
2008       SetJunction(acptr);
2009     }
2010     /*
2011      * Old sendto_serv_but_one() call removed because we now need to send
2012      * different names to different servers (domain name matching).
2013      */
2014     for (i = 0; i <= HighestFd; i++)
2015     {
2016       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
2017           bcptr == cptr || IsMe(bcptr))
2018         continue;
2019       if (0 == match(me.name, acptr->name))
2020         continue;
2021         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
2022             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
2023             NumServCap(acptr), acptr->info);
2024     }
2025     return 0;
2026   }
2027
2028   if (IsUnknown(cptr) || IsHandshake(cptr))
2029   {
2030     make_server(cptr);
2031     cptr->serv->timestamp = timestamp;
2032     cptr->serv->prot = prot;
2033     cptr->serv->ghost = ghost;
2034     SetServerYXX(cptr, cptr, parv[6]);
2035     if (start_timestamp > OLDEST_TS)
2036     {
2037 #ifndef RELIABLE_CLOCK
2038 #ifdef TESTNET
2039       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
2040           TIME_T_FMT, me.serv->timestamp, start_timestamp);
2041       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
2042           TIME_T_FMT " ; difference %ld",
2043           recv_time, timestamp, timestamp - recv_time);
2044 #endif
2045       if (start_timestamp < me.serv->timestamp)
2046       {
2047         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
2048             start_timestamp, me.serv->timestamp);
2049         me.serv->timestamp = start_timestamp;
2050         TSoffset += timestamp - recv_time;
2051         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
2052       }
2053       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
2054         cptr->serv->timestamp = TStime();
2055
2056       else if (timestamp != recv_time)
2057       {
2058         /*
2059          * Equal start times, we have a collision.  Let the connected-to server
2060          * decide. This assumes leafs issue more than half of the connection
2061          * attempts.
2062          */
2063         if (IsUnknown(cptr))
2064           cptr->serv->timestamp = TStime();
2065         else if (IsHandshake(cptr))
2066         {
2067           sendto_ops("clock adjusted by adding %d",
2068               (int)(timestamp - recv_time));
2069           TSoffset += timestamp - recv_time;
2070         }
2071       }
2072 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
2073       if (start_timestamp < me.serv->timestamp)
2074         me.serv->timestamp = start_timestamp;
2075       if (IsUnknown(cptr))
2076         cptr->serv->timestamp = TStime();
2077 #endif
2078     }
2079
2080     ret = server_estab(cptr, aconf);
2081   }
2082   else
2083     ret = 0;
2084 #ifdef RELIABLE_CLOCK
2085   if (abs(cptr->serv->timestamp - recv_time) > 30)
2086   {
2087     sendto_ops("Connected to a net with a timestamp-clock"
2088         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
2089         " this.", timestamp - recv_time);
2090     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
2091         me.name, TStime(), me.name);
2092   }
2093 #endif
2094
2095   return ret;
2096 }
2097 #endif /* 0 */
2098