]> jfr.im git - solanum.git/blame_incremental - modules/m_kline.c
extensions: add AV2 description strings to a few modules
[solanum.git] / modules / m_kline.c
... / ...
CommitLineData
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_kline.c: Bans/unbans a user.
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
23 */
24
25#include "stdinc.h"
26#include "channel.h"
27#include "class.h"
28#include "client.h"
29#include "common.h"
30#include "match.h"
31#include "ircd.h"
32#include "hostmask.h"
33#include "numeric.h"
34#include "s_conf.h"
35#include "s_newconf.h"
36#include "logger.h"
37#include "send.h"
38#include "hash.h"
39#include "s_serv.h"
40#include "msg.h"
41#include "parse.h"
42#include "modules.h"
43#include "reject.h"
44#include "bandbi.h"
45#include "operhash.h"
46
47static int mo_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
48static int ms_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
49static int me_kline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
50static int mo_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
51static int ms_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
52static int me_unkline(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
53
54struct Message kline_msgtab = {
55 "KLINE", 0, 0, 0, 0,
56 {mg_unreg, mg_not_oper, {ms_kline, 5}, {ms_kline, 5}, {me_kline, 5}, {mo_kline, 3}}
57};
58
59struct Message unkline_msgtab = {
60 "UNKLINE", 0, 0, 0, 0,
61 {mg_unreg, mg_not_oper, {ms_unkline, 4}, {ms_unkline, 4}, {me_unkline, 3}, {mo_unkline, 2}}
62};
63
64mapi_clist_av1 kline_clist[] = { &kline_msgtab, &unkline_msgtab, NULL };
65
66DECLARE_MODULE_AV2(kline, NULL, NULL, kline_clist, NULL, NULL, NULL, NULL, NULL);
67
68/* Local function prototypes */
69static int find_user_host(struct Client *source_p, const char *userhost, char *user, char *host);
70static int valid_user_host(struct Client *source_p, const char *user, const char *host);
71
72static void handle_remote_kline(struct Client *source_p, int tkline_time,
73 const char *user, const char *host, const char *reason);
74static void apply_kline(struct Client *source_p, struct ConfItem *aconf,
75 const char *reason, const char *oper_reason);
76static void apply_tkline(struct Client *source_p, struct ConfItem *aconf,
77 const char *, const char *, int);
78static void apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
79 const char *, const char *, int);
80static int already_placed_kline(struct Client *, const char *, const char *, int);
81
82static void handle_remote_unkline(struct Client *source_p, const char *user, const char *host);
83static void remove_permkline_match(struct Client *, struct ConfItem *);
84static int remove_temp_kline(struct Client *, struct ConfItem *);
85static void remove_prop_kline(struct Client *, struct ConfItem *);
86
87/* mo_kline()
88 *
89 * parv[1] - temp time or user@host
90 * parv[2] - user@host, "ON", or reason
91 * parv[3] - "ON", reason, or server to target
92 * parv[4] - server to target, or reason
93 * parv[5] - reason
94 */
95static int
96mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char **parv)
97{
98 char def[] = "No Reason";
99 char user[USERLEN + 2];
100 char host[HOSTLEN + 2];
101 char *reason = def;
102 char *oper_reason;
103 const char *target_server = NULL;
104 struct ConfItem *aconf;
105 int tkline_time = 0;
106 int loc = 1;
107 int propagated = ConfigFileEntry.use_propagated_bans;
108
109 if(!IsOperK(source_p))
110 {
111 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "kline");
112 return 0;
113 }
114
115 if((tkline_time = valid_temp_time(parv[loc])) >= 0)
116 loc++;
117 /* we just set tkline_time to -1! */
118 else
119 tkline_time = 0;
120
121 if(find_user_host(source_p, parv[loc], user, host) == 0)
122 return 0;
123
124 loc++;
125
126 if(parc >= loc + 2 && !irccmp(parv[loc], "ON"))
127 {
128 if(!IsOperRemoteBan(source_p))
129 {
130 sendto_one(source_p, form_str(ERR_NOPRIVS),
131 me.name, source_p->name, "remoteban");
132 return 0;
133 }
134
135 target_server = parv[loc + 1];
136 loc += 2;
137 }
138
139 if(parc <= loc || EmptyString(parv[loc]))
140 {
141 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
142 me.name, source_p->name, "KLINE");
143 return 0;
144 }
145
146 reason = LOCAL_COPY(parv[loc]);
147
148 if(target_server != NULL)
149 {
150 propagate_generic(source_p, "KLINE", target_server, CAP_KLN,
151 "%d %s %s :%s", tkline_time, user, host, reason);
152
153 /* If we are sending it somewhere that doesnt include us, stop */
154 if(!match(target_server, me.name))
155 return 0;
156
157 /* Set as local-only. */
158 propagated = 0;
159 }
160 /* if we have cluster servers, send it to them.. */
161 else if(!propagated && rb_dlink_list_length(&cluster_conf_list) > 0)
162 cluster_generic(source_p, "KLINE",
163 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE, CAP_KLN,
164 "%lu %s %s :%s", tkline_time, user, host, reason);
165
166 if(!valid_user_host(source_p, user, host))
167 return 0;
168
169 if(!valid_wild_card(user, host))
170 {
171 sendto_one_notice(source_p,
172 ":Please include at least %d non-wildcard "
173 "characters with the user@host",
174 ConfigFileEntry.min_nonwildcard);
175 return 0;
176 }
177
178 if(propagated && tkline_time == 0)
179 {
180 sendto_one_notice(source_p, ":Cannot set a permanent global ban");
181 return 0;
182 }
183
184 if(already_placed_kline(source_p, user, host, tkline_time))
185 return 0;
186
187 rb_set_time();
188 aconf = make_conf();
189 aconf->status = CONF_KILL;
190 aconf->created = rb_current_time();
191 aconf->host = rb_strdup(host);
192 aconf->user = rb_strdup(user);
193 aconf->port = 0;
194 aconf->info.oper = operhash_add(get_oper_name(source_p));
195
196 if(strlen(reason) > BANREASONLEN)
197 reason[BANREASONLEN] = '\0';
198
199 /* Look for an oper reason */
200 if((oper_reason = strchr(reason, '|')) != NULL)
201 {
202 *oper_reason = '\0';
203 oper_reason++;
204
205 if(!EmptyString(oper_reason))
206 aconf->spasswd = rb_strdup(oper_reason);
207 }
208 aconf->passwd = rb_strdup(reason);
209
210 if(propagated)
211 apply_prop_kline(source_p, aconf, reason, oper_reason, tkline_time);
212 else if(tkline_time > 0)
213 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
214 else
215 apply_kline(source_p, aconf, reason, oper_reason);
216
217 if(ConfigFileEntry.kline_delay)
218 {
219 if(kline_queued == 0)
220 {
221 rb_event_addonce("check_klines", check_klines_event, NULL,
222 ConfigFileEntry.kline_delay);
223 kline_queued = 1;
224 }
225 }
226 else
227 check_klines();
228
229 return 0;
230}
231
232/* ms_kline()
233 *
234 * parv[1] - server targeted at
235 * parv[2] - tkline time (0 if perm)
236 * parv[3] - user
237 * parv[4] - host
238 * parv[5] - reason
239 */
240static int
241ms_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
242{
243 int tkline_time = atoi(parv[2]);
244
245 /* 1.5-3 and earlier contains a bug that allows remote klines to be
246 * sent with an empty reason field. This is a protocol violation,
247 * but its not worth dropping the link over.. --anfl
248 */
249 if(parc < 6 || EmptyString(parv[5]))
250 return 0;
251
252 propagate_generic(source_p, "KLINE", parv[1], CAP_KLN,
253 "%d %s %s :%s", tkline_time, parv[3], parv[4], parv[5]);
254
255 if(!match(parv[1], me.name))
256 return 0;
257
258 if(!IsPerson(source_p))
259 return 0;
260
261 handle_remote_kline(source_p, tkline_time, parv[3], parv[4], parv[5]);
262 return 0;
263}
264
265static int
266me_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
267{
268 /* <tkline_time> <user> <host> :<reason> */
269 if(!IsPerson(source_p))
270 return 0;
271
272 handle_remote_kline(source_p, atoi(parv[1]), parv[2], parv[3], parv[4]);
273 return 0;
274}
275
276static void
277handle_remote_kline(struct Client *source_p, int tkline_time,
278 const char *user, const char *host, const char *kreason)
279{
280 char *reason = LOCAL_COPY(kreason);
281 struct ConfItem *aconf = NULL;
282 char *oper_reason;
283
284 if(!find_shared_conf(source_p->username, source_p->host,
285 source_p->servptr->name,
286 (tkline_time > 0) ? SHARED_TKLINE : SHARED_PKLINE))
287 return;
288
289 if(!valid_user_host(source_p, user, host))
290 return;
291
292 if(!valid_wild_card(user, host))
293 {
294 sendto_one_notice(source_p,
295 ":Please include at least %d non-wildcard "
296 "characters with the user@host",
297 ConfigFileEntry.min_nonwildcard);
298 return;
299 }
300
301 if(already_placed_kline(source_p, user, host, tkline_time))
302 return;
303
304 aconf = make_conf();
305
306 aconf->status = CONF_KILL;
307 aconf->created = rb_current_time();
308 aconf->user = rb_strdup(user);
309 aconf->host = rb_strdup(host);
310 aconf->info.oper = operhash_add(get_oper_name(source_p));
311
312 if(strlen(reason) > BANREASONLEN)
313 reason[BANREASONLEN] = '\0';
314
315 /* Look for an oper reason */
316 if((oper_reason = strchr(reason, '|')) != NULL)
317 {
318 *oper_reason = '\0';
319 oper_reason++;
320
321 if(!EmptyString(oper_reason))
322 aconf->spasswd = rb_strdup(oper_reason);
323 }
324 aconf->passwd = rb_strdup(reason);
325
326 if(tkline_time > 0)
327 apply_tkline(source_p, aconf, reason, oper_reason, tkline_time);
328 else
329 apply_kline(source_p, aconf, reason, oper_reason);
330
331 if(ConfigFileEntry.kline_delay)
332 {
333 if(kline_queued == 0)
334 {
335 rb_event_addonce("check_klines", check_klines_event, NULL,
336 ConfigFileEntry.kline_delay);
337 kline_queued = 1;
338 }
339 }
340 else
341 check_klines();
342
343 return;
344}
345
346/* mo_unkline()
347 *
348 * parv[1] - kline to remove
349 * parv[2] - optional "ON"
350 * parv[3] - optional target server
351 */
352static int
353mo_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
354{
355 const char *user;
356 char *host;
357 char splat[] = "*";
358 char *h = LOCAL_COPY(parv[1]);
359 struct ConfItem *aconf;
360 int propagated = 1;
361
362 if(!IsOperUnkline(source_p))
363 {
364 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "unkline");
365 return 0;
366 }
367
368 if((host = strchr(h, '@')) || *h == '*' || strchr(h, '.') || strchr(h, ':'))
369 {
370 /* Explicit user@host mask given */
371
372 if(host) /* Found user@host */
373 {
374 *host++ = '\0';
375
376 /* check for @host */
377 if(*h)
378 user = h;
379 else
380 user = splat;
381
382 /* check for user@ */
383 if(!*host)
384 host = splat;
385 }
386 else
387 {
388 user = splat; /* no @ found, assume its *@somehost */
389 host = h;
390 }
391 }
392 else
393 {
394 sendto_one_notice(source_p, ":Invalid parameters");
395 return 0;
396 }
397
398 /* possible remote kline.. */
399 if((parc > 3) && (irccmp(parv[2], "ON") == 0))
400 {
401 if(!IsOperRemoteBan(source_p))
402 {
403 sendto_one(source_p, form_str(ERR_NOPRIVS),
404 me.name, source_p->name, "remoteban");
405 return 0;
406 }
407
408 propagate_generic(source_p, "UNKLINE", parv[3], CAP_UNKLN, "%s %s", user, host);
409
410 if(match(parv[3], me.name) == 0)
411 return 0;
412
413 propagated = 0;
414 }
415
416 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
417
418 /* No clustering for removing a propagated kline */
419 if(propagated && (aconf == NULL || !aconf->lifetime) &&
420 rb_dlink_list_length(&cluster_conf_list) > 0)
421 cluster_generic(source_p, "UNKLINE", SHARED_UNKLINE, CAP_UNKLN,
422 "%s %s", user, host);
423
424 if(aconf == NULL)
425 {
426 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
427 return 0;
428 }
429
430 if(aconf->lifetime)
431 {
432 if(propagated)
433 remove_prop_kline(source_p, aconf);
434 else
435 sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
436 return 0;
437 }
438
439 if(remove_temp_kline(source_p, aconf))
440 return 0;
441
442 remove_permkline_match(source_p, aconf);
443
444 return 0;
445}
446
447/* ms_unkline()
448 *
449 * parv[1] - target server
450 * parv[2] - user to unkline
451 * parv[3] - host to unkline
452 */
453static int
454ms_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
455{
456 /* parv[0] parv[1] parv[2] parv[3]
457 * oper target server user host */
458 propagate_generic(source_p, "UNKLINE", parv[1], CAP_UNKLN, "%s %s", parv[2], parv[3]);
459
460 if(!match(parv[1], me.name))
461 return 0;
462
463 if(!IsPerson(source_p))
464 return 0;
465
466 handle_remote_unkline(source_p, parv[2], parv[3]);
467 return 0;
468}
469
470static int
471me_unkline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
472{
473 /* user host */
474 if(!IsPerson(source_p))
475 return 0;
476
477 handle_remote_unkline(source_p, parv[1], parv[2]);
478 return 0;
479}
480
481static void
482handle_remote_unkline(struct Client *source_p, const char *user, const char *host)
483{
484 struct ConfItem *aconf;
485
486 if(!find_shared_conf(source_p->username, source_p->host,
487 source_p->servptr->name, SHARED_UNKLINE))
488 return;
489
490 aconf = find_exact_conf_by_address(host, CONF_KILL, user);
491 if(aconf == NULL)
492 {
493 sendto_one_notice(source_p, ":No K-Line for %s@%s", user, host);
494 return;
495 }
496 if(aconf->lifetime)
497 {
498 sendto_one_notice(source_p, ":Cannot remove global K-Line %s@%s on specific servers", user, host);
499 return;
500 }
501
502 if(remove_temp_kline(source_p, aconf))
503 return;
504
505 remove_permkline_match(source_p, aconf);
506}
507
508/* apply_kline()
509 *
510 * inputs -
511 * output - NONE
512 * side effects - kline as given, is added to the hashtable
513 * and conf file
514 */
515static void
516apply_kline(struct Client *source_p, struct ConfItem *aconf,
517 const char *reason, const char *oper_reason)
518{
519 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
520 bandb_add(BANDB_KLINE, source_p, aconf->user, aconf->host,
521 reason, EmptyString(oper_reason) ? NULL : oper_reason, 0);
522
523 /* no oper reason.. */
524 if(EmptyString(oper_reason))
525 {
526 sendto_realops_snomask(SNO_GENERAL, L_ALL,
527 "%s added K-Line for [%s@%s] [%s]",
528 get_oper_name(source_p), aconf->user, aconf->host, reason);
529 ilog(L_KLINE, "K %s 0 %s %s %s",
530 get_oper_name(source_p), aconf->user, aconf->host, reason);
531 }
532 else
533 {
534 sendto_realops_snomask(SNO_GENERAL, L_ALL,
535 "%s added K-Line for [%s@%s] [%s|%s]",
536 get_oper_name(source_p), aconf->user, aconf->host,
537 reason, oper_reason);
538 ilog(L_KLINE, "K %s 0 %s %s %s|%s",
539 get_oper_name(source_p), aconf->user, aconf->host, reason, oper_reason);
540 }
541
542 sendto_one_notice(source_p, ":Added K-Line [%s@%s]",
543 aconf->user, aconf->host);
544}
545
546/* apply_tkline()
547 *
548 * inputs -
549 * output - NONE
550 * side effects - tkline as given is placed
551 */
552static void
553apply_tkline(struct Client *source_p, struct ConfItem *aconf,
554 const char *reason, const char *oper_reason, int tkline_time)
555{
556 aconf->hold = rb_current_time() + tkline_time;
557 add_temp_kline(aconf);
558
559 /* no oper reason.. */
560 if(EmptyString(oper_reason))
561 {
562 sendto_realops_snomask(SNO_GENERAL, L_ALL,
563 "%s added temporary %d min. K-Line for [%s@%s] [%s]",
564 get_oper_name(source_p), tkline_time / 60,
565 aconf->user, aconf->host, reason);
566 ilog(L_KLINE, "K %s %d %s %s %s",
567 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
568 }
569 else
570 {
571 sendto_realops_snomask(SNO_GENERAL, L_ALL,
572 "%s added temporary %d min. K-Line for [%s@%s] [%s|%s]",
573 get_oper_name(source_p), tkline_time / 60,
574 aconf->user, aconf->host, reason, oper_reason);
575 ilog(L_KLINE, "K %s %d %s %s %s|%s",
576 get_oper_name(source_p), tkline_time / 60,
577 aconf->user, aconf->host, reason, oper_reason);
578 }
579
580 sendto_one_notice(source_p, ":Added temporary %d min. K-Line [%s@%s]",
581 tkline_time / 60, aconf->user, aconf->host);
582}
583
584static void
585apply_prop_kline(struct Client *source_p, struct ConfItem *aconf,
586 const char *reason, const char *oper_reason, int tkline_time)
587{
588 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
589 aconf->hold = rb_current_time() + tkline_time;
590 aconf->lifetime = aconf->hold;
591
592 replace_old_ban(aconf);
593
594 rb_dlinkAddAlloc(aconf, &prop_bans);
595 add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
596
597 /* no oper reason.. */
598 if(EmptyString(oper_reason))
599 {
600 sendto_realops_snomask(SNO_GENERAL, L_ALL,
601 "%s added global %d min. K-Line for [%s@%s] [%s]",
602 get_oper_name(source_p), tkline_time / 60,
603 aconf->user, aconf->host, reason);
604 ilog(L_KLINE, "K %s %d %s %s %s",
605 get_oper_name(source_p), tkline_time / 60, aconf->user, aconf->host, reason);
606 }
607 else
608 {
609 sendto_realops_snomask(SNO_GENERAL, L_ALL,
610 "%s added global %d min. K-Line for [%s@%s] [%s|%s]",
611 get_oper_name(source_p), tkline_time / 60,
612 aconf->user, aconf->host, reason, oper_reason);
613 ilog(L_KLINE, "K %s %d %s %s %s|%s",
614 get_oper_name(source_p), tkline_time / 60,
615 aconf->user, aconf->host, reason, oper_reason);
616 }
617
618 sendto_one_notice(source_p, ":Added global %d min. K-Line [%s@%s]",
619 tkline_time / 60, aconf->user, aconf->host);
620
621 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
622 ":%s BAN K %s %s %lu %d %d * :%s%s%s",
623 source_p->id, aconf->user, aconf->host,
624 (unsigned long)aconf->created,
625 (int)(aconf->hold - aconf->created),
626 (int)(aconf->lifetime - aconf->created),
627 reason,
628 oper_reason ? "|" : "",
629 oper_reason ? oper_reason : "");
630}
631
632/* find_user_host()
633 *
634 * inputs - client placing kline, user@host, user buffer, host buffer
635 * output - 0 if not ok to kline, 1 to kline i.e. if valid user host
636 * side effects -
637 */
638static int
639find_user_host(struct Client *source_p, const char *userhost, char *luser, char *lhost)
640{
641 char *hostp;
642
643 hostp = strchr(userhost, '@');
644
645 if(hostp != NULL) /* I'm a little user@host */
646 {
647 *(hostp++) = '\0'; /* short and squat */
648 if(*userhost)
649 rb_strlcpy(luser, userhost, USERLEN + 1); /* here is my user */
650 else
651 strcpy(luser, "*");
652 if(*hostp)
653 rb_strlcpy(lhost, hostp, HOSTLEN + 1); /* here is my host */
654 else
655 strcpy(lhost, "*");
656 }
657 else
658 {
659 /* no '@', no '.', so its not a user@host or host, therefore
660 * its a nick, which support was removed for.
661 */
662 if(strchr(userhost, '.') == NULL && strchr(userhost, ':') == NULL)
663 {
664 sendto_one_notice(source_p, ":K-Line must be a user@host or host");
665 return 0;
666 }
667
668 luser[0] = '*'; /* no @ found, assume its *@somehost */
669 luser[1] = '\0';
670 rb_strlcpy(lhost, userhost, HOSTLEN + 1);
671 }
672
673 /* would break the protocol */
674 if (*luser == ':' || *lhost == ':')
675 {
676 sendto_one_notice(source_p, ":Invalid K-Line");
677 return 0;
678 }
679
680 return 1;
681}
682
683/* valid_user_host()
684 *
685 * inputs - user buffer, host buffer
686 * output - 0 if invalid, 1 if valid
687 * side effects -
688 */
689static int
690valid_user_host(struct Client *source_p, const char *luser, const char *lhost)
691{
692 /* # is invalid, as are '!' (n!u@h kline) and '@' (u@@h kline) */
693 if(strchr(lhost, '#') || strchr(luser, '#') || strchr(luser, '!') || strchr(lhost, '@'))
694 {
695 sendto_one_notice(source_p, ":Invalid K-Line");
696 return 0;
697 }
698
699 return 1;
700}
701
702/* already_placed_kline()
703 *
704 * inputs - source to notify, user@host to check, tkline time
705 * outputs - 1 if a perm kline or a tkline when a tkline is being
706 * set exists, else 0
707 * side effects - notifies source_p kline exists
708 */
709/* Note: This currently works if the new K-line is a special case of an
710 * existing K-line, but not the other way round. To do that we would
711 * have to walk the hash and check every existing K-line. -A1kmm.
712 */
713static int
714already_placed_kline(struct Client *source_p, const char *luser, const char *lhost, int tkline)
715{
716 const char *reason, *p;
717 struct rb_sockaddr_storage iphost, *piphost;
718 struct ConfItem *aconf;
719 int t, bits;
720
721 aconf = find_exact_conf_by_address(lhost, CONF_KILL, luser);
722 if(aconf == NULL && ConfigFileEntry.non_redundant_klines)
723 {
724 bits = 0;
725 if((t = parse_netmask(lhost, &iphost, &bits)) != HM_HOST)
726 {
727#ifdef RB_IPV6
728 if(t == HM_IPV6)
729 t = AF_INET6;
730 else
731#endif
732 t = AF_INET;
733
734 piphost = &iphost;
735 }
736 else
737 piphost = NULL;
738
739 aconf = find_conf_by_address(lhost, NULL, NULL, (struct sockaddr *) piphost,
740 CONF_KILL, t, luser, NULL);
741 if(aconf != NULL)
742 {
743 /* The above was really a lookup of a single IP,
744 * so check if the new kline is wider than the
745 * existing one.
746 * -- jilles
747 */
748 p = strchr(aconf->host, '/');
749 if(bits > 0 && (p == NULL || bits < atoi(p + 1)))
750 aconf = NULL;
751 }
752 }
753 if(aconf != NULL)
754 {
755 /* setting a tkline, or existing one is perm */
756 if(tkline || ((aconf->flags & CONF_FLAGS_TEMPORARY) == 0))
757 {
758 reason = aconf->passwd ? aconf->passwd : "<No Reason>";
759
760 sendto_one_notice(source_p,
761 ":[%s@%s] already K-Lined by [%s@%s] - %s",
762 luser, lhost, aconf->user, aconf->host, reason);
763 return 1;
764 }
765 }
766
767 return 0;
768}
769
770/* remove_permkline_match()
771 *
772 * hunts for a permanent kline, and removes it.
773 */
774static void
775remove_permkline_match(struct Client *source_p, struct ConfItem *aconf)
776{
777 sendto_one_notice(source_p, ":K-Line for [%s@%s] is removed", aconf->user, aconf->host);
778
779 sendto_realops_snomask(SNO_GENERAL, L_ALL,
780 "%s has removed the K-Line for: [%s@%s]",
781 get_oper_name(source_p), aconf->user, aconf->host);
782
783 ilog(L_KLINE, "UK %s %s %s", get_oper_name(source_p), aconf->user, aconf->host);
784
785 remove_reject_mask(aconf->user, aconf->host);
786 bandb_del(BANDB_KLINE, aconf->user, aconf->host);
787 delete_one_address_conf(aconf->host, aconf);
788
789 return;
790}
791
792/* remove_temp_kline()
793 *
794 * inputs - username, hostname to unkline
795 * outputs -
796 * side effects - tries to unkline anything that matches
797 */
798static int
799remove_temp_kline(struct Client *source_p, struct ConfItem *aconf)
800{
801 rb_dlink_node *ptr;
802 int i;
803
804 for(i = 0; i < LAST_TEMP_TYPE; i++)
805 {
806 RB_DLINK_FOREACH(ptr, temp_klines[i].head)
807 {
808 if(aconf == ptr->data)
809 {
810 sendto_one_notice(source_p,
811 ":Un-klined [%s@%s] from temporary k-lines",
812 aconf->user, aconf->host);
813 sendto_realops_snomask(SNO_GENERAL, L_ALL,
814 "%s has removed the temporary K-Line for: [%s@%s]",
815 get_oper_name(source_p), aconf->user,
816 aconf->host);
817
818 ilog(L_KLINE, "UK %s %s %s",
819 get_oper_name(source_p), aconf->user, aconf->host);
820 rb_dlinkDestroy(ptr, &temp_klines[i]);
821 remove_reject_mask(aconf->user, aconf->host);
822 delete_one_address_conf(aconf->host, aconf);
823 return YES;
824 }
825 }
826 }
827
828 return NO;
829}
830
831static void
832remove_prop_kline(struct Client *source_p, struct ConfItem *aconf)
833{
834 rb_dlink_node *ptr;
835 time_t now;
836
837 ptr = rb_dlinkFind(aconf, &prop_bans);
838 if (!ptr)
839 return;
840 sendto_one_notice(source_p,
841 ":Un-klined [%s@%s] from global k-lines",
842 aconf->user, aconf->host);
843 sendto_realops_snomask(SNO_GENERAL, L_ALL,
844 "%s has removed the global K-Line for: [%s@%s]",
845 get_oper_name(source_p), aconf->user,
846 aconf->host);
847
848 ilog(L_KLINE, "UK %s %s %s",
849 get_oper_name(source_p), aconf->user, aconf->host);
850 now = rb_current_time();
851 if(aconf->created < now)
852 aconf->created = now;
853 else
854 aconf->created++;
855 aconf->hold = aconf->created;
856 operhash_delete(aconf->info.oper);
857 aconf->info.oper = operhash_add(get_oper_name(source_p));
858 aconf->flags |= CONF_FLAGS_MYOPER | CONF_FLAGS_TEMPORARY;
859 sendto_server(NULL, NULL, CAP_BAN|CAP_TS6, NOCAPS,
860 ":%s BAN K %s %s %lu %d %d * :*",
861 source_p->id, aconf->user, aconf->host,
862 (unsigned long)aconf->created,
863 0,
864 (int)(aconf->lifetime - aconf->created));
865 remove_reject_mask(aconf->user, aconf->host);
866 deactivate_conf(aconf, ptr, now);
867}