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