static int change_nick(struct Client *client_p, const char *newnick) { char note[NICKLEN + 10]; client_p->tsinfo = rb_current_time(); monitor_signoff(client_p); invalidate_bancache_user(client_p); sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Forced nick change: From %s to %s [%s@%s]", client_p->name, newnick, client_p->username, client_p->host); sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s", client_p->name, client_p->username, client_p->host, newnick); add_history(client_p, 1); sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld", use_id(client_p), newnick, (long) client_p->tsinfo); del_from_client_hash(client_p->name, client_p); strcpy(client_p->name, newnick); add_to_client_hash(client_p->name, client_p); monitor_signon(client_p); del_all_accepts(client_p); rb_snprintf(note, NICKLEN + 10, "Nick: %s", client_p->name); rb_note(client_p->localClient->F, note); return 0; }
/* ** Exit one client, local or remote. Assuming all dependents have ** been already removed, and socket closed for local client. */ static void exit_one_client(struct Client *client_p, struct Client *source_p, struct Client *from, const char *comment) { struct Client* target_p; dlink_node *lp; dlink_node *next_lp; if (IsServer(source_p)) { if (source_p->servptr && source_p->servptr->serv) del_client_from_llist(&(source_p->servptr->serv->servers), source_p); else ts_warn("server %s without servptr!", source_p->name); if(!IsMe(source_p)) remove_server_from_list(source_p); } else if (source_p->servptr && source_p->servptr->serv) { del_client_from_llist(&(source_p->servptr->serv->users), source_p); } /* there are clients w/o a servptr: unregistered ones */ /* ** For a server or user quitting, propogate the information to ** other servers (except to the one where is came from (client_p)) */ if (IsMe(source_p)) { sendto_realops_flags(FLAGS_ALL, L_ALL, "ERROR: tried to exit me! : %s", comment); return; /* ...must *never* exit self!! */ } else if (IsServer(source_p)) { /* ** Old sendto_serv_but_one() call removed because we now ** need to send different names to different servers ** (domain name matching) */ /* ** The bulk of this is done in remove_dependents now, all ** we have left to do is send the SQUIT upstream. -orabidoo */ if (source_p->localClient) { if(source_p->localClient->ctrlfd > -1) { fd_close(source_p->localClient->ctrlfd); source_p->localClient->ctrlfd = -1; #ifndef HAVE_SOCKETPAIR fd_close(source_p->localClient->ctrlfd_r); fd_close(source_p->localClient->fd_r); source_p->localClient->ctrlfd_r = -1; source_p->localClient->fd_r = -1; #endif } } target_p = source_p->from; if (target_p && IsServer(target_p) && target_p != client_p && !IsMe(target_p) && (source_p->flags & FLAGS_KILLED) == 0) sendto_one(target_p, ":%s SQUIT %s :%s", from->name, source_p->name, comment); } else if (source_p->name[0]) /* ...just clean all others with QUIT... */ { /* ** If this exit is generated from "m_kill", then there ** is no sense in sending the QUIT--KILL's have been ** sent instead. */ if ((source_p->flags & FLAGS_KILLED) == 0) { sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS, NOFLAGS, ":%s QUIT :%s", source_p->name, comment); } /* ** If a person is on a channel, send a QUIT notice ** to every client (person) on the same channel (so ** that the client can show the "**signoff" message). ** (Note: The notice is to the local clients *only*) */ if (source_p->user) { sendto_common_channels_local(source_p, ":%s!%s@%s QUIT :%s", source_p->name, source_p->username, source_p->host, comment); for (lp = source_p->user->channel.head; lp; lp = next_lp) { next_lp = lp->next; remove_user_from_channel(lp->data, source_p); } /* Should not be in any channels now */ assert(source_p->user->channel.head == NULL); /* Clean up invitefield */ for (lp = source_p->user->invited.head; lp; lp = next_lp) { next_lp = lp->next; del_invite(lp->data, source_p); } /* Clean up allow lists */ del_all_accepts(source_p); add_history(source_p, 0); off_history(source_p); if (HasID(source_p)) del_from_id_hash_table(source_p->user->id, source_p); /* again, this is all that is needed */ } } /* * Remove source_p from the client lists */ del_from_client_hash_table(source_p->name, source_p); /* remove from global client list */ remove_client_from_list(source_p); /* Check to see if the client isn't already on the dead list */ assert(dlinkFind(&dead_list, source_p) == NULL); /* add to dead client dlist */ lp = make_dlink_node(); SetDead(source_p); dlinkAdd(source_p, lp, &dead_list); }
/* * change_local_nick * inputs - pointer to server * - pointer to client * output - * side effects - changes nick of a LOCAL user * */ int change_local_nick(struct Client *client_p, struct Client *source_p, char *nick) { /* ** 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. */ source_p->tsinfo = CurrentTime; 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 || (IsOper(source_p) && ConfigFileEntry.no_oper_flood)) { sendto_realops_flags(FLAGS_NCHANGE, L_ALL, "Nick change: From %s to %s [%s@%s]", source_p->name, nick, source_p->username, source_p->host); sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); if (source_p->user) { add_history(source_p, 1); /* Only hubs care about lazy link nicks not being sent on yet * lazylink leafs/leafs always send their nicks up to hub, * hence must always propogate nick changes. * hubs might not propogate a nick change, if the leaf * does not know about that client yet. */ sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS, NOFLAGS, ":%s NICK %s :%lu", source_p->name, nick, (unsigned long) source_p->tsinfo); } } else { sendto_one(source_p, form_str(ERR_NICKTOOFAST),me.name, source_p->name, source_p->name, nick, ConfigFileEntry.max_nick_time); return 0; } /* Finally, add to hash */ del_from_client_hash_table(source_p->name, source_p); strcpy(source_p->name, nick); add_to_client_hash_table(nick, source_p); /* Make sure everyone that has this client on its accept list * loses that reference. */ del_all_accepts(source_p); /* fd_desc is long enough */ fd_note(client_p->localClient->fd, "Nick: %s", nick); return 1; }
/* * nick_from_server() */ static int nick_from_server(struct Client *client_p, struct Client *source_p, int parc, char *parv[], time_t newts, char *nick) { if(IsServer(source_p)) { /* A server introducing a new client, change source */ source_p = make_client(client_p); add_client_to_list(source_p); 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]); } /* copy the nick in place */ (void) strcpy(source_p->name, nick); (void) add_to_client_hash_table(nick, source_p); if(parc > 8) { int flag; char *m; /* parse usermodes */ m = &parv[4][1]; while (*m) { flag = user_modes_from_c_to_bitmask[(unsigned char) *m]; if(!(source_p->umodes & UMODE_INVISIBLE) && (flag & UMODE_INVISIBLE)) Count.invisi++; if(!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER)) Count.oper++; source_p->umodes |= flag & SEND_UMODES; m++; } return do_remote_user(nick, client_p, source_p, parv[5], parv[6], parv[7], (parc > 9)? parv[8] : NULL, parv[(parc > 9)? 9 : 8]); } } else if(source_p->name[0]) { /* client changing their nick */ if(irccmp(parv[0], nick)) source_p->tsinfo = newts ? newts : CurrentTime; sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s", source_p->name, source_p->username, source_p->host, nick); if(source_p->user) { add_history(source_p, 1); sendto_server(client_p, NULL, NOCAPS, NOCAPS, ":%s NICK %s :%lu", parv[0], nick, (unsigned long) source_p->tsinfo); } } /* set the new nick name */ if(source_p->name[0]) del_from_client_hash_table(source_p->name, source_p); strcpy(source_p->name, nick); add_to_client_hash_table(nick, source_p); /* remove all accepts pointing to the client */ del_all_accepts(source_p); return 0; }