2 * IRC - Internet Relay Chat, ircd/m_gline.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
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 1, or (at your option)
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * m_functions execute protocol messages on this server:
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
84 * No need to include handlers.h here the signatures must match
85 * and we don't need to force a rebuild of all the handlers everytime
86 * we add a new one to the list. --Bleep
94 #include "ircd_reply.h"
95 #include "ircd_string.h"
110 * ms_gline - server message handler
112 * parv[0] = Sender prefix
113 * parv[1] = Target: server numeric
114 * parv[2] = (+|-)<G-line mask>
115 * parv[3] = G-line lifetime
121 * From somewhere else:
123 * parv[4] = Last modification time
128 ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
130 struct Client *acptr = 0;
131 struct Gline *agline;
132 unsigned int flags = 0;
133 time_t expire_off, lastmod = 0;
134 char *mask = parv[2], *target = parv[1], *reason;
137 if (!find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD))
138 return need_more_params(sptr, "GLINE");
141 flags |= GLINE_FORCE;
142 } else if (parc >= 5) {
143 lastmod = atoi(parv[4]);
146 return need_more_params(sptr, "GLINE");
148 if (!(target[0] == '*' && target[1] == '\0')) {
149 if (!(acptr = FindNServer(target)))
150 return 0; /* no such server */
152 if (!IsMe(acptr)) { /* manually propagate */
153 if (IsServer(sptr)) {
155 sendto_one(acptr, "%s " TOK_GLINE " %s %s %s :%s", NumServ(sptr),
156 target, mask, parv[3], reason);
158 sendto_one(acptr, "%s " TOK_GLINE " %s %s %s %s :%s", NumServ(sptr),
159 target, mask, parv[3], parv[4], reason);
161 sendto_one(acptr, "%s%s " TOK_GLINE " %s %s %s %s :%s", NumNick(sptr),
162 target, mask, parv[3], parv[4], reason);
167 flags |= GLINE_LOCAL;
172 else if (*mask == '+') {
173 flags |= GLINE_ACTIVE;
176 flags |= GLINE_ACTIVE;
178 expire_off = atoi(parv[3]);
180 agline = gline_find(mask, GLINE_ANY);
183 if (GlineIsLocal(agline) && !(flags & GLINE_LOCAL)) /* global over local */
185 else if (!lastmod || GlineLastMod(agline) < lastmod) { /* new mod */
186 if (flags & GLINE_ACTIVE)
187 return gline_activate(cptr, sptr, agline, lastmod);
189 return gline_deactivate(cptr, sptr, agline, lastmod);
190 } else if (GlineLastMod(agline) == lastmod)
193 return gline_resend(cptr, agline); /* other server desynched WRT gline */
196 return gline_add(cptr, sptr, mask, reason, expire_off, lastmod, flags);
200 * mo_gline - oper message handler
202 * parv[0] = Sender prefix
203 * parv[1] = [[+|-]<G-line mask>]
207 * parv[2] = [Expiration offset]
208 * parv[3] = [Comment]
213 * parv[3] = [Expiration offset]
214 * parv[4] = [Comment]
218 mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
220 struct Client *acptr = 0;
221 struct Gline *agline;
222 unsigned int flags = 0;
224 char *mask = parv[1], *target = 0, *reason;
227 return gline_list(sptr, 0);
230 flags |= GLINE_ACTIVE;
232 } else if (*mask == '-')
235 return gline_list(sptr, mask);
239 send_error_to_client(sptr, ERR_NOPRIVILEGES);
245 expire_off = atoi(parv[2]);
247 flags |= GLINE_LOCAL;
248 } else if (parc >= 4) {
250 expire_off = atoi(parv[3]);
253 return need_more_params(sptr, "GLINE");
256 if (!(target[0] == '*' && target[1] == '\0')) {
257 if (!(acptr = find_match_server(target))) {
258 send_error_to_client(sptr, ERR_NOSUCHSERVER, target);
262 if (!IsMe(acptr)) { /* manually propagate, since we don't set it */
264 send_error_to_client(sptr, ERR_NOPRIVILEGES);
268 sendto_one(acptr, "%s%s " TOK_GLINE " %s %c%s %s " TIME_T_FMT " :%s",
269 NumNick(sptr), NumServ(acptr),
270 flags & GLINE_ACTIVE ? '?' : '-', mask, parv[3], TStime(),
275 flags |= GLINE_LOCAL;
276 } else if (!IsOper(sptr)) {
277 send_error_to_client(sptr, ERR_NOPRIVILEGES);
282 agline = gline_find(mask, GLINE_ANY);
285 if (GlineIsLocal(agline) && !(flags & GLINE_LOCAL)) /* global over local */
288 if (flags & GLINE_ACTIVE)
289 return gline_activate(cptr, sptr, agline, TStime());
291 return gline_deactivate(cptr, sptr, agline, TStime());
295 return gline_add(cptr, sptr, mask, reason, expire_off, TStime(), flags);
299 * m_gline - user message handler
301 * parv[0] = Sender prefix
302 * parv[1] = [<server name>]
306 m_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
309 return gline_list(sptr, 0);
311 return gline_list(sptr, parv[1]);
316 * ms_gline - server message handler
318 * parv[0] = Send prefix
322 * parv[1] = Target: server numeric
323 * parv[2] = [+|-]<G-line mask>
324 * parv[3] = Expiration offset
329 * parv[1] = [+|-]<G-line mask>
330 * parv[2] = Expiration offset
334 int ms_gline(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
336 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
347 * Remove expired G-lines
349 gline_remove_expired(TStime());
352 * Remove expired bad channels
354 bad_channel_remove_expired(TStime());
357 if (IsServer(cptr)) {
358 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
359 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
360 return need_more_params(sptr, "GLINE");
362 if (*parv[2] == '-') /* add mode or delete mode? */
367 if (*parv[2] == '+' || *parv[2] == '-')
368 parv[2]++; /* step past mode indicator */
371 * forward the message appropriately
373 if (0 == ircd_strcmp(parv[1], "*")) {
377 sendto_serv_butone(cptr,
378 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
379 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
384 * REMOVE THIS after all servers upgraded to 2.10.01 and
385 * Uworld uses a numeric too
387 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
388 (strlen(parv[1]) == 1 &&
390 !(acptr = FindNServer(parv[1]))))
391 return 0; /* no such server/user exists; forget it */
395 * REMOVE THIS after all servers upgraded to 2.10.01 and
396 * Uworld uses a numeric too
398 if (IsServer(acptr) || !MyConnect(acptr))
401 /* single destination */
403 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
404 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
405 return 0; /* only the intended destination
406 should add this gline */
409 if (!(host = strchr(parv[2], '@'))) {
411 * convert user@host no @'s; assume username is '*'
418 *(host++) = '\0'; /* break up string at the '@' */
420 ip_mask = check_if_ipmask(host); /* Store this boolean */
422 if ('#' == *host || '&' == *host || '+' == *host)
423 gtype = 1; /* BAD CHANNEL GLINE */
425 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
428 if (0 == ircd_strcmp(gline->name, user) &&
429 0 == ircd_strcmp(gline->host, host))
434 if (!active && gline)
437 * removing the gline, notify opers
439 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
440 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
443 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
444 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
448 free_gline(gline, prev); /* remove the gline */
451 { /* must be adding a gline */
452 expire = atoi(parv[3]) + TStime(); /* expire time? */
453 if (gline && gline->expire < expire)
454 { /* new expire time? */
455 /* yes, notify the opers */
456 sendto_op_mask(SNO_GLINE,
457 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
458 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
461 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
462 "on %s for %s@%s to " TIME_T_FMT "\n",
463 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
464 gline->name, gline->host, expire);
467 gline->expire = expire; /* reset the expire time */
471 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
472 if (!mmatch(gline->name, user) &&
473 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
474 !mmatch(gline->host, host))
475 return 0; /* found an existing G-line that matches */
478 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
483 else if (parc < 2 || *parv[1] == '\0')
485 /* Not enough args and a user; list glines */
486 for (gline = GlobalGlineList; gline; gline = gline->next)
487 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
488 gline->name, gline->host, gline->expire, gline->reason,
489 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
491 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
498 priv = IsAnOper(cptr);
504 { /* non-oper not permitted to change things */
506 { /* oper wants to deactivate the gline */
510 else if (*parv[1] == '+')
511 { /* oper wants to activate inactive gline */
519 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
525 if (!(host = strchr(parv[1], '@')))
527 user = "*"; /* no @'s; assume username is '*' */
533 *(host++) = '\0'; /* break up string at the '@' */
535 ip_mask = check_if_ipmask(host); /* Store this boolean */
537 if ('#' == *host || '&' == *host || '+' == *host)
538 #ifndef LOCAL_BADCHAN
541 gtype = 1; /* BAD CHANNEL */
545 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
548 if (!mmatch(gline->name, user) &&
549 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
550 !mmatch(gline->host, host))
558 if (priv && active && expire > CurrentTime)
560 /* Add local G-line */
561 if (parc < 4 || !strchr(parv[3], ' '))
562 return need_more_params(sptr, "GLINE");
564 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
568 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
574 if (expire <= gline->expire)
578 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
581 /* oper wants a list of one gline only */
582 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
583 gline->host, gline->expire, gline->reason,
584 GlineIsActive(gline) ? "" : " (Inactive)");
585 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
590 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
592 if (active) /* reset activation on gline */
595 else if (GlineIsLocal(gline))
597 /* Remove local G-line */
598 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
599 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
601 write_log(GPATH, "# " TIME_T_FMT
602 " %s!%s@%s removed local %s for %s@%s\n",
603 TStime(), parv[0], cptr->user->username, cptr->user->host,
604 gtype ? "BADCHAN" : "GLINE",
605 gline->name, gline->host);
607 free_gline(gline, prev); /* remove the gline */
615 active = -1; /* for later sendto_ops and logging functions */
618 gline->expire = expire; /* reset expiration time */
620 /* inform the operators what's up */
622 { /* changing the activation */
623 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
624 "%s %sactivating %s for %s@%s and "
625 "resetting expiration time to " TIME_T_FMT,
626 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
627 gline->name, gline->host, gline->expire);
629 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
630 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
631 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
632 TStime(), parv[0], cptr->user->username, cptr->user->host,
633 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
634 gline->host, gline->expire);
639 { /* changing only the expiration */
640 sendto_op_mask(SNO_GLINE,
641 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
642 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
645 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
646 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
647 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
648 gline->name, gline->host, gline->expire);
656 * mo_gline - oper message handler
658 * parv[0] = Send prefix
662 * parv[1] = Target: server numeric
663 * parv[2] = [+|-]<G-line mask>
664 * parv[3] = Expiration offset
669 * parv[1] = [+|-]<G-line mask>
670 * parv[2] = Expiration offset
674 int mo_gline(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
676 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
687 * Remove expired G-lines
689 gline_remove_expired(TStime());
692 * Remove expired bad channels
694 bad_channel_remove_expired(TStime());
697 if (IsServer(cptr)) {
698 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
699 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
700 return need_more_params(sptr, "GLINE");
702 if (*parv[2] == '-') /* add mode or delete mode? */
707 if (*parv[2] == '+' || *parv[2] == '-')
708 parv[2]++; /* step past mode indicator */
711 * forward the message appropriately
713 if (0 == ircd_strcmp(parv[1], "*")) {
717 sendto_serv_butone(cptr,
718 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
719 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
724 * REMOVE THIS after all servers upgraded to 2.10.01 and
725 * Uworld uses a numeric too
727 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
728 (strlen(parv[1]) == 1 &&
730 !(acptr = FindNServer(parv[1]))))
731 return 0; /* no such server/user exists; forget it */
735 * REMOVE THIS after all servers upgraded to 2.10.01 and
736 * Uworld uses a numeric too
738 if (IsServer(acptr) || !MyConnect(acptr))
741 /* single destination */
743 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
744 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
745 return 0; /* only the intended destination
746 should add this gline */
749 if (!(host = strchr(parv[2], '@'))) {
751 * convert user@host no @'s; assume username is '*'
758 *(host++) = '\0'; /* break up string at the '@' */
760 ip_mask = check_if_ipmask(host); /* Store this boolean */
762 if ('#' == *host || '&' == *host || '+' == *host)
763 gtype = 1; /* BAD CHANNEL GLINE */
765 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
768 if (0 == ircd_strcmp(gline->name, user) &&
769 0 == ircd_strcmp(gline->host, host))
774 if (!active && gline)
777 * removing the gline, notify opers
779 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
780 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
783 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
784 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
788 free_gline(gline, prev); /* remove the gline */
791 { /* must be adding a gline */
792 expire = atoi(parv[3]) + TStime(); /* expire time? */
793 if (gline && gline->expire < expire)
794 { /* new expire time? */
795 /* yes, notify the opers */
796 sendto_op_mask(SNO_GLINE,
797 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
798 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
801 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
802 "on %s for %s@%s to " TIME_T_FMT "\n",
803 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
804 gline->name, gline->host, expire);
807 gline->expire = expire; /* reset the expire time */
811 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
812 if (!mmatch(gline->name, user) &&
813 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
814 !mmatch(gline->host, host))
815 return 0; /* found an existing G-line that matches */
818 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
823 else if (parc < 2 || *parv[1] == '\0')
825 /* Not enough args and a user; list glines */
826 for (gline = GlobalGlineList; gline; gline = gline->next)
827 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
828 gline->name, gline->host, gline->expire, gline->reason,
829 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
831 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
838 priv = IsAnOper(cptr);
844 { /* non-oper not permitted to change things */
846 { /* oper wants to deactivate the gline */
850 else if (*parv[1] == '+')
851 { /* oper wants to activate inactive gline */
859 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
865 if (!(host = strchr(parv[1], '@')))
867 user = "*"; /* no @'s; assume username is '*' */
873 *(host++) = '\0'; /* break up string at the '@' */
875 ip_mask = check_if_ipmask(host); /* Store this boolean */
877 if ('#' == *host || '&' == *host || '+' == *host)
878 #ifndef LOCAL_BADCHAN
881 gtype = 1; /* BAD CHANNEL */
885 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
888 if (!mmatch(gline->name, user) &&
889 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
890 !mmatch(gline->host, host))
898 if (priv && active && expire > CurrentTime)
900 /* Add local G-line */
901 if (parc < 4 || !strchr(parv[3], ' '))
902 return need_more_params(sptr, "GLINE");
904 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
908 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
914 if (expire <= gline->expire)
918 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
921 /* oper wants a list of one gline only */
922 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
923 gline->host, gline->expire, gline->reason,
924 GlineIsActive(gline) ? "" : " (Inactive)");
925 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
930 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
932 if (active) /* reset activation on gline */
935 else if (GlineIsLocal(gline))
937 /* Remove local G-line */
938 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
939 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
941 write_log(GPATH, "# " TIME_T_FMT
942 " %s!%s@%s removed local %s for %s@%s\n",
943 TStime(), parv[0], cptr->user->username, cptr->user->host,
944 gtype ? "BADCHAN" : "GLINE",
945 gline->name, gline->host);
947 free_gline(gline, prev); /* remove the gline */
955 active = -1; /* for later sendto_ops and logging functions */
958 gline->expire = expire; /* reset expiration time */
960 /* inform the operators what's up */
962 { /* changing the activation */
963 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
964 "%s %sactivating %s for %s@%s and "
965 "resetting expiration time to " TIME_T_FMT,
966 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
967 gline->name, gline->host, gline->expire);
969 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
970 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
971 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
972 TStime(), parv[0], cptr->user->username, cptr->user->host,
973 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
974 gline->host, gline->expire);
979 { /* changing only the expiration */
980 sendto_op_mask(SNO_GLINE,
981 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
982 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
985 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
986 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
987 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
988 gline->name, gline->host, gline->expire);
1000 * parv[0] = Send prefix
1004 * parv[1] = Target: server numeric
1005 * parv[2] = [+|-]<G-line mask>
1006 * parv[3] = Expiration offset
1011 * parv[1] = [+|-]<G-line mask>
1012 * parv[2] = Expiration offset
1016 int m_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
1018 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
1019 struct Gline* gline;
1029 * Remove expired G-lines
1031 gline_remove_expired(TStime());
1034 * Remove expired bad channels
1036 bad_channel_remove_expired(TStime());
1039 if (IsServer(cptr)) {
1040 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
1041 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
1042 return need_more_params(sptr, "GLINE");
1044 if (*parv[2] == '-') /* add mode or delete mode? */
1049 if (*parv[2] == '+' || *parv[2] == '-')
1050 parv[2]++; /* step past mode indicator */
1053 * forward the message appropriately
1055 if (0 == ircd_strcmp(parv[1], "*")) {
1059 sendto_serv_butone(cptr,
1060 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
1061 NumServ(cptr), parv[1], parv[2], parv[3], parv[4]);
1066 * REMOVE THIS after all servers upgraded to 2.10.01 and
1067 * Uworld uses a numeric too
1069 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
1070 (strlen(parv[1]) == 1 &&
1072 !(acptr = FindNServer(parv[1]))))
1073 return 0; /* no such server/user exists; forget it */
1077 * REMOVE THIS after all servers upgraded to 2.10.01 and
1078 * Uworld uses a numeric too
1080 if (IsServer(acptr) || !MyConnect(acptr))
1083 /* single destination */
1085 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
1086 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
1087 return 0; /* only the intended destination
1088 should add this gline */
1091 if (!(host = strchr(parv[2], '@'))) {
1093 * convert user@host no @'s; assume username is '*'
1100 *(host++) = '\0'; /* break up string at the '@' */
1102 ip_mask = check_if_ipmask(host); /* Store this boolean */
1104 if ('#' == *host || '&' == *host || '+' == *host)
1105 gtype = 1; /* BAD CHANNEL GLINE */
1107 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
1108 gline = gline->next)
1110 if (0 == ircd_strcmp(gline->name, user) &&
1111 0 == ircd_strcmp(gline->host, host))
1116 if (!active && gline)
1119 * removing the gline, notify opers
1121 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
1122 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
1125 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
1126 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
1130 free_gline(gline, prev); /* remove the gline */
1133 { /* must be adding a gline */
1134 expire = atoi(parv[3]) + TStime(); /* expire time? */
1135 if (gline && gline->expire < expire)
1136 { /* new expire time? */
1137 /* yes, notify the opers */
1138 sendto_op_mask(SNO_GLINE,
1139 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1140 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
1143 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
1144 "on %s for %s@%s to " TIME_T_FMT "\n",
1145 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
1146 gline->name, gline->host, expire);
1149 gline->expire = expire; /* reset the expire time */
1152 { /* create gline */
1153 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
1154 if (!mmatch(gline->name, user) &&
1155 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
1156 !mmatch(gline->host, host))
1157 return 0; /* found an existing G-line that matches */
1160 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
1165 else if (parc < 2 || *parv[1] == '\0')
1167 /* Not enough args and a user; list glines */
1168 for (gline = GlobalGlineList; gline; gline = gline->next)
1169 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
1170 gline->name, gline->host, gline->expire, gline->reason,
1171 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
1173 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1180 priv = IsAnOper(cptr);
1182 priv = IsOper(cptr);
1186 { /* non-oper not permitted to change things */
1187 if (*parv[1] == '-')
1188 { /* oper wants to deactivate the gline */
1192 else if (*parv[1] == '+')
1193 { /* oper wants to activate inactive gline */
1201 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
1207 if (!(host = strchr(parv[1], '@')))
1209 user = "*"; /* no @'s; assume username is '*' */
1215 *(host++) = '\0'; /* break up string at the '@' */
1217 ip_mask = check_if_ipmask(host); /* Store this boolean */
1219 if ('#' == *host || '&' == *host || '+' == *host)
1220 #ifndef LOCAL_BADCHAN
1223 gtype = 1; /* BAD CHANNEL */
1227 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
1228 gline = gline->next)
1230 if (!mmatch(gline->name, user) &&
1231 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
1232 !mmatch(gline->host, host))
1240 if (priv && active && expire > CurrentTime)
1242 /* Add local G-line */
1243 if (parc < 4 || !strchr(parv[3], ' '))
1244 return need_more_params(sptr, "GLINE");
1246 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
1250 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
1256 if (expire <= gline->expire)
1259 if ((active == -1 ||
1260 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
1263 /* oper wants a list of one gline only */
1264 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
1265 gline->host, gline->expire, gline->reason,
1266 GlineIsActive(gline) ? "" : " (Inactive)");
1267 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1272 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
1274 if (active) /* reset activation on gline */
1277 else if (GlineIsLocal(gline))
1279 /* Remove local G-line */
1280 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
1281 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
1283 write_log(GPATH, "# " TIME_T_FMT
1284 " %s!%s@%s removed local %s for %s@%s\n",
1285 TStime(), parv[0], cptr->user->username, cptr->user->host,
1286 gtype ? "BADCHAN" : "GLINE",
1287 gline->name, gline->host);
1289 free_gline(gline, prev); /* remove the gline */
1297 active = -1; /* for later sendto_ops and logging functions */
1300 gline->expire = expire; /* reset expiration time */
1302 /* inform the operators what's up */
1304 { /* changing the activation */
1305 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
1306 "%s %sactivating %s for %s@%s and "
1307 "resetting expiration time to " TIME_T_FMT,
1308 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
1309 gline->name, gline->host, gline->expire);
1311 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
1312 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
1313 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
1314 TStime(), parv[0], cptr->user->username, cptr->user->host,
1315 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
1316 gline->host, gline->expire);
1321 { /* changing only the expiration */
1322 sendto_op_mask(SNO_GLINE,
1323 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1324 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
1327 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
1328 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
1329 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
1330 gline->name, gline->host, gline->expire);