3 #include "../control/control.h"
4 #include "../lib/irc_string.h"
5 #include "../lib/strlfunc.h"
6 #include "../core/config.h"
7 #include "../lib/stringbuf.h"
10 static void registercommands(int, void *);
11 static void deregistercommands(int, void *);
13 typedef int (*trustmodificationfn
)(trustgroup
*, char *arg
);
15 struct trustmodification
{
17 trustmodificationfn fn
;
20 static int trusts_cmdtrustadd(void *source
, int cargc
, char **cargv
) {
22 nick
*sender
= source
;
25 trusthost
*th
, *superset
, *subset
;
30 tg
= tg_strtotg(cargv
[0]);
32 controlreply(sender
, "Couldn't look up trustgroup.");
37 if(!trusts_str2cidr(host
, &ip
, &mask
)) {
38 controlreply(sender
, "Invalid host.");
42 /* OKAY! Lots of checking here!
45 * - host isn't already covered by given group (reject if it is)
46 * - host doesn't already exist exactly already (reject if it does)
47 * - host is more specific than an existing one (warn if it is, fix up later)
48 * - host is less specific than an existing one (warn if it is, don't need to do anything special)
51 for(th
=tg
->hosts
;th
;th
=th
->next
) {
52 if(th
->ip
== (ip
& th
->mask
)) {
53 controlreply(sender
, "This host (or part of it) is already covered in the given group.");
58 if(th_getbyhostandmask(ip
, mask
)) {
59 controlreply(sender
, "This host already exists in another group with the same mask.");
63 /* this function will set both to NULL if it's equal, hence the check above */
64 th_getsuperandsubsets(ip
, mask
, &superset
, &subset
);
66 /* a superset exists for us, we will be more specific than one existing host */
68 controlreply(sender
, "Warning: this host already exists in another group, but this new host will override it as it has a smaller prefix.");
71 /* a subset of us exists, we will be less specific than some existing hosts */
73 controlreply(sender
, "Warning: this host already exists in at least one other group, the new host has a larger prefix and therefore will not override those hosts.");
75 if(superset
|| subset
)
76 controlreply(sender
, "Adding anyway...");
78 th
= th_new(tg
, host
);
80 controlreply(sender
, "An error occured adding the host to the group.");
84 controlreply(sender
, "Host added.");
85 triggerhook(HOOK_TRUSTS_ADDHOST
, th
);
87 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTADD'ed host %s to group '%s'", controlid(sender
), host
, th
->group
->name
->content
);
92 static int trusts_cmdtrustgroupadd(void *source
, int cargc
, char **cargv
) {
93 nick
*sender
= source
;
94 char *name
, *contact
, *comment
, createdby
[ACCOUNTLEN
+ 2];
95 unsigned int howmany
, maxperident
, enforceident
;
103 howmany
= strtoul(cargv
[1], NULL
, 10);
104 if(!howmany
|| (howmany
> MAXTRUSTEDFOR
)) {
105 controlreply(sender
, "Bad value maximum number of clients.");
109 howlong
= durationtolong(cargv
[2]);
110 if((howlong
<= 0) || (howlong
> MAXDURATION
)) {
111 controlreply(sender
, "Invalid duration supplied.");
115 maxperident
= strtoul(cargv
[3], NULL
, 10);
116 if(!howmany
|| (maxperident
> MAXPERIDENT
)) {
117 controlreply(sender
, "Bad value for max per ident.");
121 if(cargv
[4][0] != '1' && cargv
[4][0] != '0') {
122 controlreply(sender
, "Bad value for enforce ident (use 0 or 1).");
125 enforceident
= cargv
[4][0] == '1';
130 comment
= "(no comment)";
135 /* don't allow #id or id forms */
136 if((name
[0] == '#') || strtoul(name
, NULL
, 10)) {
137 controlreply(sender
, "Invalid trustgroup name.");
141 tg
= tg_strtotg(name
);
143 controlreply(sender
, "A group with that name already exists");
147 snprintf(createdby
, sizeof(createdby
), "#%s", sender
->authname
);
149 itg
.trustedfor
= howmany
;
150 itg
.mode
= enforceident
;
151 itg
.maxperident
= maxperident
;
152 itg
.expires
= howlong
+ time(NULL
);
153 itg
.createdby
= getsstring(createdby
, CREATEDBYLEN
);
154 itg
.contact
= getsstring(contact
, CONTACTLEN
);
155 itg
.comment
= getsstring(comment
, COMMENTLEN
);
156 itg
.name
= getsstring(name
, TRUSTNAMELEN
);
158 if(itg
.createdby
&& itg
.contact
&& itg
.comment
&& itg
.name
) {
164 freesstring(itg
.createdby
);
165 freesstring(itg
.comment
);
166 freesstring(itg
.name
);
167 freesstring(itg
.contact
);
170 controlreply(sender
, "An error occured adding the trustgroup.");
174 controlreply(sender
, "Group added.");
175 triggerhook(HOOK_TRUSTS_ADDGROUP
, tg
);
177 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTGROUPADD'ed '%s'", controlid(sender
), tg
->name
->content
);
182 static int trusts_cmdtrustgroupdel(void *source
, int cargc
, char **cargv
) {
184 nick
*sender
= source
;
189 tg
= tg_strtotg(cargv
[0]);
191 controlreply(sender
, "Couldn't look up trustgroup.");
196 controlreply(sender
, "Delete all hosts before deleting the group.");
200 controlreply(sender
, "TODO: NOT IMPLEMENTED");
202 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTGROUPDEL'ed '%s'.", controlid(sender
), tg
->name
->content
);
204 triggerhook(HOOK_TRUSTS_DELGROUP
, tg
);
206 controlreply(sender
, "Group deleted.");
211 static int trusts_cmdtrustdel(void *source
, int cargc
, char **cargv
) {
215 nick
*sender
= source
;
221 tg
= tg_strtotg(cargv
[0]);
223 controlreply(sender
, "Couldn't look up trustgroup.");
228 if(!trusts_str2cidr(host
, &ip
, &mask
)) {
229 controlreply(sender
, "Invalid IP/mask.");
233 for(th
=tg
->hosts
;th
;th
=th
->next
)
234 if((th
->ip
== ip
) && (th
->mask
== mask
))
238 controlreply(sender
, "Couldn't find that host in that group.");
242 controlreply(sender
, "TODO: NOT IMPLEMENTED");
244 triggerhook(HOOK_TRUSTS_DELHOST
, th
);
246 controlreply(sender
, "Host deleted.");
248 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTDEL'ed %s from group '%s'.", controlid(sender
), host
, tg
->name
->content
);
253 static int modifycomment(trustgroup
*tg
, char *comment
) {
254 sstring
*n
= getsstring(comment
, COMMENTLEN
);
258 freesstring(tg
->comment
);
264 static int modifycontact(trustgroup
*tg
, char *contact
) {
265 sstring
*n
= getsstring(contact
, CONTACTLEN
);
269 freesstring(tg
->contact
);
275 static int modifytrustedfor(trustgroup
*tg
, char *num
) {
276 unsigned int trustedfor
= strtoul(num
, NULL
, 10);
278 if(trustedfor
> MAXTRUSTEDFOR
)
281 tg
->trustedfor
= trustedfor
;
286 static int modifymaxperident(trustgroup
*tg
, char *num
) {
287 unsigned int maxperident
= strtoul(num
, NULL
, 10);
289 if(maxperident
> MAXPERIDENT
)
292 tg
->maxperident
= maxperident
;
297 static int modifyenforceident(trustgroup
*tg
, char *num
) {
300 } else if(num
[0] == '0') {
309 static int modifyexpires(trustgroup
*tg
, char *expires
) {
310 int howlong
= durationtolong(expires
);
312 if((howlong
<= 0) || (howlong
> MAXDURATION
))
315 tg
->expires
= time(NULL
) + howlong
;
320 static array trustmods_a
;
321 static struct trustmodification
*trustmods
;
323 static int trusts_cmdtrustgroupmodify(void *source
, int cargc
, char **cargv
) {
325 nick
*sender
= source
;
326 char *what
, *to
, validfields
[512];
333 tg
= tg_strtotg(cargv
[0]);
335 controlreply(sender
, "Couldn't look up trustgroup.");
342 sbinit(&b
, validfields
, sizeof(validfields
));
343 for(i
=0;i
<trustmods_a
.cursi
;i
++) {
344 if(!strcmp(what
, trustmods
[i
].name
)) {
345 if(!(trustmods
[i
].fn
)(tg
, to
)) {
346 controlreply(sender
, "An error occured changing that property, check the syntax.");
354 sbaddstr(&b
, trustmods
[i
].name
);
357 if(i
== trustmods_a
.cursi
) {
359 controlreply(sender
, "No such field, valid fields are: %s", validfields
);
363 triggerhook(HOOK_TRUSTS_MODIFYGROUP
, tg
);
365 controlreply(sender
, "Group modified.");
367 controlwall(NO_OPER
, NL_TRUSTS
, "%s TRUSTMODIFIED'ed group '%s' (field: %s, value: %s)", controlid(sender
), tg
->name
->content
, what
, to
);
372 static int commandsregistered
;
374 static void registercommands(int hooknum
, void *arg
) {
375 if(commandsregistered
)
377 commandsregistered
= 1;
379 registercontrolhelpcmd("trustgroupadd", NO_OPER
, 6, trusts_cmdtrustgroupadd
, "Usage: trustgroupadd <name> <howmany> <howlong> <maxperident> <enforceident> <contact> ?comment?");
380 registercontrolhelpcmd("trustadd", NO_OPER
, 2, trusts_cmdtrustadd
, "Usage: trustadd <#id|name|id> <host>");
381 registercontrolhelpcmd("trustgroupdel", NO_OPER
, 1, trusts_cmdtrustgroupdel
, "Usage: trustgroupdel <#id|name|id>");
382 registercontrolhelpcmd("trustdel", NO_OPER
, 2, trusts_cmdtrustdel
, "Usage: trustdel <#id|name|id> <ip/mask>");
383 registercontrolhelpcmd("trustgroupmodify", NO_OPER
, 3, trusts_cmdtrustgroupmodify
, "Usage: trustgroupmodify <#id|name|id> <field> <new value>");
386 static void deregistercommands(int hooknum
, void *arg
) {
387 if(!commandsregistered
)
389 commandsregistered
= 0;
391 deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd
);
392 deregistercontrolcmd("trustadd", trusts_cmdtrustadd
);
393 deregistercontrolcmd("trustgroupdel", trusts_cmdtrustgroupdel
);
394 deregistercontrolcmd("trustdel", trusts_cmdtrustdel
);
395 deregistercontrolcmd("trustgroupmodify", trusts_cmdtrustgroupmodify
);
400 #define _ms_(x) (struct trustmodification){ .name = # x, .fn = modify ## x }
401 #define MS(x) { int slot = array_getfreeslot(&trustmods_a); trustmods = (struct trustmodification *)trustmods_a.content; memcpy(&trustmods[slot], &_ms_(x), sizeof(struct trustmodification)); }
403 static void setupmods(void) {
415 array_init(&trustmods_a
, sizeof(struct trustmodification
));
418 m
= getconfigitem("trusts", "master");
419 if(!m
|| (atoi(m
->content
) != 1)) {
420 Error("trusts_management", ERR_ERROR
, "Not a master server, not loaded.");
426 registerhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
427 registerhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
430 registercommands(0, NULL
);
434 array_free(&trustmods_a
);
439 deregisterhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
440 deregisterhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
442 deregistercommands(0, NULL
);