]> jfr.im git - irc/quakenet/newserv.git/blame - trusts2/trusts_commands.c
fix bug in G stats
[irc/quakenet/newserv.git] / trusts2 / trusts_commands.c
CommitLineData
e2527cba
P
1#include "../core/schedule.h"
2#include "../lib/irc_string.h"
3#include "../localuser/localuserchannel.h"
4#include "../control/control.h"
5#include "trusts.h"
6#include <string.h>
9a8ffb84
P
7#include <stdlib.h>
8#include <stdarg.h>
e2527cba 9
9a8ffb84
P
10void _init(void) {
11 registerhook(HOOK_TRUSTS_DBLOADED, trusts_cmdinit);
12
13 /* Now that the database is in a separate module it might be loaded already. */
14 if (trusts_loaded)
15 trusts_cmdinit(HOOK_TRUSTS_DBLOADED, NULL);
16
17}
18
19void _fini(void) {
20 deregisterhook(HOOK_TRUSTS_DBLOADED, trusts_cmdinit);
21 trusts_cmdfini();
22}
23
24void trusts_cmdinit(int hooknum, void *arg) {
e2527cba
P
25 registercontrolcmd("trustgroupadd",10,7,trust_groupadd);
26 registercontrolcmd("trustgroupmodify",10,4,trust_groupmodify);
27 registercontrolcmd("trustgroupdel",10,2,trust_groupdel);
28
29 registercontrolcmd("trustcomment",10,2,trust_comment);
30
31 registercontrolcmd("trustadd",10,3,trust_add);
32 registercontrolcmd("trustdel",10,2,trust_del);
33
34 registercontrolcmd("trustdenyadd",10,2,trust_denyadd);
ef9fab2e 35 registercontrolcmd("trustdenycomment",10,2,trust_denycomment);
e2527cba
P
36 registercontrolcmd("trustdenydel",10,2,trust_denydel);
37
38 registercontrolcmd("truststats",10,2,trust_stats);
39 registercontrolcmd("trustdump",10,2,trust_dump);
9a8ffb84 40
ef9fab2e 41 removeusers = 0;
e2527cba
P
42}
43
44void trusts_cmdfini() {
45 deregistercontrolcmd("trustgroupadd",trust_groupadd);
46 deregistercontrolcmd("trustgroupmodify",trust_groupmodify);
47 deregistercontrolcmd("trustgroupdel",trust_groupdel);
48
49 deregistercontrolcmd("trustcomment",trust_comment);
50
51 deregistercontrolcmd("trustadd",trust_add);
52 deregistercontrolcmd("trustdel",trust_del);
53
54 deregistercontrolcmd("trustdenyadd",trust_denyadd);
ef9fab2e 55 deregistercontrolcmd("trustdenycomment",trust_denycomment);
e2527cba
P
56 deregistercontrolcmd("trustdenydel",trust_denydel);
57
58 deregistercontrolcmd("truststats",trust_stats);
59 deregistercontrolcmd("trustdump",trust_dump);
9a8ffb84
P
60
61 removeusers = 0;
e2527cba
P
62}
63
64/*TODO*/
65/* tgh - should this have a 'maxclones limit'? */
66
67int trust_groupadd(void *source, int cargc, char **cargv) {
68 nick *sender=(nick *)source;
69 int expiry;
70 unsigned long maxclones;
71 unsigned short maxperip;
72 unsigned long maxperident;
73 int enforceident;
74 int type;
75 unsigned long ownerid;
76 trustgroup_t *t;
77
78 if (cargc < 7) {
79 controlreply(sender,"Usage: trustgroupadd howmany howlong maxperident maxperip enforceident type ownerid");
80 return CMD_ERROR;
81 }
82
83 maxclones = strtoul(cargv[0],NULL,10);
84 if ( maxclones > 10000 ) {
85 /* we allow 0 for unlimited trusts, and only warn on this */
86 controlreply(sender, "WARNING: large maximum number of clients - %lu", maxclones);
87 }
88 expiry = durationtolong(cargv[1]);
89 if (expiry > (365 * 86400) ) {
90 controlreply(sender,"ERROR: Invalid duration given - temporary trusts can not be longer then 1 year");
91 return CMD_ERROR;
92 }
93 ownerid = strtoul(cargv[6],NULL,10);
94 maxperip = strtoul(cargv[3],NULL,10);
95 if (maxperip > 500) {
96 controlreply(sender, "ERROR: MaxPerIP value should be less then 500 (if set)");
97 return CMD_ERROR;
98 }
99 maxperident = strtoul(cargv[2],NULL,10);
100 if (maxperident > 50) {
101 controlreply(sender, "ERROR: MaxPerIdent value should be less then 50 (if set)");
102 return CMD_ERROR;
103 }
104 if (((cargv[4][0]!='0') && (cargv[4][0]!='1')) || (cargv[4][1]!='\0')) {
105 controlreply(sender,"ERROR: enforceident is a boolean setting, that means it can only be 0 or 1");
106 return CMD_ERROR;
107 }
108 enforceident = cargv[4][0] == '1';
109
110 if ( findtrustgroupbyownerid(ownerid) ) {
111 controlreply(sender, "ERROR: Q User ID %d already has a trustgroup", ownerid);
112 return CMD_ERROR;
113 }
114 if (ownerid > 2147483646 ) {
115 controlreply(sender, "ERROR: Invalid Q User ID: %d", ownerid);
116 return CMD_ERROR;
117 }
118
119 type = strtoul(cargv[5],NULL,10);
120
121 /* check rules */
122 switch (type ) {
123 case 0:
124 break;
125 default:
126 controlreply(sender, "Invalid Type (%d)", type);
127 return CMD_ERROR;
128 }
129
130 t = createtrustgroup( ++trusts_lasttrustgroupid, maxclones, maxperident, maxperip, enforceident, getnettime() + expiry, ownerid, type);
131
132 if(!t) {
133 controlreply(sender,"ERROR: An error occured adding trustgroup");
134 return CMD_ERROR;
135 }
136
137 trustsdb_addtrustgroup(t);
138
139 controlreply(sender,"Adding trustgroup with ID %lu", t->id);
140 controlreply(sender,"Connections: %d, Enforceident %d, Per ident: %d, Per IP %d",maxclones,enforceident,maxperident,maxperip);
141 controlreply(sender,"Expires: %d, User ID: %d", expiry, ownerid);
142 controlwall(NO_OPER, NL_TRUSTS, "NewTrust: ID: %lu, Connections: %d, Enforceident %d, Per ident: %d, Per IP %d, Owner %d", t->id,maxclones,enforceident,maxperident,maxperip, ownerid);
143 return CMD_OK;
144}
145
146int trust_del(void *source, int cargc, char **cargv) {
147 nick *sender=(nick *)source;
148 struct irc_in_addr sin;
149 unsigned char bits;
150 patricia_node_t *node;
151 trustgroup_t *tg;
152
153 if (cargc<1) {
154 controlreply(sender,"Syntax: trustdel IP[/mask]");
155 return CMD_OK;
156 }
157
158 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
159 controlreply(sender, "ERROR: Invalid mask.");
160 return CMD_ERROR;
161 }
162
163 node = refnode(iptree, &sin, bits);
164 if(!node->exts[tgh_ext]) {
165 controlreply(sender,"ERROR: That CIDR was not trusted.");
166 return CMD_ERROR;
167 } else {
168 /*TODO: only allow a host to be removed if <X users? subnets? bah */
169 tg = ((trusthost_t *)node->exts[tgh_ext])->trustgroup;
170 controlreply(sender,"%s removed from trustgroup #%lu",cargv[0],tg->id);
171 controlwall(NO_OPER, NL_TRUSTS, "%s removed from trustgroup #%lu",cargv[0],tg->id);
172 trustsdb_deletetrusthost(node->exts[tgh_ext]);
173 trusthost_free(node->exts[tgh_ext]);
174 node->exts[tgh_ext] = NULL;
175 }
176 return CMD_OK;
177}
178
179int trust_add(void *source, int cargc, char **cargv) {
180 nick *sender=(nick *)source;
181 trustgroup_t *tg;
182 struct irc_in_addr sin;
183 unsigned char bits;
184 patricia_node_t *node, *inode, *parent;
185 int expiry = 0;
186 trusthost_t *th;
187
188 if (cargc<2) {
189 controlreply(sender,"Syntax: trustadd <#groupid> IP[/mask] <duration>");
190 return CMD_OK;
191 }
192
193 if(cargv[0][0]== '#'){
194 /* find group by id */
195 tg=findtrustgroupbyid(strtol(&cargv[0][1],NULL,10));
196 } else {
197 /* find group by id */
198 tg=findtrustgroupbyid(strtol(cargv[0],NULL,10));
199 }
200
201 if(tg == NULL) {
202 controlreply(sender,"ERROR: A trustgroup with that ID does not exist.");
203 return CMD_ERROR;
204 }
205
206 if (tg->id==0) {
207 controlreply(sender,"INTERNAL ERROR: Trustgroup has ID 0");
208 return CMD_ERROR;
209 }
210
211 if (ipmask_parse(cargv[1], &sin, &bits) == 0) {
212 controlreply(sender, "ERROR: Invalid mask.");
213 return CMD_ERROR;
214 }
215
216 if ( irc_in_addr_is_ipv4(&sin) ) {
217 if (bits>128 || bits<112) {
ef9fab2e 218 controlreply(sender,"ERROR: Not a valid netmask (needs to be between 16 and 32)");
e2527cba
P
219 return CMD_ERROR;
220 }
221 } else {
222 if ( bits<64) {
223 controlreply(sender,"ERROR: Not a valid ipv6 netmask ");
224 return CMD_ERROR;
225 }
226 }
227
228 if (cargc == 3) {
229 expiry = getnettime() + durationtolong(cargv[2]);
230 if (expiry<1) {
231 controlreply(sender,"ERROR: Invalid duration given");
232 return CMD_ERROR;
233 }
234 }
235
236 node = refnode(iptree, &sin, bits);
237 if(node->exts[tgh_ext]) {
238 /* this mask is already trusted */
239 controlreply(sender,"ERROR: This mask is already trusted by trustgroup %lu.", ((trusthost_t *)node->exts[tgh_ext])->trustgroup->id);
240 return CMD_ERROR;
241 }
ef9fab2e
P
242 if ( node->exts[tgb_ext] ) {
243 controlreply(sender,"ERROR: A trustblock exists on this subnet, as follows: ID: %lu, public reason: %s", ((trustblock_t *)node->exts[tgb_ext])->id, (((trustblock_t *)node->exts[tgb_ext])->reason_public ? ((trustblock_t *)node->exts[tgb_ext])->reason_public->content : "<none>"));
244 return CMD_ERROR;
245 }
e2527cba
P
246
247 /* check child status */
248 PATRICIA_WALK(node, inode)
249 {
250 th = inode->exts[tgh_ext];
251 if (th) {
252 /* we have a child trustgroup */
253 /* Criteria 1: we can't add two hosts into the same group */
254 if (th->trustgroup == tg) {
255 controlreply(sender,"ERROR: A child subnet is already in this trustgroup, remove that subnet first (%s/%d)", IPtostr(inode->prefix->sin),irc_bitlen(&(inode->prefix->sin),inode->prefix->bitlen));
256 return CMD_ERROR;
257 }
ef9fab2e
P
258 /* Criteria 2: we can't trust a subnet containing a trustblock (unless you have +d flag, then warn) */
259 if ( inode->exts[tgb_ext] ) {
260 controlreply(sender,"ERROR: A trustblock exists on a child subnet, as follows: ID: %lu, public reason: %s", ((trustblock_t *)inode->exts[tgb_ext])->id, (((trustblock_t *)inode->exts[tgb_ext])->reason_public ? ((trustblock_t *)inode->exts[tgb_ext])->reason_public->content : "<none>"));
261 return CMD_ERROR;
262 }
e2527cba
P
263 }
264 }
265 PATRICIA_WALK_END;
266
267 /* check parents too */
268 parent = node->parent;
269 while (parent) {
270 if( parent->exts[tgh_ext]) {
271 th = parent->exts[tgh_ext];
272 /* we have a parent trustgroup */
273 /* Criteria 1: we can't add two hosts into the same group */
274 if (th->trustgroup == tg) {
275 controlreply(sender,"ERROR: A parent subnet is already in this trustgroup (%s/%d)", IPtostr(parent->prefix->sin),irc_bitlen(&(parent->prefix->sin),parent->prefix->bitlen));
276 return CMD_ERROR;
277 }
278 /* even if we find 1 parent, we continue to the top */
ef9fab2e
P
279 /* Criteria 2: we can't trust a subnet containing a trustblock (unless you have +d flag, then warn) */
280 if ( parent->exts[tgb_ext] ) {
281 controlreply(sender,"ERROR: A trustblock exists on a parent subnet, as follows: ID: %lu, public reason: %s", ((trustblock_t *)parent->exts[tgb_ext])->id, (((trustblock_t *)parent->exts[tgb_ext])->reason_public ? ((trustblock_t *)parent->exts[tgb_ext])->reason_public->content : "<none>"));
282 return CMD_ERROR;
283 }
e2527cba
P
284 }
285 parent = parent->parent;
286 }
287
288 th = trusthostadd(node, tg, expiry );
289 if ( !th ) {
290 controlreply(sender,"ERROR: Unable to add trusted host");
291 }
292
293 trustsdb_addtrusthost(th);
294 controlreply(sender,"Added %s to trustgroup #%lu",cargv[1],tg->id);
295 controlwall(NO_OPER, NL_TRUSTS, "Added %s to trustgroup #%lu",cargv[1],tg->id);
296 return CMD_OK;
297}
298
e2527cba
P
299int trust_dump(void *source, int cargc, char **cargv) {
300 nick *sender=(nick *)source;
301
302 char tmps3[512];
303 trustgroup_t *g;
304 unsigned long startid=0;
305 long num=0, count=0, lines=0;
306
307 if (cargc<2) {
308 controlreply(sender, "Syntax: trustdump <start #id> <number>");
309 controlreply(sender, "Dumps <number> trustgroups starting from <start #id>.");
310 controlreply(sender, "This allows to dump very large numbers of groups,");
311 controlreply(sender, "so use with care.");
312 return CMD_ERROR;
313 }
314 strncpy(tmps3,cargv[0],20);
315 tmps3[20]='\0';
316 num = atoi(cargv[1]);
317
318 if (tmps3[0] != '#') {
319 controlreply(sender, "First parameter has to be a trust ID (prefixed with #).");
320 return CMD_ERROR;
321 }
322
323 startid=strtoul(&tmps3[1], NULL, 10);
324 if (num < 1) {
325 controlreply(sender, "Cannot return fewer than 1 group.");
326 return CMD_ERROR;
327 }
328 if (num >= 500) {
329 controlreply(sender, "Will not list more than 500 groups in one go.");
330 return CMD_ERROR;
331 }
332
333 if (startid > trusts_lasttrustgroupid) {
334 controlreply(sender, "Start ID cannot exceed maximum group ID (#%ld).", trusts_lasttrustgroupid);
335 return CMD_ERROR;
336 }
337
338 do {
339 g=findtrustgroupbyid(startid);
340 startid++;
341 } while ((g == NULL) && (startid <= (trusts_lasttrustgroupid+1)));
342 if (g == NULL) {
343 controlreply(sender, "Failed to find nearest start group.");
344 return CMD_ERROR;
345 }
346
347 while (startid <= (trusts_lasttrustgroupid+1)) {
348 if (g == NULL) {
349 g=findtrustgroupbyid(startid);
350 startid++;
351 continue;
352 }
353 controlreply(sender, "G,#%lu,%lu,%lu,%d,%lu,%lu,%lu,%lu",
354 g->id, g->currenton, g->maxclones, g->enforceident, g->maxperident,
355 g->maxusage, g->expire, g->lastused);
356 lines++;
357
358 trusthost_t* thptr;
359
360 int hash = trusts_gettrusthostgroupidhash(g->id);
361 for (thptr = trusthostgroupidtable[hash]; thptr; thptr = thptr->nextbygroupid ) {
362 if ( thptr->trustgroup->id == g->id ) {
363 /* TODO: expire here - trusthost_free(thptr);*/
364 controlreply(sender, "H,#%lu,%s/%d,%lu,%lu,%lu", g->id,
365 IPtostr(((patricia_node_t *)thptr->node)->prefix->sin),
366 irc_bitlen(&(((patricia_node_t *)thptr->node)->prefix->sin),((patricia_node_t *)thptr->node)->prefix->bitlen),
367 0 /*a->currentlyon*/,
368 0 /*a->maxused*/,
369 0 /* a->lastused*/);
370 lines++;
371 }
372 }
373
374 count++;
375 if (count >= num) {
376 break;
377 }
378 g=findtrustgroupbyid(startid);
379 startid++;
380 }
381 controlreply(sender, "End of list, %ld groups and %ld lines returned.", count, lines);
382 return CMD_OK;
383}
384
ef9fab2e 385int trust_denyadd(void *source, int cargc, char **cargv) {
e2527cba 386 nick *sender=(nick *)source;
ef9fab2e
P
387 struct irc_in_addr sin;
388 unsigned char bits;
389 trustblock_t *tb;
390 patricia_node_t *node;
391 int expiry;
e2527cba 392
ef9fab2e
P
393 if (cargc<2) {
394 controlreply(sender,"Syntax: trustdenyadd IP[/mask] <expiry> <public reason>");
395 return CMD_OK;
396 }
397
398 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
399 controlreply(sender, "ERROR: Invalid mask.");
400 return CMD_ERROR;
401 }
402
403 if ( irc_in_addr_is_ipv4(&sin) ) {
404 if (bits>128 || bits<112) {
405 controlreply(sender,"ERROR: Not a valid netmask (needs to be between 8 and 32)");
406 return CMD_ERROR;
407 }
408 } else {
409 if ( bits<64) {
410 controlreply(sender,"ERROR: Not a valid ipv6 netmask ");
411 return CMD_ERROR;
412 }
413 }
414
415 expiry = getnettime() + durationtolong(cargv[1]);
416 if (expiry<1) {
417 controlreply(sender,"ERROR: Invalid duration given");
418 return CMD_ERROR;
419 }
420
421 node = refnode(iptree, &sin, bits);
422 if(node->exts[tgb_ext]) {
423 /* this mask is already blocked */
424 controlreply(sender,"ERROR: This mask is already blocked", ((trustblock_t *)node->exts[tgb_ext])->id);
425 return CMD_ERROR;
426 }
427
428 tb = createtrustblock( ++trusts_lasttrustblockid, node, 0 /*TODO*/, expiry, NULL,cargv[2]);
429 if (!tb) {
430 controlreply(sender,"ERROR: An error occured adding the trustblock");
431 }
432 node->exts[tgb_ext] = tb;
433
434 trustsdb_addtrustblock(tb);
435 controlreply(sender,"Added %s to trustblock list",cargv[0]);
436 controlwall(NO_OPER, NL_TRUSTS, "Added %s to trustblock list",cargv[0]);
437 return CMD_OK;
438}
439
440int trust_denycomment(void *source, int cargc, char **cargv) {
441 nick *sender=(nick *)source;
442 struct irc_in_addr sin;
443 unsigned char bits;
444 patricia_node_t *node;
445 trustblock_t *tb;
446
447 if (cargc<2) {
448 controlreply(sender,"Syntax: trustdenycomment IP[/mask] <private reason>");
449 return CMD_OK;
450 }
451
452 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
453 controlreply(sender, "ERROR: Invalid mask.");
454 return CMD_ERROR;
455 }
456
457 if ( irc_in_addr_is_ipv4(&sin) ) {
458 if (bits>128 || bits<112) {
459 controlreply(sender,"ERROR: Not a valid netmask (needs to be between 8 and 32)");
460 return CMD_ERROR;
461 }
462 } else {
463 if ( bits<64) {
464 controlreply(sender,"ERROR: Not a valid ipv6 netmask ");
465 return CMD_ERROR;
466 }
467 }
468
469 node = refnode(iptree, &sin, bits);
470 if(!node->exts[tgb_ext]) {
471 /* this mask is already blocked */
472 controlreply(sender,"ERROR: This mask is not blocked. Use trustdenyadd to add a new block");
473 return CMD_ERROR;
474 }
475 derefnode(iptree,node);
476 tb = node->exts[tgb_ext];
477
478 tb->reason_private = getsstring(cargv[1],512);
479 trustsdb_updatetrustblock(tb);
480 controlreply(sender,"Private Comment added to trustblock %s",cargv[0]);
481 controlwall(NO_OPER, NL_TRUSTS, "Private Comment added to trustblock %s",cargv[0]);
e2527cba
P
482 return CMD_OK;
483}
484
ef9fab2e 485int trust_denydel(void *source, int cargc, char **cargv) {
e2527cba 486 nick *sender=(nick *)source;
ef9fab2e
P
487 struct irc_in_addr sin;
488 unsigned char bits;
489 patricia_node_t *node;
e2527cba 490
ef9fab2e
P
491 if (cargc<1) {
492 controlreply(sender,"Syntax: trustdenydel IP[/mask]");
493 return CMD_OK;
494 }
495
496 if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
497 controlreply(sender, "ERROR: Invalid mask.");
498 return CMD_ERROR;
499 }
500
501 node = refnode(iptree, &sin, bits);
502 if(!node->exts[tgb_ext]) {
503 controlreply(sender,"ERROR: That CIDR was not blocked.");
504 return CMD_ERROR;
505 } else {
506 controlreply(sender,"trustblock removed on %s",cargv[0]);
507 controlwall(NO_OPER, NL_TRUSTS, "trustblock removed on %s", cargv[0]);
508 trustsdb_deletetrustblock( node->exts[tgb_ext]);
509 trustblock_free( node->exts[tgb_ext] );
510 node->exts[tgb_ext] = NULL;
511 }
e2527cba
P
512 controlreply(sender,"Not Implemented");
513 return CMD_OK;
514}
515
516int trust_groupmodify(void *source, int cargc, char **cargv) {
517 nick *sender=(nick *)source;
518 unsigned long oldvalue, newvalue;
519 char *mod;
520 int expiry;
521 trustgroup_t *tg;
522
523 if (cargc<3 || cargc==4) {
524 controlreply(sender,"Syntax: trustgroupmodify <#groupid> <what> [+|-|=]number");
525 controlreply(sender," +20 means add 20, =20 replaces current value, -20 means subtract");
526 controlreply(sender," what: maxclones, maxperident, maxperip, expire, enforceident, ownerid");
527 return CMD_OK;
528 }
529
530 if(cargv[0][0]== '#'){
531 /* find group by id */
532 tg=findtrustgroupbyid(strtol(&cargv[0][1],NULL,10));
533 } else {
534 /* find group by id */
535 tg=findtrustgroupbyid(strtol(cargv[0],NULL,10));
536 }
537
538 if(tg == NULL) {
539 controlreply(sender,"ERROR: A trustgroup with that ID does not exist.");
540 return CMD_ERROR;
541 }
542
543 if (tg->id==0) {
544 controlreply(sender,"INTERNAL ERROR: Trustgroup has ID 0");
545 return CMD_ERROR;
546 }
547
548 switch ( cargv[2][0] ) {
549 case '+':
550 case '-':
551 case '=':
552 mod = cargv[2];
553 break;
554 default:
555 controlreply(sender,"ERROR: invalid modifier specified (values values are +,-,=)");
556 return CMD_ERROR;
557 }
558 newvalue = strtoul(&cargv[2][1],NULL,10);
559
560 if (ircd_strcmp(cargv[1], "maxclones")==0) {
561 oldvalue = tg->maxclones;
562 switch (*mod) {
563 case '+':
564 newvalue = oldvalue + newvalue;
565 break;
566 case '-':
567 if (newvalue > oldvalue) {
568 controlreply(sender, "ERROR: maxclones cannot be less than 0");
569 return CMD_ERROR;
570 }
571 newvalue = oldvalue - newvalue;
572 if (newvalue == 0) {
573 controlreply(sender, "ERROR: maxclones limit would be 0 - unlimited maxclones can only be set with '='");
574 return CMD_ERROR;
575 }
576 break;
577 }
578
579 if (newvalue > 1000000) {
580 controlreply(sender, "ERROR: large maximum number of clients - %lu", newvalue);
581 return CMD_ERROR;
582 }
583 if (newvalue > 10000) {
584 controlreply(sender, "WARNING: large maximum number of clients - %lu", newvalue);
585 }
586
587 tg->maxclones = newvalue;
588 } else if (ircd_strcmp(cargv[1], "maxperident")==0) {
589 oldvalue = tg->maxperident;
590 switch (*mod) {
591 case '+':
592 newvalue = oldvalue + newvalue;
593 break;
594 case '-':
595 if (newvalue > oldvalue) {
596 controlreply(sender, "ERROR: maxperident cannot be less than 0");
597 return CMD_ERROR;
598 }
599 newvalue = oldvalue - newvalue;
600 if (newvalue == 0) {
601 controlreply(sender, "ERROR: maxperident limit would be 0 - unlimited maxclones can only be set with '='");
602 return CMD_ERROR;
603 }
604 break;
605 }
606
607 if (newvalue > 50) {
608 controlreply(sender, "ERROR: MaxPerIdent value should be less then 50 (if set)");
609 return CMD_ERROR;
610 }
611 tg->maxperident=newvalue;
612 } else if (ircd_strcmp(cargv[1], "maxperip")==0) {
613 oldvalue = tg->maxperip;
614 switch (*mod) {
615 case '+':
616 newvalue = oldvalue + newvalue;
617 break;
618 case '-':
619 if (newvalue > oldvalue) {
620 controlreply(sender, "ERROR: maxperip cannot be less than 0");
621 return CMD_ERROR;
622 }
623 newvalue = oldvalue - newvalue;
624 if (newvalue == 0) {
625 controlreply(sender, "ERROR: maxperip limit would be 0 - unlimited maxclones can only be set with '='");
626 return CMD_ERROR;
627 }
628 break;
629 }
630
631 if (newvalue > 500) {
632 controlreply(sender, "ERROR: MaxPerIP value should be less then 500 (if set)");
633 return CMD_ERROR;
634 }
635 tg->maxperip = newvalue;
636 } else if (ircd_strcmp(cargv[1], "expire")==0) {
637 oldvalue = tg->expire;
638 expiry = durationtolong(&cargv[2][1]);
639
640 if (expiry > (365 * 86400) ) {
641 controlreply(sender,"ERROR: Invalid duration given - temporary trusts can not be longer then 1 year");
642 return CMD_ERROR;
643 }
644
645 switch (*mod) {
646 case '+':
647 newvalue = oldvalue + expiry;
648 break;
649 case '-':
650 newvalue = oldvalue - expiry;
651 if (newvalue < getnettime() ) {
652 controlreply(sender, "ERROR: Can't set expiry before current nettime - use trustgroupdel to delete trust groups");
653 return CMD_ERROR;
654 }
655 break;
656 case '=':
657 if ( expiry > 0) {
658 newvalue = getnettime() + expiry;
659 }
660 break;
661 }
662 tg->expire = newvalue;
663 } else if (ircd_strcmp(cargv[1], "enforceident")==0) {
664 oldvalue = tg->enforceident;
665 if ( (newvalue != 0 && newvalue != 1) || *mod != '=' ) {
666 controlreply(sender,"ERROR: enforceident is a boolean setting, that means it can only be 0 or 1, and can only be set by '='");
667 return CMD_ERROR;
668 }
669 tg->enforceident = newvalue;
670 } else if (ircd_strcmp(cargv[1], "ownerid")==0) {
671 oldvalue = tg->ownerid;
672 if ( *mod != '=' ) {
673 controlreply(sender,"ERROR: Q user ID can only be set by '='");
674 return CMD_ERROR;
675 }
676 if ( findtrustgroupbyownerid(newvalue) ) {
677 controlreply(sender, "ERROR: Q User ID %d already has a trustgroup", newvalue);
678 return CMD_ERROR;
679 }
680
681 if (newvalue > 2147483646 ) {
682 controlreply(sender, "ERROR: Invalid Q User ID: %d", newvalue);
683 return CMD_ERROR;
684 }
685
686 tg->ownerid = newvalue;
687 }
688 controlreply(sender, "Modification: %s changed to %lu from %lu for trustgroup %lu", cargv[1], newvalue, oldvalue, tg->id);
689 controlwall(NO_OPER, NL_TRUSTS, "Modification: %s changed to %lu from %lu for trustgroup %lu", cargv[1], newvalue, oldvalue, tg->id);
690
691 trustsdb_updatetrustgroup(tg);
692 return CMD_OK;
693}
694
695int trust_groupdel(void *source, int cargc, char **cargv) {
696 nick *sender=(nick *)source;
697 trusthost_t *thptr, *nthptr;
698 trustgroup_t *tg;
699 patricia_node_t *node;
700
701 if (cargc<1) {
702 controlreply(sender,"Syntax: trustgroupdel <#id|id>");
703 return CMD_OK;
704 }
705
706 if(cargv[0][0]== '#'){
707 /* find group by id */
708 tg=findtrustgroupbyid(strtol(&cargv[0][1],NULL,10));
709 } else {
710 /* find group by id */
711 tg=findtrustgroupbyid(strtol(cargv[0],NULL,10));
712 }
713
714 if(tg == NULL) {
715 controlreply(sender,"ERROR: A trustgroup with that ID does not exist.");
716 return CMD_ERROR;
717 }
718
719 if (tg->id==0) {
720 controlreply(sender,"INTERNAL ERROR: Trustgroup has ID 0");
721 return CMD_ERROR;
722 }
723
724 /* we have a trustgroup to remove */
725 int hash = trusts_gettrusthostgroupidhash(tg->id);
726 for (thptr = trusthostgroupidtable[hash]; thptr; thptr = nthptr ) {
727 nthptr = thptr->nextbygroupid;
728 if(thptr->trustgroup == tg) {
729 node = thptr->node;
730 controlwall(NO_OPER, NL_TRUSTS, "%s/%d removed from trustgroup #%lu",IPtostr(thptr->node->prefix->sin),irc_bitlen(&(thptr->node->prefix->sin),thptr->node->prefix->bitlen),tg->id);
731 controlreply(sender,"%s/%d removed from trustgroup #%lu",IPtostr(thptr->node->prefix->sin),irc_bitlen(&(thptr->node->prefix->sin),thptr->node->prefix->bitlen),tg->id);
732 trustsdb_deletetrusthost(thptr);
733 trusthost_free(thptr);
734 node->exts[tgh_ext] = NULL;
735 }
736 }
737 controlwall(NO_OPER, NL_TRUSTS, "removed trustgroup #%lu",tg->id);
738 controlreply(sender,"removed trustgroup #%lu",tg->id);
739 trustsdb_deletetrustgroup(tg);
740 trustgroup_free(tg);
741 return CMD_OK;
742
743}
744
745int trust_stats(void *source, int cargc, char **cargv) {
746 nick *sender=(nick *)source;
747 trustgroup_t *tg; trusthost_t* thptr; int i;
748 unsigned long thcount=0, ucount=0, mcount=0, tgcount=0;
749 unsigned long hentries=0;
750 unsigned long netcount4[33];
751 unsigned long netucount4[33];
752 unsigned long netmcount4[33];
753 unsigned long netcount6[129];
754 unsigned long netucount6[129];
755 unsigned long netmcount6[129];
756
757 int maxthmask4 = 32;
758 int maxthmask6 = 128;
759
760 for (i=0; i<33; i++) {
761 netcount4[i]=0;
762 netucount4[i]=0;
763 netmcount4[i]=0;
764 }
765
766 for (i=0; i<129; i++) {
767 netcount6[i]=0;
768 netucount6[i]=0;
769 netmcount6[i]=0;
770 }
771
772 for ( i = 0; i < TRUSTS_HASH_GROUPSIZE ; i++ ) {
773 for ( tg = trustgroupidtable[i]; tg; tg = tg -> nextbyid ) {
774 /*check active*/
775 tgcount++;
776 }
777 }
778
779 for ( i = 0; i < TRUSTS_HASH_HOSTSIZE ; i++ ) {
780 for ( thptr = trusthostidtable[i]; thptr; thptr = thptr-> nextbyid ) {
781 /*check active*/
782 hentries++;
783 thcount++;
784 ucount+=thptr->node->usercount;
785 mcount+=thptr->maxused;
786 if(irc_in_addr_is_ipv4(&((patricia_node_t *)thptr->node)->prefix->sin)) {
787 netcount4[((patricia_node_t *)thptr->node)->prefix->bitlen-96]++;
788 netucount4[((patricia_node_t *)thptr->node)->prefix->bitlen-96]+=thptr->node->usercount;
789 netmcount4[((patricia_node_t *)thptr->node)->prefix->bitlen-96]+=thptr->maxused;
790 if( (((patricia_node_t *)thptr->node)->prefix->bitlen-96) < maxthmask4 ) {
791 maxthmask4 = (((patricia_node_t *)thptr->node)->prefix->bitlen-96);
792 }
793 } else {
794 netcount6[((patricia_node_t *)thptr->node)->prefix->bitlen]++;
795 netucount6[((patricia_node_t *)thptr->node)->prefix->bitlen]+=thptr->node->usercount;
796 netmcount6[((patricia_node_t *)thptr->node)->prefix->bitlen]+=thptr->maxused;
797 if( ((patricia_node_t *)thptr->node)->prefix->bitlen < maxthmask6 ) {
798 maxthmask6 = ((patricia_node_t *)thptr->node)->prefix->bitlen;
799 }
800 }
801 }
802 }
803 controlreply(sender, "Online trust users: %lu", ucount);
804 controlreply(sender, "Maximum online users: %lu", mcount);
805 controlreply(sender, "Trust groups: %lu", tgcount);
806 controlreply(sender, "Maximum group ID: #%lu", trusts_lasttrustgroupid);
807 controlreply(sender, "Trusted hosts/nets: %lu", thcount);
808 controlreply(sender, "Largest subnet (v4): /%d", maxthmask4);
809 controlreply(sender, "Largest subnet (v6): /%d", maxthmask6);
810 controlreply(sender, "IPv4 Subnets:");
811 for (i=0; i<32; i++) {
812 if (netcount4[i]==0) continue;
813 controlreply(sender, "|-*/%d (Netcount: %lu Cur: %lu Max: %lu)", i, netcount4[i], netucount4[i], netmcount4[i]);
814 }
815 controlreply(sender, "`-*/32 (Netcount: %lu Cur: %lu Max: %lu)", netcount4[32], netucount4[32], netmcount4[32]);
816 controlreply(sender, "IPv6 Subnets:");
817 for (i=0; i<128; i++) {
818 if (netcount6[i]==0) continue;
819 controlreply(sender, "|-*/%d (Netcount: %lu Cur: %lu Max: %lu)", i, netcount6[i], netucount6[i], netmcount6[i]);
820 }
821 controlreply(sender, "`-*/128 (Netcount: %lu Cur: %lu Max: %lu)", netcount6[128], netucount6[128], netmcount6[128]);
822
823 return CMD_OK;
824}
825
826
827int trust_comment(void *source, int cargc, char **cargv) {
828 nick *sender=(nick *)source;
829 trustgroup_t *tg;
830
831 if (cargc<2) {
832 controlreply(sender,"Syntax: trustcomment <#groupid> <comment>");
833 return CMD_OK;
834 }
835
836 if(cargv[0][0]== '#'){
837 /* find group by id */
838 tg=findtrustgroupbyid(strtol(&cargv[0][1],NULL,10));
839 } else {
840 /* find group by id */
841 tg=findtrustgroupbyid(strtol(cargv[0],NULL,10));
842 }
843
844 if(tg == NULL) {
845 controlreply(sender,"A trustgroup with that ID does not exist.");
846 return CMD_ERROR;
847 }
848
849 if (tg->id==0) {
850 controlreply(sender,"Internal error: Trustgroup has ID 0");
851 return CMD_ERROR;
852 }
853
854 trustsdb_logmessage(tg, 0, 1, cargv[1]);
855
856 controlreply(sender, "Comment: %s for trustgroup %lu", cargv[1], tg->id);
857 controlwall(NO_OPER, NL_TRUSTS, "Comment: %s for trustgroup %lu", cargv[1], tg->id);
858
859 return CMD_OK;
860
861}
862