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