s4 dns: Split up the code into multiple files for easier development
authorKai Blin <kai@samba.org>
Fri, 1 Oct 2010 19:59:22 +0000 (12:59 -0700)
committerKai Blin <kai@samba.org>
Sat, 23 Oct 2010 10:17:06 +0000 (10:17 +0000)
source4/dns_server/dns_query.c [new file with mode: 0644]
source4/dns_server/dns_server.c
source4/dns_server/dns_server.h
source4/dns_server/dns_update.c [new file with mode: 0644]
source4/dns_server/dns_utils.c [new file with mode: 0644]
source4/dns_server/wscript_build

diff --git a/source4/dns_server/dns_query.c b/source4/dns_server/dns_query.c
new file mode 100644 (file)
index 0000000..f8c39ff
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   DNS server handler for queries
+
+   Copyright (C) 2010 Kai Blin  <kai@samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/util/ntstatus.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_dns.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include <ldb.h>
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
+#include "dns_server/dns_server.h"
+
+static NTSTATUS handle_question(struct dns_server *dns,
+                               TALLOC_CTX *mem_ctx,
+                               const struct dns_name_question *question,
+                               struct dns_res_rec **answers, uint16_t *ancount)
+{
+       struct dns_res_rec *ans;
+       struct ldb_dn *dn = NULL;
+       NTSTATUS status;
+       static const char * const attrs[] = { "dnsRecord", NULL};
+       int ret;
+       uint16_t ai = *ancount;
+       uint16_t ri;
+       struct ldb_message *msg = NULL;
+       struct dnsp_DnssrvRpcRecord *recs;
+       struct ldb_message_element *el;
+
+       status = dns_name2dn(dns, mem_ctx, question->name, &dn);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn,
+                             LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)");
+       if (ret != LDB_SUCCESS) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       el = ldb_msg_find_element(msg, attrs[0]);
+       if (el == NULL) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values);
+       for (ri = 0; ri < el->num_values; ri++) {
+               struct ldb_val *v = &el->values[ri];
+               enum ndr_err_code ndr_err;
+
+               ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
+                               (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
+               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
+                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
+               }
+       }
+
+       ans = talloc_realloc(mem_ctx, *answers, struct dns_res_rec,
+                            ai + el->num_values);
+       NT_STATUS_HAVE_NO_MEMORY(ans);
+
+       switch (question->question_type) {
+       case DNS_QTYPE_CNAME:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = talloc_strdup(ans, question->name);
+                       ans[ai].rr_type = DNS_QTYPE_CNAME;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.cname_record = talloc_strdup(ans, recs[ri].data.cname);
+                       ai++;
+               }
+               break;
+       case DNS_QTYPE_A:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       /* TODO: if the record actually is a DNS_QTYPE_A */
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = talloc_strdup(ans, question->name);
+                       ans[ai].rr_type = DNS_QTYPE_A;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.ipv4_record = talloc_strdup(ans, recs[ri].data.ipv4);
+                       ai++;
+               }
+               break;
+       case DNS_QTYPE_AAAA:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = talloc_strdup(ans, question->name);
+                       ans[ai].rr_type = DNS_QTYPE_AAAA;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.ipv6_record = recs[ri].data.ipv6;
+                       ai++;
+               }
+               break;
+       case DNS_QTYPE_NS:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = question->name;
+                       ans[ai].rr_type = DNS_QTYPE_NS;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.ns_record = recs[ri].data.ns;
+                       ai++;
+               }
+               break;
+       case DNS_QTYPE_SRV:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = question->name;
+                       ans[ai].rr_type = DNS_QTYPE_SRV;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.srv_record.priority = recs[ri].data.srv.wPriority;
+                       ans[ai].rdata.srv_record.weight = recs[ri].data.srv.wWeight;
+                       ans[ai].rdata.srv_record.port = recs[ri].data.srv.wPort;
+                       ans[ai].rdata.srv_record.target = recs[ri].data.srv.nameTarget;
+                       ai++;
+               }
+               break;
+       case DNS_QTYPE_SOA:
+               for (ri = 0; ri < el->num_values; ri++) {
+                       if (recs[ri].wType != question->question_type) {
+                               continue;
+                       }
+
+                       ZERO_STRUCT(ans[ai]);
+                       ans[ai].name = question->name;
+                       ans[ai].rr_type = DNS_QTYPE_SOA;
+                       ans[ai].rr_class = DNS_QCLASS_IP;
+                       ans[ai].ttl = recs[ri].dwTtlSeconds;
+                       ans[ai].length = UINT16_MAX;
+                       ans[ai].rdata.soa_record.mname  = recs[ri].data.soa.mname;
+                       ans[ai].rdata.soa_record.rname  = recs[ri].data.soa.rname;
+                       ans[ai].rdata.soa_record.serial = recs[ri].data.soa.serial;
+                       ans[ai].rdata.soa_record.refresh= recs[ri].data.soa.refresh;
+                       ans[ai].rdata.soa_record.retry  = recs[ri].data.soa.retry;
+                       ans[ai].rdata.soa_record.expire = recs[ri].data.soa.expire;
+                       ans[ai].rdata.soa_record.minimum= recs[ri].data.soa.minimum;
+                       ai++;
+               }
+               break;
+       default:
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       if (*ancount == ai) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       *ancount = ai;
+       *answers = ans;
+
+       return NT_STATUS_OK;
+
+}
+
+NTSTATUS dns_server_process_query(struct dns_server *dns,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct dns_name_packet *in,
+                                 struct dns_res_rec **answers,    uint16_t *ancount,
+                                 struct dns_res_rec **nsrecs,     uint16_t *nscount,
+                                 struct dns_res_rec **additional, uint16_t *arcount)
+{
+       uint16_t num_answers=0;
+       struct dns_res_rec *ans=NULL;
+       int i;
+       NTSTATUS status;
+
+       ans = talloc_array(mem_ctx, struct dns_res_rec, 0);
+       if (answers == NULL) return NT_STATUS_NO_MEMORY;
+
+       for (i = 0; i < in->qdcount; ++i) {
+               status = handle_question(dns, mem_ctx, &in->questions[i], &ans, &num_answers);
+               NT_STATUS_NOT_OK_RETURN(status);
+       }
+
+       *answers = ans;
+       *ancount = num_answers;
+
+       /*FIXME: Do something for these */
+       *nsrecs  = NULL;
+       *nscount = 0;
+
+       *additional = NULL;
+       *arcount    = 0;
+
+       return NT_STATUS_OK;
+}
index 1c45691efc08911883d1d53f91239746f32403f5..e17ec2d8870d18af37f59e778c7f0e6e82bc24b6 100644 (file)
@@ -91,377 +91,6 @@ static void dns_tcp_send(struct stream_connection *conn, uint16_t flags)
        dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called");
 }
 
-static NTSTATUS dns_err_to_ntstatus(enum dns_rcode rcode)
-{
-       switch (rcode) {
-       case DNS_RCODE_OK: return NT_STATUS_OK;
-       case DNS_RCODE_FORMERR: return NT_STATUS_INVALID_PARAMETER;
-       case DNS_RCODE_SERVFAIL: return NT_STATUS_INTERNAL_ERROR;
-       case DNS_RCODE_NXDOMAIN: return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       case DNS_RCODE_NOTIMP: return NT_STATUS_NOT_IMPLEMENTED;
-       case DNS_RCODE_REFUSED: return NT_STATUS_ACCESS_DENIED;
-       case DNS_RCODE_NOTAUTH: return NT_STATUS_FOOBAR;
-       default: return NT_STATUS_NONE_MAPPED;
-       }
-}
-
-static uint8_t ntstatus_to_dns_err(NTSTATUS status)
-{
-       if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
-               return DNS_RCODE_OK;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_INVALID_PARAMETER, status)) {
-               return DNS_RCODE_FORMERR;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status)) {
-               return DNS_RCODE_SERVFAIL;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
-               return DNS_RCODE_NXDOMAIN;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
-               return DNS_RCODE_NOTIMP;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
-               return DNS_RCODE_REFUSED;
-       } else if (NT_STATUS_EQUAL(NT_STATUS_FOOBAR, status)) {
-               return DNS_RCODE_NOTAUTH;
-       }
-       DEBUG(0, ("No mapping exists for %s\n", nt_errstr(status)));
-}
-
-static bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
-{
-       size_t zl = strlen(zone);
-       size_t nl = strlen(name);
-       ssize_t zi, ni;
-       static const size_t fixup = 'a' - 'A';
-
-       if (zl > nl) {
-               return false;
-       }
-
-       for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
-               char zc = zone[zi];
-               char nc = name[ni];
-
-               /* convert to lower case */
-               if (zc >= 'A' && zc <= 'Z') {
-                       zc += fixup;
-               }
-               if (nc >= 'A' && nc <= 'Z') {
-                       nc += fixup;
-               }
-
-               if (zc != nc) {
-                       return false;
-               }
-       }
-
-       if (ni >= 0) {
-               if (name[ni] != '.') {
-                       return false;
-               }
-
-               ni--;
-       }
-
-       *host_part_len = ni+1;
-
-       return true;
-}
-
-static NTSTATUS dns_name2dn(struct dns_server *dns,
-                           TALLOC_CTX *mem_ctx,
-                           const char *name,
-                           struct ldb_dn **_dn)
-{
-       struct ldb_dn *base;
-       struct ldb_dn *dn;
-       const struct dns_server_zone *z;
-       size_t host_part_len = 0;
-
-       if (name == NULL) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       /*TODO: Check if 'name' is a valid DNS name */
-
-       if (strcmp(name, "") == 0) {
-               base = ldb_get_default_basedn(dns->samdb);
-               dn = ldb_dn_copy(mem_ctx, base);
-               ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
-               *_dn = dn;
-               return NT_STATUS_OK;
-       }
-
-       for (z = dns->zones; z != NULL; z = z->next) {
-               bool match;
-
-               match = dns_name_match(z->name, name, &host_part_len);
-               if (match) {
-                       break;
-               }
-       }
-
-       if (z == NULL) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       if (host_part_len == 0) {
-               dn = ldb_dn_copy(mem_ctx, z->dn);
-               ldb_dn_add_child_fmt(dn, "DC=@");
-               *_dn = dn;
-               return NT_STATUS_OK;
-       }
-
-       dn = ldb_dn_copy(mem_ctx, z->dn);
-       ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
-       *_dn = dn;
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS handle_question(struct dns_server *dns,
-                               TALLOC_CTX *mem_ctx,
-                               const struct dns_name_question *question,
-                               struct dns_res_rec **answers, uint16_t *ancount)
-{
-       struct dns_res_rec *ans;
-       struct ldb_dn *dn = NULL;
-       NTSTATUS status;
-       static const char * const attrs[] = { "dnsRecord", NULL};
-       int ret;
-       uint16_t ai = *ancount;
-       uint16_t ri;
-       struct ldb_message *msg = NULL;
-       struct dnsp_DnssrvRpcRecord *recs;
-       struct ldb_message_element *el;
-
-       status = dns_name2dn(dns, mem_ctx, question->name, &dn);
-       NT_STATUS_NOT_OK_RETURN(status);
-
-       ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn,
-                             LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)");
-       if (ret != LDB_SUCCESS) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       el = ldb_msg_find_element(msg, attrs[0]);
-       if (el == NULL) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values);
-       for (ri = 0; ri < el->num_values; ri++) {
-               struct ldb_val *v = &el->values[ri];
-               enum ndr_err_code ndr_err;
-
-               ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
-                               (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
-               if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
-                       DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-       }
-
-       ans = talloc_realloc(mem_ctx, *answers, struct dns_res_rec,
-                            ai + el->num_values);
-       NT_STATUS_HAVE_NO_MEMORY(ans);
-
-       switch (question->question_type) {
-       case DNS_QTYPE_CNAME:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = talloc_strdup(ans, question->name);
-                       ans[ai].rr_type = DNS_QTYPE_CNAME;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.cname_record = talloc_strdup(ans, recs[ri].data.cname);
-                       ai++;
-               }
-               break;
-       case DNS_QTYPE_A:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       /* TODO: if the record actually is a DNS_QTYPE_A */
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = talloc_strdup(ans, question->name);
-                       ans[ai].rr_type = DNS_QTYPE_A;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.ipv4_record = talloc_strdup(ans, recs[ri].data.ipv4);
-                       ai++;
-               }
-               break;
-       case DNS_QTYPE_AAAA:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = talloc_strdup(ans, question->name);
-                       ans[ai].rr_type = DNS_QTYPE_AAAA;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.ipv6_record = recs[ri].data.ipv6;
-                       ai++;
-               }
-               break;
-       case DNS_QTYPE_NS:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = question->name;
-                       ans[ai].rr_type = DNS_QTYPE_NS;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.ns_record = recs[ri].data.ns;
-                       ai++;
-               }
-               break;
-       case DNS_QTYPE_SRV:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = question->name;
-                       ans[ai].rr_type = DNS_QTYPE_SRV;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.srv_record.priority = recs[ri].data.srv.wPriority;
-                       ans[ai].rdata.srv_record.weight = recs[ri].data.srv.wWeight;
-                       ans[ai].rdata.srv_record.port = recs[ri].data.srv.wPort;
-                       ans[ai].rdata.srv_record.target = recs[ri].data.srv.nameTarget;
-                       ai++;
-               }
-               break;
-       case DNS_QTYPE_SOA:
-               for (ri = 0; ri < el->num_values; ri++) {
-                       if (recs[ri].wType != question->question_type) {
-                               continue;
-                       }
-
-                       ZERO_STRUCT(ans[ai]);
-                       ans[ai].name = question->name;
-                       ans[ai].rr_type = DNS_QTYPE_SOA;
-                       ans[ai].rr_class = DNS_QCLASS_IP;
-                       ans[ai].ttl = recs[ri].dwTtlSeconds;
-                       ans[ai].length = UINT16_MAX;
-                       ans[ai].rdata.soa_record.mname  = recs[ri].data.soa.mname;
-                       ans[ai].rdata.soa_record.rname  = recs[ri].data.soa.rname;
-                       ans[ai].rdata.soa_record.serial = recs[ri].data.soa.serial;
-                       ans[ai].rdata.soa_record.refresh= recs[ri].data.soa.refresh;
-                       ans[ai].rdata.soa_record.retry  = recs[ri].data.soa.retry;
-                       ans[ai].rdata.soa_record.expire = recs[ri].data.soa.expire;
-                       ans[ai].rdata.soa_record.minimum= recs[ri].data.soa.minimum;
-                       ai++;
-               }
-               break;
-       default:
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       if (*ancount == ai) {
-               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
-       }
-
-       *ancount = ai;
-       *answers = ans;
-
-       return NT_STATUS_OK;
-
-}
-
-static NTSTATUS dns_server_process_query(struct dns_server *dns,
-                                        TALLOC_CTX *mem_ctx,
-                                        struct dns_name_packet *in,
-                                        struct dns_res_rec **answers,    uint16_t *ancount,
-                                        struct dns_res_rec **nsrecs,     uint16_t *nscount,
-                                        struct dns_res_rec **additional, uint16_t *arcount)
-{
-       uint16_t num_answers=0;
-       struct dns_res_rec *ans=NULL;
-       int i;
-       NTSTATUS status;
-
-       ans = talloc_array(mem_ctx, struct dns_res_rec, 0);
-       if (answers == NULL) return NT_STATUS_NO_MEMORY;
-
-       for (i = 0; i < in->qdcount; ++i) {
-               status = handle_question(dns, mem_ctx, &in->questions[i], &ans, &num_answers);
-               NT_STATUS_NOT_OK_RETURN(status);
-       }
-
-       *answers = ans;
-       *ancount = num_answers;
-
-       /*FIXME: Do something for these */
-       *nsrecs  = NULL;
-       *nscount = 0;
-
-       *additional = NULL;
-       *arcount    = 0;
-
-       return NT_STATUS_OK;
-}
-
-static NTSTATUS dns_server_process_update(struct dns_server *dns,
-                                         TALLOC_CTX *mem_ctx,
-                                         struct dns_name_packet *in,
-                                         struct dns_res_rec **prereqs,    uint16_t *prereq_count,
-                                         struct dns_res_rec **updates,    uint16_t *update_count,
-                                         struct dns_res_rec **additional, uint16_t *arcount)
-{
-       struct dns_name_question *zone;
-       const struct dns_server_zone *z;
-       size_t host_part_len = 0;
-
-       if (in->qdcount != 1) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       zone = in->questions;
-
-       if (zone->question_type != DNS_QTYPE_SOA) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       DEBUG(0, ("Got a dns update request.\n"));
-
-       for (z = dns->zones; z != NULL; z = z->next) {
-               bool match;
-
-               match = dns_name_match(z->name, zone->name, &host_part_len);
-               if (match) {
-                       break;
-               }
-       }
-
-       if (z == NULL) {
-               return NT_STATUS_FOOBAR;
-       }
-
-       if (host_part_len != 0) {
-               return NT_STATUS_NOT_IMPLEMENTED;
-       }
-
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 static NTSTATUS dns_process(struct dns_server *dns,
                            TALLOC_CTX *mem_ctx,
                            DATA_BLOB *in,
index 0377a2cc8639c240f3afffe65808c1a71afb0ed0..ee3f88446059b62134e6099acafb4176d66017c4 100644 (file)
@@ -38,4 +38,27 @@ struct dns_server {
        struct dns_server_zone *zones;
 };
 
+
+NTSTATUS dns_server_process_query(struct dns_server *dns,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct dns_name_packet *in,
+                                 struct dns_res_rec **answers,    uint16_t *ancount,
+                                 struct dns_res_rec **nsrecs,     uint16_t *nscount,
+                                 struct dns_res_rec **additional, uint16_t *arcount);
+
+NTSTATUS dns_server_process_update(struct dns_server *dns,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct dns_name_packet *in,
+                                  struct dns_res_rec **prereqs,    uint16_t *prereq_count,
+                                  struct dns_res_rec **updates,    uint16_t *update_count,
+                                  struct dns_res_rec **additional, uint16_t *arcount);
+
+NTSTATUS dns_err_to_ntstatus(enum dns_rcode rcode);
+uint8_t ntstatus_to_dns_err(NTSTATUS status);
+bool dns_name_match(const char *zone, const char *name, size_t *host_part_len);
+NTSTATUS dns_name2dn(struct dns_server *dns,
+                    TALLOC_CTX *mem_ctx,
+                    const char *name,
+                    struct ldb_dn **_dn);
+
 #endif /* __DNS_SERVER_H__ */
diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c
new file mode 100644 (file)
index 0000000..d243736
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   DNS server handler for update requests
+
+   Copyright (C) 2010 Kai Blin  <kai@samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/util/ntstatus.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_dns.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include <ldb.h>
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
+#include "dns_server/dns_server.h"
+
+NTSTATUS dns_server_process_update(struct dns_server *dns,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct dns_name_packet *in,
+                                  struct dns_res_rec **prereqs,    uint16_t *prereq_count,
+                                  struct dns_res_rec **updates,    uint16_t *update_count,
+                                  struct dns_res_rec **additional, uint16_t *arcount)
+{
+       struct dns_name_question *zone;
+       NTSTATUS status;
+       const struct dns_server_zone *z;
+       size_t host_part_len = 0;
+
+       if (in->qdcount != 1) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       zone = in->questions;
+
+       if (zone->question_type != DNS_QTYPE_SOA) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       DEBUG(0, ("Got a dns update request.\n"));
+
+       for (z = dns->zones; z != NULL; z = z->next) {
+               bool match;
+
+               match = dns_name_match(z->name, zone->name, &host_part_len);
+               if (match) {
+                       break;
+               }
+       }
+
+       if (z == NULL) {
+               return NT_STATUS_FOOBAR;
+       }
+
+       if (host_part_len != 0) {
+               return NT_STATUS_NOT_IMPLEMENTED;
+       }
+
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
diff --git a/source4/dns_server/dns_utils.c b/source4/dns_server/dns_utils.c
new file mode 100644 (file)
index 0000000..2c86f0d
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   DNS server utils
+
+   Copyright (C) 2010 Kai Blin  <kai@samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/util/ntstatus.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_dns.h"
+#include "librpc/gen_ndr/ndr_dnsp.h"
+#include <ldb.h>
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/common/util.h"
+#include "dns_server/dns_server.h"
+
+NTSTATUS dns_err_to_ntstatus(enum dns_rcode rcode)
+{
+       switch (rcode) {
+       case DNS_RCODE_OK: return NT_STATUS_OK;
+       case DNS_RCODE_FORMERR: return NT_STATUS_INVALID_PARAMETER;
+       case DNS_RCODE_SERVFAIL: return NT_STATUS_INTERNAL_ERROR;
+       case DNS_RCODE_NXDOMAIN: return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       case DNS_RCODE_NOTIMP: return NT_STATUS_NOT_IMPLEMENTED;
+       case DNS_RCODE_REFUSED: return NT_STATUS_ACCESS_DENIED;
+       case DNS_RCODE_NOTAUTH: return NT_STATUS_FOOBAR;
+       default: return NT_STATUS_NONE_MAPPED;
+       }
+}
+
+uint8_t ntstatus_to_dns_err(NTSTATUS status)
+{
+       if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
+               return DNS_RCODE_OK;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_INVALID_PARAMETER, status)) {
+               return DNS_RCODE_FORMERR;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status)) {
+               return DNS_RCODE_SERVFAIL;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
+               return DNS_RCODE_NXDOMAIN;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
+               return DNS_RCODE_NOTIMP;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
+               return DNS_RCODE_REFUSED;
+       } else if (NT_STATUS_EQUAL(NT_STATUS_FOOBAR, status)) {
+               return DNS_RCODE_NOTAUTH;
+       }
+       DEBUG(0, ("No mapping exists for %s\n", nt_errstr(status)));
+       return DNS_RCODE_NOTIMP;
+}
+
+bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
+{
+       size_t zl = strlen(zone);
+       size_t nl = strlen(name);
+       ssize_t zi, ni;
+       static const size_t fixup = 'a' - 'A';
+
+       if (zl > nl) {
+               return false;
+       }
+
+       for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
+               char zc = zone[zi];
+               char nc = name[ni];
+
+               /* convert to lower case */
+               if (zc >= 'A' && zc <= 'Z') {
+                       zc += fixup;
+               }
+               if (nc >= 'A' && nc <= 'Z') {
+                       nc += fixup;
+               }
+
+               if (zc != nc) {
+                       return false;
+               }
+       }
+
+       if (ni >= 0) {
+               if (name[ni] != '.') {
+                       return false;
+               }
+
+               ni--;
+       }
+
+       *host_part_len = ni+1;
+
+       return true;
+}
+
+NTSTATUS dns_name2dn(struct dns_server *dns,
+                    TALLOC_CTX *mem_ctx,
+                    const char *name,
+                    struct ldb_dn **_dn)
+{
+       struct ldb_dn *base;
+       struct ldb_dn *dn;
+       const struct dns_server_zone *z;
+       size_t host_part_len = 0;
+
+       if (name == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /*TODO: Check if 'name' is a valid DNS name */
+
+       if (strcmp(name, "") == 0) {
+               base = ldb_get_default_basedn(dns->samdb);
+               dn = ldb_dn_copy(mem_ctx, base);
+               ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
+               *_dn = dn;
+               return NT_STATUS_OK;
+       }
+
+       for (z = dns->zones; z != NULL; z = z->next) {
+               bool match;
+
+               match = dns_name_match(z->name, name, &host_part_len);
+               if (match) {
+                       break;
+               }
+       }
+
+       if (z == NULL) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (host_part_len == 0) {
+               dn = ldb_dn_copy(mem_ctx, z->dn);
+               ldb_dn_add_child_fmt(dn, "DC=@");
+               *_dn = dn;
+               return NT_STATUS_OK;
+       }
+
+       dn = ldb_dn_copy(mem_ctx, z->dn);
+       ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
+       *_dn = dn;
+       return NT_STATUS_OK;
+}
index 26ef7ddf1ef91a7f02bde3f92c189a291e09a889..5191480d6b69377607dcc5fa14a3296d017d16ec 100644 (file)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 
 bld.SAMBA_MODULE('DNS',
-        source='dns_server.c',
+        source='dns_server.c dns_query.c dns_update.c dns_utils.c',
         subsystem='service',
         init_function='server_service_dns_init',
         deps='LIBSAMBA-HOSTCONFIG LIBTSOCKET LIBSAMBA_TSOCKET',