OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / pluto / dnskey.c
1 /* Find public key in DNS
2  * Copyright (C) 2000-2002  D. Hugh Redelmeier.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * RCSID $Id: dnskey.c,v 1.36 2002/03/23 03:33:19 dhr Exp $
15  */
16
17 #include <stdlib.h>
18 #include <stddef.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/nameser.h>
27 #include <resolv.h>
28 #include <netdb.h>      /* ??? for h_errno */
29
30 #include <freeswan.h>
31
32 #include "adns.h"       /* needs <resolv.h> */
33 #include "constants.h"
34 #include "defs.h"
35 #include "id.h"
36 #include "log.h"
37 #include "x509.h"
38 #include "connections.h"        /* needs id.h */
39 #include "preshared.h"      /* needs connections.h */
40 #include "dnskey.h"
41 #include "packet.h"
42 #include "timer.h"
43
44
45 /* ADNS stuff */
46
47 int adns_qfd = NULL_FD, /* file descriptor for sending queries to adns */
48     adns_afd = NULL_FD; /* file descriptor for receiving answers from adns */
49 static pid_t adns_pid = 0;
50 const char *pluto_adns_option = NULL;   /* path from --pluto_adns */
51
52 void
53 init_adns(void)
54 {
55 #if 0
56     const char *adns_path = pluto_adns_option;
57     static const char adns_name[] = "_pluto_adns";
58     char adns_path_space[4096]; /* plenty long? */
59     int qfds[2];
60     int afds[2];
61     char qfd_str[10];
62     char afd_str[10];
63
64     /* find a pathname to the ADNS program */
65     if (adns_path == NULL)
66     {
67         /* pathname was not specified as an option: build it.
68          * First, figure out the directory to be used.
69          */
70         const char *ipsec_dir = getenv("IPSEC_DIR");
71         ssize_t n;
72
73         if (ipsec_dir != NULL)
74         {
75             /* IPSEC_DIR specifies the directory */
76             n = strlen(ipsec_dir);
77             if ((size_t)n <= sizeof(adns_path_space) - sizeof(adns_name))
78             {
79                 strcpy(adns_path_space, ipsec_dir);
80                 if (n > 0 && adns_path_space[n -1] != '/')
81                     adns_path_space[n++] = '/';
82             }
83         }
84         else
85         {
86             /* The program will be in the same directory as Pluto,
87              * so we use the sympolic link /proc/self/exe to
88              * tell us of the path prefix.
89              */
90             n = readlink("/proc/self/exe", adns_path_space, sizeof(adns_path_space));
91
92             if (n < 0)
93                 exit_log_errno((e
94                     , "readlink(\"/proc/self/exe\") failed in init_adns()"));
95
96         }
97
98         if ((size_t)n > sizeof(adns_path_space) - sizeof(adns_name))
99             exit_log("path to %s is too long", adns_name);
100
101         while (n > 0 && adns_path_space[n - 1] != '/')
102             n--;
103
104         strcpy(adns_path_space + n, adns_name);
105         adns_path = adns_path_space;
106     }
107     if (access(adns_path, X_OK) < 0)
108         exit_log_errno((e, "%s missing or not executable", adns_path));
109
110
111     if (pipe(qfds) != 0 || pipe(afds) != 0)
112         exit_log_errno((e, "pipe(2) failed in init_adns()"));
113
114     snprintf(qfd_str, sizeof(qfd_str), "%d", qfds[0]);
115     snprintf(afd_str, sizeof(afd_str), "%d", afds[1]);
116
117 #ifdef __uClinux__ 
118     adns_pid = vfork();
119 #else
120     adns_pid = fork();
121 #endif 
122     switch (adns_pid)
123     {
124     case -1:
125         exit_log_errno((e, "fork() failed in init_adns()"));
126
127     case 0:
128         /* child */
129         {
130             
131             close(qfds[1]);
132             close(afds[0]);
133             
134 #ifdef DEBUG
135             /* this isn't elegantly covered by our macros */
136             if (cur_debugging & DBG_DNS)
137                 execlp(adns_path, adns_name, "-d", qfd_str, afd_str, NULL);
138             else
139                 execlp(adns_path, adns_name, qfd_str, afd_str, NULL);
140 #else
141             execlp(adns_path, adns_name, qfd_str, afd_str, NULL);
142 #endif
143 #ifdef __uClinux__
144             _exit(1);
145 #else
146             exit_log_errno((e, "execlp of %s failed", adns_path));
147 #endif
148         }
149
150     default:
151         /* parent */
152         close(qfds[0]);
153         adns_qfd = qfds[1];
154         adns_afd = afds[0];
155         close(afds[1]);
156         break;
157     }
158 #endif
159 }
160
161 void
162 stop_adns(void)
163 {
164     close_any(adns_qfd);
165     close_any(adns_afd);
166     if (adns_pid != 0)
167     {
168         int status;
169         pid_t p = waitpid(adns_pid, &status, 0);
170
171         if (p == -1)
172         {
173             log_errno((e, "waitpid for ADNS process failed"));
174         }
175         else if (WIFEXITED(status))
176         {
177             if (WEXITSTATUS(status) != 0)
178                 log("ADNS process exited with status %d"
179                     , (int) WEXITSTATUS(status));
180         }
181         else if (WIFSIGNALED(status))
182         {
183             log("ADNS process terminated by signal %d", (int)WTERMSIG(status));
184         }
185         else
186         {
187             log("wait for end of ADNS process returned odd status 0x%x\n"
188                 , status);
189         }
190     }
191 }
192
193
194
195 /* tricky macro to pass any hot potato */
196 #define TRY(x)  { err_t ugh = x; if (ugh != NULL) return ugh; }
197
198
199 /* structure of Query Reply (RFC 1035 4.1.1):
200  *
201  *  +---------------------+
202  *  |        Header       |
203  *  +---------------------+
204  *  |       Question      | the question for the name server
205  *  +---------------------+
206  *  |        Answer       | RRs answering the question
207  *  +---------------------+
208  *  |      Authority      | RRs pointing toward an authority
209  *  +---------------------+
210  *  |      Additional     | RRs holding additional information
211  *  +---------------------+
212  */
213
214 /* Header section format (as modified by RFC 2535 6.1):
215  *                                  1  1  1  1  1  1
216  *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
217  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
218  *  |                      ID                       |
219  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
220  *  |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
221  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
222  *  |                    QDCOUNT                    |
223  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
224  *  |                    ANCOUNT                    |
225  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
226  *  |                    NSCOUNT                    |
227  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
228  *  |                    ARCOUNT                    |
229  *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
230  */
231 struct qr_header {
232     u_int16_t   id;     /* 16-bit identifier to match query */
233
234     u_int16_t   stuff;  /* packed crud: */
235
236 #define QRS_QR  0x8000  /* QR: on if this is a response */
237
238 #define QRS_OPCODE_SHIFT        11  /* OPCODE field */
239 #define QRS_OPCODE_MASK 0xF
240 #define QRSO_QUERY      0   /* standard query */
241 #define QRSO_IQUERY     1   /* inverse query */
242 #define QRSO_STATUS     2   /* server status request query */
243
244 #define QRS_AA 0x0400   /* AA: on if Authoritative Answer */
245 #define QRS_TC 0x0200   /* TC: on if truncation happened */
246 #define QRS_RD 0x0100   /* RD: on if recursion desired */
247 #define QRS_RA 0x0080   /* RA: on if recursion available */
248 #define QRS_Z  0x0040   /* Z: reserved; must be zero */
249 #define QRS_AD 0x0020   /* AD: on if authentic data (RFC 2535) */
250 #define QRS_CD 0x0010   /* AD: on if checking disabled (RFC 2535) */
251
252 #define QRS_RCODE_SHIFT 0 /* RCODE field: response code */
253 #define QRS_RCODE_MASK  0xF
254 #define QRSR_OK     0
255
256
257     u_int16_t qdcount;      /* number of entries in question section */
258     u_int16_t ancount;      /* number of resource records in answer section */
259     u_int16_t nscount;      /* number of name server resource records in authority section */
260     u_int16_t arcount;      /* number of resource records in additional records section */
261 };
262
263 static field_desc qr_header_fields[] = {
264     { ft_nat, 16/BITS_PER_BYTE, "ID", NULL },
265     { ft_nat, 16/BITS_PER_BYTE, "stuff", NULL },
266     { ft_nat, 16/BITS_PER_BYTE, "QD Count", NULL },
267     { ft_nat, 16/BITS_PER_BYTE, "Answer Count", NULL },
268     { ft_nat, 16/BITS_PER_BYTE, "Authority Count", NULL },
269     { ft_nat, 16/BITS_PER_BYTE, "Additional Count", NULL },
270     { ft_end, 0, NULL, NULL }
271 };
272
273 static struct_desc qr_header_desc = {
274     "Query Response Header",
275     qr_header_fields,
276     sizeof(struct qr_header)
277 };
278
279 /* Messages for codes in RCODE (see RFC 1035 4.1.1) */
280 static const err_t rcode_text[QRS_RCODE_MASK + 1] = {
281     NULL,   /* not an error */
282     "Format error - The name server was unable to interpret the query",
283     "Server failure - The name server was unable to process this query"
284         " due to a problem with the name server",
285     "Name Error - Meaningful only for responses from an authoritative name"
286         " server, this code signifies that the domain name referenced in"
287         " the query does not exist",
288     "Not Implemented - The name server does not support the requested"
289         " kind of query",
290     "Refused - The name server refuses to perform the specified operation"
291         " for policy reasons",
292     /* the rest are reserved for future use */
293     };
294
295 static const char *
296 rr_typename(int type)
297 {
298     switch (type)
299     {
300     case T_TXT:
301         return "TXT";
302     case T_KEY:
303         return "KEY";
304     default:
305         return "???";
306     }
307 }
308
309 /* throw away a possibly compressed domain name */
310
311 static err_t
312 eat_name(pb_stream *pbs)
313 {
314     u_char name_buf[NS_MAXDNAME + 2];
315     u_char *ip = pbs->cur;
316     unsigned oi = 0;
317     unsigned jump_count = 0;
318
319     for (;;)
320     {
321         u_int8_t b;
322
323         if (ip >= pbs->roof)
324             return "ran out of message while skipping domain name";
325
326         b = *ip++;
327         if (jump_count == 0)
328             pbs->cur = ip;
329
330         if (b == 0)
331             break;
332
333         switch (b & 0xC0)
334         {
335             case 0x00:
336                 /* we grab the next b characters */
337                 if (oi + b > NS_MAXDNAME)
338                     return "domain name too long";
339
340                 if (pbs->roof - ip <= b)
341                     return "domain name falls off end of message";
342
343                 if (oi != 0)
344                     name_buf[oi++] = '.';
345
346                 memcpy(name_buf + oi, ip, b);
347                 oi += b;
348                 ip += b;
349                 if (jump_count == 0)
350                     pbs->cur = ip;
351                 break;
352
353             case 0xC0:
354                 {
355                     unsigned ix;
356
357                     if (ip >= pbs->roof)
358                         return "ran out of message in middle of compressed domain name";
359
360                     ix = ((b & ~0xC0u) << 8) | *ip++;
361                     if (jump_count == 0)
362                         pbs->cur = ip;
363
364                     if (ix >= pbs_room(pbs))
365                         return "impossible compressed domain name";
366
367                     /* Avoid infinite loop.
368                      * There can be no more jumps than there are bytes
369                      * in the packet.  Not a tight limit, but good enough.
370                      */
371                     jump_count++;
372                     if (jump_count > pbs_room(pbs))
373                         return "loop in compressed domain name";
374
375                     ip = pbs->start + ix;
376                 }
377                 break;
378
379             default:
380                 return "invalid code in label";
381         }
382     }
383
384     name_buf[oi++] = '\0';
385
386     DBG(DBG_DNS, DBG_log("skipping name %s", name_buf));
387
388     return NULL;
389 }
390
391 static err_t
392 eat_name_helpfully(pb_stream *pbs, const char *context)
393 {
394     err_t ugh = eat_name(pbs);
395
396     return ugh == NULL? ugh
397         : builddiag("malformed name within DNS record of %s: %s", context, ugh);
398 }
399
400 /* non-variable part of 4.1.2 Question Section entry:
401  *                                 1  1  1  1  1  1
402  *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
403  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
404  * |                                               |
405  * /                     QNAME                     /
406  * /                                               /
407  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
408  * |                     QTYPE                     |
409  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
410  * |                     QCLASS                    |
411  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
412  */
413
414 struct qs_fixed {
415     u_int16_t qtype;
416     u_int16_t qclass;
417 };
418
419 static field_desc qs_fixed_fields[] = {
420     { ft_loose_enum, 16/BITS_PER_BYTE, "QTYPE", &rr_qtype_names },
421     { ft_loose_enum, 16/BITS_PER_BYTE, "QCLASS", &rr_class_names },
422     { ft_end, 0, NULL, NULL }
423 };
424
425 static struct_desc qs_fixed_desc = {
426     "Question Section entry fixed part",
427     qs_fixed_fields,
428     sizeof(struct qs_fixed)
429 };
430
431 /* 4.1.3. Resource record format:
432  *                                 1  1  1  1  1  1
433  *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
434  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
435  * |                                               |
436  * /                                               /
437  * /                      NAME                     /
438  * |                                               |
439  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
440  * |                      TYPE                     |
441  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
442  * |                     CLASS                     |
443  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
444  * |                      TTL                      |
445  * |                                               |
446  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
447  * |                   RDLENGTH                    |
448  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
449  * /                     RDATA                     /
450  * /                                               /
451  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
452  */
453
454 struct rr_fixed {
455     u_int16_t type;
456     u_int16_t class;
457     u_int32_t ttl;      /* actually signed */
458     u_int16_t rdlength;
459 };
460
461
462 static field_desc rr_fixed_fields[] = {
463     { ft_loose_enum, 16/BITS_PER_BYTE, "type", &rr_type_names },
464     { ft_loose_enum, 16/BITS_PER_BYTE, "class", &rr_class_names },
465     { ft_nat, 32/BITS_PER_BYTE, "TTL", NULL },
466     { ft_nat, 16/BITS_PER_BYTE, "RD length", NULL },
467     { ft_end, 0, NULL, NULL }
468 };
469
470 static struct_desc rr_fixed_desc = {
471     "Resource Record fixed part",
472     rr_fixed_fields,
473     /* note: following is tricky: avoids padding problems */
474     offsetof(struct rr_fixed, rdlength) + sizeof(u_int16_t)
475 };
476
477 /* RFC 1035 3.3.14: TXT RRs have text in the RDATA field.
478  * It is in the form of a sequence of <character-string>s as described in 3.3.
479  * unpack_txt_rdata() deals with this peculiar representation.
480  */
481
482 /* RFC 2535 3.1 KEY RDATA format:
483  *
484  *                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
485  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
486  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487  * |             flags             |    protocol   |   algorithm   |
488  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
489  * |                                                               /
490  * /                          public key                           /
491  * /                                                               /
492  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
493  */
494
495 struct key_rdata {
496     u_int16_t flags;
497     u_int8_t protocol;
498     u_int8_t algorithm;
499 };
500
501 static field_desc key_rdata_fields[] = {
502     { ft_nat, 16/BITS_PER_BYTE, "flags", NULL },
503     { ft_nat, 8/BITS_PER_BYTE, "protocol", NULL },
504     { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL },
505     { ft_end, 0, NULL, NULL }
506 };
507
508 static struct_desc key_rdata_desc = {
509     "KEY RR RData fixed part",
510     key_rdata_fields,
511     sizeof(struct key_rdata)
512 };
513
514 /* RFC 2535 4.1 SIG RDATA format:
515  *
516  *                      1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
517  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
518  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519  * |        type covered           |  algorithm    |     labels    |
520  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521  * |                         original TTL                          |
522  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523  * |                      signature expiration                     |
524  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525  * |                      signature inception                      |
526  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
527  * |            key  tag           |                               |
528  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+         signer's name         +
529  * |                                                               /
530  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
531  * /                                                               /
532  * /                            signature                          /
533  * /                                                               /
534  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
535  */
536
537 struct sig_rdata {
538     u_int16_t type_covered;
539     u_int8_t algorithm;
540     u_int8_t labels;
541     u_int32_t original_ttl;
542     u_int32_t sig_expiration;
543     u_int32_t sig_inception;
544     u_int16_t key_tag;
545 };
546
547 static field_desc sig_rdata_fields[] = {
548     { ft_nat, 16/BITS_PER_BYTE, "type_covered", NULL},
549     { ft_nat, 8/BITS_PER_BYTE, "algorithm", NULL},
550     { ft_nat, 8/BITS_PER_BYTE, "labels", NULL},
551     { ft_nat, 32/BITS_PER_BYTE, "original ttl", NULL},
552     { ft_nat, 32/BITS_PER_BYTE, "sig expiration", NULL},
553     { ft_nat, 32/BITS_PER_BYTE, "sig inception", NULL},
554     { ft_nat, 16/BITS_PER_BYTE, "key tag", NULL},
555     { ft_end, 0, NULL, NULL }
556 };
557
558 static struct_desc sig_rdata_desc = {
559     "SIG RR RData fixed part",
560     sig_rdata_fields,
561     sizeof(struct sig_rdata)
562 };
563
564 /****************************************************************/
565
566 static err_t
567 build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
568 , const struct id *id
569 , const char *typename USED_BY_DEBUG)
570 {
571     /* note: all end in "." to suppress relative searches */
572     switch (id->kind)
573     {
574     case ID_IPV4_ADDR:
575     {
576         /* XXX: this is really ugly and only temporary until addrtot can
577          *      generate the correct format
578          */
579         const unsigned char *b;
580         size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
581
582         passert(bl == 4);
583         snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
584             , b[3], b[2], b[1], b[0]);
585         break;
586     }
587
588     case ID_IPV6_ADDR:
589     {
590         /* ??? is this correct? */
591         const unsigned char *b;
592         size_t bl;
593         u_char *op = name_buf;
594         static const char suffix[] = "IP6.INT.";
595
596         for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
597         {
598             if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
599                 return "IPv6 reverse name too long";
600             op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
601         }
602         strcpy(op, suffix);
603         break;
604     }
605
606     case ID_FQDN:
607         if (id->name.len > NS_MAXDNAME)
608             return "FQDN too long for domain name";
609
610         memcpy(name_buf, id->name.ptr, id->name.len);
611         strcpy(name_buf + id->name.len, ".");
612         break;
613
614     default:
615         return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
616     }
617
618     DBG(DBG_CONTROL | DBG_DNS, DBG_log("Querying DNS for %s for %s"
619         , typename, name_buf));
620     return NULL;
621 }
622
623 /* handle a key Resource Record. */
624
625 struct pubkeyrec *keys_from_dns = NULL; /* ephemeral! extracted keys */
626
627 static err_t
628 process_key_rr(u_char *ptr, size_t len
629 , bool doit     /* should we capture information? */
630 , enum dns_auth_level dns_auth_level
631 , int *goodies  /* where we count accepted RRs */
632 , const struct id *id)  /* subject of query (i.e. client) */
633 {
634     pb_stream pbs;
635     struct key_rdata kr;
636
637     if (len < sizeof(struct key_rdata))
638         return "KEY Resource Record's RD Length is too small";
639
640     init_pbs(&pbs, ptr, len, "KEY RR");
641
642     if (!in_struct(&kr, &key_rdata_desc, &pbs, NULL))
643         return "failed to get fixed part of KEY Resource Record RDATA";
644
645     if (kr.protocol == 4        /* IPSEC (RFC 2535 3.1.3) */
646     && kr.algorithm == 1        /* RSA/MD5 (RFC 2535 3.2) */
647     && (kr.flags & 0x8000) == 0 /* use for authentication (3.1.2) */
648     && (kr.flags & 0x2CF0) == 0)        /* must be zero */
649     {
650         /* we have what seems to be a tasty key */
651         (*goodies)++;
652
653         if (doit)
654         {
655             chunk_t k;
656
657             setchunk(k, pbs.cur, pbs_left(&pbs));
658             TRY(add_public_key(id, dns_auth_level, PUBKEY_ALG_RSA, &k
659                 , &keys_from_dns));
660         }
661     }
662     return NULL;
663 }
664
665
666 /* Process TXT X-IPsec-Server record, accumulating relevant ones
667  * in gateways_from_dns, a list sorted by "preference".
668  *
669  * Format of TXT record body: X-IPsec-Server ( nnn ) = iii kkk
670  *  nnn is a 16-bit unsigned integer preference
671  *  iii is @FQDN or dotted-decimal IPv4 address or colon-hex IPv6 address
672  *  kkk is an optional RSA public signing key in base 64.
673  *
674  * NOTE: we've got to be very wary of anything we find -- bad guys
675  * might have prepared it.
676  */
677
678 #define our_TXT_attr_string "X-IPsec-Server"
679 static const char our_TXT_attr[] = our_TXT_attr_string;
680
681 struct gw_info *gateways_from_dns = NULL;       /* ephemeral! */
682
683 /* unpack TXT rr RDATA into C string.
684  * A sequence of <character-string>s as described in RFC 1035 3.3.
685  * We concatenate them.  If a count is less than 255, we add a space
686  * because that looks more like the "source" version of the record.
687  */
688 static err_t
689 unpack_txt_rdata(u_char *d, size_t dlen, const u_char *s, size_t slen)
690 {
691     size_t i = 0
692         , o = 0;
693
694     while (i < slen)
695     {
696         size_t cl = s[i++];
697         int add_sp = cl < 255 && i + cl != slen;        /* reconstitute whitespace? */
698
699         if (i + cl > slen)
700             return "TXT rr RDATA representation malformed";
701
702         if (o + cl + add_sp >= dlen)
703             return "TXT rr RDATA too large";
704
705         memcpy(d + o, s + i, cl);
706         i += cl;
707         o += cl;
708         if (add_sp)
709             d[o++] = ' ';
710     }
711     d[o] = '\0';
712     if (strlen(d) != o)
713         return "TXT rr RDATA contains a NUL";
714
715     return NULL;
716 }
717
718 static err_t
719 decode_iii(u_char **pp, struct id *gw_id)
720 {
721     u_char *p = *pp + strspn(*pp, " \t");
722     u_char *e = p + strcspn(p, " \t");
723     u_char under = *e;
724
725     if (p == e)
726         return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
727
728     *e = '\0';
729     if (*p == '@')
730     {
731         /* gateway specification in this record is @FQDN */
732         err_t ugh = atoid(p, gw_id);
733
734         if (ugh != NULL)
735             return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
736                 , ugh);
737     }
738     else
739     {
740         /* gateway specification is numeric */
741         ip_address ip;
742         err_t ugh = tnatoaddr(p, e-p
743             , strchr(p, ':') == NULL? AF_INET : AF_INET6
744             , &ip);
745
746         if (ugh != NULL)
747             return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
748                 , ugh);
749
750         if (isanyaddr(&ip))
751             return "gateway address must not be 0.0.0.0 or 0::0";
752
753         iptoid(&ip, gw_id);
754     }
755
756     *e = under;
757     *pp = e + strspn(e, " \t");
758
759     return NULL;
760 }
761
762 static err_t
763 process_txt_rr(u_char *rdata, size_t rdlen
764 , bool doit     /* should we capture information? */
765 , enum dns_auth_level dns_auth_level
766 , int *goodies  /* where we count accepted RRs */
767 , const struct id *client_id    /* subject of query */
768 , const struct id *peer_id)     /* security gateway of interest, if any */
769 {
770     u_char str[2049];   /* space for unpacked RDATA */
771     u_char *p = str;
772     unsigned long pref = 0;
773     struct gw_info gi;
774
775     TRY(unpack_txt_rdata(str, sizeof(str), rdata, rdlen));
776
777     p += strspn(p, " \t");      /* ignore leading whitespace */
778
779     /* is this for us? */
780     if (strncasecmp(p, our_TXT_attr, sizeof(our_TXT_attr)-1) != 0)
781         return NULL;    /* neither interesting nor bad */
782
783     p += sizeof(our_TXT_attr) - 1;      /* ignore our attribute name */
784     p += strspn(p, " \t");      /* ignore leading whitespace */
785
786     /* decode '(' nnn ')' */
787     if (*p != '(')
788         return "X-IPsec-Server missing '('";
789
790     {
791         char *e;
792
793         p++;
794         pref = strtoul(p, &e, 0);
795         if ((u_char *)e == p)
796             return "malformed X-IPsec-Server priority";
797
798         p = e + strspn(e, " \t");
799
800         if (*p != ')')
801             return "X-IPsec-Server priority missing ')'";
802
803         p++;
804         p += strspn(p, " \t");
805
806         if (pref > 0xFFFF)
807             return "X-IPsec-Server priority larger than 0xFFFF";
808     }
809
810     /* time for '=' */
811
812     if (*p != '=')
813         return "X-IPsec-Server priority missing '='";
814
815     p++;
816     p += strspn(p, " \t");
817
818     /* Decode iii (Security Gateway ID). */
819
820     zero(&gi);  /* before first use */
821
822     TRY(decode_iii(&p, &gi.gw_id));
823
824     if (peer_id == NULL)
825     {
826         /* we don't know the peer's ID (because we are initiating
827          * and we don't know who to initiate with.
828          * So we're looking for gateway specs with an IP address
829          */
830         if (!id_is_ipaddr(&gi.gw_id))
831         {
832             DBG(DBG_DNS,
833                 {
834                     char cidb[IDTOA_BUF];
835                     char gwidb[IDTOA_BUF];
836
837                     idtoa(client_id, cidb, sizeof(cidb));
838                     idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
839                     DBG_log("TXT %s record for %s: security gateway %s;"
840                         " ignored because gateway's IP is unspecified"
841                         , our_TXT_attr, cidb, gwidb);
842                 });
843             return NULL;        /* we cannot use this record, but it isn't wrong */
844         }
845     }
846     else
847     {
848         /* We do know the peer's ID (because we are responding)
849          * So we're looking for gateway specs specifying this known ID.
850          */
851         if (!same_id(peer_id, &gi.gw_id))
852         {
853             DBG(DBG_DNS,
854                 {
855                     char cidb[IDTOA_BUF];
856                     char gwidb[IDTOA_BUF];
857                     char pidb[IDTOA_BUF];
858
859                     idtoa(client_id, cidb, sizeof(cidb));
860                     idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
861                     idtoa(peer_id, pidb, sizeof(pidb));
862                     DBG_log("TXT %s record for %s: security gateway %s;"
863                         " ignored -- looking to confirm %s as gateway"
864                         , our_TXT_attr, cidb, gwidb, pidb);
865                 });
866             return NULL;        /* we cannot use this record, but it isn't wrong */
867         }
868     }
869
870     (*goodies)++;
871
872     if (doit)
873     {
874         /* really accept gateway */
875         u_char kb[sizeof(str)]; /* plenty of space for binary form of public key */
876         chunk_t kbc;
877         struct gw_info **gwip;  /* gateway insertion point */
878
879         gi.client_id = *client_id;      /* will need to unshare_id_content */
880
881         /* decode optional key */
882
883         gi.gw_key_present = *p != '\0';
884         if (gi.gw_key_present)
885         {
886             /* kkk is base 64 encoding of key */
887             err_t ugh = ttodatav(p, 0, 64, kb, sizeof(kb), &kbc.len
888                 , diag_space, sizeof(diag_space));
889
890             if (ugh != NULL)
891                 return builddiag("malformed key data: %s", ugh);
892
893             passert(kbc.len < sizeof(kb));
894
895             kbc.ptr = kb;
896             ugh = unpack_RSA_public_key(&gi.gw_key, &kbc);
897             if (ugh != NULL)
898                 return builddiag("invalid key data: %s", ugh);
899         }
900
901         /* we're home free!  Allocate everything and add to gateways list. */
902         gi.refcnt = 1;
903         gi.pref = pref;
904         gi.dns_auth_level = dns_auth_level;
905         gi.created_time = now();
906         gi.last_tried_time = gi.last_worked_time = NO_TIME;
907
908         /* find insertion point */
909         for (gwip = &gateways_from_dns; *gwip != NULL && (*gwip)->pref < pref; gwip = &(*gwip)->next)
910             ;
911
912         DBG(DBG_DNS,
913             {
914                 char cidb[IDTOA_BUF];
915                 char gwidb[IDTOA_BUF];
916
917                 idtoa(client_id, cidb, sizeof(cidb));
918                 idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
919                 /* should print key, but it is too long */
920                 DBG_log("gateway for %s is %s"
921                     , cidb, gwidb);
922             });
923
924         gi.next = *gwip;
925         *gwip = clone_thing(gi, "gateway info");
926         unshare_id_content(&gateways_from_dns->client_id);
927     }
928
929     return NULL;
930 }
931
932 void
933 gw_addref(struct gw_info *gw)
934 {
935     if (gw != NULL)
936         gw->refcnt++;
937 }
938
939 void
940 gw_delref(struct gw_info **gwp)
941 {
942     struct gw_info *gw = *gwp;
943
944     if (gw != NULL)
945     {
946         passert(gw->refcnt != 0);
947         gw->refcnt--;
948         if (gw->refcnt == 0)
949         {
950             free_id_content(&gw->client_id);
951             free_id_content(&gw->gw_id);
952             if (gw->gw_key_present)
953                 free_RSA_public_content(&gw->gw_key);
954             gw_delref(&gw->next);
955             pfree(gw);  /* trickery could make this a tail-call */
956         }
957         *gwp = NULL;
958     }
959 }
960
961 static err_t
962 process_answer_section(pb_stream *pbs
963 , bool doit     /* should we capture information? */
964 , enum dns_auth_level *dns_auth_level
965 , u_int16_t ancount     /* number of RRs in the answer section */
966 , int type      /* type of RR of interest */
967 , const struct id *id   /* subject of query (i.e. client) */
968 , const struct id *sgw_id)      /* peer's ID */
969 {
970     unsigned c;
971     int goodies = 0;
972
973     DBG(DBG_DNS, DBG_log("*Answer Section:"));
974
975     for (c = 0; c != ancount; c++)
976     {
977         struct rr_fixed rrf;
978         size_t tail;
979
980         /* ??? do we need to match the name? */
981
982         TRY(eat_name_helpfully(pbs, "Answer Section"));
983
984         if (!in_struct(&rrf, &rr_fixed_desc, pbs, NULL))
985             return "failed to get fixed part of Answer Section Resource Record";
986
987         if (rrf.rdlength > pbs_left(pbs))
988             return "RD Length extends beyond end of message";
989
990         /* ??? should we care about ttl? */
991
992         tail = rrf.rdlength;
993
994         if (rrf.type == type && rrf.class == C_IN)
995         {
996             err_t ugh;
997
998             switch (type)
999             {
1000             case T_KEY:
1001                 ugh = process_key_rr(pbs->cur, tail, doit, *dns_auth_level
1002                     , &goodies, id);
1003                 break;
1004             case T_TXT:
1005                 ugh = process_txt_rr(pbs->cur, tail, doit, *dns_auth_level
1006                     , &goodies, id, sgw_id);
1007                 break;
1008             case T_SIG:
1009                 /* Check if SIG RR authenticates what we are learning.
1010                  * The RRset covered by a SIG must have the same owner,
1011                  * class, and type.
1012                  * For us, the class is always C_IN, so that matches.
1013                  * We decode the SIG RR's fixed part to check
1014                  * that the type_covered field matches our query type
1015                  * (this may be redundant).
1016                  * We don't check the owner (apparently this is the
1017                  * name on the record) -- we assume that it matches
1018                  * or we would not have been given this SIG in the
1019                  * Answer Section.
1020                  *
1021                  * We only look on first pass, and only if we've something
1022                  * to learn.  This cuts down on useless decoding.
1023                  */
1024                 if (!doit && *dns_auth_level == DAL_UNSIGNED)
1025                 {
1026                     struct sig_rdata sr;
1027
1028                     if (!in_struct(&sr, &sig_rdata_desc, pbs, NULL))
1029                         ugh = "failed to get fixed part of SIG Resource Record RDATA";
1030                     else if (sr.type_covered == type)
1031                         *dns_auth_level = DAL_SIGNED;
1032                 }
1033                 break;
1034             default:
1035                 ugh = builddiag("unexpected RR type %d", type);
1036                 break;
1037             }
1038             if (ugh != NULL)
1039                 return ugh;
1040         }
1041         in_raw(NULL, tail, pbs, "RR RDATA");
1042     }
1043
1044     return goodies > 0? NULL
1045         : builddiag("no suitable %s record found in DNS", rr_typename(type));
1046 }
1047
1048 /* process DNS answer -- TXT or KEY query */
1049
1050 static err_t
1051 process_dns_answer(const struct id *id  /* subject of query */
1052 , const struct id *sgw_id       /* security gw, if fixed */
1053 , u_char ans[], int anslen
1054 , int type)     /* type of record being sought */
1055 {
1056     int r;      /* all-purpose return value holder */
1057     u_int16_t c;        /* number of current RR in current answer section */
1058     pb_stream pbs;
1059     u_int8_t *ans_start;        /* saved position of answer section */
1060     struct qr_header qr_header;
1061     enum dns_auth_level dns_auth_level;
1062
1063     init_pbs(&pbs, ans, anslen, "Query Response Message");
1064
1065     /* decode and check header */
1066
1067     if (!in_struct(&qr_header, &qr_header_desc, &pbs, NULL))
1068         return "malformed header";
1069
1070     /* ID: nothing to do with us */
1071
1072     /* stuff -- lots of things */
1073     if ((qr_header.stuff & QRS_QR) == 0)
1074         return "not a response?!?";
1075
1076     if (((qr_header.stuff >> QRS_OPCODE_SHIFT) & QRS_OPCODE_MASK) != QRSO_QUERY)
1077         return "unexpected opcode";
1078
1079     /* I don't think we care about AA */
1080
1081     if (qr_header.stuff & QRS_TC)
1082         return "response truncated";
1083
1084     /* I don't think we care about RD, RA, or CD */
1085
1086     /* AD means "authentic data" */
1087     dns_auth_level = qr_header.stuff & QRS_AD? DAL_UNSIGNED : DAL_NOTSEC;
1088
1089     if (qr_header.stuff & QRS_Z)
1090         return "Z bit is not zero";
1091
1092     r = (qr_header.stuff >> QRS_RCODE_SHIFT) & QRS_RCODE_MASK;
1093     if (r != 0)
1094         return r < (int)elemsof(rcode_text)? rcode_text[r] : "unknown rcode";
1095
1096     if (qr_header.ancount == 0)
1097         return builddiag("no %s RR found by DNS", rr_typename(type));
1098
1099     /* end of header checking */
1100
1101     /* Question Section processing */
1102
1103     /* 4.1.2. Question section format:
1104      *                                 1  1  1  1  1  1
1105      *   0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
1106      * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1107      * |                                               |
1108      * /                     QNAME                     /
1109      * /                                               /
1110      * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1111      * |                     QTYPE                     |
1112      * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1113      * |                     QCLASS                    |
1114      * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1115      */
1116
1117     DBG(DBG_DNS, DBG_log("*Question Section:"));
1118
1119     for (c = 0; c != qr_header.qdcount; c++)
1120     {
1121         struct qs_fixed qsf;
1122
1123         TRY(eat_name_helpfully(&pbs, "Question Section"));
1124
1125         if (!in_struct(&qsf, &qs_fixed_desc, &pbs, NULL))
1126             return "failed to get fixed part of Question Section";
1127
1128         if (qsf.qtype != type)
1129             return "unexpected QTYPE in Question Section";
1130
1131         if (qsf.qclass != C_IN)
1132             return "unexpected QCLASS in Question Section";
1133     }
1134
1135     /* rest of sections are made up of Resource Records */
1136
1137     /* Answer Section processing -- error checking, noting T_SIG */
1138
1139     ans_start = pbs.cur;        /* remember start of answer section */
1140
1141     TRY(process_answer_section(&pbs, FALSE, &dns_auth_level
1142         ,qr_header.ancount, type, id, sgw_id));
1143
1144     /* Authority Section processing (just sanity checking) */
1145
1146     DBG(DBG_DNS, DBG_log("*Authority Section:"));
1147
1148     for (c = 0; c != qr_header.nscount; c++)
1149     {
1150         struct rr_fixed rrf;
1151         size_t tail;
1152
1153         TRY(eat_name_helpfully(&pbs, "Authority Section"));
1154
1155         if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
1156             return "failed to get fixed part of Authority Section Resource Record";
1157
1158         if (rrf.rdlength > pbs_left(&pbs))
1159             return "RD Length extends beyond end of message";
1160
1161         /* ??? should we care about ttl? */
1162
1163         tail = rrf.rdlength;
1164
1165         in_raw(NULL, tail, &pbs, "RR RDATA");
1166     }
1167
1168     /* Additional Section processing (just sanity checking) */
1169
1170     DBG(DBG_DNS, DBG_log("*Additional Section:"));
1171
1172     for (c = 0; c != qr_header.arcount; c++)
1173     {
1174         struct rr_fixed rrf;
1175         size_t tail;
1176
1177         TRY(eat_name_helpfully(&pbs, "Additional Section"));
1178
1179         if (!in_struct(&rrf, &rr_fixed_desc, &pbs, NULL))
1180             return "failed to get fixed part of Additional Section Resource Record";
1181
1182         if (rrf.rdlength > pbs_left(&pbs))
1183             return "RD Length extends beyond end of message";
1184
1185         /* ??? should we care about ttl? */
1186
1187         tail = rrf.rdlength;
1188
1189         in_raw(NULL, tail, &pbs, "RR RDATA");
1190     }
1191
1192     /* done all sections */
1193
1194     /* ??? is padding legal, or can we complain if more left in record? */
1195
1196     /* process Answer Section again -- accept contents */
1197
1198     pbs.cur = ans_start;        /* go back to start of answer section */
1199
1200     return process_answer_section(&pbs, TRUE, &dns_auth_level
1201         , qr_header.ancount, type, id, sgw_id);
1202 }
1203
1204 static int adns_in_flight = 0;  /* queries outstanding */
1205
1206 /* Start an asynchronous DNS query.
1207  *
1208  * For KEY record, the result will be a list in "keys_from_dns".
1209  * For TXT records, the result will be a list in "gateways_from_dns".
1210  *
1211  * If sgw_id is null, only consider TXT records that specify an
1212  * IP address for the gatway: we need this in the initiation case.
1213  *
1214  * If sgw_id is non-null, only consider TXT records that specify
1215  * this id as the security gatway; this is useful to the Responder
1216  * for confirming claims of gateways.
1217  *
1218  * Continuation cr gives information for continuing when the result shows up.
1219  *
1220  * Two kinds of errors must be handled: synchronous (immediate)
1221  * and asynchronous.  Synchronous errors are indicated by the returned
1222  * value of start_adns_query; in this case, the continuation will
1223  * have been freed and the continuation routine will not be called.
1224  * Asynchronous errors are indicated by the ugh parameter passed to the
1225  * continuation routine.
1226  *
1227  * After the continuation routine has completed, handle_adns_answer
1228  * will free the continuation.  The continuation routine should have
1229  * freed any axiliary resources.
1230  *
1231  * Note: in the synchronous error case, start_adns_query will have
1232  * freed the continuation; this means that the caller will have to
1233  * be very careful to release any auxiliary resources that were in
1234  * the continuation record without using the continuation record.
1235  *
1236  * Either there will be an error result passed to the continuation routine,
1237  * or the results will be in keys_from_dns or gatways_from_dns.
1238  * The result variables must by left NULL by the continutation routine.
1239  * The continuation routine is responsible for establishing and
1240  * disestablishing any logging context (whack_log_fd, cur_*).
1241  */
1242
1243 err_t
1244 start_adns_query(const struct id *id    /* domain to query */
1245 , const struct id *sgw_id       /* if non-null, any accepted gw_info must match */
1246 , int type      /* T_TXT or T_KEY, selecting rr type of interest */
1247 , cont_fn_t cont_fn
1248 , struct adns_continuation *cr)
1249 {
1250     ssize_t n;
1251     const char *typename = rr_typename(type);
1252
1253     /* Be sure that the result lists start out empty */
1254     passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1255
1256     cr->cont_fn = cont_fn;
1257     cr->id = *id;
1258     cr->sgw_specified = sgw_id != NULL;
1259     cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
1260
1261     memset(&cr->query, '\0', sizeof(cr->query));
1262     cr->query.len = sizeof(cr->query);
1263     cr->query.qmagic = ADNS_Q_MAGIC;
1264     cr->query.continuation = cr;
1265
1266     {
1267         err_t ugh = build_dns_name(cr->query.name_buf, id, typename);
1268
1269         if (ugh != NULL)
1270         {
1271             release_adns_continuation(cr);
1272             return ugh;
1273         }
1274     }
1275
1276     cr->query.type = type;
1277
1278     /* write out query, perhaps a piece at a time */
1279     n = 0;
1280     do {
1281         ssize_t m = write(adns_qfd
1282             , (unsigned char *)&cr->query + n, sizeof(cr->query) - n);
1283
1284         if (m == -1)
1285         {
1286             if (errno != EINTR)
1287             {
1288                 log_errno((e, "error writing query to adns"));
1289                 /* ??? how can we recover? */
1290             }
1291         }
1292         else
1293         {
1294             n += m;
1295         }
1296     } while (n != sizeof(cr->query));
1297
1298     unshare_id_content(&cr->id);
1299     unshare_id_content(&cr->sgw_id);
1300
1301     adns_in_flight++;
1302
1303     return NULL;
1304 }
1305
1306 void
1307 handle_adns_answer(void)
1308 {
1309     static size_t aalen = 0;    /* bytes in answer buffer */
1310     static struct adns_answer a;
1311     ssize_t n;
1312
1313     passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1314     passert(aalen < sizeof(a));
1315     n = read(adns_afd, (unsigned char *)&a + aalen, sizeof(a) - aalen);
1316
1317     if (n < 0)
1318     {
1319         if (errno != EINTR)
1320         {
1321             log_errno((e, "error reading answer from adns"));
1322             /* ??? how can we recover? */
1323         }
1324         n = 0;  /* now n reflects amount read */
1325     }
1326     else if (n == 0)
1327     {
1328         /* EOF */
1329         if (adns_in_flight != 0)
1330         {
1331             log("EOF from adns with %d queries outstanding", adns_in_flight);
1332             /* ??? how can we recover? */
1333         }
1334         if (aalen != 0)
1335         {
1336             log("EOF from adns with %lu bytes of a partial answer outstanding"
1337                 , (unsigned long)aalen);
1338             /* ??? how can we recover? */
1339         }
1340         stop_adns();
1341     }
1342     else
1343     {
1344         passert(adns_in_flight > 0);
1345     }
1346
1347     aalen += n;
1348
1349     while (aalen >= offsetof(struct adns_answer, ans) && aalen >= a.len)
1350     {
1351         /* we've got a tasty answer -- process it */
1352         err_t ugh;
1353         struct adns_continuation *cr = a.continuation;
1354         const char *typename = rr_typename(cr->query.type);
1355         const char *name_buf = cr->query.name_buf;
1356
1357         adns_in_flight--;
1358         if (a.result == -1)
1359         {
1360             /* newer resolvers support statp->res_h_errno as well as h_errno.
1361              * That might be better, but older resolvers don't.
1362              * See resolver(3), if you have it.
1363              * The undocumented(!) h_errno values are defined in
1364              * /usr/include/netdb.h.
1365              */
1366             switch (a.h_errno_val)
1367             {
1368             case NO_DATA:
1369                 ugh = builddiag("no %s record for %s", typename, name_buf);
1370                 break;
1371             case HOST_NOT_FOUND:
1372                 ugh = builddiag("no host %s for %s record", name_buf, typename);
1373                 break;
1374             default:
1375                 ugh = builddiag("failure querying DNS for %s of %s: %s"
1376                     , typename, name_buf, hstrerror(a.h_errno_val));
1377                 break;
1378             }
1379         }
1380         else if (a.result > (int) sizeof(a.ans))
1381         {
1382             ugh = builddiag("(INTERNAL ERROR) answer too long (%ld) for buffer"
1383                 , (long)a.result);
1384         }
1385         else
1386         {
1387             ugh = process_dns_answer(&cr->id
1388                 , cr->sgw_specified? &cr->sgw_id : NULL
1389                 , a.ans, a.result, cr->query.type);
1390             if (ugh != NULL)
1391                 ugh = builddiag("failure processing %s record of DNS answer for %s: %s"
1392                     , typename, name_buf, ugh);
1393         }
1394         DBG(DBG_RAW | DBG_CRYPT | DBG_PARSING | DBG_CONTROL | DBG_DNS,
1395             DBG_log(BLANK_FORMAT);
1396             if (ugh == NULL)
1397                 DBG_log("asynch DNS answer for %s of %s", typename, name_buf);
1398             else
1399                 DBG_log("asynch DNS answer %s", ugh);
1400             );
1401
1402         passert(GLOBALS_ARE_RESET());
1403         cr->cont_fn(cr, ugh);
1404         reset_globals();
1405         release_adns_continuation(cr);
1406
1407         /* shift out answer that we've consumed */
1408         aalen -= a.len;
1409         memmove((unsigned char *)&a, (unsigned char *)&a + a.len, aalen);
1410     }
1411     passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1412 }
1413
1414 void
1415 release_adns_continuation(struct adns_continuation *cr)
1416 {
1417     passert(gateways_from_dns == NULL && keys_from_dns == NULL);
1418     unshare_id_content(&cr->id);
1419     unshare_id_content(&cr->sgw_id);
1420     pfree(cr);
1421 }