--- /dev/null
+#include "../core/nsmalloc.h"
+#include "../lib/irc_string.h"
+#include "../lib/version.h"
+#include "patricia.h"
+#include "../core/error.h"
+#include "../core/hooks.h"
+#include "../control/control.h"
+
+#include <assert.h> /* assert */
+#include <stdio.h>
+#include <string.h>
+
+MODULE_VERSION("");
+
+patricia_tree_t *iptree;
+sstring *nodeextnames[PATRICIA_MAXSLOTS];
+
+void patriciastats(int hooknum, void *arg);
+
+void _init(void) {
+ iptree = patricia_new_tree(PATRICIA_MAXBITS);
+ assert(iptree);
+
+ registerhook(HOOK_CORE_STATSREQUEST,&patriciastats);
+}
+
+void _fini(void) {
+ deregisterhook(HOOK_CORE_STATSREQUEST,&patriciastats);
+ patricia_destroy_tree (iptree, NULL);
+ nsfreeall(POOL_PATRICIA);
+}
+
+void patriciastats(int hooknum, void *arg) {
+ long level=(long)arg;
+ char buf[100];
+ patricia_node_t *head, *node;
+ int i,j,k,l;
+
+ if (level < 5)
+ return;
+
+ sprintf(buf, "Patricia: %6d Active Nodes (%d bits)", iptree->num_active_node, iptree->maxbits);
+ triggerhook(HOOK_CORE_STATSREPLY,buf);
+
+ head = iptree->head;
+
+ i=0;j=0;
+ PATRICIA_WALK_ALL(head, node) {
+ if ( node->prefix )
+ j++;
+ else
+ i++;
+ } PATRICIA_WALK_END;
+ sprintf(buf, "Patricia: %6d Nodes, %6d Prefix (walk all)", i,j);
+ triggerhook(HOOK_CORE_STATSREPLY,buf);
+
+ head = iptree->head;
+ i=0;j=0;k=0;l=0;
+ PATRICIA_WALK(head, node) {
+ if ( node->prefix ) {
+ if (irc_in_addr_is_ipv4(&(node->prefix->sin)))
+ k++;
+ else
+ l++;
+ j++;
+ } else
+ i++;
+ } PATRICIA_WALK_END;
+ sprintf(buf, "Patricia: %6d Nodes, %6d Prefix (walk prefixes only)", i,j);
+ triggerhook(HOOK_CORE_STATSREPLY,buf);
+ sprintf(buf, "Patricia: %6d IP4Node, %6d IP6Node", k, l);
+ triggerhook(HOOK_CORE_STATSREPLY,buf);
+
+ j=0;
+ for (i=0;i<PATRICIA_MAXSLOTS;i++) {
+ if (nodeextnames[i]!=NULL) {
+ j++;
+ }
+ }
+ sprintf(buf, "Patricia: %6d ExtsUsed, %5d Max", j,PATRICIA_MAXSLOTS);
+ triggerhook(HOOK_CORE_STATSREPLY,buf);
+
+}
+
+int registernodeext(const char *name) {
+ int i;
+
+ if (findnodeext(name)!=-1) {
+ Error("patricia",ERR_WARNING,"Tried to register duplicate node extension %s",name);
+ return -1;
+ }
+
+ for (i=0;i<PATRICIA_MAXSLOTS;i++) {
+ if (nodeextnames[i]==NULL) {
+ nodeextnames[i]=getsstring(name,100);
+ return i;
+ }
+ }
+
+ Error("patricia",ERR_WARNING,"Tried to register too many extensions: %s",name);
+ return -1;
+}
+
+int findnodeext(const char *name) {
+ int i;
+
+ for (i=0;i<PATRICIA_MAXSLOTS;i++) {
+ if (nodeextnames[i]!=NULL && !ircd_strcmp(name,nodeextnames[i]->content)) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void releasenodeext(int index) {
+ patricia_node_t *head, *node;
+
+ freesstring(nodeextnames[index]);
+ nodeextnames[index]=NULL;
+
+ head = iptree->head;
+
+ PATRICIA_WALK_ALL(head, node)
+ {
+ node->exts[index]=NULL;
+ } PATRICIA_WALK_END;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "../nick/nick.h"
+#include "../localuser/localuserchannel.h"
+#include "../core/hooks.h"
+#include "../core/schedule.h"
+#include "../lib/array.h"
+#include "../lib/base64.h"
+#include "../lib/irc_string.h"
+#include "../lib/splitline.h"
+#include "../control/control.h"
+
+FILE* dumpip_logfp;
+int nc_cmd_dumptree(void *source, int cargc, char **cargv);
+int nc_cmd_nodecount(void *source, int cargc, char **cargv);
+
+void _init() {
+ if (!(dumpip_logfp = fopen("log/iplist", "w")))
+ Error("dumpip", ERR_ERROR, "Failed to open log file!");
+ registercontrolcmd("dumptree", 10, 2, &nc_cmd_dumptree);
+ registercontrolcmd("nodecount", 10, 1, &nc_cmd_nodecount);
+}
+
+void _fini() {
+ if (dumpip_logfp)
+ fclose(dumpip_logfp);
+ deregistercontrolcmd("dumptree", &nc_cmd_dumptree);
+ deregistercontrolcmd("nodecount", &nc_cmd_nodecount);
+}
+
+int nc_cmd_dumptree(void *source, int cargc, char **cargv) {
+ nick *np=(nick *)source;
+ struct irc_in_addr sin;
+ unsigned char bits;
+ patricia_node_t *head, *node;
+ unsigned int level=0;
+ int i = 0;
+
+ if (cargc < 1) {
+ controlreply(np, "Syntax: dumptree <ipv4|ipv6|cidr4|cidr6>");
+ return CMD_OK;
+ }
+
+ if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
+ controlreply(np, "Invalid mask.");
+ return CMD_OK;
+ }
+
+ if (cargc>1) {
+ level=strtoul(cargv[1],NULL,10);
+ }
+
+ head = refnode(iptree, &sin, bits);
+
+ if (level < 10) {
+ PATRICIA_WALK(head, node)
+ {
+ switch (level) {
+ case 0:
+ controlreply(np,"%p: %s", node, IPtostr(node->prefix->sin));
+ break;
+ case 1:
+ controlreply(np,"%p: prefix %p, bit %d, ref_count %d, IP: %s",node, node->prefix,
+ node->prefix->bitlen, node->prefix->ref_count, IPtostr(node->prefix->sin));
+ break;
+ case 2:
+ controlreply(np,"%p: bit: %d, usercount: %d, IP: %s", node, node->bit, node->usercount, IPtostr(node->prefix->sin));
+ break;
+ case 3:
+ controlreply(np,"%p: L: %p, R: %p", node, node->l, node->r);
+ break;
+ case 4:
+ controlreply(np,"%p: 0: %p, 1: %p, 2: %p, 3: %p, 4: %p", node,
+ node->exts[0], node->exts[1], node->exts[2], node->exts[3], node->exts[4]);
+ break;
+ default:
+ if( i == 0 ) controlreply(np,"Invalid Level");
+ }
+ if ( i++ > 500) {
+ controlreply(np,"too many... aborting...");
+ break;
+ }
+ }
+ PATRICIA_WALK_END;
+ } else {
+ PATRICIA_WALK_ALL(head, node)
+ {
+ switch (level) {
+ case 10:
+ controlreply(np,"%p: prefix: %p %s", node, node->prefix, node->prefix?IPtostr(node->prefix->sin):"");
+ break;
+ case 11:
+ if(node->prefix)
+ controlreply(np,"%p: prefix bit: %d, ref_count %d, IP: %s",node,
+ node->prefix->bitlen, node->prefix->ref_count, IPtostr(node->prefix->sin));
+ else
+ controlreply(np,"%p: --", node);
+ break;
+ case 12:
+ controlreply(np,"%p: bit: %d, usercount: %d, IP: %s", node, node->bit, node->usercount, node->prefix?IPtostr(node->prefix->sin):"");
+ break;
+ case 13:
+ controlreply(np,"%p: L: %p, R: %p", node, node->l, node->r);
+ break;
+ case 14:
+ controlreply(np,"%p%s 0: %p, 1: %p, 2: %p, 3: %p, 4: %p", node, node->prefix?"-":":",
+ node->exts[0], node->exts[1], node->exts[2], node->exts[3], node->exts[4]);
+ break;
+ default:
+ if ( i == 0 ) controlreply(np,"Invalid Level");
+ }
+ if ( i++ > 500) {
+ controlreply(np,"too many... aborting...");
+ break;
+ }
+ }
+ PATRICIA_WALK_END;
+ }
+ derefnode(iptree, head);
+
+}
+
+int nc_cmd_nodecount(void *source, int cargc, char **cargv) {
+ nick *np = (nick *)source;
+ struct irc_in_addr sin;
+ unsigned char bits;
+ patricia_node_t *head, *node;
+ int count;
+
+ if (cargc < 1) {
+ controlreply(np, "Syntax: nodecount <ipv4|ipv6|cidr4|cidr6>");
+ return CMD_OK;
+ }
+
+ if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
+ controlreply(np, "Invalid mask.");
+
+ return CMD_OK;
+ }
+
+ head = refnode(iptree, &sin, bits);
+
+ count = 0;
+
+ PATRICIA_WALK(head, node) {
+ count += node->usercount;
+ } PATRICIA_WALK_END;
+
+ derefnode(iptree, head);
+
+ controlreply(np, "%d user(s) found.", count);
+
+ return CMD_OK;
+}
+