]> jfr.im git - irc/quakenet/newserv.git/blobdiff - patricianick/patricianick.c
LUA: add function for channel chanop notice
[irc/quakenet/newserv.git] / patricianick / patricianick.c
index 5227a109e477ee7e071131d9cdaf392c290cab81..44de41dcd4a63f45d2abf8cfdf71865940284e8f 100644 (file)
@@ -7,30 +7,30 @@
 #include "../core/nsmalloc.h"
 #include "../control/control.h"
 #include "../core/schedule.h"
+#include "../lib/version.h"
 
 #include <stdio.h>
 #include <string.h>
 
-#define ALLOCUNIT      1000
+MODULE_VERSION("")
 
-patricianick_t *freepatricianicks;
 int pnode_ext;
 int pnick_ext;
 
-int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv);
+int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv);
 
 void _init() {
   nick *np, *nnp;
   int i;
 
   pnode_ext = registernodeext("patricianick");
-  if ( pnode_ext == -1 ) {
+  if (pnode_ext == -1) {
     Error("patricianick", ERR_FATAL, "Could not register a required node extension");
     return;
   }
 
   pnick_ext = registernickext("patricianick");
-  if ( pnick_ext == -1) { 
+  if (pnick_ext == -1) {
     Error("patricianick", ERR_FATAL, "Could not register a required nick extension");
     return;
   }
@@ -44,12 +44,12 @@ void _init() {
   registerhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
   registerhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
 
-  registercontrolcmd("dumpnodenicks", NO_DEVELOPER, 1, &pn_cmd_dumpnodenicks);
+  registercontrolhelpcmd("nodeuserlist", NO_OPER, 1, &pn_cmd_nodeuserlist, "Usage: nodeuserlist <ipv4|ipv6|cidr4|cidr6>\nLists all users on a given IP address or CIDR range.");
 }
 
 void _fini() {
   nsfreeall(POOL_PATRICIANICK);
+
   if (pnode_ext != -1) {
     releasenodeext(pnode_ext);
   }
@@ -61,44 +61,41 @@ void _fini() {
   deregisterhook(HOOK_NICK_NEWNICK, &pn_hook_newuser);
   deregisterhook(HOOK_NICK_LOSTNICK, &pn_hook_lostuser);
 
-  deregistercontrolcmd("dumpnodenicks", &pn_cmd_dumpnodenicks);
+  deregistercontrolcmd("nodeuserlist", &pn_cmd_nodeuserlist);
 }
 
 patricianick_t *getpatricianick() {
-  int i;
-  patricianick_t *pnp;
+  patricianick_t *pnp = nsmalloc(POOL_PATRICIANICK, sizeof(patricianick_t));
 
-  if (freepatricianicks==NULL) {
-    freepatricianicks=(patricianick_t *)nsmalloc(POOL_PATRICIANICK, ALLOCUNIT*sizeof(patricianick_t));
-    for(i=0;i<ALLOCUNIT-1;i++) {
-      freepatricianicks[i].np=(nick *)&(freepatricianicks[i+1]);
-    }
-    freepatricianicks[ALLOCUNIT-1].np=NULL;
-  }
-
-  pnp=freepatricianicks;
-  freepatricianicks=(patricianick_t *)pnp->np;
+  if (!pnp)
+    return NULL;
 
-  pnp->marker = 0;
-  pnp->np = NULL;
+  memset(pnp, 0, sizeof(patricianick_t));
   return pnp;
 }
 
 void addnicktonode(patricia_node_t *node, nick *np) {
-  if ( !(node->exts[pnode_ext]) ) {
+  unsigned long hash;
+
+  patricia_ref_prefix(node->prefix);
+
+  if (!(node->exts[pnode_ext])) {
     node->exts[pnode_ext] = getpatricianick();
   }
-  np->exts[pnick_ext] = ((patricianick_t *)node->exts[pnode_ext])->np;
-  ((patricianick_t *)node->exts[pnode_ext])->np = np;
+
+  hash = pn_getidenthash(np->ident);
+  np->exts[pnick_ext] = ((patricianick_t *)node->exts[pnode_ext])->identhash[hash];
+  ((patricianick_t *)node->exts[pnode_ext])->identhash[hash] = np;
 }
 
 void deletenickfromnode(patricia_node_t *node, nick *np) {
   nick **tnp;
-  int found =0; 
+  int found, i;
+
+  found = 0;
 
-  for ( tnp = &(((patricianick_t *)node->exts[pnode_ext])->np); *tnp; tnp = (nick **)(&((*tnp)->exts[pnick_ext])) ) {
-    if ( *tnp == np ) { 
+  for (tnp = &(((patricianick_t *)node->exts[pnode_ext])->identhash[pn_getidenthash(np->ident)]); *tnp; tnp = (nick **)(&((*tnp)->exts[pnick_ext]))) {
+    if (*tnp == np) {
       *tnp = np->exts[pnick_ext];
       found = 1;
       break;
@@ -106,19 +103,22 @@ void deletenickfromnode(patricia_node_t *node, nick *np) {
   }
 
   if (!found) {
-    return; /* err */
+    Error("patricianick", ERR_ERROR, "Could not remove %s!%s from %s", np->nick, np->ident, IPtostr(node->prefix->sin));
+    return;
   }
 
-  if (!(((patricianick_t *)node->exts[pnode_ext])->np)) {
-    freepatricianick(node->exts[pnode_ext]);
-    node->exts[pnode_ext]= NULL;
+  for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
+    if (((patricianick_t *)node->exts[pnode_ext])->identhash[i]) {
+      return;
+    }
   }
 
+  freepatricianick(node->exts[pnode_ext]);
+  node->exts[pnode_ext]= NULL;
 }
 
 void freepatricianick(patricianick_t *pnp) {
-  pnp->np=(nick *)freepatricianicks;
-  freepatricianicks=pnp;
+  nsfree(POOL_PATRICIANICK, pnp);
 }
 
 void pn_hook_newuser(int hook, void *arg) {
@@ -133,46 +133,51 @@ void pn_hook_lostuser(int hook, void *arg) {
   deletenickfromnode(np->ipnode, np);
 }
 
-int pn_cmd_dumpnodenicks(void *source, int cargc, char **cargv) {
+int pn_cmd_nodeuserlist(void *source, int cargc, char **cargv) {
   nick *np=(nick *)source;
   struct irc_in_addr sin;
   unsigned char bits;
+  unsigned int count, i;
   patricia_node_t *head, *node;
   patricianick_t *pnp;
   nick *npp;
-  int limit = 0;
 
   if (cargc < 1) {
-    controlreply(np, "Syntax: dumpnodenicks <ipv4|ipv6|cidr4|cidr6>");
-    return CMD_OK;
+    return CMD_USAGE;
   }
 
   if (ipmask_parse(cargv[0], &sin, &bits) == 0) {
     controlreply(np, "Invalid mask.");
-    return CMD_OK;
+    return CMD_ERROR;
   }
 
   head = refnode(iptree, &sin, bits);
+  count = 0;
 
   PATRICIA_WALK(head, node)
   {
     pnp = node->exts[pnode_ext];
-    if (pnp ) {
-      npp = pnp->np;
-      while(npp) {
-        limit++;
-
-        if ( limit < PATRICIANICK_MAXRESULTS )
-          controlreply(np, "%s!%s@%s%s%s (%s)", npp->nick, npp->ident, npp->host->name->content, IsAccount(npp) ? "/" : "", npp->authname, IPtostr(node->prefix->sin));
-        else if ( limit == PATRICIANICK_MAXRESULTS )
-          controlreply(np, "Too many Results, truncated..");
-        npp=npp->exts[pnick_ext];
-      }    
+    if (pnp) {
+      if (count < PATRICIANICK_MAXRESULTS) {
+        for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
+          for (npp = pnp->identhash[i]; npp; npp=npp->exts[pnick_ext]) {
+            controlreply(np, "%s!%s@%s%s%s (%s)", npp->nick, npp->ident, npp->host->name->content, IsAccount(npp) ? "/" : "", npp->authname, IPtostr(node->prefix->sin));
+          }
+        }
+
+        count += node->usercount;
+
+        if (count >= PATRICIANICK_MAXRESULTS) {
+          controlreply(np, "Too many results, output truncated");
+        }
+      } else {
+        count += node->usercount;
+      }
     }
   }
   PATRICIA_WALK_END;
-  controlreply(np, "Nick Count: %d", limit);
+  derefnode(iptree, head);
 
+  controlreply(np, "Total users on %s: %d", cargv[0], count);
   return CMD_OK;
 }
-