3 #include "../lib/version.h"
4 #include "../control/control.h"
5 #include "../lib/irc_string.h"
6 #include "../lib/strlfunc.h"
7 #include "../core/nsmalloc.h"
8 #include "../irc/irc.h"
9 #include "../newsearch/newsearch.h"
10 #include "../glines/glines.h"
12 #include "newsearch/trusts_newsearch.h"
16 static void registercommands(int, void *);
17 static void deregistercommands(int, void *);
19 extern void printnick_channels(searchCtx
*, nick
*, nick
*);
21 void calculatespaces(int spaces
, int width
, char *str
, char **_prebuf
, char **_postbuf
) {
22 static char prebuf
[512], postbuf
[512];
25 if(spaces
+ 5 >= sizeof(prebuf
)) {
26 prebuf
[0] = prebuf
[1] = '\0';
28 memset(prebuf
, ' ', spaces
);
29 prebuf
[spaces
] = '\0';
32 spacelen
= width
- (strlen(str
) + spaces
);
33 if(spacelen
<= 0 || spacelen
+ 5 >= sizeof(postbuf
)) {
34 postbuf
[0] = postbuf
[1] = '\0';
36 memset(postbuf
, ' ', spacelen
);
37 postbuf
[spacelen
] = '\0';
44 static void traverseandmark(unsigned int marker
, trusthost
*th
, int markchildren
) {
48 for(th
=th
->children
;th
;th
=th
->nextbychild
) {
50 traverseandmark(marker
, th
, markchildren
);
55 static void insertth(array
*parents
, trusthost
*th
) {
57 trusthost
**p2
= (trusthost
**)(parents
->content
);
59 /* this eliminates common subtrees */
60 for(i
=0;i
<parents
->cursi
;i
++)
64 if(i
== parents
->cursi
) {
65 int pos
= array_getfreeslot(parents
);
66 ((trusthost
**)(parents
->content
))[pos
] = th
;
70 static void marktree(array
*parents
, unsigned int marker
, trusthost
*th
, int showchildren
) {
74 for(pth
=th
->parent
;pth
;pth
=pth
->parent
) {
75 insertth(parents
, pth
);
81 insertth(parents
, th
);
83 /* sadly we need to recurse down */
84 traverseandmark(marker
, th
, showchildren
);
87 static void outputtree(nick
*np
, unsigned int marker
, trustgroup
*originalgroup
, trusthost
*th
, int depth
, int showchildren
) {
88 char *cidrstr
, *prespacebuf
, *postspacebuf
, parentbuf
[512];
90 if(th
->marker
!= marker
)
93 cidrstr
= trusts_cidr2str(&th
->ip
, th
->bits
);
94 calculatespaces(depth
+ 2, 30 + 1, cidrstr
, &prespacebuf
, &postspacebuf
);
96 if(th
->group
== originalgroup
) {
97 if(!showchildren
&& th
->group
== originalgroup
&& th
->children
)
100 prespacebuf
[0] = ' ';
102 prespacebuf
[1] = '>';
106 /* show the ids of other groups */
108 snprintf(parentbuf
, sizeof(parentbuf
), "%-10d %s", th
->group
->id
, th
->group
->name
->content
);
111 controlreply(np
, "%s%s%s %-10d %-10d %-21s %-15d /%-14d%s", prespacebuf
, cidrstr
, postspacebuf
, th
->count
, th
->maxusage
, (th
->count
>0)?"(now)":((th
->lastseen
>0)?trusts_timetostr(th
->lastseen
):"(never)"), th
->maxpernode
, (irc_in_addr_is_ipv4(&th
->ip
))?(th
->nodebits
- 96):th
->nodebits
, parentbuf
);
113 /* Make sure we're not seeing this subtree again. */
116 for(th
=th
->children
;th
;th
=th
->nextbychild
)
117 outputtree(np
, marker
, originalgroup
, th
, depth
+ 1, showchildren
);
120 static char *formatflags(int flags
) {
121 static char buf
[512];
125 if(flags
& TRUST_ENFORCE_IDENT
)
126 strncat(buf
, "enforcing ident", 512);
128 if(flags
& TRUST_NO_CLEANUP
) {
130 strncat(buf
, ", ", 512);
132 strncat(buf
, "exempt from cleanup", 512);
135 if(flags
& TRUST_PROTECTED
) {
137 strncat(buf
, ", ", 512);
139 strncat(buf
, "protected", 512);
142 if(flags
& TRUST_RELIABLE_USERNAME
) {
144 strncat(buf
, ", ", 512);
146 strncat(buf
, "reliable username", 512);
154 static char *formatlimit(unsigned int limit
) {
158 snprintf(buf
, sizeof(buf
), "%u", limit
);
160 strncpy(buf
, "unlimited", sizeof(buf
));
165 static void displaygroup(nick
*sender
, trustgroup
*tg
, int showchildren
) {
170 time_t t
= getnettime();
172 /* abusing the ternary operator a bit :( */
173 controlreply(sender
, "Name: : %s", tg
->name
->content
);
174 controlreply(sender
, "Trusted for : %s", formatlimit(tg
->trustedfor
));
175 controlreply(sender
, "Currently using : %d", tg
->count
);
176 controlreply(sender
, "Clients per user : %s", formatlimit(tg
->maxperident
));
177 controlreply(sender
, "Flags : %s", formatflags(tg
->flags
));
178 controlreply(sender
, "Contact: : %s", tg
->contact
->content
);
179 controlreply(sender
, "Expires in : %s", (tg
->expires
)?((tg
->expires
>t
)?longtoduration(tg
->expires
- t
, 2):"the past (will be removed during next cleanup)"):"never");
180 controlreply(sender
, "Created by : %s", tg
->createdby
->content
);
181 controlreply(sender
, "Comment: : %s", tg
->comment
->content
);
182 controlreply(sender
, "ID: : %u", tg
->id
);
183 controlreply(sender
, "Last used : %s", (tg
->count
>0)?"(now)":((tg
->lastseen
>0)?trusts_timetostr(tg
->lastseen
):"(never)"));
184 controlreply(sender
, "Max usage : %d", tg
->maxusage
);
185 controlreply(sender
, "Last max reset : %s", tg
->lastmaxusereset
?trusts_timetostr(tg
->lastmaxusereset
):"(never)");
187 controlreply(sender
, "---");
188 controlreply(sender
, "Attributes: * (has hidden children, show with -v), > (belongs to this trust group)");
189 controlreply(sender
, "Host Current Max Last seen Max per Node Node Mask Group ID Group name");
191 marker
= nextthmarker();
192 array_init(&parents
, sizeof(trusthost
*));
194 for(th
=tg
->hosts
;th
;th
=th
->next
)
195 marktree(&parents
, marker
, th
, showchildren
);
197 p2
= (trusthost
**)(parents
.content
);
198 for(i
=0;i
<parents
.cursi
;i
++)
199 outputtree(sender
, marker
, tg
, p2
[i
], 0, showchildren
);
201 array_free(&parents
);
203 controlreply(sender
, "End of list.");
206 static int trusts_cmdtrustlist(void *source
, int cargc
, char **cargv
) {
207 nick
*sender
= source
;
208 trustgroup
*tg
= NULL
;
209 int found
= 0, remaining
= 50;
212 struct irc_in_addr ip
;
219 if(strcmp(cargv
[0], "-v") == 0) {
230 tg
= tg_strtotg(name
);
233 displaygroup(sender
, tg
, showchildren
);
237 if(ipmask_parse(name
, &ip
, &bits
)) {
238 th
= th_getbyhost(&ip
);
241 controlreply(sender
, "Specified IP address is not trusted.");
245 displaygroup(sender
, th
->group
, showchildren
);
249 for(tg
=tglist
;tg
;tg
=tg
->next
) {
250 if(match(name
, tg
->name
->content
))
253 displaygroup(sender
, tg
, showchildren
);
254 if(--remaining
== 0) {
255 controlreply(sender
, "Maximum number of matches reached.");
262 controlreply(sender
, "No matches found.");
267 static int comparetgs(const void *_a
, const void *_b
) {
268 const trustgroup
*a
= _a
;
269 const trustgroup
*b
= _b
;
278 static int trusts_cmdtrustdump(void *source
, int argc
, char **argv
) {
280 trustgroup
*tg
, **atg
;
281 unsigned int wanted
, max
, maxid
, totalcount
, i
, groupcount
, linecount
;
284 if((argc
< 2) || (argv
[0][0] != '#'))
287 wanted
= atoi(&argv
[0][1]);
290 for(maxid
=totalcount
=0,tg
=tglist
;tg
;tg
=tg
->next
) {
291 if(totalcount
== 0 || tg
->id
> maxid
)
297 if(maxid
> totalcount
) {
298 controlreply(np
, "Start ID cannot exceed current maximum group ID (#%u)", maxid
);
302 atg
= nsmalloc(POOL_TRUSTS
, sizeof(trusthost
*) * totalcount
);
304 controlreply(np
, "Memory error.");
308 for(i
=0,tg
=tglist
;i
<totalcount
&&tg
;tg
=tg
->next
,i
++)
311 qsort(atg
, totalcount
, sizeof(trustgroup
*), comparetgs
);
313 for(i
=0;i
<totalcount
;i
++)
314 if(atg
[i
]->id
>= wanted
)
317 for(groupcount
=linecount
=0;i
<totalcount
;i
++) {
321 controlreply(np
, "G,%s", dumptg(atg
[i
], 1));
323 for(th
=atg
[i
]->hosts
;th
;th
=th
->next
) {
325 controlreply(np
, "H,%s", dumpth(th
, 1));
331 nsfree(POOL_TRUSTS
, atg
);
333 controlreply(np
, "End of list, %u groups and %u lines returned.", groupcount
, linecount
);
337 static void trusts_suggestgline_cb(const char *mask
, int hits
, void *uarg
) {
340 controlreply(sender
, "mask: %s, hits: %d", mask
, hits
);
343 static int trusts_cmdtrustglinesuggest(void *source
, int cargc
, char **cargv
) {
344 nick
*sender
= source
;
346 char *p
, *user
, *host
;
347 struct irc_in_addr ip
;
354 strncpy(mask
, cargv
[0], sizeof(mask
));
356 p
= strchr(mask
, '@');
365 if(!ipmask_parse(host
, &ip
, &bits
)) {
366 controlreply(sender
, "Invalid CIDR.");
370 count
= glinesuggestbyip(user
, &ip
, 128, 0, trusts_suggestgline_cb
, sender
);
372 controlreply(sender
, "Total hits: %d", count
);
377 static int trusts_cmdtrustspew(void *source
, int cargc
, char **cargv
) {
378 nick
*sender
= source
;
384 tree
= NSASTNode(tgroup_parse
, NSASTLiteral(cargv
[0]));
385 return ast_nicksearch(&tree
, controlreply
, sender
, NULL
, printnick_channels
, NULL
, NULL
, 2000);
388 static int commandsregistered
;
390 static void registercommands(int hooknum
, void *arg
) {
391 if(commandsregistered
)
393 commandsregistered
= 1;
395 registercontrolhelpcmd("trustlist", NO_OPER
, 2, trusts_cmdtrustlist
, "Usage: trustlist [-v] <#id|name|IP>\nShows trust data for the specified trust group.");
396 registercontrolhelpcmd("trustdump", NO_OPER
, 2, trusts_cmdtrustdump
, "Usage: trustdump <#id> <number>");
397 registercontrolhelpcmd("trustglinesuggest", NO_OPER
, 1, trusts_cmdtrustglinesuggest
, "Usage: trustglinesuggest <user@host>\nSuggests glines for the specified hostmask.");
398 registercontrolhelpcmd("trustspew", NO_OPER
, 1, trusts_cmdtrustspew
, "Usage: trustspew <#id|name>\nShows currently connected users for the specified trust group.");
401 static void deregistercommands(int hooknum
, void *arg
) {
402 if(!commandsregistered
)
404 commandsregistered
= 0;
406 deregistercontrolcmd("trustlist", trusts_cmdtrustlist
);
407 deregistercontrolcmd("trustdump", trusts_cmdtrustdump
);
408 deregistercontrolcmd("trustglinesuggest", trusts_cmdtrustglinesuggest
);
409 deregistercontrolcmd("trustspew", trusts_cmdtrustspew
);
413 registerhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
414 registerhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
417 registercommands(0, NULL
);
421 deregisterhook(HOOK_TRUSTS_DB_LOADED
, registercommands
);
422 deregisterhook(HOOK_TRUSTS_DB_CLOSED
, deregistercommands
);
424 deregistercommands(0, NULL
);