2 * ircd-ratbox: A slightly useful ircd.
3 * m_resv.c: Reserves(jupes) a nickname or channel.
5 * Copyright (C) 2001-2002 Hybrid Development Team
6 * Copyright (C) 2002-2005 ircd-ratbox development team
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
37 #include "s_newconf.h"
43 static int mo_resv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
44 static int ms_resv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
45 static int me_resv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
46 static int mo_unresv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
47 static int ms_unresv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
48 static int me_unresv(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
50 struct Message resv_msgtab
= {
52 {mg_ignore
, mg_not_oper
, {ms_resv
, 4}, {ms_resv
, 4}, {me_resv
, 5}, {mo_resv
, 3}}
55 struct Message unresv_msgtab
= {
57 {mg_ignore
, mg_not_oper
, {ms_unresv
, 3}, {ms_unresv
, 3}, {me_unresv
, 2}, {mo_unresv
, 2}}
60 mapi_clist_av1 resv_clist
[] = { &resv_msgtab
, &unresv_msgtab
, NULL
};
62 DECLARE_MODULE_AV1(resv
, NULL
, NULL
, resv_clist
, NULL
, NULL
, "$Revision$");
64 static void parse_resv(struct Client
*source_p
, const char *name
,
65 const char *reason
, int temp_time
, int propagated
);
66 static void propagate_resv(struct Client
*source_p
, const char *target
,
67 int temp_time
, const char *name
, const char *reason
);
68 static void cluster_resv(struct Client
*source_p
, int temp_time
,
69 const char *name
, const char *reason
);
71 static void handle_remote_unresv(struct Client
*source_p
, const char *name
);
72 static void remove_resv(struct Client
*source_p
, const char *name
, int propagated
);
76 * parv[1] = channel/nick to forbid
80 mo_resv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
84 const char *target_server
= NULL
;
87 int propagated
= ConfigFileEntry
.use_propagated_bans
;
89 if(!IsOperResv(source_p
))
91 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "resv");
95 /* RESV [time] <name> [ON <server>] :<reason> */
97 if((temp_time
= valid_temp_time(parv
[loc
])) >= 0)
99 /* we just set temp_time to -1! */
106 if((parc
>= loc
+ 2) && (irccmp(parv
[loc
], "ON") == 0))
108 if(!IsOperRemoteBan(source_p
))
110 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
111 me
.name
, source_p
->name
, "remoteban");
115 target_server
= parv
[loc
+ 1];
118 /* Set as local-only. */
122 if(parc
<= loc
|| EmptyString(parv
[loc
]))
124 sendto_one(source_p
, form_str(ERR_NEEDMOREPARAMS
), me
.name
, source_p
->name
, "RESV");
133 propagate_resv(source_p
, target_server
, temp_time
, name
, reason
);
135 if(match(target_server
, me
.name
) == 0)
138 else if(!propagated
&& rb_dlink_list_length(&cluster_conf_list
) > 0)
139 cluster_resv(source_p
, temp_time
, name
, reason
);
141 if(propagated
&& temp_time
== 0)
143 sendto_one_notice(source_p
, ":Cannot set a permanent global ban");
147 parse_resv(source_p
, name
, reason
, temp_time
, propagated
);
153 * parv[1] = target server
154 * parv[2] = channel/nick to forbid
158 ms_resv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
160 /* parv[0] parv[1] parv[2] parv[3]
161 * oper target server resv reason
163 propagate_resv(source_p
, parv
[1], 0, parv
[2], parv
[3]);
165 if(!match(parv
[1], me
.name
))
168 if(!IsPerson(source_p
))
171 parse_resv(source_p
, parv
[2], parv
[3], 0, 0);
176 me_resv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
178 /* time name 0 :reason */
179 if(!IsPerson(source_p
))
182 parse_resv(source_p
, parv
[2], parv
[4], atoi(parv
[1]), 0);
188 * inputs - source_p if error messages wanted
192 * side effects - will parse the resv and create it if valid
195 parse_resv(struct Client
*source_p
, const char *name
, const char *reason
, int temp_time
, int propagated
)
197 struct ConfItem
*aconf
;
199 if(!MyClient(source_p
) &&
200 !find_shared_conf(source_p
->username
, source_p
->host
,
201 source_p
->servptr
->name
,
202 (temp_time
> 0) ? SHARED_TRESV
: SHARED_PRESV
))
205 if(IsChannelName(name
))
207 if(hash_find_resv(name
))
209 sendto_one_notice(source_p
,
210 ":A RESV has already been placed on channel: %s", name
);
214 if(strlen(name
) > CHANNELLEN
)
216 sendto_one_notice(source_p
, ":Invalid RESV length: %s", name
);
221 aconf
->status
= CONF_RESV_CHANNEL
;
223 aconf
->created
= rb_current_time();
224 aconf
->host
= rb_strdup(name
);
225 aconf
->passwd
= rb_strdup(reason
);
226 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
230 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
231 aconf
->hold
= rb_current_time() + temp_time
;
232 aconf
->lifetime
= aconf
->hold
;
233 replace_old_ban(aconf
);
234 rb_dlinkAddAlloc(aconf
, &prop_bans
);
236 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
237 "%s added global %d min. RESV for [%s] [%s]",
238 get_oper_name(source_p
), temp_time
/ 60,
240 ilog(L_KLINE
, "R %s %d %s %s",
241 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
242 sendto_one_notice(source_p
, ":Added global %d min. RESV [%s]",
243 temp_time
/ 60, name
);
244 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
245 ":%s BAN R * %s %lu %d %d * :%s",
246 source_p
->id
, aconf
->host
,
247 (unsigned long)aconf
->created
,
248 (int)(aconf
->hold
- aconf
->created
),
249 (int)(aconf
->lifetime
- aconf
->created
),
252 else if(temp_time
> 0)
254 aconf
->hold
= rb_current_time() + temp_time
;
256 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
257 "%s added temporary %d min. RESV for [%s] [%s]",
258 get_oper_name(source_p
), temp_time
/ 60,
260 ilog(L_KLINE
, "R %s %d %s %s",
261 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
262 sendto_one_notice(source_p
, ":Added temporary %d min. RESV [%s]",
263 temp_time
/ 60, name
);
267 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
268 "%s added RESV for [%s] [%s]",
269 get_oper_name(source_p
), name
, reason
);
270 ilog(L_KLINE
, "R %s 0 %s %s",
271 get_oper_name(source_p
), name
, reason
);
272 sendto_one_notice(source_p
, ":Added RESV [%s]", name
);
274 bandb_add(BANDB_RESV
, source_p
, aconf
->host
, NULL
, aconf
->passwd
, NULL
, 0);
277 add_to_resv_hash(aconf
->host
, aconf
);
278 resv_chan_forcepart(aconf
->host
, aconf
->passwd
, temp_time
);
280 else if(clean_resv_nick(name
))
282 if(strlen(name
) > NICKLEN
* 2)
284 sendto_one_notice(source_p
, ":Invalid RESV length: %s", name
);
288 if(!valid_wild_card_simple(name
))
290 sendto_one_notice(source_p
,
291 ":Please include at least %d non-wildcard "
292 "characters with the resv",
293 ConfigFileEntry
.min_nonwildcard_simple
);
297 if(find_nick_resv_mask(name
))
299 sendto_one_notice(source_p
,
300 ":A RESV has already been placed on nick: %s", name
);
305 aconf
->status
= CONF_RESV_NICK
;
307 aconf
->created
= rb_current_time();
308 aconf
->host
= rb_strdup(name
);
309 aconf
->passwd
= rb_strdup(reason
);
310 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
314 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
315 aconf
->hold
= rb_current_time() + temp_time
;
316 aconf
->lifetime
= aconf
->hold
;
317 replace_old_ban(aconf
);
318 rb_dlinkAddAlloc(aconf
, &prop_bans
);
320 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
321 "%s added global %d min. RESV for [%s] [%s]",
322 get_oper_name(source_p
), temp_time
/ 60,
324 ilog(L_KLINE
, "R %s %d %s %s",
325 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
326 sendto_one_notice(source_p
, ":Added global %d min. RESV [%s]",
327 temp_time
/ 60, name
);
328 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
329 ":%s BAN R * %s %lu %d %d * :%s",
330 source_p
->id
, aconf
->host
,
331 (unsigned long)aconf
->created
,
332 (int)(aconf
->hold
- aconf
->created
),
333 (int)(aconf
->lifetime
- aconf
->created
),
336 else if(temp_time
> 0)
338 aconf
->hold
= rb_current_time() + temp_time
;
340 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
341 "%s added temporary %d min. RESV for [%s] [%s]",
342 get_oper_name(source_p
), temp_time
/ 60,
344 ilog(L_KLINE
, "R %s %d %s %s",
345 get_oper_name(source_p
), temp_time
/ 60, name
, reason
);
346 sendto_one_notice(source_p
, ":Added temporary %d min. RESV [%s]",
347 temp_time
/ 60, name
);
351 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
352 "%s added RESV for [%s] [%s]",
353 get_oper_name(source_p
), name
, reason
);
354 ilog(L_KLINE
, "R %s 0 %s %s",
355 get_oper_name(source_p
), name
, reason
);
356 sendto_one_notice(source_p
, ":Added RESV [%s]", name
);
358 bandb_add(BANDB_RESV
, source_p
, aconf
->host
, NULL
, aconf
->passwd
, NULL
, 0);
361 rb_dlinkAddAlloc(aconf
, &resv_conf_list
);
362 resv_nick_fnc(aconf
->host
, aconf
->passwd
, temp_time
);
365 sendto_one_notice(source_p
, ":You have specified an invalid resv: [%s]", name
);
369 propagate_resv(struct Client
*source_p
, const char *target
,
370 int temp_time
, const char *name
, const char *reason
)
374 sendto_match_servs(source_p
, target
,
375 CAP_CLUSTER
, NOCAPS
, "RESV %s %s :%s", target
, name
, reason
);
376 sendto_match_servs(source_p
, target
,
377 CAP_ENCAP
, CAP_CLUSTER
,
378 "ENCAP %s RESV %d %s 0 :%s", target
, temp_time
, name
, reason
);
381 sendto_match_servs(source_p
, target
,
383 "ENCAP %s RESV %d %s 0 :%s", target
, temp_time
, name
, reason
);
387 cluster_resv(struct Client
*source_p
, int temp_time
, const char *name
, const char *reason
)
389 struct remote_conf
*shared_p
;
392 RB_DLINK_FOREACH(ptr
, cluster_conf_list
.head
)
394 shared_p
= ptr
->data
;
396 /* old protocol cant handle temps, and we dont really want
397 * to convert them to perm.. --fl
401 if(!(shared_p
->flags
& SHARED_PRESV
))
404 sendto_match_servs(source_p
, shared_p
->server
,
406 "RESV %s %s :%s", shared_p
->server
, name
, reason
);
407 sendto_match_servs(source_p
, shared_p
->server
,
408 CAP_ENCAP
, CAP_CLUSTER
,
409 "ENCAP %s RESV 0 %s 0 :%s",
410 shared_p
->server
, name
, reason
);
412 else if(shared_p
->flags
& SHARED_TRESV
)
413 sendto_match_servs(source_p
, shared_p
->server
,
415 "ENCAP %s RESV %d %s 0 :%s",
416 shared_p
->server
, temp_time
, name
, reason
);
423 * parv[1] = channel/nick to unforbid
426 mo_unresv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
430 if(!IsOperResv(source_p
))
432 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "resv");
436 if((parc
== 4) && (irccmp(parv
[2], "ON") == 0))
438 if(!IsOperRemoteBan(source_p
))
440 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
441 me
.name
, source_p
->name
, "remoteban");
445 propagate_generic(source_p
, "UNRESV", parv
[3], CAP_CLUSTER
, "%s", parv
[1]);
447 if(match(parv
[3], me
.name
) == 0)
453 else if(rb_dlink_list_length(&cluster_conf_list
) > 0)
454 cluster_generic(source_p
, "UNRESV", SHARED_UNRESV
, CAP_CLUSTER
, "%s", parv
[1]);
456 /* cluster{} moved to remove_resv */
458 remove_resv(source_p
, parv
[1], propagated
);
463 * parv[1] = target server
464 * parv[2] = resv to remove
467 ms_unresv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
469 /* parv[0] parv[1] parv[2]
470 * oper target server resv to remove
472 propagate_generic(source_p
, "UNRESV", parv
[1], CAP_CLUSTER
, "%s", parv
[2]);
474 if(!match(parv
[1], me
.name
))
477 if(!IsPerson(source_p
))
480 handle_remote_unresv(source_p
, parv
[2]);
485 me_unresv(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
488 if(!IsPerson(source_p
))
491 handle_remote_unresv(source_p
, parv
[1]);
496 handle_remote_unresv(struct Client
*source_p
, const char *name
)
498 if(!find_shared_conf(source_p
->username
, source_p
->host
,
499 source_p
->servptr
->name
, SHARED_UNRESV
))
502 remove_resv(source_p
, name
, 0);
508 remove_resv(struct Client
*source_p
, const char *name
, int propagated
)
510 struct ConfItem
*aconf
= NULL
;
514 if(IsChannelName(name
))
516 if((aconf
= hash_find_resv(name
)) == NULL
)
518 if(propagated
&& rb_dlink_list_length(&cluster_conf_list
))
519 cluster_generic(source_p
, "UNRESV", SHARED_UNRESV
, CAP_CLUSTER
, "%s", name
);
521 sendto_one_notice(source_p
, ":No RESV for %s", name
);
529 sendto_one_notice(source_p
, ":Cannot remove global RESV %s on specific servers", name
);
532 ptr
= rb_dlinkFind(aconf
, &prop_bans
);
535 sendto_one_notice(source_p
, ":RESV for [%s] is removed", name
);
536 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
537 "%s has removed the global RESV for: [%s]",
538 get_oper_name(source_p
), name
);
539 ilog(L_KLINE
, "UR %s %s", get_oper_name(source_p
), name
);
540 now
= rb_current_time();
541 if(aconf
->created
< now
)
542 aconf
->created
= now
;
545 aconf
->hold
= aconf
->created
;
546 operhash_delete(aconf
->info
.oper
);
547 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
548 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
549 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
550 ":%s BAN R * %s %lu %d %d * :*",
551 source_p
->id
, aconf
->host
,
552 (unsigned long)aconf
->created
,
554 (int)(aconf
->lifetime
- aconf
->created
));
555 deactivate_conf(aconf
, ptr
, now
);
558 else if(propagated
&& rb_dlink_list_length(&cluster_conf_list
) > 0)
559 cluster_generic(source_p
, "UNRESV", SHARED_UNRESV
, CAP_CLUSTER
, "%s", name
);
561 sendto_one_notice(source_p
, ":RESV for [%s] is removed", name
);
562 ilog(L_KLINE
, "UR %s %s", get_oper_name(source_p
), name
);
565 bandb_del(BANDB_RESV
, aconf
->host
, NULL
);
566 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
567 "%s has removed the RESV for: [%s]",
568 get_oper_name(source_p
), name
);
572 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
573 "%s has removed the temporary RESV for: [%s]",
574 get_oper_name(source_p
), name
);
576 del_from_resv_hash(name
, aconf
);
580 RB_DLINK_FOREACH(ptr
, resv_conf_list
.head
)
584 if(irccmp(aconf
->host
, name
))
592 if(propagated
&& rb_dlink_list_length(&cluster_conf_list
))
593 cluster_generic(source_p
, "UNRESV", SHARED_UNRESV
, CAP_CLUSTER
, "%s", name
);
595 sendto_one_notice(source_p
, ":No RESV for %s", name
);
603 sendto_one_notice(source_p
, ":Cannot remove global RESV %s on specific servers", name
);
606 ptr
= rb_dlinkFind(aconf
, &prop_bans
);
609 sendto_one_notice(source_p
, ":RESV for [%s] is removed", name
);
610 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
611 "%s has removed the global RESV for: [%s]",
612 get_oper_name(source_p
), name
);
613 ilog(L_KLINE
, "UR %s %s", get_oper_name(source_p
), name
);
614 now
= rb_current_time();
615 if(aconf
->created
< now
)
616 aconf
->created
= now
;
619 aconf
->hold
= aconf
->created
;
620 operhash_delete(aconf
->info
.oper
);
621 aconf
->info
.oper
= operhash_add(get_oper_name(source_p
));
622 aconf
->flags
|= CONF_FLAGS_MYOPER
| CONF_FLAGS_TEMPORARY
;
623 sendto_server(NULL
, NULL
, CAP_BAN
|CAP_TS6
, NOCAPS
,
624 ":%s BAN R * %s %lu %d %d * :*",
625 source_p
->id
, aconf
->host
,
626 (unsigned long)aconf
->created
,
628 (int)(aconf
->lifetime
- aconf
->created
));
629 deactivate_conf(aconf
, ptr
, now
);
632 else if(propagated
&& rb_dlink_list_length(&cluster_conf_list
) > 0)
633 cluster_generic(source_p
, "UNRESV", SHARED_UNRESV
, CAP_CLUSTER
, "%s", name
);
635 sendto_one_notice(source_p
, ":RESV for [%s] is removed", name
);
636 ilog(L_KLINE
, "UR %s %s", get_oper_name(source_p
), name
);
639 bandb_del(BANDB_RESV
, aconf
->host
, NULL
);
640 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
641 "%s has removed the RESV for: [%s]",
642 get_oper_name(source_p
), name
);
646 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
647 "%s has removed the temporary RESV for: [%s]",
648 get_oper_name(source_p
), name
);
650 /* already have ptr from the loop above.. */
651 rb_dlinkDestroy(ptr
, &resv_conf_list
);