1c45691efc08911883d1d53f91239746f32403f5
[obnox/samba/samba-obnox.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 /* hold information about one dns socket */
47 struct dns_socket {
48         struct dns_server *dns;
49         struct tsocket_address *local_address;
50 };
51
52 struct dns_udp_socket {
53         struct dns_socket *dns_socket;
54         struct tdgram_context *dgram;
55         struct tevent_queue *send_queue;
56 };
57
58 /*
59   state of an open tcp connection
60 */
61 struct dns_tcp_connection {
62         /* stream connection we belong to */
63         struct stream_connection *conn;
64
65         /* the dns_server the connection belongs to */
66         struct dns_socket *dns_socket;
67
68         struct tstream_context *tstream;
69
70         struct tevent_queue *send_queue;
71 };
72
73 static void dns_tcp_terminate_connection(struct dns_tcp_connection *dnsconn, const char *reason)
74 {
75         stream_terminate_connection(dnsconn->conn, reason);
76 }
77
78 static void dns_tcp_recv(struct stream_connection *conn, uint16_t flags)
79 {
80         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
81                                                              struct dns_tcp_connection);
82         /* this should never be triggered! */
83         dns_tcp_terminate_connection(dnsconn, "dns_tcp_recv: called");
84 }
85
86 static void dns_tcp_send(struct stream_connection *conn, uint16_t flags)
87 {
88         struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
89                                                              struct dns_tcp_connection);
90         /* this should never be triggered! */
91         dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called");
92 }
93
94 static NTSTATUS dns_err_to_ntstatus(enum dns_rcode rcode)
95 {
96         switch (rcode) {
97         case DNS_RCODE_OK: return NT_STATUS_OK;
98         case DNS_RCODE_FORMERR: return NT_STATUS_INVALID_PARAMETER;
99         case DNS_RCODE_SERVFAIL: return NT_STATUS_INTERNAL_ERROR;
100         case DNS_RCODE_NXDOMAIN: return NT_STATUS_OBJECT_NAME_NOT_FOUND;
101         case DNS_RCODE_NOTIMP: return NT_STATUS_NOT_IMPLEMENTED;
102         case DNS_RCODE_REFUSED: return NT_STATUS_ACCESS_DENIED;
103         case DNS_RCODE_NOTAUTH: return NT_STATUS_FOOBAR;
104         default: return NT_STATUS_NONE_MAPPED;
105         }
106 }
107
108 static uint8_t ntstatus_to_dns_err(NTSTATUS status)
109 {
110         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
111                 return DNS_RCODE_OK;
112         } else if (NT_STATUS_EQUAL(NT_STATUS_INVALID_PARAMETER, status)) {
113                 return DNS_RCODE_FORMERR;
114         } else if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status)) {
115                 return DNS_RCODE_SERVFAIL;
116         } else if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
117                 return DNS_RCODE_NXDOMAIN;
118         } else if (NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
119                 return DNS_RCODE_NOTIMP;
120         } else if (NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, status)) {
121                 return DNS_RCODE_REFUSED;
122         } else if (NT_STATUS_EQUAL(NT_STATUS_FOOBAR, status)) {
123                 return DNS_RCODE_NOTAUTH;
124         }
125         DEBUG(0, ("No mapping exists for %s\n", nt_errstr(status)));
126 }
127
128 static bool dns_name_match(const char *zone, const char *name, size_t *host_part_len)
129 {
130         size_t zl = strlen(zone);
131         size_t nl = strlen(name);
132         ssize_t zi, ni;
133         static const size_t fixup = 'a' - 'A';
134
135         if (zl > nl) {
136                 return false;
137         }
138
139         for (zi = zl, ni = nl; zi >= 0; zi--, ni--) {
140                 char zc = zone[zi];
141                 char nc = name[ni];
142
143                 /* convert to lower case */
144                 if (zc >= 'A' && zc <= 'Z') {
145                         zc += fixup;
146                 }
147                 if (nc >= 'A' && nc <= 'Z') {
148                         nc += fixup;
149                 }
150
151                 if (zc != nc) {
152                         return false;
153                 }
154         }
155
156         if (ni >= 0) {
157                 if (name[ni] != '.') {
158                         return false;
159                 }
160
161                 ni--;
162         }
163
164         *host_part_len = ni+1;
165
166         return true;
167 }
168
169 static NTSTATUS dns_name2dn(struct dns_server *dns,
170                             TALLOC_CTX *mem_ctx,
171                             const char *name,
172                             struct ldb_dn **_dn)
173 {
174         struct ldb_dn *base;
175         struct ldb_dn *dn;
176         const struct dns_server_zone *z;
177         size_t host_part_len = 0;
178
179         if (name == NULL) {
180                 return NT_STATUS_INVALID_PARAMETER;
181         }
182
183         /*TODO: Check if 'name' is a valid DNS name */
184
185         if (strcmp(name, "") == 0) {
186                 base = ldb_get_default_basedn(dns->samdb);
187                 dn = ldb_dn_copy(mem_ctx, base);
188                 ldb_dn_add_child_fmt(dn, "DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System");
189                 *_dn = dn;
190                 return NT_STATUS_OK;
191         }
192
193         for (z = dns->zones; z != NULL; z = z->next) {
194                 bool match;
195
196                 match = dns_name_match(z->name, name, &host_part_len);
197                 if (match) {
198                         break;
199                 }
200         }
201
202         if (z == NULL) {
203                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
204         }
205
206         if (host_part_len == 0) {
207                 dn = ldb_dn_copy(mem_ctx, z->dn);
208                 ldb_dn_add_child_fmt(dn, "DC=@");
209                 *_dn = dn;
210                 return NT_STATUS_OK;
211         }
212
213         dn = ldb_dn_copy(mem_ctx, z->dn);
214         ldb_dn_add_child_fmt(dn, "DC=%*.*s", (int)host_part_len, (int)host_part_len, name);
215         *_dn = dn;
216         return NT_STATUS_OK;
217 }
218
219 static NTSTATUS handle_question(struct dns_server *dns,
220                                 TALLOC_CTX *mem_ctx,
221                                 const struct dns_name_question *question,
222                                 struct dns_res_rec **answers, uint16_t *ancount)
223 {
224         struct dns_res_rec *ans;
225         struct ldb_dn *dn = NULL;
226         NTSTATUS status;
227         static const char * const attrs[] = { "dnsRecord", NULL};
228         int ret;
229         uint16_t ai = *ancount;
230         uint16_t ri;
231         struct ldb_message *msg = NULL;
232         struct dnsp_DnssrvRpcRecord *recs;
233         struct ldb_message_element *el;
234
235         status = dns_name2dn(dns, mem_ctx, question->name, &dn);
236         NT_STATUS_NOT_OK_RETURN(status);
237
238         ret = dsdb_search_one(dns->samdb, mem_ctx, &msg, dn,
239                               LDB_SCOPE_BASE, attrs, 0, "%s", "(objectClass=dnsNode)");
240         if (ret != LDB_SUCCESS) {
241                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
242         }
243
244         el = ldb_msg_find_element(msg, attrs[0]);
245         if (el == NULL) {
246                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
247         }
248
249         recs = talloc_array(mem_ctx, struct dnsp_DnssrvRpcRecord, el->num_values);
250         for (ri = 0; ri < el->num_values; ri++) {
251                 struct ldb_val *v = &el->values[ri];
252                 enum ndr_err_code ndr_err;
253
254                 ndr_err = ndr_pull_struct_blob(v, recs, &recs[ri],
255                                 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
256                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
257                         DEBUG(0, ("Failed to grab dnsp_DnssrvRpcRecord\n"));
258                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
259                 }
260         }
261
262         ans = talloc_realloc(mem_ctx, *answers, struct dns_res_rec,
263                              ai + el->num_values);
264         NT_STATUS_HAVE_NO_MEMORY(ans);
265
266         switch (question->question_type) {
267         case DNS_QTYPE_CNAME:
268                 for (ri = 0; ri < el->num_values; ri++) {
269                         if (recs[ri].wType != question->question_type) {
270                                 continue;
271                         }
272
273                         ZERO_STRUCT(ans[ai]);
274                         ans[ai].name = talloc_strdup(ans, question->name);
275                         ans[ai].rr_type = DNS_QTYPE_CNAME;
276                         ans[ai].rr_class = DNS_QCLASS_IP;
277                         ans[ai].ttl = recs[ri].dwTtlSeconds;
278                         ans[ai].length = UINT16_MAX;
279                         ans[ai].rdata.cname_record = talloc_strdup(ans, recs[ri].data.cname);
280                         ai++;
281                 }
282                 break;
283         case DNS_QTYPE_A:
284                 for (ri = 0; ri < el->num_values; ri++) {
285                         if (recs[ri].wType != question->question_type) {
286                                 continue;
287                         }
288
289                         /* TODO: if the record actually is a DNS_QTYPE_A */
290
291                         ZERO_STRUCT(ans[ai]);
292                         ans[ai].name = talloc_strdup(ans, question->name);
293                         ans[ai].rr_type = DNS_QTYPE_A;
294                         ans[ai].rr_class = DNS_QCLASS_IP;
295                         ans[ai].ttl = recs[ri].dwTtlSeconds;
296                         ans[ai].length = UINT16_MAX;
297                         ans[ai].rdata.ipv4_record = talloc_strdup(ans, recs[ri].data.ipv4);
298                         ai++;
299                 }
300                 break;
301         case DNS_QTYPE_AAAA:
302                 for (ri = 0; ri < el->num_values; ri++) {
303                         if (recs[ri].wType != question->question_type) {
304                                 continue;
305                         }
306
307                         ZERO_STRUCT(ans[ai]);
308                         ans[ai].name = talloc_strdup(ans, question->name);
309                         ans[ai].rr_type = DNS_QTYPE_AAAA;
310                         ans[ai].rr_class = DNS_QCLASS_IP;
311                         ans[ai].ttl = recs[ri].dwTtlSeconds;
312                         ans[ai].length = UINT16_MAX;
313                         ans[ai].rdata.ipv6_record = recs[ri].data.ipv6;
314                         ai++;
315                 }
316                 break;
317         case DNS_QTYPE_NS:
318                 for (ri = 0; ri < el->num_values; ri++) {
319                         if (recs[ri].wType != question->question_type) {
320                                 continue;
321                         }
322
323                         ZERO_STRUCT(ans[ai]);
324                         ans[ai].name = question->name;
325                         ans[ai].rr_type = DNS_QTYPE_NS;
326                         ans[ai].rr_class = DNS_QCLASS_IP;
327                         ans[ai].ttl = recs[ri].dwTtlSeconds;
328                         ans[ai].length = UINT16_MAX;
329                         ans[ai].rdata.ns_record = recs[ri].data.ns;
330                         ai++;
331                 }
332                 break;
333         case DNS_QTYPE_SRV:
334                 for (ri = 0; ri < el->num_values; ri++) {
335                         if (recs[ri].wType != question->question_type) {
336                                 continue;
337                         }
338
339                         ZERO_STRUCT(ans[ai]);
340                         ans[ai].name = question->name;
341                         ans[ai].rr_type = DNS_QTYPE_SRV;
342                         ans[ai].rr_class = DNS_QCLASS_IP;
343                         ans[ai].ttl = recs[ri].dwTtlSeconds;
344                         ans[ai].length = UINT16_MAX;
345                         ans[ai].rdata.srv_record.priority = recs[ri].data.srv.wPriority;
346                         ans[ai].rdata.srv_record.weight = recs[ri].data.srv.wWeight;
347                         ans[ai].rdata.srv_record.port = recs[ri].data.srv.wPort;
348                         ans[ai].rdata.srv_record.target = recs[ri].data.srv.nameTarget;
349                         ai++;
350                 }
351                 break;
352         case DNS_QTYPE_SOA:
353                 for (ri = 0; ri < el->num_values; ri++) {
354                         if (recs[ri].wType != question->question_type) {
355                                 continue;
356                         }
357
358                         ZERO_STRUCT(ans[ai]);
359                         ans[ai].name = question->name;
360                         ans[ai].rr_type = DNS_QTYPE_SOA;
361                         ans[ai].rr_class = DNS_QCLASS_IP;
362                         ans[ai].ttl = recs[ri].dwTtlSeconds;
363                         ans[ai].length = UINT16_MAX;
364                         ans[ai].rdata.soa_record.mname  = recs[ri].data.soa.mname;
365                         ans[ai].rdata.soa_record.rname  = recs[ri].data.soa.rname;
366                         ans[ai].rdata.soa_record.serial = recs[ri].data.soa.serial;
367                         ans[ai].rdata.soa_record.refresh= recs[ri].data.soa.refresh;
368                         ans[ai].rdata.soa_record.retry  = recs[ri].data.soa.retry;
369                         ans[ai].rdata.soa_record.expire = recs[ri].data.soa.expire;
370                         ans[ai].rdata.soa_record.minimum= recs[ri].data.soa.minimum;
371                         ai++;
372                 }
373                 break;
374         default:
375                 return NT_STATUS_NOT_IMPLEMENTED;
376         }
377
378         if (*ancount == ai) {
379                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
380         }
381
382         *ancount = ai;
383         *answers = ans;
384
385         return NT_STATUS_OK;
386
387 }
388
389 static NTSTATUS dns_server_process_query(struct dns_server *dns,
390                                          TALLOC_CTX *mem_ctx,
391                                          struct dns_name_packet *in,
392                                          struct dns_res_rec **answers,    uint16_t *ancount,
393                                          struct dns_res_rec **nsrecs,     uint16_t *nscount,
394                                          struct dns_res_rec **additional, uint16_t *arcount)
395 {
396         uint16_t num_answers=0;
397         struct dns_res_rec *ans=NULL;
398         int i;
399         NTSTATUS status;
400
401         ans = talloc_array(mem_ctx, struct dns_res_rec, 0);
402         if (answers == NULL) return NT_STATUS_NO_MEMORY;
403
404         for (i = 0; i < in->qdcount; ++i) {
405                 status = handle_question(dns, mem_ctx, &in->questions[i], &ans, &num_answers);
406                 NT_STATUS_NOT_OK_RETURN(status);
407         }
408
409         *answers = ans;
410         *ancount = num_answers;
411
412         /*FIXME: Do something for these */
413         *nsrecs  = NULL;
414         *nscount = 0;
415
416         *additional = NULL;
417         *arcount    = 0;
418
419         return NT_STATUS_OK;
420 }
421
422 static NTSTATUS dns_server_process_update(struct dns_server *dns,
423                                           TALLOC_CTX *mem_ctx,
424                                           struct dns_name_packet *in,
425                                           struct dns_res_rec **prereqs,    uint16_t *prereq_count,
426                                           struct dns_res_rec **updates,    uint16_t *update_count,
427                                           struct dns_res_rec **additional, uint16_t *arcount)
428 {
429         struct dns_name_question *zone;
430         const struct dns_server_zone *z;
431         size_t host_part_len = 0;
432
433         if (in->qdcount != 1) {
434                 return NT_STATUS_INVALID_PARAMETER;
435         }
436
437         zone = in->questions;
438
439         if (zone->question_type != DNS_QTYPE_SOA) {
440                 return NT_STATUS_INVALID_PARAMETER;
441         }
442
443         DEBUG(0, ("Got a dns update request.\n"));
444
445         for (z = dns->zones; z != NULL; z = z->next) {
446                 bool match;
447
448                 match = dns_name_match(z->name, zone->name, &host_part_len);
449                 if (match) {
450                         break;
451                 }
452         }
453
454         if (z == NULL) {
455                 return NT_STATUS_FOOBAR;
456         }
457
458         if (host_part_len != 0) {
459                 return NT_STATUS_NOT_IMPLEMENTED;
460         }
461
462         return NT_STATUS_NOT_IMPLEMENTED;
463 }
464
465 static NTSTATUS dns_process(struct dns_server *dns,
466                             TALLOC_CTX *mem_ctx,
467                             DATA_BLOB *in,
468                             DATA_BLOB *out)
469 {
470         enum ndr_err_code ndr_err;
471         NTSTATUS ret;
472         struct dns_name_packet *in_packet;
473         struct dns_name_packet *out_packet;
474         struct dns_res_rec *answers = NULL, *nsrecs = NULL, *additional = NULL;
475         uint16_t num_answers = 0 , num_nsrecs = 0, num_additional = 0;
476         uint16_t reply_code;
477
478         if (in->length < 12) {
479                 return NT_STATUS_INVALID_PARAMETER;
480         }
481
482         in_packet = talloc_zero(mem_ctx, struct dns_name_packet);
483         /* TODO: We don't really need an out_packet. */
484         out_packet = talloc_zero(mem_ctx, struct dns_name_packet);
485
486         if (in_packet == NULL) return NT_STATUS_NO_MEMORY;
487         if (out_packet == NULL) return NT_STATUS_NO_MEMORY;
488
489         dump_data(2, in->data, in->length);
490
491         ndr_err = ndr_pull_struct_blob(in, in_packet, in_packet,
492                         (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
493         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
494                 TALLOC_FREE(in_packet);
495                 DEBUG(0, ("Failed to parse packet %d!\n", ndr_err));
496                 *out = *in;
497
498                 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */
499                 out->data[3] |= DNS_RCODE_FORMERR;
500
501                 return NT_STATUS_OK;
502         }
503
504         NDR_PRINT_DEBUG(dns_name_packet, in_packet);
505         *out_packet = *in_packet;
506         out_packet->operation |= DNS_FLAG_REPLY;
507
508         switch (in_packet->operation & DNS_OPCODE) {
509         case DNS_OPCODE_QUERY:
510
511                 ret = dns_server_process_query(dns, out_packet, in_packet,
512                                                &answers, &num_answers,
513                                                &nsrecs,  &num_nsrecs,
514                                                &additional, &num_additional);
515                 reply_code = DNS_RCODE_NXDOMAIN;
516
517                 break;
518         case DNS_OPCODE_REGISTER:
519                 ret = dns_server_process_update(dns, out_packet, in_packet,
520                                                 &answers, &num_answers,
521                                                 &nsrecs,  &num_nsrecs,
522                                                 &additional, &num_additional);
523                 reply_code = ntstatus_to_dns_err(ret);
524                 break;
525         default:
526                 ret = NT_STATUS_NOT_IMPLEMENTED;
527                 reply_code = DNS_RCODE_NOTIMP;
528                 break;
529         }
530
531         if (NT_STATUS_IS_OK(ret)) {
532                 out_packet->ancount = num_answers;
533                 out_packet->answers = answers;
534
535                 out_packet->nscount = num_nsrecs;
536                 out_packet->nsrecs  = nsrecs;
537
538                 out_packet->arcount = num_additional;
539                 out_packet->additional = additional;
540         } else {
541                 out_packet->operation |= reply_code;
542         }
543
544         NDR_PRINT_DEBUG(dns_name_packet, out_packet);
545         ndr_err = ndr_push_struct_blob(out, out_packet, out_packet,
546                         (ndr_push_flags_fn_t)ndr_push_dns_name_packet);
547         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
548                 TALLOC_FREE(in_packet);
549                 TALLOC_FREE(out_packet);
550                 DEBUG(0, ("Failed to push packet %d!\n", ndr_err));
551                 *out = *in;
552
553                 out->data[2] |= 0x80; /* Toggle DNS_FLAG_REPLY */
554                 out->data[3] |= DNS_RCODE_SERVFAIL;
555
556                 return NT_STATUS_OK;
557         }
558
559         dump_data(2, out->data, out->length);
560         return NT_STATUS_OK;
561 }
562
563 struct dns_tcp_call {
564         struct dns_tcp_connection *dns_conn;
565         DATA_BLOB in;
566         DATA_BLOB out;
567         uint8_t out_hdr[4];
568         struct iovec out_iov[2];
569 };
570
571 static void dns_tcp_call_writev_done(struct tevent_req *subreq);
572
573 static void dns_tcp_call_loop(struct tevent_req *subreq)
574 {
575         struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq,
576                                       struct dns_tcp_connection);
577         struct dns_tcp_call *call;
578         NTSTATUS status;
579
580         call = talloc(dns_conn, struct dns_tcp_call);
581         if (call == NULL) {
582                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
583                                 "no memory for dns_tcp_call");
584                 return;
585         }
586         call->dns_conn = dns_conn;
587
588         status = tstream_read_pdu_blob_recv(subreq,
589                                             call,
590                                             &call->in);
591         TALLOC_FREE(subreq);
592         if (!NT_STATUS_IS_OK(status)) {
593                 const char *reason;
594
595                 reason = talloc_asprintf(call, "dns_tcp_call_loop: "
596                                          "tstream_read_pdu_blob_recv() - %s",
597                                          nt_errstr(status));
598                 if (!reason) {
599                         reason = nt_errstr(status);
600                 }
601
602                 dns_tcp_terminate_connection(dns_conn, reason);
603                 return;
604         }
605
606         DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
607                  (long) call->in.length,
608                  tsocket_address_string(dns_conn->conn->remote_address, call)));
609
610         /* skip length header */
611         call->in.data +=4;
612         call->in.length -= 4;
613
614         /* Call dns */
615         status = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out);
616         if (!NT_STATUS_IS_OK(status)) {
617                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
618                 dns_tcp_terminate_connection(dns_conn,
619                                 "dns_tcp_call_loop: process function failed");
620                 return;
621         }
622
623         /* First add the length of the out buffer */
624         RSIVAL(call->out_hdr, 0, call->out.length);
625         call->out_iov[0].iov_base = (char *) call->out_hdr;
626         call->out_iov[0].iov_len = 4;
627
628         call->out_iov[1].iov_base = (char *) call->out.data;
629         call->out_iov[1].iov_len = call->out.length;
630
631         subreq = tstream_writev_queue_send(call,
632                                            dns_conn->conn->event.ctx,
633                                            dns_conn->tstream,
634                                            dns_conn->send_queue,
635                                            call->out_iov, 2);
636         if (subreq == NULL) {
637                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
638                                 "no memory for tstream_writev_queue_send");
639                 return;
640         }
641         tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call);
642
643         /*
644          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
645          * packet_full_request_u32 provides the pdu length then.
646          */
647         subreq = tstream_read_pdu_blob_send(dns_conn,
648                                             dns_conn->conn->event.ctx,
649                                             dns_conn->tstream,
650                                             4, /* initial_read_size */
651                                             packet_full_request_u32,
652                                             dns_conn);
653         if (subreq == NULL) {
654                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
655                                 "no memory for tstream_read_pdu_blob_send");
656                 return;
657         }
658         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
659 }
660
661 static void dns_tcp_call_writev_done(struct tevent_req *subreq)
662 {
663         struct dns_tcp_call *call = tevent_req_callback_data(subreq,
664                         struct dns_tcp_call);
665         int sys_errno;
666         int rc;
667
668         rc = tstream_writev_queue_recv(subreq, &sys_errno);
669         TALLOC_FREE(subreq);
670         if (rc == -1) {
671                 const char *reason;
672
673                 reason = talloc_asprintf(call, "dns_tcp_call_writev_done: "
674                                          "tstream_writev_queue_recv() - %d:%s",
675                                          sys_errno, strerror(sys_errno));
676                 if (!reason) {
677                         reason = "dns_tcp_call_writev_done: tstream_writev_queue_recv() failed";
678                 }
679
680                 dns_tcp_terminate_connection(call->dns_conn, reason);
681                 return;
682         }
683
684         /* We don't care about errors */
685
686         talloc_free(call);
687 }
688
689 /*
690   called when we get a new connection
691 */
692 static void dns_tcp_accept(struct stream_connection *conn)
693 {
694         struct dns_socket *dns_socket;
695         struct dns_tcp_connection *dns_conn;
696         struct tevent_req *subreq;
697         int rc;
698
699         dns_conn = talloc_zero(conn, struct dns_tcp_connection);
700         if (dns_conn == NULL) {
701                 stream_terminate_connection(conn,
702                                 "dns_tcp_accept: out of memory");
703                 return;
704         }
705
706         dns_conn->send_queue = tevent_queue_create(conn, "dns_tcp_accept");
707         if (dns_conn->send_queue == NULL) {
708                 stream_terminate_connection(conn,
709                                 "dns_tcp_accept: out of memory");
710                 return;
711         }
712
713         dns_socket = talloc_get_type(conn->private_data, struct dns_socket);
714
715         TALLOC_FREE(conn->event.fde);
716
717         rc = tstream_bsd_existing_socket(dns_conn,
718                         socket_get_fd(conn->socket),
719                         &dns_conn->tstream);
720         if (rc < 0) {
721                 stream_terminate_connection(conn,
722                                 "dns_tcp_accept: out of memory");
723                 return;
724         }
725
726         dns_conn->conn = conn;
727         dns_conn->dns_socket = dns_socket;
728         conn->private_data = dns_conn;
729
730         /*
731          * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
732          * packet_full_request_u32 provides the pdu length then.
733          */
734         subreq = tstream_read_pdu_blob_send(dns_conn,
735                                             dns_conn->conn->event.ctx,
736                                             dns_conn->tstream,
737                                             4, /* initial_read_size */
738                                             packet_full_request_u32,
739                                             dns_conn);
740         if (subreq == NULL) {
741                 dns_tcp_terminate_connection(dns_conn, "dns_tcp_accept: "
742                                 "no memory for tstream_read_pdu_blob_send");
743                 return;
744         }
745         tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
746 }
747
748 static const struct stream_server_ops dns_tcp_stream_ops = {
749         .name                   = "dns_tcp",
750         .accept_connection      = dns_tcp_accept,
751         .recv_handler           = dns_tcp_recv,
752         .send_handler           = dns_tcp_send
753 };
754
755 struct dns_udp_call {
756         struct tsocket_address *src;
757         DATA_BLOB in;
758         DATA_BLOB out;
759 };
760
761 static void dns_udp_call_sendto_done(struct tevent_req *subreq);
762
763 static void dns_udp_call_loop(struct tevent_req *subreq)
764 {
765         struct dns_udp_socket *sock = tevent_req_callback_data(subreq,
766                                       struct dns_udp_socket);
767         struct dns_udp_call *call;
768         uint8_t *buf;
769         ssize_t len;
770         int sys_errno;
771         NTSTATUS status;
772
773         call = talloc(sock, struct dns_udp_call);
774         if (call == NULL) {
775                 talloc_free(call);
776                 goto done;
777         }
778
779         len = tdgram_recvfrom_recv(subreq, &sys_errno,
780                                    call, &buf, &call->src);
781         TALLOC_FREE(subreq);
782         if (len == -1) {
783                 talloc_free(call);
784                 goto done;
785         }
786
787         call->in.data = buf;
788         call->in.length = len;
789
790         DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
791                  (long)call->in.length,
792                  tsocket_address_string(call->src, call)));
793
794         /* Call krb5 */
795         status = dns_process(sock->dns_socket->dns, call, &call->in, &call->out);
796         if (!NT_STATUS_IS_OK(status)) {
797                 talloc_free(call);
798                 DEBUG(0, ("dns_process returned %s\n", nt_errstr(status)));
799                 goto done;
800         }
801
802         subreq = tdgram_sendto_queue_send(call,
803                                           sock->dns_socket->dns->task->event_ctx,
804                                           sock->dgram,
805                                           sock->send_queue,
806                                           call->out.data,
807                                           call->out.length,
808                                           call->src);
809         if (subreq == NULL) {
810                 talloc_free(call);
811                 goto done;
812         }
813         tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call);
814
815 done:
816         subreq = tdgram_recvfrom_send(sock,
817                                       sock->dns_socket->dns->task->event_ctx,
818                                       sock->dgram);
819         if (subreq == NULL) {
820                 task_server_terminate(sock->dns_socket->dns->task,
821                                       "no memory for tdgram_recvfrom_send",
822                                       true);
823                 return;
824         }
825         tevent_req_set_callback(subreq, dns_udp_call_loop, sock);
826 }
827
828 static void dns_udp_call_sendto_done(struct tevent_req *subreq)
829 {
830         struct dns_udp_call *call = tevent_req_callback_data(subreq,
831                                        struct dns_udp_call);
832         ssize_t ret;
833         int sys_errno;
834
835         ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
836
837         /* We don't care about errors */
838
839         talloc_free(call);
840 }
841
842 /*
843   start listening on the given address
844 */
845 static NTSTATUS dns_add_socket(struct dns_server *dns,
846                                const struct model_ops *model_ops,
847                                const char *name,
848                                const char *address,
849                                uint16_t port)
850 {
851         struct dns_socket *dns_socket;
852         struct dns_udp_socket *dns_udp_socket;
853         struct tevent_req *udpsubreq;
854         NTSTATUS status;
855         int ret;
856
857         dns_socket = talloc(dns, struct dns_socket);
858         NT_STATUS_HAVE_NO_MEMORY(dns_socket);
859
860         dns_socket->dns = dns;
861
862         ret = tsocket_address_inet_from_strings(dns_socket, "ip",
863                                                 address, port,
864                                                 &dns_socket->local_address);
865         if (ret != 0) {
866                 status = map_nt_error_from_unix(errno);
867                 return status;
868         }
869
870         status = stream_setup_socket(dns->task->event_ctx,
871                                      dns->task->lp_ctx,
872                                      model_ops,
873                                      &dns_tcp_stream_ops,
874                                      "ip", address, &port,
875                                      lpcfg_socket_options(dns->task->lp_ctx),
876                                      dns_socket);
877         if (!NT_STATUS_IS_OK(status)) {
878                 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
879                          address, port, nt_errstr(status)));
880                 talloc_free(dns_socket);
881                 return status;
882         }
883
884         dns_udp_socket = talloc(dns_socket, struct dns_udp_socket);
885         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket);
886
887         dns_udp_socket->dns_socket = dns_socket;
888
889         ret = tdgram_inet_udp_socket(dns_socket->local_address,
890                                      NULL,
891                                      dns_udp_socket,
892                                      &dns_udp_socket->dgram);
893         if (ret != 0) {
894                 status = map_nt_error_from_unix(errno);
895                 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
896                          address, port, nt_errstr(status)));
897                 return status;
898         }
899
900         dns_udp_socket->send_queue = tevent_queue_create(dns_udp_socket,
901                                                          "dns_udp_send_queue");
902         NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket->send_queue);
903
904         udpsubreq = tdgram_recvfrom_send(dns_udp_socket,
905                                          dns->task->event_ctx,
906                                          dns_udp_socket->dgram);
907         NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
908         tevent_req_set_callback(udpsubreq, dns_udp_call_loop, dns_udp_socket);
909
910         return NT_STATUS_OK;
911 }
912
913 /*
914   setup our listening sockets on the configured network interfaces
915 */
916 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,
917                                        struct interface *ifaces)
918 {
919         const struct model_ops *model_ops;
920         int num_interfaces;
921         TALLOC_CTX *tmp_ctx = talloc_new(dns);
922         NTSTATUS status;
923         int i;
924
925         /* within the dns task we want to be a single process, so
926            ask for the single process model ops and pass these to the
927            stream_setup_socket() call. */
928         model_ops = process_model_startup(dns->task->event_ctx, "single");
929         if (!model_ops) {
930                 DEBUG(0,("Can't find 'single' process model_ops\n"));
931                 return NT_STATUS_INTERNAL_ERROR;
932         }
933
934         num_interfaces = iface_count(ifaces);
935
936         for (i=0; i<num_interfaces; i++) {
937                 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
938
939                 status = dns_add_socket(dns, model_ops, "dns", address, DNS_SERVICE_PORT);
940                 NT_STATUS_NOT_OK_RETURN(status);
941         }
942
943         talloc_free(tmp_ctx);
944
945         return NT_STATUS_OK;
946 }
947
948 static int dns_server_sort_zones(struct ldb_message **m1, struct ldb_message **m2)
949 {
950         const char *n1, *n2;
951         size_t l1, l2;
952
953         n1 = ldb_msg_find_attr_as_string(*m1, "name", NULL);
954         n2 = ldb_msg_find_attr_as_string(*m2, "name", NULL);
955
956         l1 = strlen(n1);
957         l2 = strlen(n2);
958
959         /* If the string lengths are not equal just sort by length */
960         if (l1 != l2) {
961                 /* If m1 is the larger zone name, return it first */
962                 return l2 - l1;
963         }
964
965         /*TODO: We need to compare DNs here, we want the DomainDNSZones first */
966         return 0;
967 }
968
969 static void dns_task_init(struct task_server *task)
970 {
971         struct dns_server *dns;
972         NTSTATUS status;
973         struct interface *ifaces;
974         int ret;
975         struct ldb_result *res;
976         struct ldb_dn *rootdn;
977         static const char * const attrs[] = { "name", NULL};
978         int i;
979
980
981         switch (lpcfg_server_role(task->lp_ctx)) {
982         case ROLE_STANDALONE:
983                 task_server_terminate(task, "dns: no DNS required in standalone configuration", false);
984                 return;
985         case ROLE_DOMAIN_MEMBER:
986                 task_server_terminate(task, "dns: no DNS required in member server configuration", false);
987                 return;
988         case ROLE_DOMAIN_CONTROLLER:
989                 /* Yes, we want a DNS */
990                 break;
991         }
992
993         load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces);
994
995         if (iface_count(ifaces) == 0) {
996                 task_server_terminate(task, "dns: no network interfaces configured", false);
997                 return;
998         }
999
1000         task_server_set_title(task, "task[dns]");
1001
1002         dns = talloc_zero(task, struct dns_server);
1003         if (dns == NULL) {
1004                 task_server_terminate(task, "dns: out of memory", true);
1005                 return;
1006         }
1007
1008         dns->task = task;
1009
1010         dns->samdb = samdb_connect(dns, dns->task->event_ctx, dns->task->lp_ctx,
1011                               system_session(dns->task->lp_ctx), 0);
1012         if (!dns->samdb) {
1013                 task_server_terminate(task, "dns: samdb_connect failed", true);
1014                 return;
1015         }
1016
1017         rootdn = ldb_dn_new(dns, dns->samdb, "");
1018         if (rootdn == NULL) {
1019                 task_server_terminate(task, "dns: out of memory", true);
1020                 return;
1021         }
1022
1023         // TODO: this search does not work against windows
1024         ret = dsdb_search(dns->samdb, dns, &res, rootdn, LDB_SCOPE_SUBTREE,
1025                           attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(objectClass=dnsZone)");
1026         if (ret != LDB_SUCCESS) {
1027                 task_server_terminate(task,
1028                                       "dns: failed to look up root DNS zones",
1029                                       true);
1030                 return;
1031         }
1032
1033         TYPESAFE_QSORT(res->msgs, res->count, dns_server_sort_zones);
1034
1035         for (i=0; i < res->count; i++) {
1036                 struct dns_server_zone *z;
1037
1038                 z = talloc_zero(dns, struct dns_server_zone);
1039                 if (z == NULL) {
1040                 }
1041
1042                 z->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
1043                 z->dn = talloc_move(z, &res->msgs[i]->dn);
1044
1045                 DLIST_ADD_END(dns->zones, z, NULL);
1046         }
1047
1048         status = dns_startup_interfaces(dns, task->lp_ctx, ifaces);
1049         if (!NT_STATUS_IS_OK(status)) {
1050                 task_server_terminate(task, "dns failed to setup interfaces", true);
1051                 return;
1052         }
1053 }
1054
1055 NTSTATUS server_service_dns_init(void)
1056 {
1057         return register_server_service("dns", dns_task_init);
1058 }