From: Perry Lorier Date: Sat, 14 Jul 2007 02:40:01 +0000 (+0000) Subject: Author: Perry Lorier X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=commitdiff_plain;h=30cd7d8a8c1b9efdbf25977174e733754877d496 Author: Perry Lorier Log message: Try and fix issues with large numbers of invisible (or non invisible) users. Do this by always calling set_user_mode() for all mode setting/unsetting. This requires an extra flag so we can limit which userflags can be set in some situations. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/branches/u2_10_12_branch@1818 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 37f80a7..6869bc1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2007-07-12 Perry Lorier + Reconsider how we manage modes before registration, to avoid stats + getting out of sync. + + * ircd/s_user.c (set_user_mode): Add new parameter to set_user_mode to + ignore some modes. + (register_user): Use set_user_mode to parse default usermode for + users. + + * ircd/m_user.c: Add extra parameter to set_user_mode call + + * ircd/s_auth.c: Add extra parameter to set_user_mode call + + * ircd/m_mode.c: Add extra parameter to set_user_mode call + + * ircd/s_misc.c: Verify stats are consistant. + + * include/s_user.h: Change prototype, add flag definitions. + + * ircd/m_lusers.c (m_users): Assert that we're generating sane stats, + include "unknowns" in the total user connections to avoid negative + wrap arounds. + 2007-07-12 Perry Lorier * ircd/m_user.c (m_luser): Fix broken RFC 2812 on connect user mode diff --git a/include/s_user.h b/include/s_user.h index 205776c..63ed134 100644 --- a/include/s_user.h +++ b/include/s_user.h @@ -50,6 +50,10 @@ struct Flags; #define MATCH_SERVER 1 /**< flag for relay_masked_message (etc) to indicate the mask matches a server name */ #define MATCH_HOST 2 /**< flag for relay_masked_message (etc) to indicate the mask matches host name */ +/* used for parsing user modes */ +#define ALLOWMODES_ANY 0 /**< Allow any user mode */ +#define ALLOWMODES_DEFAULT 1 /**< Only allow the subset of modes that are legit defaults */ + /** Formatter function for send_user_info(). * @param who Client being displayed. * @param sptr Client requesting information. @@ -77,7 +81,7 @@ extern void send_user_info(struct Client* to, char* names, int rpl, extern int hide_hostmask(struct Client *cptr, unsigned int flags); extern int set_user_mode(struct Client *cptr, struct Client *sptr, - int parc, char *parv[]); + int parc, char *parv[], int allow_modes); extern int is_silenced(struct Client *sptr, struct Client *acptr); extern int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok, struct Client *one, diff --git a/ircd/m_lusers.c b/ircd/m_lusers.c index b1b7afd..573fa52 100644 --- a/ircd/m_lusers.c +++ b/ircd/m_lusers.c @@ -112,7 +112,10 @@ int m_lusers(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) "%s :%C", 2, parc, parv) != HUNTED_ISME) return 0; - send_reply(sptr, RPL_LUSERCLIENT, UserStats.clients - UserStats.inv_clients, + assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns); + + send_reply(sptr, RPL_LUSERCLIENT, + UserStats.clients - UserStats.inv_clients + UserStats.unknowns, UserStats.inv_clients, UserStats.servers); if (longoutput && UserStats.opers) send_reply(sptr, RPL_LUSEROP, UserStats.opers); diff --git a/ircd/m_mode.c b/ircd/m_mode.c index 8b91fd5..e85398d 100644 --- a/ircd/m_mode.c +++ b/ircd/m_mode.c @@ -127,7 +127,7 @@ m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) send_reply(sptr, ERR_USERSDONTMATCH); return 0; } - return set_user_mode(cptr, sptr, parc, parv); + return set_user_mode(cptr, sptr, parc, parv, ALLOWMODES_ANY); } ClrFlag(sptr, FLAG_TS8); @@ -198,7 +198,7 @@ ms_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) cli_name(cptr), cli_name(sptr)); return 0; } - return set_user_mode(cptr, sptr, parc, parv); + return set_user_mode(cptr, sptr, parc, parv, ALLOWMODES_ANY); } ClrFlag(sptr, FLAG_TS8); diff --git a/ircd/m_user.c b/ircd/m_user.c index 6316463..2ef1320 100644 --- a/ircd/m_user.c +++ b/ircd/m_user.c @@ -142,13 +142,15 @@ int m_user(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if ((mode_request = strtoul(parv[2], &term, 10)) != 0 && term != NULL && *term == '\0') { + char *invisible[4] = { NULL, NULL, "+i", NULL }; + char *wallops[4] = { NULL, NULL, "+w" , NULL }; /* These bitmask values are codified in RFC 2812, showing * ... well, something that is probably best not said. */ if (mode_request & 8) - SetInvisible(cptr); + set_user_mode(cptr, sptr, 3, invisible, ALLOWMODES_ANY); if (mode_request & 4) - SetWallops(cptr); + set_user_mode(cptr, sptr, 3, wallops, ALLOWMODES_ANY); } else if (parv[2][0] == '+') { @@ -157,7 +159,7 @@ int m_user(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) user_modes[1] = NULL; user_modes[2] = parv[2]; user_modes[3] = NULL; - set_user_mode(cptr, sptr, 3, user_modes); + set_user_mode(cptr, sptr, 3, user_modes, ALLOWMODES_ANY); } info = (EmptyString(parv[4])) ? "No Info" : parv[4]; diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 2aeef4b..2264202 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -1917,7 +1917,7 @@ static int iauth_cmd_usermode(struct IAuth *iauth, struct Client *cli, { if (params[0][0] == '+') { - set_user_mode(cli, cli, parc + 2, params - 2); + set_user_mode(cli, cli, parc + 2, params - 2, ALLOWMODES_ANY); } return 0; } diff --git a/ircd/s_misc.c b/ircd/s_misc.c index 8eab44e..b5324fa 100644 --- a/ircd/s_misc.c +++ b/ircd/s_misc.c @@ -223,10 +223,14 @@ static void exit_one_client(struct Client* bcptr, const char* comment) if (MyUser(bcptr)) set_snomask(bcptr, ~0, SNO_DEL); - if (IsInvisible(bcptr)) + if (IsInvisible(bcptr)) { + assert(UserStats.inv_clients > 0); --UserStats.inv_clients; - if (IsOper(bcptr)) + } + if (IsOper(bcptr)) { + assert(UserStats.opers > 0); --UserStats.opers; + } if (MyConnect(bcptr)) Count_clientdisconnects(bcptr, UserStats); else diff --git a/ircd/s_user.c b/ircd/s_user.c index fb08e0b..a5a75a1 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -118,6 +118,7 @@ void free_user(struct User* user) assert(0 == user->channel); MyFree(user); + assert(userCount>0); --userCount; } } @@ -452,10 +453,6 @@ int register_user(struct Client *cptr, struct Client *sptr) SetUser(sptr); } - if (IsInvisible(sptr)) - ++UserStats.inv_clients; - if (IsOper(sptr)) - ++UserStats.opers; /* If they get both +x and an account during registration, hide * their hostmask here. Calling hide_hostmask() from IAuth's * account assignment causes a numeric reply during registration. @@ -984,9 +981,12 @@ hide_hostmask(struct Client *cptr, unsigned int flag) * @param[in] sptr Client who sent the mode change message. * @param[in] parc Number of parameters in \a parv. * @param[in] parv Parameters to MODE. + * @param[in] allow_modes ALLOWMODES_ANY for any mode, ALLOWMODES_DEFAULT for + * only permitting legitimate default user modes. * @return Zero. */ -int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) +int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, + char *parv[], int allow_modes) { char** p; char* m; @@ -1186,18 +1186,23 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv if (FlagHas(&setflags, FLAG_OPER) && !IsOper(sptr)) { /* user no longer oper */ + assert(UserStats.opers > 0); --UserStats.opers; client_set_privs(sptr, NULL); /* will clear propagate privilege */ } - if (FlagHas(&setflags, FLAG_INVISIBLE) && !IsInvisible(sptr)) + if (FlagHas(&setflags, FLAG_INVISIBLE) && !IsInvisible(sptr)) { + assert(UserStats.inv_clients > 0); --UserStats.inv_clients; + } if (!FlagHas(&setflags, FLAG_INVISIBLE) && IsInvisible(sptr)) ++UserStats.inv_clients; - if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding) + if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding && allow_modes != ALLOWMODES_DEFAULT) hide_hostmask(sptr, FLAG_HIDDENHOST); if (IsRegistered(sptr)) send_umode_out(cptr, sptr, &setflags, prop); + assert(UserStats.opers <= UserStats.clients + UserStats.unknowns); + assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns); return 0; }