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 | GLINE_EXACT);
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 | GLINE_EXACT);
285 if (GlineIsLocal(agline) && !(flags & GLINE_LOCAL)) /* global over local */
288 if (flags & GLINE_ACTIVE)
289 return gline_activate(cptr, sptr, agline,
290 GlineLastMod(agline) ? TStime() : 0);
292 return gline_deactivate(cptr, sptr, agline,
293 GlineLastMod(agline) ? TStime() : 0);
297 return gline_add(cptr, sptr, mask, reason, expire_off, TStime(), flags);
301 * m_gline - user message handler
303 * parv[0] = Sender prefix
304 * parv[1] = [<server name>]
308 m_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
311 return gline_list(sptr, 0);
313 return gline_list(sptr, parv[1]);
318 * ms_gline - server message handler
320 * parv[0] = Send prefix
324 * parv[1] = Target: server numeric
325 * parv[2] = [+|-]<G-line mask>
326 * parv[3] = Expiration offset
331 * parv[1] = [+|-]<G-line mask>
332 * parv[2] = Expiration offset
336 int ms_gline(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
338 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
349 * Remove expired G-lines
351 gline_remove_expired(TStime());
354 * Remove expired bad channels
356 bad_channel_remove_expired(TStime());
359 if (IsServer(cptr)) {
360 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
361 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
362 return need_more_params(sptr, "GLINE");
364 if (*parv[2] == '-') /* add mode or delete mode? */
369 if (*parv[2] == '+' || *parv[2] == '-')
370 parv[2]++; /* step past mode indicator */
373 * forward the message appropriately
375 if (0 == ircd_strcmp(parv[1], "*")) {
379 sendto_serv_butone(cptr,
380 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
381 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
386 * REMOVE THIS after all servers upgraded to 2.10.01 and
387 * Uworld uses a numeric too
389 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
390 (strlen(parv[1]) == 1 &&
392 !(acptr = FindNServer(parv[1]))))
393 return 0; /* no such server/user exists; forget it */
397 * REMOVE THIS after all servers upgraded to 2.10.01 and
398 * Uworld uses a numeric too
400 if (IsServer(acptr) || !MyConnect(acptr))
403 /* single destination */
405 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
406 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
407 return 0; /* only the intended destination
408 should add this gline */
411 if (!(host = strchr(parv[2], '@'))) {
413 * convert user@host no @'s; assume username is '*'
420 *(host++) = '\0'; /* break up string at the '@' */
422 ip_mask = check_if_ipmask(host); /* Store this boolean */
424 if ('#' == *host || '&' == *host || '+' == *host)
425 gtype = 1; /* BAD CHANNEL GLINE */
427 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
430 if (0 == ircd_strcmp(gline->name, user) &&
431 0 == ircd_strcmp(gline->host, host))
436 if (!active && gline)
439 * removing the gline, notify opers
441 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
442 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
445 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
446 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
450 free_gline(gline, prev); /* remove the gline */
453 { /* must be adding a gline */
454 expire = atoi(parv[3]) + TStime(); /* expire time? */
455 if (gline && gline->expire < expire)
456 { /* new expire time? */
457 /* yes, notify the opers */
458 sendto_op_mask(SNO_GLINE,
459 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
460 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
463 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
464 "on %s for %s@%s to " TIME_T_FMT "\n",
465 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
466 gline->name, gline->host, expire);
469 gline->expire = expire; /* reset the expire time */
473 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
474 if (!mmatch(gline->name, user) &&
475 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
476 !mmatch(gline->host, host))
477 return 0; /* found an existing G-line that matches */
480 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
485 else if (parc < 2 || *parv[1] == '\0')
487 /* Not enough args and a user; list glines */
488 for (gline = GlobalGlineList; gline; gline = gline->next)
489 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
490 gline->name, gline->host, gline->expire, gline->reason,
491 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
493 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
500 priv = IsAnOper(cptr);
506 { /* non-oper not permitted to change things */
508 { /* oper wants to deactivate the gline */
512 else if (*parv[1] == '+')
513 { /* oper wants to activate inactive gline */
521 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
527 if (!(host = strchr(parv[1], '@')))
529 user = "*"; /* no @'s; assume username is '*' */
535 *(host++) = '\0'; /* break up string at the '@' */
537 ip_mask = check_if_ipmask(host); /* Store this boolean */
539 if ('#' == *host || '&' == *host || '+' == *host)
540 #ifndef LOCAL_BADCHAN
543 gtype = 1; /* BAD CHANNEL */
547 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
550 if (!mmatch(gline->name, user) &&
551 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
552 !mmatch(gline->host, host))
560 if (priv && active && expire > CurrentTime)
562 /* Add local G-line */
563 if (parc < 4 || !strchr(parv[3], ' '))
564 return need_more_params(sptr, "GLINE");
566 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
570 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
576 if (expire <= gline->expire)
580 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
583 /* oper wants a list of one gline only */
584 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
585 gline->host, gline->expire, gline->reason,
586 GlineIsActive(gline) ? "" : " (Inactive)");
587 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
592 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
594 if (active) /* reset activation on gline */
597 else if (GlineIsLocal(gline))
599 /* Remove local G-line */
600 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
601 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
603 write_log(GPATH, "# " TIME_T_FMT
604 " %s!%s@%s removed local %s for %s@%s\n",
605 TStime(), parv[0], cptr->user->username, cptr->user->host,
606 gtype ? "BADCHAN" : "GLINE",
607 gline->name, gline->host);
609 free_gline(gline, prev); /* remove the gline */
617 active = -1; /* for later sendto_ops and logging functions */
620 gline->expire = expire; /* reset expiration time */
622 /* inform the operators what's up */
624 { /* changing the activation */
625 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
626 "%s %sactivating %s for %s@%s and "
627 "resetting expiration time to " TIME_T_FMT,
628 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
629 gline->name, gline->host, gline->expire);
631 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
632 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
633 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
634 TStime(), parv[0], cptr->user->username, cptr->user->host,
635 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
636 gline->host, gline->expire);
641 { /* changing only the expiration */
642 sendto_op_mask(SNO_GLINE,
643 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
644 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
647 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
648 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
649 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
650 gline->name, gline->host, gline->expire);
658 * mo_gline - oper message handler
660 * parv[0] = Send prefix
664 * parv[1] = Target: server numeric
665 * parv[2] = [+|-]<G-line mask>
666 * parv[3] = Expiration offset
671 * parv[1] = [+|-]<G-line mask>
672 * parv[2] = Expiration offset
676 int mo_gline(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
678 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
689 * Remove expired G-lines
691 gline_remove_expired(TStime());
694 * Remove expired bad channels
696 bad_channel_remove_expired(TStime());
699 if (IsServer(cptr)) {
700 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
701 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
702 return need_more_params(sptr, "GLINE");
704 if (*parv[2] == '-') /* add mode or delete mode? */
709 if (*parv[2] == '+' || *parv[2] == '-')
710 parv[2]++; /* step past mode indicator */
713 * forward the message appropriately
715 if (0 == ircd_strcmp(parv[1], "*")) {
719 sendto_serv_butone(cptr,
720 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
721 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
726 * REMOVE THIS after all servers upgraded to 2.10.01 and
727 * Uworld uses a numeric too
729 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
730 (strlen(parv[1]) == 1 &&
732 !(acptr = FindNServer(parv[1]))))
733 return 0; /* no such server/user exists; forget it */
737 * REMOVE THIS after all servers upgraded to 2.10.01 and
738 * Uworld uses a numeric too
740 if (IsServer(acptr) || !MyConnect(acptr))
743 /* single destination */
745 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
746 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
747 return 0; /* only the intended destination
748 should add this gline */
751 if (!(host = strchr(parv[2], '@'))) {
753 * convert user@host no @'s; assume username is '*'
760 *(host++) = '\0'; /* break up string at the '@' */
762 ip_mask = check_if_ipmask(host); /* Store this boolean */
764 if ('#' == *host || '&' == *host || '+' == *host)
765 gtype = 1; /* BAD CHANNEL GLINE */
767 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
770 if (0 == ircd_strcmp(gline->name, user) &&
771 0 == ircd_strcmp(gline->host, host))
776 if (!active && gline)
779 * removing the gline, notify opers
781 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
782 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
785 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
786 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
790 free_gline(gline, prev); /* remove the gline */
793 { /* must be adding a gline */
794 expire = atoi(parv[3]) + TStime(); /* expire time? */
795 if (gline && gline->expire < expire)
796 { /* new expire time? */
797 /* yes, notify the opers */
798 sendto_op_mask(SNO_GLINE,
799 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
800 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
803 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
804 "on %s for %s@%s to " TIME_T_FMT "\n",
805 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
806 gline->name, gline->host, expire);
809 gline->expire = expire; /* reset the expire time */
813 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
814 if (!mmatch(gline->name, user) &&
815 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
816 !mmatch(gline->host, host))
817 return 0; /* found an existing G-line that matches */
820 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
825 else if (parc < 2 || *parv[1] == '\0')
827 /* Not enough args and a user; list glines */
828 for (gline = GlobalGlineList; gline; gline = gline->next)
829 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
830 gline->name, gline->host, gline->expire, gline->reason,
831 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
833 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
840 priv = IsAnOper(cptr);
846 { /* non-oper not permitted to change things */
848 { /* oper wants to deactivate the gline */
852 else if (*parv[1] == '+')
853 { /* oper wants to activate inactive gline */
861 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
867 if (!(host = strchr(parv[1], '@')))
869 user = "*"; /* no @'s; assume username is '*' */
875 *(host++) = '\0'; /* break up string at the '@' */
877 ip_mask = check_if_ipmask(host); /* Store this boolean */
879 if ('#' == *host || '&' == *host || '+' == *host)
880 #ifndef LOCAL_BADCHAN
883 gtype = 1; /* BAD CHANNEL */
887 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
890 if (!mmatch(gline->name, user) &&
891 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
892 !mmatch(gline->host, host))
900 if (priv && active && expire > CurrentTime)
902 /* Add local G-line */
903 if (parc < 4 || !strchr(parv[3], ' '))
904 return need_more_params(sptr, "GLINE");
906 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
910 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
916 if (expire <= gline->expire)
920 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
923 /* oper wants a list of one gline only */
924 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
925 gline->host, gline->expire, gline->reason,
926 GlineIsActive(gline) ? "" : " (Inactive)");
927 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
932 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
934 if (active) /* reset activation on gline */
937 else if (GlineIsLocal(gline))
939 /* Remove local G-line */
940 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
941 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
943 write_log(GPATH, "# " TIME_T_FMT
944 " %s!%s@%s removed local %s for %s@%s\n",
945 TStime(), parv[0], cptr->user->username, cptr->user->host,
946 gtype ? "BADCHAN" : "GLINE",
947 gline->name, gline->host);
949 free_gline(gline, prev); /* remove the gline */
957 active = -1; /* for later sendto_ops and logging functions */
960 gline->expire = expire; /* reset expiration time */
962 /* inform the operators what's up */
964 { /* changing the activation */
965 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
966 "%s %sactivating %s for %s@%s and "
967 "resetting expiration time to " TIME_T_FMT,
968 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
969 gline->name, gline->host, gline->expire);
971 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
972 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
973 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
974 TStime(), parv[0], cptr->user->username, cptr->user->host,
975 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
976 gline->host, gline->expire);
981 { /* changing only the expiration */
982 sendto_op_mask(SNO_GLINE,
983 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
984 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
987 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
988 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
989 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
990 gline->name, gline->host, gline->expire);
1002 * parv[0] = Send prefix
1006 * parv[1] = Target: server numeric
1007 * parv[2] = [+|-]<G-line mask>
1008 * parv[3] = Expiration offset
1013 * parv[1] = [+|-]<G-line mask>
1014 * parv[2] = Expiration offset
1018 int m_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
1020 struct Client* acptr = 0; /* Init. to avoid compiler warning. */
1021 struct Gline* gline;
1031 * Remove expired G-lines
1033 gline_remove_expired(TStime());
1036 * Remove expired bad channels
1038 bad_channel_remove_expired(TStime());
1041 if (IsServer(cptr)) {
1042 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD)) {
1043 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
1044 return need_more_params(sptr, "GLINE");
1046 if (*parv[2] == '-') /* add mode or delete mode? */
1051 if (*parv[2] == '+' || *parv[2] == '-')
1052 parv[2]++; /* step past mode indicator */
1055 * forward the message appropriately
1057 if (0 == ircd_strcmp(parv[1], "*")) {
1061 sendto_serv_butone(cptr,
1062 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
1063 NumServ(cptr), parv[1], parv[2], parv[3], parv[4]);
1068 * REMOVE THIS after all servers upgraded to 2.10.01 and
1069 * Uworld uses a numeric too
1071 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
1072 (strlen(parv[1]) == 1 &&
1074 !(acptr = FindNServer(parv[1]))))
1075 return 0; /* no such server/user exists; forget it */
1079 * REMOVE THIS after all servers upgraded to 2.10.01 and
1080 * Uworld uses a numeric too
1082 if (IsServer(acptr) || !MyConnect(acptr))
1085 /* single destination */
1087 active ? "%s " TOK_GLINE " %s +%s %s :%s" : "%s " TOK_GLINE " %s -%s",
1088 NumServ(sptr), parv[1], parv[2], parv[3], parv[4]);
1089 return 0; /* only the intended destination
1090 should add this gline */
1093 if (!(host = strchr(parv[2], '@'))) {
1095 * convert user@host no @'s; assume username is '*'
1102 *(host++) = '\0'; /* break up string at the '@' */
1104 ip_mask = check_if_ipmask(host); /* Store this boolean */
1106 if ('#' == *host || '&' == *host || '+' == *host)
1107 gtype = 1; /* BAD CHANNEL GLINE */
1109 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
1110 gline = gline->next)
1112 if (0 == ircd_strcmp(gline->name, user) &&
1113 0 == ircd_strcmp(gline->host, host))
1118 if (!active && gline)
1121 * removing the gline, notify opers
1123 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
1124 gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
1127 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
1128 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE", gline->name,
1132 free_gline(gline, prev); /* remove the gline */
1135 { /* must be adding a gline */
1136 expire = atoi(parv[3]) + TStime(); /* expire time? */
1137 if (gline && gline->expire < expire)
1138 { /* new expire time? */
1139 /* yes, notify the opers */
1140 sendto_op_mask(SNO_GLINE,
1141 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1142 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
1145 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
1146 "on %s for %s@%s to " TIME_T_FMT "\n",
1147 TStime(), parv[0], gtype ? "BADCHAN" : "GLINE",
1148 gline->name, gline->host, expire);
1151 gline->expire = expire; /* reset the expire time */
1154 { /* create gline */
1155 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList; gline; gline = gline->next)
1156 if (!mmatch(gline->name, user) &&
1157 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
1158 !mmatch(gline->host, host))
1159 return 0; /* found an existing G-line that matches */
1162 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
1167 else if (parc < 2 || *parv[1] == '\0')
1169 /* Not enough args and a user; list glines */
1170 for (gline = GlobalGlineList; gline; gline = gline->next)
1171 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
1172 gline->name, gline->host, gline->expire, gline->reason,
1173 GlineIsActive(gline) ? (GlineIsLocal(gline) ? " (local)" : "") :
1175 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1182 priv = IsAnOper(cptr);
1184 priv = IsOper(cptr);
1188 { /* non-oper not permitted to change things */
1189 if (*parv[1] == '-')
1190 { /* oper wants to deactivate the gline */
1194 else if (*parv[1] == '+')
1195 { /* oper wants to activate inactive gline */
1203 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
1209 if (!(host = strchr(parv[1], '@')))
1211 user = "*"; /* no @'s; assume username is '*' */
1217 *(host++) = '\0'; /* break up string at the '@' */
1219 ip_mask = check_if_ipmask(host); /* Store this boolean */
1221 if ('#' == *host || '&' == *host || '+' == *host)
1222 #ifndef LOCAL_BADCHAN
1225 gtype = 1; /* BAD CHANNEL */
1229 for (gline = (gtype) ? BadChanGlineList : GlobalGlineList, prev = 0; gline;
1230 gline = gline->next)
1232 if (!mmatch(gline->name, user) &&
1233 (ip_mask ? GlineIsIpMask(gline) : !GlineIsIpMask(gline)) &&
1234 !mmatch(gline->host, host))
1242 if (priv && active && expire > CurrentTime)
1244 /* Add local G-line */
1245 if (parc < 4 || !strchr(parv[3], ' '))
1246 return need_more_params(sptr, "GLINE");
1248 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
1252 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
1258 if (expire <= gline->expire)
1261 if ((active == -1 ||
1262 (active ? GlineIsActive(gline) : !GlineIsActive(gline))) &&
1265 /* oper wants a list of one gline only */
1266 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], gline->name,
1267 gline->host, gline->expire, gline->reason,
1268 GlineIsActive(gline) ? "" : " (Inactive)");
1269 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1274 (active ? !GlineIsActive(gline) : GlineIsActive(gline)))
1276 if (active) /* reset activation on gline */
1279 else if (GlineIsLocal(gline))
1281 /* Remove local G-line */
1282 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
1283 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host);
1285 write_log(GPATH, "# " TIME_T_FMT
1286 " %s!%s@%s removed local %s for %s@%s\n",
1287 TStime(), parv[0], cptr->user->username, cptr->user->host,
1288 gtype ? "BADCHAN" : "GLINE",
1289 gline->name, gline->host);
1291 free_gline(gline, prev); /* remove the gline */
1299 active = -1; /* for later sendto_ops and logging functions */
1302 gline->expire = expire; /* reset expiration time */
1304 /* inform the operators what's up */
1306 { /* changing the activation */
1307 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
1308 "%s %sactivating %s for %s@%s and "
1309 "resetting expiration time to " TIME_T_FMT,
1310 parv[0], active ? "re" : "de", gtype ? "BADCHAN" : "GLINE",
1311 gline->name, gline->host, gline->expire);
1313 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
1314 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
1315 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
1316 TStime(), parv[0], cptr->user->username, cptr->user->host,
1317 active ? "re" : "de", gtype ? "BADCHAN" : "GLINE", gline->name,
1318 gline->host, gline->expire);
1323 { /* changing only the expiration */
1324 sendto_op_mask(SNO_GLINE,
1325 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1326 parv[0], gtype ? "BADCHAN" : "GLINE", gline->name, gline->host,
1329 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
1330 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
1331 cptr->user->username, cptr->user->host, gtype ? "BADCHAN" : "GLINE",
1332 gline->name, gline->host, gline->expire);