Move check_if_ipmask() from support.* to match.*.
[ircu2.10.12-pk.git] / ircd / jupe.c
1 /*
2  * IRC - Internet Relay Chat, ircd/jupe.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Finland
5  * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 1, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * $Id$
22  */
23 #include "config.h"
24
25 #include "jupe.h"
26 #include "client.h"
27 #include "hash.h"
28 #include "ircd.h"
29 #include "ircd_alloc.h"
30 #include "ircd_features.h"
31 #include "ircd_log.h"
32 #include "ircd_reply.h"
33 #include "ircd_string.h"
34 #include "match.h"
35 #include "msg.h"
36 #include "numeric.h"
37 #include "numnicks.h"
38 #include "s_bsd.h"
39 #include "s_misc.h"
40 #include "send.h"
41 #include "struct.h"
42 #include "sys.h"    /* FALSE bleah */
43
44 #include <assert.h>
45 #include <string.h>
46
47 static struct Jupe *GlobalJupeList = 0;
48
49 static struct Jupe *
50 make_jupe(char *server, char *reason, time_t expire, time_t lastmod,
51           unsigned int flags)
52 {
53   struct Jupe *ajupe;
54
55   ajupe = (struct Jupe*) MyMalloc(sizeof(struct Jupe)); /* alloc memory */
56   assert(0 != ajupe);
57
58   DupString(ajupe->ju_server, server); /* copy vital information */
59   DupString(ajupe->ju_reason, reason);
60   ajupe->ju_expire = expire;
61   ajupe->ju_lastmod = lastmod;
62   ajupe->ju_flags = flags & JUPE_MASK; /* set jupe flags */
63
64   ajupe->ju_next = GlobalJupeList; /* link it into the list */
65   ajupe->ju_prev_p = &GlobalJupeList;
66   if (GlobalJupeList)
67     GlobalJupeList->ju_prev_p = &ajupe->ju_next;
68   GlobalJupeList = ajupe;
69
70   return ajupe;
71 }
72
73 static int
74 do_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
75 {
76   struct Client *acptr;
77
78   if (!JupeIsActive(jupe)) /* no action to be taken on inactive jupes */
79     return 0;
80
81   acptr = FindServer(jupe->ju_server);
82
83   /* server isn't online or isn't local or is me */
84   if (!acptr || !MyConnect(acptr) || IsMe(acptr))
85     return 0;
86
87   return exit_client_msg(cptr, acptr, &me, "Juped: %s", jupe->ju_reason);
88 }
89
90 static void
91 propagate_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
92 {
93   if (JupeIsLocal(jupe)) /* don't propagate local jupes */
94     return;
95
96   sendcmdto_serv_butone(sptr, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
97                         JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
98                         jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
99                         jupe->ju_reason);
100 }
101
102 int
103 jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason,
104          time_t expire, time_t lastmod, unsigned int flags)
105 {
106   struct Jupe *ajupe;
107
108   assert(0 != server);
109   assert(0 != reason);
110
111   /*
112    * You cannot set a negative (or zero) expire time, nor can you set an
113    * expiration time for greater than JUPE_MAX_EXPIRE.
114    */
115   if (expire <= 0 || expire > JUPE_MAX_EXPIRE) {
116     if (!IsServer(cptr) && MyConnect(cptr))
117       send_reply(cptr, ERR_BADEXPIRE, expire);
118     return 0;
119   }
120
121   expire += CurrentTime; /* convert from lifetime to timestamp */
122
123   /* Inform ops and log it */
124   sendto_opmask_butone(0, SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
125                        "%Tu: %s",
126                        (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
127                          cli_name(sptr) :
128                          cli_name((cli_user(sptr))->server),
129                        flags & JUPE_LOCAL ? "local " : "", server,
130                        expire + TSoffset, reason);
131
132   log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
133             "%#C adding %sJUPE for %s, expiring at %Tu: %s", sptr,
134             flags & JUPE_LOCAL ? "local " : "", server, expire + TSoffset,
135             reason);
136
137   /* make the jupe */
138   ajupe = make_jupe(server, reason, expire, lastmod, flags);
139
140   propagate_jupe(cptr, sptr, ajupe);
141
142   return do_jupe(cptr, sptr, ajupe); /* remove server if necessary */
143 }
144
145 int
146 jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
147               time_t lastmod, unsigned int flags)
148 {
149   unsigned int saveflags = 0;
150
151   assert(0 != jupe);
152
153   saveflags = jupe->ju_flags;
154
155   if (flags & JUPE_LOCAL)
156     jupe->ju_flags &= ~JUPE_LDEACT;
157   else {
158     jupe->ju_flags |= JUPE_ACTIVE;
159
160     if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
161       jupe->ju_lastmod++;
162     else
163       jupe->ju_lastmod = lastmod;
164   }
165
166   if ((saveflags & JUPE_ACTMASK) == JUPE_ACTIVE)
167     return 0; /* was active to begin with */
168
169   /* Inform ops and log it */
170   sendto_opmask_butone(0, SNO_NETWORK, "%s activating JUPE for %s, expiring "
171                        "at %Tu: %s",
172                        (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
173                          cli_name(sptr) :
174                          cli_name((cli_user(sptr))->server),
175                        jupe->ju_server, jupe->ju_expire + TSoffset,
176                        jupe->ju_reason);
177
178   log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
179             "%#C activating JUPE for %s, expiring at %Tu: %s",sptr,
180             jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
181
182   if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
183     propagate_jupe(cptr, sptr, jupe);
184
185   return do_jupe(cptr, sptr, jupe);
186 }
187
188 int
189 jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
190                 time_t lastmod, unsigned int flags)
191 {
192   unsigned int saveflags = 0;
193
194   assert(0 != jupe);
195
196   saveflags = jupe->ju_flags;
197
198   if (!JupeIsLocal(jupe)) {
199     if (flags & JUPE_LOCAL)
200       jupe->ju_flags |= JUPE_LDEACT;
201     else {
202       jupe->ju_flags &= ~JUPE_ACTIVE;
203
204       if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
205         jupe->ju_lastmod++;
206       else
207         jupe->ju_lastmod = lastmod;
208     }
209
210     if ((saveflags & JUPE_ACTMASK) != JUPE_ACTIVE)
211       return 0; /* was inactive to begin with */
212   }
213
214   /* Inform ops and log it */
215   sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
216                        "%s",
217                        (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
218                          cli_name(sptr) :
219                          cli_name((cli_user(sptr))->server),
220                        JupeIsLocal(jupe) ? "removing local" : "deactivating",
221                        jupe->ju_server, jupe->ju_expire + TSoffset,
222                        jupe->ju_reason);
223
224   log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
225             "%#C %s JUPE for %s, expiring at %Tu: %s", sptr,
226             JupeIsLocal(jupe) ? "removing local" : "deactivating",
227             jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
228
229   if (JupeIsLocal(jupe))
230     jupe_free(jupe);
231   else if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
232     propagate_jupe(cptr, sptr, jupe);
233
234   return 0;
235 }
236
237 struct Jupe *
238 jupe_find(char *server)
239 {
240   struct Jupe* jupe;
241   struct Jupe* sjupe;
242
243   for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
244     sjupe = jupe->ju_next;
245
246     if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
247       jupe_free(jupe);
248     else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */
249       return jupe;
250   }
251
252   return 0;
253 }
254
255 void
256 jupe_free(struct Jupe* jupe)
257 {
258   assert(0 != jupe);
259
260   *jupe->ju_prev_p = jupe->ju_next; /* squeeze this jupe out */
261   if (jupe->ju_next)
262     jupe->ju_next->ju_prev_p = jupe->ju_prev_p;
263
264   MyFree(jupe->ju_server);  /* and free up the memory */
265   MyFree(jupe->ju_reason);
266   MyFree(jupe);
267 }
268
269 void
270 jupe_burst(struct Client *cptr)
271 {
272   struct Jupe *jupe;
273   struct Jupe *sjupe;
274
275   for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
276     sjupe = jupe->ju_next;
277
278     if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
279       jupe_free(jupe);
280     else if (!JupeIsLocal(jupe)) /* forward global jupes */
281       sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
282                     JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
283                     jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
284                     jupe->ju_reason);
285   }
286 }
287
288 int
289 jupe_resend(struct Client *cptr, struct Jupe *jupe)
290 {
291   if (JupeIsLocal(jupe)) /* don't propagate local jupes */
292     return 0;
293
294   sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
295                 JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
296                 jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
297                 jupe->ju_reason);
298
299   return 0;
300 }
301
302 int
303 jupe_list(struct Client *sptr, char *server)
304 {
305   struct Jupe *jupe;
306   struct Jupe *sjupe;
307
308   if (server) {
309     if (!(jupe = jupe_find(server))) /* no such jupe */
310       return send_reply(sptr, ERR_NOSUCHJUPE, server);
311
312     /* send jupe information along */
313     send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
314                JupeIsLocal(jupe) ? cli_name(&me) : "*",
315                JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
316   } else {
317     for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
318       sjupe = jupe->ju_next;
319
320       if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
321         jupe_free(jupe);
322       else /* send jupe information along */
323         send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
324                    jupe->ju_expire + TSoffset,
325                    JupeIsLocal(jupe) ? cli_name(&me) : "*",
326                    JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
327     }
328   }
329
330   /* end of jupe information */
331   return send_reply(sptr, RPL_ENDOFJUPELIST);
332 }
333
334 int
335 jupe_memory_count(size_t *ju_size)
336 {
337   struct Jupe *jupe;
338   unsigned int ju = 0;
339
340   for (jupe = GlobalJupeList; jupe; jupe = jupe->ju_next)
341   {
342     ju++;
343     *ju_size += sizeof(struct Jupe);
344     *ju_size += jupe->ju_server ? (strlen(jupe->ju_server) + 1) : 0;
345     *ju_size += jupe->ju_reason ? (strlen(jupe->ju_reason) + 1) : 0;
346   }
347   return ju;
348 }