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