dns: Support larger queries when asking forwarder
authorKai Blin <kai@samba.org>
Sat, 25 May 2013 11:21:33 +0000 (13:21 +0200)
committerMichael Adam <obnox@samba.org>
Sun, 26 May 2013 16:13:28 +0000 (18:13 +0200)
This should fix bug #9632

Signed-off-by: Kai Blin <kai@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
source4/dns_server/dns_query.c
source4/dns_server/dns_server.c
source4/dns_server/dns_server.h
source4/dns_server/dns_utils.c

index 4ad14b9a558810e07f2590d66df762fc5545ecd8..5414e1d9ee40adec7c944620a5d081da0308efa1 100644 (file)
@@ -138,14 +138,17 @@ struct ask_forwarder_state {
 static void ask_forwarder_done(struct tevent_req *subreq);
 
 static struct tevent_req *ask_forwarder_send(
+       struct dns_server *dns,
        TALLOC_CTX *mem_ctx, struct tevent_context *ev,
        const char *forwarder, struct dns_name_question *question)
 {
        struct tevent_req *req, *subreq;
        struct ask_forwarder_state *state;
+       struct dns_res_rec *options;
        struct dns_name_packet out_packet = { 0, };
        DATA_BLOB out_blob;
        enum ndr_err_code ndr_err;
+       WERROR werr;
 
        req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state);
        if (req == NULL) {
@@ -166,6 +169,15 @@ static struct tevent_req *ask_forwarder_send(
        out_packet.qdcount = 1;
        out_packet.questions = question;
 
+       werr = dns_generate_options(dns, state, &options);
+       if (!W_ERROR_IS_OK(werr)) {
+               tevent_req_werror(req, werr);
+               return tevent_req_post(req, ev);
+       }
+
+       out_packet.arcount = 1;
+       out_packet.additional = options;
+
        ndr_err = ndr_push_struct_blob(
                &out_blob, state, &out_packet,
                (ndr_push_flags_fn_t)ndr_push_dns_name_packet);
@@ -615,6 +627,7 @@ struct tevent_req *dns_server_process_query_send(
                          in->questions[0].name));
 
                subreq = ask_forwarder_send(
+                       dns,
                        state, ev, lpcfg_dns_forwarder(dns->task->lp_ctx),
                        &in->questions[0]);
                if (tevent_req_nomem(subreq, req)) {
index bb4605f56ac44ce03a127607b56a32c6ab80ab8c..7ad4acae7a15579bef231b353169dbc617a6e010 100644 (file)
@@ -791,6 +791,8 @@ static void dns_task_init(struct task_server *task)
        }
 
        dns->task = task;
+       /*FIXME: Make this a configurable option */
+       dns->max_payload = 4096;
 
        dns->server_credentials = cli_credentials_init(dns);
        if (!dns->server_credentials) {
index ef85730ff833af41d292abdb0afea85e9e18746e..efe4db822fc638e342615f9371265865ae4821f9 100644 (file)
@@ -56,6 +56,7 @@ struct dns_server {
        struct dns_server_zone *zones;
        struct dns_server_tkey_store *tkeys;
        struct cli_credentials *server_credentials;
+       uint16_t max_payload;
 };
 
 struct dns_request_state {
@@ -107,6 +108,9 @@ WERROR dns_name2dn(struct dns_server *dns,
                   TALLOC_CTX *mem_ctx,
                   const char *name,
                   struct ldb_dn **_dn);
+WERROR dns_generate_options(struct dns_server *dns,
+                           TALLOC_CTX *mem_ctx,
+                           struct dns_res_rec **options);
 struct dns_server_tkey *dns_find_tkey(struct dns_server_tkey_store *store,
                                      const char *name);
 WERROR dns_verify_tsig(struct dns_server *dns,
index e03a4097513114530601be244f1d4f110fbbda45..21c7f5a6808bd214208fa1e278e36384bfdc58ec 100644 (file)
@@ -378,3 +378,24 @@ WERROR dns_name2dn(struct dns_server *dns,
        *_dn = dn;
        return WERR_OK;
 }
+
+WERROR dns_generate_options(struct dns_server *dns,
+                           TALLOC_CTX *mem_ctx,
+                           struct dns_res_rec **options)
+{
+       struct dns_res_rec *o;
+
+       o = talloc_zero(mem_ctx, struct dns_res_rec);
+       if (o == NULL) {
+               return WERR_NOMEM;
+       }
+       o->name = '\0';
+       o->rr_type = DNS_QTYPE_OPT;
+       /* This is ugly, but RFC2671 wants the payload size in this field */
+       o->rr_class = (enum dns_qclass) dns->max_payload;
+       o->ttl = 0;
+       o->length = 0;
+
+       *options = o;
+       return WERR_OK;
+}