]> jfr.im git - solanum.git/blame - modules/core/m_mode.c
add help for `chm_regmsg`
[solanum.git] / modules / core / m_mode.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_mode.c: Sets a user or channel mode.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
212380e3
AC
23 */
24
25#include "stdinc.h"
212380e3
AC
26#include "channel.h"
27#include "client.h"
28#include "hash.h"
4562c604 29#include "match.h"
212380e3
AC
30#include "ircd.h"
31#include "numeric.h"
32#include "s_user.h"
33#include "s_conf.h"
34#include "s_serv.h"
4016731b 35#include "logger.h"
212380e3
AC
36#include "send.h"
37#include "msg.h"
38#include "parse.h"
39#include "modules.h"
40#include "packet.h"
212380e3
AC
41#include "s_newconf.h"
42
eeabf33a
EM
43static const char mode_desc[] =
44 "Provides the MODE and MLOCK client and server commands, and TS6 server-to-server TMODE and BMASK commands";
45
3c7d6fcc
EM
46static void m_mode(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
47static void ms_mode(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
48static void ms_tmode(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
49static void ms_mlock(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
50static void ms_bmask(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
fdd8cad9 51static void ms_ebmask(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
212380e3
AC
52
53struct Message mode_msgtab = {
7baa37a9 54 "MODE", 0, 0, 0, 0,
212380e3
AC
55 {mg_unreg, {m_mode, 2}, {m_mode, 3}, {ms_mode, 3}, mg_ignore, {m_mode, 2}}
56};
57struct Message tmode_msgtab = {
7baa37a9 58 "TMODE", 0, 0, 0, 0,
212380e3
AC
59 {mg_ignore, mg_ignore, {ms_tmode, 4}, {ms_tmode, 4}, mg_ignore, mg_ignore}
60};
8727cbe8 61struct Message mlock_msgtab = {
7baa37a9 62 "MLOCK", 0, 0, 0, 0,
6b8db2da 63 {mg_ignore, mg_ignore, {ms_mlock, 3}, {ms_mlock, 3}, mg_ignore, mg_ignore}
8727cbe8 64};
212380e3 65struct Message bmask_msgtab = {
7baa37a9 66 "BMASK", 0, 0, 0, 0,
212380e3
AC
67 {mg_ignore, mg_ignore, mg_ignore, {ms_bmask, 5}, mg_ignore, mg_ignore}
68};
fdd8cad9
JP
69struct Message ebmask_msgtab = {
70 "EBMASK", 0, 0, 0, 0,
71 {mg_ignore, mg_ignore, mg_ignore, {ms_ebmask, 5}, mg_ignore, mg_ignore}
72};
212380e3 73
fdd8cad9 74mapi_clist_av1 mode_clist[] = { &mode_msgtab, &tmode_msgtab, &mlock_msgtab, &bmask_msgtab, &ebmask_msgtab, NULL };
212380e3 75
ee6dcb05 76DECLARE_MODULE_AV2(mode, NULL, NULL, mode_clist, NULL, NULL, NULL, NULL, mode_desc);
212380e3
AC
77
78/*
79 * m_mode - MODE command handler
212380e3
AC
80 * parv[1] - channel
81 */
3c7d6fcc 82static void
428ca87b 83m_mode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
84{
85 struct Channel *chptr = NULL;
86 struct membership *msptr;
87 int n = 2;
88 const char *dest;
89 int operspy = 0;
90
91 dest = parv[1];
92
93 if(IsOperSpy(source_p) && *dest == '!')
94 {
95 dest++;
96 operspy = 1;
97
98 if(EmptyString(dest))
99 {
100 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
101 me.name, source_p->name, "MODE");
3c7d6fcc 102 return;
212380e3
AC
103 }
104 }
105
106 /* Now, try to find the channel in question */
107 if(!IsChanPrefix(*dest))
108 {
109 /* if here, it has to be a non-channel name */
110 user_mode(client_p, source_p, parc, parv);
3c7d6fcc 111 return;
212380e3
AC
112 }
113
114 if(!check_channel_name(dest))
115 {
116 sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]);
3c7d6fcc 117 return;
212380e3
AC
118 }
119
120 chptr = find_channel(dest);
121
122 if(chptr == NULL)
123 {
124 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
125 form_str(ERR_NOSUCHCHANNEL), parv[1]);
3c7d6fcc 126 return;
212380e3
AC
127 }
128
129 /* Now know the channel exists */
130 if(parc < n + 1)
131 {
132 if(operspy)
133 report_operspy(source_p, "MODE", chptr->chname);
134
135 sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
136 me.name, source_p->name, parv[1],
137 operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p));
138
139 sendto_one(source_p, form_str(RPL_CREATIONTIME),
5c01fc8b 140 me.name, source_p->name, parv[1], (long long)chptr->channelts);
212380e3
AC
141 }
142 else
143 {
144 msptr = find_channel_membership(chptr, source_p);
145
212380e3
AC
146 set_channel_mode(client_p, source_p, chptr, msptr, parc - n, parv + n);
147 }
212380e3
AC
148}
149
3c7d6fcc 150static void
428ca87b 151ms_mode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
152{
153 struct Channel *chptr;
154
155 chptr = find_channel(parv[1]);
156
157 if(chptr == NULL)
158 {
159 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
160 form_str(ERR_NOSUCHCHANNEL), parv[1]);
3c7d6fcc 161 return;
212380e3
AC
162 }
163
164 set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2);
212380e3
AC
165}
166
3c7d6fcc 167static void
428ca87b 168ms_tmode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3
AC
169{
170 struct Channel *chptr = NULL;
171 struct membership *msptr;
172
173 /* Now, try to find the channel in question */
174 if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
175 {
176 sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
3c7d6fcc 177 return;
212380e3
AC
178 }
179
180 chptr = find_channel(parv[2]);
181
182 if(chptr == NULL)
183 {
184 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
185 form_str(ERR_NOSUCHCHANNEL), parv[2]);
3c7d6fcc 186 return;
212380e3
AC
187 }
188
189 /* TS is higher, drop it. */
190 if(atol(parv[1]) > chptr->channelts)
3c7d6fcc 191 return;
212380e3
AC
192
193 if(IsServer(source_p))
194 {
195 set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3);
196 }
197 else
198 {
199 msptr = find_channel_membership(chptr, source_p);
200
212380e3
AC
201 set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
202 }
212380e3
AC
203}
204
3c7d6fcc 205static void
428ca87b 206ms_mlock(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
8727cbe8
AC
207{
208 struct Channel *chptr = NULL;
209
210 /* Now, try to find the channel in question */
211 if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
212 {
213 sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
3c7d6fcc 214 return;
8727cbe8
AC
215 }
216
217 chptr = find_channel(parv[2]);
218
219 if(chptr == NULL)
220 {
221 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
222 form_str(ERR_NOSUCHCHANNEL), parv[2]);
3c7d6fcc 223 return;
8727cbe8
AC
224 }
225
226 /* TS is higher, drop it. */
227 if(atol(parv[1]) > chptr->channelts)
3c7d6fcc 228 return;
8727cbe8
AC
229
230 if(IsServer(source_p))
07554369 231 set_channel_mlock(client_p, source_p, chptr, parv[3], true);
8727cbe8
AC
232}
233
d1316b19
JT
234static void
235possibly_remove_lower_forward(struct Client *fakesource_p, int mems,
236 struct Channel *chptr, rb_dlink_list *banlist, int mchar,
237 const char *mask, const char *forward)
238{
239 struct Ban *actualBan;
240 rb_dlink_node *ptr;
241
242 RB_DLINK_FOREACH(ptr, banlist->head)
243 {
244 actualBan = ptr->data;
245 if(!irccmp(actualBan->banstr, mask) &&
246 (actualBan->forward == NULL ||
247 irccmp(actualBan->forward, forward) < 0))
248 {
4b1cce65 249 sendto_channel_local(fakesource_p, mems, chptr, ":%s MODE %s -%c %s%s%s",
d1316b19
JT
250 fakesource_p->name,
251 chptr->chname,
252 mchar,
253 actualBan->banstr,
254 actualBan->forward ? "$" : "",
255 actualBan->forward ? actualBan->forward : "");
256 rb_dlinkDelete(&actualBan->node, banlist);
257 free_ban(actualBan);
258 return;
259 }
260 }
261}
262
3c7d6fcc 263static void
fdd8cad9 264do_bmask(bool extended, struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 265{
fdd8cad9 266 static char output[BUFSIZE];
212380e3 267 static char parabuf[BUFSIZE];
fdd8cad9
JP
268 static char degrade[BUFSIZE];
269 static char squitreason[120];
212380e3 270 struct Channel *chptr;
fdd8cad9 271 struct Ban *banptr;
5b96d9a6 272 rb_dlink_list *banlist;
fdd8cad9
JP
273 char *s, *mask, *forward, *who;
274 char *output_ptr;
275 char *param_ptr;
276 char *degrade_ptr;
212380e3
AC
277 long mode_type;
278 int mlen;
279 int plen = 0;
280 int tlen;
281 int arglen;
282 int modecount = 0;
283 int needcap = NOCAPS;
284 int mems;
fdd8cad9 285 time_t when = (long)rb_current_time();
212380e3
AC
286 struct Client *fakesource_p;
287
288 if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
3c7d6fcc 289 return;
212380e3
AC
290
291 if((chptr = find_channel(parv[2])) == NULL)
3c7d6fcc 292 return;
212380e3
AC
293
294 /* TS is higher, drop it. */
295 if(atol(parv[1]) > chptr->channelts)
3c7d6fcc 296 return;
212380e3
AC
297
298 switch (parv[3][0])
299 {
300 case 'b':
301 banlist = &chptr->banlist;
302 mode_type = CHFL_BAN;
303 mems = ALL_MEMBERS;
304 break;
305
306 case 'e':
307 banlist = &chptr->exceptlist;
308 mode_type = CHFL_EXCEPTION;
309 needcap = CAP_EX;
310 mems = ONLY_CHANOPS;
311 break;
312
313 case 'I':
314 banlist = &chptr->invexlist;
315 mode_type = CHFL_INVEX;
316 needcap = CAP_IE;
317 mems = ONLY_CHANOPS;
318 break;
319
320 case 'q':
321 banlist = &chptr->quietlist;
322 mode_type = CHFL_QUIET;
323 mems = ALL_MEMBERS;
324 break;
325
326 /* maybe we should just blindly propagate this? */
327 default:
3c7d6fcc 328 return;
212380e3
AC
329 }
330
331 parabuf[0] = '\0';
332 s = LOCAL_COPY(parv[4]);
333
334 /* Hide connecting server on netburst -- jilles */
335 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
336 fakesource_p = &me;
337 else
338 fakesource_p = source_p;
fdd8cad9
JP
339 who = fakesource_p->name;
340
341 mlen = sprintf(output, ":%s MODE %s +", fakesource_p->name, chptr->chname);
342 output_ptr = output + mlen;
343 param_ptr = parabuf;
344 degrade_ptr = degrade;
212380e3
AC
345
346 while(*s == ' ')
347 s++;
348
fdd8cad9 349 s = strtok(s, " ");
212380e3 350
212380e3
AC
351 while(!EmptyString(s))
352 {
212380e3 353 if(*s == ':')
fdd8cad9
JP
354 {
355 /* ban with a leading ':' -- this will break the protocol */
356 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
357 "Link %s dropped, invalid BMASK mask (%s)", source_p->name, s);
358 snprintf(squitreason, sizeof squitreason, "Invalid BMASK mask (%s)", s);
359 exit_client(client_p, client_p, client_p, squitreason);
360 return;
361 }
212380e3
AC
362
363 tlen = strlen(s);
364
365 /* I dont even want to begin parsing this.. */
366 if(tlen > MODEBUFLEN)
367 break;
368
765d839d
EM
369 if((forward = strchr(s+1, '$')) != NULL)
370 {
371 *forward++ = '\0';
372 if(*forward == '\0')
23f6b63a 373 tlen--, forward = NULL;
fea6157d
JT
374 else
375 possibly_remove_lower_forward(fakesource_p,
376 mems, chptr, banlist,
377 parv[3][0], s, forward);
765d839d
EM
378 }
379
fdd8cad9
JP
380 mask = s;
381 if (extended) {
382 when = atol(strtok(NULL, " "));
383 who = strtok(NULL, " ");
384 if (who == NULL)
385 {
386 /* EBMASK params don't divide by 3, so we have an incomplete chunk */
387 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
388 "Link %s dropped, invalid EBMASK chunk", source_p->name);
389 snprintf(squitreason, sizeof squitreason, "Invalid EBMASK chunk");
390 exit_client(client_p, client_p, client_p, squitreason);
391 return;
392 }
393
394 arglen = sprintf(degrade_ptr, "%s ", mask);
395 degrade_ptr += arglen;
396 }
397
398 if((banptr = add_id(fakesource_p, chptr, mask, forward, banlist, mode_type)) != NULL)
212380e3 399 {
fdd8cad9
JP
400 banptr->when = when;
401 rb_free(banptr->who);
402 banptr->who = rb_strdup(who);
403
212380e3
AC
404 /* this new one wont fit.. */
405 if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 5 ||
406 modecount >= MAXMODEPARAMS)
407 {
fdd8cad9
JP
408 *output_ptr = '\0';
409 *(param_ptr - 1) = '\0';
410 sendto_channel_local(fakesource_p, mems, chptr, "%s %s", output, parabuf);
212380e3 411
fdd8cad9
JP
412 output_ptr = output + mlen;
413 param_ptr = parabuf;
212380e3
AC
414 plen = modecount = 0;
415 }
416
23f6b63a
JT
417 if (forward != NULL)
418 forward[-1] = '$';
419
fdd8cad9
JP
420 *output_ptr++ = parv[3][0];
421 arglen = sprintf(param_ptr, "%s ", mask);
422 param_ptr += arglen;
212380e3
AC
423 plen += arglen;
424 modecount++;
425 }
426
fdd8cad9 427 s = strtok(NULL, " ");
212380e3
AC
428 }
429
430 if(modecount)
431 {
fdd8cad9
JP
432 *output_ptr = '\0';
433 *(param_ptr - 1) = '\0';
434 sendto_channel_local(fakesource_p, mems, chptr, "%s %s", output, parabuf);
435 }
436
437 if (extended) {
438 *(degrade_ptr - 1) = '\0';
439 sendto_server(client_p, chptr, CAP_EBMASK | CAP_TS6 | needcap, NOCAPS, ":%s EBMASK %ld %s %s :%s",
440 source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
441 sendto_server(client_p, chptr, CAP_TS6 | needcap, CAP_EBMASK, ":%s BMASK %ld %s %s :%s",
442 source_p->id, (long) chptr->channelts, chptr->chname, parv[3], degrade);
212380e3 443 }
fdd8cad9
JP
444 else
445 sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
446 source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
447}
212380e3 448
fdd8cad9
JP
449static void
450ms_bmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
451{
452 do_bmask(false, msgbuf_p, client_p, source_p, parc, parv);
212380e3 453}
fdd8cad9
JP
454static void
455ms_ebmask(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
456{
457 do_bmask(true, msgbuf_p, client_p, source_p, parc, parv);
458}
459