]> jfr.im git - irc/quakenet/newserv.git/blobdiff - patricia/patricialib.c
CHANSERV: add missing error statements.
[irc/quakenet/newserv.git] / patricia / patricialib.c
index 44b4e6c39489c62070c61cf9ffbf9fafa8158b8e..86584c342add2f44863660c2f30c98e54639d2c9 100644 (file)
@@ -27,6 +27,18 @@ char patricia_copyright[] =
 
 #include "patricia.h"
 
+//#define LEAK_DETECTION
+
+#ifdef LEAK_DETECTION
+#define MAGIC 0x6a3b4ef3
+
+struct fake_node {
+  patricia_node_t node;
+  uint32_t magic;
+  patricia_node_t *real_node;
+};
+#endif
+
 /* prefix_tochar
  * convert prefix information to bytes
  */
@@ -53,6 +65,7 @@ comp_with_mask (void *addr, void *dest, u_int mask)
     return (0);
 }
 
+
 prefix_t *
 patricia_new_prefix (struct irc_in_addr *dest, int bitlen)
 {
@@ -89,8 +102,8 @@ patricia_deref_prefix (prefix_t * prefix)
 
     prefix->ref_count--;
     if (prefix->ref_count <= 0) {
-       freeprefix(prefix);
-       return;
+      freeprefix(prefix);
+      return;
     }
 }
 
@@ -212,7 +225,7 @@ patricia_search_exact (patricia_tree_t *patricia, struct irc_in_addr *sin, unsig
     addr = (u_char *)sin;
 
     while (node->bit < bitlen) {
-       if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+        if (is_bit_set(addr,node->bit))
            node = node->r;
        else
            node = node->l;
@@ -225,7 +238,7 @@ patricia_search_exact (patricia_tree_t *patricia, struct irc_in_addr *sin, unsig
        return (NULL);
     assert (node->bit == bitlen);
     assert (node->bit == node->prefix->bitlen);
-    if (comp_with_mask (prefix_tochar (node->prefix), addr,    bitlen)) {
+    if (comp_with_mask (prefix_tochar (node->prefix), addr, bitlen)) {
        return (node);
     }
     return (NULL);
@@ -257,7 +270,7 @@ patricia_search_best2 (patricia_tree_t *patricia, struct irc_in_addr *sin, unsig
            stack[cnt++] = node;
        }
 
-       if (BIT_TEST (addr[node->bit >> 3], 0x80 >> (node->bit & 0x07))) {
+        if (is_bit_set(addr,node->bit)) {
            node = node->r;
        }
        else {
@@ -320,7 +333,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
     while (node->bit < bitlen || node->prefix == NULL) {
         /* check that we're not at the lowest leaf i.e. node->bit is less than max bits */
        if (node->bit < patricia->maxbits &&
-           (addr[node->bit >> 3]) & (0x80 >> (node->bit & 0x07))) {
+            (is_bit_set(addr,node->bit))) {
            if (node->r == NULL)
                break;
            node = node->r;
@@ -346,7 +359,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
            continue;
        }
        /* I know the better way, but for now */
-       for (j = 0; j < 8; j++) {
+        for (j = 0; j < 8; j++) {
            if ((r) & ((0x80 >> j)))
                break;
        }
@@ -366,19 +379,17 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
     }
 
     if (differ_bit == bitlen && node->bit == bitlen) {
-       if (node->prefix) {
-           return (node);
-       }
-       node->prefix = patricia_ref_prefix (prefix);
+       if (!node->prefix) {
+           node->prefix = patricia_ref_prefix (prefix);
+        }
        return (node);
     }
 
     new_node = patricia_new_node(patricia, prefix->bitlen, patricia_ref_prefix (prefix));
-
     if (node->bit == differ_bit) {
        new_node->parent = node;
        if (node->bit < patricia->maxbits &&
-           (addr[node->bit >> 3]) & (0x80 >> (node->bit & 0x07))) {
+           (is_bit_set(addr, node->bit))) {
            assert (node->r == NULL);
            node->r = new_node;
        }
@@ -391,7 +402,7 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
 
     if (bitlen == differ_bit) {
        if (bitlen < patricia->maxbits &&
-           (test_addr[bitlen >> 3]) & (0x80 >> (bitlen & 0x07))) {
+           (is_bit_set(test_addr,bitlen))) {
            new_node->r = node;
        }
        else {
@@ -409,13 +420,13 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
            node->parent->l = new_node;
        }
        node->parent = new_node;
+        new_node->usercount = node->usercount;
     }
     else {
         glue = patricia_new_node(patricia, differ_bit, NULL);
         glue->parent = node->parent;
-        
        if (differ_bit < patricia->maxbits &&
-           (addr[differ_bit >> 3]) & (0x80 >> (differ_bit & 0x07))) {
+           (is_bit_set(addr, differ_bit))) {
            glue->r = new_node;
            glue->l = node;
        }
@@ -436,7 +447,9 @@ patricia_lookup (patricia_tree_t *patricia, prefix_t *prefix)
            node->parent->l = glue;
        }
        node->parent = glue;
+        glue->usercount = node->usercount;
     }
+
     return (new_node);
 }
 
@@ -530,6 +543,16 @@ patricia_remove (patricia_tree_t *patricia, patricia_node_t *node)
     }
 }
 
+#ifdef LEAK_DETECTION
+static patricia_node_t *getrealnode(patricia_node_t *node) {
+  struct fake_node *f = (struct fake_node *)node;
+  if(f->magic != MAGIC) {
+    printf("magic failure\n");
+    abort();
+  }
+  return f->real_node;
+}
+#endif
 
 patricia_node_t *
 refnode(patricia_tree_t *tree, struct irc_in_addr *sin, int bitlen) {
@@ -546,6 +569,14 @@ refnode(patricia_tree_t *tree, struct irc_in_addr *sin, int bitlen) {
     patricia_ref_prefix(node->prefix);
   }
 
+#ifdef LEAK_DETECTION
+  struct fake_node *f = malloc(sizeof(struct fake_node));
+  f->magic = MAGIC;
+  f->node = *node;
+  f->real_node = node;
+  node = (patricia_node_t *)f;
+#endif
+
   return node;
 }
 
@@ -554,6 +585,15 @@ derefnode(patricia_tree_t *tree, patricia_node_t *node) {
   if (!node || !node->prefix)
     return;
 
+#ifdef LEAK_DETECTION
+  patricia_node_t *real_node = getrealnode(node);
+  free(node);
+  node = real_node;
+
+  if (!node || !node->prefix)
+    return;
+#endif
+
   if (node->prefix->ref_count == 1) {
     patricia_remove(tree, node);
   } else
@@ -572,3 +612,35 @@ patricia_node_t *patricia_new_node(patricia_tree_t *patricia, unsigned char bit,
   return new_node;  
 }
 
+void node_increment_usercount( patricia_node_t *node) {
+#ifdef LEAK_DETECTION
+  node = getrealnode(node);
+#endif
+
+  while(node) {
+    node->usercount++;
+    node=node->parent;
+  }
+}
+
+void node_decrement_usercount( patricia_node_t *node) {
+#ifdef LEAK_DETECTION
+  node = getrealnode(node);
+#endif
+
+  while(node) {
+    node->usercount--;
+    node=node->parent;
+  }
+}
+
+int is_normalized_ipmask( struct irc_in_addr *sin, unsigned char bitlen ) {
+  u_char *addr = (u_char *)sin;
+
+  while (bitlen < PATRICIA_MAXBITS) {
+    if (is_bit_set(addr,bitlen))
+       return 0;
+    bitlen++;
+  }
+  return 1;
+}