]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Implicit declaration -> strange crashes
authorYuri Schaeffer <yuri@nlnetlabs.nl>
Thu, 14 Feb 2013 15:38:07 +0000 (15:38 +0000)
committerYuri Schaeffer <yuri@nlnetlabs.nl>
Thu, 14 Feb 2013 15:38:07 +0000 (15:38 +0000)
Improved parsing ednsdata
Improved mesh state selection

git-svn-id: file:///svn/unbound/branches/edns-subnet@2844 be551aaa-1e26-0410-a405-d3ace91eadb9

edns-subnet/subnetmod.c
services/mesh.c
util/data/msgparse.c

index 54e0e49829e933bb7f875d5ed42e6d1cfd2d2f4e..acaf115fc6a4588e4673095f03b889dc8e240fc5 100644 (file)
@@ -46,6 +46,7 @@
 #include "edns-subnet/edns-subnet.h"
 #include "services/mesh.h"
 #include "util/module.h"
+#include "util/regional.h"
 
 /** fill in message structure */
 static struct subnet_qstate*
index 04df7ac5f6fd8ea1d7d911d84a649152c45db816..d85b04eb0fce8605de82df6f7868598bc1b69d07 100644 (file)
@@ -124,11 +124,46 @@ timeval_smaller(const struct timeval* x, const struct timeval* y)
 #endif
 }
 
+#ifdef CLIENT_SUBNET
+/** Returns a==b: 0, a<b: positive, a>b: negative */
+int subnet_compare(struct edns_data *a, struct edns_data *b)
+{
+       if (!a) {
+               if (b) return 1;
+               return 0;
+       } else {
+               if (!b) return -1;
+               /* crude way:
+                * return  memcmp(b, a, sizeof(struct edns_data)); */
+               
+               if ( a->edns_present && !b->edns_present) return -1;
+               if (!a->edns_present && !b->edns_present) return  0;
+               if (!a->edns_present &&  b->edns_present) return  1;
+
+               if ( a->subnet_validdata && !b->subnet_validdata) return -1;
+               if (!a->subnet_validdata && !b->subnet_validdata) return  0;
+               if (!a->subnet_validdata &&  b->subnet_validdata) return  1;
+               
+               if (a->subnet_addr_fam != b->subnet_addr_fam) {
+                       return b->subnet_addr_fam - a->subnet_addr_fam;
+               }
+               if (a->subnet_source_mask != b->subnet_source_mask) {
+                       return b->subnet_source_mask - a->subnet_source_mask;
+               }
+               return memcmp(b->subnet_addr, a->subnet_addr, INET6_SIZE);
+               
+       }
+}
+#endif
+
 int
 mesh_state_compare(const void* ap, const void* bp)
 {
        struct mesh_state* a = (struct mesh_state*)ap;
        struct mesh_state* b = (struct mesh_state*)bp;
+#ifdef CLIENT_SUBNET
+       int r;
+#endif
 
        if(ap == bp)
                return 0;
@@ -147,6 +182,10 @@ mesh_state_compare(const void* ap, const void* bp)
        if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD))
                return 1;
 
+#ifdef CLIENT_SUBNET
+       r = subnet_compare(a->s.edns_from_client, b->s.edns_from_client);
+       if (r != 0) return r;
+#endif
        return query_info_compare(&a->s.qinfo, &b->s.qinfo);
 }
 
@@ -311,21 +350,6 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
                        return;
                }
        }
-#ifdef CLIENT_SUBNET
-       /* See if both the found mesh and the query have the same subnet
-        * option set. If not forget about mesh_state and create a new one */
-       if(s) {
-               struct edns_data* medns = s->s.edns_from_client;
-               if ( !(edns->edns_present && edns->subnet_validdata) ||
-                       !(medns && medns->edns_present && medns->subnet_validdata) ||
-                       edns->subnet_addr_fam != medns->subnet_addr_fam ||
-                       edns->subnet_source_mask != medns->subnet_source_mask ||
-                       memcmp(edns->subnet_addr, medns->subnet_addr, INET6_SIZE) != 0)
-               {
-                       s = NULL;
-               }
-       }
-#endif
        /* see if it already exists, if not, create one */
        if(!s) {
 #ifdef UNBOUND_DEBUG
@@ -1015,7 +1039,10 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
        key.s.is_priming = prime;
        key.s.qinfo = *qinfo;
        key.s.query_flags = qflags;
-       
+#ifdef CLIENT_SUBNET
+       key.s.edns_from_client = NULL;
+#endif
+
        result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
        return result;
 }
index 580e82d2684b6acd9430a9d3e6295e392841a473..3d34b25ad9442093e04e02a18424fff374fa8905 100644 (file)
@@ -941,20 +941,21 @@ parse_ednsdata(uint8_t* data, struct edns_data* edns)
        edns->subnet_validdata = 0;
        /* Parse EDNS data field */
        edns_datalen = ldns_read_uint16(data);
+       data += 2;
        if(edns_datalen < 4) return;
        /* iterate trough all options */
        opt_start = 0;
        while(opt_start + 4 <= edns_datalen) { /* opcode + len must fit */
-               opt_opc = ldns_read_uint16(&data[2 + opt_start]);
-               opt_len = ldns_read_uint16(&data[4 + opt_start]);
+               opt_opc = ldns_read_uint16(&data[opt_start]);
+               opt_len = ldns_read_uint16(&data[2 + opt_start]);
                /* Option does not fit in remaining data */
                if(opt_start + 4 + opt_len > edns_datalen) return;
                opt_start += 4;
                if(opt_opc == EDNSSUBNET_OPCODE) {
                        if(opt_len < 4) break;
-                       edns->subnet_addr_fam = ldns_read_uint16(data + 2 + opt_start);
-                       edns->subnet_source_mask = data[4 + opt_start];
-                       edns->subnet_scope_mask = data[5 + opt_start];
+                       edns->subnet_addr_fam = ldns_read_uint16(data + opt_start);
+                       edns->subnet_source_mask = data[2 + opt_start];
+                       edns->subnet_scope_mask = data[3 + opt_start];
                        /* remaing bytes indicate address */
                        if(opt_len - 4 > INET6_SIZE || opt_len == 0) break;
                        memset(edns->subnet_addr, 0, INET6_SIZE);
@@ -1022,7 +1023,7 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns)
        edns->ext_rcode = found->rr_last->ttl_data[0];
        edns->edns_version = found->rr_last->ttl_data[1];
        edns->bits = ldns_read_uint16(&found->rr_last->ttl_data[2]);
-#ifdef CLIENT_SUBNET   
+#ifdef CLIENT_SUBNET
        parse_ednsdata(found->rr_last->ttl_data + 4, edns);
 #endif
        /* ignore rdata and rrsigs */