dns server: move very verbose debug to higher level 2 -> 8
[ddiss/samba.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 "dsdb/common/util.h"
43 #include "auth/session.h"
44 #include "lib/util/dlinklist.h"
45
46 NTSTATUS server_service_dns_init(void);
47
48 /* hold information about one dns socket */
49 struct dns_socket {
50         struct dns_server *dns;
51         struct tsocket_address *local_address;
52 };
53
54 struct dns_udp_socket {
55         struct dns_socket *dns_socket;
56         struct tdgram_context *dgram;
57         struct tevent_queue *send_queue;
58 };
59
60 /*
61   state of an open tcp connection
62 */
63 struct dns_tcp_connection {
64         /* stream connection we belong to */
65         struct stream_connection *conn;
66
67         /* the dns_server the connection belongs to */
68         struct dns_socket *dns_socket;
69
70         struct tstream_context *tstream;
71
72         struct tevent_queue *send_queue;
73 };
74
75 static void dns_tcp_terminate_connection(struct dns_tcp_connection *dnsconn, const char *reason)
76 {
77         stream_terminate_connection(dnsconn->conn, reason);
78 }
79
80 static void dns_tcp_recv(struct stream_connection *conn, uint16_t flags)
81 {
82         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
83                                                              struct dns_tcp_connection);
84         /* this should never be triggered! */
85         dns_tcp_terminate_connection(dnsconn, "dns_tcp_recv: called");
86 }
87
88 static void dns_tcp_send(struct stream_connection *conn, uint16_t flags)
89 {
90         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
91                                                              struct dns_tcp_connection);
92         /* this should never be triggered! */
93         dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called");
94 }
95
96 static NTSTATUS dns_process(struct dns_server *dns,
97                             TALLOC_CTX *mem_ctx,
98                             DATA_BLOB *in,
99                             DATA_BLOB *out)
100 {
101         enum ndr_err_code ndr_err;
102         WERROR ret;
103         struct dns_request_state *state;
104         struct dns_name_packet *in_packet;
105         struct dns_name_packet *out_packet;
106         struct dns_res_rec *answers = NULL, *nsrecs = NULL, *additional = NULL;
107         uint16_t num_answers = 0 , num_nsrecs = 0, num_additional = 0;
108
109         if (in->length < 12) {
110                 return NT_STATUS_INVALID_PARAMETER;
111         }
112
113         state = talloc_zero(mem_ctx, struct dns_request_state);
114
115         in_packet = talloc_zero(state, struct dns_name_packet);
116         /* TODO: We don't really need an out_packet. */
117         out_packet = talloc_zero(state, struct dns_name_packet);
118
119         if (in_packet == NULL) return NT_STATUS_NO_MEMORY;
120         if (out_packet == NULL) return NT_STATUS_NO_MEMORY;
121
122         dump_data(8, in->data, in->length);
123
124         ndr_err = ndr_pull_struct_blob(in, in_packet, in_packet,
125                         (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
126         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
127                 TALLOC_FREE(in_packet);
128                 DEBUG(0, ("Failed to parse packet %d!\n", ndr_err));
129                 *out = *in;
130
131                 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */
132                 out->data[3] |= DNS_RCODE_FORMERR;
133
134                 return NT_STATUS_OK;
135         }
136         if (DEBUGLVL(8)) {
137                 NDR_PRINT_DEBUG(dns_name_packet, in_packet);
138         }
139         *out_packet = *in_packet;
140         state->flags |= in_packet->operation | DNS_FLAG_REPLY;
141
142         if (lpcfg_dns_recursive_queries(dns->task->lp_ctx)) {
143                 state->flags |= DNS_FLAG_RECURSION_AVAIL;
144         }
145
146         switch (in_packet->operation & DNS_OPCODE) {
147         case DNS_OPCODE_QUERY:
148
149                 ret = dns_server_process_query(dns, state,
150                                                out_packet, in_packet,
151                                                &answers, &num_answers,
152                                                &nsrecs,  &num_nsrecs,
153                                                &additional, &num_additional);
154
155                 break;
156         case DNS_OPCODE_UPDATE:
157                 ret = dns_server_process_update(dns, state,
158                                                 out_packet, in_packet,
159                                                 &answers, &num_answers,
160                                                 &nsrecs,  &num_nsrecs,
161                                                 &additional, &num_additional);
162                 break;
163         default:
164                 ret = WERR_DNS_ERROR_RCODE_NOT_IMPLEMENTED;
165                 break;
166         }
167
168         if (W_ERROR_IS_OK(ret)) {
169                 out_packet->ancount = num_answers;
170                 out_packet->answers = answers;
171
172                 out_packet->nscount = num_nsrecs;
173                 out_packet->nsrecs  = nsrecs;
174
175                 out_packet->arcount = num_additional;
176                 out_packet->additional = additional;
177         } else {
178                 out_packet->operation |= werr_to_dns_err(ret);
179         }
180
181         out_packet->operation |= state->flags;
182
183         if (DEBUGLVL(8)) {
184                 NDR_PRINT_DEBUG(dns_name_packet, out_packet);
185         }
186         ndr_err = ndr_push_struct_blob(out, out_packet, out_packet,
187                         (ndr_push_flags_fn_t)ndr_push_dns_name_packet);
188         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
189                 TALLOC_FREE(in_packet);
190                 TALLOC_FREE(out_packet);
191                 DEBUG(0, ("Failed to push packet %d!\n", ndr_err));
192                 *out = *in;
193
194                 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */
195                 out->data[3] |= DNS_RCODE_SERVFAIL;
196
197                 return NT_STATUS_OK;
198         }
199
200         dump_data(8, out->data, out->length);
201         return NT_STATUS_OK;
202 }
203
204 struct dns_tcp_call {
205         struct dns_tcp_connection *dns_conn;
206         DATA_BLOB in;
207         DATA_BLOB out;
208         uint8_t out_hdr[4];
209         struct iovec out_iov[2];
210 };
211
212 static void dns_tcp_call_writev_done(struct tevent_req *subreq);
213
214 static void dns_tcp_call_loop(struct tevent_req *subreq)
215 {
216         struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq,
217                                       struct dns_tcp_connection);
218         struct dns_tcp_call *call;
219         NTSTATUS status;
220
221         call = talloc(dns_conn, struct dns_tcp_call);
222         if (call == NULL) {
223                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
224                                 "no memory for dns_tcp_call");
225                 return;
226         }
227         call->dns_conn = dns_conn;
228
229         status = tstream_read_pdu_blob_recv(subreq,
230                                             call,
231                                             &call->in);
232         TALLOC_FREE(subreq);
233         if (!NT_STATUS_IS_OK(status)) {
234                 const char *reason;
235
236                 reason = talloc_asprintf(call, "dns_tcp_call_loop: "
237                                          "tstream_read_pdu_blob_recv() - %s",
238                                          nt_errstr(status));
239                 if (!reason) {
240                         reason = nt_errstr(status);
241                 }
242
243                 dns_tcp_terminate_connection(dns_conn, reason);
244                 return;
245         }
246
247         DEBUG(10,("Received DNS TCP packet of length %lu from %s\n",
248                  (long) call->in.length,
249                  tsocket_address_string(dns_conn->conn->remote_address, call)));
250
251         /* skip length header */
252         call->in.data += 2;
253         call->in.length -= 2;
254
255         /* Call dns */
256         status = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out);
257         if (!NT_STATUS_IS_OK(status)) {
258                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
259                 dns_tcp_terminate_connection(dns_conn,
260                                 "dns_tcp_call_loop: process function failed");
261                 return;
262         }
263
264         /* First add the length of the out buffer */
265         RSSVAL(call->out_hdr, 0, call->out.length);
266         call->out_iov[0].iov_base = (char *) call->out_hdr;
267         call->out_iov[0].iov_len = 2;
268
269         call->out_iov[1].iov_base = (char *) call->out.data;
270         call->out_iov[1].iov_len = call->out.length;
271
272         subreq = tstream_writev_queue_send(call,
273                                            dns_conn->conn->event.ctx,
274                                            dns_conn->tstream,
275                                            dns_conn->send_queue,
276                                            call->out_iov, 2);
277         if (subreq == NULL) {
278                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
279                                 "no memory for tstream_writev_queue_send");
280                 return;
281         }
282         tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call);
283
284         /*
285          * The dns tcp pdu's has the length as 2 byte (initial_read_size),
286          * packet_full_request_u16 provides the pdu length then.
287          */
288         subreq = tstream_read_pdu_blob_send(dns_conn,
289                                             dns_conn->conn->event.ctx,
290                                             dns_conn->tstream,
291                                             2, /* initial_read_size */
292                                             packet_full_request_u16,
293                                             dns_conn);
294         if (subreq == NULL) {
295                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
296                                 "no memory for tstream_read_pdu_blob_send");
297                 return;
298         }
299         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
300 }
301
302 static void dns_tcp_call_writev_done(struct tevent_req *subreq)
303 {
304         struct dns_tcp_call *call = tevent_req_callback_data(subreq,
305                         struct dns_tcp_call);
306         int sys_errno;
307         int rc;
308
309         rc = tstream_writev_queue_recv(subreq, &sys_errno);
310         TALLOC_FREE(subreq);
311         if (rc == -1) {
312                 const char *reason;
313
314                 reason = talloc_asprintf(call, "dns_tcp_call_writev_done: "
315                                          "tstream_writev_queue_recv() - %d:%s",
316                                          sys_errno, strerror(sys_errno));
317                 if (!reason) {
318                         reason = "dns_tcp_call_writev_done: tstream_writev_queue_recv() failed";
319                 }
320
321                 dns_tcp_terminate_connection(call->dns_conn, reason);
322                 return;
323         }
324
325         /* We don't care about errors */
326
327         talloc_free(call);
328 }
329
330 /*
331   called when we get a new connection
332 */
333 static void dns_tcp_accept(struct stream_connection *conn)
334 {
335         struct dns_socket *dns_socket;
336         struct dns_tcp_connection *dns_conn;
337         struct tevent_req *subreq;
338         int rc;
339
340         dns_conn = talloc_zero(conn, struct dns_tcp_connection);
341         if (dns_conn == NULL) {
342                 stream_terminate_connection(conn,
343                                 "dns_tcp_accept: out of memory");
344                 return;
345         }
346
347         dns_conn->send_queue = tevent_queue_create(conn, "dns_tcp_accept");
348         if (dns_conn->send_queue == NULL) {
349                 stream_terminate_connection(conn,
350                                 "dns_tcp_accept: out of memory");
351                 return;
352         }
353
354         dns_socket = talloc_get_type(conn->private_data, struct dns_socket);
355
356         TALLOC_FREE(conn->event.fde);
357
358         rc = tstream_bsd_existing_socket(dns_conn,
359                         socket_get_fd(conn->socket),
360                         &dns_conn->tstream);
361         if (rc < 0) {
362                 stream_terminate_connection(conn,
363                                 "dns_tcp_accept: out of memory");
364                 return;
365         }
366
367         dns_conn->conn = conn;
368         dns_conn->dns_socket = dns_socket;
369         conn->private_data = dns_conn;
370
371         /*
372          * The dns tcp pdu's has the length as 2 byte (initial_read_size),
373          * packet_full_request_u16 provides the pdu length then.
374          */
375         subreq = tstream_read_pdu_blob_send(dns_conn,
376                                             dns_conn->conn->event.ctx,
377                                             dns_conn->tstream,
378                                             2, /* initial_read_size */
379                                             packet_full_request_u16,
380                                             dns_conn);
381         if (subreq == NULL) {
382                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_accept: "
383                                 "no memory for tstream_read_pdu_blob_send");
384                 return;
385         }
386         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
387 }
388
389 static const struct stream_server_ops dns_tcp_stream_ops = {
390         .name                   = "dns_tcp",
391         .accept_connection      = dns_tcp_accept,
392         .recv_handler           = dns_tcp_recv,
393         .send_handler           = dns_tcp_send
394 };
395
396 struct dns_udp_call {
397         struct tsocket_address *src;
398         DATA_BLOB in;
399         DATA_BLOB out;
400 };
401
402 static void dns_udp_call_sendto_done(struct tevent_req *subreq);
403
404 static void dns_udp_call_loop(struct tevent_req *subreq)
405 {
406         struct dns_udp_socket *sock = tevent_req_callback_data(subreq,
407                                       struct dns_udp_socket);
408         struct dns_udp_call *call;
409         uint8_t *buf;
410         ssize_t len;
411         int sys_errno;
412         NTSTATUS status;
413
414         call = talloc(sock, struct dns_udp_call);
415         if (call == NULL) {
416                 talloc_free(call);
417                 goto done;
418         }
419
420         len = tdgram_recvfrom_recv(subreq, &sys_errno,
421                                    call, &buf, &call->src);
422         TALLOC_FREE(subreq);
423         if (len == -1) {
424                 talloc_free(call);
425                 goto done;
426         }
427
428         call->in.data = buf;
429         call->in.length = len;
430
431         DEBUG(10,("Received DNS UDP packet of length %lu from %s\n",
432                  (long)call->in.length,
433                  tsocket_address_string(call->src, call)));
434
435         /* Call dns_process */
436         status = dns_process(sock->dns_socket->dns, call, &call->in, &call->out);
437         if (!NT_STATUS_IS_OK(status)) {
438                 talloc_free(call);
439                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
440                 goto done;
441         }
442
443         subreq = tdgram_sendto_queue_send(call,
444                                           sock->dns_socket->dns->task->event_ctx,
445                                           sock->dgram,
446                                           sock->send_queue,
447                                           call->out.data,
448                                           call->out.length,
449                                           call->src);
450         if (subreq == NULL) {
451                 talloc_free(call);
452                 goto done;
453         }
454         tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call);
455
456 done:
457         subreq = tdgram_recvfrom_send(sock,
458                                       sock->dns_socket->dns->task->event_ctx,
459                                       sock->dgram);
460         if (subreq == NULL) {
461                 task_server_terminate(sock->dns_socket->dns->task,
462                                       "no memory for tdgram_recvfrom_send",
463                                       true);
464                 return;
465         }
466         tevent_req_set_callback(subreq, dns_udp_call_loop, sock);
467 }
468
469 static void dns_udp_call_sendto_done(struct tevent_req *subreq)
470 {
471         struct dns_udp_call *call = tevent_req_callback_data(subreq,
472                                        struct dns_udp_call);
473         ssize_t ret;
474         int sys_errno;
475
476         ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
477
478         /* We don't care about errors */
479
480         talloc_free(call);
481 }
482
483 /*
484   start listening on the given address
485 */
486 static NTSTATUS dns_add_socket(struct dns_server *dns,
487                                const struct model_ops *model_ops,
488                                const char *name,
489                                const char *address,
490                                uint16_t port)
491 {
492         struct dns_socket *dns_socket;
493         struct dns_udp_socket *dns_udp_socket;
494         struct tevent_req *udpsubreq;
495         NTSTATUS status;
496         int ret;
497
498         dns_socket = talloc(dns, struct dns_socket);
499         NT_STATUS_HAVE_NO_MEMORY(dns_socket);
500
501         dns_socket->dns = dns;
502
503         ret = tsocket_address_inet_from_strings(dns_socket, "ip",
504                                                 address, port,
505                                                 &dns_socket->local_address);
506         if (ret != 0) {
507                 status = map_nt_error_from_unix_common(errno);
508                 return status;
509         }
510
511         status = stream_setup_socket(dns->task,
512                                      dns->task->event_ctx,
513                                      dns->task->lp_ctx,
514                                      model_ops,
515                                      &dns_tcp_stream_ops,
516                                      "ip", address, &port,
517                                      lpcfg_socket_options(dns->task->lp_ctx),
518                                      dns_socket);
519         if (!NT_STATUS_IS_OK(status)) {
520                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
521                          address, port, nt_errstr(status)));
522                 talloc_free(dns_socket);
523                 return status;
524         }
525
526         dns_udp_socket = talloc(dns_socket, struct dns_udp_socket);
527         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket);
528
529         dns_udp_socket->dns_socket = dns_socket;
530
531         ret = tdgram_inet_udp_socket(dns_socket->local_address,
532                                      NULL,
533                                      dns_udp_socket,
534                                      &dns_udp_socket->dgram);
535         if (ret != 0) {
536                 status = map_nt_error_from_unix_common(errno);
537                 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
538                          address, port, nt_errstr(status)));
539                 return status;
540         }
541
542         dns_udp_socket->send_queue = tevent_queue_create(dns_udp_socket,
543                                                          "dns_udp_send_queue");
544         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket->send_queue);
545
546         udpsubreq = tdgram_recvfrom_send(dns_udp_socket,
547                                          dns->task->event_ctx,
548                                          dns_udp_socket->dgram);
549         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
550         tevent_req_set_callback(udpsubreq, dns_udp_call_loop, dns_udp_socket);
551
552         return NT_STATUS_OK;
553 }
554
555 /*
556   setup our listening sockets on the configured network interfaces
557 */
558 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,
559                                        struct interface *ifaces)
560 {
561         const struct model_ops *model_ops;
562         int num_interfaces;
563         TALLOC_CTX *tmp_ctx = talloc_new(dns);
564         NTSTATUS status;
565         int i;
566
567         /* within the dns task we want to be a single process, so
568            ask for the single process model ops and pass these to the
569            stream_setup_socket() call. */
570         model_ops = process_model_startup("single");
571         if (!model_ops) {
572                 DEBUG(0,("Can't find 'single' process model_ops\n"));
573                 return NT_STATUS_INTERNAL_ERROR;
574         }
575
576         num_interfaces = iface_list_count(ifaces);
577
578         for (i=0; i<num_interfaces; i++) {
579                 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
580
581                 status = dns_add_socket(dns, model_ops, "dns", address, DNS_SERVICE_PORT);
582                 NT_STATUS_NOT_OK_RETURN(status);
583         }
584
585         talloc_free(tmp_ctx);
586
587         return NT_STATUS_OK;
588 }
589
590 static int dns_server_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
591 {
592         const char *n1, *n2;
593         size_t l1, l2;
594
595         n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
596         n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
597
598         l1 = strlen(n1);
599         l2 = strlen(n2);
600
601         /* If the string lengths are not equal just sort by length */
602         if (l1 != l2) {
603                 /* If m1 is the larger zone name, return it first */
604                 return l2 - l1;
605         }
606
607         /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
608         return 0;
609 }
610
611 static void dns_task_init(struct task_server *task)
612 {
613         struct dns_server *dns;
614         NTSTATUS status;
615         struct interface *ifaces;
616         int ret;
617         struct ldb_result *res;
618         static const char * const attrs[] = { "name", NULL};
619         unsigned int i;
620
621         switch (lpcfg_server_role(task->lp_ctx)) {
622         case ROLE_STANDALONE:
623                 task_server_terminate(task, "dns: no DNS required in standalone configuration", false);
624                 return;
625         case ROLE_DOMAIN_MEMBER:
626                 task_server_terminate(task, "dns: no DNS required in member server configuration", false);
627                 return;
628         case ROLE_DOMAIN_CONTROLLER:
629                 /* Yes, we want a DNS */
630                 break;
631         }
632
633         load_interface_list(task, task->lp_ctx, &ifaces);
634
635         if (iface_list_count(ifaces) == 0) {
636                 task_server_terminate(task, "dns: no network interfaces configured", false);
637                 return;
638         }
639
640         task_server_set_title(task, "task[dns]");
641
642         dns = talloc_zero(task, struct dns_server);
643         if (dns == NULL) {
644                 task_server_terminate(task, "dns: out of memory", true);
645                 return;
646         }
647
648         dns->task = task;
649
650         dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx,
651                               system_session(dns->task->lp_ctx), 0);
652         if (!dns->samdb) {
653                 task_server_terminate(task, "dns: samdb_connect failed", true);
654                 return;
655         }
656
657         // TODO: this search does not work against windows
658         ret = dsdb_search(dns->samdb, dns, &res, NULL, LDB_SCOPE_SUBTREE,
659                           attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)");
660         if (ret != LDB_SUCCESS) {
661                 task_server_terminate(task,
662                                       "dns: failed to look up root DNS zones",
663                                       true);
664                 return;
665         }
666
667         TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones);
668
669         for (i=0; i < res->count; i++) {
670                 struct dns_server_zone *z;
671
672                 z = talloc_zero(dns, struct dns_server_zone);
673                 if (z == NULL) {
674                 }
675
676                 z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
677                 z->dn = talloc_move(z, &res->msgs[i]->dn);
678
679                 DLIST_ADD_END(dns->zones, z, NULL);
680         }
681
682         status = dns_startup_interfaces(dns, task->lp_ctx, ifaces);
683         if (!NT_STATUS_IS_OK(status)) {
684                 task_server_terminate(task, "dns failed to setup interfaces", true);
685                 return;
686         }
687 }
688
689 NTSTATUS server_service_dns_init(void)
690 {
691         return register_server_service("dns", dns_task_init);
692 }