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 #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)", 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)" : "Leaf-only link %s <- %s(%s)",
631           cptr->name, host, 
632           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
633     }
634     else
635     {
636       int killed = a_kills_b_too(LHcptr, sptr);
637       if (active_lh_line < 3)
638       {
639         if (exit_client_msg(cptr, LHcptr, &me,
640             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
641             cptr->name, host,
642             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
643           return CPTR_KILLED;
644       }
645       else
646       {
647         ServerStats->is_ref++;
648         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
649           return CPTR_KILLED;
650       }
651       /*
652        * Did we kill the incoming server off already ?
653        */
654       if (killed)
655         return 0;
656     }
657   }
658
659   if (IsServer(cptr))
660   {
661     /*
662      * Server is informing about a new server behind
663      * this link. Create REMOTE server structure,
664      * add it to list and propagate word to my other
665      * server links...
666      */
667
668     acptr = make_client(cptr, STAT_SERVER);
669     make_server(acptr);
670     acptr->serv->prot = prot;
671     acptr->serv->timestamp = timestamp;
672     acptr->hopcount = hop;
673     ircd_strncpy(acptr->name, host, HOSTLEN);
674     ircd_strncpy(acptr->info, info, REALLEN);
675     acptr->serv->up = sptr;
676     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
677     /* Use cptr, because we do protocol 9 -> 10 translation
678        for numeric nicks ! */
679     SetServerYXX(cptr, acptr, parv[6]);
680
681     Count_newremoteserver(UserStats);
682     if (Protocol(acptr) < 10)
683       acptr->flags |= FLAGS_TS8;
684     add_client_to_list(acptr);
685     hAddClient(acptr);
686     if (*parv[5] == 'J')
687     {
688       SetBurst(acptr);
689       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
690           sptr->name, acptr->name);
691       SetJunction(acptr);
692     }
693     /*
694      * Old sendto_serv_but_one() call removed because we now need to send
695      * different names to different servers (domain name matching).
696      */
697     for (i = 0; i <= HighestFd; i++)
698     {
699       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
700           bcptr == cptr || IsMe(bcptr))
701         continue;
702       if (0 == match(me.name, acptr->name))
703         continue;
704         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
705             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
706             NumServCap(acptr), acptr->info);
707     }
708     return 0;
709   }
710
711   if (IsUnknown(cptr) || IsHandshake(cptr))
712   {
713     make_server(cptr);
714     cptr->serv->timestamp = timestamp;
715     cptr->serv->prot = prot;
716     cptr->serv->ghost = ghost;
717     SetServerYXX(cptr, cptr, parv[6]);
718     if (start_timestamp > OLDEST_TS)
719     {
720 #ifndef RELIABLE_CLOCK
721 #ifdef TESTNET
722       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
723           TIME_T_FMT, me.serv->timestamp, start_timestamp);
724       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
725           TIME_T_FMT " ; difference %ld",
726           recv_time, timestamp, timestamp - recv_time);
727 #endif
728       if (start_timestamp < me.serv->timestamp)
729       {
730         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
731             start_timestamp, me.serv->timestamp);
732         me.serv->timestamp = start_timestamp;
733         TSoffset += timestamp - recv_time;
734         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
735       }
736       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
737         cptr->serv->timestamp = TStime();
738
739       else if (timestamp != recv_time)
740       {
741         /*
742          * Equal start times, we have a collision.  Let the connected-to server
743          * decide. This assumes leafs issue more than half of the connection
744          * attempts.
745          */
746         if (IsUnknown(cptr))
747           cptr->serv->timestamp = TStime();
748         else if (IsHandshake(cptr))
749         {
750           sendto_ops("clock adjusted by adding %d",
751               (int)(timestamp - recv_time));
752           TSoffset += timestamp - recv_time;
753         }
754       }
755 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
756       if (start_timestamp < me.serv->timestamp)
757         me.serv->timestamp = start_timestamp;
758       if (IsUnknown(cptr))
759         cptr->serv->timestamp = TStime();
760 #endif
761     }
762
763     ret = server_estab(cptr, aconf);
764   }
765   else
766     ret = 0;
767 #ifdef RELIABLE_CLOCK
768   if (abs(cptr->serv->timestamp - recv_time) > 30)
769   {
770     sendto_ops("Connected to a net with a timestamp-clock"
771         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
772         " this.", timestamp - recv_time);
773     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
774         me.name, TStime(), me.name);
775   }
776 #endif
777
778   return ret;
779 }
780
781 /*
782  * ms_server - server message handler
783  *
784  *    parv[0] = sender prefix
785  *    parv[1] = servername
786  *    parv[2] = hopcount
787  *    parv[3] = start timestamp
788  *    parv[4] = link timestamp
789  *    parv[5] = major protocol version: P09/P10
790  *    parv[parc-1] = serverinfo
791  *  If cptr is P10:
792  *    parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
793  *              numeric nick mask of this server.
794  *    parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
795  */
796 int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
797 {
798   char*            ch;
799   int              i;
800   char             info[REALLEN + 1];
801   char*            host;
802   struct Client*   acptr;
803   struct Client*   bcptr;
804   struct Client*   LHcptr = 0;
805   struct ConfItem* aconf = 0;
806   struct ConfItem* cconf;
807   struct ConfItem* lhconf = 0;
808   struct Jupe*     ajupe = 0;
809   int              hop;
810   int              ret;
811   int              active_lh_line = 0;
812   unsigned short   prot;
813   time_t           start_timestamp;
814   time_t           timestamp = 0;
815   time_t           recv_time;
816   time_t           ghost = 0;
817
818   if (IsUser(cptr))
819   {
820     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
821     return 0;
822   }
823
824   if (IsUserPort(cptr))
825     return exit_client_msg(cptr, cptr, &me,
826                            "Cannot connect a server to a user port");
827
828   recv_time = TStime();
829   info[0] = '\0';
830   if (parc < 7)
831   {
832     return need_more_params(sptr, "SERVER");
833     return exit_client(cptr, cptr, &me, "Need more parameters");
834   }
835   host = parv[1];
836
837   if ((ajupe = jupe_find(host)) && JupeIsActive(ajupe))
838     jupe_resend(cptr, ajupe);
839
840   /*
841    * Detect protocol
842    */
843   if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
844     return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
845
846   if (!IsServer(cptr))          /* Don't allow silently connecting a server */
847     *parv[5] = 'J';
848
849   prot = atoi(parv[5] + 1);
850   if (prot > atoi(MAJOR_PROTOCOL))
851     prot = atoi(MAJOR_PROTOCOL);
852   /*
853    * Because the previous test is only in 2.10, the following is needed
854    * till all servers are 2.10:
855    */
856   if (IsServer(cptr) && prot > Protocol(cptr))
857     prot = Protocol(cptr);
858   hop = atoi(parv[2]);
859   start_timestamp = atoi(parv[3]);
860   timestamp = atoi(parv[4]);
861   Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
862       TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
863   if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
864   {
865     return exit_client_msg(cptr, sptr, &me,
866         "Bogus timestamps (%s %s)", parv[3], parv[4]);
867   }
868   ircd_strncpy(info, parv[parc - 1], REALLEN);
869   info[REALLEN] = '\0';
870   if (prot < atoi(MINOR_PROTOCOL)) {
871     sendto_ops("Got incompatible protocol version (%s) from %s",
872                parv[5], cptr->name);
873     return exit_new_server(cptr, sptr, host, timestamp,
874                            "Incompatible protocol: %s", parv[5]);
875   }
876   /*
877    * Check for "FRENCH " infection ;-) (actually this should
878    * be replaced with routine to check the hostname syntax in
879    * general). [ This check is still needed, even after the parse
880    * is fixed, because someone can send "SERVER :foo bar " ].
881    * Also, changed to check other "difficult" characters, now
882    * that parse lets all through... --msa
883    */
884   if (strlen(host) > HOSTLEN)
885     host[HOSTLEN] = '\0';
886   for (ch = host; *ch; ch++)
887     if (*ch <= ' ' || *ch > '~')
888       break;
889   if (*ch || !strchr(host, '.')) {
890     sendto_ops("Bogus server name (%s) from %s", host, cptr->name);
891     return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
892   }
893
894   if (IsServer(cptr))
895   {
896     /*
897      * A local server introduces a new server behind this link.
898      * Check if this is allowed according L:, H: and Q: lines.
899      */
900     if (info[0] == '\0')
901       return exit_client_msg(cptr, cptr, &me,
902           "No server info specified for %s", host);
903     /*
904      * See if the newly found server is behind a guaranteed
905      * leaf (L-line). If so, close the link.
906      */
907     if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
908         (!lhconf->port || (hop > lhconf->port)))
909     {
910       /*
911        * L: lines normally come in pairs, here we try to
912        * make sure that the oldest link is squitted, not
913        * both.
914        */
915       active_lh_line = 1;
916       if (timestamp <= cptr->serv->timestamp)
917         LHcptr = 0;          /* Kill incoming server */
918       else
919         LHcptr = cptr;          /* Squit ourselfs */
920     }
921     else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
922              (lhconf->port && (hop > lhconf->port)))
923     {
924       struct Client *ac3ptr;
925       active_lh_line = 2;
926       /* Look for net junction causing this: */
927       LHcptr = 0;            /* incoming server */
928       if (*parv[5] != 'J') {
929         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
930           if (IsJunction(ac3ptr)) {
931             LHcptr = ac3ptr;
932             break;
933           }
934         }
935       }
936     }
937   }
938
939   if (IsUnknown(cptr) || IsHandshake(cptr))
940   {
941     const char* encr;
942
943     /*
944      * A local link that is still in undefined state wants
945      * to be a SERVER. Check if this is allowed and change
946      * status accordingly...
947      */
948     /*
949      * If there is more then one server on the same machine
950      * that we try to connect to, it could be that the /CONNECT
951      * <mask> caused this connect to be put at the wrong place
952      * in the hashtable.        --Run
953      * Same thing for Unknown connections that first send NICK.
954      *                          --Xorath
955      * Better check if the two strings are (caseless) identical 
956      * and not mess with hash internals. 
957      *                          --Nemesi
958      */
959     if ((!(EmptyString(cptr->name)))
960         && (IsUnknown(cptr) || IsHandshake(cptr))
961         && 0 != ircd_strcmp(cptr->name, host))
962       hChangeClient(cptr, host);
963     ircd_strncpy(cptr->name, host, HOSTLEN);
964     ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
965     cptr->hopcount = hop;
966
967     /* check connection rules */
968     for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
969       if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
970         if (crule_eval(cconf->passwd))
971         {
972           ServerStats->is_ref++;
973           sendto_ops("Refused connection from %s.", cptr->name);
974           return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
975         }
976       }
977     }
978     if (conf_check_server(cptr)) {
979       ++ServerStats->is_ref;
980       sendto_ops("Received unauthorized connection from %s.", cptr->name);
981       return exit_client(cptr, cptr, &me, "No C conf lines");
982     }
983
984     host = cptr->name;
985
986     update_load();
987
988     if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
989       ++ServerStats->is_ref;
990 #ifndef GODMODE
991       sendto_ops("Access denied. No conf line for server %s", cptr->name);
992       return exit_client_msg(cptr, cptr, &me,
993                              "Access denied. No conf line for server %s", cptr->name);
994 #else /* GODMODE */
995       sendto_ops("General C line active: No line for server %s", cptr->name);
996       aconf =
997           find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
998       if (!aconf) {
999         sendto_ops("Neither C lines for server %s nor "
1000             "\"general.undernet.org\"", cptr->name);
1001         return exit_client_msg(cptr, cptr, &me,
1002             "No C lines for server %s", cptr->name);
1003       }
1004 #endif /* GODMODE */
1005     }
1006 #ifdef CRYPT_LINK_PASSWORD
1007     /* passwd may be NULL. Head it off at the pass... */
1008     if (*cptr->passwd)
1009     {
1010       char salt[3];
1011
1012       salt[0] = aconf->passwd[0];
1013       salt[1] = aconf->passwd[1];
1014       salt[2] = '\0';
1015       encr = ircd_crypt(cptr->passwd, salt);
1016     }
1017     else
1018       encr = "";
1019 #else
1020     encr = cptr->passwd;
1021 #endif /* CRYPT_LINK_PASSWORD */
1022 #ifndef GODMODE
1023     if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1024       ++ServerStats->is_ref;
1025       sendto_ops("Access denied (passwd mismatch) %s", cptr->name);
1026       return exit_client_msg(cptr, cptr, &me,
1027                              "No Access (passwd mismatch) %s", cptr->name);
1028     }
1029 #endif /* not GODMODE */
1030     memset(cptr->passwd, 0, sizeof(cptr->passwd));
1031
1032 #ifndef HUB
1033     for (i = 0; i <= HighestFd; i++)
1034       if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1035         active_lh_line = 3;
1036         LHcptr = 0;
1037         break;
1038       }
1039 #endif
1040   }
1041
1042   /*
1043    *  We want to find IsConnecting() and IsHandshake() too,
1044    *  use FindClient().
1045    *  The second finds collisions with numeric representation of existing
1046    *  servers - these shouldn't happen anymore when all upgraded to 2.10.
1047    *  -- Run
1048    */
1049   while ((acptr = FindClient(host)) || 
1050          (parc > 7 && (acptr = FindNServer(parv[6]))))
1051   {
1052     /*
1053      *  This link is trying feed me a server that I already have
1054      *  access through another path
1055      *
1056      *  Do not allow Uworld to do this.
1057      *  Do not allow servers that are juped.
1058      *  Do not allow servers that have older link timestamps
1059      *    then this try.
1060      *  Do not allow servers that use the same numeric as an existing
1061      *    server, but have a different name.
1062      *
1063      *  If my ircd.conf sucks, I can try to connect to myself:
1064      */
1065     if (acptr == &me)
1066       return exit_client_msg(cptr, cptr, &me,
1067           "nick collision with me (%s)", host);
1068     /*
1069      * Detect wrong numeric.
1070      */
1071     if (0 != ircd_strcmp(acptr->name, host))
1072     {
1073       sendto_serv_butone(cptr,
1074           ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
1075           me.name, acptr->name, host);
1076       return exit_client_msg(cptr, cptr, &me,
1077           "NUMERIC collision between %s and %s."
1078           " Is your server numeric correct ?", host, acptr->name);
1079     }
1080     /*
1081      *  Kill our try, if we had one.
1082      */
1083     if (IsConnecting(acptr))
1084     {
1085       if (!active_lh_line && exit_client(cptr, acptr, &me,
1086           "Just connected via another link") == CPTR_KILLED)
1087         return CPTR_KILLED;
1088       /*
1089        * We can have only ONE 'IsConnecting', 'IsHandshake' or
1090        * 'IsServer', because new 'IsConnecting's are refused to
1091        * the same server if we already had it.
1092        */
1093       break;
1094     }
1095     /*
1096      * Avoid other nick collisions...
1097      * This is a doubtfull test though, what else would it be
1098      * when it has a server.name ?
1099      */
1100     else if (!IsServer(acptr) && !IsHandshake(acptr))
1101       return exit_client_msg(cptr, cptr, &me,
1102           "Nickname %s already exists!", host);
1103     /*
1104      * Our new server might be a juped server,
1105      * or someone trying abuse a second Uworld:
1106      */
1107     else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1108         find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1109     {
1110       if (!IsServer(sptr))
1111         return exit_client(cptr, sptr, &me, acptr->info);
1112       sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
1113           me.name, parv[0], parv[1], cptr->name);
1114       return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1115     }
1116     /*
1117      * Of course we find the handshake this link was before :)
1118      */
1119     else if (IsHandshake(acptr) && acptr == cptr)
1120       break;
1121     /*
1122      * Here we have a server nick collision...
1123      * We don't want to kill the link that was last /connected,
1124      * but we neither want to kill a good (old) link.
1125      * Therefor we kill the second youngest link.
1126      */
1127     if (1)
1128     {
1129       struct Client* c2ptr = 0;
1130       struct Client* c3ptr = acptr;
1131       struct Client* ac2ptr;
1132       struct Client* ac3ptr;
1133
1134       /* Search youngest link: */
1135       for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1136         if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1137           c3ptr = ac3ptr;
1138       if (IsServer(sptr))
1139       {
1140         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1141           if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1142             c3ptr = ac3ptr;
1143       }
1144       if (timestamp > c3ptr->serv->timestamp)
1145       {
1146         c3ptr = 0;
1147         c2ptr = acptr;          /* Make sure they differ */
1148       }
1149       /* Search second youngest link: */
1150       for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1151         if (ac2ptr != c3ptr &&
1152             ac2ptr->serv->timestamp >
1153             (c2ptr ? c2ptr->serv->timestamp : timestamp))
1154           c2ptr = ac2ptr;
1155       if (IsServer(sptr))
1156       {
1157         for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1158           if (ac2ptr != c3ptr &&
1159               ac2ptr->serv->timestamp >
1160               (c2ptr ? c2ptr->serv->timestamp : timestamp))
1161             c2ptr = ac2ptr;
1162       }
1163       if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1164         c2ptr = 0;
1165       /* If timestamps are equal, decide which link to break
1166        *  by name.
1167        */
1168       if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1169           (c3ptr ? c3ptr->serv->timestamp : timestamp))
1170       {
1171         char* n2;
1172         char* n2up;
1173         char* n3;
1174         char* n3up;
1175         if (c2ptr)
1176         {
1177           n2 = c2ptr->name;
1178           n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1179         }
1180         else
1181         {
1182           n2 = host;
1183           n2up = IsServer(sptr) ? sptr->name : me.name;
1184         }
1185         if (c3ptr)
1186         {
1187           n3 = c3ptr->name;
1188           n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1189         }
1190         else
1191         {
1192           n3 = host;
1193           n3up = IsServer(sptr) ? sptr->name : me.name;
1194         }
1195         if (strcmp(n2, n2up) > 0)
1196           n2 = n2up;
1197         if (strcmp(n3, n3up) > 0)
1198           n3 = n3up;
1199         if (strcmp(n3, n2) > 0)
1200         {
1201           ac2ptr = c2ptr;
1202           c2ptr = c3ptr;
1203           c3ptr = ac2ptr;
1204         }
1205       }
1206       /* Now squit the second youngest link: */
1207       if (!c2ptr)
1208         return exit_new_server(cptr, sptr, host, timestamp,
1209             "server %s already exists and is %ld seconds younger.",
1210             host, (long)acptr->serv->timestamp - (long)timestamp);
1211       else if (c2ptr->from == cptr || IsServer(sptr))
1212       {
1213         struct Client *killedptrfrom = c2ptr->from;
1214         if (active_lh_line)
1215         {
1216           /*
1217            * If the L: or H: line also gets rid of this link,
1218            * we sent just one squit.
1219            */
1220           if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1221             break;
1222           /*
1223            * If breaking the loop here solves the L: or H:
1224            * line problem, we don't squit that.
1225            */
1226           if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1227             active_lh_line = 0;
1228           else
1229           {
1230             /*
1231              * If we still have a L: or H: line problem,
1232              * we prefer to squit the new server, solving
1233              * loop and L:/H: line problem with only one squit.
1234              */
1235             LHcptr = 0;
1236             break;
1237           }
1238         }
1239         /*
1240          * If the new server was introduced by a server that caused a
1241          * Ghost less then 20 seconds ago, this is probably also
1242          * a Ghost... (20 seconds is more then enough because all
1243          * SERVER messages are at the beginning of a net.burst). --Run
1244          */
1245         if (CurrentTime - cptr->serv->ghost < 20)
1246         {
1247           killedptrfrom = acptr->from;
1248           if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1249             return CPTR_KILLED;
1250         }
1251         else if (exit_client_msg(cptr, c2ptr, &me,
1252             "Loop <-- %s (new link is %ld seconds younger)", host,
1253             (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1254             (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1255           return CPTR_KILLED;
1256         /*
1257          * Did we kill the incoming server off already ?
1258          */
1259         if (killedptrfrom == cptr)
1260           return 0;
1261       }
1262       else
1263       {
1264         if (active_lh_line)
1265         {
1266           if (LHcptr && a_kills_b_too(LHcptr, acptr))
1267             break;
1268           if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1269             active_lh_line = 0;
1270           else
1271           {
1272             LHcptr = 0;
1273             break;
1274           }
1275         }
1276         /*
1277          * We can't believe it is a lagged server message
1278          * when it directly connects to us...
1279          * kill the older link at the ghost, rather then
1280          * at the second youngest link, assuming it isn't
1281          * a REAL loop.
1282          */
1283         ghost = CurrentTime;            /* Mark that it caused a ghost */
1284         if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1285           return CPTR_KILLED;
1286         break;
1287       }
1288     }
1289   }
1290
1291   if (active_lh_line)
1292   {
1293     if (LHcptr == 0) {
1294       return exit_new_server(cptr, sptr, host, timestamp,
1295           (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1296           cptr->name, host,
1297           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1298     }
1299     else
1300     {
1301       int killed = a_kills_b_too(LHcptr, sptr);
1302       if (active_lh_line < 3)
1303       {
1304         if (exit_client_msg(cptr, LHcptr, &me,
1305             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1306             cptr->name, host,
1307             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1308           return CPTR_KILLED;
1309       }
1310       else
1311       {
1312         ServerStats->is_ref++;
1313         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
1314           return CPTR_KILLED;
1315       }
1316       /*
1317        * Did we kill the incoming server off already ?
1318        */
1319       if (killed)
1320         return 0;
1321     }
1322   }
1323
1324   if (IsServer(cptr))
1325   {
1326     /*
1327      * Server is informing about a new server behind
1328      * this link. Create REMOTE server structure,
1329      * add it to list and propagate word to my other
1330      * server links...
1331      */
1332
1333     acptr = make_client(cptr, STAT_SERVER);
1334     make_server(acptr);
1335     acptr->serv->prot = prot;
1336     acptr->serv->timestamp = timestamp;
1337     acptr->hopcount = hop;
1338     ircd_strncpy(acptr->name, host, HOSTLEN);
1339     ircd_strncpy(acptr->info, info, REALLEN);
1340     acptr->serv->up = sptr;
1341     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
1342     /* Use cptr, because we do protocol 9 -> 10 translation
1343        for numeric nicks ! */
1344     SetServerYXX(cptr, acptr, parv[6]);
1345
1346     Count_newremoteserver(UserStats);
1347     if (Protocol(acptr) < 10)
1348       acptr->flags |= FLAGS_TS8;
1349     add_client_to_list(acptr);
1350     hAddClient(acptr);
1351     if (*parv[5] == 'J')
1352     {
1353       SetBurst(acptr);
1354       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
1355           sptr->name, acptr->name);
1356       SetJunction(acptr);
1357     }
1358     /*
1359      * Old sendto_serv_but_one() call removed because we now need to send
1360      * different names to different servers (domain name matching).
1361      */
1362     for (i = 0; i <= HighestFd; i++)
1363     {
1364       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
1365           bcptr == cptr || IsMe(bcptr))
1366         continue;
1367       if (0 == match(me.name, acptr->name))
1368         continue;
1369         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
1370             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
1371             NumServCap(acptr), acptr->info);
1372     }
1373     return 0;
1374   }
1375
1376   if (IsUnknown(cptr) || IsHandshake(cptr))
1377   {
1378     make_server(cptr);
1379     cptr->serv->timestamp = timestamp;
1380     cptr->serv->prot = prot;
1381     cptr->serv->ghost = ghost;
1382     SetServerYXX(cptr, cptr, parv[6]);
1383     if (start_timestamp > OLDEST_TS)
1384     {
1385 #ifndef RELIABLE_CLOCK
1386 #ifdef TESTNET
1387       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
1388           TIME_T_FMT, me.serv->timestamp, start_timestamp);
1389       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
1390           TIME_T_FMT " ; difference %ld",
1391           recv_time, timestamp, timestamp - recv_time);
1392 #endif
1393       if (start_timestamp < me.serv->timestamp)
1394       {
1395         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
1396             start_timestamp, me.serv->timestamp);
1397         me.serv->timestamp = start_timestamp;
1398         TSoffset += timestamp - recv_time;
1399         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
1400       }
1401       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
1402         cptr->serv->timestamp = TStime();
1403
1404       else if (timestamp != recv_time)
1405       {
1406         /*
1407          * Equal start times, we have a collision.  Let the connected-to server
1408          * decide. This assumes leafs issue more than half of the connection
1409          * attempts.
1410          */
1411         if (IsUnknown(cptr))
1412           cptr->serv->timestamp = TStime();
1413         else if (IsHandshake(cptr))
1414         {
1415           sendto_ops("clock adjusted by adding %d",
1416               (int)(timestamp - recv_time));
1417           TSoffset += timestamp - recv_time;
1418         }
1419       }
1420 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
1421       if (start_timestamp < me.serv->timestamp)
1422         me.serv->timestamp = start_timestamp;
1423       if (IsUnknown(cptr))
1424         cptr->serv->timestamp = TStime();
1425 #endif
1426     }
1427
1428     ret = server_estab(cptr, aconf);
1429   }
1430   else
1431     ret = 0;
1432 #ifdef RELIABLE_CLOCK
1433   if (abs(cptr->serv->timestamp - recv_time) > 30)
1434   {
1435     sendto_ops("Connected to a net with a timestamp-clock"
1436         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
1437         " this.", timestamp - recv_time);
1438     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
1439         me.name, TStime(), me.name);
1440   }
1441 #endif
1442
1443   return ret;
1444 }
1445
1446
1447 #if 0
1448 /*
1449  *  m_server
1450  *
1451  *    parv[0] = sender prefix
1452  *    parv[1] = servername
1453  *    parv[2] = hopcount
1454  *    parv[3] = start timestamp
1455  *    parv[4] = link timestamp
1456  *    parv[5] = major protocol version: P09/P10
1457  *    parv[parc-1] = serverinfo
1458  *  If cptr is P10:
1459  *    parv[6] = "YMM", where 'Y' is the server numeric and "MM" is the
1460  *              numeric nick mask of this server.
1461  *    parv[7] = 0 (not used yet, mandatory unsigned int after u2.10.06)
1462  */
1463 int m_server(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
1464 {
1465   char*            ch;
1466   int              i;
1467   char             info[REALLEN + 1];
1468   char*            host;
1469   struct Client*   acptr;
1470   struct Client*   bcptr;
1471   struct Client*   LHcptr = 0;
1472   struct ConfItem* aconf = 0;
1473   struct ConfItem* cconf;
1474   struct ConfItem* lhconf = 0;
1475   struct Jupe*     ajupe = 0;
1476   int              hop;
1477   int              ret;
1478   int              active_lh_line = 0;
1479   unsigned short   prot;
1480   time_t           start_timestamp;
1481   time_t           timestamp = 0;
1482   time_t           recv_time;
1483   time_t           ghost = 0;
1484
1485   if (IsUser(cptr))
1486   {
1487     sendto_one(cptr, err_str(ERR_ALREADYREGISTRED), me.name, parv[0]);
1488     return 0;
1489   }
1490
1491   if (IsUserPort(cptr))
1492     return exit_client_msg(cptr, cptr, &me,
1493         "You cannot connect a server to a user port; connect to %s port %u",
1494         me.name, server_port);
1495
1496   recv_time = TStime();
1497   info[0] = '\0';
1498   if (parc < 7)
1499   {
1500     return need_more_params(sptr, "SERVER");
1501     return exit_client(cptr, cptr, &me, "Need more parameters");
1502   }
1503   host = parv[1];
1504   /*
1505    * Detect protocol
1506    */
1507   if (strlen(parv[5]) != 3 || (parv[5][0] != 'P' && parv[5][0] != 'J'))
1508     return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
1509
1510   if (!IsServer(cptr))          /* Don't allow silently connecting a server */
1511     *parv[5] = 'J';
1512
1513   prot = atoi(parv[5] + 1);
1514   if (prot > atoi(MAJOR_PROTOCOL))
1515     prot = atoi(MAJOR_PROTOCOL);
1516   /*
1517    * Because the previous test is only in 2.10, the following is needed
1518    * till all servers are 2.10:
1519    */
1520   if (IsServer(cptr) && prot > Protocol(cptr))
1521     prot = Protocol(cptr);
1522   hop = atoi(parv[2]);
1523   start_timestamp = atoi(parv[3]);
1524   timestamp = atoi(parv[4]);
1525   Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age " TIME_T_FMT " ("
1526       TIME_T_FMT ")", host, parv[4], start_timestamp, me.serv->timestamp));
1527   if ((timestamp < OLDEST_TS || (hop == 1 && start_timestamp < OLDEST_TS)))
1528   {
1529     return exit_client_msg(cptr, sptr, &me,
1530         "Bogus timestamps (%s %s)", parv[3], parv[4]);
1531   }
1532   ircd_strncpy(info, parv[parc - 1], REALLEN);
1533   info[REALLEN] = '\0';
1534   if (prot < atoi(MINOR_PROTOCOL)) {
1535     sendto_ops("Got incompatible protocol version (%s) from %s",
1536                parv[5], cptr->name);
1537     return exit_new_server(cptr, sptr, host, timestamp,
1538         "Incompatible protocol: %s", parv[5]);
1539   }
1540   /*
1541    * Check for "FRENCH " infection ;-) (actually this should
1542    * be replaced with routine to check the hostname syntax in
1543    * general). [ This check is still needed, even after the parse
1544    * is fixed, because someone can send "SERVER :foo bar " ].
1545    * Also, changed to check other "difficult" characters, now
1546    * that parse lets all through... --msa
1547    */
1548   if (strlen(host) > HOSTLEN)
1549     host[HOSTLEN] = '\0';
1550   for (ch = host; *ch; ch++)
1551     if (*ch <= ' ' || *ch > '~')
1552       break;
1553   if (*ch || !strchr(host, '.'))
1554   {
1555     sendto_ops("Bogus server name (%s) from %s", host, cptr->name);
1556     return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
1557   }
1558
1559   if (IsServer(cptr))
1560   {
1561     /*
1562      * A local server introduces a new server behind this link.
1563      * Check if this is allowed according L:, H: and Q: lines.
1564      */
1565     if (info[0] == '\0')
1566       return exit_client_msg(cptr, cptr, &me,
1567           "No server info specified for %s", host);
1568     /*
1569      * See if the newly found server is behind a guaranteed
1570      * leaf (L-line). If so, close the link.
1571      */
1572     if ((lhconf = find_conf_byhost(cptr->confs, cptr->name, CONF_LEAF)) &&
1573         (!lhconf->port || (hop > lhconf->port)))
1574     {
1575       /*
1576        * L: lines normally come in pairs, here we try to
1577        * make sure that the oldest link is squitted, not
1578        * both.
1579        */
1580       active_lh_line = 1;
1581       if (timestamp <= cptr->serv->timestamp)
1582         LHcptr = 0;          /* Kill incoming server */
1583       else
1584         LHcptr = cptr;          /* Squit ourselfs */
1585     }
1586     else if (!(lhconf = find_conf_byname(cptr->confs, cptr->name, CONF_HUB)) ||
1587              (lhconf->port && (hop > lhconf->port)))
1588     {
1589       struct Client *ac3ptr;
1590       active_lh_line = 2;
1591       /* Look for net junction causing this: */
1592       LHcptr = 0;            /* incoming server */
1593       if (*parv[5] != 'J') {
1594         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up) {
1595           if (IsJunction(ac3ptr)) {
1596             LHcptr = ac3ptr;
1597             break;
1598           }
1599         }
1600       }
1601     }
1602   }
1603
1604   if (IsUnknown(cptr) || IsHandshake(cptr))
1605   {
1606     const char* encr;
1607
1608     /*
1609      * A local link that is still in undefined state wants
1610      * to be a SERVER. Check if this is allowed and change
1611      * status accordingly...
1612      */
1613     /*
1614      * If there is more then one server on the same machine
1615      * that we try to connect to, it could be that the /CONNECT
1616      * <mask> caused this connect to be put at the wrong place
1617      * in the hashtable.        --Run
1618      * Same thing for Unknown connections that first send NICK.
1619      *                          --Xorath
1620      * Better check if the two strings are (caseless) identical 
1621      * and not mess with hash internals. 
1622      *                          --Nemesi
1623      */
1624     if ((!(EmptyString(cptr->name)))
1625         && (IsUnknown(cptr) || IsHandshake(cptr))
1626         && 0 != ircd_strcmp(cptr->name, host))
1627       hChangeClient(cptr, host);
1628     ircd_strncpy(cptr->name, host, HOSTLEN);
1629     ircd_strncpy(cptr->info, info[0] ? info : me.name, REALLEN);
1630     cptr->hopcount = hop;
1631
1632     /* check connection rules */
1633     for (cconf = GlobalConfList; cconf; cconf = cconf->next) {
1634       if ((cconf->status == CONF_CRULEALL) && (match(cconf->host, host) == 0)) {
1635         if (crule_eval(cconf->passwd))
1636         {
1637           ServerStats->is_ref++;
1638           sendto_ops("Refused connection from %s.", cptr->name);
1639           return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
1640         }
1641       }
1642     }
1643     if (conf_check_server(cptr)) {
1644       ++ServerStats->is_ref;
1645       sendto_ops("Received unauthorized connection from %s.", cptr->name);
1646       return exit_client(cptr, cptr, &me, "No C/N conf lines");
1647     }
1648
1649     host = cptr->name;
1650
1651     update_load();
1652
1653     if (!(aconf = find_conf_byname(cptr->confs, host, CONF_SERVER))) {
1654       ++ServerStats->is_ref;
1655 #ifndef GODMODE
1656       sendto_ops("Access denied. No conf line for server %s", cptr->name);
1657       return exit_client_msg(cptr, cptr, &me,
1658           "Access denied. No conf line for server %s", cptr->name);
1659 #else /* GODMODE */
1660       sendto_ops("General C/N: line active: No line for server %s", cptr->name);
1661       aconf =
1662           find_conf_byname(cptr->confs, "general.undernet.org", CONF_SERVER);
1663       if (!aconf) {
1664         sendto_ops("Neither C/N lines for server %s nor "
1665             "\"general.undernet.org\"", cptr->name);
1666         return exit_client_msg(cptr, cptr, &me,
1667             "No C/N lines for server %s", cptr->name);
1668       }
1669 #endif /* GODMODE */
1670     }
1671 #ifdef CRYPT_LINK_PASSWORD
1672     /* passwd may be NULL. Head it off at the pass... */
1673     if (*cptr->passwd)
1674     {
1675       char salt[3];
1676
1677       salt[0] = aconf->passwd[0];
1678       salt[1] = aconf->passwd[1];
1679       salt[2] = '\0';
1680       encr = ircd_crypt(cptr->passwd, salt);
1681     }
1682     else
1683       encr = "";
1684 #else
1685     encr = cptr->passwd;
1686 #endif /* CRYPT_LINK_PASSWORD */
1687 #ifndef GODMODE
1688     if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) {
1689       ++ServerStats->is_ref;
1690       sendto_ops("Access denied (passwd mismatch) %s", cptr->name);
1691       return exit_client_msg(cptr, cptr, &me,
1692           "No Access (passwd mismatch) %s", cptr->name);
1693     }
1694 #endif /* not GODMODE */
1695     memset(cptr->passwd, 0, sizeof(cptr->passwd));
1696
1697 #ifndef HUB
1698     for (i = 0; i <= HighestFd; i++)
1699       if (LocalClientArray[i] && IsServer(LocalClientArray[i])) {
1700         active_lh_line = 3;
1701         LHcptr = 0;
1702         break;
1703       }
1704 #endif
1705   }
1706
1707   /*
1708    *  We want to find IsConnecting() and IsHandshake() too,
1709    *  use FindClient().
1710    *  The second finds collisions with numeric representation of existing
1711    *  servers - these shouldn't happen anymore when all upgraded to 2.10.
1712    *  -- Run
1713    */
1714   while ((acptr = FindClient(host)) || 
1715          (parc > 7 && (acptr = FindNServer(parv[6]))))
1716   {
1717     /*
1718      *  This link is trying feed me a server that I already have
1719      *  access through another path
1720      *
1721      *  Do not allow Uworld to do this.
1722      *  Do not allow servers that are juped.
1723      *  Do not allow servers that have older link timestamps
1724      *    then this try.
1725      *  Do not allow servers that use the same numeric as an existing
1726      *    server, but have a different name.
1727      *
1728      *  If my ircd.conf sucks, I can try to connect to myself:
1729      */
1730     if (acptr == &me)
1731       return exit_client_msg(cptr, cptr, &me,
1732           "nick collision with me (%s)", host);
1733     /*
1734      * Detect wrong numeric.
1735      */
1736     if (0 != ircd_strcmp(acptr->name, host))
1737     {
1738       sendto_serv_butone(cptr,
1739           ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
1740           me.name, acptr->name, host);
1741       return exit_client_msg(cptr, cptr, &me,
1742           "NUMERIC collision between %s and %s."
1743           " Is your server numeric correct ?", host, acptr->name);
1744     }
1745     /*
1746      *  Kill our try, if we had one.
1747      */
1748     if (IsConnecting(acptr))
1749     {
1750       if (!active_lh_line && exit_client(cptr, acptr, &me,
1751           "Just connected via another link") == CPTR_KILLED)
1752         return CPTR_KILLED;
1753       /*
1754        * We can have only ONE 'IsConnecting', 'IsHandshake' or
1755        * 'IsServer', because new 'IsConnecting's are refused to
1756        * the same server if we already had it.
1757        */
1758       break;
1759     }
1760     /*
1761      * Avoid other nick collisions...
1762      * This is a doubtfull test though, what else would it be
1763      * when it has a server.name ?
1764      */
1765     else if (!IsServer(acptr) && !IsHandshake(acptr))
1766       return exit_client_msg(cptr, cptr, &me,
1767           "Nickname %s already exists!", host);
1768     /*
1769      * Our new server might be a juped server,
1770      * or someone trying abuse a second Uworld:
1771      */
1772     else if (IsServer(acptr) && (0 == ircd_strncmp(acptr->info, "JUPE", 4) ||
1773         find_conf_byhost(cptr->confs, acptr->name, CONF_UWORLD)))
1774     {
1775       if (!IsServer(sptr))
1776         return exit_client(cptr, sptr, &me, acptr->info);
1777       sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
1778           me.name, parv[0], parv[1], cptr->name);
1779       return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
1780     }
1781     /*
1782      * Of course we find the handshake this link was before :)
1783      */
1784     else if (IsHandshake(acptr) && acptr == cptr)
1785       break;
1786     /*
1787      * Here we have a server nick collision...
1788      * We don't want to kill the link that was last /connected,
1789      * but we neither want to kill a good (old) link.
1790      * Therefor we kill the second youngest link.
1791      */
1792     if (1)
1793     {
1794       struct Client* c2ptr = 0;
1795       struct Client* c3ptr = acptr;
1796       struct Client* ac2ptr;
1797       struct Client* ac3ptr;
1798
1799       /* Search youngest link: */
1800       for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1801         if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1802           c3ptr = ac3ptr;
1803       if (IsServer(sptr))
1804       {
1805         for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
1806           if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
1807             c3ptr = ac3ptr;
1808       }
1809       if (timestamp > c3ptr->serv->timestamp)
1810       {
1811         c3ptr = 0;
1812         c2ptr = acptr;          /* Make sure they differ */
1813       }
1814       /* Search second youngest link: */
1815       for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1816         if (ac2ptr != c3ptr &&
1817             ac2ptr->serv->timestamp >
1818             (c2ptr ? c2ptr->serv->timestamp : timestamp))
1819           c2ptr = ac2ptr;
1820       if (IsServer(sptr))
1821       {
1822         for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
1823           if (ac2ptr != c3ptr &&
1824               ac2ptr->serv->timestamp >
1825               (c2ptr ? c2ptr->serv->timestamp : timestamp))
1826             c2ptr = ac2ptr;
1827       }
1828       if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
1829         c2ptr = 0;
1830       /* If timestamps are equal, decide which link to break
1831        *  by name.
1832        */
1833       if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
1834           (c3ptr ? c3ptr->serv->timestamp : timestamp))
1835       {
1836         char* n2;
1837         char* n2up;
1838         char* n3;
1839         char* n3up;
1840         if (c2ptr)
1841         {
1842           n2 = c2ptr->name;
1843           n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
1844         }
1845         else
1846         {
1847           n2 = host;
1848           n2up = IsServer(sptr) ? sptr->name : me.name;
1849         }
1850         if (c3ptr)
1851         {
1852           n3 = c3ptr->name;
1853           n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
1854         }
1855         else
1856         {
1857           n3 = host;
1858           n3up = IsServer(sptr) ? sptr->name : me.name;
1859         }
1860         if (strcmp(n2, n2up) > 0)
1861           n2 = n2up;
1862         if (strcmp(n3, n3up) > 0)
1863           n3 = n3up;
1864         if (strcmp(n3, n2) > 0)
1865         {
1866           ac2ptr = c2ptr;
1867           c2ptr = c3ptr;
1868           c3ptr = ac2ptr;
1869         }
1870       }
1871       /* Now squit the second youngest link: */
1872       if (!c2ptr)
1873         return exit_new_server(cptr, sptr, host, timestamp,
1874             "server %s already exists and is %ld seconds younger.",
1875             host, (long)acptr->serv->timestamp - (long)timestamp);
1876       else if (c2ptr->from == cptr || IsServer(sptr))
1877       {
1878         struct Client *killedptrfrom = c2ptr->from;
1879         if (active_lh_line)
1880         {
1881           /*
1882            * If the L: or H: line also gets rid of this link,
1883            * we sent just one squit.
1884            */
1885           if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
1886             break;
1887           /*
1888            * If breaking the loop here solves the L: or H:
1889            * line problem, we don't squit that.
1890            */
1891           if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
1892             active_lh_line = 0;
1893           else
1894           {
1895             /*
1896              * If we still have a L: or H: line problem,
1897              * we prefer to squit the new server, solving
1898              * loop and L:/H: line problem with only one squit.
1899              */
1900             LHcptr = 0;
1901             break;
1902           }
1903         }
1904         /*
1905          * If the new server was introduced by a server that caused a
1906          * Ghost less then 20 seconds ago, this is probably also
1907          * a Ghost... (20 seconds is more then enough because all
1908          * SERVER messages are at the beginning of a net.burst). --Run
1909          */
1910         if (CurrentTime - cptr->serv->ghost < 20)
1911         {
1912           killedptrfrom = acptr->from;
1913           if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
1914             return CPTR_KILLED;
1915         }
1916         else if (exit_client_msg(cptr, c2ptr, &me,
1917             "Loop <-- %s (new link is %ld seconds younger)", host,
1918             (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
1919             (long)c2ptr->serv->timestamp) == CPTR_KILLED)
1920           return CPTR_KILLED;
1921         /*
1922          * Did we kill the incoming server off already ?
1923          */
1924         if (killedptrfrom == cptr)
1925           return 0;
1926       }
1927       else
1928       {
1929         if (active_lh_line)
1930         {
1931           if (LHcptr && a_kills_b_too(LHcptr, acptr))
1932             break;
1933           if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
1934             active_lh_line = 0;
1935           else
1936           {
1937             LHcptr = 0;
1938             break;
1939           }
1940         }
1941         /*
1942          * We can't believe it is a lagged server message
1943          * when it directly connects to us...
1944          * kill the older link at the ghost, rather then
1945          * at the second youngest link, assuming it isn't
1946          * a REAL loop.
1947          */
1948         ghost = CurrentTime;            /* Mark that it caused a ghost */
1949         if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
1950           return CPTR_KILLED;
1951         break;
1952       }
1953     }
1954   }
1955
1956   if (active_lh_line)
1957   {
1958     if (LHcptr == 0) {
1959       return exit_new_server(cptr, sptr, host, timestamp,
1960           (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1961           cptr->name, host,
1962           lhconf ? (lhconf->name ? lhconf->name : "*") : "!");
1963     }
1964     else
1965     {
1966       int killed = a_kills_b_too(LHcptr, sptr);
1967       if (active_lh_line < 3)
1968       {
1969         if (exit_client_msg(cptr, LHcptr, &me,
1970             (active_lh_line == 2) ?  "Non-Hub link %s <- %s(%s)" : "Leaf-only link %s <- %s(%s)",
1971             cptr->name, host,
1972             lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED)
1973           return CPTR_KILLED;
1974       }
1975       else
1976       {
1977         ServerStats->is_ref++;
1978         if (exit_client(cptr, LHcptr, &me, "I'm a leaf") == CPTR_KILLED)
1979           return CPTR_KILLED;
1980       }
1981       /*
1982        * Did we kill the incoming server off already ?
1983        */
1984       if (killed)
1985         return 0;
1986     }
1987   }
1988
1989   if (IsServer(cptr))
1990   {
1991     /*
1992      * Server is informing about a new server behind
1993      * this link. Create REMOTE server structure,
1994      * add it to list and propagate word to my other
1995      * server links...
1996      */
1997
1998     acptr = make_client(cptr, STAT_SERVER);
1999     make_server(acptr);
2000     acptr->serv->prot = prot;
2001     acptr->serv->timestamp = timestamp;
2002     acptr->hopcount = hop;
2003     ircd_strncpy(acptr->name, host, HOSTLEN);
2004     ircd_strncpy(acptr->info, info, REALLEN);
2005     acptr->serv->up = sptr;
2006     acptr->serv->updown = add_dlink(&sptr->serv->down, acptr);
2007     /* Use cptr, because we do protocol 9 -> 10 translation
2008        for numeric nicks ! */
2009     SetServerYXX(cptr, acptr, parv[6]);
2010
2011     Count_newremoteserver(UserStats);
2012     if (Protocol(acptr) < 10)
2013       acptr->flags |= FLAGS_TS8;
2014     add_client_to_list(acptr);
2015     hAddClient(acptr);
2016     if (*parv[5] == 'J')
2017     {
2018       SetBurst(acptr);
2019       sendto_op_mask(SNO_NETWORK, "Net junction: %s %s",
2020           sptr->name, acptr->name);
2021       SetJunction(acptr);
2022     }
2023     /*
2024      * Old sendto_serv_but_one() call removed because we now need to send
2025      * different names to different servers (domain name matching).
2026      */
2027     for (i = 0; i <= HighestFd; i++)
2028     {
2029       if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
2030           bcptr == cptr || IsMe(bcptr))
2031         continue;
2032       if (0 == match(me.name, acptr->name))
2033         continue;
2034         sendto_one(bcptr, "%s " TOK_SERVER " %s %d 0 %s %s %s%s 0 :%s",
2035             NumServ(sptr), acptr->name, hop + 1, parv[4], parv[5],
2036             NumServCap(acptr), acptr->info);
2037     }
2038     return 0;
2039   }
2040
2041   if (IsUnknown(cptr) || IsHandshake(cptr))
2042   {
2043     make_server(cptr);
2044     cptr->serv->timestamp = timestamp;
2045     cptr->serv->prot = prot;
2046     cptr->serv->ghost = ghost;
2047     SetServerYXX(cptr, cptr, parv[6]);
2048     if (start_timestamp > OLDEST_TS)
2049     {
2050 #ifndef RELIABLE_CLOCK
2051 #ifdef TESTNET
2052       sendto_ops("Debug: my start time: " TIME_T_FMT " ; others start time: "
2053           TIME_T_FMT, me.serv->timestamp, start_timestamp);
2054       sendto_ops("Debug: receive time: " TIME_T_FMT " ; received timestamp: "
2055           TIME_T_FMT " ; difference %ld",
2056           recv_time, timestamp, timestamp - recv_time);
2057 #endif
2058       if (start_timestamp < me.serv->timestamp)
2059       {
2060         sendto_ops("got earlier start time: " TIME_T_FMT " < " TIME_T_FMT,
2061             start_timestamp, me.serv->timestamp);
2062         me.serv->timestamp = start_timestamp;
2063         TSoffset += timestamp - recv_time;
2064         sendto_ops("clock adjusted by adding %d", (int)(timestamp - recv_time));
2065       }
2066       else if ((start_timestamp > me.serv->timestamp) && IsUnknown(cptr))
2067         cptr->serv->timestamp = TStime();
2068
2069       else if (timestamp != recv_time)
2070       {
2071         /*
2072          * Equal start times, we have a collision.  Let the connected-to server
2073          * decide. This assumes leafs issue more than half of the connection
2074          * attempts.
2075          */
2076         if (IsUnknown(cptr))
2077           cptr->serv->timestamp = TStime();
2078         else if (IsHandshake(cptr))
2079         {
2080           sendto_ops("clock adjusted by adding %d",
2081               (int)(timestamp - recv_time));
2082           TSoffset += timestamp - recv_time;
2083         }
2084       }
2085 #else /* RELIABLE CLOCK IS TRUE, we _always_ use our own clock */
2086       if (start_timestamp < me.serv->timestamp)
2087         me.serv->timestamp = start_timestamp;
2088       if (IsUnknown(cptr))
2089         cptr->serv->timestamp = TStime();
2090 #endif
2091     }
2092
2093     ret = server_estab(cptr, aconf);
2094   }
2095   else
2096     ret = 0;
2097 #ifdef RELIABLE_CLOCK
2098   if (abs(cptr->serv->timestamp - recv_time) > 30)
2099   {
2100     sendto_ops("Connected to a net with a timestamp-clock"
2101         " difference of " STIME_T_FMT " seconds! Used SETTIME to correct"
2102         " this.", timestamp - recv_time);
2103     sendto_one(cptr, ":%s SETTIME " TIME_T_FMT " :%s",
2104         me.name, TStime(), me.name);
2105   }
2106 #endif
2107
2108   return ret;
2109 }
2110 #endif /* 0 */
2111