]>
jfr.im git - irc/quakenet/newserv.git/blob - glines/glines_buf.c
4 #include "../lib/array.h"
5 #include "../lib/irc_string.h"
6 #include "../irc/irc.h"
7 #include "../control/control.h"
8 #include "../trusts/trusts.h"
11 static int nextglinebufid
= 1;
12 glinebuf
*glinebuflog
[MAXGLINELOG
] = {};
13 int glinebuflogoffset
= 0;
15 void glinebufinit(glinebuf
*gbuf
, int merge
) {
21 gbuf
->channelhits
= 0;
22 array_init(&gbuf
->hits
, sizeof(sstring
*));
25 gline
*glinebufadd(glinebuf
*gbuf
, const char *mask
, const char *creator
, const char *reason
, time_t expire
, time_t lastmod
, time_t lifetime
) {
26 gline
*gl
, *sgl
, **pnext
;
28 gl
= makegline(mask
); /* sets up nick,user,host,node and flags */
31 /* couldn't process gline mask */
32 Error("gline", ERR_WARNING
, "Tried to add malformed G-Line %s!", mask
);
37 /* Check if an existing gline supercedes this mask */
38 for (sgl
= gbuf
->glines
; sgl
; sgl
= sgl
->next
) {
39 if (gline_match_mask(sgl
, gl
)) {
45 /* Remove older glines this gline matches */
46 for (pnext
= &gbuf
->glines
; *pnext
; pnext
= &((*pnext
)->next
)) {
49 if (gline_match_mask(gl
, sgl
)) {
59 gl
->creator
= getsstring(creator
, 255);
61 /* it's not unreasonable to assume gline is active, if we're adding a deactivated gline, we can remove this later */
62 gl
->flags
|= GLINE_ACTIVE
;
64 gl
->reason
= getsstring(reason
, 255);
66 gl
->lastmod
= lastmod
;
67 gl
->lifetime
= lifetime
;
69 gl
->next
= gbuf
->glines
;
75 void glinebufaddbyip(glinebuf
*gbuf
, const char *user
, struct irc_in_addr
*ip
, unsigned char bits
, int flags
, const char *creator
, const char *reason
, time_t expire
, time_t lastmod
, time_t lifetime
) {
78 unsigned char nodebits
;
80 nodebits
= getnodebits(ip
);
82 if (!(flags
& GLINE_IGNORE_TRUST
)) {
83 th
= th_getbyhost(ip
);
85 if (th
&& (th
->group
->flags
& TRUST_RELIABLE_USERNAME
)) { /* Trust with reliable usernames */
86 for (oth
= th
->group
->hosts
; oth
; oth
= oth
->next
)
87 glinebufaddbyip(gbuf
, user
, &oth
->ip
, oth
->bits
, flags
| GLINE_ALWAYS_USER
| GLINE_IGNORE_TRUST
, creator
, reason
, expire
, lastmod
, lifetime
);
93 if (!(flags
& GLINE_ALWAYS_USER
))
96 /* Widen gline to match the node mask. */
100 snprintf(mask
, sizeof(mask
), "%s@%s", user
, trusts_cidr2str(ip
, bits
));
102 glinebufadd(gbuf
, mask
, creator
, reason
, expire
, lastmod
, lifetime
);
105 void glinebufaddbynick(glinebuf
*gbuf
, nick
*np
, int flags
, const char *creator
, const char *reason
, time_t expire
, time_t lastmod
, time_t lifetime
) {
106 if (flags
& GLINE_ALWAYS_NICK
) {
108 snprintf(mask
, sizeof(mask
), "%s!*@*", np
->nick
);
109 glinebufadd(gbuf
, mask
, creator
, reason
, expire
, lastmod
, lifetime
);
111 glinebufaddbyip(gbuf
, np
->ident
, &np
->p_ipaddr
, 128, flags
, creator
, reason
, expire
, lastmod
, lifetime
);
115 void glinebufcounthits(glinebuf
*gbuf
, int *users
, int *channels
, nick
*spewto
) {
124 gbuf
->channelhits
= 0;
126 for (i
= 0; i
< gbuf
->hits
.cursi
; i
++)
127 freesstring(((sstring
**)gbuf
->hits
.content
)[i
]);
129 array_free(&gbuf
->hits
);
130 array_init(&gbuf
->hits
, sizeof(sstring
*));
132 for (i
= 0; i
<CHANNELHASHSIZE
; i
++) {
133 for (cip
= chantable
[i
]; cip
; cip
= cip
->next
) {
141 for (gl
= gbuf
->glines
; gl
; gl
= gl
->next
) {
142 if (gline_match_channel(gl
, cp
)) {
149 snprintf(uhmask
, sizeof(uhmask
), "channel: %s", cip
->name
->content
);
152 controlreply(spewto
, "%s", uhmask
);
156 slot
= array_getfreeslot(&gbuf
->hits
);
157 ((sstring
**)gbuf
->hits
.content
)[slot
] = getsstring(uhmask
, 512);
162 for (i
= 0; i
< NICKHASHSIZE
; i
++) {
163 for (np
= nicktable
[i
]; np
; np
= np
->next
) {
166 for (gl
= gbuf
->glines
; gl
; gl
= gl
->next
) {
167 if (gline_match_nick(gl
, np
)) {
174 snprintf(uhmask
, sizeof(uhmask
), "user: %s!%s@%s r(%s)", np
->nick
, np
->ident
, np
->host
->name
->content
, np
->realname
->name
->content
);
177 controlreply(spewto
, "%s", uhmask
);
181 slot
= array_getfreeslot(&gbuf
->hits
);
182 ((sstring
**)gbuf
->hits
.content
)[slot
] = getsstring(uhmask
, 512);
188 *users
= gbuf
->userhits
;
191 *channels
= gbuf
->channelhits
;
194 int glinebufchecksane(glinebuf
*gbuf
, nick
*spewto
, int overridesanity
, int overridelimit
, int spewhits
) {
196 int users
, channels
, good
;
199 glinebufcounthits(gbuf
, &users
, &channels
, spewhits
? spewto
: NULL
);
201 if (!overridelimit
) {
202 if (channels
> MAXUSERGLINECHANNELHITS
) {
203 controlreply(spewto
, "G-Lines would hit %d channels. Limit is %d. Not setting G-Lines.", channels
, MAXUSERGLINECHANNELHITS
);
205 } else if (users
> MAXUSERGLINEUSERHITS
) {
206 controlreply(spewto
, "G-Lines would hit %d users. Limit is %d. Not setting G-Lines.", users
, MAXUSERGLINEUSERHITS
);
213 if (!overridesanity
) {
214 /* Remove glines that fail the sanity check */
215 for (gl
= gbuf
->glines
; gl
; gl
= gl
->next
) {
216 if (!isglinesane(gl
, &hint
)) {
217 controlreply(spewto
, "Sanity check failed for G-Line on '%s' - Skipping: %s",
218 glinetostring(gl
), hint
);
227 void glinebufspew(glinebuf
*gbuf
, nick
*spewto
) {
232 ref
= (gbuf
->flush
) ? gbuf
->flush
: getnettime();
234 controlreply(spewto
, "Mask Duration Creator Reason");
236 for (gl
= gbuf
->glines
; gl
; gl
= gl
->next
)
237 controlreply(spewto
, "%-40s %-20s %-20s %s", glinetostring(gl
), longtoduration(gl
->expire
- ref
, 0), gl
->creator
->content
, gl
->reason
->content
);
239 controlreply(spewto
, "Hit");
241 for (i
= 0; i
< gbuf
->hits
.cursi
; i
++)
242 controlreply(spewto
, "%s", ((sstring
**)gbuf
->hits
.content
)[i
]->content
);
245 void glinebufcommit(glinebuf
*gbuf
, int propagate
) {
246 gline
*gl
, *next
, *sgl
;
248 int users
, channels
, i
, slot
;
251 glinebufcounthits(gbuf
, &users
, &channels
, NULL
);
253 if (propagate
&& (users
> MAXGLINEUSERHITS
|| channels
> MAXGLINECHANNELHITS
)) {
254 controlwall(NO_OPER
, NL_GLINES
, "G-Line buffer would hit %d users/%d channels. Not setting G-Lines.");
262 /* Make a copy of the glinebuf for the log */
263 gbl
= malloc(sizeof(glinebuf
));
264 gbl
->id
= nextglinebufid
++;
265 gbl
->comment
= (gbuf
->comment
) ? getsstring(gbuf
->comment
->content
, 512) : NULL
;
266 gbl
->flush
= gbuf
->flush
;
267 gbl
->merge
= gbuf
->merge
;
268 gbl
->glines
= NULL
; /* going to set this later */
269 gbl
->userhits
= gbuf
->userhits
;
270 gbl
->channelhits
= gbuf
->channelhits
;
272 array_init(&gbl
->hits
, sizeof(sstring
*));
274 for (i
= 0; i
< gbuf
->hits
.cursi
; i
++) {
275 slot
= array_getfreeslot(&gbl
->hits
);
276 ((sstring
**)gbl
->hits
.content
)[slot
] = getsstring(((sstring
**)gbuf
->hits
.content
)[i
]->content
, 512);
280 for (gl
= gbuf
->glines
; gl
; gl
= next
) {
283 sgl
= findgline(glinetostring(gl
));
287 * in 1.4, can update expire, reason etc
288 * in 1.3 can only activate/deactivate an existing gline */
290 if (gl
->flags
& GLINE_ACTIVE
&& !(sgl
->flags
& GLINE_ACTIVE
))
291 gline_activate(sgl
, 0, 0);
292 else if (!(gl
->flags
& GLINE_ACTIVE
) && sgl
->flags
& GLINE_ACTIVE
)
293 gline_deactivate(sgl
, 0, 0);
295 #if SNIRCD_VERSION >= 140
296 sgl
->expire
= gl
->expire
;
298 if (gl
->lifetime
> sgl
->lifetime
)
299 sgl
->lifetime
= gl
->lifetime
;
301 freesstring(sgl
->reason
);
302 sgl
->reason
= getsstring(gl
->reason
, 512);
308 gl
->next
= glinelist
;
316 sgl
->next
= gbl
->glines
;
321 /* We've moved all glines to the gline list. Clear glines link in the glinebuf. */
324 if (propagate
&& gbl
->glines
) {
327 if (glinebuflogoffset
>= MAXGLINELOG
)
328 glinebuflogoffset
= 0;
330 if (glinebuflog
[glinebuflogoffset
])
331 glinebufabort(glinebuflog
[glinebuflogoffset
]);
333 glinebuflog
[glinebuflogoffset
]= gbl
;
339 void glinebufabort(glinebuf
*gbuf
) {
343 for (gl
= gbuf
->glines
; gl
; gl
= next
) {
349 freesstring(gbuf
->comment
);
351 for (i
= 0; i
< gbuf
->hits
.cursi
; i
++)
352 freesstring(((sstring
**)gbuf
->hits
.content
)[i
]);
354 array_free(&gbuf
->hits
);
357 int glinebufundo(int id
) {
362 for (i
= 0; i
< MAXGLINELOG
; i
++) {
363 gbl
= glinebuflog
[i
];
365 if (!gbl
|| gbl
->id
!= id
)
368 for (gl
= gbl
->glines
; gl
; gl
= gl
->next
) {
369 sgl
= findgline(glinetostring(gl
));
374 gline_deactivate(sgl
, 0, 1);
378 glinebuflog
[i
] = NULL
;
386 void glinebufcommentf(glinebuf
*gbuf
, const char *format
, ...) {
390 va_start(va
, format
);
391 vsnprintf(comment
, 511, format
, va
);
395 gbuf
->comment
= getsstring(comment
, 512);
398 void glinebufcommentv(glinebuf
*gbuf
, const char *prefix
, int cargc
, char **cargv
) {
403 strncpy(comment
, prefix
, sizeof(comment
));
407 for (i
= 0; i
< cargc
; i
++) {
409 strncat(comment
, " ", sizeof(comment
));
411 strncat(comment
, cargv
[i
], sizeof(comment
));
416 gbuf
->comment
= getsstring(comment
, 512);