- while ((acptr = FindClient(host)) ||
- (parc > 7 && (acptr = FindNServer(parv[6]))))
- {
- /*
- * This link is trying feed me a server that I already have
- * access through another path
- *
- * Do not allow Uworld to do this.
- * Do not allow servers that are juped.
- * Do not allow servers that have older link timestamps
- * then this try.
- * Do not allow servers that use the same numeric as an existing
- * server, but have a different name.
- *
- * If my ircd.conf sucks, I can try to connect to myself:
- */
- if (acptr == &me)
- return exit_client_msg(cptr, cptr, &me,
- "nick collision with me (%s)", host);
- /*
- * Detect wrong numeric.
- */
- if (strCasediff(acptr->name, host))
- {
- sendto_serv_butone(cptr,
- ":%s WALLOPS :SERVER Numeric Collision: %s != %s",
- me.name, acptr->name, host);
- return exit_client_msg(cptr, cptr, &me,
- "NUMERIC collision between %s and %s."
- " Is your server numeric correct ?", host, acptr->name);
- }
- /*
- * Kill our try, if we had one.
- */
- if (IsConnecting(acptr))
- {
- if (!active_lh_line && exit_client(cptr, acptr, &me,
- "Just connected via another link") == CPTR_KILLED)
- return CPTR_KILLED;
- /*
- * We can have only ONE 'IsConnecting', 'IsHandshake' or
- * 'IsServer', because new 'IsConnecting's are refused to
- * the same server if we already had it.
- */
- break;
- }
- /*
- * Avoid other nick collisions...
- * This is a doubtfull test though, what else would it be
- * when it has a server.name ?
- */
- else if (!IsServer(acptr) && !IsHandshake(acptr))
- return exit_client_msg(cptr, cptr, &me,
- "Nickname %s already exists!", host);
- /*
- * Our new server might be a juped server,
- * or someone trying abuse a second Uworld:
- */
- else if (IsServer(acptr) && (strnCasecmp(acptr->info, "JUPE", 4) == 0 ||
- find_conf_host(cptr->confs, acptr->name, CONF_UWORLD)))
- {
- if (!IsServer(sptr))
- return exit_client(cptr, sptr, &me, acptr->info);
- sendto_one(cptr, ":%s WALLOPS :Received :%s SERVER %s from %s !?!",
- me.name, parv[0], parv[1], cptr->name);
- return exit_new_server(cptr, sptr, host, timestamp, "%s", acptr->info);
- }
- /*
- * Of course we find the handshake this link was before :)
- */
- else if (IsHandshake(acptr) && acptr == cptr)
- break;
- /*
- * Here we have a server nick collision...
- * We don't want to kill the link that was last /connected,
- * but we neither want to kill a good (old) link.
- * Therefor we kill the second youngest link.
- */
- if (1)
- {
- aClient *c2ptr = NULL, *c3ptr = acptr;
- aClient *ac2ptr, *ac3ptr;
-
- /* Search youngest link: */
- for (ac3ptr = acptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
- if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
- c3ptr = ac3ptr;
- if (IsServer(sptr))
- {
- for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = ac3ptr->serv->up)
- if (ac3ptr->serv->timestamp > c3ptr->serv->timestamp)
- c3ptr = ac3ptr;
- }
- if (timestamp > c3ptr->serv->timestamp)
- {
- c3ptr = NULL;
- c2ptr = acptr; /* Make sure they differ */
- }
- /* Search second youngest link: */
- for (ac2ptr = acptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
- if (ac2ptr != c3ptr &&
- ac2ptr->serv->timestamp >
- (c2ptr ? c2ptr->serv->timestamp : timestamp))
- c2ptr = ac2ptr;
- if (IsServer(sptr))
- {
- for (ac2ptr = sptr; ac2ptr != &me; ac2ptr = ac2ptr->serv->up)
- if (ac2ptr != c3ptr &&
- ac2ptr->serv->timestamp >
- (c2ptr ? c2ptr->serv->timestamp : timestamp))
- c2ptr = ac2ptr;
- }
- if (c3ptr && timestamp > (c2ptr ? c2ptr->serv->timestamp : timestamp))
- c2ptr = NULL;
- /* If timestamps are equal, decide which link to break
- * by name.
- */
- if ((c2ptr ? c2ptr->serv->timestamp : timestamp) ==
- (c3ptr ? c3ptr->serv->timestamp : timestamp))
- {
- char *n2, *n2up;
- char *n3, *n3up;
- if (c2ptr)
- {
- n2 = c2ptr->name;
- n2up = MyConnect(c2ptr) ? me.name : c2ptr->serv->up->name;
- }
- else
- {
- n2 = host;
- n2up = IsServer(sptr) ? sptr->name : me.name;
- }
- if (c3ptr)
- {
- n3 = c3ptr->name;
- n3up = MyConnect(c3ptr) ? me.name : c3ptr->serv->up->name;
- }
- else
- {
- n3 = host;
- n3up = IsServer(sptr) ? sptr->name : me.name;
- }
- if (strcmp(n2, n2up) > 0)
- n2 = n2up;
- if (strcmp(n3, n3up) > 0)
- n3 = n3up;
- if (strcmp(n3, n2) > 0)
- {
- ac2ptr = c2ptr;
- c2ptr = c3ptr;
- c3ptr = ac2ptr;
- }
- }
- /* Now squit the second youngest link: */
- if (!c2ptr)
- return exit_new_server(cptr, sptr, host, timestamp,
- "server %s already exists and is %ld seconds younger.",
- host, (long)acptr->serv->timestamp - (long)timestamp);
- else if (c2ptr->from == cptr || IsServer(sptr))
- {
- aClient *killedptrfrom = c2ptr->from;
- if (active_lh_line)
- {
- /*
- * If the L: or H: line also gets rid of this link,
- * we sent just one squit.
- */
- if (LHcptr && a_kills_b_too(LHcptr, c2ptr))
- break;
- /*
- * If breaking the loop here solves the L: or H:
- * line problem, we don't squit that.
- */
- if (c2ptr->from == cptr || (LHcptr && a_kills_b_too(c2ptr, LHcptr)))
- active_lh_line = 0;
- else
- {
- /*
- * If we still have a L: or H: line problem,
- * we prefer to squit the new server, solving
- * loop and L:/H: line problem with only one squit.
- */
- LHcptr = NULL;
- break;
- }
- }
- /*
- * If the new server was introduced by a server that caused a
- * Ghost less then 20 seconds ago, this is probably also
- * a Ghost... (20 seconds is more then enough because all
- * SERVER messages are at the beginning of a net.burst). --Run
- */
- if (now - cptr->serv->ghost < 20)
- {
- killedptrfrom = acptr->from;
- if (exit_client(cptr, acptr, &me, "Ghost loop") == CPTR_KILLED)
- return CPTR_KILLED;
- }
- else if (exit_client_msg(cptr, c2ptr, &me,
- "Loop <-- %s (new link is %ld seconds younger)", host,
- (c3ptr ? (long)c3ptr->serv->timestamp : timestamp) -
- (long)c2ptr->serv->timestamp) == CPTR_KILLED)
- return CPTR_KILLED;
- /*
- * Did we kill the incoming server off already ?
- */
- if (killedptrfrom == cptr)
- return 0;
- }
- else
- {
- if (active_lh_line)
- {
- if (LHcptr && a_kills_b_too(LHcptr, acptr))
- break;
- if (acptr->from == cptr || (LHcptr && a_kills_b_too(acptr, LHcptr)))
- active_lh_line = 0;
- else
- {
- LHcptr = NULL;
- break;
- }
- }
- /*
- * We can't believe it is a lagged server message
- * when it directly connects to us...
- * kill the older link at the ghost, rather then
- * at the second youngest link, assuming it isn't
- * a REAL loop.
- */
- ghost = now; /* Mark that it caused a ghost */
- if (exit_client(cptr, acptr, &me, "Ghost") == CPTR_KILLED)
- return CPTR_KILLED;
- break;
- }