EBMASK capab, to burst BMASK metadata (#354)
This commit is contained in:
parent
a5192806a9
commit
fdd8cad93f
6 changed files with 125 additions and 60 deletions
|
@ -319,6 +319,21 @@ Sets a D:line (IP ban checked directly after accepting connection).
|
|||
|
||||
The mask must be an IP address or CIDR mask.
|
||||
|
||||
EBMASK
|
||||
source: server
|
||||
propagation: broadcast
|
||||
parameters: channelTS, channel, type, space separated "masks ts hostmask" chunks
|
||||
|
||||
If the channelTS in the message is greater (newer) than the current TS of
|
||||
the channel, drop the message and do not propagate it.
|
||||
|
||||
Type is the mode letter of a ban-like mode. In efnet TS6 this is 'b', 'e' or
|
||||
'I'. In charybdis TS6 additionally 'q' is possible.
|
||||
|
||||
Add all the masks and their set at/by to the given list of the channel.
|
||||
|
||||
All ban-like modes must be bursted using this command, not using MODE or TMODE.
|
||||
|
||||
ECHO
|
||||
source: user
|
||||
parameters: "P"/"N", target, text
|
||||
|
|
|
@ -302,7 +302,7 @@ extern void set_channel_mlock(struct Client *client_p, struct Client *source_p,
|
|||
|
||||
extern struct ChannelMode chmode_table[256];
|
||||
|
||||
extern bool add_id(struct Client *source_p, struct Channel *chptr, const char *banid,
|
||||
extern struct Ban * add_id(struct Client *source_p, struct Channel *chptr, const char *banid,
|
||||
const char *forward, rb_dlink_list * list, long mode_type);
|
||||
|
||||
extern struct Ban * del_id(struct Channel *chptr, const char *banid, rb_dlink_list * list,
|
||||
|
|
|
@ -92,6 +92,7 @@ extern unsigned int CAP_EUID; /* supports EUID (ext UID + nonencap CHGHOST) */
|
|||
extern unsigned int CAP_EOPMOD; /* supports EOPMOD (ext +z + ext topic) */
|
||||
extern unsigned int CAP_BAN; /* supports propagated bans */
|
||||
extern unsigned int CAP_MLOCK; /* supports MLOCK messages */
|
||||
extern unsigned int CAP_EBMASK; /* supports sending BMASK set by/at metadata */
|
||||
|
||||
/* XXX: added for backwards compatibility. --nenolod */
|
||||
#define CAP_MASK (capability_index_mask(serv_capindex) & ~(CAP_TS6 | CAP_CAP))
|
||||
|
|
|
@ -237,10 +237,10 @@ allow_mode_change(struct Client *source_p, struct Channel *chptr, int alevel,
|
|||
/* add_id()
|
||||
*
|
||||
* inputs - client, channel, id to add, type, forward
|
||||
* outputs - false on failure, true on success
|
||||
* outputs - NULL on failure, allocated Ban on success
|
||||
* side effects - given id is added to the appropriate list
|
||||
*/
|
||||
bool
|
||||
struct Ban *
|
||||
add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const char *forward,
|
||||
rb_dlink_list * list, long mode_type)
|
||||
{
|
||||
|
@ -256,7 +256,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const
|
|||
{
|
||||
sendto_one(source_p, form_str(ERR_BANLISTFULL),
|
||||
me.name, source_p->name, chptr->chname, realban);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const
|
|||
{
|
||||
actualBan = ptr->data;
|
||||
if(!irccmp(actualBan->banstr, realban))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(IsPerson(source_p))
|
||||
|
@ -282,7 +282,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const
|
|||
if(mode_type == CHFL_BAN || mode_type == CHFL_QUIET || mode_type == CHFL_EXCEPTION)
|
||||
chptr->bants = rb_current_time();
|
||||
|
||||
return true;
|
||||
return actualBan;
|
||||
}
|
||||
|
||||
/* del_id()
|
||||
|
|
|
@ -86,6 +86,7 @@ unsigned int CAP_EUID;
|
|||
unsigned int CAP_EOPMOD;
|
||||
unsigned int CAP_BAN;
|
||||
unsigned int CAP_MLOCK;
|
||||
unsigned int CAP_EBMASK;
|
||||
|
||||
unsigned int CLICAP_MULTI_PREFIX;
|
||||
unsigned int CLICAP_ACCOUNT_NOTIFY;
|
||||
|
@ -126,6 +127,7 @@ init_builtin_capabs(void)
|
|||
CAP_EOPMOD = capability_put(serv_capindex, "EOPMOD", NULL);
|
||||
CAP_BAN = capability_put(serv_capindex, "BAN", NULL);
|
||||
CAP_MLOCK = capability_put(serv_capindex, "MLOCK", NULL);
|
||||
CAP_EBMASK = capability_put(serv_capindex, "EBMASK", NULL);
|
||||
|
||||
capability_require(serv_capindex, "QS");
|
||||
capability_require(serv_capindex, "EX");
|
||||
|
@ -511,8 +513,9 @@ burst_modes_TS6(struct Client *client_p, struct Channel *chptr,
|
|||
rb_dlink_node *ptr;
|
||||
struct Ban *banptr;
|
||||
|
||||
send_multiline_init(client_p, " ", ":%s BMASK %ld %s %c :",
|
||||
send_multiline_init(client_p, " ", ":%s %s %ld %s %c :",
|
||||
me.id,
|
||||
IsCapable(client_p, CAP_EBMASK) ? "EBMASK" : "BMASK",
|
||||
(long)chptr->channelts,
|
||||
chptr->chname,
|
||||
flag);
|
||||
|
@ -522,11 +525,18 @@ burst_modes_TS6(struct Client *client_p, struct Channel *chptr,
|
|||
banptr = ptr->data;
|
||||
|
||||
if (banptr->forward)
|
||||
send_multiline_item(client_p, "%s$%s",
|
||||
banptr->banstr,
|
||||
banptr->forward);
|
||||
sprintf(buf, "%s$%s", banptr->banstr, banptr->forward);
|
||||
else
|
||||
send_multiline_item(client_p, "%s", banptr->banstr);
|
||||
strcpy(buf, banptr->banstr);
|
||||
|
||||
if IsCapable(client_p, CAP_EBMASK)
|
||||
send_multiline_item(client_p, "%s %ld %s",
|
||||
buf,
|
||||
(long)banptr->when,
|
||||
banptr->who);
|
||||
else
|
||||
send_multiline_item(client_p, "%s", buf);
|
||||
|
||||
}
|
||||
|
||||
send_multiline_fini(client_p, NULL);
|
||||
|
|
|
@ -48,6 +48,7 @@ static void ms_mode(struct MsgBuf *, struct Client *, struct Client *, int, cons
|
|||
static void ms_tmode(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||
static void ms_mlock(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||
static void ms_bmask(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||
static void ms_ebmask(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||
|
||||
struct Message mode_msgtab = {
|
||||
"MODE", 0, 0, 0, 0,
|
||||
|
@ -65,8 +66,12 @@ struct Message bmask_msgtab = {
|
|||
"BMASK", 0, 0, 0, 0,
|
||||
{mg_ignore, mg_ignore, mg_ignore, {ms_bmask, 5}, mg_ignore, mg_ignore}
|
||||
};
|
||||
struct Message ebmask_msgtab = {
|
||||
"EBMASK", 0, 0, 0, 0,
|
||||
{mg_ignore, mg_ignore, mg_ignore, {ms_ebmask, 5}, mg_ignore, mg_ignore}
|
||||
};
|
||||
|
||||
mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &mlock_msgtab, &bmask_msgtab, NULL };
|
||||
mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &mlock_msgtab, &bmask_msgtab, &ebmask_msgtab, NULL };
|
||||
|
||||
DECLARE_MODULE_AV2(mode, NULL, NULL, mode_clist, NULL, NULL, NULL, NULL, mode_desc);
|
||||
|
||||
|
@ -256,16 +261,19 @@ possibly_remove_lower_forward(struct Client *fakesource_p, int mems,
|
|||
}
|
||||
|
||||
static void
|
||||
ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||
do_bmask(bool extended, struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||
{
|
||||
static char modebuf[BUFSIZE];
|
||||
static char output[BUFSIZE];
|
||||
static char parabuf[BUFSIZE];
|
||||
static char degrade[BUFSIZE];
|
||||
static char squitreason[120];
|
||||
struct Channel *chptr;
|
||||
struct Ban *banptr;
|
||||
rb_dlink_list *banlist;
|
||||
char *s, *forward;
|
||||
char *t;
|
||||
char *mbuf;
|
||||
char *pbuf;
|
||||
char *s, *mask, *forward, *who;
|
||||
char *output_ptr;
|
||||
char *param_ptr;
|
||||
char *degrade_ptr;
|
||||
long mode_type;
|
||||
int mlen;
|
||||
int plen = 0;
|
||||
|
@ -274,6 +282,7 @@ ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
int modecount = 0;
|
||||
int needcap = NOCAPS;
|
||||
int mems;
|
||||
time_t when = (long)rb_current_time();
|
||||
struct Client *fakesource_p;
|
||||
|
||||
if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
|
||||
|
@ -327,29 +336,29 @@ ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
fakesource_p = &me;
|
||||
else
|
||||
fakesource_p = source_p;
|
||||
mlen = sprintf(modebuf, ":%s MODE %s +", fakesource_p->name, chptr->chname);
|
||||
mbuf = modebuf + mlen;
|
||||
pbuf = parabuf;
|
||||
who = fakesource_p->name;
|
||||
|
||||
mlen = sprintf(output, ":%s MODE %s +", fakesource_p->name, chptr->chname);
|
||||
output_ptr = output + mlen;
|
||||
param_ptr = parabuf;
|
||||
degrade_ptr = degrade;
|
||||
|
||||
while(*s == ' ')
|
||||
s++;
|
||||
|
||||
/* next char isnt a space, point t to the next one */
|
||||
if((t = strchr(s, ' ')) != NULL)
|
||||
{
|
||||
*t++ = '\0';
|
||||
s = strtok(s, " ");
|
||||
|
||||
/* double spaces will break the parser */
|
||||
while(*t == ' ')
|
||||
t++;
|
||||
}
|
||||
|
||||
/* couldve skipped spaces and got nothing.. */
|
||||
while(!EmptyString(s))
|
||||
{
|
||||
/* ban with a leading ':' -- this will break the protocol */
|
||||
if(*s == ':')
|
||||
goto nextban;
|
||||
{
|
||||
/* ban with a leading ':' -- this will break the protocol */
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Link %s dropped, invalid BMASK mask (%s)", source_p->name, s);
|
||||
snprintf(squitreason, sizeof squitreason, "Invalid BMASK mask (%s)", s);
|
||||
exit_client(client_p, client_p, client_p, squitreason);
|
||||
return;
|
||||
}
|
||||
|
||||
tlen = strlen(s);
|
||||
|
||||
|
@ -368,53 +377,83 @@ ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
|
|||
parv[3][0], s, forward);
|
||||
}
|
||||
|
||||
if(add_id(fakesource_p, chptr, s, forward, banlist, mode_type))
|
||||
mask = s;
|
||||
if (extended) {
|
||||
when = atol(strtok(NULL, " "));
|
||||
who = strtok(NULL, " ");
|
||||
if (who == NULL)
|
||||
{
|
||||
/* EBMASK params don't divide by 3, so we have an incomplete chunk */
|
||||
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
|
||||
"Link %s dropped, invalid EBMASK chunk", source_p->name);
|
||||
snprintf(squitreason, sizeof squitreason, "Invalid EBMASK chunk");
|
||||
exit_client(client_p, client_p, client_p, squitreason);
|
||||
return;
|
||||
}
|
||||
|
||||
arglen = sprintf(degrade_ptr, "%s ", mask);
|
||||
degrade_ptr += arglen;
|
||||
}
|
||||
|
||||
if((banptr = add_id(fakesource_p, chptr, mask, forward, banlist, mode_type)) != NULL)
|
||||
{
|
||||
banptr->when = when;
|
||||
rb_free(banptr->who);
|
||||
banptr->who = rb_strdup(who);
|
||||
|
||||
/* this new one wont fit.. */
|
||||
if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 5 ||
|
||||
modecount >= MAXMODEPARAMS)
|
||||
{
|
||||
*mbuf = '\0';
|
||||
*(pbuf - 1) = '\0';
|
||||
sendto_channel_local(fakesource_p, mems, chptr, "%s %s", modebuf, parabuf);
|
||||
*output_ptr = '\0';
|
||||
*(param_ptr - 1) = '\0';
|
||||
sendto_channel_local(fakesource_p, mems, chptr, "%s %s", output, parabuf);
|
||||
|
||||
mbuf = modebuf + mlen;
|
||||
pbuf = parabuf;
|
||||
output_ptr = output + mlen;
|
||||
param_ptr = parabuf;
|
||||
plen = modecount = 0;
|
||||
}
|
||||
|
||||
if (forward != NULL)
|
||||
forward[-1] = '$';
|
||||
|
||||
*mbuf++ = parv[3][0];
|
||||
arglen = sprintf(pbuf, "%s ", s);
|
||||
pbuf += arglen;
|
||||
*output_ptr++ = parv[3][0];
|
||||
arglen = sprintf(param_ptr, "%s ", mask);
|
||||
param_ptr += arglen;
|
||||
plen += arglen;
|
||||
modecount++;
|
||||
}
|
||||
|
||||
nextban:
|
||||
s = t;
|
||||
|
||||
if(s != NULL)
|
||||
{
|
||||
if((t = strchr(s, ' ')) != NULL)
|
||||
{
|
||||
*t++ = '\0';
|
||||
|
||||
while(*t == ' ')
|
||||
t++;
|
||||
}
|
||||
}
|
||||
s = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
if(modecount)
|
||||
{
|
||||
*mbuf = '\0';
|
||||
*(pbuf - 1) = '\0';
|
||||
sendto_channel_local(fakesource_p, mems, chptr, "%s %s", modebuf, parabuf);
|
||||
*output_ptr = '\0';
|
||||
*(param_ptr - 1) = '\0';
|
||||
sendto_channel_local(fakesource_p, mems, chptr, "%s %s", output, parabuf);
|
||||
}
|
||||
|
||||
sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
|
||||
source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
|
||||
if (extended) {
|
||||
*(degrade_ptr - 1) = '\0';
|
||||
sendto_server(client_p, chptr, CAP_EBMASK | CAP_TS6 | needcap, NOCAPS, ":%s EBMASK %ld %s %s :%s",
|
||||
source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
|
||||
sendto_server(client_p, chptr, CAP_TS6 | needcap, CAP_EBMASK, ":%s BMASK %ld %s %s :%s",
|
||||
source_p->id, (long) chptr->channelts, chptr->chname, parv[3], degrade);
|
||||
}
|
||||
else
|
||||
sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
|
||||
source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
|
||||
}
|
||||
|
||||
static void
|
||||
ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||
{
|
||||
do_bmask(false, msgbuf_p, client_p, source_p, parc, parv);
|
||||
}
|
||||
static void
|
||||
ms_ebmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||
{
|
||||
do_bmask(true, msgbuf_p, client_p, source_p, parc, parv);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue