Author: Kev <klmitch@mit.edu>
[ircu2.10.12-pk.git] / ircd / gline.c
1 /*
2  * IRC - Internet Relay Chat, ircd/gline.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Finland
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 1, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * $Id$
21  */
22 #include "gline.h"
23 #include "client.h"
24 #include "ircd.h"
25 #include "ircd_alloc.h"
26 #include "ircd_reply.h"
27 #include "ircd_string.h"
28 #include "match.h"
29 #include "numeric.h"
30 #include "s_bsd.h"
31 #include "s_misc.h"
32 #include "send.h"
33 #include "struct.h"
34 #include "support.h"
35 #include "msg.h"
36 #include "numnicks.h"
37 #include "numeric.h"
38 #include "sys.h"    /* FALSE bleah */
39
40 #include <assert.h>
41 #include <string.h>
42
43 struct Gline* GlobalGlineList  = 0;
44 struct Gline* BadChanGlineList = 0;
45
46 static void
47 canon_userhost(char *userhost, char **user_p, char **host_p, char *def_user)
48 {
49   char *tmp;
50
51   if (!(tmp = strchr(userhost, '@'))) {
52     *user_p = def_user;
53     *host_p = userhost;
54   } else {
55     *user_p = userhost;
56     *(tmp++) = '\0';
57     *host_p = tmp;
58   }
59 }
60
61 static struct Gline *
62 make_gline(char *userhost, char *reason, time_t expire, time_t lastmod,
63            unsigned int flags)
64 {
65   struct Gline *gline;
66   char *user, *host;
67
68   gline = (struct Gline *)MyMalloc(sizeof(struct Gline)); /* alloc memory */
69   assert(0 != gline);
70
71   DupString(gline->gl_reason, reason); /* initialize gline... */
72   gline->gl_expire = expire;
73   gline->gl_lastmod = lastmod;
74   gline->gl_flags = flags & GLINE_MASK;
75
76   if (flags & GLINE_BADCHAN) { /* set a BADCHAN gline */
77     DupString(gline->gl_user, userhost); /* first, remember channel */
78     gline->gl_host = 0;
79
80     gline->gl_next = BadChanGlineList; /* then link it into list */
81     gline->gl_prev_p = &BadChanGlineList;
82     if (BadChanGlineList)
83       BadChanGlineList->gl_prev_p = &gline->gl_next;
84     BadChanGlineList = gline;
85   } else {
86     canon_userhost(userhost, &user, &host, "*"); /* find user and host */
87
88     DupString(gline->gl_user, user); /* remember them... */
89     DupString(gline->gl_host, host);
90
91     if (check_if_ipmask(host)) /* mark if it's an IP mask */
92       gline->gl_flags |= GLINE_IPMASK;
93
94     gline->gl_next = GlobalGlineList; /* then link it into list */
95     gline->gl_prev_p = &GlobalGlineList;
96     if (GlobalGlineList)
97       GlobalGlineList->gl_prev_p = &gline->gl_next;
98     GlobalGlineList = gline;
99   }
100
101   return gline;
102 }
103
104 static int
105 do_gline(struct Client *cptr, struct Client *sptr, struct Gline *gline)
106 {
107   struct Client *acptr;
108   int fd, retval = 0, tval;
109
110   if (!GlineIsActive(gline)) /* no action taken on inactive glines */
111     return 0;
112
113   for (fd = HighestFd; fd >= 0; --fd) {
114     /*
115      * get the users!
116      */
117     if ((acptr = LocalClientArray[fd])) {
118       if (!acptr->user)
119         continue;
120
121       if ((GlineIsIpMask(gline) ? match(gline->gl_host, acptr->sock_ip) :
122            match(gline->gl_host, acptr->sockhost)) == 0 &&
123           (!acptr->user->username ||
124            match(gline->gl_user, acptr->user->username) == 0)) {
125         /* ok, here's one that got G-lined */
126         sendto_one(acptr, ":%s %d %s :*** %s.", me.name, ERR_YOUREBANNEDCREEP,
127                    acptr->name, gline->gl_reason);
128
129         /* let the ops know about it */
130         sendto_op_mask(SNO_GLINE, "G-line active for %s",
131                        get_client_name(acptr, FALSE));
132
133         /* and get rid of him */
134         if ((tval = exit_client_msg(cptr, acptr, &me, "G-lined (%s)",
135                                     gline->gl_reason)))
136           retval = tval; /* retain killed status */
137       }
138     }
139   }
140
141   return retval;
142 }
143
144 static void
145 propagate_gline(struct Client *cptr, struct Client *sptr, struct Gline *gline)
146 {
147   if (GlineIsLocal(gline)) /* don't propagate local glines */
148     return;
149
150   if (IsUser(sptr)) { /* select appropriate source */
151     if (!gline->gl_lastmod)
152       return;
153     sendto_serv_butone(cptr, "%s%s " TOK_GLINE " * %c%s%s%s " TIME_T_FMT " "
154                        TIME_T_FMT " :%s", NumNick(sptr),
155                        GlineIsActive(gline) ? '+' : '-', gline->gl_user,
156                        GlineIsBadChan(gline) ? "" : "@",
157                        GlineIsBadChan(gline) ? "" : gline->gl_host,
158                        gline->gl_expire - TStime(), gline->gl_lastmod,
159                        gline->gl_reason);
160   } else {
161     if (gline->gl_lastmod)
162       sendto_serv_butone(cptr, "%s " TOK_GLINE " * %c%s%s%s " TIME_T_FMT " "
163                          TIME_T_FMT " :%s", NumServ(sptr),
164                          GlineIsActive(gline) ? '+' : '-', gline->gl_user,
165                          GlineIsBadChan(gline) ? "" : "@",
166                          GlineIsBadChan(gline) ? "" : gline->gl_host,
167                          gline->gl_expire - TStime(), gline->gl_lastmod,
168                          gline->gl_reason);
169     else
170       sendto_serv_butone(cptr, "%s " TOK_GLINE " * %c%s%s%s " TIME_T_FMT
171                          " :%s", NumServ(sptr),
172                          GlineIsActive(gline) ? '+' : '-', gline->gl_user,
173                          GlineIsBadChan(gline) ? "" : "@",
174                          GlineIsBadChan(gline) ? "" : gline->gl_host,
175                          gline->gl_expire - TStime(), gline->gl_reason);
176   }
177 }
178
179 int 
180 gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
181           char *reason, time_t expire, time_t lastmod, unsigned int flags)
182 {
183   struct Gline *agline;
184
185   assert(0 != userhost);
186   assert(0 != reason);
187
188   /*
189    * You cannot set a negative (or zero) expire time, nor can you set an
190    * expiration time for greater than GLINE_MAX_EXPIRE.
191    */
192   if (!(flags & GLINE_FORCE) && (expire <= 0 || expire > GLINE_MAX_EXPIRE)) {
193     if (!IsServer(sptr) && MyConnect(sptr))
194       send_error_to_client(sptr, ERR_BADEXPIRE, expire);
195     return 0;
196   }
197
198   expire += TStime(); /* convert from lifetime to timestamp */
199
200   /* NO_OLD_GLINE allows *@#channel to work correctly */
201 #ifdef BADCHAN
202   if (*userhost == '#' || *userhost == '&' || *userhost == '+'
203 # ifndef NO_OLD_GLINE
204       || userhost[2] == '#' || userhost[2] == '&' || userhost[2] == '+'
205 # endif /* OLD_GLINE */
206       ) {
207 # ifndef LOCAL_BADCHAN
208     if (flags & GLINE_LOCAL)
209       return 0;
210 # endif
211     flags |= GLINE_BADCHAN;
212   }
213 #endif /* BADCHAN */
214
215   /* Inform ops... */
216   sendto_op_mask(SNO_GLINE, "%s adding %s %s for %s, expiring at "
217                  TIME_T_FMT ": %s",
218                  IsServer(sptr) ? sptr->name : sptr->user->server->name,
219                  flags & GLINE_LOCAL ? "local" : "global",
220                  flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", userhost,
221                  expire, reason);
222
223 #ifdef GPATH
224   /* and log it */
225   if (IsServer(sptr))
226     write_log(GPATH, "# " TIME_T_FMT " %s adding %s %s for %s, expiring at "
227               TIME_T_FMT ": %s\n", TStime(), sptr->name,
228               flags & GLINE_LOCAL ? "local" : "global",
229               flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", userhost, expire,
230               reason);
231   else
232     write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s adding %s %s for %s, "
233               "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
234               sptr->user->username, sptr->user->host,
235               flags & GLINE_LOCAL ? "local" : "global",
236               flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", userhost, expire,
237               reason);
238 #endif /* GPATH */
239
240   /* make the gline */
241   agline = make_gline(userhost, reason, expire, lastmod, flags);
242
243   propagate_gline(cptr, sptr, agline);
244
245   if (GlineIsBadChan(agline))
246     return 0;
247
248 #ifdef GPATH
249   /* this can be inserted into the conf */
250   write_log(GPATH, "%c:%s:%s:%s\n", GlineIsIpMask(agline) ? 'k' : 'K',
251             GlineHost(agline), GlineReason(agline), GlineUser(agline));
252 #endif /* GPATH */
253
254   return do_gline(cptr, sptr, agline); /* knock off users if necessary */
255 }
256
257 int
258 gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
259                time_t lastmod)
260 {
261   assert(0 != gline);
262
263   gline->gl_flags |= GLINE_ACTIVE;
264   gline->gl_lastmod = lastmod;
265
266   /* Inform ops and log it */
267   sendto_op_mask(SNO_GLINE, "%s activating %s %s for %s%s%s, expiring at "
268                  TIME_T_FMT ": %s",
269                  IsServer(sptr) ? sptr->name : sptr->user->server->name,
270                  GlineIsLocal(gline) ? "local" : "global",
271                  GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
272                  gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
273                  GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
274                  gline->gl_reason);
275
276 #ifdef GPATH
277   if (IsServer(sptr))
278     write_log(GPATH, "# " TIME_T_FMT " %s activating %s %s for %s%s%s, "
279               "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
280               GlineIsLocal(gline) ? "local" : "global",
281               GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
282               gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
283               GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
284               gline->gl_reason);
285   else
286     write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s activating %s %s for "
287               "%s%s%s, expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
288               sptr->user->username, sptr->user->host,
289               GlineIsLocal(gline) ? "local" : "global",
290               GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
291               gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
292               GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
293               gline->gl_reason);
294 #endif /* GPATH */
295
296   propagate_gline(cptr, sptr, gline);
297
298   return GlineIsBadChan(gline) ? 0 : do_gline(cptr, sptr, gline);
299 }
300
301 int
302 gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
303                  time_t lastmod)
304 {
305   assert(0 != gline);
306
307   gline->gl_flags &= ~GLINE_ACTIVE;
308   gline->gl_lastmod = lastmod;
309
310   /* Inform ops and log it */
311   sendto_op_mask(SNO_GLINE, "%s deactivating %s %s for %s%s%s, expiring at "
312                  TIME_T_FMT ": %s",
313                  IsServer(sptr) ? sptr->name : sptr->user->server->name,
314                  GlineIsLocal(gline) ? "local" : "global",
315                  GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
316                  gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
317                  GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
318                  gline->gl_reason);
319
320 #ifdef GPATH
321   if (IsServer(sptr))
322     write_log(GPATH, "# " TIME_T_FMT " %s deactivating %s %s for %s%s%s, "
323               "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
324               GlineIsLocal(gline) ? "local" : "global",
325               GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
326               gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
327               GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
328               gline->gl_reason);
329   else
330     write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s deactivating %s %s for "
331               "%s%s%s, expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name,
332               sptr->user->username, sptr->user->host,
333               GlineIsLocal(gline) ? "local" : "global",
334               GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
335               gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
336               GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
337               gline->gl_reason);
338 #endif /* GPATH */
339
340   propagate_gline(cptr, sptr, gline);
341
342   return 0;
343 }
344
345 struct Gline *
346 gline_find(char *userhost, unsigned int flags)
347 {
348   struct Gline *gline;
349   struct Gline *sgline;
350   char *user, *host, *t_uh;
351
352   if (flags & (GLINE_BADCHAN | GLINE_ANY)) {
353     for (gline = BadChanGlineList; gline; gline = sgline) {
354       sgline = gline->gl_next;
355
356       if (gline->gl_expire <= TStime())
357         gline_free(gline);
358       else if ((flags & GLINE_EXACT ? ircd_strcmp(gline->gl_user, userhost) :
359                 match(gline->gl_user, userhost)) == 0)
360         return gline;
361     }
362   }
363
364   if ((flags & (GLINE_BADCHAN | GLINE_ANY)) == GLINE_BADCHAN)
365     return 0;
366
367   DupString(t_uh, userhost);
368   canon_userhost(t_uh, &user, &host, 0);
369
370   for (gline = GlobalGlineList; gline; gline = sgline) {
371     sgline = gline->gl_next;
372
373     if (gline->gl_expire <= TStime())
374       gline_free(gline);
375     else if (flags & GLINE_EXACT) {
376       if (ircd_strcmp(gline->gl_host, host) == 0 &&
377           ((!user && ircd_strcmp(gline->gl_user, "*") == 0) ||
378            ircd_strcmp(gline->gl_user, user) == 0))
379         break;
380     } else {
381       if (match(gline->gl_host, host) == 0 &&
382           ((!user && ircd_strcmp(gline->gl_user, "*") == 0) ||
383            match(gline->gl_user, user) == 0))
384       break;
385     }
386   }
387
388   MyFree(t_uh);
389
390   return gline;
391 }
392
393 struct Gline *
394 gline_lookup(struct Client *cptr)
395 {
396   struct Gline *gline;
397   struct Gline *sgline;
398
399   for (gline = GlobalGlineList; gline; gline = sgline) {
400     sgline = gline->gl_next;
401
402     if (gline->gl_expire <= TStime())
403       gline_free(gline);
404     else if ((GlineIsIpMask(gline) ?
405               match(gline->gl_host, cptr->sock_ip) :
406               match(gline->gl_host, cptr->sockhost)) == 0 &&
407              match(gline->gl_user, cptr->user->username) == 0)
408       return gline;
409   }
410
411   return 0;
412 }
413
414 void
415 gline_free(struct Gline *gline)
416 {
417   assert(0 != gline);
418
419   *gline->gl_prev_p = gline->gl_next; /* squeeze this gline out */
420   if (gline->gl_next)
421     gline->gl_next->gl_prev_p = gline->gl_prev_p;
422
423   MyFree(gline->gl_user); /* free up the memory */
424   if (gline->gl_host)
425     MyFree(gline->gl_host);
426   MyFree(gline->gl_reason);
427   MyFree(gline);
428 }
429
430 void
431 gline_burst(struct Client *cptr)
432 {
433   struct Gline *gline;
434   struct Gline *sgline;
435
436   for (gline = GlobalGlineList; gline; gline = sgline) { /* all glines */
437     sgline = gline->gl_next;
438
439     if (gline->gl_expire <= TStime()) /* expire any that need expiring */
440       gline_free(gline);
441     else if (!GlineIsLocal(gline) && gline->gl_lastmod)
442       sendto_one(cptr, "%s " TOK_GLINE " * %c%s@%s " TIME_T_FMT " " TIME_T_FMT
443                  " :%s", NumServ(&me), GlineIsActive(gline) ? '+' : '-',
444                  gline->gl_user, gline->gl_host, gline->gl_expire - TStime(),
445                  gline->gl_lastmod, gline->gl_reason);
446   }
447
448   for (gline = BadChanGlineList; gline; gline = sgline) { /* all glines */
449     sgline = gline->gl_next;
450
451     if (gline->gl_expire <= TStime()) /* expire any that need expiring */
452       gline_free(gline);
453     else if (!GlineIsLocal(gline) && gline->gl_lastmod)
454       sendto_one(cptr, "%s " TOK_GLINE " * %c%s " TIME_T_FMT " " TIME_T_FMT
455                  " :%s", NumServ(&me), GlineIsActive(gline) ? '+' : '-',
456                  gline->gl_user, gline->gl_expire - TStime(),
457                  gline->gl_lastmod, gline->gl_reason);
458   }
459 }
460
461 int
462 gline_resend(struct Client *cptr, struct Gline *gline)
463 {
464   if (GlineIsLocal(gline) || !gline->gl_lastmod)
465     return 0;
466
467   sendto_one(cptr, "%s " TOK_GLINE " * %c%s%s%s " TIME_T_FMT " " TIME_T_FMT
468              " :%s", NumServ(&me), GlineIsActive(gline) ? '+' : '-',
469              gline->gl_user, GlineIsBadChan(gline) ? "" : "@",
470              GlineIsBadChan(gline) ? "" : gline->gl_host,
471              gline->gl_expire - TStime(), gline->gl_lastmod, gline->gl_reason);
472
473   return 0;
474 }
475
476 int
477 gline_list(struct Client *sptr, char *userhost)
478 {
479   struct Gline *gline;
480   struct Gline *sgline;
481
482   if (userhost) {
483     if (!(gline = gline_find(userhost, GLINE_ANY))) { /* no such gline */
484       send_error_to_client(sptr, ERR_NOSUCHGLINE, userhost);
485       return 0;
486     }
487
488     /* send gline information along */
489     sendto_one(sptr, rpl_str(RPL_GLIST), me.name, sptr->name, gline->gl_user,
490                GlineIsBadChan(gline) ? "" : "@",
491                GlineIsBadChan(gline) ? "" : gline->gl_host, gline->gl_expire,
492                GlineIsLocal(gline) ? me.name : "*",
493                GlineIsActive(gline) ? '+' : '-', gline->gl_reason);
494   } else {
495     for (gline = GlobalGlineList; gline; gline = sgline) {
496       sgline = gline->gl_next;
497
498       if (gline->gl_expire <= TStime())
499         gline_free(gline);
500       else
501         sendto_one(sptr, rpl_str(RPL_GLIST), me.name, sptr->name, gline->gl_user,
502                    "@", gline->gl_host, gline->gl_expire,
503                    GlineIsLocal(gline) ? me.name : "*",
504                    GlineIsActive(gline) ? '+' : '-', gline->gl_reason);
505     }
506
507     for (gline = BadChanGlineList; gline; gline = sgline) {
508       sgline = gline->gl_next;
509
510       if (gline->gl_expire <= TStime())
511         gline_free(gline);
512       else
513         sendto_one(sptr, rpl_str(RPL_GLIST), me.name, sptr->name, gline->gl_user,
514                    "", "", gline->gl_expire,
515                    GlineIsLocal(gline) ? me.name : "*",
516                    GlineIsActive(gline) ? '+' : '-', gline->gl_reason);
517     }
518   }
519
520   /* end of gline information */
521   sendto_one(sptr, rpl_str(RPL_ENDOFGLIST), me.name, sptr->name);
522   return 0;
523 }
524
525 void
526 gline_stats(struct Client *sptr)
527 {
528   struct Gline *gline;
529   struct Gline *sgline;
530
531   for (gline = GlobalGlineList; gline; gline = sgline) {
532     sgline = gline->gl_next;
533
534     if (gline->gl_expire <= TStime())
535       gline_free(gline);
536     else
537       sendto_one(sptr, rpl_str(RPL_STATSGLINE), me.name, sptr->name, 'G',
538                  gline->gl_user, gline->gl_host, gline->gl_expire,
539                  gline->gl_reason);
540   }
541 }
542
543
544 #if 0 /* forget about it! */
545 struct Gline *make_gline(int is_ipmask, char *host, char *reason,
546                          char *name, time_t expire)
547 {
548   struct Gline *agline;
549
550 #ifdef BADCHAN
551   int gtype = 0;
552   if ('#' == *host || '&' == *host || '+' == *host)
553     gtype = 1; /* BAD CHANNEL GLINE */
554 #endif
555
556   agline = (struct Gline*) MyMalloc(sizeof(struct Gline)); /* alloc memory */
557   assert(0 != agline);
558   DupString(agline->host, host);        /* copy vital information */
559   DupString(agline->reason, reason);
560   DupString(agline->name, name);
561   agline->expire = expire;
562   agline->gflags = GLINE_ACTIVE;        /* gline is active */
563   if (is_ipmask)
564     SetGlineIsIpMask(agline);
565 #ifdef BADCHAN
566   if (gtype)
567   { 
568     agline->next = BadChanGlineList;    /* link it into the list */
569     return (BadChanGlineList = agline);
570   }
571 #endif
572   agline->next = GlobalGlineList;       /* link it into the list */
573   return (GlobalGlineList = agline);
574 }
575
576 struct Gline *find_gline(struct Client *cptr, struct Gline **pgline)
577 {
578   struct Gline* gline = GlobalGlineList;
579   struct Gline* prev = 0;
580
581   while (gline) {
582     /*
583      * look through all glines
584      */
585     if (gline->expire <= TStime()) {
586       /*
587        * handle expired glines
588        */
589       free_gline(gline, prev);
590       gline = prev ? prev->next : GlobalGlineList;
591       if (!gline)
592         break;                  /* gline == NULL means gline == NULL */
593       continue;
594     }
595
596     /* Does gline match? */
597     /* Added a check against the user's IP address as well -Kev */
598     if ((GlineIsIpMask(gline) ?
599         match(gline->host, ircd_ntoa((const char*) &cptr->ip)) :
600         match(gline->host, cptr->sockhost)) == 0 &&
601         match(gline->name, cptr->user->username) == 0) {
602       if (pgline)
603         *pgline = prev; /* If they need it, give them the previous gline
604                                    entry (probably for free_gline, below) */
605       return gline;
606     }
607
608     prev = gline;
609     gline = gline->next;
610   }
611
612   return 0;                  /* found no glines */
613 }
614
615 void free_gline(struct Gline* gline, struct Gline* prev)
616 {
617   assert(0 != gline);
618   if (prev)
619     prev->next = gline->next;   /* squeeze agline out */
620   else { 
621 #ifdef BADCHAN
622     assert(0 != gline->host);
623     if ('#' == *gline->host ||
624         '&' == *gline->host ||
625         '+' == *gline->host) {
626       BadChanGlineList = gline->next;
627     }
628     else
629 #endif
630       GlobalGlineList = gline->next;
631   }
632
633   MyFree(gline->host);  /* and free up the memory */
634   MyFree(gline->reason);
635   MyFree(gline->name);
636   MyFree(gline);
637 }
638
639 void gline_remove_expired(time_t now)
640 {
641   struct Gline* gline;
642   struct Gline* prev = 0;
643   
644   for (gline = GlobalGlineList; gline; gline = gline->next) {
645     if (gline->expire < now) {
646       free_gline(gline, prev);
647       gline = (prev) ? prev : GlobalGlineList;
648       if (!gline)
649         break;
650       continue;
651     }
652     prev = gline;
653   }
654 }
655
656 #ifdef BADCHAN
657 int bad_channel(const char* name)
658
659   struct Gline* agline = BadChanGlineList;
660
661   while (agline)
662   { 
663     if ((agline->gflags & GLINE_ACTIVE) && (agline->expire > TStime()) && 
664          !mmatch(agline->host, name)) { 
665       return 1;
666     }
667     agline = agline->next;
668   }
669   return 0;
670 }
671
672 void bad_channel_remove_expired(time_t now)
673 {
674   struct Gline* gline;
675   struct Gline* prev = 0;
676   
677   for (gline = BadChanGlineList; gline; gline = gline->next) {
678     if (gline->expire < now) {
679       free_gline(gline, prev);
680       gline = (prev) ? prev : BadChanGlineList;
681       if (!gline)
682         break;
683       continue;
684     }
685     prev = gline;
686   }
687 }
688
689 #endif
690
691
692 void add_gline(struct Client *sptr, int ip_mask, char *host, char *comment,
693                char *user, time_t expire, int local)
694 {
695   struct Client *acptr;
696   struct Gline *agline;
697   int fd;
698   int gtype = 0;
699   assert(0 != host);
700
701 #ifdef BADCHAN
702   if ('#' == *host || '&' == *host || '+' == *host)
703     gtype = 1;   /* BAD CHANNEL */
704 #endif
705
706   /* Inform ops */
707   sendto_op_mask(SNO_GLINE,
708       "%s adding %s%s for %s@%s, expiring at " TIME_T_FMT ": %s", sptr->name,
709       local ? "local " : "",
710       gtype ? "BADCHAN" : "GLINE", user, host, expire, comment);
711
712 #ifdef GPATH
713   write_log(GPATH,
714       "# " TIME_T_FMT " %s adding %s %s for %s@%s, expiring at " TIME_T_FMT
715       ": %s\n", TStime(), sptr->name, local ? "local" : "global",
716       gtype ? "BADCHAN" : "GLINE", user, host, expire, comment);
717
718   /* this can be inserted into the conf */
719   if (!gtype)
720     write_log(GPATH, "%c:%s:%s:%s\n", ip_mask ? 'k' : 'K', host, comment, 
721       user);
722 #endif /* GPATH */
723
724   agline = make_gline(ip_mask, host, comment, user, expire);
725   if (local)
726     SetGlineIsLocal(agline);
727
728 #ifdef BADCHAN
729   if (gtype)
730     return;
731 #endif
732
733   for (fd = HighestFd; fd >= 0; --fd) { 
734     /*
735      * get the users!
736      */ 
737     if ((acptr = LocalClientArray[fd])) {
738       if (!acptr->user)
739         continue;
740 #if 0
741       /*
742        * whee!! :)
743        */
744       if (!acptr->user || strlen(acptr->sockhost) > HOSTLEN ||
745           (acptr->user->username ? strlen(acptr->user->username) : 0) > HOSTLEN)
746         continue;               /* these tests right out of
747                                    find_kill for safety's sake */
748 #endif
749
750       if ((GlineIsIpMask(agline) ?  match(agline->host, acptr->sock_ip) :
751           match(agline->host, acptr->sockhost)) == 0 &&
752           (!acptr->user->username ||
753           match(agline->name, acptr->user->username) == 0))
754       {
755
756         /* ok, he was the one that got G-lined */
757         sendto_one(acptr, ":%s %d %s :*** %s.", me.name,
758             ERR_YOUREBANNEDCREEP, acptr->name, agline->reason);
759
760         /* let the ops know about my first kill */
761         sendto_op_mask(SNO_GLINE, "G-line active for %s",
762             get_client_name(acptr, FALSE));
763
764         /* and get rid of him */
765         if (sptr != acptr)
766           exit_client_msg(sptr->from, acptr, &me, "G-lined (%s)", agline->reason);
767       }
768     }
769   }
770 }
771
772 #endif /* 0 */