]> jfr.im git - irc/quakenet/newserv.git/blame - patrol/patrol.c
LUA: port luadb to dbapi2 to drop postgres dependency
[irc/quakenet/newserv.git] / patrol / patrol.c
CommitLineData
c0e6ee63
GB
1#include <ctype.h>
2#include <string.h>
3#include "../lib/strlfunc.h"
4#include "../core/config.h"
5#include "../core/schedule.h"
6#include "../localuser/localuser.h"
7#include "patrol.h"
8
9static sstring *patrol_hostpool[PATROL_POOLSIZE], *patrol_tailpool[PATROL_POOLSIZE];
10static unsigned int patrol_hostpoolsize, patrol_tailpoolsize;
11static int patrol_min_hosts;
12static char patrol_hostmode;
13
14int patrol_minmaxrand(float min, float max) {
15 return (int)((max - min + 1) * rand() / (RAND_MAX + min)) + min;
16}
17
18nick *patrol_selectuser(void) {
19 int target = patrol_minmaxrand(0, 500), loops = 150, j;
20 nick *np;
21
22 do {
23 for (j = patrol_minmaxrand(0, NICKHASHSIZE - 1); j < NICKHASHSIZE; j++)
24 for (np = nicktable[j]; np; np = np->next)
25 if (!--target)
26 return np;
27 } while (--loops > 0);
28
29 return NULL;
30}
31
32host *patrol_selecthost(void) {
33 int target = patrol_minmaxrand(0, 500), loops = 150, j;
34 host *hp;
35
36 do {
37 for (j = patrol_minmaxrand(0, HOSTHASHSIZE - 1); j < HOSTHASHSIZE; j++)
38 for (hp = hosttable[j]; hp; hp = hp->next)
39 if (!--target)
40 return hp;
41 } while (--loops > 0);
42
43 return NULL;
44}
45
46int patrol_isip(char *host) {
7b3355b6
GB
47 struct irc_in_addr ip;
48 unsigned char bits;
49
50 return (ipmask_parse(host, &ip, &bits));
c0e6ee63
GB
51}
52
53static int specialuseronhost(host *hp) {
54 nick *np;
55
56 for (np = hp->nicks; np; np = np->nextbyhost)
57 if (IsOper(np) || IsService(np) || IsXOper(np) || NickOnServiceServer(np))
58 return 1;
59
60 return 0;
61}
62
63char patrol_genchar(int ty) {
64 /* hostname and realname characters*/
65 if (!ty) {
66 if (!(patrol_minmaxrand(0, 40) % 10)) {
67 return patrol_minmaxrand(48, 57);
68 } else {
69 return patrol_minmaxrand(97, 122);
70 }
71
72 /* ident characters - without numbers*/
73 } else if (ty == 1) {
74 return patrol_minmaxrand(97, 122);
75 /* ident characters - with numbers*/
76 } else if (ty == 2) {
77 ty = patrol_minmaxrand(97, 125);
78
79 if (ty > 122) return patrol_minmaxrand(48, 57);
80
81 return ty;
82 /* nick characters - with and without numbers*/
83 } else if (ty == 3 || ty == 4) {
84 if (!(patrol_minmaxrand(0, 59) % 16)) {
85 char weirdos[6] = { '\\', '|', '[', '{', ']', '}' };
86 return weirdos[patrol_minmaxrand(0, 5)];
87 }
88
89 if (ty == 4) {
90 ty = patrol_minmaxrand(65, 93);
91
92 if (ty > 90) return patrol_minmaxrand(48, 57);
93 } else {
94 ty = patrol_minmaxrand(65, 90);
95 }
96
97 if (!(patrol_minmaxrand(0, 40) % 8)) return ty;
98
99 return ty + 32;
100 /* moron check */
101 } else {
102 return ' ';
103 }
104}
105
106void patrol_gennick(char *ptc, char size) {
107 int i;
108
109 for (i = 0; i < size; i++) {
110 if (i == 0) {
111 ptc[i] = patrol_genchar(3);
112 } else {
113 ptc[i] = patrol_genchar(4);
114 }
115 }
116
117 ptc[i] = '\0';
118}
119
120void patrol_genident(char *ptc, char size) {
121 int i;
122
123 for (i = 0; i < size; i++) {
124 if (i == 0) {
125 ptc[i] = patrol_genchar(1);
126 } else {
127 ptc[i] = patrol_genchar(2);
128 }
129 }
130
131 ptc[i] = '\0';
132}
133
134void patrol_genhost(char *ptc, char size, struct irc_in_addr *ipaddress) {
135 int dots = patrol_minmaxrand(2, 5), i, dotexist = 0, cur;
136
137 while (!dotexist) {
138 for (i = 0; i < size; i++) {
139 ptc[i] = patrol_genchar(0);
140
141 if ((i > 5) && (i < (size - 4))) {
142 if ((ptc[i - 1] != '.') && (ptc[i - 1] != '-')) {
143 cur = patrol_minmaxrand(1, size / dots);
144
145 if (cur < 3) {
146 if (cur == 1) {
147 ptc[i] = '.';
148 dotexist = 1;
149 } else {
150 ptc[i] = '-';
151 }
152 }
153 }
154 }
155 }
156 }
157
158 ptc[i] = '\0';
159
01eaf134 160 memset(ipaddress, 0, sizeof(*ipaddress));
c0e6ee63
GB
161 ((unsigned short *)(ipaddress->in6_16))[5] = 65535;
162 ((unsigned short *)(ipaddress->in6_16))[6] = patrol_minmaxrand(0, 65535);
163 ((unsigned short *)(ipaddress->in6_16))[7] = patrol_minmaxrand(0, 65535);
164}
165
166void patrol_genreal(char *ptc, char size) {
167 int spaces = patrol_minmaxrand(2, 4), i;
168
169 for (i = 0; i < size; i++) {
170 ptc[i] = patrol_genchar(0);
171
172 if ((i > 5) && (i < (size - 4))) {
173 if (ptc[i - 1] != ' ') {
174 if (patrol_minmaxrand(1, size / spaces) == 1) ptc[i] = ' ';
175 }
176 }
177 }
178
179 ptc[i] = '\0';
180}
181
182void patrol_generatehost(char *buf, int maxsize, struct irc_in_addr *ipaddress) {
183 if (PATROL_HOST_MODE == PATROL_STEAL_HOST) {
184 host *hp;
185 int loops = 20;
186
187 buf[0] = '\0';
188
189 do {
190 hp = patrol_selecthost();
191
192 if (hp && (hp->clonecount <= PATROL_MAX_CLONE_COUNT) && !patrol_isip(hp->name->content) && !specialuseronhost(hp)) {
193 strlcpy(buf, hp->name->content, maxsize + 1);
194
195 if (hp->nicks) {
196 memcpy(ipaddress, &hp->nicks->ipaddress, sizeof(struct irc_in_addr));
197 } else {
198 memset(ipaddress, 0, sizeof(struct irc_in_addr));
199 ((unsigned short *)(ipaddress->in6_16))[5] = 65535;
200 ((unsigned short *)(ipaddress->in6_16))[6] = patrol_minmaxrand(0, 65535);
201 ((unsigned short *)(ipaddress->in6_16))[7] = patrol_minmaxrand(0, 65535);
202 }
203
204 break;
205 }
206 } while (--loops > 0);
207 } else {
208 char *cpos;
209 int pieces = patrol_minmaxrand(2, 4), totallen = 0, a = 0, i;
210 int *choices = malloc(sizeof(int) * (pieces + 1));
211 int *lengths = malloc(sizeof(int) * (pieces + 1));
212
213 choices[pieces] = patrol_minmaxrand(0, patrol_tailpoolsize - 1);
214 lengths[pieces] = strlen(patrol_tailpool[choices[pieces]]->content) + 1;
215 totallen += lengths[pieces];
216
217 for (i = 0; i < pieces; i++) {
218 choices[i] = patrol_minmaxrand(0, patrol_hostpoolsize - 1);
219 lengths[i] = strlen(patrol_hostpool[choices[i]]->content) + 1;
220
221 if (totallen + lengths[i] > maxsize) {
222 choices[i] = choices[pieces];
223 lengths[i] = lengths[pieces];
224 pieces -= (pieces - i);
225 break;
226 }
227
228 totallen += lengths[i];
229 }
230
231 for (i = 0; i < pieces; i++) {
232 for (cpos = patrol_hostpool[choices[i]]->content; *cpos;)
233 buf[a++] = *cpos++;
234
235 buf[a++] = '.';
236 }
237
238 for (cpos = patrol_tailpool[choices[i]]->content; *cpos;) {
239 buf[a++] = *cpos++;
240 }
241
242 buf[a] = '\0';
243 free(choices);
244 free(lengths);
245
246 memset(ipaddress, 0, sizeof(struct irc_in_addr));
247 ((unsigned short *)(ipaddress->in6_16))[5] = 65535;
248 ((unsigned short *)(ipaddress->in6_16))[6] = patrol_minmaxrand(0, 65535);
249 ((unsigned short *)(ipaddress->in6_16))[7] = patrol_minmaxrand(0, 65535);
250 }
251}
252
253void patrol_generatenick(char *buf, int maxsize) {
254 int bits = patrol_minmaxrand(2, 3), loops = 0, wanttocopy, len = 0, i, d = 0, newmaxsize = maxsize - patrol_minmaxrand(0, 7);
255 nick *np;
256
257 if (newmaxsize > 2)
258 maxsize = newmaxsize;
259
260 do {
261 np = patrol_selectuser();
262
263 if (np) {
264 wanttocopy = patrol_minmaxrand(1, (strlen(np->nick) / 2) + 3);
265
266 for (i = 0; ((i < wanttocopy) && (len < maxsize)); i++)
267 buf[len++] = np->nick[i];
268
269 if (++d > bits) {
270 buf[len] = '\0';
271 return;
272 }
273 }
274 } while (++loops < 10);
275
276 buf[0] = '\0';
277}
278
279void patrol_generateident(char *buf, int maxsize) {
280 nick *np = patrol_selectuser();
281 buf[0] = '\0';
282
283 if (np)
284 strlcpy(buf, np->ident, maxsize + 1);
285}
286
287void patrol_generaterealname(char *buf, int maxsize) {
288 nick *np = patrol_selectuser();
289 buf[0] = '\0';
290
291 if (np)
292 strlcpy(buf, np->realname->name->content, maxsize + 1);
293}
294
ad77af1a
GB
295nick *patrol_generateclone(int extraumodes, UserMessageHandler handler) {
296 int loops = 0, modes = UMODE_XOPER | UMODE_INV | extraumodes;
c0e6ee63
GB
297 char c_nick[NICKLEN + 1], c_ident[USERLEN + 1], c_host[HOSTLEN + 1], c_real[REALLEN + 1];
298 struct irc_in_addr ipaddress;
299
300 /* PPA: unlikely to be infinite */
301 do {
302 c_nick[0] = '\0';
303
304 if (!loops && patrol_hostmode) /* only have one go at this */
305 patrol_generatenick(c_nick, NICKLEN);
306
307 if (!c_nick[0])
308 patrol_gennick(c_nick, patrol_minmaxrand(7, PATROL_MMIN(13, NICKLEN)));
309
310 loops++;
311 } while ((getnickbynick(c_nick) != NULL));
312
313 patrol_generateident(c_ident, USERLEN);
314
315 if (!c_ident[0])
316 patrol_genident(c_ident, patrol_minmaxrand(4, PATROL_MMIN(8, USERLEN)));
317
318 if (patrol_hostmode) {
319 patrol_generatehost(c_host, HOSTLEN, &ipaddress);
320
321 if (!c_host[0])
322 patrol_genhost(c_host, HOSTLEN, &ipaddress);
323 } else {
324 patrol_genhost(c_host, HOSTLEN, &ipaddress);
325 }
326
327 patrol_generaterealname(c_real, REALLEN);
328
329 if (!c_real[0])
330 patrol_genreal(c_real, patrol_minmaxrand(15, PATROL_MMIN(50, REALLEN)));
331
332 return registerlocaluserflagsip(c_nick, c_ident, c_host, c_real, NULL, 0, 0, modes, &ipaddress, handler);
333}
334
335void patrol_nickchange(nick *np) {
336 char c_nick[NICKLEN + 1];
337 int loops = 0;
338
339 /* PPA: unlikely to be infinite */
340 do {
341 if ((loops++ < 10) && patrol_hostmode) {
342 patrol_generatenick(c_nick, NICKLEN);
343 } else {
344 patrol_gennick(c_nick, patrol_minmaxrand(7, PATROL_MMIN(13, NICKLEN)));
345 }
346 } while (c_nick[0] && (getnickbynick(c_nick) != NULL));
347
348 renamelocaluser(np, c_nick);
349}
350
351int patrol_is_not_octet(char *begin, int length) {
352 int i;
353
354 if (length > 3)
355 return 0;
356
357 for (i = 0; i < length; i++) {
358 if (!((*begin >= '0') && (*begin <= '9')))
359 return 0;
360
361 begin++;
362 }
363
364 return 1;
365}
366
367int patrol_generatepool(void) {
368 int i, k = 0, j = 0, loops = 0;
369 char *p, *pp;
370 nick *np;
371
372 for (i = 0; i < NICKHASHSIZE; i++)
373 for (np = nicktable[i]; np; np = np->next)
374 j++;
375
376 if (j < patrol_min_hosts)
377 return 0;
378
379 if (PATROL_HOST_MODE == PATROL_STEAL_HOST)
380 return PATROL_MINPOOLSIZE;
381
382 i = 0;
383
384 do {
385 for (j = patrol_minmaxrand(0, NICKHASHSIZE - 1); j < NICKHASHSIZE; j++) {
386 if (nicktable[j]) {
387 for (p = nicktable[j]->host->name->content, pp = p; *p;) {
388 if (*++p == '.') {
389 if (!patrol_is_not_octet(pp, p - pp)) {
390 if (i < PATROL_POOLSIZE) {
391 if (i < patrol_hostpoolsize)
392 freesstring(patrol_hostpool[i]);
393
394 patrol_hostpool[i] = getsstring(pp, p - pp);
395 i++;
396 } else {
397 if (k >= PATROL_POOLSIZE)
398 break;
399 }
400 }
401
402 pp = ++p;
403 }
404 }
405
406 if (!patrol_is_not_octet(pp, p - pp)) {
407 if (k < PATROL_POOLSIZE) {
408 if (k < patrol_tailpoolsize)
409 freesstring(patrol_tailpool[k]);
410
411 patrol_tailpool[k] = getsstring(pp, p - pp);
412 k++;
413 } else {
414 if (i >= PATROL_POOLSIZE)
415 break;
416 }
417 }
418 }
419 }
420
421 loops++;
422 } while ((loops < 5) && ((i < PATROL_POOLSIZE) || (k < PATROL_POOLSIZE)));
423
424 patrol_hostpoolsize = i;
425 patrol_tailpoolsize = k;
426 return i;
427}
428
429int patrol_repool(void) {
430 if (patrol_generatepool() < PATROL_MINPOOLSIZE) {
431 patrol_hostmode = 0;
432 return 0;
433 } else {
434 patrol_hostmode = 1;
435 return 1;
436 }
437}
438
439void patrol_sched_repool(void *arg) {
440 int delta;
441
442 if (patrol_repool())
443 delta = PATROL_POOL_REGENERATION;
444 else
445 delta = 10;
446
447 scheduleoneshot(time(NULL) + delta, &patrol_sched_repool, NULL);
448}
449
450void _init(void) {
451 char buf[32];
452 sstring *m;
453
454 snprintf(buf, sizeof(buf), "%d", PATROL_MINIMUM_HOSTS_BEFORE_POOL);
455 m = getcopyconfigitem("patrol", "minpoolhosts", buf, 32);
456 patrol_min_hosts = atoi(m->content);
457 freesstring(m);
458
459 scheduleoneshot(time(NULL) + 5, &patrol_sched_repool, NULL);
460}
461
462void _fini(void) {
463 int i;
464
465 deleteallschedules(&patrol_sched_repool);
466
467 for (i = 0; i < patrol_hostpoolsize; i++)
468 freesstring(patrol_hostpool[i]);
469
470 for (i = 0; i < patrol_tailpoolsize; i++)
471 freesstring(patrol_tailpool[i]);
472}
473