dairiki / rbldnsd

Enhanced IP6 support for rbldnsd
3 stars 0 forks source link

Support /128 in ip6tset #2

Closed key2peace closed 11 years ago

key2peace commented 11 years ago

First of all, lemme explain WHY I made this patch:

diff --git a/rbldnsd_ip6tset.c b/rbldnsd_ip6tset.c
index ca3e885..2f645a7 100644
--- a/rbldnsd_ip6tset.c
+++ b/rbldnsd_ip6tset.c
@@ -1,4 +1,4 @@
-/* ip6tset dataset type: IP6 half-addresses (/64s),
+/* ip6tset dataset type: IP6 full-addresses (/128s),
  * with the same A and TXT values for every individual entry.
  * Exclusions as /64 or /128 are recognized.
  */
@@ -9,28 +9,30 @@
 #include "rbldnsd.h"
 #include "ip6addr.h"

-struct ip6half {
-  ip6oct_t a[IP6ADDR_HALF];
-};
-
-struct ip6full {
-  ip6oct_t a[IP6ADDR_FULL];
+struct entry {
+  ip6oct_t a[IP6ADDR_FULL];    /* key: IP address */
 };

 struct dsdata {
   unsigned a_cnt, e_cnt; /* count */
   unsigned a_alc, e_alc; /* allocated (only for loading) */
   unsigned a_hnt, e_hnt; /* hint: how much to allocate next time */
-  struct ip6half *a;    /* array of entries */
-  struct ip6full *e;    /* array of exclusions */
+  struct entry *a;  /* array of entries */
+  struct entry *e;  /* array of exclusions */
   const char *def_rr;   /* default A and TXT RRs */
 };

 definedstype(ip6tset, DSTF_IP6REV, "(trivial) set of ip6 addresses");

 static void ds_ip6tset_reset(struct dsdata *dsd, int UNUSED unused_freeall) {
-  free(dsd->a); dsd->a = NULL;
-  free(dsd->e); dsd->e = NULL;
+  if (dsd->a) {  
+    free(dsd->a);
+    dsd->a = NULL;
+  }
+  if (dsd->e) {
+    free(dsd->e);
+    dsd->e = NULL;
+  }
   dsd->a_alc = dsd->e_alc = 0;
   dsd->a_cnt = dsd->e_cnt = 0;
   dsd->def_rr = NULL;
@@ -69,19 +71,19 @@ ds_ip6tset_line(struct dataset *ds, char *s, struct dsctx *dsc) {
     dswarn(dsc, "invalid address");
     return 1;
   }
-  if (bits != (excl ? 128 : 64)) {
-    dswarn(dsc, "invalid address for %s (should be %d bits)",
-      excl ? "exclusion" : "regular entry", excl ? 128 : 64);
+  if (bits != 128) {
+    dswarn(dsc, "invalid address for %s (should be 128 bits)",
+      excl ? "exclusion" : "regular entry");
     return 1;
   }

   if (excl) {
     if (dsd->e_cnt >= dsd->e_alc) {
-      struct ip6full *e = dsd->e;
+      struct entry *e = dsd->e;
       unsigned alc =
    dsd->e_alc ? dsd->e_alc << 1 :
-   dsd->e_hnt ? dsd->e_hnt : 64;
-      e = trealloc(struct ip6full, e, alc);
+   dsd->e_hnt ? dsd->e_hnt : 128;
+      e = trealloc(struct entry, e, alc);
       if (!e)
    return 0;
       dsd->e = e;
@@ -91,11 +93,11 @@ ds_ip6tset_line(struct dataset *ds, char *s, struct dsctx *dsc) {
   }
   else {
     if (dsd->a_cnt >= dsd->a_alc) {
-      struct ip6half *a = dsd->a;
+      struct entry *a = dsd->a;
       unsigned alc =
    dsd->a_alc ? dsd->a_alc << 1 :
-   dsd->a_hnt ? dsd->a_hnt : 64;
-      a = trealloc(struct ip6half, a, alc);
+   dsd->a_hnt ? dsd->a_hnt : 128;
+      a = trealloc(struct entry, a, alc);
       if (!a)
    return 0;
       dsd->a = a;
@@ -114,18 +116,18 @@ static void ds_ip6tset_finish(struct dataset *ds, struct dsctx *dsc) {
 #define ip6tset_eeq(a,b) memcmp(&a, &b, sizeof(a)) == 0
 #define QSORT_LT(a,b) (memcmp(a, b, sizeof(*a)) < 0)

-  /* regular entries, ip6halves */
+  /* regular entries */
   n = dsd->a_cnt;
   if (!n)
     dsd->a_hnt = 0;
   else {
-    struct ip6half *a = dsd->a;
+    struct entry *a = dsd->a;

     dsd->a_hnt = dsd->a_alc;
     while((dsd->a_hnt >> 1) >= n)
       dsd->a_hnt >>= 1;

-#   define QSORT_TYPE struct ip6half
+#   define QSORT_TYPE struct entry 
 #   define QSORT_BASE a
 #   define QSORT_NELT n
 #   include "qsort.c"
@@ -133,24 +135,24 @@ static void ds_ip6tset_finish(struct dataset *ds, struct dsctx *dsc) {
 #   undef QSORT_BASE
 #   undef QSORT_TYPE

-    REMOVE_DUPS(struct ip6half, a, n, ip6tset_eeq);
-    SHRINK_ARRAY(struct ip6half, a, n, dsd->a_alc);
+    REMOVE_DUPS(struct entry, a, n, ip6tset_eeq);
+    SHRINK_ARRAY(struct entry, a, n, dsd->a_alc);
     dsd->a = a;
     dsd->a_cnt = n;
   }

-  /* exclusions, ip6fulls */
+  /* exclusions */
   n = dsd->e_cnt;
   if (!n)
     dsd->e_hnt = 0;
   else {
-    struct ip6full *e = dsd->e;
+    struct entry *e = dsd->e;

     dsd->e_hnt = dsd->e_alc;
     while((dsd->e_hnt >> 1) >= n)
       dsd->e_hnt >>= 1;

-#   define QSORT_TYPE struct ip6full
+#   define QSORT_TYPE struct entry 
 #   define QSORT_BASE e
 #   define QSORT_NELT n
 #   include "qsort.c"
@@ -158,8 +160,8 @@ static void ds_ip6tset_finish(struct dataset *ds, struct dsctx *dsc) {
 #   undef QSORT_BASE
 #   undef QSORT_TYPE

-    REMOVE_DUPS(struct ip6full, e, n, ip6tset_eeq);
-    SHRINK_ARRAY(struct ip6full, e, n, dsd->a_alc);
+    REMOVE_DUPS(struct entry, e, n, ip6tset_eeq);
+    SHRINK_ARRAY(struct entry, e, n, dsd->a_alc);
     dsd->e = e;
     dsd->e_cnt = n;
   }
@@ -169,21 +171,7 @@ static void ds_ip6tset_finish(struct dataset *ds, struct dsctx *dsc) {
 }

 static int
-ds_ip6tset_find(const struct ip6half *arr, int b, const ip6oct_t *q) {
-  int a = 0;
-  --b;
-  while(a <= b) {
-    int m = (a + b) >> 1;
-    int r = memcmp(arr[m].a, q, sizeof(*arr));
-    if (r == 0) return 1;
-    else if (r < 0) a = m + 1;
-    else b = m - 1;
-  }
-  return 0;
-}
-
-static int
-ds_ip6tset_find_excl(const struct ip6full *arr, int b, const ip6oct_t *q) {
+ds_ip6tset_find(const struct entry *arr, int b, const ip6oct_t *q) {
   int a = 0;
   --b;
   while(a <= b) {
@@ -207,7 +195,7 @@ ds_ip6tset_query(const struct dataset *ds, const struct dnsqinfo *qi,

   if (!ds_ip6tset_find(dsd->a, dsd->a_cnt, qi->qi_ip6))
     return 0;
-  if (dsd->e_cnt && ds_ip6tset_find_excl(dsd->e, dsd->e_cnt, qi->qi_ip6))
+  if (dsd->e_cnt && ds_ip6tset_find(dsd->e, dsd->e_cnt, qi->qi_ip6))
     return 0;

   ipsubst = (qi->qi_tflag & NSQUERY_TXT) ?
@@ -225,13 +213,13 @@ ds_ip6tset_dump(const struct dataset *ds,
                FILE *f) {
   const struct dsdata *dsd = ds->ds_dsd;

-  { const struct ip6half *a = dsd->a, *at = a + dsd->a_cnt;
+  { const struct entry *a = dsd->a, *at = a + dsd->a_cnt;
     while(a < at) {
-      dump_ip6((a++)->a, 16, dsd->def_rr, ds, f);
+      dump_ip6((a++)->a, 0, dsd->def_rr , ds, f);
     }
   }

-  { const struct ip6full *e = dsd->e, *et = e + dsd->e_cnt;
+  { const struct entry *e = dsd->e, *et = e + dsd->e_cnt;
     while(e < et) {
       dump_ip6((e++)->a, 0, NULL, ds, f);
     }
dairiki commented 11 years ago

Discussed via private email, however for posterity here's my take on this.

You should be using the full-featured ip6trie dataset. The ip6tset dataset was the first crack at supporting ipv6 and is very feature-constrained. Unless your server is very memory-constrained, just stick with ip6trie.

I'm just the guy who contributed the ip6trie code. Michael Tokarev is still the guy in charge of rbldnsd. So far as I know, the official support channel is still the rbldnsd mailing list.

Anyhow, I will point Michael at this ticket, but other than that I'm going to ignore it.