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