On 10/05/2009 03:55 PM, Marcus Alves Grando wrote:
> Hello guys,
> 
> We started to test unbound in our internal DNS servers, but when has
> some zone update we need to wait until ttl expire to had a fresh
> information. To solve this problem I implemented NOTIFY part in unbound
> to flush qname in cache.
> 
> I think that can be used in many cases, since most of times we need to
> propagate fast DNS modifications to our DNS internals.
> 
> I need to implement acl yet (notify-access-control), but what
> maintainers think about?

Complete version with acl attached. Need flex/bison to recreate related
files.

Regards

-- 
Marcus Alves Grando
marcus(at)sbh.eng.br | Personal
mnag(at)FreeBSD.org  | FreeBSD.org
Index: daemon/acl_list.h
===================================================================
--- daemon/acl_list.h   (revision 1868)
+++ daemon/acl_list.h   (working copy)
@@ -45,6 +45,7 @@
 #include "util/storage/dnstree.h"
 struct config_file;
 struct regional;
+struct config_str2list;
 
 /**
  * Enumeration of access control options for an address range.
@@ -100,10 +101,11 @@
 /**
  * Process access control config.
  * @param acl: where to store.
- * @param cfg: config options.
+ * @param acllist: linked acl list.
  * @return 0 on error.
  */
-int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg);
+int acl_list_apply_cfg(struct acl_list* acl, struct config_str2list* acllist, 
+       int do_ip6);
 
 /**
  * Lookup address to see its access control status.
Index: daemon/remote.h
===================================================================
--- daemon/remote.h     (revision 1868)
+++ daemon/remote.h     (working copy)
@@ -133,6 +133,14 @@
        struct listen_port* ports, struct worker* worker);
 
 /**
+ * Remove all rrsets and keys from zone from cache.
+ * @param ssl: the SSL connection to print to.
+ * @param worker: worker with communication base. and links to command 
channels.
+ * @param arg: argument to find out and flush.
+ */
+void do_flush_zone(SSL* ssl, struct worker* worker, char* arg);
+
+/**
  * Handle nonthreaded remote cmd execution.
  * @param worker: this worker (the remote worker).
  */
Index: daemon/daemon.c
===================================================================
--- daemon/daemon.c     (revision 1868)
+++ daemon/daemon.c     (working copy)
@@ -201,7 +201,8 @@
        }
        alloc_init(&daemon->superalloc, NULL, 0);
        daemon->acl = acl_list_create();
-       if(!daemon->acl) {
+       daemon->acl_notify = acl_list_create();
+       if(!daemon->acl || !daemon->acl_notify) {
                free(daemon->env);
                free(daemon);
                return NULL;
@@ -416,8 +417,10 @@
 daemon_fork(struct daemon* daemon)
 {
        log_assert(daemon);
-       if(!acl_list_apply_cfg(daemon->acl, daemon->cfg))
+       if(!acl_list_apply_cfg(daemon->acl, daemon->cfg->acls, 
daemon->cfg->do_ip6))
                fatal_exit("Could not setup access control list");
+       if(!acl_list_apply_cfg(daemon->acl_notify, daemon->cfg->acls_notify, 
daemon->cfg->do_ip6))
+               fatal_exit("Could not setup notify access control list");
        if(!(daemon->local_zones = local_zones_create()))
                fatal_exit("Could not create local zones: out of memory");
        if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
Index: daemon/daemon.h
===================================================================
--- daemon/daemon.h     (revision 1868)
+++ daemon/daemon.h     (working copy)
@@ -96,6 +96,8 @@
        struct module_stack mods;
        /** access control, which client IPs are allowed to connect */
        struct acl_list* acl;
+       /** access control, which client IPs are allowed to notify */
+       struct acl_list* acl_notify;
        /** local authority zones */
        struct local_zones* local_zones;
        /** last time of statistics printout */
Index: daemon/worker.c
===================================================================
--- daemon/worker.c     (revision 1868)
+++ daemon/worker.c     (working copy)
@@ -295,7 +295,8 @@
                verbose(VERB_QUERY, "request bad, has TC bit on");
                return LDNS_RCODE_FORMERR;
        }
-       if(LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
+       if(LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY &&
+               LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY) 
{
                verbose(VERB_QUERY, "request unknown opcode %d", 
                        LDNS_OPCODE_WIRE(ldns_buffer_begin(pkt)));
                return LDNS_RCODE_NOTIMPL;
@@ -689,6 +690,7 @@
        struct query_info qinfo;
        struct edns_data edns;
        enum acl_access acl;
+       char buf[257];
 
        if(error != NETEVENT_NOERROR) {
                /* some bad tcp query DNS formats give these error calls */
@@ -727,7 +729,6 @@
                comm_point_drop_reply(repinfo);
                return 0;
        }
-       worker->stats.num_queries++;
        /* see if query is in the cache */
        if(!query_info_parse(&qinfo, c->buffer)) {
                verbose(VERB_ALGO, "worker parse request: formerror.");
@@ -739,6 +740,32 @@
                server_stats_insrcode(&worker->stats, c->buffer);
                return 1;
        }
+       if(LDNS_OPCODE_WIRE(ldns_buffer_begin(c->buffer)) == 
LDNS_PACKET_NOTIFY) {
+               acl = acl_list_lookup(worker->daemon->acl_notify, 
&repinfo->addr, 
+                       repinfo->addrlen);
+               if(acl == acl_deny) {
+                       comm_point_drop_reply(repinfo);
+                       return 0;
+               } else if(acl == acl_refuse) {
+                       ldns_buffer_rewind(c->buffer);
+                       LDNS_QR_SET(ldns_buffer_begin(c->buffer));
+                       LDNS_RCODE_SET(ldns_buffer_begin(c->buffer), 
+                               LDNS_RCODE_REFUSED);
+                       log_addr(VERB_ALGO, "refused notify from",
+                               &repinfo->addr, repinfo->addrlen);
+                       log_buf(VERB_ALGO, "refuse", c->buffer);
+                       return 1;
+               }
+               verbose(VERB_ALGO, "received notify.");
+               log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
+               dname_str(qinfo.qname, buf);
+               do_flush_zone(NULL, worker, buf);
+               LDNS_QR_SET(ldns_buffer_begin(c->buffer));
+               ldns_buffer_rewind(c->buffer);
+               comm_point_send_reply(repinfo);
+               return 0;
+       }
+       worker->stats.num_queries++;
        if(qinfo.qtype == LDNS_RR_TYPE_AXFR || 
                qinfo.qtype == LDNS_RR_TYPE_IXFR) {
                verbose(VERB_ALGO, "worker request: refused zone transfer.");
Index: daemon/acl_list.c
===================================================================
--- daemon/acl_list.c   (revision 1868)
+++ daemon/acl_list.c   (working copy)
@@ -123,10 +123,10 @@
 
 /** read acl_list config */
 static int 
-read_acl_list(struct acl_list* acl, struct config_file* cfg)
+read_acl_list(struct acl_list* acl, struct config_str2list* acllist)
 {
        struct config_str2list* p;
-       for(p = cfg->acls; p; p = p->next) {
+       for(p = acllist; p; p = p->next) {
                log_assert(p->str && p->str2);
                if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
                        return 0;
@@ -135,18 +135,18 @@
 }
 
 int 
-acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg)
+acl_list_apply_cfg(struct acl_list* acl, struct config_str2list* acllist, int 
do_ip6)
 {
        regional_free_all(acl->region);
        addr_tree_init(&acl->tree);
-       if(!read_acl_list(acl, cfg))
+       if(!read_acl_list(acl, acllist))
                return 0;
        /* insert defaults, with '0' to ignore them if they are duplicates */
        if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
                return 0;
        if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
                return 0;
-       if(cfg->do_ip6) {
+       if(do_ip6) {
                if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
                        return 0;
                if(!acl_list_str_cfg(acl, "::1", "allow", 0))
Index: daemon/remote.c
===================================================================
--- daemon/remote.c     (revision 1868)
+++ daemon/remote.c     (working copy)
@@ -1161,7 +1161,7 @@
 }
 
 /** remove all rrsets and keys from zone from cache */
-static void
+void
 do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
 {
        uint8_t* nm;
Index: util/config_file.c
===================================================================
--- util/config_file.c  (revision 1868)
+++ util/config_file.c  (working copy)
@@ -131,6 +131,7 @@
        cfg->stubs = NULL;
        cfg->forwards = NULL;
        cfg->acls = NULL;
+       cfg->acls_notify = NULL;
        cfg->harden_short_bufsize = 0;
        cfg->harden_large_queries = 0;
        cfg->harden_glue = 1;
@@ -564,6 +565,7 @@
        free(cfg->dlv_anchor_file);
        config_delstrlist(cfg->dlv_anchor_list);
        config_deldblstrlist(cfg->acls);
+       config_deldblstrlist(cfg->acls_notify);
        free(cfg->val_nsec3_key_iterations);
        config_deldblstrlist(cfg->local_zones);
        config_delstrlist(cfg->local_zones_nodefault);
Index: util/configparser.y
===================================================================
--- util/configparser.y (revision 1868)
+++ util/configparser.y (working copy)
@@ -87,9 +87,9 @@
 %token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG 
 %token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST
 %token VAR_CACHE_MAX_TTL VAR_HARDEN_DNNSEC_STRIPPED VAR_ACCESS_CONTROL
-%token VAR_LOCAL_ZONE VAR_LOCAL_DATA VAR_INTERFACE_AUTOMATIC
-%token VAR_STATISTICS_INTERVAL VAR_DO_DAEMONIZE VAR_USE_CAPS_FOR_ID
-%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT 
+%token VAR_ACCESS_CONTROL_NOTIFY VAR_LOCAL_ZONE VAR_LOCAL_DATA
+%token VAR_INTERFACE_AUTOMATIC VAR_STATISTICS_INTERVAL VAR_DO_DAEMONIZE
+%token VAR_USE_CAPS_FOR_ID VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
 %token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
 %token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
 %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
@@ -140,7 +140,8 @@
        server_use_syslog | server_outgoing_interface | server_root_hints |
        server_do_not_query_localhost | server_cache_max_ttl |
        server_harden_dnssec_stripped | server_access_control |
-       server_local_zone | server_local_data | server_interface_automatic |
+       server_access_control_notify | server_local_zone | 
+       server_local_data | server_interface_automatic |
        server_statistics_interval | server_do_daemonize | 
        server_use_caps_for_id | server_statistics_cumulative |
        server_outgoing_port_permit | server_outgoing_port_avoid |
@@ -768,6 +769,19 @@
                }
        }
        ;
+server_access_control_notify: VAR_ACCESS_CONTROL_NOTIFY STRING_ARG STRING_ARG
+       {
+               OUTYY(("P(server_access_control_notify:%s %s)\n", $2, $3));
+               if(strcmp($3, "deny")!=0 && strcmp($3, "refuse")!=0 &&
+                       strcmp($3, "allow")!=0) {
+                       yyerror("expected deny, refuse or allow "
+                               "in access control action");
+               } else {
+                       if(!cfg_str2list_insert(&cfg_parser->cfg->acls_notify, 
$2, $3))
+                               fatal_exit("out of memory adding acl");
+               }
+       }
+       ;
 server_module_conf: VAR_MODULE_CONF STRING_ARG
        {
                OUTYY(("P(server_module_conf:%s)\n", $2));
Index: util/config_file.h
===================================================================
--- util/config_file.h  (revision 1868)
+++ util/config_file.h  (working copy)
@@ -138,6 +138,8 @@
        struct config_strlist* donotqueryaddrs;
        /** list of access control entries, linked list */
        struct config_str2list* acls;
+       /** list of notify access control entries, linked list */
+       struct config_str2list* acls_notify;
        /** use default localhost donotqueryaddr entries */
        int donotquery_localhost;
 
Index: util/data/msgreply.c
===================================================================
--- util/data/msgreply.c        (revision 1868)
+++ util/data/msgreply.c        (working copy)
@@ -498,7 +498,8 @@
        /* minimum size: header + \0 + qtype + qclass */
        if(ldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
                return 0;
-       if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY || 
+       if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && 
+               LDNS_OPCODE_WIRE(q) != LDNS_PACKET_NOTIFY) ||
                LDNS_QDCOUNT(q) != 1 || ldns_buffer_position(query) != 0)
                return 0;
        ldns_buffer_skip(query, LDNS_HEADER_SIZE);
Index: util/configlexer.lex
===================================================================
--- util/configlexer.lex        (revision 1868)
+++ util/configlexer.lex        (working copy)
@@ -184,6 +184,7 @@
 do-not-query-address{COLON}    { YDVAR(1, VAR_DO_NOT_QUERY_ADDRESS) }
 do-not-query-localhost{COLON}  { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) }
 access-control{COLON}          { YDVAR(2, VAR_ACCESS_CONTROL) }
+access-control-notify{COLON}   { YDVAR(2, VAR_ACCESS_CONTROL_NOTIFY) }
 hide-identity{COLON}           { YDVAR(1, VAR_HIDE_IDENTITY) }
 hide-version{COLON}            { YDVAR(1, VAR_HIDE_VERSION) }
 identity{COLON}                        { YDVAR(1, VAR_IDENTITY) }
_______________________________________________
Unbound-users mailing list
[email protected]
http://unbound.nlnetlabs.nl/mailman/listinfo/unbound-users

Reply via email to