]> jfr.im git - irc/quakenet/newserv.git/blame - glines/glines_buf.c
Refactor glines code to make hit tests for multiple glines easier.
[irc/quakenet/newserv.git] / glines / glines_buf.c
CommitLineData
cb581522
GB
1#include <stdio.h>
2#include <string.h>
3#include "../control/control.h"
4#include "../trusts/trusts.h"
5#include "glines.h"
6
7void glinebufinit(glinebuf *gbuf, int merge) {
8 gbuf->head = NULL;
9 gbuf->merge = merge;
10}
11
12gline *glinebufadd(glinebuf *gbuf, const char *mask, const char *creator, const char *reason, time_t expire, time_t lastmod, time_t lifetime) {
13 gline *gl, *sgl, **pnext;
14
15 gl = makegline(mask); /* sets up nick,user,host,node and flags */
16
17 if (!gl) {
18 /* couldn't process gline mask */
19 Error("gline", ERR_WARNING, "Tried to add malformed G-Line %s!", mask);
20 return 0;
21 }
22
23 if (gbuf->merge) {
24 /* Check if an existing gline supercedes this mask */
25 for (sgl = gbuf->head; sgl; sgl = sgl->next) {
26 if (gline_match_mask(sgl, gl)) {
27 freegline(gl);
28 return sgl;
29 }
30 }
31
32 /* Remove older glines this gline matches */
33 for (pnext = &gbuf->head; *pnext; pnext = &((*pnext)->next)) {
34 sgl = *pnext;
35
36 if (gline_match_mask(gl, sgl)) {
37 *pnext = sgl->next;
38 freegline(sgl);
39 }
40 }
41 }
42
43 gl->creator = getsstring(creator, 255);
44
45 /* it's not unreasonable to assume gline is active, if we're adding a deactivated gline, we can remove this later */
46 gl->flags |= GLINE_ACTIVE;
47
48 gl->reason = getsstring(reason, 255);
49 gl->expire = expire;
50 gl->lastmod = lastmod;
51 gl->lifetime = lifetime;
52
53 gl->next = gbuf->head;
54 gbuf->head = gl;
55
56 return gl;
57}
58
59void 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) {
60 trusthost *th, *oth;
61 char mask[512];
62 unsigned char nodebits;
63
64 nodebits = getnodebits(ip);
65
66 if (!(flags & GLINE_IGNORE_TRUST)) {
67 th = th_getbyhost(ip);
68
69 if (th && (th->group->flags & TRUST_RELIABLE_USERNAME)) { /* Trust with reliable usernames */
70 for(oth = th->group->hosts; oth; oth = oth->next)
71 glinebufaddbyip(gbuf, user, &oth->ip, oth->bits, flags | GLINE_ALWAYS_USER | GLINE_IGNORE_TRUST, creator, reason, expire, lastmod, lifetime);
72 }
73 }
74
75 if (!(flags & GLINE_ALWAYS_USER))
76 user = "*";
77
78 /* Widen gline to match the node mask. */
79 if (nodebits < bits)
80 bits = nodebits;
81
82 snprintf(mask, sizeof(mask), "%s@%s", user, trusts_cidr2str(ip, bits));
83
84 glinebufadd(gbuf, mask, creator, reason, expire, lastmod, lifetime);
85}
86
87void glinebufaddbynick(glinebuf *gbuf, nick *np, int flags, const char *creator, const char *reason, time_t expire, time_t lastmod, time_t lifetime) {
88 if (flags & GLINE_ALWAYS_NICK) {
89 char mask[512];
90 snprintf(mask, sizeof(mask), "%s!*@*", np->nick);
91 glinebufadd(gbuf, mask, creator, reason, expire, lastmod, lifetime);
92 } else {
93 glinebufaddbyip(gbuf, np->ident, &np->p_ipaddr, 128, flags, creator, reason, expire, lastmod, lifetime);
94 }
95}
96
97void glinebufcounthits(glinebuf *gbuf, int *users, int *channels) {
98 gline *gl;
99 int i, hit;
100 chanindex *cip;
101 channel *cp;
102 nick *np;
103
104 if (users)
105 *users = 0;
106
107 if (channels)
108 *channels = 0;
109
110 if (channels) {
111 for (i = 0; i<CHANNELHASHSIZE; i++) {
112 for (cip = chantable[i]; cip; cip = cip->next) {
113 cp = cip->channel;
114
115 if (!cp)
116 continue;
117
118 hit = 0;
119
120 for (gl = gbuf->head; gl; gl = gl->next) {
121 if (gline_match_channel(gl, cp)) {
122 hit = 1;
123 break;
124 }
125 }
126
127 if (hit)
128 (*channels)++;
129 }
130 }
131 }
132
133 if (users) {
134 for (i = 0; i < NICKHASHSIZE; i++) {
135 for (np = nicktable[i]; np; np = np->next) {
136 hit = 0;
137
138 for (gl = gbuf->head; gl; gl = gl->next) {
139 if (gline_match_nick(gl, np)) {
140 hit = 1;
141 break;
142 }
143 }
144
145 if (hit)
146 (*users)++;
147 }
148 }
149 }
150}
151
152void glinebufflush(glinebuf *gbuf, int propagate) {
153 gline *gl, *next, *sgl;
154 int users, channels;
155
156 /* Sanity check */
157 glinebufcounthits(gbuf, &users, &channels);
158
159 if (propagate && (users > MAXGLINEUSERHITS || channels > MAXGLINECHANNELHITS)) {
160 controlwall(NO_OPER, NL_GLINES, "G-Line buffer would hit %d users/%d channels. Not setting G-Lines.");
161 glinebufabandon(gbuf);
162 return;
163 }
164
165 for (gl = gbuf->head; gl; gl = next) {
166 next = gl->next;
167
168 sgl = findgline(glinetostring(gl));
169
170 if (sgl) {
171 /* existing gline
172 * in 1.4, can update expire, reason etc
173 * in 1.3 can only activate/deactivate an existing gline */
174
175 if (gl->flags & GLINE_ACTIVE && !(sgl->flags & GLINE_ACTIVE))
176 gline_activate(sgl, 0, 0);
177 else if (!(gl->flags & GLINE_ACTIVE) && sgl->flags & GLINE_ACTIVE)
178 gline_deactivate(sgl, 0, 0);
179
180 freegline(gl);
181 gl = sgl;
182 } else {
183 gl->next = glinelist;
184 glinelist = gl;
185 }
186
187 if (propagate)
188 gline_propagate(gl);
189 }
190}
191
192void glinebufabandon(glinebuf *gbuf) {
193 gline *gl, *next;
194
195 for (gl = gbuf->head; gl; gl = next) {
196 next = gl->next;
197
198 freegline(gl);
199 }
200}