s4 dns: Look up records in the ldb database
[sfrench/samba-autobuild/.git] / source4 / dns_server / dns_server.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DNS server startup
5
6    Copyright (C) 2010 Kai Blin  <kai@samba.org>
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/service_task.h"
24 #include "smbd/service.h"
25 #include "smbd/service_stream.h"
26 #include "smbd/process_model.h"
27 #include "lib/events/events.h"
28 #include "lib/socket/socket.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "libcli/util/tstream.h"
31 #include "libcli/util/ntstatus.h"
32 #include "system/network.h"
33 #include "lib/stream/packet.h"
34 #include "lib/socket/netif.h"
35 #include "dns_server/dns_server.h"
36 #include "param/param.h"
37 #include "librpc/ndr/libndr.h"
38 #include "librpc/gen_ndr/ndr_dns.h"
39 #include "librpc/gen_ndr/ndr_dnsp.h"
40 #include <ldb.h>
41 #include "dsdb/samdb/samdb.h"
42 #include "auth/session.h"
43
44 /* hold information about one dns socket */
45 struct dns_socket {
46         struct dns_server *dns;
47         struct tsocket_address *local_address;
48 };
49
50 struct dns_udp_socket {
51         struct dns_socket *dns_socket;
52         struct tdgram_context *dgram;
53         struct tevent_queue *send_queue;
54 };
55
56 /*
57   state of an open tcp connection
58 */
59 struct dns_tcp_connection {
60         /* stream connection we belong to */
61         struct stream_connection *conn;
62
63         /* the dns_server the connection belongs to */
64         struct dns_socket *dns_socket;
65
66         struct tstream_context *tstream;
67
68         struct tevent_queue *send_queue;
69 };
70
71 static void dns_tcp_terminate_connection(struct dns_tcp_connection *dnsconn, const char *reason)
72 {
73         stream_terminate_connection(dnsconn->conn, reason);
74 }
75
76 static void dns_tcp_recv(struct stream_connection *conn, uint16_t flags)
77 {
78         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
79                                                              struct dns_tcp_connection);
80         /* this should never be triggered! */
81         dns_tcp_terminate_connection(dnsconn, "dns_tcp_recv: called");
82 }
83
84 static void dns_tcp_send(struct stream_connection *conn, uint16_t flags)
85 {
86         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
87                                                              struct dns_tcp_connection);
88         /* this should never be triggered! */
89         dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called");
90 }
91
92 static NTSTATUS dns_name2dn(struct dns_server *dns,
93                             TALLOC_CTX *mem_ctx,
94                             const char *name,
95                             struct ldb_dn **_dn)
96 {
97         struct ldb_dn *base;
98         struct ldb_dn *dn;
99         const char *p;
100
101         if (name == NULL) {
102                 return NT_STATUS_INVALID_PARAMETER;
103         }
104
105         /*TODO: Check if 'name' is a valid DNS name */
106
107         if (strcmp(name, "") == 0) {
108                 base = ldb_get_default_basedn(dns->samdb);
109                 dn = ldb_dn_copy(mem_ctx, base);
110                 ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
111                 *_dn = dn;
112                 return NT_STATUS_OK;
113         }
114
115         p = strcasestr(name, "root-servers.net");
116         if (p != NULL) {
117                 base = ldb_get_default_basedn(dns->samdb);
118                 dn = ldb_dn_copy(mem_ctx, base);
119                 ldb_dn_add_child_fmt(dn, "DC=%s,DC=RootDNSServers,CN=MicrosoftDNS,CN=System", name);
120                 *_dn = dn;
121                 return NT_STATUS_OK;
122         }
123
124         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
125 }
126
127 static NTSTATUS handle_question(struct dns_server *dns,
128                                 TALLOC_CTX *mem_ctx,
129                                 const struct dns_name_question *question,
130                                 struct dns_res_rec **answers, uint16_t *ancount)
131 {
132         struct dns_res_rec *ans;
133         struct ldb_dn *dn = NULL;
134         NTSTATUS status;
135         static const char * const attrs[] = { "dnsRecord", NULL};
136         int ret;
137         uint16_t ai = *ancount;
138         uint16_t ri;
139         struct ldb_message *msg = NULL;
140         struct dnsp_DnssrvRpcRecord *recs;
141         struct ldb_message_element *el;
142
143         status = dns_name2dn(dns, mem_ctx, question->name, &dn);
144         NT_STATUS_NOT_OK_RETURN(status);
145
146         ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn,
147                               LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)");
148         if (ret != LDB_SUCCESS) {
149                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
150         }
151
152         el = ldb_msg_find_element(msg, attrs[0]);
153         if (el == NULL) {
154                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
155         }
156
157         recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values);
158         for (ri = 0; ri < el->num_values; ri++) {
159                 struct ldb_val *v = &el->values[ri];
160                 enum ndr_err_code ndr_err;
161
162                 ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
163                                 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
164                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
165                         DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
166                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
167                 }
168         }
169
170         ans = talloc_realloc(mem_ctx, *answers, struct dns_res_rec,
171                              ai + el->num_values);
172         NT_STATUS_HAVE_NO_MEMORY(ans);
173
174         switch (question->question_type) {
175         case DNS_QTYPE_A:
176                 for (ri = 0; ri < el->num_values; ri++) {
177                         if (recs[ri].wType != question->question_type) {
178                                 continue;
179                         }
180
181                         ZERO_STRUCT(ans[ai]);
182                         ans[ai].name = talloc_strdup(ans, question->name);
183                         ans[ai].rr_type = DNS_QTYPE_A;
184                         ans[ai].rr_class = DNS_QCLASS_IP;
185                         ans[ai].ttl = recs[ri].dwTtlSeconds;
186                         ans[ai].rdata.ipv4_record = talloc_strdup(ans, recs[ri].data.ipv4);
187                         ai++;
188                 }
189                 break;
190         case DNS_QTYPE_AAAA:
191                 for (ri = 0; ri < el->num_values; ri++) {
192                         if (recs[ri].wType != question->question_type) {
193                                 continue;
194                         }
195
196                         ZERO_STRUCT(ans[ai]);
197                         ans[ai].name = talloc_strdup(ans, question->name);
198                         ans[ai].rr_type = DNS_QTYPE_AAAA;
199                         ans[ai].rr_class = DNS_QCLASS_IP;
200                         ans[ai].ttl = recs[ri].dwTtlSeconds;
201                         ans[ai].rdata.ipv6_record = recs[ri].data.ipv6;
202                         ai++;
203                 }
204                 break;
205         case DNS_QTYPE_NS:
206                 for (ri = 0; ri < el->num_values; ri++) {
207                         if (recs[ri].wType != question->question_type) {
208                                 continue;
209                         }
210
211                         ZERO_STRUCT(ans[ai]);
212                         ans[ai].name = question->name;
213                         ans[ai].rr_type = DNS_QTYPE_NS;
214                         ans[ai].rr_class = DNS_QCLASS_IP;
215                         ans[ai].ttl = recs[ri].dwTtlSeconds;
216                         ans[ai].rdata.ns_record = recs[ri].data.ns;
217                         ai++;
218                 }
219                 break;
220         default:
221                 return NT_STATUS_NOT_IMPLEMENTED;
222         }
223
224         *ancount = ai;
225         *answers = ans;
226
227         return NT_STATUS_OK;
228
229 }
230
231 static NTSTATUS compute_reply(struct dns_server *dns,
232                               TALLOC_CTX *mem_ctx,
233                               struct dns_name_packet *in,
234                               struct dns_res_rec **answers,    uint16_t *ancount,
235                               struct dns_res_rec **nsrecs,     uint16_t *nscount,
236                               struct dns_res_rec **additional, uint16_t *arcount)
237 {
238         uint16_t num_answers=0;
239         struct dns_res_rec *ans=NULL;
240         int i;
241         NTSTATUS status;
242
243         ans = talloc_array(mem_ctx, struct dns_res_rec, 0);
244         if (answers == NULL) return NT_STATUS_NO_MEMORY;
245
246         for (i = 0; i < in->qdcount; ++i) {
247                 status = handle_question(dns, mem_ctx, &in->questions[i], &ans, &num_answers);
248                 NT_STATUS_NOT_OK_RETURN(status);
249         }
250
251         *answers = ans;
252         *ancount = num_answers;
253
254         /*FIXME: Do something for these */
255         *nsrecs  = NULL;
256         *nscount = 0;
257
258         *additional = NULL;
259         *arcount    = 0;
260
261         return NT_STATUS_OK;
262 }
263
264 static NTSTATUS dns_process(struct dns_server *dns,
265                             TALLOC_CTX *mem_ctx,
266                             DATA_BLOB *in,
267                             DATA_BLOB *out)
268 {
269         enum ndr_err_code ndr_err;
270         NTSTATUS ret;
271         struct dns_name_packet *in_packet = talloc_zero(mem_ctx, struct dns_name_packet);
272         struct dns_name_packet *out_packet = talloc_zero(mem_ctx, struct dns_name_packet);
273         struct dns_res_rec *answers, *nsrecs, *additional;
274         uint16_t num_answers, num_nsrecs, num_additional;
275
276         if (in_packet == NULL) return NT_STATUS_INVALID_PARAMETER;
277
278         dump_data(2, in->data, in->length);
279
280         ndr_err = ndr_pull_struct_blob(in, in_packet, in_packet,
281                         (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
282         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
283                 TALLOC_FREE(in_packet);
284                 DEBUG(0, ("Failed to parse packet %d!\n", ndr_err));
285                 return NT_STATUS_COULD_NOT_INTERPRET;
286         }
287
288         NDR_PRINT_DEBUG(dns_name_packet, in_packet);
289         out_packet->id = in_packet->id;
290         out_packet->operation = DNS_FLAG_REPLY | DNS_FLAG_AUTHORITATIVE |
291                                 DNS_FLAG_RECURSION_DESIRED | DNS_FLAG_RECURSION_AVAIL;
292
293         out_packet->qdcount = in_packet->qdcount;
294         out_packet->questions = in_packet->questions;
295
296         out_packet->ancount = 0;
297         out_packet->answers = NULL;
298
299         out_packet->nscount = 0;
300         out_packet->nsrecs  = NULL;
301
302         out_packet->arcount = 0;
303         out_packet->additional = NULL;
304
305         ret = compute_reply(dns, out_packet, in_packet, &answers, &num_answers,
306                             &nsrecs, &num_nsrecs, &additional, &num_additional);
307
308         if (NT_STATUS_IS_OK(ret)) {
309                 out_packet->ancount = num_answers;
310                 out_packet->answers = answers;
311
312                 out_packet->nscount = num_nsrecs;
313                 out_packet->nsrecs  = nsrecs;
314
315                 out_packet->arcount = num_additional;
316                 out_packet->additional = additional;
317         }
318
319         NDR_PRINT_DEBUG(dns_name_packet, out_packet);
320         ndr_err = ndr_push_struct_blob(out, out_packet, out_packet,
321                         (ndr_push_flags_fn_t)ndr_push_dns_name_packet);
322         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
323                 TALLOC_FREE(in_packet);
324                 TALLOC_FREE(out_packet);
325                 DEBUG(0, ("Failed to push packet %d!\n", ndr_err));
326                 return NT_STATUS_INTERNAL_ERROR;
327         }
328
329         dump_data(2, out->data, out->length);
330         return NT_STATUS_OK;
331 }
332
333 struct dns_tcp_call {
334         struct dns_tcp_connection *dns_conn;
335         DATA_BLOB in;
336         DATA_BLOB out;
337         uint8_t out_hdr[4];
338         struct iovec out_iov[2];
339 };
340
341 static void dns_tcp_call_writev_done(struct tevent_req *subreq);
342
343 static void dns_tcp_call_loop(struct tevent_req *subreq)
344 {
345         struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq,
346                                       struct dns_tcp_connection);
347         struct dns_tcp_call *call;
348         NTSTATUS status;
349
350         call = talloc(dns_conn, struct dns_tcp_call);
351         if (call == NULL) {
352                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
353                                 "no memory for dns_tcp_call");
354                 return;
355         }
356         call->dns_conn = dns_conn;
357
358         status = tstream_read_pdu_blob_recv(subreq,
359                                             call,
360                                             &call->in);
361         TALLOC_FREE(subreq);
362         if (!NT_STATUS_IS_OK(status)) {
363                 const char *reason;
364
365                 reason = talloc_asprintf(call, "dns_tcp_call_loop: "
366                                          "tstream_read_pdu_blob_recv() - %s",
367                                          nt_errstr(status));
368                 if (!reason) {
369                         reason = nt_errstr(status);
370                 }
371
372                 dns_tcp_terminate_connection(dns_conn, reason);
373                 return;
374         }
375
376         DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
377                  (long) call->in.length,
378                  tsocket_address_string(dns_conn->conn->remote_address, call)));
379
380         /* skip length header */
381         call->in.data +=4;
382         call->in.length -= 4;
383
384         /* Call dns */
385         status = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out);
386         if (!NT_STATUS_IS_OK(status)) {
387                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
388                 dns_tcp_terminate_connection(dns_conn,
389                                 "dns_tcp_call_loop: process function failed");
390                 return;
391         }
392
393         /* First add the length of the out buffer */
394         RSIVAL(call->out_hdr, 0, call->out.length);
395         call->out_iov[0].iov_base = (char *) call->out_hdr;
396         call->out_iov[0].iov_len = 4;
397
398         call->out_iov[1].iov_base = (char *) call->out.data;
399         call->out_iov[1].iov_len = call->out.length;
400
401         subreq = tstream_writev_queue_send(call,
402                                            dns_conn->conn->event.ctx,
403                                            dns_conn->tstream,
404                                            dns_conn->send_queue,
405                                            call->out_iov, 2);
406         if (subreq == NULL) {
407                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
408                                 "no memory for tstream_writev_queue_send");
409                 return;
410         }
411         tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call);
412
413         /*
414          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
415          * packet_full_request_u32 provides the pdu length then.
416          */
417         subreq = tstream_read_pdu_blob_send(dns_conn,
418                                             dns_conn->conn->event.ctx,
419                                             dns_conn->tstream,
420                                             4, /* initial_read_size */
421                                             packet_full_request_u32,
422                                             dns_conn);
423         if (subreq == NULL) {
424                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
425                                 "no memory for tstream_read_pdu_blob_send");
426                 return;
427         }
428         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
429 }
430
431 static void dns_tcp_call_writev_done(struct tevent_req *subreq)
432 {
433         struct dns_tcp_call *call = tevent_req_callback_data(subreq,
434                         struct dns_tcp_call);
435         int sys_errno;
436         int rc;
437
438         rc = tstream_writev_queue_recv(subreq, &sys_errno);
439         TALLOC_FREE(subreq);
440         if (rc == -1) {
441                 const char *reason;
442
443                 reason = talloc_asprintf(call, "dns_tcp_call_writev_done: "
444                                          "tstream_writev_queue_recv() - %d:%s",
445                                          sys_errno, strerror(sys_errno));
446                 if (!reason) {
447                         reason = "dns_tcp_call_writev_done: tstream_writev_queue_recv() failed";
448                 }
449
450                 dns_tcp_terminate_connection(call->dns_conn, reason);
451                 return;
452         }
453
454         /* We don't care about errors */
455
456         talloc_free(call);
457 }
458
459 /*
460   called when we get a new connection
461 */
462 static void dns_tcp_accept(struct stream_connection *conn)
463 {
464         struct dns_socket *dns_socket;
465         struct dns_tcp_connection *dns_conn;
466         struct tevent_req *subreq;
467         int rc;
468
469         dns_conn = talloc_zero(conn, struct dns_tcp_connection);
470         if (dns_conn == NULL) {
471                 stream_terminate_connection(conn,
472                                 "dns_tcp_accept: out of memory");
473                 return;
474         }
475
476         dns_conn->send_queue = tevent_queue_create(conn, "dns_tcp_accept");
477         if (dns_conn->send_queue == NULL) {
478                 stream_terminate_connection(conn,
479                                 "dns_tcp_accept: out of memory");
480                 return;
481         }
482
483         dns_socket = talloc_get_type(conn->private_data, struct dns_socket);
484
485         TALLOC_FREE(conn->event.fde);
486
487         rc = tstream_bsd_existing_socket(dns_conn,
488                         socket_get_fd(conn->socket),
489                         &dns_conn->tstream);
490         if (rc < 0) {
491                 stream_terminate_connection(conn,
492                                 "dns_tcp_accept: out of memory");
493                 return;
494         }
495
496         dns_conn->conn = conn;
497         dns_conn->dns_socket = dns_socket;
498         conn->private_data = dns_conn;
499
500         /*
501          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
502          * packet_full_request_u32 provides the pdu length then.
503          */
504         subreq = tstream_read_pdu_blob_send(dns_conn,
505                                             dns_conn->conn->event.ctx,
506                                             dns_conn->tstream,
507                                             4, /* initial_read_size */
508                                             packet_full_request_u32,
509                                             dns_conn);
510         if (subreq == NULL) {
511                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_accept: "
512                                 "no memory for tstream_read_pdu_blob_send");
513                 return;
514         }
515         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
516 }
517
518 static const struct stream_server_ops dns_tcp_stream_ops = {
519         .name                   = "dns_tcp",
520         .accept_connection      = dns_tcp_accept,
521         .recv_handler           = dns_tcp_recv,
522         .send_handler           = dns_tcp_send
523 };
524
525 struct dns_udp_call {
526         struct tsocket_address *src;
527         DATA_BLOB in;
528         DATA_BLOB out;
529 };
530
531 static void dns_udp_call_sendto_done(struct tevent_req *subreq);
532
533 static void dns_udp_call_loop(struct tevent_req *subreq)
534 {
535         struct dns_udp_socket *sock = tevent_req_callback_data(subreq,
536                                       struct dns_udp_socket);
537         struct dns_udp_call *call;
538         uint8_t *buf;
539         ssize_t len;
540         int sys_errno;
541         NTSTATUS status;
542
543         call = talloc(sock, struct dns_udp_call);
544         if (call == NULL) {
545                 talloc_free(call);
546                 goto done;
547         }
548
549         len = tdgram_recvfrom_recv(subreq, &sys_errno,
550                                    call, &buf, &call->src);
551         TALLOC_FREE(subreq);
552         if (len == -1) {
553                 talloc_free(call);
554                 goto done;
555         }
556
557         call->in.data = buf;
558         call->in.length = len;
559
560         DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
561                  (long)call->in.length,
562                  tsocket_address_string(call->src, call)));
563
564         /* Call krb5 */
565         status = dns_process(sock->dns_socket->dns, call, &call->in, &call->out);
566         if (!NT_STATUS_IS_OK(status)) {
567                 talloc_free(call);
568                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
569                 goto done;
570         }
571
572         subreq = tdgram_sendto_queue_send(call,
573                                           sock->dns_socket->dns->task->event_ctx,
574                                           sock->dgram,
575                                           sock->send_queue,
576                                           call->out.data,
577                                           call->out.length,
578                                           call->src);
579         if (subreq == NULL) {
580                 talloc_free(call);
581                 goto done;
582         }
583         tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call);
584
585 done:
586         subreq = tdgram_recvfrom_send(sock,
587                                       sock->dns_socket->dns->task->event_ctx,
588                                       sock->dgram);
589         if (subreq == NULL) {
590                 task_server_terminate(sock->dns_socket->dns->task,
591                                       "no memory for tdgram_recvfrom_send",
592                                       true);
593                 return;
594         }
595         tevent_req_set_callback(subreq, dns_udp_call_loop, sock);
596 }
597
598 static void dns_udp_call_sendto_done(struct tevent_req *subreq)
599 {
600         struct dns_udp_call *call = tevent_req_callback_data(subreq,
601                                        struct dns_udp_call);
602         ssize_t ret;
603         int sys_errno;
604
605         ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
606
607         /* We don't care about errors */
608
609         talloc_free(call);
610 }
611
612 /*
613   start listening on the given address
614 */
615 static NTSTATUS dns_add_socket(struct dns_server *dns,
616                                const struct model_ops *model_ops,
617                                const char *name,
618                                const char *address,
619                                uint16_t port)
620 {
621         struct dns_socket *dns_socket;
622         struct dns_udp_socket *dns_udp_socket;
623         struct tevent_req *udpsubreq;
624         NTSTATUS status;
625         int ret;
626
627         dns_socket = talloc(dns, struct dns_socket);
628         NT_STATUS_HAVE_NO_MEMORY(dns_socket);
629
630         dns_socket->dns = dns;
631
632         ret = tsocket_address_inet_from_strings(dns_socket, "ip",
633                                                 address, port,
634                                                 &dns_socket->local_address);
635         if (ret != 0) {
636                 status = map_nt_error_from_unix(errno);
637                 return status;
638         }
639
640         status = stream_setup_socket(dns->task->event_ctx,
641                                      dns->task->lp_ctx,
642                                      model_ops,
643                                      &dns_tcp_stream_ops,
644                                      "ip", address, &port,
645                                      lpcfg_socket_options(dns->task->lp_ctx),
646                                      dns_socket);
647         if (!NT_STATUS_IS_OK(status)) {
648                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
649                          address, port, nt_errstr(status)));
650                 talloc_free(dns_socket);
651                 return status;
652         }
653
654         dns_udp_socket = talloc(dns_socket, struct dns_udp_socket);
655         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket);
656
657         dns_udp_socket->dns_socket = dns_socket;
658
659         ret = tdgram_inet_udp_socket(dns_socket->local_address,
660                                      NULL,
661                                      dns_udp_socket,
662                                      &dns_udp_socket->dgram);
663         if (ret != 0) {
664                 status = map_nt_error_from_unix(errno);
665                 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
666                          address, port, nt_errstr(status)));
667                 return status;
668         }
669
670         dns_udp_socket->send_queue = tevent_queue_create(dns_udp_socket,
671                                                          "dns_udp_send_queue");
672         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket->send_queue);
673
674         udpsubreq = tdgram_recvfrom_send(dns_udp_socket,
675                                          dns->task->event_ctx,
676                                          dns_udp_socket->dgram);
677         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
678         tevent_req_set_callback(udpsubreq, dns_udp_call_loop, dns_udp_socket);
679
680         return NT_STATUS_OK;
681 }
682
683 /*
684   setup our listening sockets on the configured network interfaces
685 */
686 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,
687                                        struct interface *ifaces)
688 {
689         const struct model_ops *model_ops;
690         int num_interfaces;
691         TALLOC_CTX *tmp_ctx = talloc_new(dns);
692         NTSTATUS status;
693         int i;
694
695         /* within the dns task we want to be a single process, so
696            ask for the single process model ops and pass these to the
697            stream_setup_socket() call. */
698         model_ops = process_model_startup(dns->task->event_ctx, "single");
699         if (!model_ops) {
700                 DEBUG(0,("Can't find 'single' process model_ops\n"));
701                 return NT_STATUS_INTERNAL_ERROR;
702         }
703
704         num_interfaces = iface_count(ifaces);
705
706         for (i=0; i<num_interfaces; i++) {
707                 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
708
709                 status = dns_add_socket(dns, model_ops, "dns", address, DNS_SERVICE_PORT);
710                 NT_STATUS_NOT_OK_RETURN(status);
711         }
712
713         talloc_free(tmp_ctx);
714
715         return NT_STATUS_OK;
716 }
717 static void dns_task_init(struct task_server *task)
718 {
719         struct dns_server *dns;
720         NTSTATUS status;
721         struct interface *ifaces;
722
723         switch (lpcfg_server_role(task->lp_ctx)) {
724         case ROLE_STANDALONE:
725                 task_server_terminate(task, "dns: no DNS required in standalone configuration", false);
726                 return;
727         case ROLE_DOMAIN_MEMBER:
728                 task_server_terminate(task, "dns: no DNS required in member server configuration", false);
729                 return;
730         case ROLE_DOMAIN_CONTROLLER:
731                 /* Yes, we want a DNS */
732                 break;
733         }
734
735         load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces);
736
737         if (iface_count(ifaces) == 0) {
738                 task_server_terminate(task, "dns: no network interfaces configured", false);
739                 return;
740         }
741
742         task_server_set_title(task, "task[dns]");
743
744         dns = talloc(task, struct dns_server);
745         if (dns == NULL) {
746                 task_server_terminate(task, "dns: out of memory", true);
747                 return;
748         }
749
750         dns->task = task;
751
752         /* Connect to a SAMDB with system privileges for fetching the old pw
753          * hashes. */
754         dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx,
755                               system_session(dns->task->lp_ctx), 0);
756         if (!dns->samdb) {
757                 task_server_terminate(task, "dns: samdb_connect failed", true);
758                 return;
759         }
760
761         status = dns_startup_interfaces(dns, task->lp_ctx, ifaces);
762         if (!NT_STATUS_IS_OK(status)) {
763                 task_server_terminate(task, "dns failed to setup interfaces", true);
764                 return;
765         }
766 }
767
768 NTSTATUS server_service_dns_init(void)
769 {
770         return register_server_service("dns", dns_task_init);
771 }