- /* No collisions? Set the nick name and we're done */
- if (!acptr)
- return set_nick_name(cptr, sptr, nick, parc, parv);
- /*
- * If acptr == sptr, then we have a client doing a nick
- * change between *equivalent* nicknames as far as server
- * is concerned (user is changing the case of his/her
- * nickname or somesuch)
- */
- if (acptr == sptr)
- {
- if (strcmp(acptr->name, nick) != 0)
- /*
- * Allows change of case in his/her nick
- */
- return set_nick_name(cptr, sptr, nick, parc, parv);
- else
- /*
- * This is just ':old NICK old' type thing.
- * Just forget the whole thing here. There is
- * no point forwarding it to anywhere,
- * especially since servers prior to this
- * version would treat it as nick collision.
- */
- return 0; /* NICK Message ignored */
- }
-
- /*
- * Note: From this point forward it can be assumed that
- * acptr != sptr (point to different client structures).
- */
- /*
- * If the older one is "non-person", the new entry is just
- * allowed to overwrite it. Just silently drop non-person,
- * and proceed with the nick. This should take care of the
- * "dormant nick" way of generating collisions...
- */
- if (IsUnknown(acptr) && MyConnect(acptr))
- {
- ++ServerStats->is_ref;
- IPcheck_connect_fail(acptr->ip);
- exit_client(cptr, acptr, &me, "Overridden by other sign on");
- return set_nick_name(cptr, sptr, nick, parc, parv);
- }
- /*
- * Decide, we really have a nick collision and deal with it
- */
- if (!IsServer(cptr))
- {
- /*
- * NICK is coming from local client connection. Just
- * send error reply and ignore the command.
- */
- sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name, /* XXX DEAD */
- /* parv[0] is empty when connecting */
- EmptyString(parv[0]) ? "*" : parv[0], nick);
- return 0; /* NICK message ignored */
- }
- /*
- * NICK was coming from a server connection.
- * This means we have a race condition (two users signing on
- * at the same time), or two net fragments reconnecting with the same nick.
- * The latter can happen because two different users connected
- * or because one and the same user switched server during a net break.
- * If the TimeStamps are equal, we kill both (or only 'new'
- * if it was a ":server NICK new ...").
- * Otherwise we kill the youngest when user@host differ,
- * or the oldest when they are the same.
- * We treat user and ~user as different, because if it wasn't
- * a faked ~user the AUTH wouldn't have added the '~'.
- * --Run
- *
- */
- if (IsServer(sptr))
- {
- /*
- * A new NICK being introduced by a neighbouring
- * server (e.g. message type ":server NICK new ..." received)
- */
- differ = (acptr->ip.s_addr != htonl(base64toint(parv[parc - 3]))) ||
- (0 != ircd_strcmp(acptr->user->username, parv[4]));
- sendto_ops("Nick collision on %s (%s " TIME_T_FMT " <- %s " TIME_T_FMT /* XXX DEAD */
- " (%s user@host))", acptr->name, acptr->from->name, acptr->lastnick,
- cptr->name, lastnick, differ ? "Different" : "Same");
- }
- else
- {
- /*
- * A NICK change has collided (e.g. message type ":old NICK new").
- */
- lastnick = atoi(parv[2]);
- differ = (acptr->ip.s_addr != sptr->ip.s_addr) ||
- (0 != ircd_strcmp(acptr->user->username, sptr->user->username));
- sendto_ops("Nick change collision from %s to %s (%s " TIME_T_FMT " <- %s " /* XXX DEAD */
- TIME_T_FMT ")", sptr->name, acptr->name, acptr->from->name,
- acptr->lastnick, cptr->name, lastnick);
- }