]> jfr.im git - irc/quakenet/newserv.git/blame - glines/glines_handler.c
A4STATS: remove E style escapes and switch to createtable for indices
[irc/quakenet/newserv.git] / glines / glines_handler.c
CommitLineData
a44fc5f7
GB
1#include <stdio.h>
2#include <string.h>
a44fc5f7 3#include "../localuser/localuserchannel.h"
a44fc5f7
GB
4#include "glines.h"
5
86a32bbf
CP
6//#define DEBUG
7
8#ifdef DEBUG
9#define Debug(...) Error("debuggline", ERR_DEBUG, ##__VA_ARGS__)
10#else
11#define Debug(...)
12#endif
13
a44fc5f7
GB
14/*
15 <prefix> GL <target> [!][+|-|>|<]<mask> [<expiration>] [<lastmod>] [<lifetime>] [:<reason>]
16*/
17
18int handleglinemsg(void *source, int cargc, char **cargv) {
19 char *sender = (char *)source;
a44fc5f7
GB
20 char *mask;
21 char *reason;
22 char *creator;
23 time_t lifetime = 0, expire = 0, lastmod = 0;
24 unsigned int flags = 0;
a44fc5f7
GB
25 long creatornum;
26 gline *agline;
27 nick *np;
cb581522 28 glinebuf gbuf;
a44fc5f7
GB
29
30 /**
31 * Valid GL tokens have X params:
32 * 2: Local modification to a local gline - ignored by services
c26406c8 33 * 4: ulined GL
a44fc5f7
GB
34 * 5: 1.3.x GL Token
35 * 6: 1.4.x GL Token - adds lifetime parameter
36 */
c684f472 37 switch (cargc) {
a44fc5f7
GB
38 case 2:
39 /* local modification which we reject later */
40 break;
c26406c8
GB
41 case 4:
42 /* ulined GL */
43 break;
a44fc5f7
GB
44 case 5:
45 /* 1.3.x GL Token */
46 break;
47 case 6:
48 /* 1.4.0 and above GL token */
49 break;
50 default:
51 Error("gline", ERR_WARNING, "Invalid number of arguments in GL token (%d)", cargc);
52 return CMD_ERROR;
53 }
54
55 /**
56 * Gline creator can be either a nick or a server
57 * 2 long numeric = server
58 * 5 long number = client
59 */
c684f472 60 switch (strlen(source)) {
a44fc5f7
GB
61 case 2:
62 creatornum = numerictolong(sender, 2);
63 if (creatornum < 0) {
64 Error("gline", ERR_WARNING, "Failed to resolve numeric (%s) to server when adding G-Line from network!", sender);
65 creator = "unknown";
66 } else
c684f472 67 if (serverlist[(int)creatornum].name == NULL) {
a44fc5f7
GB
68 Error("gline", ERR_WARNING, "Received gline from non-existant server");
69 return CMD_ERROR;
70 } else {
6ab2705a 71 creator = serverlist[(int)creatornum].name->content;
a44fc5f7
GB
72 }
73 break;
74 case 5:
75 creatornum = numerictolong(sender, 5);
c684f472
GB
76 np = getnickbynumeric(creatornum);
77 if (!np) {
a44fc5f7
GB
78 Error("gline", ERR_WARNING, "Failed to resolve numeric (%s) to nick when adding G-Line from network!", sender);
79 creator = "unknown";
80 } else
81 creator = np->nick;
82 break;
83 default:
84 Error("gline", ERR_WARNING, "Invalid numeric '%s' in G-Line message.", sender);
85 return CMD_ERROR;
86 }
87
a44fc5f7
GB
88 /* 2nd param is mask */
89 mask = cargv[1];
90
20447d72
GB
91 if (*mask == '%') {
92 flags |= GLINE_DESTROY;
93 mask++;
94 }
95
a44fc5f7
GB
96 switch (*mask) {
97 case '+':
98 flags |= GLINE_ACTIVATE;
99 mask++;
100 break;
101 case '-':
102 flags |= GLINE_DEACTIVATE;
103 mask++;
104 break;
105 case '>':
106 case '<':
107 Error("gline", ERR_WARNING, "Received local modification from %s - do they realise we're a service?", sender);
108 return CMD_ERROR;
109 case '!':
110 Error("gline", ERR_WARNING, "Received 'forced gline' token from %s", sender);
111 return CMD_ERROR;
112 }
113
114 if (flags & GLINE_ACTIVATE) {
115 /* activate gline */
116 expire = abs_expire(atoi(cargv[2]));
117 switch (cargc) {
118 case 4:
119 /* asuka U:d, no lastmod */
21ae66d1
GB
120 lastmod = 0;
121 lifetime = expire;
a44fc5f7
GB
122 reason = cargv[3];
123 break;
124 case 5:
125 /*asuka lastmod */
126 lastmod = atoi(cargv[3]);
c684f472 127 lifetime = gline_max(lastmod, expire); /* set lifetime = lastmod */
a44fc5f7
GB
128 reason = cargv[4];
129 break;
130 case 6:
131 /* snircd */
132 lastmod = atoi(cargv[3]);
133 lifetime = atoi(cargv[4]);
134 reason = cargv[5];
135 break;
136 default:
137 Error("gline", ERR_WARNING, "Gline Activate with invalid number (%d) of arguments", cargc);
138 return CMD_ERROR;
139 }
140
86a32bbf 141 Debug("GL Received: Creator %s, Mask %s, Reason %s, Expire %lu, Lastmod %lu, Lifetime %lu", creator, mask, reason, expire, lastmod, lifetime);
a44fc5f7 142
96662a86 143 agline = findgline(mask);
c684f472
GB
144
145 if (agline) {
86a32bbf 146 Debug("Update for existing gline received for %s - old lastmod %lu, expire %lu, lifetime %lu, reason %s, creator %s", mask, agline->lastmod, agline->expire, agline->lifetime, agline->reason ? agline->reason->content : "", agline->creator->content);
dd44e3d8
GB
147
148 agline->flags |= GLINE_ACTIVE;
149
150 /* check lastmod then assume the new gline is authoritive */
151 if (lastmod > agline->lastmod) {
152 agline->lastmod = lastmod;
153 agline->expire = expire;
154 agline->lifetime = lifetime;
155 freesstring(agline->creator);
156 agline->creator = getsstring(creator, 255);
157 freesstring(agline->reason);
158 agline->reason = getsstring(reason, 255);
a44fc5f7 159 } else {
86a32bbf 160 Debug("received a gline with a lower lastmod");
dd44e3d8
GB
161 /* Don't send our gline as that might cause loops in case we don't understand the gline properly. */
162 }
163
164 return CMD_OK;
a44fc5f7 165 } else {
cb581522
GB
166 glinebufinit(&gbuf, 0);
167 glinebufadd(&gbuf, mask, creator, reason, expire, lastmod, lifetime);
0b2e8a55 168 glinebufcommit(&gbuf, 0);
a44fc5f7
GB
169 }
170 } else if (flags & GLINE_DEACTIVATE) {
171 /* deactivate gline */
96662a86
GB
172 agline = findgline(mask);
173
174 if (agline) {
a44fc5f7
GB
175 switch (cargc) {
176 case 2:
177 /* asuka U:d, no last mod */
178 removegline(agline);
179 break;
180 case 5:
181 /* asuka last mod */
182 lastmod = atoi(cargv[3]);
20447d72
GB
183
184 if (flags & GLINE_DESTROY)
185 gline_destroy(agline, lastmod, 0);
186 else
187 gline_deactivate(agline, lastmod, 0);
188
a44fc5f7
GB
189 break;
190 case 6:
191 /* snircd */
192 lastmod = atoi(cargv[3]);
20447d72
GB
193
194 if (flags & GLINE_DESTROY)
195 gline_destroy(agline, lastmod, 0);
196 else
197 gline_deactivate(agline, lastmod, 0);
198
a44fc5f7
GB
199 break;
200 default:
201 Error("gline", ERR_WARNING, "Gline Deactivate with invalid number (%d) of arguments", cargc);
202 return CMD_ERROR;
203 }
c684f472 204
a44fc5f7
GB
205 return CMD_OK;
206 } else {
e372a040
GB
207 if (cargc < 5)
208 return; /* U:lined gline, we're done */
a44fc5f7
GB
209 Error("gline", ERR_WARNING, "Gline addition - adding deactivated gline - mask not found (%s)", mask);
210 expire = abs_expire(atoi(cargv[2]));
211 switch (cargc) {
a44fc5f7
GB
212 case 5:
213 /*asuka lastmod */
214 lastmod = atoi(cargv[3]);
c684f472 215 lifetime = gline_max(lastmod, expire); /* set lifetime = lastmod */
a44fc5f7
GB
216 reason = cargv[4];
217 break;
218 case 6:
219 /* snircd */
220 lastmod = atoi(cargv[3]);
221 lifetime = atoi(cargv[4]);
222 reason = cargv[5];
223 break;
224 default:
225 Error("gline", ERR_WARNING, "Gline DeActivate with invalid number (%d) of arguments", cargc);
226 return CMD_ERROR;
227 }
228
cb581522
GB
229 glinebufinit(&gbuf, 0);
230 agline = glinebufadd(&gbuf, mask, creator, reason, expire, lastmod, lifetime);
c684f472
GB
231
232 if (!agline) {
0b2e8a55 233 glinebufabort(&gbuf);
a44fc5f7 234 Error("gline", ERR_WARNING, "gline_add failed");
c684f472
GB
235 return CMD_ERROR;
236 }
237
238 gline_deactivate(agline, lastmod, 0);
0b2e8a55 239 glinebufcommit(&gbuf, 0);
c684f472
GB
240
241 return CMD_OK;
a44fc5f7
GB
242 }
243 } else {
244 /* modification - only snircd 1.4.x */
96662a86
GB
245 agline = findgline(mask);
246
247 if (agline) {
a44fc5f7
GB
248 expire = abs_expire(atoi(cargv[2]));
249 lastmod = atoi(cargv[3]);
250 lifetime = atoi(cargv[4]);
251 reason = cargv[5];
252
c684f472 253 if (lastmod > agline->lastmod) {
a44fc5f7
GB
254 agline->lastmod = lastmod;
255 agline->expire = expire;
256 agline->lifetime = lifetime;
257 agline->creator = getsstring(creator, 255);
258 freesstring(agline->reason);
259 agline->reason = getsstring(reason, 255);
260 } else {
86a32bbf 261 Debug("received a gline modification with a lower lastmod");
a44fc5f7 262 }
c684f472 263
a44fc5f7
GB
264 return CMD_OK;
265 } else {
86a32bbf 266 Debug("Received modification for G-Line that does not exist for mask %s", mask);
a44fc5f7
GB
267 return CMD_ERROR;
268 }
269 }
c684f472 270
a44fc5f7
GB
271 return CMD_OK;
272}
273
a44fc5f7 274void handleglinestats(int hooknum, void *arg) {
c684f472 275 if ((long)arg > 10) {
a44fc5f7
GB
276 char message[100];
277 int glcount = 0;
278 gline *gl;
279
c684f472 280 for(gl = glinelist; gl; gl = gl->next)
a44fc5f7 281 glcount++;
a44fc5f7 282
c684f472 283 snprintf(message, sizeof(message), "G-Lines :%7d glines", glcount);
a44fc5f7
GB
284 triggerhook(HOOK_CORE_STATSREPLY, message);
285 }
286}
287