diff --git a/include/h.h b/include/h.h index f86fba297..a94d2e7b2 100644 --- a/include/h.h +++ b/include/h.h @@ -515,8 +515,6 @@ extern u_char getrandom8(); extern u_int16_t getrandom16(); extern u_int32_t getrandom32(); #define EVENT_DRUGS BASE_VERSION -extern void rejoin_leave(aClient *sptr); -extern void rejoin_joinandmode(aClient *sptr); extern void ident_failed(aClient *cptr); extern MODVAR char extchmstr[4][64]; @@ -669,6 +667,8 @@ extern MODVAR int (*check_banned)(aClient *cptr); extern MODVAR void (*introduce_user)(aClient *to, aClient *acptr); extern MODVAR int (*check_deny_version)(aClient *cptr, char *version_string, int protocol, char *flags); extern MODVAR int (*match_user)(char *rmask, aClient *acptr, int options); +extern MODVAR void (*userhost_save_current)(aClient *sptr); +extern MODVAR void (*userhost_changed)(aClient *sptr); /* /Efuncs */ extern MODVAR aMotdFile opermotd, svsmotd, motd, botmotd, smotd, rules; @@ -798,3 +798,5 @@ extern int cipher_check(SSL_CTX *ctx, char **errstr); extern void clicap_pre_rehash(void); extern void clicap_post_rehash(void); extern void send_cap_notify(int add, char *token); +extern void sendbufto_one(aClient *to, char *msg, unsigned int quick); +extern MODVAR int current_serial; diff --git a/include/modules.h b/include/modules.h index 8e9bb2872..f0586683f 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1044,6 +1044,8 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum #define EFUNC_SEND_MODDATA_MEMBERS 51 #define EFUNC_BROADCAST_MODDATA_CLIENT 52 #define EFUNC_MATCH_USER 53 +#define EFUNC_USERHOST_SAVE_CURRENT 54 +#define EFUNC_USERHOST_CHANGED 55 /* Module flags */ #define MODFLAG_NONE 0x0000 diff --git a/include/struct.h b/include/struct.h index 444051f5f..dfbe20d3f 100644 --- a/include/struct.h +++ b/include/struct.h @@ -357,6 +357,7 @@ typedef OperPermission (*OperClassEntryEvalCallback)(OperClassACLEntryVar* varia #define PROTO_ACCOUNT_NOTIFY 0x200000 /* client supports account-notify */ #define PROTO_MLOCK 0x400000 /* server supports MLOCK */ #define PROTO_EXTSWHOIS 0x800000 /* extended SWHOIS support */ +#define PROTO_CAP_CHGHOST 0x1000000 /* CAP chghost */ /* * flags macros. diff --git a/src/channel.c b/src/channel.c index ac207352a..66cdb792a 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1269,104 +1269,6 @@ void send_user_joins(aClient *cptr, aClient *user) return; } -/* - * rejoin_leave: - * sends a PART to all channels (to local users only) - * TODO: use QUIT instead of PART if configured to do so - */ -void rejoin_leave(aClient *sptr) -{ - Membership *tmp; - aChannel *chptr; - char *comment = "Changing host"; - int i = 0; - - for (tmp = sptr->user->channel; tmp; tmp = tmp->next) - { - tmp->flags &= ~CHFL_REJOINING; - - chptr = tmp->chptr; - if (!chptr) - continue; /* Possible? */ - - /* If the user is banned, don't do it */ - if (is_banned(sptr, chptr, BANCHK_JOIN)) - continue; - - /* Ok, we will now part/quit/whatever the user, so tag it.. */ - tmp->flags |= CHFL_REJOINING; - - if (invisible_user_in_channel(sptr, chptr)) - { - sendto_chanops_butone(sptr, chptr, ":%s!%s@%s PART %s :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname, comment); - } else - sendto_channel_butserv_butone(chptr, sptr, sptr, ":%s PART %s :%s", sptr->name, chptr->chname, comment); - } -} - -/* - * rejoin_joinandmode: - * sends a JOIN and a MODE (if needed) to restore qaohv modes (to local users only) - */ -void rejoin_joinandmode(aClient *sptr) -{ - Membership *tmp; - aChannel *chptr; - int i, j = 0, n, flags; - int k = 0; - char flagbuf[8]; /* For holding "qohva" and "*~@%+" */ - - for (tmp = sptr->user->channel; tmp; tmp = tmp->next) - { - flags = tmp->flags; - chptr = tmp->chptr; - if (!chptr) - continue; /* Is it possible? */ - - /* If the user is banned, don't do it */ - if (!(flags & CHFL_REJOINING)) - continue; - - if (invisible_user_in_channel(sptr, chptr)) - { - sendto_chanops_butone(sptr, chptr, ":%s!%s@%s JOIN :%s", sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); - } else - sendto_channel_butserv_butone(chptr, sptr, sptr, ":%s JOIN :%s", sptr->name, chptr->chname); - - /* Set the modes (if any) */ - if (flags) - { - char *p = flagbuf; - if (flags & MODE_CHANOP) - *p++ = 'o'; - if (flags & MODE_VOICE) - *p++ = 'v'; - if (flags & MODE_HALFOP) - *p++ = 'h'; - if (flags & MODE_CHANOWNER) - *p++ = 'q'; - if (flags & MODE_CHANPROT) - *p++ = 'a'; - *p = '\0'; - parabuf[0] = '\0'; - n = strlen(flagbuf); - if (n) - { - for (i=0; i < n; i++) - { - strcat(parabuf, sptr->name); - if (i < n - 1) - strcat(parabuf, " "); - } - sendto_channel_butserv_butone(chptr, &me, sptr, ":%s MODE %s +%s %s", - me.name, chptr->chname, flagbuf, parabuf); - } - } - - tmp->flags &= ~CHFL_REJOINING; /* esthetics.. ;) */ - } -} - /* set_channel_mlock() * * inputs - client, source, channel, params diff --git a/src/modules.c b/src/modules.c index a3c71d729..de44d0f83 100644 --- a/src/modules.c +++ b/src/modules.c @@ -132,6 +132,8 @@ void (*send_moddata_channel)(aClient *srv, aChannel *chptr); void (*send_moddata_members)(aClient *srv); void (*broadcast_moddata_client)(aClient *acptr); int (*match_user)(char *rmask, aClient *acptr, int options); +void (*userhost_changed)(aClient *sptr); +void (*userhost_save_current)(aClient *sptr); static const EfunctionsList efunction_table[MAXEFUNCTIONS] = { /* 00 */ {NULL, NULL}, @@ -188,7 +190,9 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = { /* 51 */ {"send_moddata_members", (void *)&send_moddata_members}, /* 52 */ {"broadcast_moddata_client", (void *)&broadcast_moddata_client}, /* 53 */ {"match_user", (void *)&match_user}, -/* 54 */ {NULL, NULL} +/* 54 */ {"userhost_save_current", (void *)&userhost_save_current}, +/* 55 */ {"userhost_changed", (void *)&userhost_changed}, +/* 56 */ {NULL, NULL} }; #ifdef UNDERSCORE diff --git a/src/modules/m_cap.c b/src/modules/m_cap.c index 7cfbb1b75..7a2e5a695 100644 --- a/src/modules/m_cap.c +++ b/src/modules/m_cap.c @@ -69,6 +69,11 @@ MOD_INIT(m_cap) c.cap = PROTO_CAP_NOTIFY; ClientCapabilityAdd(modinfo->handle, &c); + memset(&c, 0, sizeof(c)); + c.name = "chghost"; + c.cap = PROTO_CAP_CHGHOST; + ClientCapabilityAdd(modinfo->handle, &c); + return MOD_SUCCESS; } diff --git a/src/modules/m_chghost.c b/src/modules/m_chghost.c index 9aa044ae2..38744be83 100644 --- a/src/modules/m_chghost.c +++ b/src/modules/m_chghost.c @@ -110,6 +110,9 @@ CMD_FUNC(m_chghost) sendnotice(sptr, "*** /ChgHost Error: requested host is same as current host."); return 0; } + + userhost_save_current(acptr); + switch (UHOST_ALLOWED) { case UHALLOW_NEVER: @@ -130,8 +133,7 @@ CMD_FUNC(m_chghost) } break; case UHALLOW_REJOIN: - rejoin_leave(acptr); - /* join sent later when the host has been changed */ + /* rejoin sent later when the host has been changed */ break; } @@ -158,9 +160,9 @@ CMD_FUNC(m_chghost) acptr->user->virthost = 0; } acptr->user->virthost = strdup(parv[2]); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(acptr); + userhost_changed(acptr); + if (MyClient(acptr)) sendto_one(acptr, err_str(RPL_HOSTHIDDEN), me.name, acptr->name, parv[2]); diff --git a/src/modules/m_chgident.c b/src/modules/m_chgident.c index dca7f971c..e396c4f49 100644 --- a/src/modules/m_chgident.c +++ b/src/modules/m_chgident.c @@ -113,6 +113,8 @@ CMD_FUNC(m_chgident) if ((acptr = find_person(parv[1], NULL))) { + userhost_save_current(acptr); + switch (UHOST_ALLOWED) { case UHALLOW_NEVER: @@ -133,7 +135,6 @@ CMD_FUNC(m_chgident) } break; case UHALLOW_REJOIN: - rejoin_leave(acptr); /* join sent later when the ident has been changed */ break; } @@ -150,13 +151,11 @@ CMD_FUNC(m_chgident) GetHost(acptr), parv[2]); } - - sendto_server(cptr, 0, 0, ":%s CHGIDENT %s %s", sptr->name, acptr->name, parv[2]); ircsnprintf(acptr->user->username, sizeof(acptr->user->username), "%s", parv[2]); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(acptr); + + userhost_changed(acptr); return 0; } else diff --git a/src/modules/m_join.c b/src/modules/m_join.c index 67f585241..fd3cea530 100644 --- a/src/modules/m_join.c +++ b/src/modules/m_join.c @@ -27,7 +27,8 @@ CMD_FUNC(m_join); DLLFUNC void _join_channel(aChannel *chptr, aClient *cptr, aClient *sptr, int flags); CMD_FUNC(_do_join); DLLFUNC int _can_join(aClient *cptr, aClient *sptr, aChannel *chptr, char *key, char *parv[]); -#define MAXBOUNCE 5 /** Most sensible */ +void _userhost_save_current(aClient *sptr); +void _userhost_changed(aClient *sptr); /* Externs */ extern MODVAR int spamf_ugly_vchanoverride; @@ -36,6 +37,8 @@ extern int find_invex(aChannel *chptr, aClient *sptr); /* Local vars */ static int bouncedtimes = 0; +/* Macros */ +#define MAXBOUNCE 5 /** Most sensible */ #define MSG_JOIN "JOIN" ModuleHeader MOD_HEADER(m_join) @@ -53,6 +56,9 @@ MOD_TEST(m_join) EfunctionAddVoid(modinfo->handle, EFUNC_JOIN_CHANNEL, _join_channel); EfunctionAdd(modinfo->handle, EFUNC_DO_JOIN, _do_join); EfunctionAdd(modinfo->handle, EFUNC_CAN_JOIN, _can_join); + EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_SAVE_CURRENT, _userhost_save_current); + EfunctionAddVoid(modinfo->handle, EFUNC_USERHOST_CHANGED, _userhost_changed); + return MOD_SUCCESS; } @@ -526,3 +532,195 @@ CMD_FUNC(_do_join) RET(0) #undef RET } + +/* Additional channel-related functions. I've put it here instead + * of the core so it could be upgraded on the fly should it be necessary. + */ + +char *get_chmodes_for_user(aClient *sptr, int flags) +{ + static char modebuf[512]; /* returned */ + char flagbuf[8]; /* For holding "vhoaq" */ + char *p = flagbuf; + char parabuf[512]; + int n, i; + + if (!flags) + return ""; + + if (flags & MODE_CHANOWNER) + *p++ = 'q'; + if (flags & MODE_CHANPROT) + *p++ = 'a'; + if (flags & MODE_CHANOP) + *p++ = 'o'; + if (flags & MODE_VOICE) + *p++ = 'v'; + if (flags & MODE_HALFOP) + *p++ = 'h'; + *p = '\0'; + + parabuf[0] = '\0'; + + n = strlen(flagbuf); + if (n) + { + for (i=0; i < n; i++) + { + strlcat(parabuf, sptr->name, sizeof(parabuf)); + if (i < n - 1) + strlcat(parabuf, " ", sizeof(parabuf)); + } + /* And we have our mode line! */ + snprintf(modebuf, sizeof(modebuf), "+%s %s", flagbuf, parabuf); + return modebuf; + } + + return ""; +} + +static char remember_nick[NICKLEN+1]; +static char remember_user[USERLEN+1]; +static char remember_host[HOSTLEN+1]; + +/** Save current nick/user/host. Used later by userhost_changed(). */ +void _userhost_save_current(aClient *sptr) +{ + strlcpy(remember_nick, sptr->name, sizeof(remember_nick)); + strlcpy(remember_user, sptr->user->username, sizeof(remember_user)); + strlcpy(remember_host, GetHost(sptr), sizeof(remember_host)); +} + +/** User/Host changed for user. + * Note that userhost_save_current() needs to be called before this + * to save the old username/hostname. + * This userhost_changed() function deals with notifying local clients + * about the user/host change by sending PART+JOIN+MODE if + * set::allow-userhost-change force-rejoin is in use, + * and it wills end "CAP chghost" to such capable clients. + * It will also deal with bumping fakelag for the user since a user/host + * change is costly, doesn't matter if it was self-induced or not. + * + * Please call this function for any user/host change by doing: + * userhost_save_current(acptr); + * << change username or hostname here >> + * userhost_changed(acptr); + */ +void _userhost_changed(aClient *sptr) +{ + Membership *channels; + aChannel *chptr; + Member *lp; + aClient *acptr; + int i = 0; + int impact = 0; + char buf[512]; + + if (strcmp(remember_nick, sptr->name)) + { + ircd_log(LOG_ERROR, "[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s", + sptr->name); + ircd_log(LOG_ERROR, "Please report above bug on https://bugs.unrealircd.org/"); + sendto_realops("[BUG] userhost_changed() was called but without calling userhost_save_current() first! Affected user: %s", + sptr->name); + sendto_realops("Please report above bug on https://bugs.unrealircd.org/"); + return; /* We cannot safely process this request anymore */ + } + + /* It's perfectly acceptable to call us even if the userhost didn't change. */ + if (!strcmp(remember_user, sptr->user->username) && !strcmp(remember_host, GetHost(sptr))) + return; /* Nothing to do */ + + /* Most of the work is only necessary for set::allow-userhost-change force-rejoin */ + if (UHOST_ALLOWED == UHALLOW_REJOIN) + { + /* Walk through all channels of this user.. */ + for (channels = sptr->user->channel; channels; channels = channels->next) + { + aChannel *chptr = channels->chptr; + int flags = channels->flags; + char *modes; + char partbuf[512]; /* PART */ + char joinbuf[512]; /* JOIN */ + char modebuf[512]; /* MODE (if any) */ + int chanops_only = invisible_user_in_channel(sptr, chptr); + + modebuf[0] = '\0'; + + /* If the user is banned, don't send any rejoins, it would only be annoying */ + if (is_banned(sptr, chptr, BANCHK_JOIN)) + continue; + + /* Prepare buffers for PART, JOIN, MODE */ + ircsnprintf(partbuf, sizeof(partbuf), ":%s!%s@%s PART %s :%s", + remember_nick, remember_user, remember_host, + chptr->chname, + "Changing host"); + + ircsnprintf(joinbuf, sizeof(joinbuf), ":%s!%s@%s JOIN %s", + sptr->name, sptr->user->username, GetHost(sptr), chptr->chname); + + modes = get_chmodes_for_user(sptr, flags); + if (modes) + ircsnprintf(modebuf, sizeof(modebuf), ":%s MODE %s %s", me.name, chptr->chname, modes); + + for (lp = chptr->members; lp; lp = lp->next) + { + acptr = lp->cptr; + + if (acptr == sptr) + continue; /* skip self */ + + if (!MyConnect(acptr)) + continue; /* only locally connected clients */ + + if (chanops_only && !(lp->flags & (CHFL_CHANOP|CHFL_CHANOWNER|CHFL_CHANPROT))) + continue; /* skip non-ops if requested to (used for mode +D) */ + + if (acptr->local->proto & PROTO_CAP_CHGHOST) + continue; /* we notify 'CAP chghost' users in a different way, so don't send it here. */ + + impact++; + + sendbufto_one(acptr, partbuf, 0); + sendbufto_one(acptr, joinbuf, 0); + if (*modebuf) + sendbufto_one(acptr, modebuf, 0); + } + } + } + + /* Now deal with "CAP chghost" clients. + * This only needs to be sent one per "common channel". + * This would normally call sendto_common_channels_local_butone() but the user already + * has the new user/host.. so we do it here.. + */ + ircsnprintf(buf, sizeof(buf), ":%s!%s@%s CHGHOST %s %s", + remember_nick, remember_user, remember_host, + sptr->user->username, + GetHost(sptr)); + current_serial++; + for (channels = sptr->user->channel; channels; channels = channels->next) + { + for (lp = channels->chptr->members; lp; lp = lp->next) + { + acptr = lp->cptr; + if (MyClient(acptr) && (acptr->local->proto & PROTO_CAP_CHGHOST) && + (acptr->local->serial != current_serial) && (sptr != acptr)) + { + sendbufto_one(acptr, buf, 0); + acptr->local->serial = current_serial; + } + } + } + + /* A userhost change always generates the following network traffic: + * server to server traffic, CAP "chghost" notifications, and + * possibly PART+JOIN+MODE if force-rejoin had work to do. + * We give the user a penalty so they don't flood... + */ + if (impact) + sptr->local->since += 7; /* Resulted in rejoins and such. */ + else + sptr->local->since += 4; /* No rejoins */ +} diff --git a/src/modules/m_mode.c b/src/modules/m_mode.c index d8a748a05..e259e29ae 100644 --- a/src/modules/m_mode.c +++ b/src/modules/m_mode.c @@ -1599,6 +1599,8 @@ CMD_FUNC(_m_umode) return 0; } + userhost_save_current(sptr); /* save host, in case we do any +x/-x or similar */ + /* find flags already set for user */ for (i = 0; i <= Usermode_highest; i++) if ((sptr->umodes & Usermode_Table[i].mode)) @@ -1769,28 +1771,12 @@ CMD_FUNC(_m_umode) sendto_server(cptr, PROTO_VHP, 0, ":%s SETHOST :%s", sptr->name, sptr->user->virthost); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - { - /* Damn, this is ugly: we have to restore umodes to old state, - * do the PART and then set umodes to the new modes again. - */ - long newmodes = sptr->umodes; - sptr->umodes = oldumodes; - rejoin_leave(sptr); - sptr->umodes = newmodes; - } - + /* Set the vhost */ safefree(sptr->user->virthost); sptr->user->virthost = strdup(sptr->user->cloakedhost); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - { - sptr->umodes |= UMODE_HIDE; - rejoin_joinandmode(sptr); - if (MyClient(sptr)) - sptr->local->since += 7; /* Add fake lag */ - } - + /* Notify */ + userhost_changed(sptr); if (MyClient(sptr)) sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->virthost); } @@ -1798,22 +1784,15 @@ CMD_FUNC(_m_umode) /* -x */ if (!IsHidden(sptr) && (oldumodes & UMODE_HIDE)) { - if (UHOST_ALLOWED == UHALLOW_REJOIN) - { - /* LOL, this is ugly ;) */ - sptr->umodes |= UMODE_HIDE; - rejoin_leave(sptr); - sptr->umodes &= ~UMODE_HIDE; - rejoin_joinandmode(sptr); - if (MyClient(sptr)) - sptr->local->since += 7; /* Add fake lag */ - } /* (Re)create the cloaked virthost, because it will be used * for ban-checking... free+recreate here because it could have * been a vhost for example. -- Syzop */ safefree(sptr->user->virthost); sptr->user->virthost = strdup(sptr->user->cloakedhost); + + /* Notify */ + userhost_changed(sptr); if (MyClient(sptr)) sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->realhost); } diff --git a/src/modules/m_sethost.c b/src/modules/m_sethost.c index c787c4e0c..e6705756d 100644 --- a/src/modules/m_sethost.c +++ b/src/modules/m_sethost.c @@ -128,6 +128,8 @@ CMD_FUNC(m_sethost) } { + userhost_save_current(sptr); + switch (UHOST_ALLOWED) { case UHALLOW_NEVER: @@ -147,7 +149,6 @@ CMD_FUNC(m_sethost) } break; case UHALLOW_REJOIN: - rejoin_leave(sptr); /* join sent later when the host has been changed */ break; } @@ -165,8 +166,7 @@ CMD_FUNC(m_sethost) /* spread it out */ sendto_server(cptr, 0, 0, ":%s SETHOST %s", sptr->name, parv[1]); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(sptr); + userhost_changed(sptr); } if (MyConnect(sptr)) diff --git a/src/modules/m_setident.c b/src/modules/m_setident.c index 85649362c..2ce720c7a 100644 --- a/src/modules/m_setident.c +++ b/src/modules/m_setident.c @@ -155,6 +155,8 @@ CMD_FUNC(m_setident) } { + userhost_save_current(sptr); + switch (UHOST_ALLOWED) { case UHALLOW_ALWAYS: @@ -174,7 +176,7 @@ CMD_FUNC(m_setident) } break; case UHALLOW_REJOIN: - rejoin_leave(sptr); + /* dealt with later */ break; } @@ -183,8 +185,7 @@ CMD_FUNC(m_setident) /* spread it out */ sendto_server(cptr, 0, 0, ":%s SETIDENT %s", sptr->name, parv[1]); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(sptr); + userhost_changed(sptr); } if (MyConnect(sptr)) diff --git a/src/modules/m_svsmode.c b/src/modules/m_svsmode.c index 65991ebde..8fade638a 100644 --- a/src/modules/m_svsmode.c +++ b/src/modules/m_svsmode.c @@ -387,6 +387,8 @@ int do_svsmode(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_c if (!(acptr = find_person(parv[1], NULL))) return 0; + userhost_save_current(acptr); + /* initialize setflag to be the user's pre-SVSMODE flags */ for (i = 0; i <= Usermode_highest; i++) if (Usermode_Table[i].flag && (acptr->umodes & Usermode_Table[i].mode)) @@ -550,6 +552,8 @@ int do_svsmode(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_c sendto_one(acptr, ":%s MODE %s :%s", sptr->name, acptr->name, buf); } + userhost_changed(acptr); /* we can safely call this, even if nothing changed */ + VERIFY_OPERCOUNT(acptr, "svsmodeX"); return 0; } diff --git a/src/modules/m_vhost.c b/src/modules/m_vhost.c index c6c1988a4..8d95a9aee 100644 --- a/src/modules/m_vhost.c +++ b/src/modules/m_vhost.c @@ -109,6 +109,8 @@ CMD_FUNC(m_vhost) { char olduser[USERLEN+1]; + userhost_save_current(sptr); + switch (UHOST_ALLOWED) { case UHALLOW_NEVER: @@ -128,7 +130,6 @@ CMD_FUNC(m_vhost) } break; case UHALLOW_REJOIN: - rejoin_leave(sptr); /* join sent later when the host has been changed */ break; } @@ -162,8 +163,7 @@ CMD_FUNC(m_vhost) vhost->virtuser ? olduser : sptr->user->username, sptr->user->realhost, vhost->virtuser ? vhost->virtuser : "", vhost->virtuser ? "@" : "", vhost->virthost); - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(sptr); + userhost_changed(sptr); return 0; } if (i == -1) diff --git a/src/s_user.c b/src/s_user.c index c95f2c314..3f2059877 100644 --- a/src/s_user.c +++ b/src/s_user.c @@ -65,8 +65,8 @@ void iNAH_host(aClient *sptr, char *host) if (!sptr->user) return; - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_leave(sptr); + userhost_save_current(sptr); + if (sptr->user->virthost) { MyFree(sptr->user->virthost); @@ -77,8 +77,7 @@ void iNAH_host(aClient *sptr, char *host) sendto_server(&me, 0, 0, ":%s SETHOST :%s", sptr->name, sptr->user->virthost); sptr->umodes |= UMODE_SETHOST; - if (UHOST_ALLOWED == UHALLOW_REJOIN) - rejoin_joinandmode(sptr); + userhost_changed(sptr); sendto_one(sptr, err_str(RPL_HOSTHIDDEN), me.name, sptr->name, sptr->user->virthost); }