/*! * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * * - parv[0] = command * - parv[1] = nickname * - parv[2] = timestamp */ static void change_remote_nick(struct Client *source_p, char *parv[]) { int samenick = !irccmp(source_p->name, parv[1]); assert(!EmptyString(parv[1])); assert(IsClient(source_p)); assert(source_p->name[0]); /* Client changing their nick */ if (!samenick) { DelUMode(source_p, UMODE_REGISTERED); watch_check_hash(source_p, RPL_LOGOFF); source_p->tsinfo = atol(parv[2]); assert(source_p->tsinfo > 0); } sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, parv[1]); whowas_add_history(source_p, 1); sendto_server(source_p, 0, 0, ":%s NICK %s :%lu", source_p->id, parv[1], (unsigned long)source_p->tsinfo); /* Set the new nick name */ hash_del_client(source_p); strlcpy(source_p->name, parv[1], sizeof(source_p->name)); hash_add_client(source_p); if (!samenick) watch_check_hash(source_p, RPL_LOGON); }
/* set_initial_nick() * * inputs * output * side effects - * * This function is only called to set up an initially registering * client. */ static void set_initial_nick(struct Client *source_p, const char *nick) { /* Client setting NICK the first time */ /* This had to be copied here to avoid problems.. */ source_p->tsinfo = CurrentTime; source_p->localClient->registration &= ~REG_NEED_NICK; if (source_p->name[0]) hash_del_client(source_p); strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); /* fd_desc is long enough */ fd_note(&source_p->localClient->fd, "Nick: %s", nick); if (!source_p->localClient->registration) register_local_user(source_p); }
/* set_initial_nick() * * inputs * output * side effects - * * This function is only called to set up an initially registering * client. */ static void set_initial_nick(struct Client *source_p, const char *nick) { const int samenick = !irccmp(source_p->name, nick); if (!samenick) source_p->tsinfo = CurrentTime; source_p->connection->registration &= ~REG_NEED_NICK; if (source_p->name[0]) hash_del_client(source_p); strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); /* fd_desc is long enough */ fd_note(&source_p->connection->fd, "Nick: %s", source_p->name); if (!source_p->connection->registration) register_local_user(source_p); }
/* * nick_from_server() */ static void nick_from_server(struct Client *client_p, struct Client *source_p, int parc, char *parv[], time_t newts, const char *svsid, char *nick, char *ngecos) { int samenick = 0; if (IsServer(source_p)) { /* A server introducing a new client, change source */ source_p = make_client(client_p); dlinkAdd(source_p, &source_p->node, &global_client_list); if (parc > 2) source_p->hopcount = atoi(parv[2]); if (newts) source_p->tsinfo = newts; else { newts = source_p->tsinfo = CurrentTime; ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]); } strlcpy(source_p->svid, svsid, sizeof(source_p->svid)); strlcpy(source_p->info, ngecos, sizeof(source_p->info)); /* copy the nick in place */ strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); if (parc > 8) { const char *m; /* parse usermodes */ for (m = &parv[4][1]; *m; ++m) { unsigned int flag = user_modes[(unsigned char)*m]; if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER)) ++Count.oper; source_p->umodes |= flag & SEND_UMODES; } register_remote_user(source_p, parv[5], parv[6], parv[7], ngecos); return; } } else if (source_p->name[0]) { samenick = !irccmp(source_p->name, nick); /* Client changing their nick */ if (!samenick) { DelUMode(source_p, UMODE_REGISTERED); watch_check_hash(source_p, RPL_LOGOFF); source_p->tsinfo = newts ? newts : CurrentTime; } sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s", source_p->name,source_p->username, source_p->host, nick); add_history(source_p, 1); sendto_server(client_p, CAP_TS6, NOCAPS, ":%s NICK %s :%lu", ID(source_p), nick, (unsigned long)source_p->tsinfo); sendto_server(client_p, NOCAPS, CAP_TS6, ":%s NICK %s :%lu", source_p->name, nick, (unsigned long)source_p->tsinfo); } /* set the new nick name */ if (source_p->name[0]) hash_del_client(source_p); strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); if (!samenick) watch_check_hash(source_p, RPL_LOGON); }
/* change_local_nick() * * inputs - pointer to server * - pointer to client * - nick * output - * side effects - changes nick of a LOCAL user */ static void change_local_nick(struct Client *source_p, const char *nick) { assert(source_p->name[0] && !EmptyString(nick)); assert(MyConnect(source_p)); /* * Client just changing his/her nick. If he/she is * on a channel, send note of change to all clients * on that channel. Propagate notice to other servers. */ if ((source_p->localClient->last_nick_change + ConfigFileEntry.max_nick_time) < CurrentTime) source_p->localClient->number_of_nick_changes = 0; source_p->localClient->last_nick_change = CurrentTime; source_p->localClient->number_of_nick_changes++; if ((ConfigFileEntry.anti_nick_flood && (source_p->localClient->number_of_nick_changes <= ConfigFileEntry.max_nick_changes)) || !ConfigFileEntry.anti_nick_flood || (HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.no_oper_flood)) { int samenick = !irccmp(source_p->name, nick); if (!samenick) { source_p->tsinfo = CurrentTime; clear_ban_cache_client(source_p); watch_check_hash(source_p, RPL_LOGOFF); if (HasUMode(source_p, UMODE_REGISTERED)) { unsigned int oldmodes = source_p->umodes; char modebuf[IRCD_BUFSIZE] = { '\0' }; DelUMode(source_p, UMODE_REGISTERED); send_umode(source_p, source_p, oldmodes, 0xffffffff, modebuf); } } sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE, "Nick change: From %s to %s [%s@%s]", source_p->name, nick, source_p->username, source_p->host); sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); add_history(source_p, 1); sendto_server(source_p, CAP_TS6, NOCAPS, ":%s NICK %s :%lu", ID(source_p), nick, (unsigned long)source_p->tsinfo); sendto_server(source_p, NOCAPS, CAP_TS6, ":%s NICK %s :%lu", source_p->name, nick, (unsigned long)source_p->tsinfo); hash_del_client(source_p); strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); if (!samenick) watch_check_hash(source_p, RPL_LOGON); /* fd_desc is long enough */ fd_note(&source_p->localClient->fd, "Nick: %s", nick); } else sendto_one(source_p, form_str(ERR_NICKTOOFAST), me.name, source_p->name, source_p->name, nick, ConfigFileEntry.max_nick_time); }
/* change_local_nick() * * inputs - pointer to server * - pointer to client * - nick * output - * side effects - changes nick of a LOCAL user */ static void change_local_nick(struct Client *source_p, const char *nick) { int samenick = 0; assert(source_p->name[0] && !EmptyString(nick)); assert(MyClient(source_p)); /* * Client just changing his/her nick. If he/she is * on a channel, send note of change to all clients * on that channel. Propagate notice to other servers. */ if ((source_p->connection->nick.last_attempt + ConfigGeneral.max_nick_time) < CurrentTime) source_p->connection->nick.count = 0; if (ConfigGeneral.anti_nick_flood && !HasUMode(source_p, UMODE_OPER) && source_p->connection->nick.count > ConfigGeneral.max_nick_changes) { sendto_one_numeric(source_p, &me, ERR_NICKTOOFAST, nick, ConfigGeneral.max_nick_time); return; } source_p->connection->nick.last_attempt = CurrentTime; source_p->connection->nick.count++; samenick = !irccmp(source_p->name, nick); if (!samenick) { source_p->tsinfo = CurrentTime; clear_ban_cache_client(source_p); watch_check_hash(source_p, RPL_LOGOFF); if (HasUMode(source_p, UMODE_REGISTERED)) { unsigned int oldmodes = source_p->umodes; char modebuf[IRCD_BUFSIZE] = ""; DelUMode(source_p, UMODE_REGISTERED); send_umode(source_p, source_p, oldmodes, modebuf); } } sendto_realops_flags(UMODE_NCHANGE, L_ALL, SEND_NOTICE, "Nick change: From %s to %s [%s@%s]", source_p->name, nick, source_p->username, source_p->host); sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); whowas_add_history(source_p, 1); sendto_server(source_p, 0, 0, ":%s NICK %s :%lu", source_p->id, nick, (unsigned long)source_p->tsinfo); hash_del_client(source_p); strlcpy(source_p->name, nick, sizeof(source_p->name)); hash_add_client(source_p); if (!samenick) watch_check_hash(source_p, RPL_LOGON); /* fd_desc is long enough */ fd_note(&source_p->connection->fd, "Nick: %s", source_p->name); }
/*! \brief SVSNICK command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = old nickname * - parv[2] = new nickname * - parv[3] = timestamp */ static int ms_svsnick(struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL, *exists_p = NULL; if (!HasFlag(source_p, FLAGS_SERVICE) || !valid_nickname(parv[2], 1)) return 0; if ((target_p = find_person(source_p, parv[1])) == NULL) return 0; if (!MyConnect(target_p)) { if (target_p->from == source_p->from) { sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE, "Received wrong-direction SVSNICK " "for %s (behind %s) from %s", target_p->name, source_p->from->name, get_client_name(source_p, HIDE_IP)); return 0; } sendto_one(target_p, ":%s SVSNICK %s %s %s", source_p->id, target_p->id, parv[2], parv[3]); return 0; } if ((exists_p = hash_find_client(parv[2]))) { if (target_p == exists_p) { if (!strcmp(target_p->name, parv[2])) return 0; } else if (IsUnknown(exists_p)) exit_client(exists_p, "SVSNICK Override"); else { exit_client(target_p, "SVSNICK Collide"); return 0; } } target_p->tsinfo = strtoimax(parv[3], NULL, 10); clear_ban_cache_client(target_p); watch_check_hash(target_p, RPL_LOGOFF); if (HasUMode(target_p, UMODE_REGISTERED)) { const unsigned int oldmodes = target_p->umodes; char modebuf[IRCD_BUFSIZE] = ""; DelUMode(target_p, UMODE_REGISTERED); send_umode(target_p, target_p, oldmodes, modebuf); } sendto_common_channels_local(target_p, 1, 0, 0, ":%s!%s@%s NICK :%s", target_p->name, target_p->username, target_p->host, parv[2]); whowas_add_history(target_p, 1); sendto_server(NULL, 0, 0, ":%s NICK %s :%ju", target_p->id, parv[2], target_p->tsinfo); hash_del_client(target_p); strlcpy(target_p->name, parv[2], sizeof(target_p->name)); hash_add_client(target_p); watch_check_hash(target_p, RPL_LOGON); fd_note(&target_p->connection->fd, "Nick: %s", target_p->name); return 0; }