]> jfr.im git - irc/quakenet/snircd.git/blame - ircd/jupe.c
add sbounce from asuka into snircd tree
[irc/quakenet/snircd.git] / ircd / jupe.c
CommitLineData
189935b1 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/** @file
22 * @brief Implementation of juped server handling functions.
9f8856e9 23 * @version $Id: jupe.c,v 1.20.2.1 2006/03/25 03:46:56 entrope Exp $
189935b1 24 */
25#include "config.h"
26
27#include "jupe.h"
28#include "client.h"
29#include "hash.h"
30#include "ircd.h"
31#include "ircd_alloc.h"
32#include "ircd_features.h"
33#include "ircd_log.h"
34#include "ircd_reply.h"
35#include "ircd_string.h"
36#include "match.h"
37#include "msg.h"
38#include "numeric.h"
39#include "numnicks.h"
40#include "s_bsd.h"
41#include "s_misc.h"
42#include "send.h"
43#include "struct.h"
44#include "sys.h" /* FALSE bleah */
45
46/* #include <assert.h> -- Now using assert in ircd_log.h */
47#include <string.h>
48
49/** List of jupes. */
50static struct Jupe *GlobalJupeList = 0;
51
52/** Allocate a new jupe with the given parameters.
53 * @param[in] server Server name to jupe.
54 * @param[in] reason Reason for jupe.
55 * @param[in] expire Expiration time for jupe.
56 * @param[in] lastmod Last modification time for jupe.
57 * @param[in] flags Flags to set for the jupe.
58 */
59static struct Jupe *
60make_jupe(char *server, char *reason, time_t expire, time_t lastmod,
61 unsigned int flags)
62{
63 struct Jupe *ajupe;
64
65 ajupe = (struct Jupe*) MyMalloc(sizeof(struct Jupe)); /* alloc memory */
66 assert(0 != ajupe);
67
9f8856e9 68 memset(ajupe, 0, sizeof(*ajupe));
189935b1 69 DupString(ajupe->ju_server, server); /* copy vital information */
70 DupString(ajupe->ju_reason, reason);
71 ajupe->ju_expire = expire;
72 ajupe->ju_lastmod = lastmod;
73 ajupe->ju_flags = flags & JUPE_MASK; /* set jupe flags */
74
75 ajupe->ju_next = GlobalJupeList; /* link it into the list */
76 ajupe->ju_prev_p = &GlobalJupeList;
77 if (GlobalJupeList)
78 GlobalJupeList->ju_prev_p = &ajupe->ju_next;
79 GlobalJupeList = ajupe;
80
81 return ajupe;
82}
83
84/** Apply a jupe.
85 * @param[in] cptr Local client that sent us the jupe.
86 * @param[in] sptr Originator of the jupe.
87 * @param[in] jupe Jupe to check.
88 */
89static int
90do_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
91{
92 struct Client *acptr;
93
94 if (!JupeIsActive(jupe)) /* no action to be taken on inactive jupes */
95 return 0;
96
97 acptr = FindServer(jupe->ju_server);
98
99 /* server isn't online or isn't local or is me */
100 if (!acptr || !MyConnect(acptr) || IsMe(acptr))
101 return 0;
102
103 return exit_client_msg(cptr, acptr, &me, "Juped: %s", jupe->ju_reason);
104}
105
106/** Forward a jupe to another server.
107 * @param[in] cptr Local client that sent us the jupe.
108 * @param[in] sptr Originator of the jupe.
109 * @param[in] jupe Jupe to forward.
110 */
111static void
112propagate_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe)
113{
114 if (JupeIsLocal(jupe)) /* don't propagate local jupes */
115 return;
116
117 sendcmdto_serv_butone(sptr, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
118 JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
119 jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
120 jupe->ju_reason);
121}
122
123/** Add a new server jupe.
124 * @param[in] cptr Local client that sent us the jupe.
125 * @param[in] sptr Originator of the jupe.
126 * @param[in] server Server name to jupe.
127 * @param[in] reason Reason for the jupe.
128 * @param[in] expire Jupe duration in seconds.
129 * @param[in] lastmod Last modification timestamp (or NULL).
130 * @param[in] flags Flags to set on jupe.
131 * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
132 * case CPTR_KILLED.
133 */
134int
135jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason,
136 time_t expire, time_t lastmod, unsigned int flags)
137{
138 struct Jupe *ajupe;
139
140 assert(0 != server);
141 assert(0 != reason);
142
143 /*
144 * You cannot set a negative (or zero) expire time, nor can you set an
145 * expiration time for greater than JUPE_MAX_EXPIRE.
146 */
147 if (expire <= 0 || expire > JUPE_MAX_EXPIRE) {
148 if (!IsServer(cptr) && MyConnect(cptr))
149 send_reply(cptr, ERR_BADEXPIRE, expire);
150 return 0;
151 }
152
153 expire += CurrentTime; /* convert from lifetime to timestamp */
154
155 /* Inform ops and log it */
156 sendto_opmask_butone(0, SNO_NETWORK, "%s adding %sJUPE for %s, expiring at "
157 "%Tu: %s",
158 (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
159 cli_name(sptr) :
160 cli_name((cli_user(sptr))->server),
161 flags & JUPE_LOCAL ? "local " : "", server,
162 expire + TSoffset, reason);
163
164 log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
165 "%#C adding %sJUPE for %s, expiring at %Tu: %s", sptr,
166 flags & JUPE_LOCAL ? "local " : "", server, expire + TSoffset,
167 reason);
168
169 /* make the jupe */
170 ajupe = make_jupe(server, reason, expire, lastmod, flags);
171
172 propagate_jupe(cptr, sptr, ajupe);
173
174 return do_jupe(cptr, sptr, ajupe); /* remove server if necessary */
175}
176
177/** Activate a jupe, optionally changing its lastmod and flags.
178 * @param[in] cptr Local client that sent us the jupe.
179 * @param[in] sptr Originator of the jupe.
180 * @param[in] jupe Jupe to activate.
181 * @param[in] lastmod New timestamp for last modification of the jupe.
182 * @param[in] flags Flags to set on the jupe.
183 * @return Zero, unless the jupe causes \a cptr to be SQUIT, in which
184 * case CPTR_KILLED.
185 */
186int
187jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
188 time_t lastmod, unsigned int flags)
189{
190 unsigned int saveflags = 0;
191
192 assert(0 != jupe);
193
194 saveflags = jupe->ju_flags;
195
196 if (flags & JUPE_LOCAL)
197 jupe->ju_flags &= ~JUPE_LDEACT;
198 else {
199 jupe->ju_flags |= JUPE_ACTIVE;
200
201 if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
202 jupe->ju_lastmod++;
203 else
204 jupe->ju_lastmod = lastmod;
205 }
206
207 if ((saveflags & JUPE_ACTMASK) == JUPE_ACTIVE)
208 return 0; /* was active to begin with */
209
210 /* Inform ops and log it */
211 sendto_opmask_butone(0, SNO_NETWORK, "%s activating JUPE for %s, expiring "
212 "at %Tu: %s",
213 (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
214 cli_name(sptr) :
215 cli_name((cli_user(sptr))->server),
216 jupe->ju_server, jupe->ju_expire + TSoffset,
217 jupe->ju_reason);
218
219 log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
220 "%#C activating JUPE for %s, expiring at %Tu: %s",sptr,
221 jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
222
223 if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
224 propagate_jupe(cptr, sptr, jupe);
225
226 return do_jupe(cptr, sptr, jupe);
227}
228
229/** Deactivate a jupe.
230 * @param[in] cptr Local client that sent us the jupe.
231 * @param[in] sptr Originator of the jupe.
232 * @param[in] jupe Jupe to deactivate.
233 * @param[in] lastmod New timestamp for last modification of the jupe.
234 * @param[in] flags Flags to set on the jupe.
235 * @return Zero.
236 */
237int
238jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
239 time_t lastmod, unsigned int flags)
240{
241 unsigned int saveflags = 0;
242
243 assert(0 != jupe);
244
245 saveflags = jupe->ju_flags;
246
247 if (!JupeIsLocal(jupe)) {
248 if (flags & JUPE_LOCAL)
249 jupe->ju_flags |= JUPE_LDEACT;
250 else {
251 jupe->ju_flags &= ~JUPE_ACTIVE;
252
253 if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
254 jupe->ju_lastmod++;
255 else
256 jupe->ju_lastmod = lastmod;
257 }
258
259 if ((saveflags & JUPE_ACTMASK) != JUPE_ACTIVE)
260 return 0; /* was inactive to begin with */
261 }
262
263 /* Inform ops and log it */
264 sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
265 "%s",
266 (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
267 cli_name(sptr) :
268 cli_name((cli_user(sptr))->server),
269 JupeIsLocal(jupe) ? "removing local" : "deactivating",
270 jupe->ju_server, jupe->ju_expire + TSoffset,
271 jupe->ju_reason);
272
273 log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
274 "%#C %s JUPE for %s, expiring at %Tu: %s", sptr,
275 JupeIsLocal(jupe) ? "removing local" : "deactivating",
276 jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);
277
278 if (JupeIsLocal(jupe))
279 jupe_free(jupe);
280 else if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
281 propagate_jupe(cptr, sptr, jupe);
282
283 return 0;
284}
285
286/** Find a jupe by name.
287 * @param[in] server %Jupe name to search for.
288 * @return Matching jupe (or NULL if none match).
289 */
290struct Jupe *
291jupe_find(char *server)
292{
293 struct Jupe* jupe;
294 struct Jupe* sjupe;
295
296 for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
297 sjupe = jupe->ju_next;
298
299 if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
300 jupe_free(jupe);
301 else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */
302 return jupe;
303 }
304
305 return 0;
306}
307
308/** Unlink and free an unused jupe.
309 * @param[in] jupe Server jupe to free.
310 */
311void
312jupe_free(struct Jupe* jupe)
313{
314 assert(0 != jupe);
315
316 *jupe->ju_prev_p = jupe->ju_next; /* squeeze this jupe out */
317 if (jupe->ju_next)
318 jupe->ju_next->ju_prev_p = jupe->ju_prev_p;
319
320 MyFree(jupe->ju_server); /* and free up the memory */
321 MyFree(jupe->ju_reason);
322 MyFree(jupe);
323}
324
325/** Send the full list of active global jupes to \a cptr.
326 * @param[in] cptr Local server to send jupes to.
327 */
328void
329jupe_burst(struct Client *cptr)
330{
331 struct Jupe *jupe;
332 struct Jupe *sjupe;
333
334 for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
335 sjupe = jupe->ju_next;
336
337 if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
338 jupe_free(jupe);
339 else if (!JupeIsLocal(jupe)) /* forward global jupes */
340 sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
341 JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
342 jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
343 jupe->ju_reason);
344 }
345}
346
347/** Forward a jupe to another server.
348 * @param[in] cptr %Server to send jupe to.
349 * @param[in] jupe Jupe to forward.
350 */
351int
352jupe_resend(struct Client *cptr, struct Jupe *jupe)
353{
354 if (JupeIsLocal(jupe)) /* don't propagate local jupes */
355 return 0;
356
357 sendcmdto_one(&me, CMD_JUPE, cptr, "* %c%s %Tu %Tu :%s",
358 JupeIsRemActive(jupe) ? '+' : '-', jupe->ju_server,
359 jupe->ju_expire - CurrentTime, jupe->ju_lastmod,
360 jupe->ju_reason);
361
362 return 0;
363}
364
365/** Send a jupe (or a list of jupes) to a server.
366 * @param[in] sptr Client searching for jupes.
367 * @param[in] server Name of jupe to search for (if NULL, list all).
368 * @return Zero.
369 */
370int
371jupe_list(struct Client *sptr, char *server)
372{
373 struct Jupe *jupe;
374 struct Jupe *sjupe;
375
376 if (server) {
377 if (!(jupe = jupe_find(server))) /* no such jupe */
378 return send_reply(sptr, ERR_NOSUCHJUPE, server);
379
380 /* send jupe information along */
381 send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
382 JupeIsLocal(jupe) ? cli_name(&me) : "*",
383 JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
384 } else {
385 for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
386 sjupe = jupe->ju_next;
387
388 if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
389 jupe_free(jupe);
390 else /* send jupe information along */
391 send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
392 jupe->ju_expire + TSoffset,
393 JupeIsLocal(jupe) ? cli_name(&me) : "*",
394 JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
395 }
396 }
397
398 /* end of jupe information */
399 return send_reply(sptr, RPL_ENDOFJUPELIST);
400}
401
402/** Count jupes and memory used by them.
403 * @param[out] ju_size Receives total number of bytes allocated for jupes.
404 * @return Number of jupes currently allocated.
405 */
406int
407jupe_memory_count(size_t *ju_size)
408{
409 struct Jupe *jupe;
410 unsigned int ju = 0;
411
412 for (jupe = GlobalJupeList; jupe; jupe = jupe->ju_next)
413 {
414 ju++;
415 *ju_size += sizeof(struct Jupe);
416 *ju_size += jupe->ju_server ? (strlen(jupe->ju_server) + 1) : 0;
417 *ju_size += jupe->ju_reason ? (strlen(jupe->ju_reason) + 1) : 0;
418 }
419 return ju;
420}