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