3 #include "../control/control.h"
4 #include "../lib/version.h"
5 #include "../lib/irc_string.h"
6 #include "../lib/strlfunc.h"
7 #include "../core/config.h"
8 #include "../core/schedule.h"
9 #include "../irc/irc.h"
10 #include "../lib/stringbuf.h"
11 #include "../control/control.h"
12 #include "../control/control_policy.h"
17 static void registercommands(int, void *);
18 static void deregistercommands(int, void *);
20 typedef int (*trustmodificationfn
)(void *, char *arg
, nick
*, int);
22 struct trustmodification
{
24 trustmodificationfn fn
;
27 static int trusts_cmdtrustadd(void *source
, int cargc
, char **cargv
) {
29 nick
*sender
= source
;
31 struct irc_in_addr ip
;
33 trusthost
*th
, *superset
, *subset
;
38 tg
= tg_strtotg(cargv
[0]);
40 controlreply(sender
, "Couldn't look up trustgroup.");
45 if(!ipmask_parse(host
, &ip
, &bits
)) {
46 controlreply(sender
, "Invalid host.");
50 if(!is_normalized_ipmask(&ip
, bits
)) {
51 controlreply(sender
, "Invalid IP Mask.");
55 /* Don't allow non-developers to add trusts for large subnets or modify protected groups. */
56 if (!noperserv_policy_command_permitted(NO_DEVELOPER
, sender
)) {
57 int minbits
= irc_in_addr_is_ipv4(&ip
)?TRUST_MIN_UNPRIVILEGED_BITS_IPV4
:TRUST_MIN_UNPRIVILEGED_BITS_IPV6
;
59 controlreply(sender
, "You don't have the necessary privileges to add a subnet larger than /%d.", irc_bitlen(&ip
, minbits
));
63 if(tg
->flags
& TRUST_PROTECTED
) {
64 controlreply(sender
, "You don't have the necessary privileges to modify a protected trust group.");
69 /* OKAY! Lots of checking here!
72 * - exact same host isn't already covered by given group (reject if it is)
73 * - host doesn't already exist exactly already (reject if it does)
74 * - host is more specific than an existing one (warn if it is, fix up later)
75 * - host is less specific than an existing one (warn if it is, don't need to do anything special)
78 for(th
=tg
->hosts
;th
;th
=th
->next
) {
79 if(ipmask_check(&ip
, &th
->ip
, th
->bits
) && th
->bits
== bits
) {
80 controlreply(sender
, "This host (or part of it) is already covered in the given group.");
85 if(th_getbyhostandmask(&ip
, bits
)) {
86 controlreply(sender
, "This host already exists in another group with the same mask.");
90 /* this function will set both to NULL if it's equal, hence the check above */
91 th_getsuperandsubsets(&ip
, bits
, &superset
, &subset
);
93 /* a superset exists for us, we will be more specific than one existing host */
95 controlreply(sender
, "Note: This host already exists in another group, but this new host will override it as it has a smaller prefix.");
98 /* a subset of us exists, we will be less specific than some existing hosts */
100 controlreply(sender
, "Note: This host already exists in at least one other group, the new host has a larger prefix and therefore will not override those hosts.");
103 th
= th_new(tg
, host
);
105 controlreply(sender
, "An error occured adding the host to the group.");
109 controlreply(sender
, "Host added.");
110 triggerhook(HOOK_TRUSTS_ADDHOST
, th
);
112 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTADD'ed host %s to group '%s'", controlid(sender
), host
, th
->group
->name
->content
);
113 trustlog(tg
, sender
->authname
, "Added host '%s'.", host
);
118 static int trusts_cmdtrustgroupadd(void *source
, int cargc
, char **cargv
) {
119 nick
*sender
= source
;
120 char *name
, *contact
, *comment
, createdby
[ACCOUNTLEN
+ 2];
121 long howmany
, maxperident
, enforceident
;
128 override
= noperserv_policy_command_permitted(NO_DEVELOPER
, sender
);
131 howmany
= strtol(cargv
[1], NULL
, 10);
132 if(!override
&& (!howmany
|| (howmany
> MAXTRUSTEDFOR
))) {
133 controlreply(sender
, "Bad value maximum number of clients.");
137 maxperident
= strtol(cargv
[2], NULL
, 10);
138 if(maxperident
< 0 || (maxperident
> MAXPERIDENT
)) {
139 controlreply(sender
, "Bad value for max per ident.");
143 if(cargv
[3][0] != '1' && cargv
[3][0] != '0') {
144 controlreply(sender
, "Bad value for enforce ident (use 0 or 1).");
147 enforceident
= cargv
[3][0] == '1';
152 comment
= "(no comment)";
157 /* don't allow #id or id forms */
158 if((name
[0] == '#') || strtol(name
, NULL
, 10)) {
159 controlreply(sender
, "Invalid trustgroup name.");
163 tg
= tg_strtotg(name
);
165 controlreply(sender
, "A group with that name already exists.");
169 snprintf(createdby
, sizeof(createdby
), "#%s", sender
->authname
);
174 flags
|= TRUST_RELIABLE_USERNAME
;
177 flags
|= TRUST_ENFORCE_IDENT
;
179 itg
.trustedfor
= howmany
;
181 itg
.maxperident
= maxperident
;
183 itg
.createdby
= getsstring(createdby
, CREATEDBYLEN
);
184 itg
.contact
= getsstring(contact
, CONTACTLEN
);
185 itg
.comment
= getsstring(comment
, COMMENTLEN
);
186 itg
.name
= getsstring(name
, TRUSTNAMELEN
);
188 if(itg
.createdby
&& itg
.contact
&& itg
.comment
&& itg
.name
) {
194 freesstring(itg
.createdby
);
195 freesstring(itg
.comment
);
196 freesstring(itg
.name
);
197 freesstring(itg
.contact
);
200 controlreply(sender
, "An error occured adding the trustgroup.");
204 controlreply(sender
, "Group added.");
205 triggerhook(HOOK_TRUSTS_ADDGROUP
, tg
);
207 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTGROUPADD'ed '%s'", controlid(sender
), tg
->name
->content
);
208 trustlog(tg
, sender
->authname
, "Created trust group '%s' (ID #%d): howmany=%d, enforceident=%d, maxperident=%d, "
209 "createdby=%s, contact=%s, comment=%s",
210 tg
->name
->content
, tg
->id
, howmany
, enforceident
, maxperident
, createdby
, contact
, comment
);
215 static int trusts_cmdtrustgroupdel(void *source
, int cargc
, char **cargv
) {
217 nick
*sender
= source
;
222 tg
= tg_strtotg(cargv
[0]);
224 controlreply(sender
, "Couldn't look up trustgroup.");
228 /* Don't allow non-developers to delete protected groups. */
229 if (!noperserv_policy_command_permitted(NO_DEVELOPER
, sender
)) {
230 if(tg
->flags
& TRUST_PROTECTED
) {
231 controlreply(sender
, "You don't have the necessary privileges to modify a protected trust group.");
237 controlreply(sender
, "Delete all hosts before deleting the group.");
241 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTGROUPDEL'ed '%s'.", controlid(sender
), tg
->name
->content
);
242 trustlog(tg
, sender
->authname
, "Deleted group '%s'.", tg
->name
->content
);
244 triggerhook(HOOK_TRUSTS_DELGROUP
, tg
);
246 controlreply(sender
, "Group deleted.");
251 static int trusts_cmdtrustdel(void *source
, int cargc
, char **cargv
) {
254 struct irc_in_addr ip
;
256 nick
*sender
= source
;
262 tg
= tg_strtotg(cargv
[0]);
264 controlreply(sender
, "Couldn't look up trustgroup.");
269 if(!ipmask_parse(host
, &ip
, &bits
)) {
270 controlreply(sender
, "Invalid IP/mask.");
274 /* Don't allow non-developers to remove trusts for large subnets or modify protected groups. */
275 if (!noperserv_policy_command_permitted(NO_DEVELOPER
, sender
)) {
276 int minbits
= irc_in_addr_is_ipv4(&ip
)?TRUST_MIN_UNPRIVILEGED_BITS_IPV4
:TRUST_MIN_UNPRIVILEGED_BITS_IPV6
;
278 controlreply(sender
, "You don't have the necessary privileges to remove a subnet larger than /%d.", irc_bitlen(&ip
, minbits
));
282 if(tg
->flags
& TRUST_PROTECTED
) {
283 controlreply(sender
, "You don't have the necessary privileges to modify a protected trust group.");
288 for(th
=tg
->hosts
;th
;th
=th
->next
)
289 if(ipmask_check(&ip
, &th
->ip
, th
->bits
) && th
->bits
== bits
)
293 controlreply(sender
, "Couldn't find that host in that group.");
297 triggerhook(HOOK_TRUSTS_DELHOST
, th
);
299 controlreply(sender
, "Host deleted.");
301 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTDEL'ed %s from group '%s'.", controlid(sender
), host
, tg
->name
->content
);
302 trustlog(tg
, sender
->authname
, "Removed host '%s'.", host
);
307 static int modifycomment(void *arg
, char *comment
, nick
*source
, int override
) {
308 trustgroup
*tg
= arg
;
309 sstring
*n
= getsstring(comment
, COMMENTLEN
);
313 freesstring(tg
->comment
);
319 static int modifycontact(void *arg
, char *contact
, nick
*source
, int override
) {
320 trustgroup
*tg
= arg
;
321 sstring
*n
= getsstring(contact
, CONTACTLEN
);
325 freesstring(tg
->contact
);
331 static int modifytrustedfor(void *arg
, char *num
, nick
*source
, int override
) {
332 trustgroup
*tg
= arg
;
333 long trustedfor
= strtol(num
, NULL
, 10);
336 controlreply(source
, "The clone limit must not be negative.");
341 if (trustedfor
== 0) {
342 controlreply(source
, "You don't have the necessary privileges to set an unlimited clone limit.");
346 if (trustedfor
> MAXTRUSTEDFOR
) {
347 controlreply(source
, "You don't have the necessary privileges to set the clone limit to a value higher than %d.", MAXTRUSTEDFOR
);
352 tg
->trustedfor
= trustedfor
;
357 static int modifymaxperident(void *arg
, char *num
, nick
*source
, int override
) {
358 trustgroup
*tg
= arg
;
359 long maxperident
= strtol(num
, NULL
, 10);
361 if(maxperident
< 0) {
362 controlreply(source
, "Ident limit must not be negative.");
366 if(maxperident
> MAXPERIDENT
) {
367 controlreply(source
, "Ident limit must not be higher than %d. Consider setting it to 0 (unlimited) instead.", MAXPERIDENT
);
371 tg
->maxperident
= maxperident
;
376 static int modifyenforceident(void *arg
, char *num
, nick
*source
, int override
) {
377 trustgroup
*tg
= arg
;
380 tg
->flags
|= TRUST_ENFORCE_IDENT
;
381 } else if(num
[0] == '0') {
382 tg
->flags
&= ~TRUST_ENFORCE_IDENT
;
390 static int modifyreliableusername(void *arg
, char *num
, nick
*source
, int override
) {
391 trustgroup
*tg
= arg
;
394 tg
->flags
|= TRUST_RELIABLE_USERNAME
;
395 } else if(num
[0] == '0') {
396 tg
->flags
&= ~TRUST_RELIABLE_USERNAME
;
404 static int modifyunthrottle(void *arg
, char *num
, nick
*source
, int override
) {
405 trustgroup
*tg
= arg
;
408 tg
->flags
|= TRUST_UNTHROTTLE
;
409 } else if(num
[0] == '0') {
410 tg
->flags
&= ~TRUST_UNTHROTTLE
;
418 static int modifyexpires(void *arg
, char *expires
, nick
*source
, int override
) {
419 trustgroup
*tg
= arg
;
420 int howlong
= durationtolong(expires
);
422 if((howlong
< 0) || (howlong
> MAXDURATION
)) {
423 controlreply(source
, "Duration cannot be negative or greater than %s (use 0 instead if you don't want the group to expire).", longtoduration(MAXDURATION
, 0));
428 tg
->expires
= getnettime() + howlong
;
430 tg
->expires
= 0; /* never */
435 static int modifycleanup(void *arg
, char *num
, nick
*source
, int override
) {
436 trustgroup
*tg
= arg
;
439 controlreply(source
, "You don't have the necessary privileges to modify this attribute.");
444 tg
->flags
&= ~TRUST_NO_CLEANUP
;
445 } else if(num
[0] == '0') {
446 tg
->flags
|= TRUST_NO_CLEANUP
;
454 static int modifyprotected(void *arg
, char *num
, nick
*source
, int override
) {
455 trustgroup
*tg
= arg
;
458 controlreply(source
, "You don't have the necessary privileges to modify this attribute.");
463 tg
->flags
|= TRUST_PROTECTED
;
464 } else if(num
[0] == '0') {
465 tg
->flags
&= ~TRUST_PROTECTED
;
473 static int modifymaxpernode(void *arg
, char *num
, nick
*source
, int override
) {
475 int maxpernode
= strtol(num
, NULL
, 10);
478 controlreply(source
, "Node limit must not be negative.");
482 if(maxpernode
>MAXPERNODE
) {
483 controlreply(source
, "Node limit must not be higher than %d. Consider setting it to 0 (unlimited) instead.", MAXPERNODE
);
487 th
->maxpernode
= maxpernode
;
492 static int modifynodebits(void *arg
, char *num
, nick
*source
, int override
) {
494 int nodebits
= strtol(num
, NULL
, 10);
497 controlreply(source
, "Node bits must not be negative.");
501 if(irc_in_addr_is_ipv4(&th
->ip
))
505 controlreply(source
, "Node bits is invalid.");
510 int minbits
= irc_in_addr_is_ipv4(&th
->ip
)?TRUST_MIN_UNPRIVILEGED_NODEBITS_IPV4
:TRUST_MIN_UNPRIVILEGED_NODEBITS_IPV6
;
512 if(nodebits
< minbits
) {
513 controlreply(source
, "You don't have the necessary privileges to set node bits to a subnet larger than /%d.", irc_bitlen(&th
->ip
, minbits
));
518 if(nodebits
<th
->bits
) {
519 controlreply(source
, "Node bits must be smaller or equal to the trusted CIDR's subnet size.");
523 th
->nodebits
= nodebits
;
528 static array trustgroupmods_a
;
529 static struct trustmodification
*trustgroupmods
;
530 static array trusthostmods_a
;
531 static struct trustmodification
*trusthostmods
;
533 static int trusts_cmdtrustgroupmodify(void *source
, int cargc
, char **cargv
) {
535 nick
*sender
= source
;
542 tg
= tg_strtotg(cargv
[0]);
544 controlreply(sender
, "Couldn't look up trustgroup.");
551 override
= noperserv_policy_command_permitted(NO_DEVELOPER
, sender
);
553 /* Don't allow non-developers to modify protected groups. */
554 if (!override
&& tg
->flags
& TRUST_PROTECTED
) {
555 controlreply(sender
, "You don't have the necessary privileges to modify a protected trust group.");
559 for(i
=0;i
<trustgroupmods_a
.cursi
;i
++) {
560 if(!strcmp(what
, trustgroupmods
[i
].name
)) {
561 if(!(trustgroupmods
[i
].fn
)(tg
, to
, sender
, override
)) {
562 controlreply(sender
, "An error occured changing that property, check the syntax.");
569 if(i
== trustgroupmods_a
.cursi
)
572 triggerhook(HOOK_TRUSTS_MODIFYGROUP
, tg
);
574 controlreply(sender
, "Group modified.");
576 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTMODIFIED'ed group '%s' (field: %s, value: %s)", controlid(sender
), tg
->name
->content
, what
, to
);
577 trustlog(tg
, sender
->authname
, "Modified %s: %s", what
, to
);
582 static int trusts_cmdtrusthostmodify(void *source
, int cargc
, char **cargv
) {
585 nick
*sender
= source
;
588 struct irc_in_addr ip
;
594 tg
= tg_strtotg(cargv
[0]);
596 controlreply(sender
, "Couldn't look up trustgroup.");
600 if(!ipmask_parse(cargv
[1], &ip
, &bits
)) {
601 controlreply(sender
, "Invalid host.");
605 /* Don't allow non-developers to modify trusts for large subnets or modify protected groups. */
606 if (!noperserv_policy_command_permitted(NO_DEVELOPER
, sender
)) {
607 int minbits
= irc_in_addr_is_ipv4(&ip
)?TRUST_MIN_UNPRIVILEGED_BITS_IPV4
:TRUST_MIN_UNPRIVILEGED_BITS_IPV6
;
609 controlreply(sender
, "You don't have the necessary privileges to modify a subnet larger than /%d.", irc_bitlen(&ip
, minbits
));
613 if(tg
->flags
& TRUST_PROTECTED
) {
614 controlreply(sender
, "You don't have the necessary privileges to modify a protected trust group.");
619 th
= th_getbyhostandmask(&ip
, bits
);
621 if(!th
|| th
->group
!= tg
) {
622 controlreply(sender
, "Host does not belong to the specified group.");
629 override
= noperserv_policy_command_permitted(NO_DEVELOPER
, sender
);
631 for(i
=0;i
<trusthostmods_a
.cursi
;i
++) {
632 if(!strcmp(what
, trusthostmods
[i
].name
)) {
633 if(!(trusthostmods
[i
].fn
)(th
, to
, sender
, override
)) {
634 controlreply(sender
, "An error occured changing that property, check the syntax.");
641 if(i
== trusthostmods_a
.cursi
)
644 triggerhook(HOOK_TRUSTS_MODIFYHOST
, th
);
646 controlreply(sender
, "Host modified.");
648 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTMODIFIED'ed host '%s' in group '%s' (field: %s, value: %s)", controlid(sender
), CIDRtostr(ip
, bits
), tg
->name
->content
, what
, to
);
649 trustlog(tg
, sender
->authname
, "Modified %s for host '%s': %s", what
, CIDRtostr(ip
, bits
), to
);
654 static int trusts_cmdtrustlog(void *source
, int cargc
, char **cargv
) {
655 nick
*sender
= source
;
664 limit
= strtol(cargv
[1], NULL
, 10);
671 if (name
[0] == '#') {
672 groupid
= strtol(name
+ 1, NULL
, 10);
673 trustlogspewid(sender
, groupid
, limit
);
675 trustlogspewname(sender
, name
, limit
);
681 static int trusts_cmdtrustloggrep(void *source
, int cargc
, char **cargv
) {
682 nick
*sender
= source
;
692 limit
= strtol(cargv
[1], NULL
, 10);
697 trustloggrep(sender
, pattern
, limit
);
702 static int trusts_cmdtrustcomment(void *source
, int cargc
, char **cargv
) {
703 nick
*sender
= source
;
704 trustgroup
*tg
= NULL
;
705 char *name
, *comment
;
713 if(strlen(comment
)>TRUSTLOGLEN
) {
714 controlreply(sender
, "Your comment is too long (max: %d characters).", TRUSTLOGLEN
);
718 tg
= tg_strtotg(name
);
721 controlreply(sender
, "Invalid trust group name or ID.");
725 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTCOMMENT'ed group '%s': %s", controlid(sender
), tg
->name
->content
, comment
);
726 trustlog(tg
, sender
->authname
, "Comment: %s", comment
);
731 static void cleanuptrusts(void *arg
);
733 static int trusts_cmdtrustcleanup(void *source
, int cargc
, char **cargv
) {
734 cleanuptrusts(source
);
736 controlreply(source
, "Done.");
742 static int commandsregistered
;
744 static void registercommands(int hooknum
, void *arg
) {
745 static char tgmhelp
[512], thmhelp
[512];
746 char validfields
[512];
750 if(commandsregistered
)
752 commandsregistered
= 1;
754 registercontrolhelpcmd("trustgroupadd", NO_OPER
, 6, trusts_cmdtrustgroupadd
, "Usage: trustgroupadd <name> <howmany> <maxperident> <enforceident> <contact> ?comment?");
755 registercontrolhelpcmd("trustadd", NO_OPER
, 2, trusts_cmdtrustadd
, "Usage: trustadd <#id|name|id> <host>");
756 registercontrolhelpcmd("trustgroupdel", NO_OPER
, 1, trusts_cmdtrustgroupdel
, "Usage: trustgroupdel <#id|name|id>");
757 registercontrolhelpcmd("trustdel", NO_OPER
, 2, trusts_cmdtrustdel
, "Usage: trustdel <#id|name|id> <ip/mask>");
759 sbinit(&b
, validfields
, sizeof(validfields
));
760 for(i
=0;i
<trustgroupmods_a
.cursi
;i
++) {
763 sbaddstr(&b
, trustgroupmods
[i
].name
);
767 snprintf(tgmhelp
, sizeof(tgmhelp
), "Usage: trustgroupmodify <#id|name|id> <field> <new value>\nModifies a trust group.\nValid fields: %s", validfields
);
768 registercontrolhelpcmd("trustgroupmodify", NO_OPER
, 3, trusts_cmdtrustgroupmodify
, tgmhelp
);
770 sbinit(&b
, validfields
, sizeof(validfields
));
771 for(i
=0;i
<trusthostmods_a
.cursi
;i
++) {
774 sbaddstr(&b
, trusthostmods
[i
].name
);
778 snprintf(thmhelp
, sizeof(thmhelp
), "Usage: trusthostmodify <#id|name|id> <host> <field> <new value>\nModifies a trust host\nValid fields: %s", validfields
);
779 registercontrolhelpcmd("trusthostmodify", NO_OPER
, 4, trusts_cmdtrusthostmodify
, thmhelp
);
781 registercontrolhelpcmd("trustlog", NO_OPER
, 2, trusts_cmdtrustlog
, "Usage: trustlog <#id|name> ?limit?\nShows log for the specified trust group.");
782 registercontrolhelpcmd("trustloggrep", NO_OPER
, 2, trusts_cmdtrustloggrep
, "Usage trustloggrep <pattern> ?limit?\nShows maching log entries.");
783 registercontrolhelpcmd("trustcomment", NO_OPER
, 2, trusts_cmdtrustcomment
, "Usage: trustcomment <#id|name> <comment>\nLogs a comment for a trust.");
784 registercontrolhelpcmd("trustcleanup", NO_DEVELOPER
, 0, trusts_cmdtrustcleanup
, "Usage: trustcleanup\nCleans up unused trusts.");
787 static void deregistercommands(int hooknum
, void *arg
) {
788 if(!commandsregistered
)
790 commandsregistered
= 0;
792 deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd
);
793 deregistercontrolcmd("trustadd", trusts_cmdtrustadd
);
794 deregistercontrolcmd("trustgroupdel", trusts_cmdtrustgroupdel
);
795 deregistercontrolcmd("trustdel", trusts_cmdtrustdel
);
796 deregistercontrolcmd("trustgroupmodify", trusts_cmdtrustgroupmodify
);
797 deregistercontrolcmd("trusthostmodify", trusts_cmdtrusthostmodify
);
798 deregistercontrolcmd("trustlog", trusts_cmdtrustlog
);
799 deregistercontrolcmd("trustloggrep", trusts_cmdtrustloggrep
);
800 deregistercontrolcmd("trustcomment", trusts_cmdtrustcomment
);
801 deregistercontrolcmd("trustcleanup", trusts_cmdtrustcleanup
);
806 #define _ms_(x) (struct trustmodification){ .name = # x, .fn = modify ## x }
807 #define MSGROUP(x) { int slot = array_getfreeslot(&trustgroupmods_a); trustgroupmods = (struct trustmodification *)trustgroupmods_a.content; memcpy(&trustgroupmods[slot], &_ms_(x), sizeof(struct trustmodification)); }
808 #define MSHOST(x) { int slot = array_getfreeslot(&trusthostmods_a); trusthostmods = (struct trustmodification *)trusthostmods_a.content; memcpy(&trusthostmods[slot], &_ms_(x), sizeof(struct trustmodification)); }
810 static void setupmods(void) {
812 MSGROUP(enforceident
);
813 MSGROUP(reliableusername
);
814 MSGROUP(maxperident
);
826 static int cleanuptrusts_active
;
828 static void cleanuptrusts(void *arg
) {
829 unsigned int now
, to_age
;
830 nick
*np
= (nick
*)arg
;
833 int thcount
= 0, tgcount
= 0;
836 array expiredths
, expiredtgs
;
839 to_age
= now
- (CLEANUP_TH_INACTIVE
* 3600 * 24);
842 noticelevel
= NL_TRUSTS
;
843 controlwall(NO_OPER
, noticelevel
, "CLEANUPTRUSTS: Manually started by %s.", np
->nick
);
845 noticelevel
= NL_CLEANUP
;
846 controlwall(NO_OPER
, noticelevel
, "CLEANUPTRUSTS: Automatically started.");
849 if (cleanuptrusts_active
) {
850 controlwall(NO_OPER
, NL_TRUSTS
, "CLEANUPTRUSTS: ABORTED! Cleanup already in progress! BUG BUG BUG!");
854 cleanuptrusts_active
=1;
856 array_init(&expiredtgs
, sizeof(trustgroup
*));
858 for(tg
=tglist
;tg
;tg
=tg
->next
) {
859 array_init(&expiredths
, sizeof(trusthost
*));
861 if(tg
->flags
& TRUST_NO_CLEANUP
)
864 for(th
=tg
->hosts
;th
;th
=th
->next
) {
865 if((th
->count
== 0 && th
->created
< to_age
&& th
->lastseen
< to_age
) || (tg
->expires
&& tg
->expires
< now
)) {
866 int pos
= array_getfreeslot(&expiredths
);
867 ((trusthost
**)(expiredths
.content
))[pos
] = th
;
871 for(i
=0;i
<expiredths
.cursi
;i
++) {
874 th
= ((trusthost
**)(expiredths
.content
))[i
];
875 triggerhook(HOOK_TRUSTS_DELHOST
, th
);
877 cidrstr
= CIDRtostr(th
->ip
, th
->bits
);
878 trustlog(tg
, "cleanuptrusts", "Removed host '%s' because it was unused for %d days.", cidrstr
, CLEANUP_TH_INACTIVE
);
886 int pos
= array_getfreeslot(&expiredtgs
);
887 ((trustgroup
**)(expiredtgs
.content
))[pos
] = tg
;
891 for(i
=0;i
<expiredtgs
.cursi
;i
++) {
892 tg
= ((trustgroup
**)(expiredtgs
.content
))[i
];
893 triggerhook(HOOK_TRUSTS_DELGROUP
, tg
);
894 trustlog(tg
, "cleanuptrusts", "Deleted group '%s' because it had no hosts left.", tg
->name
->content
);
899 controlwall(NO_OPER
, noticelevel
, "CLEANUPTRUSTS: Removed %d trust hosts (inactive for %d days) and %d empty trust groups.", thcount
, CLEANUP_TH_INACTIVE
, tgcount
);
901 cleanuptrusts_active
=0;
904 static void schedulecleanup(int hooknum
, void *arg
) {
905 /* run at 1am but only if we're more than 15m away from it, otherwise run tomorrow */
907 time_t t
= time(NULL
);
908 time_t next_run
= ((t
/ 86400) * 86400 + 86400) + 3600;
909 if(next_run
- t
< 900)
912 schedulerecurring(next_run
,0,86400,cleanuptrusts
,NULL
);
918 array_init(&trustgroupmods_a
, sizeof(struct trustmodification
));
919 array_init(&trusthostmods_a
, sizeof(struct trustmodification
));
922 m
= getconfigitem("trusts", "master");
923 if(!m
|| (atoi(m
->content
) != 1)) {
924 Error("trusts_management", ERR_ERROR
, "Not a master server, not loaded.");
930 registerhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
931 registerhook(HOOK_TRUSTS_DB_LOADED
, schedulecleanup
);
932 registerhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
935 registercommands(0, NULL
);
939 array_free(&trustgroupmods_a
);
940 array_free(&trusthostmods_a
);
945 deregisterhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
946 deregisterhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
948 deregistercommands(0, NULL
);
950 deleteallschedules(cleanuptrusts
);