xref: /freebsd-src/crypto/heimdal/lib/roken/resolve.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov  * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan
3b528cefcSMark Murray  * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray  * All rights reserved.
5b528cefcSMark Murray  *
6b528cefcSMark Murray  * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray  * modification, are permitted provided that the following conditions
8b528cefcSMark Murray  * are met:
9b528cefcSMark Murray  *
10b528cefcSMark Murray  * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray  *
13b528cefcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray  *    documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray  *
17b528cefcSMark Murray  * 3. Neither the name of the Institute nor the names of its contributors
18b528cefcSMark Murray  *    may be used to endorse or promote products derived from this software
19b528cefcSMark Murray  *    without specific prior written permission.
20b528cefcSMark Murray  *
21b528cefcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22b528cefcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24b528cefcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25b528cefcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26b528cefcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27b528cefcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28b528cefcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29b528cefcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30b528cefcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31b528cefcSMark Murray  * SUCH DAMAGE.
32b528cefcSMark Murray  */
33b528cefcSMark Murray 
34*ae771770SStanislav Sedov 
35b528cefcSMark Murray #include <config.h>
36*ae771770SStanislav Sedov 
37b528cefcSMark Murray #include "roken.h"
38b528cefcSMark Murray #ifdef HAVE_ARPA_NAMESER_H
39b528cefcSMark Murray #include <arpa/nameser.h>
40b528cefcSMark Murray #endif
41b528cefcSMark Murray #ifdef HAVE_RESOLV_H
42b528cefcSMark Murray #include <resolv.h>
43b528cefcSMark Murray #endif
44*ae771770SStanislav Sedov #ifdef HAVE_DNS_H
45*ae771770SStanislav Sedov #include <dns.h>
46*ae771770SStanislav Sedov #endif
47b528cefcSMark Murray #include "resolve.h"
48b528cefcSMark Murray 
494137ff4cSJacques Vidrine #include <assert.h>
504137ff4cSJacques Vidrine 
51c19800e8SDoug Rabson #ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */
520cadf2f4SJacques Vidrine #undef HAVE_RES_NSEARCH
53c19800e8SDoug Rabson #endif
54b528cefcSMark Murray 
55c19800e8SDoug Rabson #define DECL(X) {#X, rk_ns_t_##X}
56b528cefcSMark Murray 
57b528cefcSMark Murray static struct stot{
58b528cefcSMark Murray     const char *name;
59b528cefcSMark Murray     int type;
60b528cefcSMark Murray }stot[] = {
61c19800e8SDoug Rabson     DECL(a),
62c19800e8SDoug Rabson     DECL(aaaa),
63c19800e8SDoug Rabson     DECL(ns),
64c19800e8SDoug Rabson     DECL(cname),
65c19800e8SDoug Rabson     DECL(soa),
66c19800e8SDoug Rabson     DECL(ptr),
67c19800e8SDoug Rabson     DECL(mx),
68c19800e8SDoug Rabson     DECL(txt),
69c19800e8SDoug Rabson     DECL(afsdb),
70c19800e8SDoug Rabson     DECL(sig),
71c19800e8SDoug Rabson     DECL(key),
72c19800e8SDoug Rabson     DECL(srv),
73c19800e8SDoug Rabson     DECL(naptr),
74c19800e8SDoug Rabson     DECL(sshfp),
75c19800e8SDoug Rabson     DECL(ds),
76b528cefcSMark Murray     {NULL, 	0}
77b528cefcSMark Murray };
78b528cefcSMark Murray 
795e9cd1aeSAssar Westerlund int _resolve_debug = 0;
80b528cefcSMark Murray 
81*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_dns_string_to_type(const char * name)82*ae771770SStanislav Sedov rk_dns_string_to_type(const char *name)
83b528cefcSMark Murray {
84b528cefcSMark Murray     struct stot *p = stot;
85b528cefcSMark Murray     for(p = stot; p->name; p++)
86b528cefcSMark Murray 	if(strcasecmp(name, p->name) == 0)
87b528cefcSMark Murray 	    return p->type;
88b528cefcSMark Murray     return -1;
89b528cefcSMark Murray }
90b528cefcSMark Murray 
91*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL
rk_dns_type_to_string(int type)92*ae771770SStanislav Sedov rk_dns_type_to_string(int type)
93b528cefcSMark Murray {
94b528cefcSMark Murray     struct stot *p = stot;
95b528cefcSMark Murray     for(p = stot; p->name; p++)
96b528cefcSMark Murray 	if(type == p->type)
97b528cefcSMark Murray 	    return p->name;
98b528cefcSMark Murray     return NULL;
99b528cefcSMark Murray }
100b528cefcSMark Murray 
101*ae771770SStanislav Sedov #if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS)
102c19800e8SDoug Rabson 
103c19800e8SDoug Rabson static void
dns_free_rr(struct rk_resource_record * rr)104*ae771770SStanislav Sedov dns_free_rr(struct rk_resource_record *rr)
105c19800e8SDoug Rabson {
106c19800e8SDoug Rabson     if(rr->domain)
107c19800e8SDoug Rabson 	free(rr->domain);
108c19800e8SDoug Rabson     if(rr->u.data)
109c19800e8SDoug Rabson 	free(rr->u.data);
110c19800e8SDoug Rabson     free(rr);
111c19800e8SDoug Rabson }
112c19800e8SDoug Rabson 
113*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_free_data(struct rk_dns_reply * r)114*ae771770SStanislav Sedov rk_dns_free_data(struct rk_dns_reply *r)
115b528cefcSMark Murray {
116*ae771770SStanislav Sedov     struct rk_resource_record *rr;
117b528cefcSMark Murray     if(r->q.domain)
118b528cefcSMark Murray 	free(r->q.domain);
119b528cefcSMark Murray     for(rr = r->head; rr;){
120*ae771770SStanislav Sedov 	struct rk_resource_record *tmp = rr;
121b528cefcSMark Murray 	rr = rr->next;
122c19800e8SDoug Rabson 	dns_free_rr(tmp);
123b528cefcSMark Murray     }
124b528cefcSMark Murray     free (r);
125b528cefcSMark Murray }
126b528cefcSMark Murray 
127*ae771770SStanislav Sedov #ifndef HAVE_WINDNS
128*ae771770SStanislav Sedov 
1295bda878eSJacques Vidrine static int
parse_record(const unsigned char * data,const unsigned char * end_data,const unsigned char ** pp,struct rk_resource_record ** ret_rr)1305bda878eSJacques Vidrine parse_record(const unsigned char *data, const unsigned char *end_data,
131*ae771770SStanislav Sedov 	     const unsigned char **pp, struct rk_resource_record **ret_rr)
132b528cefcSMark Murray {
133*ae771770SStanislav Sedov     struct rk_resource_record *rr;
134*ae771770SStanislav Sedov     int type, class, ttl;
135*ae771770SStanislav Sedov     unsigned size;
1365bda878eSJacques Vidrine     int status;
1375bda878eSJacques Vidrine     char host[MAXDNAME];
1385bda878eSJacques Vidrine     const unsigned char *p = *pp;
139c19800e8SDoug Rabson 
140c19800e8SDoug Rabson     *ret_rr = NULL;
141c19800e8SDoug Rabson 
1428373020dSJacques Vidrine     status = dn_expand(data, end_data, p, host, sizeof(host));
1435bda878eSJacques Vidrine     if(status < 0)
1445bda878eSJacques Vidrine 	return -1;
1455bda878eSJacques Vidrine     if (p + status + 10 > end_data)
1465bda878eSJacques Vidrine 	return -1;
147c19800e8SDoug Rabson 
148b528cefcSMark Murray     p += status;
149b528cefcSMark Murray     type = (p[0] << 8) | p[1];
150b528cefcSMark Murray     p += 2;
151b528cefcSMark Murray     class = (p[0] << 8) | p[1];
152b528cefcSMark Murray     p += 2;
153b528cefcSMark Murray     ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
154b528cefcSMark Murray     p += 4;
155b528cefcSMark Murray     size = (p[0] << 8) | p[1];
156b528cefcSMark Murray     p += 2;
1578373020dSJacques Vidrine 
1585bda878eSJacques Vidrine     if (p + size > end_data)
1595bda878eSJacques Vidrine 	return -1;
1608373020dSJacques Vidrine 
161c19800e8SDoug Rabson     rr = calloc(1, sizeof(*rr));
162c19800e8SDoug Rabson     if(rr == NULL)
1635bda878eSJacques Vidrine 	return -1;
164c19800e8SDoug Rabson     rr->domain = strdup(host);
165c19800e8SDoug Rabson     if(rr->domain == NULL) {
166c19800e8SDoug Rabson 	dns_free_rr(rr);
1675bda878eSJacques Vidrine 	return -1;
168b528cefcSMark Murray     }
169c19800e8SDoug Rabson     rr->type = type;
170c19800e8SDoug Rabson     rr->class = class;
171c19800e8SDoug Rabson     rr->ttl = ttl;
172c19800e8SDoug Rabson     rr->size = size;
173b528cefcSMark Murray     switch(type){
174c19800e8SDoug Rabson     case rk_ns_t_ns:
175c19800e8SDoug Rabson     case rk_ns_t_cname:
176c19800e8SDoug Rabson     case rk_ns_t_ptr:
1778373020dSJacques Vidrine 	status = dn_expand(data, end_data, p, host, sizeof(host));
178b528cefcSMark Murray 	if(status < 0) {
179c19800e8SDoug Rabson 	    dns_free_rr(rr);
1805bda878eSJacques Vidrine 	    return -1;
181b528cefcSMark Murray 	}
182c19800e8SDoug Rabson 	rr->u.txt = strdup(host);
183c19800e8SDoug Rabson 	if(rr->u.txt == NULL) {
184c19800e8SDoug Rabson 	    dns_free_rr(rr);
1855bda878eSJacques Vidrine 	    return -1;
186b528cefcSMark Murray 	}
187b528cefcSMark Murray 	break;
188c19800e8SDoug Rabson     case rk_ns_t_mx:
189c19800e8SDoug Rabson     case rk_ns_t_afsdb:{
190bbd80c28SJacques Vidrine 	size_t hostlen;
191bbd80c28SJacques Vidrine 
1928373020dSJacques Vidrine 	status = dn_expand(data, end_data, p + 2, host, sizeof(host));
193b528cefcSMark Murray 	if(status < 0){
194c19800e8SDoug Rabson 	    dns_free_rr(rr);
1955bda878eSJacques Vidrine 	    return -1;
196b528cefcSMark Murray 	}
197*ae771770SStanislav Sedov 	if ((size_t)status + 2 > size) {
198c19800e8SDoug Rabson 	    dns_free_rr(rr);
1995bda878eSJacques Vidrine 	    return -1;
2008373020dSJacques Vidrine 	}
2018373020dSJacques Vidrine 
202bbd80c28SJacques Vidrine 	hostlen = strlen(host);
203c19800e8SDoug Rabson 	rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
204bbd80c28SJacques Vidrine 						hostlen);
205c19800e8SDoug Rabson 	if(rr->u.mx == NULL) {
206c19800e8SDoug Rabson 	    dns_free_rr(rr);
2075bda878eSJacques Vidrine 	    return -1;
208b528cefcSMark Murray 	}
209c19800e8SDoug Rabson 	rr->u.mx->preference = (p[0] << 8) | p[1];
210c19800e8SDoug Rabson 	strlcpy(rr->u.mx->domain, host, hostlen + 1);
211b528cefcSMark Murray 	break;
212b528cefcSMark Murray     }
213c19800e8SDoug Rabson     case rk_ns_t_srv:{
214bbd80c28SJacques Vidrine 	size_t hostlen;
2158373020dSJacques Vidrine 	status = dn_expand(data, end_data, p + 6, host, sizeof(host));
216b528cefcSMark Murray 	if(status < 0){
217c19800e8SDoug Rabson 	    dns_free_rr(rr);
2185bda878eSJacques Vidrine 	    return -1;
219b528cefcSMark Murray 	}
220*ae771770SStanislav Sedov 	if ((size_t)status + 6 > size) {
221c19800e8SDoug Rabson 	    dns_free_rr(rr);
2225bda878eSJacques Vidrine 	    return -1;
2238373020dSJacques Vidrine 	}
2248373020dSJacques Vidrine 
225bbd80c28SJacques Vidrine 	hostlen = strlen(host);
226c19800e8SDoug Rabson 	rr->u.srv =
227b528cefcSMark Murray 	    (struct srv_record*)malloc(sizeof(struct srv_record) +
228bbd80c28SJacques Vidrine 				       hostlen);
229c19800e8SDoug Rabson 	if(rr->u.srv == NULL) {
230c19800e8SDoug Rabson 	    dns_free_rr(rr);
2315bda878eSJacques Vidrine 	    return -1;
232b528cefcSMark Murray 	}
233c19800e8SDoug Rabson 	rr->u.srv->priority = (p[0] << 8) | p[1];
234c19800e8SDoug Rabson 	rr->u.srv->weight = (p[2] << 8) | p[3];
235c19800e8SDoug Rabson 	rr->u.srv->port = (p[4] << 8) | p[5];
236c19800e8SDoug Rabson 	strlcpy(rr->u.srv->target, host, hostlen + 1);
237b528cefcSMark Murray 	break;
238b528cefcSMark Murray     }
239c19800e8SDoug Rabson     case rk_ns_t_txt:{
240*ae771770SStanislav Sedov 	if(size == 0 || size < (unsigned)(*p + 1)) {
241c19800e8SDoug Rabson 	    dns_free_rr(rr);
2425bda878eSJacques Vidrine 	    return -1;
2435bda878eSJacques Vidrine 	}
244c19800e8SDoug Rabson 	rr->u.txt = (char*)malloc(*p + 1);
245c19800e8SDoug Rabson 	if(rr->u.txt == NULL) {
246c19800e8SDoug Rabson 	    dns_free_rr(rr);
2475bda878eSJacques Vidrine 	    return -1;
248b528cefcSMark Murray 	}
249c19800e8SDoug Rabson 	strncpy(rr->u.txt, (const char*)(p + 1), *p);
250c19800e8SDoug Rabson 	rr->u.txt[*p] = '\0';
251b528cefcSMark Murray 	break;
252b528cefcSMark Murray     }
253c19800e8SDoug Rabson     case rk_ns_t_key : {
2545e9cd1aeSAssar Westerlund 	size_t key_len;
255b528cefcSMark Murray 
2568373020dSJacques Vidrine 	if (size < 4) {
257c19800e8SDoug Rabson 	    dns_free_rr(rr);
2585bda878eSJacques Vidrine 	    return -1;
2598373020dSJacques Vidrine 	}
2608373020dSJacques Vidrine 
2615e9cd1aeSAssar Westerlund 	key_len = size - 4;
262c19800e8SDoug Rabson 	rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
263c19800e8SDoug Rabson 	if (rr->u.key == NULL) {
264c19800e8SDoug Rabson 	    dns_free_rr(rr);
2655bda878eSJacques Vidrine 	    return -1;
2665e9cd1aeSAssar Westerlund 	}
2675e9cd1aeSAssar Westerlund 
268c19800e8SDoug Rabson 	rr->u.key->flags     = (p[0] << 8) | p[1];
269c19800e8SDoug Rabson 	rr->u.key->protocol  = p[2];
270c19800e8SDoug Rabson 	rr->u.key->algorithm = p[3];
271c19800e8SDoug Rabson 	rr->u.key->key_len   = key_len;
272c19800e8SDoug Rabson 	memcpy (rr->u.key->key_data, p + 4, key_len);
2735e9cd1aeSAssar Westerlund 	break;
2745e9cd1aeSAssar Westerlund     }
275c19800e8SDoug Rabson     case rk_ns_t_sig : {
276bbd80c28SJacques Vidrine 	size_t sig_len, hostlen;
2775e9cd1aeSAssar Westerlund 
2785bda878eSJacques Vidrine 	if(size <= 18) {
279c19800e8SDoug Rabson 	    dns_free_rr(rr);
2805bda878eSJacques Vidrine 	    return -1;
2815bda878eSJacques Vidrine 	}
2828373020dSJacques Vidrine 	status = dn_expand (data, end_data, p + 18, host, sizeof(host));
2835e9cd1aeSAssar Westerlund 	if (status < 0) {
284c19800e8SDoug Rabson 	    dns_free_rr(rr);
2855bda878eSJacques Vidrine 	    return -1;
2865e9cd1aeSAssar Westerlund 	}
287*ae771770SStanislav Sedov 	if ((size_t)status + 18 > size) {
288c19800e8SDoug Rabson 	    dns_free_rr(rr);
2895bda878eSJacques Vidrine 	    return -1;
2908373020dSJacques Vidrine 	}
2918373020dSJacques Vidrine 
2925bda878eSJacques Vidrine 	/* the signer name is placed after the sig_data, to make it
293c19800e8SDoug Rabson            easy to free this structure; the size calculation below
2945bda878eSJacques Vidrine            includes the zero-termination if the structure itself.
2955bda878eSJacques Vidrine 	   don't you just love C?
2965bda878eSJacques Vidrine 	*/
2975bda878eSJacques Vidrine 	sig_len = size - 18 - status;
298bbd80c28SJacques Vidrine 	hostlen = strlen(host);
299c19800e8SDoug Rabson 	rr->u.sig = malloc(sizeof(*rr->u.sig)
300bbd80c28SJacques Vidrine 			      + hostlen + sig_len);
301c19800e8SDoug Rabson 	if (rr->u.sig == NULL) {
302c19800e8SDoug Rabson 	    dns_free_rr(rr);
3035bda878eSJacques Vidrine 	    return -1;
3045e9cd1aeSAssar Westerlund 	}
305c19800e8SDoug Rabson 	rr->u.sig->type           = (p[0] << 8) | p[1];
306c19800e8SDoug Rabson 	rr->u.sig->algorithm      = p[2];
307c19800e8SDoug Rabson 	rr->u.sig->labels         = p[3];
308c19800e8SDoug Rabson 	rr->u.sig->orig_ttl       = (p[4] << 24) | (p[5] << 16)
3095e9cd1aeSAssar Westerlund 	    | (p[6] << 8) | p[7];
310c19800e8SDoug Rabson 	rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
3115e9cd1aeSAssar Westerlund 	    | (p[10] << 8) | p[11];
312c19800e8SDoug Rabson 	rr->u.sig->sig_inception  = (p[12] << 24) | (p[13] << 16)
3135e9cd1aeSAssar Westerlund 	    | (p[14] << 8) | p[15];
314c19800e8SDoug Rabson 	rr->u.sig->key_tag        = (p[16] << 8) | p[17];
315c19800e8SDoug Rabson 	rr->u.sig->sig_len        = sig_len;
316c19800e8SDoug Rabson 	memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len);
317c19800e8SDoug Rabson 	rr->u.sig->signer         = &rr->u.sig->sig_data[sig_len];
318c19800e8SDoug Rabson 	strlcpy(rr->u.sig->signer, host, hostlen + 1);
3195e9cd1aeSAssar Westerlund 	break;
3205e9cd1aeSAssar Westerlund     }
3215e9cd1aeSAssar Westerlund 
322c19800e8SDoug Rabson     case rk_ns_t_cert : {
3235e9cd1aeSAssar Westerlund 	size_t cert_len;
3245e9cd1aeSAssar Westerlund 
3258373020dSJacques Vidrine 	if (size < 5) {
326c19800e8SDoug Rabson 	    dns_free_rr(rr);
3275bda878eSJacques Vidrine 	    return -1;
3288373020dSJacques Vidrine 	}
3298373020dSJacques Vidrine 
3305e9cd1aeSAssar Westerlund 	cert_len = size - 5;
331c19800e8SDoug Rabson 	rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1);
332c19800e8SDoug Rabson 	if (rr->u.cert == NULL) {
333c19800e8SDoug Rabson 	    dns_free_rr(rr);
3345bda878eSJacques Vidrine 	    return -1;
3355e9cd1aeSAssar Westerlund 	}
3365e9cd1aeSAssar Westerlund 
337c19800e8SDoug Rabson 	rr->u.cert->type      = (p[0] << 8) | p[1];
338c19800e8SDoug Rabson 	rr->u.cert->tag       = (p[2] << 8) | p[3];
339c19800e8SDoug Rabson 	rr->u.cert->algorithm = p[4];
340c19800e8SDoug Rabson 	rr->u.cert->cert_len  = cert_len;
341c19800e8SDoug Rabson 	memcpy (rr->u.cert->cert_data, p + 5, cert_len);
342c19800e8SDoug Rabson 	break;
343c19800e8SDoug Rabson     }
344c19800e8SDoug Rabson     case rk_ns_t_sshfp : {
345c19800e8SDoug Rabson 	size_t sshfp_len;
346c19800e8SDoug Rabson 
347c19800e8SDoug Rabson 	if (size < 2) {
348c19800e8SDoug Rabson 	    dns_free_rr(rr);
349c19800e8SDoug Rabson 	    return -1;
350c19800e8SDoug Rabson 	}
351c19800e8SDoug Rabson 
352c19800e8SDoug Rabson 	sshfp_len = size - 2;
353c19800e8SDoug Rabson 
354c19800e8SDoug Rabson 	rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1);
355c19800e8SDoug Rabson 	if (rr->u.sshfp == NULL) {
356c19800e8SDoug Rabson 	    dns_free_rr(rr);
357c19800e8SDoug Rabson 	    return -1;
358c19800e8SDoug Rabson 	}
359c19800e8SDoug Rabson 
360c19800e8SDoug Rabson 	rr->u.sshfp->algorithm = p[0];
361c19800e8SDoug Rabson 	rr->u.sshfp->type      = p[1];
362c19800e8SDoug Rabson 	rr->u.sshfp->sshfp_len  = sshfp_len;
363c19800e8SDoug Rabson 	memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len);
364c19800e8SDoug Rabson 	break;
365c19800e8SDoug Rabson     }
366c19800e8SDoug Rabson     case rk_ns_t_ds: {
367c19800e8SDoug Rabson 	size_t digest_len;
368c19800e8SDoug Rabson 
369c19800e8SDoug Rabson 	if (size < 4) {
370c19800e8SDoug Rabson 	    dns_free_rr(rr);
371c19800e8SDoug Rabson 	    return -1;
372c19800e8SDoug Rabson 	}
373c19800e8SDoug Rabson 
374c19800e8SDoug Rabson 	digest_len = size - 4;
375c19800e8SDoug Rabson 
376c19800e8SDoug Rabson 	rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1);
377c19800e8SDoug Rabson 	if (rr->u.ds == NULL) {
378c19800e8SDoug Rabson 	    dns_free_rr(rr);
379c19800e8SDoug Rabson 	    return -1;
380c19800e8SDoug Rabson 	}
381c19800e8SDoug Rabson 
382c19800e8SDoug Rabson 	rr->u.ds->key_tag     = (p[0] << 8) | p[1];
383c19800e8SDoug Rabson 	rr->u.ds->algorithm   = p[2];
384c19800e8SDoug Rabson 	rr->u.ds->digest_type = p[3];
385c19800e8SDoug Rabson 	rr->u.ds->digest_len  = digest_len;
386c19800e8SDoug Rabson 	memcpy (rr->u.ds->digest_data, p + 4, digest_len);
3875e9cd1aeSAssar Westerlund 	break;
3885e9cd1aeSAssar Westerlund     }
389b528cefcSMark Murray     default:
390c19800e8SDoug Rabson 	rr->u.data = (unsigned char*)malloc(size);
391c19800e8SDoug Rabson 	if(size != 0 && rr->u.data == NULL) {
392c19800e8SDoug Rabson 	    dns_free_rr(rr);
3935bda878eSJacques Vidrine 	    return -1;
394b528cefcSMark Murray 	}
395c19800e8SDoug Rabson 	if (size)
396c19800e8SDoug Rabson 	    memcpy(rr->u.data, p, size);
397b528cefcSMark Murray     }
3985bda878eSJacques Vidrine     *pp = p + size;
399c19800e8SDoug Rabson     *ret_rr = rr;
400c19800e8SDoug Rabson 
4015bda878eSJacques Vidrine     return 0;
4025bda878eSJacques Vidrine }
4035bda878eSJacques Vidrine 
4045bda878eSJacques Vidrine #ifndef TEST_RESOLVE
4055bda878eSJacques Vidrine static
4065bda878eSJacques Vidrine #endif
407*ae771770SStanislav Sedov struct rk_dns_reply*
parse_reply(const unsigned char * data,size_t len)4085bda878eSJacques Vidrine parse_reply(const unsigned char *data, size_t len)
4095bda878eSJacques Vidrine {
4105bda878eSJacques Vidrine     const unsigned char *p;
4115bda878eSJacques Vidrine     int status;
412*ae771770SStanislav Sedov     size_t i;
4135bda878eSJacques Vidrine     char host[MAXDNAME];
4145bda878eSJacques Vidrine     const unsigned char *end_data = data + len;
415*ae771770SStanislav Sedov     struct rk_dns_reply *r;
416*ae771770SStanislav Sedov     struct rk_resource_record **rr;
4175bda878eSJacques Vidrine 
4185bda878eSJacques Vidrine     r = calloc(1, sizeof(*r));
4195bda878eSJacques Vidrine     if (r == NULL)
4205bda878eSJacques Vidrine 	return NULL;
4215bda878eSJacques Vidrine 
4225bda878eSJacques Vidrine     p = data;
423c19800e8SDoug Rabson 
424c19800e8SDoug Rabson     r->h.id = (p[0] << 8) | p[1];
425c19800e8SDoug Rabson     r->h.flags = 0;
426c19800e8SDoug Rabson     if (p[2] & 0x01)
427c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG;
428c19800e8SDoug Rabson     r->h.opcode = (p[2] >> 1) & 0xf;
429c19800e8SDoug Rabson     if (p[2] & 0x20)
430c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
431c19800e8SDoug Rabson     if (p[2] & 0x40)
432c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE;
433c19800e8SDoug Rabson     if (p[2] & 0x80)
434c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED;
435c19800e8SDoug Rabson     if (p[3] & 0x01)
436c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE;
437c19800e8SDoug Rabson     if (p[3] & 0x04)
438c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
439c19800e8SDoug Rabson     if (p[3] & 0x08)
440c19800e8SDoug Rabson 	r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED;
441c19800e8SDoug Rabson     r->h.response_code = (p[3] >> 4) & 0xf;
442c19800e8SDoug Rabson     r->h.qdcount = (p[4] << 8) | p[5];
443c19800e8SDoug Rabson     r->h.ancount = (p[6] << 8) | p[7];
444c19800e8SDoug Rabson     r->h.nscount = (p[8] << 8) | p[9];
445c19800e8SDoug Rabson     r->h.arcount = (p[10] << 8) | p[11];
446c19800e8SDoug Rabson 
4475bda878eSJacques Vidrine     p += 12;
448c19800e8SDoug Rabson 
449c19800e8SDoug Rabson     if(r->h.qdcount != 1) {
4505bda878eSJacques Vidrine 	free(r);
4515bda878eSJacques Vidrine 	return NULL;
4525bda878eSJacques Vidrine     }
4535bda878eSJacques Vidrine     status = dn_expand(data, end_data, p, host, sizeof(host));
4545bda878eSJacques Vidrine     if(status < 0){
455*ae771770SStanislav Sedov 	rk_dns_free_data(r);
4565bda878eSJacques Vidrine 	return NULL;
4575bda878eSJacques Vidrine     }
4585bda878eSJacques Vidrine     r->q.domain = strdup(host);
4595bda878eSJacques Vidrine     if(r->q.domain == NULL) {
460*ae771770SStanislav Sedov 	rk_dns_free_data(r);
4615bda878eSJacques Vidrine 	return NULL;
4625bda878eSJacques Vidrine     }
4635bda878eSJacques Vidrine     if (p + status + 4 > end_data) {
464*ae771770SStanislav Sedov 	rk_dns_free_data(r);
4655bda878eSJacques Vidrine 	return NULL;
4665bda878eSJacques Vidrine     }
4675bda878eSJacques Vidrine     p += status;
4685bda878eSJacques Vidrine     r->q.type = (p[0] << 8 | p[1]);
4695bda878eSJacques Vidrine     p += 2;
4705bda878eSJacques Vidrine     r->q.class = (p[0] << 8 | p[1]);
4715bda878eSJacques Vidrine     p += 2;
4725bda878eSJacques Vidrine 
4735bda878eSJacques Vidrine     rr = &r->head;
474c19800e8SDoug Rabson     for(i = 0; i < r->h.ancount; i++) {
4755bda878eSJacques Vidrine 	if(parse_record(data, end_data, &p, rr) != 0) {
476*ae771770SStanislav Sedov 	    rk_dns_free_data(r);
4775bda878eSJacques Vidrine 	    return NULL;
4785bda878eSJacques Vidrine 	}
4795bda878eSJacques Vidrine 	rr = &(*rr)->next;
4805bda878eSJacques Vidrine     }
481c19800e8SDoug Rabson     for(i = 0; i < r->h.nscount; i++) {
4825bda878eSJacques Vidrine 	if(parse_record(data, end_data, &p, rr) != 0) {
483*ae771770SStanislav Sedov 	    rk_dns_free_data(r);
4845bda878eSJacques Vidrine 	    return NULL;
4855bda878eSJacques Vidrine 	}
4865bda878eSJacques Vidrine 	rr = &(*rr)->next;
4875bda878eSJacques Vidrine     }
488c19800e8SDoug Rabson     for(i = 0; i < r->h.arcount; i++) {
4895bda878eSJacques Vidrine 	if(parse_record(data, end_data, &p, rr) != 0) {
490*ae771770SStanislav Sedov 	    rk_dns_free_data(r);
4915bda878eSJacques Vidrine 	    return NULL;
4925bda878eSJacques Vidrine 	}
493b528cefcSMark Murray 	rr = &(*rr)->next;
494b528cefcSMark Murray     }
495b528cefcSMark Murray     *rr = NULL;
496b528cefcSMark Murray     return r;
497b528cefcSMark Murray }
498b528cefcSMark Murray 
499c19800e8SDoug Rabson #ifdef HAVE_RES_NSEARCH
500c19800e8SDoug Rabson #ifdef HAVE_RES_NDESTROY
501c19800e8SDoug Rabson #define rk_res_free(x) res_ndestroy(x)
502c19800e8SDoug Rabson #else
503c19800e8SDoug Rabson #define rk_res_free(x) res_nclose(x)
504c19800e8SDoug Rabson #endif
505c19800e8SDoug Rabson #endif
506c19800e8SDoug Rabson 
507*ae771770SStanislav Sedov #if defined(HAVE_DNS_SEARCH)
508*ae771770SStanislav Sedov #define resolve_search(h,n,c,t,r,l) \
509*ae771770SStanislav Sedov     	((int)dns_search(h,n,c,t,r,l,(struct sockaddr *)&from,&fromsize))
510*ae771770SStanislav Sedov #define resolve_free_handle(h) dns_free(h)
511*ae771770SStanislav Sedov #elif defined(HAVE_RES_NSEARCH)
512*ae771770SStanislav Sedov #define resolve_search(h,n,c,t,r,l) res_nsearch(h,n,c,t,r,l)
513*ae771770SStanislav Sedov #define resolve_free_handle(h) rk_res_free(h);
514*ae771770SStanislav Sedov #else
515*ae771770SStanislav Sedov #define resolve_search(h,n,c,t,r,l) res_search(n,c,t,r,l)
516*ae771770SStanislav Sedov #define handle 0
517*ae771770SStanislav Sedov #define resolve_free_handle(h)
5188373020dSJacques Vidrine #endif
519b528cefcSMark Murray 
520*ae771770SStanislav Sedov 
521*ae771770SStanislav Sedov static struct rk_dns_reply *
dns_lookup_int(const char * domain,int rr_class,int rr_type)522*ae771770SStanislav Sedov dns_lookup_int(const char *domain, int rr_class, int rr_type)
523*ae771770SStanislav Sedov {
524*ae771770SStanislav Sedov     struct rk_dns_reply *r;
525*ae771770SStanislav Sedov     void *reply = NULL;
526*ae771770SStanislav Sedov     int size, len;
527*ae771770SStanislav Sedov #if defined(HAVE_DNS_SEARCH)
528*ae771770SStanislav Sedov     struct sockaddr_storage from;
529*ae771770SStanislav Sedov     uint32_t fromsize = sizeof(from);
530*ae771770SStanislav Sedov     dns_handle_t handle;
531*ae771770SStanislav Sedov 
532*ae771770SStanislav Sedov     handle = dns_open(NULL);
533*ae771770SStanislav Sedov     if (handle == NULL)
534*ae771770SStanislav Sedov 	return NULL;
535*ae771770SStanislav Sedov #elif defined(HAVE_RES_NSEARCH)
536*ae771770SStanislav Sedov     struct __res_state state;
537*ae771770SStanislav Sedov     struct __res_state *handle = &state;
538*ae771770SStanislav Sedov 
539*ae771770SStanislav Sedov     memset(&state, 0, sizeof(state));
540*ae771770SStanislav Sedov     if(res_ninit(handle))
541*ae771770SStanislav Sedov 	return NULL; /* is this the best we can do? */
542*ae771770SStanislav Sedov #endif
543*ae771770SStanislav Sedov 
544*ae771770SStanislav Sedov     len = 1500;
545*ae771770SStanislav Sedov     while(1) {
546c19800e8SDoug Rabson 	if (reply) {
547c19800e8SDoug Rabson 	    free(reply);
548c19800e8SDoug Rabson 	    reply = NULL;
549c19800e8SDoug Rabson 	}
550b528cefcSMark Murray 	if (_resolve_debug) {
551*ae771770SStanislav Sedov #if defined(HAVE_DNS_SEARCH)
552*ae771770SStanislav Sedov 	    dns_set_debug(handle, 1);
553*ae771770SStanislav Sedov #elif defined(HAVE_RES_NSEARCH)
554c19800e8SDoug Rabson 	    state.options |= RES_DEBUG;
5558373020dSJacques Vidrine #endif
556c19800e8SDoug Rabson 	    fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
557*ae771770SStanislav Sedov 		    rr_class, rk_dns_type_to_string(rr_type), len);
558c19800e8SDoug Rabson 	}
559*ae771770SStanislav Sedov 	reply = malloc(len);
560c19800e8SDoug Rabson 	if (reply == NULL) {
561*ae771770SStanislav Sedov 	    resolve_free_handle(handle);
562c19800e8SDoug Rabson 	    return NULL;
563b528cefcSMark Murray 	}
564*ae771770SStanislav Sedov 
565*ae771770SStanislav Sedov 	size = resolve_search(handle, domain, rr_class, rr_type, reply, len);
566*ae771770SStanislav Sedov 
567b528cefcSMark Murray 	if (_resolve_debug) {
568b528cefcSMark Murray 	    fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
569*ae771770SStanislav Sedov 		    domain, rr_class, rk_dns_type_to_string(rr_type), size);
570b528cefcSMark Murray 	}
571*ae771770SStanislav Sedov 	if (size > len) {
572*ae771770SStanislav Sedov 	    /* resolver thinks it know better, go for it */
573*ae771770SStanislav Sedov 	    len = size;
574*ae771770SStanislav Sedov 	} else if (size > 0) {
575*ae771770SStanislav Sedov 	    /* got a good reply */
576*ae771770SStanislav Sedov 	    break;
577*ae771770SStanislav Sedov 	} else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) {
578*ae771770SStanislav Sedov 	    len *= 2;
579*ae771770SStanislav Sedov 	    if (len > rk_DNS_MAX_PACKET_SIZE)
580*ae771770SStanislav Sedov 		len = rk_DNS_MAX_PACKET_SIZE;
581*ae771770SStanislav Sedov 	} else {
582*ae771770SStanislav Sedov 	    /* the end, leave */
583*ae771770SStanislav Sedov 	    resolve_free_handle(handle);
584c19800e8SDoug Rabson 	    free(reply);
5858373020dSJacques Vidrine 	    return NULL;
5868373020dSJacques Vidrine 	}
587*ae771770SStanislav Sedov     }
588c19800e8SDoug Rabson 
589c19800e8SDoug Rabson     len = min(len, size);
590c19800e8SDoug Rabson     r = parse_reply(reply, len);
591c19800e8SDoug Rabson     free(reply);
592*ae771770SStanislav Sedov 
593*ae771770SStanislav Sedov     resolve_free_handle(handle);
594*ae771770SStanislav Sedov 
595c19800e8SDoug Rabson     return r;
596b528cefcSMark Murray }
597b528cefcSMark Murray 
598*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)599*ae771770SStanislav Sedov rk_dns_lookup(const char *domain, const char *type_name)
600b528cefcSMark Murray {
601b528cefcSMark Murray     int type;
602b528cefcSMark Murray 
603*ae771770SStanislav Sedov     type = rk_dns_string_to_type(type_name);
604b528cefcSMark Murray     if(type == -1) {
605b528cefcSMark Murray 	if(_resolve_debug)
606b528cefcSMark Murray 	    fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
607b528cefcSMark Murray 		    type_name);
608b528cefcSMark Murray 	return NULL;
609b528cefcSMark Murray     }
610*ae771770SStanislav Sedov     return dns_lookup_int(domain, rk_ns_c_in, type);
611b528cefcSMark Murray }
612b528cefcSMark Murray 
613*ae771770SStanislav Sedov #endif	/* !HAVE_WINDNS */
614*ae771770SStanislav Sedov 
6154137ff4cSJacques Vidrine static int
compare_srv(const void * a,const void * b)6164137ff4cSJacques Vidrine compare_srv(const void *a, const void *b)
6174137ff4cSJacques Vidrine {
618*ae771770SStanislav Sedov     const struct rk_resource_record *const* aa = a, *const* bb = b;
6194137ff4cSJacques Vidrine 
6204137ff4cSJacques Vidrine     if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
6214137ff4cSJacques Vidrine 	return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
6224137ff4cSJacques Vidrine     return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
6234137ff4cSJacques Vidrine }
6244137ff4cSJacques Vidrine 
6254137ff4cSJacques Vidrine /* try to rearrange the srv-records by the algorithm in RFC2782 */
626*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_srv_order(struct rk_dns_reply * r)627*ae771770SStanislav Sedov rk_dns_srv_order(struct rk_dns_reply *r)
6284137ff4cSJacques Vidrine {
629*ae771770SStanislav Sedov     struct rk_resource_record **srvs, **ss, **headp;
630*ae771770SStanislav Sedov     struct rk_resource_record *rr;
6314137ff4cSJacques Vidrine     int num_srv = 0;
6324137ff4cSJacques Vidrine 
633*ae771770SStanislav Sedov     rk_random_init();
6344137ff4cSJacques Vidrine 
6354137ff4cSJacques Vidrine     for(rr = r->head; rr; rr = rr->next)
636c19800e8SDoug Rabson 	if(rr->type == rk_ns_t_srv)
6374137ff4cSJacques Vidrine 	    num_srv++;
6384137ff4cSJacques Vidrine 
6394137ff4cSJacques Vidrine     if(num_srv == 0)
6404137ff4cSJacques Vidrine 	return;
6414137ff4cSJacques Vidrine 
6424137ff4cSJacques Vidrine     srvs = malloc(num_srv * sizeof(*srvs));
6434137ff4cSJacques Vidrine     if(srvs == NULL)
6444137ff4cSJacques Vidrine 	return; /* XXX not much to do here */
6454137ff4cSJacques Vidrine 
6464137ff4cSJacques Vidrine     /* unlink all srv-records from the linked list and put them in
6474137ff4cSJacques Vidrine        a vector */
6484137ff4cSJacques Vidrine     for(ss = srvs, headp = &r->head; *headp; )
649c19800e8SDoug Rabson 	if((*headp)->type == rk_ns_t_srv) {
6504137ff4cSJacques Vidrine 	    *ss = *headp;
6514137ff4cSJacques Vidrine 	    *headp = (*headp)->next;
6524137ff4cSJacques Vidrine 	    (*ss)->next = NULL;
6534137ff4cSJacques Vidrine 	    ss++;
6544137ff4cSJacques Vidrine 	} else
6554137ff4cSJacques Vidrine 	    headp = &(*headp)->next;
6564137ff4cSJacques Vidrine 
6574137ff4cSJacques Vidrine     /* sort them by priority and weight */
6584137ff4cSJacques Vidrine     qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
6594137ff4cSJacques Vidrine 
6604137ff4cSJacques Vidrine     headp = &r->head;
6614137ff4cSJacques Vidrine 
6624137ff4cSJacques Vidrine     for(ss = srvs; ss < srvs + num_srv; ) {
6634137ff4cSJacques Vidrine 	int sum, rnd, count;
664*ae771770SStanislav Sedov 	struct rk_resource_record **ee, **tt;
6654137ff4cSJacques Vidrine 	/* find the last record with the same priority and count the
6664137ff4cSJacques Vidrine            sum of all weights */
6674137ff4cSJacques Vidrine 	for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
668c19800e8SDoug Rabson 	    assert(*tt != NULL);
6694137ff4cSJacques Vidrine 	    if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
6704137ff4cSJacques Vidrine 		break;
6714137ff4cSJacques Vidrine 	    sum += (*tt)->u.srv->weight;
6724137ff4cSJacques Vidrine 	}
6734137ff4cSJacques Vidrine 	ee = tt;
6744137ff4cSJacques Vidrine 	/* ss is now the first record of this priority and ee is the
6754137ff4cSJacques Vidrine            first of the next */
6764137ff4cSJacques Vidrine 	while(ss < ee) {
677*ae771770SStanislav Sedov 	    rnd = rk_random() % (sum + 1);
6784137ff4cSJacques Vidrine 	    for(count = 0, tt = ss; ; tt++) {
6794137ff4cSJacques Vidrine 		if(*tt == NULL)
6804137ff4cSJacques Vidrine 		    continue;
6814137ff4cSJacques Vidrine 		count += (*tt)->u.srv->weight;
6824137ff4cSJacques Vidrine 		if(count >= rnd)
6834137ff4cSJacques Vidrine 		    break;
6844137ff4cSJacques Vidrine 	    }
6854137ff4cSJacques Vidrine 
6864137ff4cSJacques Vidrine 	    assert(tt < ee);
6874137ff4cSJacques Vidrine 
6884137ff4cSJacques Vidrine 	    /* insert the selected record at the tail (of the head) of
6894137ff4cSJacques Vidrine                the list */
6904137ff4cSJacques Vidrine 	    (*tt)->next = *headp;
6914137ff4cSJacques Vidrine 	    *headp = *tt;
6924137ff4cSJacques Vidrine 	    headp = &(*tt)->next;
6934137ff4cSJacques Vidrine 	    sum -= (*tt)->u.srv->weight;
6944137ff4cSJacques Vidrine 	    *tt = NULL;
6954137ff4cSJacques Vidrine 	    while(ss < ee && *ss == NULL)
6964137ff4cSJacques Vidrine 		ss++;
6974137ff4cSJacques Vidrine 	}
6984137ff4cSJacques Vidrine     }
6994137ff4cSJacques Vidrine 
7004137ff4cSJacques Vidrine     free(srvs);
7014137ff4cSJacques Vidrine     return;
7024137ff4cSJacques Vidrine }
7034137ff4cSJacques Vidrine 
704*ae771770SStanislav Sedov #ifdef HAVE_WINDNS
705*ae771770SStanislav Sedov 
706*ae771770SStanislav Sedov #include <WinDNS.h>
707*ae771770SStanislav Sedov 
708*ae771770SStanislav Sedov static struct rk_resource_record *
parse_dns_record(PDNS_RECORD pRec)709*ae771770SStanislav Sedov parse_dns_record(PDNS_RECORD pRec)
710*ae771770SStanislav Sedov {
711*ae771770SStanislav Sedov     struct rk_resource_record * rr;
712*ae771770SStanislav Sedov 
713*ae771770SStanislav Sedov     if (pRec == NULL)
714*ae771770SStanislav Sedov 	return NULL;
715*ae771770SStanislav Sedov 
716*ae771770SStanislav Sedov     rr = calloc(1, sizeof(*rr));
717*ae771770SStanislav Sedov 
718*ae771770SStanislav Sedov     rr->domain = strdup(pRec->pName);
719*ae771770SStanislav Sedov     rr->type = pRec->wType;
720*ae771770SStanislav Sedov     rr->class = 0;
721*ae771770SStanislav Sedov     rr->ttl = pRec->dwTtl;
722*ae771770SStanislav Sedov     rr->size = 0;
723*ae771770SStanislav Sedov 
724*ae771770SStanislav Sedov     switch (rr->type) {
725*ae771770SStanislav Sedov     case rk_ns_t_ns:
726*ae771770SStanislav Sedov     case rk_ns_t_cname:
727*ae771770SStanislav Sedov     case rk_ns_t_ptr:
728*ae771770SStanislav Sedov 	rr->u.txt = strdup(pRec->Data.NS.pNameHost);
729*ae771770SStanislav Sedov 	if(rr->u.txt == NULL) {
730*ae771770SStanislav Sedov 	    dns_free_rr(rr);
731*ae771770SStanislav Sedov 	    return NULL;
732*ae771770SStanislav Sedov 	}
733*ae771770SStanislav Sedov 	break;
734*ae771770SStanislav Sedov 
735*ae771770SStanislav Sedov     case rk_ns_t_mx:
736*ae771770SStanislav Sedov     case rk_ns_t_afsdb:{
737*ae771770SStanislav Sedov 	size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH);
738*ae771770SStanislav Sedov 
739*ae771770SStanislav Sedov 	rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) +
740*ae771770SStanislav Sedov 					      hostlen);
741*ae771770SStanislav Sedov 	if (rr->u.mx == NULL) {
742*ae771770SStanislav Sedov 	    dns_free_rr(rr);
743*ae771770SStanislav Sedov 	    return NULL;
744*ae771770SStanislav Sedov 	}
745*ae771770SStanislav Sedov 
746*ae771770SStanislav Sedov 	strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange);
747*ae771770SStanislav Sedov 	rr->u.mx->preference = pRec->Data.MX.wPreference;
748*ae771770SStanislav Sedov 	break;
749*ae771770SStanislav Sedov     }
750*ae771770SStanislav Sedov 
751*ae771770SStanislav Sedov     case rk_ns_t_srv:{
752*ae771770SStanislav Sedov 	size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH);
753*ae771770SStanislav Sedov 
754*ae771770SStanislav Sedov 	rr->u.srv =
755*ae771770SStanislav Sedov 	    (struct srv_record*)malloc(sizeof(struct srv_record) +
756*ae771770SStanislav Sedov 				       hostlen);
757*ae771770SStanislav Sedov 	if(rr->u.srv == NULL) {
758*ae771770SStanislav Sedov 	    dns_free_rr(rr);
759*ae771770SStanislav Sedov 	    return NULL;
760*ae771770SStanislav Sedov 	}
761*ae771770SStanislav Sedov 
762*ae771770SStanislav Sedov 	rr->u.srv->priority = pRec->Data.SRV.wPriority;
763*ae771770SStanislav Sedov 	rr->u.srv->weight = pRec->Data.SRV.wWeight;
764*ae771770SStanislav Sedov 	rr->u.srv->port = pRec->Data.SRV.wPort;
765*ae771770SStanislav Sedov 	strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget);
766*ae771770SStanislav Sedov 
767*ae771770SStanislav Sedov 	break;
768*ae771770SStanislav Sedov     }
769*ae771770SStanislav Sedov 
770*ae771770SStanislav Sedov     case rk_ns_t_txt:{
771*ae771770SStanislav Sedov 	size_t len;
772*ae771770SStanislav Sedov 
773*ae771770SStanislav Sedov 	if (pRec->Data.TXT.dwStringCount == 0) {
774*ae771770SStanislav Sedov 	    rr->u.txt = strdup("");
775*ae771770SStanislav Sedov 	    break;
776*ae771770SStanislav Sedov 	}
777*ae771770SStanislav Sedov 
778*ae771770SStanislav Sedov 	len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH);
779*ae771770SStanislav Sedov 
780*ae771770SStanislav Sedov 	rr->u.txt = (char *)malloc(len + 1);
781*ae771770SStanislav Sedov 	strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]);
782*ae771770SStanislav Sedov 
783*ae771770SStanislav Sedov 	break;
784*ae771770SStanislav Sedov     }
785*ae771770SStanislav Sedov 
786*ae771770SStanislav Sedov     case rk_ns_t_key : {
787*ae771770SStanislav Sedov 	size_t key_len;
788*ae771770SStanislav Sedov 
789*ae771770SStanislav Sedov 	if (pRec->wDataLength < 4) {
790*ae771770SStanislav Sedov 	    dns_free_rr(rr);
791*ae771770SStanislav Sedov 	    return NULL;
792*ae771770SStanislav Sedov 	}
793*ae771770SStanislav Sedov 
794*ae771770SStanislav Sedov 	key_len = pRec->wDataLength - 4;
795*ae771770SStanislav Sedov 	rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
796*ae771770SStanislav Sedov 	if (rr->u.key == NULL) {
797*ae771770SStanislav Sedov 	    dns_free_rr(rr);
798*ae771770SStanislav Sedov 	    return NULL;
799*ae771770SStanislav Sedov 	}
800*ae771770SStanislav Sedov 
801*ae771770SStanislav Sedov 	rr->u.key->flags     = pRec->Data.KEY.wFlags;
802*ae771770SStanislav Sedov 	rr->u.key->protocol  = pRec->Data.KEY.chProtocol;
803*ae771770SStanislav Sedov 	rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm;
804*ae771770SStanislav Sedov 	rr->u.key->key_len   = key_len;
805*ae771770SStanislav Sedov 	memcpy_s (rr->u.key->key_data, key_len,
806*ae771770SStanislav Sedov 		  pRec->Data.KEY.Key, key_len);
807*ae771770SStanislav Sedov 	break;
808*ae771770SStanislav Sedov     }
809*ae771770SStanislav Sedov 
810*ae771770SStanislav Sedov     case rk_ns_t_sig : {
811*ae771770SStanislav Sedov 	size_t sig_len, hostlen;
812*ae771770SStanislav Sedov 
813*ae771770SStanislav Sedov 	if(pRec->wDataLength <= 18) {
814*ae771770SStanislav Sedov 	    dns_free_rr(rr);
815*ae771770SStanislav Sedov 	    return NULL;
816*ae771770SStanislav Sedov 	}
817*ae771770SStanislav Sedov 
818*ae771770SStanislav Sedov 	sig_len = pRec->wDataLength;
819*ae771770SStanislav Sedov 
820*ae771770SStanislav Sedov 	hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH);
821*ae771770SStanislav Sedov 
822*ae771770SStanislav Sedov 	rr->u.sig = malloc(sizeof(*rr->u.sig)
823*ae771770SStanislav Sedov 			      + hostlen + sig_len);
824*ae771770SStanislav Sedov 	if (rr->u.sig == NULL) {
825*ae771770SStanislav Sedov 	    dns_free_rr(rr);
826*ae771770SStanislav Sedov 	    return NULL;
827*ae771770SStanislav Sedov 	}
828*ae771770SStanislav Sedov 	rr->u.sig->type           = pRec->Data.SIG.wTypeCovered;
829*ae771770SStanislav Sedov 	rr->u.sig->algorithm      = pRec->Data.SIG.chAlgorithm;
830*ae771770SStanislav Sedov 	rr->u.sig->labels         = pRec->Data.SIG.chLabelCount;
831*ae771770SStanislav Sedov 	rr->u.sig->orig_ttl       = pRec->Data.SIG.dwOriginalTtl;
832*ae771770SStanislav Sedov 	rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration;
833*ae771770SStanislav Sedov 	rr->u.sig->sig_inception  = pRec->Data.SIG.dwTimeSigned;
834*ae771770SStanislav Sedov 	rr->u.sig->key_tag        = pRec->Data.SIG.wKeyTag;
835*ae771770SStanislav Sedov 	rr->u.sig->sig_len        = sig_len;
836*ae771770SStanislav Sedov 	memcpy_s (rr->u.sig->sig_data, sig_len,
837*ae771770SStanislav Sedov 		  pRec->Data.SIG.Signature, sig_len);
838*ae771770SStanislav Sedov 	rr->u.sig->signer         = &rr->u.sig->sig_data[sig_len];
839*ae771770SStanislav Sedov 	strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner);
840*ae771770SStanislav Sedov 	break;
841*ae771770SStanislav Sedov     }
842*ae771770SStanislav Sedov 
843*ae771770SStanislav Sedov #ifdef DNS_TYPE_DS
844*ae771770SStanislav Sedov     case rk_ns_t_ds: {
845*ae771770SStanislav Sedov 	rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1);
846*ae771770SStanislav Sedov 	if (rr->u.ds == NULL) {
847*ae771770SStanislav Sedov 	    dns_free_rr(rr);
848*ae771770SStanislav Sedov 	    return NULL;
849*ae771770SStanislav Sedov 	}
850*ae771770SStanislav Sedov 
851*ae771770SStanislav Sedov 	rr->u.ds->key_tag     = pRec->Data.DS.wKeyTag;
852*ae771770SStanislav Sedov 	rr->u.ds->algorithm   = pRec->Data.DS.chAlgorithm;
853*ae771770SStanislav Sedov 	rr->u.ds->digest_type = pRec->Data.DS.chDigestType;
854*ae771770SStanislav Sedov 	rr->u.ds->digest_len  = pRec->Data.DS.wDigestLength;
855*ae771770SStanislav Sedov 	memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength,
856*ae771770SStanislav Sedov 		  pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength);
857*ae771770SStanislav Sedov 	break;
858*ae771770SStanislav Sedov     }
859*ae771770SStanislav Sedov #endif
860*ae771770SStanislav Sedov 
861*ae771770SStanislav Sedov     default:
862*ae771770SStanislav Sedov 	dns_free_rr(rr);
863*ae771770SStanislav Sedov 	return NULL;
864*ae771770SStanislav Sedov     }
865*ae771770SStanislav Sedov 
866*ae771770SStanislav Sedov     rr->next = parse_dns_record(pRec->pNext);
867*ae771770SStanislav Sedov     return rr;
868*ae771770SStanislav Sedov }
869*ae771770SStanislav Sedov 
870*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)871*ae771770SStanislav Sedov rk_dns_lookup(const char *domain, const char *type_name)
872*ae771770SStanislav Sedov {
873*ae771770SStanislav Sedov     DNS_STATUS status;
874*ae771770SStanislav Sedov     int type;
875*ae771770SStanislav Sedov     PDNS_RECORD pRec = NULL;
876*ae771770SStanislav Sedov     struct rk_dns_reply * r = NULL;
877*ae771770SStanislav Sedov 
878*ae771770SStanislav Sedov     __try {
879*ae771770SStanislav Sedov 
880*ae771770SStanislav Sedov 	type = rk_dns_string_to_type(type_name);
881*ae771770SStanislav Sedov 	if(type == -1) {
882*ae771770SStanislav Sedov 	    if(_resolve_debug)
883*ae771770SStanislav Sedov 		fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
884*ae771770SStanislav Sedov 			type_name);
885*ae771770SStanislav Sedov 	    return NULL;
886*ae771770SStanislav Sedov 	}
887*ae771770SStanislav Sedov 
888*ae771770SStanislav Sedov 	status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL,
889*ae771770SStanislav Sedov 			       &pRec, NULL);
890*ae771770SStanislav Sedov 	if (status != ERROR_SUCCESS)
891*ae771770SStanislav Sedov 	    return NULL;
892*ae771770SStanislav Sedov 
893*ae771770SStanislav Sedov 	r = calloc(1, sizeof(*r));
894*ae771770SStanislav Sedov 	r->q.domain = strdup(domain);
895*ae771770SStanislav Sedov 	r->q.type = type;
896*ae771770SStanislav Sedov 	r->q.class = 0;
897*ae771770SStanislav Sedov 
898*ae771770SStanislav Sedov 	r->head = parse_dns_record(pRec);
899*ae771770SStanislav Sedov 
900*ae771770SStanislav Sedov 	if (r->head == NULL) {
901*ae771770SStanislav Sedov 	    rk_dns_free_data(r);
902*ae771770SStanislav Sedov 	    return NULL;
903*ae771770SStanislav Sedov 	} else {
904*ae771770SStanislav Sedov 	    return r;
905*ae771770SStanislav Sedov 	}
906*ae771770SStanislav Sedov 
907*ae771770SStanislav Sedov     } __finally {
908*ae771770SStanislav Sedov 
909*ae771770SStanislav Sedov 	if (pRec)
910*ae771770SStanislav Sedov 	    DnsRecordListFree(pRec, DnsFreeRecordList);
911*ae771770SStanislav Sedov 
912*ae771770SStanislav Sedov     }
913*ae771770SStanislav Sedov }
914*ae771770SStanislav Sedov #endif	/* HAVE_WINDNS */
915*ae771770SStanislav Sedov 
916b528cefcSMark Murray #else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
917b528cefcSMark Murray 
918*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)919*ae771770SStanislav Sedov rk_dns_lookup(const char *domain, const char *type_name)
920b528cefcSMark Murray {
921b528cefcSMark Murray     return NULL;
922b528cefcSMark Murray }
923b528cefcSMark Murray 
924*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_free_data(struct rk_dns_reply * r)925*ae771770SStanislav Sedov rk_dns_free_data(struct rk_dns_reply *r)
926b528cefcSMark Murray {
927b528cefcSMark Murray }
928b528cefcSMark Murray 
929*ae771770SStanislav Sedov ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_srv_order(struct rk_dns_reply * r)930*ae771770SStanislav Sedov rk_dns_srv_order(struct rk_dns_reply *r)
9314137ff4cSJacques Vidrine {
9324137ff4cSJacques Vidrine }
9334137ff4cSJacques Vidrine 
934b528cefcSMark Murray #endif
935