X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/2d10c559903b1eed9947f734a7e08b4b2551fd6f..07db71cda082d1d7db7bec491bb60aee5f1e2879:/src/chmode.c diff --git a/src/chmode.c b/src/chmode.c index dbf47f6..4c86b3d 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -43,6 +43,7 @@ #include "chmode.h" #include "irc_dictionary.h" + /* bitmasks for error returns, so we send once per call */ #define SM_ERR_NOTS 0x00000001 /* No TS on channel */ #define SM_ERR_NOOPS 0x00000002 /* No chan ops */ @@ -56,6 +57,7 @@ #define SM_ERR_NOPRIVS 0x00000400 #define SM_ERR_RPL_Q 0x00000800 #define SM_ERR_RPL_F 0x00001000 +#define SM_ERR_MLOCK 0x00002000 #define MAXMODES_SIMPLE 46 /* a-zA-Z except bqeIov */ @@ -68,11 +70,10 @@ static int no_override_deop; char cflagsbuf[256]; char cflagsmyinfo[256]; +char cflagsparaminfo[256]; int chmode_flags[256]; -struct module_modes ModuleModes; - /* OPTIMIZE ME! -- dwr */ void construct_cflags_strings(void) @@ -103,27 +104,35 @@ construct_cflags_strings(void) chmode_flags[i] = 0; } - if(chmode_flags[i] == ModuleModes.MODE_DISFORWARD) + switch (chmode_flags[i]) { - if (ModuleModes.MODE_FORWARD) + case MODE_EXLIMIT: + case MODE_DISFORWARD: + if(ConfigChannel.use_forward) { - *ptr++ = (char) i; + *ptr++ = (char) i; } - } - else if(chmode_flags[i] == ModuleModes.MODE_REGONLY) - { - if (rb_dlink_list_length(&service_list)) + + break; + case MODE_REGONLY: + if(rb_dlink_list_length(&service_list)) { - *ptr++ = (char) i; + *ptr++ = (char) i; + } + + break; + default: + if(chmode_flags[i] != 0 && !(chmode_table[i].set_func == chm_orphaned)) + { + *ptr++ = (char) i; } - } - else if(chmode_flags[i] != ModuleModes.MODE_EXLIMIT && chmode_flags[i] != 0) - { - *ptr++ = (char) i; } /* Should we leave orphaned check here? -- dwr */ - if(!(chmode_table[i].set_func == chm_nosuch) && !(chmode_table[i].set_func == chm_orphaned)) + if( !(chmode_table[i].set_func == chm_nosuch) && + !(chmode_table[i].set_func == chm_orphaned) && + !(chmode_table[i].set_func == chm_admin && !ConfigChannel.use_admin) && + !(chmode_table[i].set_func == chm_halfop && !ConfigChannel.use_halfop)) { *ptr2++ = (char) i; } @@ -133,6 +142,21 @@ construct_cflags_strings(void) *ptr2++ = '\0'; } +void +construct_cflag_param_string(void) +{ + + *cflagsparaminfo = '\0'; + rb_snprintf(cflagsparaminfo, sizeof cflagsparaminfo, "%sb%s%s%s%sklov%s%s", + ConfigChannel.use_admin ? "a" : "", + ConfigChannel.use_except ? "e" : "", + ConfigChannel.use_forward ? "f" : "", + ConfigChannel.use_halfop ? "h" : "", + strcasecmp(ConfigChannel.disabledmodes, "j") ? "" : "j", + strcasecmp(ConfigChannel.disabledmodes, "q") ? "" : "q", + ConfigChannel.use_invex ? "I" : ""); +} + /* * find_umode_slot * @@ -216,7 +240,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, */ if(MyClient(source_p)) { - if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (chptr->mode.mode & ModuleModes.MODE_EXLIMIT ? ConfigChannel.max_bans_large : ConfigChannel.max_bans)) + if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (chptr->mode.mode & MODE_EXLIMIT ? ConfigChannel.max_bans_large : ConfigChannel.max_bans)) { sendto_one(source_p, form_str(ERR_BANLISTFULL), me.name, source_p->name, chptr->chname, realban); @@ -253,7 +277,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, rb_dlinkAdd(actualBan, &actualBan->node, list); /* invalidate the can_send() cache */ - if(mode_type == CHFL_BAN || mode_type == ModuleModes.CHFL_QUIET || mode_type == CHFL_EXCEPTION) + if(mode_type == CHFL_BAN || mode_type == CHFL_QUIET || mode_type == CHFL_EXCEPTION) chptr->bants++; return 1; @@ -284,7 +308,7 @@ del_id(struct Channel *chptr, const char *banid, rb_dlink_list * list, long mode free_ban(banptr); /* invalidate the can_send() cache */ - if(mode_type == CHFL_BAN || mode_type == ModuleModes.CHFL_QUIET || mode_type == CHFL_EXCEPTION) + if(mode_type == CHFL_BAN || mode_type == CHFL_QUIET || mode_type == CHFL_EXCEPTION) chptr->bants++; return 1; @@ -530,10 +554,10 @@ chm_simple(struct Client *source_p, struct Channel *chptr, return; /* setting + */ - if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type) && !(chptr->mode_lock.off_mode & mode_type)) + if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { /* if +f is disabled, ignore an attempt to set +QF locally */ - if(!ModuleModes.MODE_FORWARD && MyClient(source_p) && + if(!ConfigChannel.use_forward && MyClient(source_p) && (c == 'Q' || c == 'F')) return; @@ -581,7 +605,10 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, const char **parv, int *errors, int dir, char c, long mode_type) { if(MyClient(source_p)) + { + sendto_one_numeric(source_p, 469, "Mode %c is disabled.", c); return; + } if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { @@ -595,7 +622,7 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ALL_MEMBERS; mode_changes[mode_count++].arg = NULL; } - else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type) && !(chptr->mode_lock.mode & mode_type)) + else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { chptr->mode.mode &= ~mode_type; @@ -748,17 +775,18 @@ chm_ban(struct Client *source_p, struct Channel *chptr, int mems; int override = 0; - if(mode_type == CHFL_BAN) + switch (mode_type) { + case CHFL_BAN: list = &chptr->banlist; errorval = SM_ERR_RPL_B; rpl_list = RPL_BANLIST; rpl_endlist = RPL_ENDOFBANLIST; mems = ALL_MEMBERS; caps = 0; - } - else if(mode_type == CHFL_EXCEPTION) - { + break; + + case CHFL_EXCEPTION: /* if +e is disabled, allow all but +e locally */ if(!ConfigChannel.use_except && MyClient(source_p) && ((dir == MODE_ADD) && (parc > *parn))) @@ -774,9 +802,9 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mems = ONLY_CHANOPS; else mems = ONLY_SERVERS; - } - else if(mode_type == CHFL_INVEX) - { + break; + + case CHFL_INVEX: /* if +I is disabled, allow all but +I locally */ if(!ConfigChannel.use_invex && MyClient(source_p) && (dir == MODE_ADD) && (parc > *parn)) @@ -792,20 +820,21 @@ chm_ban(struct Client *source_p, struct Channel *chptr, mems = ONLY_CHANOPS; else mems = ONLY_SERVERS; - } - else if(mode_type == ModuleModes.CHFL_QUIET) - { + break; + + case CHFL_QUIET: list = &chptr->quietlist; errorval = SM_ERR_RPL_Q; rpl_list = RPL_QUIETLIST; rpl_endlist = RPL_ENDOFQUIETLIST; mems = ALL_MEMBERS; caps = 0; - } - else - { + break; + + default: sendto_realops_snomask(SNO_GENERAL, L_ALL, "chm_ban() called with unknown type!"); return; + break; } if(dir == 0 || parc <= *parn) @@ -816,7 +845,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, /* non-ops cant see +eI lists.. */ if(alevel != CHFL_CHANOP && alevel != CHFL_ADMIN && alevel != CHFL_HALFOP && mode_type != CHFL_BAN && - mode_type != ModuleModes.CHFL_QUIET) + mode_type != CHFL_QUIET) { if(IsOverride(source_p)) { @@ -1503,7 +1532,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, int override = 0; /* if +f is disabled, ignore local attempts to set it */ - if(!ModuleModes.MODE_FORWARD && MyClient(source_p) && + if(!ConfigChannel.use_forward && MyClient(source_p) && (dir == MODE_ADD) && (parc > *parn)) return; @@ -1573,7 +1602,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, form_str(ERR_NOSUCHCHANNEL), forward); return; } - if(MyClient(source_p) && !(targptr->mode.mode & ModuleModes.MODE_FREETARGET)) + if(MyClient(source_p) && !(targptr->mode.mode & MODE_FREETARGET)) { if((msptr = find_channel_membership(targptr, source_p)) == NULL || !is_any_op(msptr)) @@ -1595,7 +1624,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].dir = MODE_ADD; mode_changes[mode_count].caps = 0; mode_changes[mode_count].nocaps = 0; - mode_changes[mode_count].mems = ModuleModes.MODE_FORWARD ? ALL_MEMBERS : ONLY_SERVERS; + mode_changes[mode_count].mems = ConfigChannel.use_forward ? ALL_MEMBERS : ONLY_SERVERS; mode_changes[mode_count].id = NULL; mode_changes[mode_count].override = override; mode_changes[mode_count++].arg = forward; @@ -1752,9 +1781,6 @@ chm_regonly(struct Client *source_p, struct Channel *chptr, } /* *INDENT-OFF* */ -/* Only RFC and ircd-ratbox modes are held in this table - * All other modes are added via loading modules in shadowircd/modes - * Such is documented in the comments for each mode, ex: C - NOCTCP. */ struct ChannelMode chmode_table[256] = { {chm_nosuch, 0 }, /* 0x00 */ @@ -1825,24 +1851,24 @@ struct ChannelMode chmode_table[256] = {chm_nosuch, 0 }, /* @ */ {chm_nosuch, 0 }, /* A */ {chm_nosuch, 0 }, /* B */ - {chm_nosuch, 0 }, /* C - MODE_NOCTCP */ - {chm_nosuch, 0 }, /* D - MODE_NOACTION */ - {chm_nosuch, 0 }, /* E - MODE_NOKICK */ - {chm_nosuch, 0 }, /* F - MODE_FREETARGET */ - {chm_nosuch, 0 }, /* G - MODE_NOCAPS */ + {chm_simple, MODE_NOCTCP }, /* C */ + {chm_simple, MODE_NOACTION }, /* D */ + {chm_simple, MODE_NOKICK }, /* E */ + {chm_simple, MODE_FREETARGET }, /* F */ + {chm_simple, MODE_NOCAPS }, /* G */ {chm_nosuch, 0 }, /* H */ {chm_ban, CHFL_INVEX }, /* I */ - {chm_nosuch, 0 }, /* J - MODE_NOREJOIN */ - {chm_nosuch, 0 }, /* K - MODE_NOREPEAT */ - {chm_nosuch, 0 }, /* L - MODE_EXLIMIT */ - {chm_nosuch, 0 }, /* M - MODE_NOOPERKICK */ - {chm_nosuch, 0 }, /* N - MODE_NONICK */ + {chm_simple, MODE_NOREJOIN }, /* J */ + {chm_simple, MODE_NOREPEAT }, /* K */ + {chm_staff, MODE_EXLIMIT }, /* L */ + {chm_hidden, MODE_NOOPERKICK }, /* M */ + {chm_simple, MODE_NONICK }, /* N */ {chm_nosuch, 0 }, /* O */ - {chm_nosuch, 0 }, /* P - MODE_PERMANENT */ - {chm_nosuch, 0 }, /* Q - MODE_DISFORWARD */ + {chm_staff, MODE_PERMANENT }, /* P */ + {chm_simple, MODE_DISFORWARD }, /* Q */ {chm_nosuch, 0 }, /* R */ {chm_nosuch, 0 }, /* S */ - {chm_nosuch, 0 }, /* T - MODE_NONOTICE */ + {chm_simple, MODE_NONOTICE }, /* T */ {chm_nosuch, 0 }, /* U */ {chm_nosuch, 0 }, /* V */ {chm_nosuch, 0 }, /* W */ @@ -1857,22 +1883,22 @@ struct ChannelMode chmode_table[256] = {chm_nosuch, 0 }, {chm_admin, 0 }, /* a */ {chm_ban, CHFL_BAN }, /* b */ - {chm_nosuch, 0 }, /* c - MODE_NOCOLOR */ + {chm_simple, MODE_NOCOLOR }, /* c */ {chm_nosuch, 0 }, /* d */ {chm_ban, CHFL_EXCEPTION }, /* e */ - {chm_nosuch, 0 }, /* f - MODE_FORWARD */ - {chm_nosuch, 0 }, /* g - MODE_FREEINVITE */ + {chm_forward, 0 }, /* f */ + {chm_simple, MODE_FREEINVITE }, /* g */ {chm_halfop, 0 }, /* h */ {chm_simple, MODE_INVITEONLY }, /* i */ - {chm_nosuch, 0 }, /* j - MODE_THROTTLE */ + {chm_throttle, 0 }, /* j */ {chm_key, 0 }, /* k */ {chm_limit, 0 }, /* l */ {chm_simple, MODE_MODERATED }, /* m */ {chm_simple, MODE_NOPRIVMSGS }, /* n */ {chm_op, 0 }, /* o */ {chm_simple, MODE_PRIVATE }, /* p */ - {chm_nosuch, 0 }, /* q - CHFL_QUIET */ - {chm_nosuch, 0 }, /* r - MODE_REGONLY */ + {chm_ban, CHFL_QUIET }, /* q */ + {chm_regonly, MODE_REGONLY }, /* r */ {chm_simple, MODE_SECRET }, /* s */ {chm_simple, MODE_TOPICLIMIT }, /* t */ {chm_nosuch, 0 }, /* u */ @@ -1880,7 +1906,7 @@ struct ChannelMode chmode_table[256] = {chm_nosuch, 0 }, /* w */ {chm_nosuch, 0 }, /* x */ {chm_nosuch, 0 }, /* y */ - {chm_nosuch, 0 }, /* z - MODE_OPMODERATE */ + {chm_simple, MODE_OPMODERATE }, /* z */ {chm_nosuch, 0 }, /* 0x7b */ {chm_nosuch, 0 }, /* 0x7c */ @@ -2084,6 +2110,19 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, dir = MODE_QUERY; break; default: + /* If this mode char is locked, don't allow local users to change it. */ + if (MyClient(source_p) && chptr->mode_lock && strchr(chptr->mode_lock, c)) + { + if (!(errors & SM_ERR_MLOCK)) + sendto_one_numeric(source_p, + ERR_MLOCKRESTRICTED, + form_str(ERR_MLOCKRESTRICTED), + chptr->chname, + c, + chptr->mode_lock); + errors |= SM_ERR_MLOCK; + continue; + } chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel, parc, &parn, parv, &errors, dir, c, @@ -2240,41 +2279,15 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, */ void set_channel_mlock(struct Client *client_p, struct Client *source_p, - struct Channel *chptr, int parc, const char *parv[]) + struct Channel *chptr, const char *newmlock, int propagate) { - int dir = MODE_ADD; - const char *ml = parv[0]; - char c; + rb_free(chptr->mode_lock); + chptr->mode_lock = newmlock ? rb_strdup(newmlock) : NULL; - memset(&chptr->mode_lock, '\0', sizeof(struct Mode)); - - for(; (c = *ml) != 0; ml++) + if (propagate) { - switch (c) - { - case '+': - dir = MODE_ADD; - break; - case '-': - dir = MODE_DEL; - break; - default: - if (chmode_table[(unsigned char) c].set_func == chm_simple) - switch(dir) - { - case MODE_ADD: - chptr->mode_lock.mode |= chmode_table[(unsigned char) c].mode_type; - chptr->mode_lock.off_mode &= ~chmode_table[(unsigned char) c].mode_type; - break; - case MODE_DEL: - chptr->mode_lock.off_mode |= chmode_table[(unsigned char) c].mode_type; - chptr->mode_lock.mode &= ~chmode_table[(unsigned char) c].mode_type; - break; - } - break; - } + sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s :%s", + source_p->id, (long) chptr->channelts, chptr->chname, + chptr->mode_lock ? chptr->mode_lock : ""); } - - sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s %s", - source_p->id, (long) chptr->channelts, chptr->chname, channel_mlock(chptr, &me)); }