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