0935928dc2aaab18686020a37f55ec13a9b4944d
[obnox/samba/samba-obnox.git] / source4 / libcli / resolve / dns_ex.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    async getaddrinfo()/dns_lookup() name resolution module
5
6    Copyright (C) Andrew Tridgell 2005
7    Copyright (C) Stefan Metzmacher 2008
8    Copyright (C) Matthieu Patou 2011
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /*
25   this module uses a fork() per getaddrinfo() or dns_looup() call.
26   At first that might seem crazy, but it is actually very fast,
27   and solves many of the tricky problems of keeping a child
28   hanging around in a librar (like what happens when the parent forks).
29   We use a talloc destructor to ensure that the child is cleaned up
30   when we have finished with this name resolution.
31 */
32
33 #include "includes.h"
34 #include "lib/events/events.h"
35 #include "system/network.h"
36 #include "system/filesys.h"
37 #include "lib/socket/socket.h"
38 #include "libcli/composite/composite.h"
39 #include "librpc/gen_ndr/ndr_nbt.h"
40 #include "libcli/resolve/resolve.h"
41 #include "lib/util/util_net.h"
42 #include "lib/addns/dnsquery.h"
43 #include "lib/addns/dns.h"
44 #include <arpa/nameser.h>
45 #include <resolv.h>
46
47 struct dns_ex_state {
48         bool do_fallback;
49         uint32_t flags;
50         uint16_t port;
51         struct nbt_name name;
52         struct socket_address **addrs;
53         char **names;
54         pid_t child;
55         int child_fd;
56         struct tevent_fd *fde;
57         struct tevent_context *event_ctx;
58 };
59
60 /*
61   kill off a wayward child if needed. This allows us to stop an async
62   name resolution without leaving a potentially blocking call running
63   in a child
64 */
65 static int dns_ex_destructor(struct dns_ex_state *state)
66 {
67         int status;
68
69         kill(state->child, SIGTERM);
70         if (waitpid(state->child, &status, WNOHANG) == 0) {
71                 kill(state->child, SIGKILL);
72                 waitpid(state->child, &status, 0);
73         }
74
75         return 0;
76 }
77
78 struct dns_records_container {
79         char **list;
80         uint32_t count;
81 };
82
83 static int reply_to_addrs(TALLOC_CTX *mem_ctx, uint32_t *a_num,
84                           char ***cur_addrs, uint32_t total,
85                           struct dns_request *reply, int port)
86 {
87         char addrstr[INET6_ADDRSTRLEN];
88         struct dns_rrec *rr;
89         char **addrs;
90         uint32_t i;
91         const char *addr;
92
93         /* at most we over-allocate here, but not by much */
94         addrs = talloc_realloc(mem_ctx, *cur_addrs, char *,
95                                 total + reply->num_answers);
96         if (!addrs) {
97                 return 0;
98         }
99         *cur_addrs = addrs;
100
101         for (i = 0; i < reply->num_answers; i++) {
102                 rr = reply->answers[i];
103
104                 /* we are only interested in the IN class */
105                 if (rr->r_class != DNS_CLASS_IN) {
106                         continue;
107                 }
108
109                 if (rr->type == QTYPE_NS) {
110                         /*
111                          * After the record for NS will come the A or AAAA
112                          * record of the NS.
113                          */
114                         break;
115                 }
116
117                 /* verify we actually have a record here */
118                 if (!rr->data) {
119                         continue;
120                 }
121
122                 /* we are only interested in A and AAAA records */
123                 switch (rr->type) {
124                 case QTYPE_A:
125                         addr = inet_ntop(AF_INET,
126                                          (struct in_addr *)rr->data,
127                                          addrstr, sizeof(addrstr));
128                         if (addr == NULL) {
129                                 continue;
130                         }
131                         break;
132                 case QTYPE_AAAA:
133 #ifdef HAVE_IPV6
134                         addr = inet_ntop(AF_INET6,
135                                          (struct in6_addr *)rr->data,
136                                          addrstr, sizeof(addrstr));
137 #else
138                         addr = NULL;
139 #endif
140                         if (addr == NULL) {
141                                 continue;
142                         }
143                         break;
144                 default:
145                         continue;
146                 }
147
148                 addrs[total] = talloc_asprintf(addrs, "%s@%u/%s",
149                                                 addrstr, port,
150                                                 rr->name->pLabelList->label);
151                 if (addrs[total]) {
152                         total++;
153                         if (rr->type == QTYPE_A) {
154                                 (*a_num)++;
155                         }
156                 }
157         }
158
159         return total;
160 }
161
162 static DNS_ERROR dns_lookup(TALLOC_CTX *mem_ctx, const char* name,
163                             uint16_t q_type, struct dns_request **reply)
164 {
165         int len, rlen;
166         uint8_t *answer;
167         bool loop;
168         struct dns_buffer buf;
169         DNS_ERROR err;
170
171         /* give space for a good sized answer by default */
172         answer = NULL;
173         len = 1500;
174         do {
175                 answer = talloc_realloc(mem_ctx, answer, uint8_t, len);
176                 if (!answer) {
177                         return ERROR_DNS_NO_MEMORY;
178                 }
179                 rlen = res_search(name, DNS_CLASS_IN, q_type, answer, len);
180                 if (rlen == -1) {
181                         if (len >= 65535) {
182                                 return ERROR_DNS_SOCKET_ERROR;
183                         }
184                         /* retry once with max packet size */
185                         len = 65535;
186                         loop = true;
187                 } else if (rlen > len) {
188                         len = rlen;
189                         loop = true;
190                 } else {
191                         loop = false;
192                 }
193         } while(loop);
194
195         buf.data = answer;
196         buf.size = rlen;
197         buf.offset = 0;
198         buf.error = ERROR_DNS_SUCCESS;
199
200         err = dns_unmarshall_request(mem_ctx, &buf, reply);
201
202         TALLOC_FREE(answer);
203         return err;
204 }
205
206 static struct dns_records_container get_a_aaaa_records(TALLOC_CTX *mem_ctx,
207                                                         const char* name,
208                                                         int port)
209 {
210         struct dns_request *reply;
211         struct dns_records_container ret;
212         char **addrs = NULL;
213         uint32_t a_num, total;
214         uint16_t qtype;
215         TALLOC_CTX *tmp_ctx;
216         DNS_ERROR err;
217
218         memset(&ret, 0, sizeof(struct dns_records_container));
219
220         tmp_ctx = talloc_new(mem_ctx);
221         if (!tmp_ctx) {
222                 return ret;
223         }
224
225         qtype = QTYPE_AAAA;
226
227         /* this is the blocking call we are going to lots of trouble
228            to avoid them in the parent */
229         err = dns_lookup(tmp_ctx, name, qtype, &reply);
230         if (!ERR_DNS_IS_OK(err)) {
231                 qtype = QTYPE_A;
232                 err = dns_lookup(tmp_ctx, name, qtype, &reply);
233                 if (!ERR_DNS_IS_OK(err)) {
234                         goto done;
235                 }
236         }
237
238         a_num = total = 0;
239         total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total, reply, port);
240
241         if (qtype == QTYPE_AAAA && a_num == 0) {
242                 /*
243                 * DNS server didn't returned A when asked for AAAA records.
244                 * Most of the server do it, let's ask for A specificaly.
245                 */
246                 err = dns_lookup(tmp_ctx, name, QTYPE_A, &reply);
247                 if (!ERR_DNS_IS_OK(err)) {
248                         goto done;
249                 }
250
251                 total = reply_to_addrs(tmp_ctx, &a_num, &addrs, total,
252                                         reply, port);
253
254         }
255
256         if (total) {
257                 talloc_steal(mem_ctx, addrs);
258                 ret.count = total;
259                 ret.list = addrs;
260         }
261
262 done:
263         TALLOC_FREE(tmp_ctx);
264         return ret;
265 }
266
267 static struct dns_records_container get_srv_records(TALLOC_CTX *mem_ctx,
268                                                         const char* name)
269 {
270         struct dns_records_container ret;
271         char **addrs = NULL;
272         struct dns_rr_srv *dclist;
273         NTSTATUS status;
274         uint32_t total;
275         unsigned i;
276         int count;
277
278         memset(&ret, 0, sizeof(struct dns_records_container));
279         /* this is the blocking call we are going to lots of trouble
280            to avoid them in the parent */
281         status = ads_dns_lookup_srv(mem_ctx, NULL, name, &dclist, &count);
282         if (!NT_STATUS_IS_OK(status)) {
283                 return ret;
284         }
285         total = 0;
286         if (count == 0) {
287                 return ret;
288         }
289
290         /* Loop over all returned records and pick the records */
291         for (i = 0; i < count; i++) {
292                 struct dns_records_container c;
293                 const char* tmp_str;
294
295                 tmp_str = dclist[i].hostname;
296                 if (strchr(tmp_str, '.') && tmp_str[strlen(tmp_str)-1] != '.') {
297                         /* we are asking for a fully qualified name, but the
298                         name doesn't end in a '.'. We need to prevent the
299                         DNS library trying the search domains configured in
300                         resolv.conf */
301                         tmp_str = talloc_asprintf(mem_ctx, "%s.", tmp_str);
302                 }
303
304                 c = get_a_aaaa_records(mem_ctx, tmp_str, dclist[i].port);
305                 total += c.count;
306                 if (addrs == NULL) {
307                         addrs = c.list;
308                 } else {
309                         unsigned j;
310
311                         addrs = talloc_realloc(mem_ctx, addrs, char*, total);
312                         for (j=0; j < c.count; j++) {
313                                 addrs[total - j - 1] = talloc_steal(addrs, c.list[j]);
314                         }
315                 }
316         }
317
318         if (total) {
319                 ret.count = total;
320                 ret.list = addrs;
321         }
322
323         return ret;
324 }
325 /*
326   the blocking child
327 */
328 static void run_child_dns_lookup(struct dns_ex_state *state, int fd)
329 {
330         bool first;
331         bool do_srv = (state->flags & RESOLVE_NAME_FLAG_DNS_SRV);
332         struct dns_records_container c;
333         char* addrs = NULL;
334         unsigned int i;
335
336         if (strchr(state->name.name, '.') && state->name.name[strlen(state->name.name)-1] != '.') {
337                 /* we are asking for a fully qualified name, but the
338                    name doesn't end in a '.'. We need to prevent the
339                    DNS library trying the search domains configured in
340                    resolv.conf */
341                 state->name.name = talloc_strdup_append(discard_const_p(char, state->name.name),
342                                                         ".");
343         }
344
345
346         if (do_srv) {
347                 c = get_srv_records(state, state->name.name);
348         } else {
349                 c = get_a_aaaa_records(state, state->name.name, state->port);
350         }
351
352         /* This line in critical - if we return without writing to the
353          * pipe, this is the signal that the name did not exist */
354         if (c.count == 0) {
355                 goto done;
356         }
357
358         addrs = talloc_strdup(state, "");
359         if (!addrs) {
360                 goto done;
361         }
362         first = true;
363
364         for (i=0; i < c.count; i++) {
365                 addrs = talloc_asprintf_append_buffer(addrs, "%s%s",
366                                                         first?"":",",
367                                                         c.list[i]);
368                 first = false;
369         }
370
371         if (addrs) {
372                 DEBUG(11, ("Addrs = %s\n", addrs));
373                 write(fd, addrs, talloc_get_size(addrs));
374         }
375
376 done:
377         close(fd);
378 }
379
380 /*
381   the blocking child
382 */
383 static void run_child_getaddrinfo(struct dns_ex_state *state, int fd)
384 {
385         int ret;
386         struct addrinfo hints;
387         struct addrinfo *res;
388         struct addrinfo *res_list = NULL;
389         char *addrs;
390         bool first;
391
392         ZERO_STRUCT(hints);
393         hints.ai_socktype = SOCK_STREAM;
394         hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
395
396         ret = getaddrinfo(state->name.name, "0", &hints, &res_list);
397         /* try to fallback in case of error */
398         if (state->do_fallback) {
399                 switch (ret) {
400 #ifdef EAI_NODATA
401                 case EAI_NODATA:
402 #endif
403                 case EAI_FAIL:
404                         /* Linux returns EAI_NODATA on non-RFC1034-compliant names. FreeBSD returns EAI_FAIL */
405                 case EAI_NONAME:
406                         /* getaddrinfo() doesn't handle CNAME or non-RFC1034 compatible records */
407                         run_child_dns_lookup(state, fd);
408                         return;
409                 default:
410                         break;
411                 }
412         }
413         if (ret != 0) {
414                 goto done;
415         }
416
417         addrs = talloc_strdup(state, "");
418         if (!addrs) {
419                 goto done;
420         }
421         first = true;
422         for (res = res_list; res; res = res->ai_next) {
423                 char addrstr[INET6_ADDRSTRLEN];
424                 if (!print_sockaddr_len(addrstr, sizeof(addrstr), (struct sockaddr *)res->ai_addr, res->ai_addrlen)) {
425                         continue;
426                 }
427                 addrs = talloc_asprintf_append_buffer(addrs, "%s%s@%u/%s",
428                                                       first?"":",",
429                                                       addrstr,
430                                                       state->port,
431                                                       state->name.name);
432                 if (!addrs) {
433                         goto done;
434                 }
435                 first = false;
436         }
437
438         if (addrs) {
439                 write(fd, addrs, talloc_get_size(addrs));
440         }
441 done:
442         if (res_list) {
443                 freeaddrinfo(res_list);
444         }
445         close(fd);
446 }
447
448 /*
449   handle a read event on the pipe
450 */
451 static void pipe_handler(struct tevent_context *ev, struct tevent_fd *fde, 
452                          uint16_t flags, void *private_data)
453 {
454         struct composite_context *c = talloc_get_type(private_data, struct composite_context);
455         struct dns_ex_state *state = talloc_get_type(c->private_data,
456                                      struct dns_ex_state);
457         char *address;
458         uint32_t num_addrs, i;
459         char **addrs;
460         int ret;
461         int status;
462         int value = 0;
463
464         /* if we get any event from the child then we know that we
465            won't need to kill it off */
466         talloc_set_destructor(state, NULL);
467
468         if (ioctl(state->child_fd, FIONREAD, &value) != 0) {
469                 value = 8192;
470         }
471
472         address = talloc_array(state, char, value+1);
473         if (address) {
474                 /* yes, we don't care about EAGAIN or other niceities
475                    here. They just can't happen with this parent/child
476                    relationship, and even if they did then giving an error is
477                    the right thing to do */
478                 ret = read(state->child_fd, address, value);
479         } else {
480                 ret = -1;
481         }
482         if (waitpid(state->child, &status, WNOHANG) == 0) {
483                 kill(state->child, SIGKILL);
484                 waitpid(state->child, &status, 0);
485         }
486
487         if (ret <= 0) {
488                 /* The check for ret == 0 here is important, if the
489                  * name does not exist, then no bytes are written to
490                  * the pipe */
491                 DEBUG(3,("dns child failed to find name '%s' of type %s\n",
492                          state->name.name, (state->flags & RESOLVE_NAME_FLAG_DNS_SRV)?"SRV":"A"));
493                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
494                 return;
495         }
496
497         /* ensure the address looks good */
498         address[ret] = 0;
499
500         addrs = str_list_make(state, address, ",");
501         if (composite_nomem(addrs, c)) return;
502
503         num_addrs = str_list_length((const char * const *)addrs);
504
505         state->addrs = talloc_array(state, struct socket_address *,
506                                     num_addrs+1);
507         if (composite_nomem(state->addrs, c)) return;
508
509         state->names = talloc_array(state, char *, num_addrs+1);
510         if (composite_nomem(state->names, c)) return;
511
512         for (i=0; i < num_addrs; i++) {
513                 uint32_t port = 0;
514                 char *p = strrchr(addrs[i], '@');
515                 char *n;
516
517                 if (!p) {
518                         composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
519                         return;
520                 }
521
522                 *p = '\0';
523                 p++;
524
525                 n = strrchr(p, '/');
526                 if (!n) {
527                         composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
528                         return;
529                 }
530
531                 *n = '\0';
532                 n++;
533
534                 if (strcmp(addrs[i], "0.0.0.0") == 0) {
535                         composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
536                         return;
537                 }
538                 port = strtoul(p, NULL, 10);
539                 if (port > UINT16_MAX) {
540                         composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
541                         return;
542                 }
543                 state->addrs[i] = socket_address_from_strings(state->addrs,
544                                                               "ip",
545                                                               addrs[i],
546                                                               port);
547                 if (composite_nomem(state->addrs[i], c)) return;
548
549                 state->names[i] = talloc_strdup(state->names, n);
550                 if (composite_nomem(state->names[i], c)) return;
551         }
552         state->addrs[i] = NULL;
553         state->names[i] = NULL;
554
555         composite_done(c);
556 }
557
558 /*
559   getaddrinfo() or dns_lookup() name resolution method - async send
560  */
561 struct composite_context *resolve_name_dns_ex_send(TALLOC_CTX *mem_ctx,
562                                                    struct tevent_context *event_ctx,
563                                                    void *privdata,
564                                                    uint32_t flags,
565                                                    uint16_t port,
566                                                    struct nbt_name *name,
567                                                    bool do_fallback)
568 {
569         struct composite_context *c;
570         struct dns_ex_state *state;
571         int fd[2] = { -1, -1 };
572         int ret;
573
574         c = composite_create(mem_ctx, event_ctx);
575         if (c == NULL) return NULL;
576
577         if (flags & RESOLVE_NAME_FLAG_FORCE_NBT) {
578                 composite_error(c, NT_STATUS_OBJECT_NAME_NOT_FOUND);
579                 return c;
580         }
581
582         state = talloc_zero(c, struct dns_ex_state);
583         if (composite_nomem(state, c)) return c;
584         c->private_data = state;
585
586         c->status = nbt_name_dup(state, name, &state->name);
587         if (!composite_is_ok(c)) return c;
588
589         /* setup a pipe to chat to our child */
590         ret = pipe(fd);
591         if (ret == -1) {
592                 composite_error(c, map_nt_error_from_unix_common(errno));
593                 return c;
594         }
595
596         state->do_fallback = do_fallback;
597         state->flags = flags;
598         state->port = port;
599
600         state->child_fd = fd[0];
601         state->event_ctx = c->event_ctx;
602
603         /* we need to put the child in our event context so
604            we know when the dns_lookup() has finished */
605         state->fde = tevent_add_fd(c->event_ctx, c, state->child_fd, TEVENT_FD_READ,
606                                   pipe_handler, c);
607         if (composite_nomem(state->fde, c)) {
608                 close(fd[0]);
609                 close(fd[1]);
610                 return c;
611         }
612         tevent_fd_set_auto_close(state->fde);
613
614         state->child = fork();
615         if (state->child == (pid_t)-1) {
616                 composite_error(c, map_nt_error_from_unix_common(errno));
617                 return c;
618         }
619
620         if (state->child == 0) {
621                 close(fd[0]);
622                 if (state->flags & RESOLVE_NAME_FLAG_FORCE_DNS) {
623                         run_child_dns_lookup(state, fd[1]);
624                 } else {
625                         run_child_getaddrinfo(state, fd[1]);
626                 }
627                 _exit(0);
628         }
629         close(fd[1]);
630
631         /* cleanup wayward children */
632         talloc_set_destructor(state, dns_ex_destructor);
633
634         return c;
635 }
636
637 /*
638   getaddrinfo() or dns_lookup() name resolution method - recv side
639 */
640 NTSTATUS resolve_name_dns_ex_recv(struct composite_context *c, 
641                                   TALLOC_CTX *mem_ctx,
642                                   struct socket_address ***addrs,
643                                   char ***names)
644 {
645         NTSTATUS status;
646
647         status = composite_wait(c);
648
649         if (NT_STATUS_IS_OK(status)) {
650                 struct dns_ex_state *state = talloc_get_type(c->private_data,
651                                              struct dns_ex_state);
652                 *addrs = talloc_steal(mem_ctx, state->addrs);
653                 if (names) {
654                         *names = talloc_steal(mem_ctx, state->names);
655                 }
656         }
657
658         talloc_free(c);
659         return status;
660 }