]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix memory free on fail for $INCLUDE in authzone.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 13 Apr 2018 13:04:26 +0000 (13:04 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 13 Apr 2018 13:04:26 +0000 (13:04 +0000)
- Fix that an internal error to look up the wrong rr type for
  auth zone gets stopped, before trying to send there.
- auth zone notify work.

git-svn-id: file:///svn/unbound/trunk@4623 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/authzone.c
services/authzone.h

index c18c0b8e7c20d14897f621cba1ec18c970ce45df..4e8b11319c0720a667f0fb00bd3439b982bc12b6 100644 (file)
@@ -1,5 +1,9 @@
 13 April 2018: Wouter
        - Fix for max include depth for authzones.
+       - Fix memory free on fail for $INCLUDE in authzone.
+       - Fix that an internal error to look up the wrong rr type for
+         auth zone gets stopped, before trying to send there.
+       - auth zone notify work.
 
 10 April 2018: Ralph
        - num.query.aggressive.NOERROR and num.query.aggressive.NXDOMAIN
index a46dd3b99699f032a86c051502c44ad1a1821fdf..4353341862ea82a650ff00f622ef50bed1bfa7e1 100644 (file)
@@ -1494,6 +1494,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                                "file %s", fname,
                                                lineno_orig, incfile);
                                        fclose(inc);
+                                       free(incfile);
                                        return 0;
                                }
                                fclose(inc);
@@ -1946,6 +1947,7 @@ auth_xfer_delete(struct auth_xfer* xfr)
                }
                free(xfr->task_transfer);
        }
+       auth_free_masters(xfr->allow_notify_list);
        free(xfr);
 }
 
@@ -3225,15 +3227,49 @@ auth_zone_parse_notify_serial(sldns_buffer* pkt, uint32_t *serial)
        return 1;
 }
 
+/** see if addr appears in the list */
+static int
+addr_in_list(struct auth_addr* list, struct sockaddr_storage* addr,
+       socklen_t addrlen)
+{
+       struct auth_addr* p;
+       for(p=list; p; p=p->next) {
+               if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0)
+                       return 1;
+       }
+       return 0;
+}
+
+/** check if an address matches a master specification (or one of its
+ * addresses in the addr list) */
+static int
+addr_matches_master(struct auth_master* master, struct sockaddr_storage* addr,
+       socklen_t addrlen)
+{
+       struct sockaddr_storage a;
+       socklen_t alen = 0;
+       if(addr_in_list(master->list, addr, addrlen))
+               return 1;
+       /* could be nice to note host is an IP literal? TODO */
+       if(extstrtoaddr(master->host, &a, &alen) &&
+               sockaddr_cmp_addr(addr, addrlen, &a, alen)==0)
+               return 1;
+       /* TODO prefixes need a bool to note they are or detectable with
+        * a detector routine, also to avoid looking them up. */
+       return 0;
+}
+
 /** check access list for notifies */
 static int
 az_xfr_allowed_notify(struct auth_xfer* xfr, struct sockaddr_storage* addr,
        socklen_t addrlen)
 {
-       /* TODO */
-       (void)xfr;
-       (void)addr;
-       (void)addrlen;
+       struct auth_master* p;
+       for(p=xfr->allow_notify_list; p; p=p->next) {
+               if(addr_matches_master(p, addr, addrlen)) {
+                       return 1;
+               }
+       }
        return 0;
 }
 
@@ -3339,6 +3375,93 @@ xfr_masterlist_free_addrs(struct auth_master* list)
        }
 }
 
+/** copy a list of auth_addrs */
+static struct auth_addr*
+auth_addr_list_copy(struct auth_addr* source)
+{
+       struct auth_addr* list = NULL, *last = NULL;
+       struct auth_addr* p;
+       for(p=source; p; p=p->next) {
+               struct auth_addr* a = (struct auth_addr*)memdup(p, sizeof(*p));
+               if(!a) {
+                       log_err("malloc failure");
+                       auth_free_master_addrs(list);
+                       return NULL;
+               }
+               a->next = NULL;
+               if(last) last->next = a;
+               if(!list) list = a;
+               last = a;
+       }
+       return list;
+}
+
+/** copy a master to a new structure, NULL on alloc failure */
+static struct auth_master*
+auth_master_copy(struct auth_master* o)
+{
+       struct auth_master* m;
+       if(!o) return NULL;
+       m = (struct auth_master*)memdup(o, sizeof(*o));
+       if(!m) {
+               log_err("malloc failure");
+               return NULL;
+       }
+       m->next = NULL;
+       if(m->host) {
+               m->host = strdup(m->host);
+               if(!m->host) {
+                       free(m);
+                       log_err("malloc failure");
+                       return NULL;
+               }
+       }
+       if(m->file) {
+               m->file = strdup(m->file);
+               if(!m->file) {
+                       free(m->host);
+                       free(m);
+                       log_err("malloc failure");
+                       return NULL;
+               }
+       }
+       if(m->list) {
+               m->list = auth_addr_list_copy(m->list);
+               if(!m->list) {
+                       free(m->file);
+                       free(m->host);
+                       free(m);
+                       return NULL;
+               }
+       }
+       return m;
+}
+
+/** copy the master addresses from the task_probe lookups to the allow_notify
+ * list of masters */
+static void
+probe_copy_masters_for_allow_notify(struct auth_xfer* xfr)
+{
+       struct auth_master* list = NULL, *last = NULL;
+       struct auth_master* p;
+       /* build up new list with copies */
+       for(p = xfr->task_probe->masters; p; p=p->next) {
+               struct auth_master* m = auth_master_copy(p);
+               if(!m) {
+                       auth_free_masters(list);
+                       /* failed because of malloc failure, use old list */
+                       return;
+               }
+               m->next = NULL;
+               if(last) last->next = m;
+               if(!list) list = m;
+               last = m;
+       }
+       /* success, replace list */
+       auth_free_masters(xfr->allow_notify_list);
+       xfr->allow_notify_list = list;
+}
+
 /** start the lookups for task_transfer */
 static void
 xfr_transfer_start_lookups(struct auth_xfer* xfr)
@@ -4792,6 +4915,8 @@ xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
        size_t i;
        struct packed_rrset_data* data;
        if(!m || !rrset) return;
+       if(rrtype != LDNS_RR_TYPE_A && rrtype != LDNS_RR_TYPE_AAAA)
+               return;
        data = (struct packed_rrset_data*)rrset->entry.data;
        for(i=0; i<data->count; i++) {
                struct auth_addr* a;
@@ -5664,6 +5789,14 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
                }
                xfr_probe_move_to_next_lookup(xfr, env);
        }
+       /* TODO Also lookup notify in masterlist.
+        * but skip them for xfr and probe attempts.  (allow_notify_only).
+        * and here, copy the list of addresses for the masters/notifies
+        * to a separate list.  
+        */ 
+       /* probe of list has ended.  Create or refresh the list of of
+        * allow_notify addrs */
+       probe_copy_masters_for_allow_notify(xfr);
 
        /* send probe packets */
        while(!xfr_probe_end_of_list(xfr)) {
index 0b45edb29e9770af63b953091854b42a966ab83c..30ef204484c21498cf6c8142ae60682c6c1a8da7 100644 (file)
@@ -220,6 +220,10 @@ struct auth_xfer {
        int notify_received;
        /** serial number of the notify */
        uint32_t notify_serial;
+       /** the list of masters for checking notifies.  This list is
+        * empty on start, and a copy of the list from the probe_task when
+        * it is done looking them up. */
+       struct auth_master* allow_notify_list;
 
        /* protected by the lock on the structure, information about
         * the loaded authority zone. */