]> jfr.im git - irc/rqf/shadowircd.git/blame - modules/m_resv.c
Add ERR_MLOCKRESTRICTED (735) to reflect bounces caused by MLOCK.
[irc/rqf/shadowircd.git] / modules / m_resv.c
CommitLineData
212380e3 1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_resv.c: Reserves(jupes) a nickname or channel.
4 *
5 * Copyright (C) 2001-2002 Hybrid Development Team
6 * Copyright (C) 2002-2005 ircd-ratbox development team
7 *
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.
12 *
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.
17 *
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
21 * USA
22 *
d8a4c5f6 23 * $Id$
212380e3 24 */
25
26#include "stdinc.h"
27#include "client.h"
28#include "channel.h"
29#include "ircd.h"
30#include "numeric.h"
31#include "s_serv.h"
32#include "send.h"
33#include "msg.h"
34#include "parse.h"
35#include "modules.h"
36#include "s_conf.h"
37#include "s_newconf.h"
38#include "hash.h"
d3455e2c 39#include "logger.h"
d8a4c5f6 40#include "bandbi.h"
a0f4c418 41#include "operhash.h"
212380e3 42
43static int mo_resv(struct Client *, struct Client *, int, const char **);
44static int ms_resv(struct Client *, struct Client *, int, const char **);
45static int me_resv(struct Client *, struct Client *, int, const char **);
46static int mo_unresv(struct Client *, struct Client *, int, const char **);
47static int ms_unresv(struct Client *, struct Client *, int, const char **);
48static int me_unresv(struct Client *, struct Client *, int, const char **);
49
50struct Message resv_msgtab = {
51 "RESV", 0, 0, 0, MFLG_SLOW | MFLG_UNREG,
52 {mg_ignore, mg_not_oper, {ms_resv, 4}, {ms_resv, 4}, {me_resv, 5}, {mo_resv, 3}}
53};
d8a4c5f6 54
212380e3 55struct Message unresv_msgtab = {
56 "UNRESV", 0, 0, 0, MFLG_SLOW | MFLG_UNREG,
57 {mg_ignore, mg_not_oper, {ms_unresv, 3}, {ms_unresv, 3}, {me_unresv, 2}, {mo_unresv, 2}}
58};
59
d8a4c5f6
WP
60mapi_clist_av1 resv_clist[] = { &resv_msgtab, &unresv_msgtab, NULL };
61
62DECLARE_MODULE_AV1(resv, NULL, NULL, resv_clist, NULL, NULL, "$Revision$");
212380e3 63
64static void parse_resv(struct Client *source_p, const char *name,
9b9d818b 65 const char *reason, int temp_time, int propagated);
212380e3 66static void propagate_resv(struct Client *source_p, const char *target,
d8a4c5f6
WP
67 int temp_time, const char *name, const char *reason);
68static void cluster_resv(struct Client *source_p, int temp_time,
69 const char *name, const char *reason);
212380e3 70
71static void handle_remote_unresv(struct Client *source_p, const char *name);
9b9d818b 72static void remove_resv(struct Client *source_p, const char *name, int propagated);
212380e3 73
74/*
75 * mo_resv()
d8a4c5f6 76 * parv[0] = sender prefix
212380e3 77 * parv[1] = channel/nick to forbid
78 * parv[2] = reason
79 */
80static int
81mo_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
82{
83 const char *name;
84 const char *reason;
85 const char *target_server = NULL;
86 int temp_time;
87 int loc = 1;
9b9d818b 88 int propagated = ConfigFileEntry.use_propagated_bans;
212380e3 89
1ebe6ffc
JT
90 if(!IsOperResv(source_p))
91 {
d8a4c5f6 92 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv");
1ebe6ffc
JT
93 return 0;
94 }
95
212380e3 96 /* RESV [time] <name> [ON <server>] :<reason> */
97
98 if((temp_time = valid_temp_time(parv[loc])) >= 0)
99 loc++;
100 /* we just set temp_time to -1! */
101 else
102 temp_time = 0;
103
104 name = parv[loc];
105 loc++;
106
d8a4c5f6 107 if((parc >= loc + 2) && (irccmp(parv[loc], "ON") == 0))
212380e3 108 {
109 if(!IsOperRemoteBan(source_p))
110 {
111 sendto_one(source_p, form_str(ERR_NOPRIVS),
d8a4c5f6 112 me.name, source_p->name, "remoteban");
212380e3 113 return 0;
114 }
115
d8a4c5f6 116 target_server = parv[loc + 1];
212380e3 117 loc += 2;
9b9d818b
JT
118
119 /* Set as local-only. */
120 propagated = 0;
212380e3 121 }
122
123 if(parc <= loc || EmptyString(parv[loc]))
124 {
d8a4c5f6 125 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "RESV");
212380e3 126 return 0;
127 }
128
129 reason = parv[loc];
130
131 /* remote resv.. */
132 if(target_server)
133 {
134 propagate_resv(source_p, target_server, temp_time, name, reason);
135
136 if(match(target_server, me.name) == 0)
137 return 0;
138 }
9b9d818b 139 else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
212380e3 140 cluster_resv(source_p, temp_time, name, reason);
141
9b9d818b
JT
142 if(propagated && temp_time == 0)
143 {
144 sendto_one_notice(source_p, ":Cannot set a permanent global ban");
145 return 0;
146 }
147
148 parse_resv(source_p, name, reason, temp_time, propagated);
212380e3 149
150 return 0;
151}
152
153/* ms_resv()
d8a4c5f6 154 * parv[0] = sender prefix
212380e3 155 * parv[1] = target server
156 * parv[2] = channel/nick to forbid
157 * parv[3] = reason
158 */
159static int
d8a4c5f6 160ms_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 161{
d8a4c5f6
WP
162 /* parv[0] parv[1] parv[2] parv[3]
163 * oper target server resv reason
212380e3 164 */
165 propagate_resv(source_p, parv[1], 0, parv[2], parv[3]);
166
167 if(!match(parv[1], me.name))
168 return 0;
169
170 if(!IsPerson(source_p))
171 return 0;
172
9b9d818b 173 parse_resv(source_p, parv[2], parv[3], 0, 0);
212380e3 174 return 0;
175}
176
177static int
d8a4c5f6 178me_resv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
212380e3 179{
180 /* time name 0 :reason */
181 if(!IsPerson(source_p))
182 return 0;
183
9b9d818b 184 parse_resv(source_p, parv[2], parv[4], atoi(parv[1]), 0);
212380e3 185 return 0;
186}
187
188/* parse_resv()
189 *
190 * inputs - source_p if error messages wanted
191 * - thing to resv
192 * - reason for resv
193 * outputs -
194 * side effects - will parse the resv and create it if valid
195 */
196static void
9b9d818b 197parse_resv(struct Client *source_p, const char *name, const char *reason, int temp_time, int propagated)
212380e3 198{
199 struct ConfItem *aconf;
200
d8a4c5f6 201 if(!MyClient(source_p) &&
212380e3 202 !find_shared_conf(source_p->username, source_p->host,
d8a4c5f6
WP
203 source_p->servptr->name,
204 (temp_time > 0) ? SHARED_TRESV : SHARED_PRESV))
212380e3 205 return;
206
207 if(IsChannelName(name))
208 {
209 if(hash_find_resv(name))
210 {
211 sendto_one_notice(source_p,
d8a4c5f6 212 ":A RESV has already been placed on channel: %s", name);
212380e3 213 return;
214 }
215
216 if(strlen(name) > CHANNELLEN)
217 {
d8a4c5f6 218 sendto_one_notice(source_p, ":Invalid RESV length: %s", name);
6e5b8a5d
JT
219 return;
220 }
212380e3 221
222 if(strchr(reason, '"'))
223 {
d8a4c5f6 224 sendto_one_notice(source_p, ":Invalid character '\"' in comment");
212380e3 225 return;
226 }
227
228 aconf = make_conf();
229 aconf->status = CONF_RESV_CHANNEL;
230 aconf->port = 0;
ce60772d 231 aconf->created = rb_current_time();
ff0482a9 232 aconf->host = rb_strdup(name);
62d28946 233 aconf->passwd = rb_strdup(reason);
a0f4c418 234 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 235
9b9d818b
JT
236 if(propagated)
237 {
238 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
239 aconf->hold = rb_current_time() + temp_time;
240 aconf->lifetime = aconf->hold;
241 replace_old_ban(aconf);
242 rb_dlinkAddAlloc(aconf, &prop_bans);
243
244 sendto_realops_snomask(SNO_GENERAL, L_ALL,
245 "%s added global %d min. RESV for [%s] [%s]",
246 get_oper_name(source_p), temp_time / 60,
247 name, reason);
248 ilog(L_KLINE, "R %s %d %s %s",
249 get_oper_name(source_p), temp_time / 60, name, reason);
250 sendto_one_notice(source_p, ":Added global %d min. RESV [%s]",
251 temp_time / 60, name);
252 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
253 ":%s BAN R * %s %lu %d %d * :%s",
254 source_p->id, aconf->host,
255 (unsigned long)aconf->created,
256 (int)(aconf->hold - aconf->created),
257 (int)(aconf->lifetime - aconf->created),
258 reason);
259 }
260 else if(temp_time > 0)
212380e3 261 {
9f6bbe3c 262 aconf->hold = rb_current_time() + temp_time;
212380e3 263
264 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
265 "%s added temporary %d min. RESV for [%s] [%s]",
266 get_oper_name(source_p), temp_time / 60,
267 name, reason);
212380e3 268 ilog(L_KLINE, "R %s %d %s %s",
d8a4c5f6 269 get_oper_name(source_p), temp_time / 60, name, reason);
212380e3 270 sendto_one_notice(source_p, ":Added temporary %d min. RESV [%s]",
d8a4c5f6 271 temp_time / 60, name);
212380e3 272 }
273 else
4cb3ae78
WP
274 {
275 sendto_realops_snomask(SNO_GENERAL, L_ALL,
276 "%s added RESV for [%s] [%s]",
277 get_oper_name(source_p), name, reason);
278 ilog(L_KLINE, "R %s 0 %s %s",
279 get_oper_name(source_p), name, reason);
280 sendto_one_notice(source_p, ":Added RESV [%s]", name);
281
ff0482a9 282 bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0);
4cb3ae78 283 }
9b9d818b
JT
284
285 add_to_resv_hash(aconf->host, aconf);
286 resv_chan_forcepart(aconf->host, aconf->passwd, temp_time);
212380e3 287 }
288 else if(clean_resv_nick(name))
289 {
d8a4c5f6 290 if(strlen(name) > NICKLEN * 2)
212380e3 291 {
d8a4c5f6 292 sendto_one_notice(source_p, ":Invalid RESV length: %s", name);
212380e3 293 return;
294 }
295
296 if(strchr(reason, '"'))
297 {
d8a4c5f6 298 sendto_one_notice(source_p, ":Invalid character '\"' in comment");
212380e3 299 return;
300 }
301
302 if(!valid_wild_card_simple(name))
303 {
304 sendto_one_notice(source_p,
d8a4c5f6
WP
305 ":Please include at least %d non-wildcard "
306 "characters with the resv",
307 ConfigFileEntry.min_nonwildcard_simple);
212380e3 308 return;
309 }
310
0fdb2570 311 if(find_nick_resv_mask(name))
212380e3 312 {
313 sendto_one_notice(source_p,
d8a4c5f6 314 ":A RESV has already been placed on nick: %s", name);
212380e3 315 return;
316 }
317
318 aconf = make_conf();
319 aconf->status = CONF_RESV_NICK;
320 aconf->port = 0;
ce60772d 321 aconf->created = rb_current_time();
ff0482a9 322 aconf->host = rb_strdup(name);
62d28946 323 aconf->passwd = rb_strdup(reason);
a0f4c418 324 aconf->info.oper = operhash_add(get_oper_name(source_p));
212380e3 325
9b9d818b
JT
326 if(propagated)
327 {
328 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
329 aconf->hold = rb_current_time() + temp_time;
330 aconf->lifetime = aconf->hold;
331 replace_old_ban(aconf);
332 rb_dlinkAddAlloc(aconf, &prop_bans);
333
334 sendto_realops_snomask(SNO_GENERAL, L_ALL,
335 "%s added global %d min. RESV for [%s] [%s]",
336 get_oper_name(source_p), temp_time / 60,
337 name, reason);
338 ilog(L_KLINE, "R %s %d %s %s",
339 get_oper_name(source_p), temp_time / 60, name, reason);
340 sendto_one_notice(source_p, ":Added global %d min. RESV [%s]",
341 temp_time / 60, name);
342 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
343 ":%s BAN R * %s %lu %d %d * :%s",
344 source_p->id, aconf->host,
345 (unsigned long)aconf->created,
346 (int)(aconf->hold - aconf->created),
347 (int)(aconf->lifetime - aconf->created),
348 reason);
349 }
350 else if(temp_time > 0)
212380e3 351 {
9f6bbe3c 352 aconf->hold = rb_current_time() + temp_time;
212380e3 353
354 sendto_realops_snomask(SNO_GENERAL, L_ALL,
d8a4c5f6
WP
355 "%s added temporary %d min. RESV for [%s] [%s]",
356 get_oper_name(source_p), temp_time / 60,
357 name, reason);
212380e3 358 ilog(L_KLINE, "R %s %d %s %s",
d8a4c5f6 359 get_oper_name(source_p), temp_time / 60, name, reason);
212380e3 360 sendto_one_notice(source_p, ":Added temporary %d min. RESV [%s]",
d8a4c5f6 361 temp_time / 60, name);
212380e3 362 }
363 else
4cb3ae78
WP
364 {
365 sendto_realops_snomask(SNO_GENERAL, L_ALL,
366 "%s added RESV for [%s] [%s]",
367 get_oper_name(source_p), name, reason);
368 ilog(L_KLINE, "R %s 0 %s %s",
369 get_oper_name(source_p), name, reason);
370 sendto_one_notice(source_p, ":Added RESV [%s]", name);
371
ff0482a9 372 bandb_add(BANDB_RESV, source_p, aconf->host, NULL, aconf->passwd, NULL, 0);
4cb3ae78 373 }
9b9d818b
JT
374
375 rb_dlinkAddAlloc(aconf, &resv_conf_list);
212380e3 376 }
377 else
d8a4c5f6 378 sendto_one_notice(source_p, ":You have specified an invalid resv: [%s]", name);
212380e3 379}
380
d8a4c5f6 381static void
212380e3 382propagate_resv(struct Client *source_p, const char *target,
d8a4c5f6 383 int temp_time, const char *name, const char *reason)
212380e3 384{
385 if(!temp_time)
386 {
387 sendto_match_servs(source_p, target,
d8a4c5f6 388 CAP_CLUSTER, NOCAPS, "RESV %s %s :%s", target, name, reason);
212380e3 389 sendto_match_servs(source_p, target,
d8a4c5f6
WP
390 CAP_ENCAP, CAP_CLUSTER,
391 "ENCAP %s RESV %d %s 0 :%s", target, temp_time, name, reason);
212380e3 392 }
393 else
394 sendto_match_servs(source_p, target,
d8a4c5f6
WP
395 CAP_ENCAP, NOCAPS,
396 "ENCAP %s RESV %d %s 0 :%s", target, temp_time, name, reason);
212380e3 397}
398
399static void
d8a4c5f6 400cluster_resv(struct Client *source_p, int temp_time, const char *name, const char *reason)
212380e3 401{
402 struct remote_conf *shared_p;
08d11e34 403 rb_dlink_node *ptr;
212380e3 404
08d11e34 405 RB_DLINK_FOREACH(ptr, cluster_conf_list.head)
212380e3 406 {
407 shared_p = ptr->data;
408
409 /* old protocol cant handle temps, and we dont really want
410 * to convert them to perm.. --fl
411 */
412 if(!temp_time)
413 {
414 if(!(shared_p->flags & SHARED_PRESV))
415 continue;
416
417 sendto_match_servs(source_p, shared_p->server,
d8a4c5f6
WP
418 CAP_CLUSTER, NOCAPS,
419 "RESV %s %s :%s", shared_p->server, name, reason);
212380e3 420 sendto_match_servs(source_p, shared_p->server,
d8a4c5f6
WP
421 CAP_ENCAP, CAP_CLUSTER,
422 "ENCAP %s RESV 0 %s 0 :%s",
423 shared_p->server, name, reason);
212380e3 424 }
425 else if(shared_p->flags & SHARED_TRESV)
426 sendto_match_servs(source_p, shared_p->server,
d8a4c5f6
WP
427 CAP_ENCAP, NOCAPS,
428 "ENCAP %s RESV %d %s 0 :%s",
429 shared_p->server, temp_time, name, reason);
212380e3 430 }
431}
432
433
434/*
435 * mo_unresv()
d8a4c5f6 436 * parv[0] = sender prefix
212380e3 437 * parv[1] = channel/nick to unforbid
438 */
439static int
440mo_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
441{
9b9d818b
JT
442 int propagated = 1;
443
1ebe6ffc
JT
444 if(!IsOperResv(source_p))
445 {
d8a4c5f6 446 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "resv");
1ebe6ffc
JT
447 return 0;
448 }
449
212380e3 450 if((parc == 4) && (irccmp(parv[2], "ON") == 0))
451 {
452 if(!IsOperRemoteBan(source_p))
453 {
454 sendto_one(source_p, form_str(ERR_NOPRIVS),
d8a4c5f6 455 me.name, source_p->name, "remoteban");
212380e3 456 return 0;
457 }
458
d8a4c5f6 459 propagate_generic(source_p, "UNRESV", parv[3], CAP_CLUSTER, "%s", parv[1]);
212380e3 460
461 if(match(parv[3], me.name) == 0)
462 return 0;
9b9d818b
JT
463
464 propagated = 0;
212380e3 465 }
9b9d818b 466#if 0
08d11e34 467 else if(rb_dlink_list_length(&cluster_conf_list) > 0)
d8a4c5f6 468 cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", parv[1]);
9b9d818b
JT
469#endif
470 /* cluster{} moved to remove_resv */
212380e3 471
9b9d818b 472 remove_resv(source_p, parv[1], propagated);
212380e3 473 return 0;
474}
475
476/* ms_unresv()
d8a4c5f6 477 * parv[0] = sender prefix
212380e3 478 * parv[1] = target server
479 * parv[2] = resv to remove
480 */
481static int
482ms_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
483{
d8a4c5f6
WP
484 /* parv[0] parv[1] parv[2]
485 * oper target server resv to remove
212380e3 486 */
d8a4c5f6 487 propagate_generic(source_p, "UNRESV", parv[1], CAP_CLUSTER, "%s", parv[2]);
212380e3 488
489 if(!match(parv[1], me.name))
490 return 0;
491
492 if(!IsPerson(source_p))
493 return 0;
494
495 handle_remote_unresv(source_p, parv[2]);
496 return 0;
497}
498
499static int
500me_unresv(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
501{
502 /* name */
503 if(!IsPerson(source_p))
504 return 0;
505
506 handle_remote_unresv(source_p, parv[1]);
507 return 0;
508}
509
510static void
511handle_remote_unresv(struct Client *source_p, const char *name)
512{
513 if(!find_shared_conf(source_p->username, source_p->host,
d8a4c5f6 514 source_p->servptr->name, SHARED_UNRESV))
212380e3 515 return;
516
9b9d818b 517 remove_resv(source_p, name, 0);
212380e3 518
519 return;
520}
521
1328da86 522static void
9b9d818b 523remove_resv(struct Client *source_p, const char *name, int propagated)
212380e3 524{
525 struct ConfItem *aconf = NULL;
9b9d818b 526 rb_dlink_node *ptr;
212380e3 527
528 if(IsChannelName(name))
529 {
530 if((aconf = hash_find_resv(name)) == NULL)
1328da86 531 {
9b9d818b
JT
532 if(propagated && rb_dlink_list_length(&cluster_conf_list))
533 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
534
1328da86
JT
535 sendto_one_notice(source_p, ":No RESV for %s", name);
536 return;
537 }
212380e3 538
9b9d818b
JT
539 if(aconf->lifetime)
540 {
541 if(!propagated)
542 {
543 sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name);
544 return;
545 }
546 ptr = rb_dlinkFind(aconf, &prop_bans);
547 if(ptr == NULL)
548 return;
549 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
550 sendto_realops_snomask(SNO_GENERAL, L_ALL,
551 "%s has removed the global RESV for: [%s]",
552 get_oper_name(source_p), name);
553 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
554 if(aconf->created < rb_current_time())
555 aconf->created = rb_current_time();
556 else
557 aconf->created++;
558 aconf->hold = aconf->created;
559 operhash_delete(aconf->info.oper);
560 aconf->info.oper = operhash_add(get_oper_name(source_p));
561 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
562 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
563 ":%s BAN R * %s %lu %d %d * :*",
564 source_p->id, aconf->host,
565 (unsigned long)aconf->created,
566 0,
567 (int)(aconf->lifetime - aconf->created));
568 deactivate_conf(aconf, ptr);
569 return;
570 }
571 else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
572 cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name);
573
ddbd4a81
JT
574 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
575 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
212380e3 576 if(!aconf->hold)
4d9be1a6 577 {
d8a4c5f6 578 bandb_del(BANDB_RESV, aconf->host, NULL);
4d9be1a6
JT
579 sendto_realops_snomask(SNO_GENERAL, L_ALL,
580 "%s has removed the RESV for: [%s]",
581 get_oper_name(source_p), name);
4d9be1a6 582 }
1328da86
JT
583 else
584 {
1328da86 585 sendto_realops_snomask(SNO_GENERAL, L_ALL,
ddbd4a81 586 "%s has removed the temporary RESV for: [%s]",
d8a4c5f6 587 get_oper_name(source_p), name);
1328da86 588 }
212380e3 589 del_from_resv_hash(name, aconf);
212380e3 590 }
591 else
592 {
08d11e34 593 RB_DLINK_FOREACH(ptr, resv_conf_list.head)
212380e3 594 {
595 aconf = ptr->data;
596
ff0482a9 597 if(irccmp(aconf->host, name))
212380e3 598 aconf = NULL;
599 else
600 break;
601 }
602
603 if(aconf == NULL)
1328da86 604 {
9b9d818b
JT
605 if(propagated && rb_dlink_list_length(&cluster_conf_list))
606 cluster_generic(source_p, "UNXLINE", SHARED_UNXLINE, CAP_CLUSTER, "%s", name);
607
1328da86
JT
608 sendto_one_notice(source_p, ":No RESV for %s", name);
609 return;
610 }
212380e3 611
9b9d818b
JT
612 if(aconf->lifetime)
613 {
614 if(!propagated)
615 {
616 sendto_one_notice(source_p, ":Cannot remove global RESV %s on specific servers", name);
617 return;
618 }
619 ptr = rb_dlinkFind(aconf, &prop_bans);
620 if(ptr == NULL)
621 return;
622 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
623 sendto_realops_snomask(SNO_GENERAL, L_ALL,
624 "%s has removed the global RESV for: [%s]",
625 get_oper_name(source_p), name);
626 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
627 if(aconf->created < rb_current_time())
628 aconf->created = rb_current_time();
629 else
630 aconf->created++;
631 aconf->hold = aconf->created;
632 operhash_delete(aconf->info.oper);
633 aconf->info.oper = operhash_add(get_oper_name(source_p));
634 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
635 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
636 ":%s BAN R * %s %lu %d %d * :*",
637 source_p->id, aconf->host,
638 (unsigned long)aconf->created,
639 0,
640 (int)(aconf->lifetime - aconf->created));
641 deactivate_conf(aconf, ptr);
642 return;
643 }
644 else if(propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
645 cluster_generic(source_p, "UNRESV", SHARED_UNRESV, CAP_CLUSTER, "%s", name);
646
7bf8ae67
JT
647 sendto_one_notice(source_p, ":RESV for [%s] is removed", name);
648 ilog(L_KLINE, "UR %s %s", get_oper_name(source_p), name);
212380e3 649 if(!aconf->hold)
7bf8ae67 650 {
d8a4c5f6 651 bandb_del(BANDB_RESV, aconf->host, NULL);
7bf8ae67
JT
652 sendto_realops_snomask(SNO_GENERAL, L_ALL,
653 "%s has removed the RESV for: [%s]",
654 get_oper_name(source_p), name);
655 }
1328da86
JT
656 else
657 {
1328da86 658 sendto_realops_snomask(SNO_GENERAL, L_ALL,
7bf8ae67 659 "%s has removed the temporary RESV for: [%s]",
d8a4c5f6 660 get_oper_name(source_p), name);
1328da86 661 }
212380e3 662 /* already have ptr from the loop above.. */
9f6c3353 663 rb_dlinkDestroy(ptr, &resv_conf_list);
212380e3 664 }
1328da86 665 free_conf(aconf);
212380e3 666
1328da86 667 return;
212380e3 668}