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