1*0a6a1f1dSLionel Sambuc /* $NetBSD: resolve.c,v 1.4 2014/04/24 14:49:43 pettai Exp $ */
2ebfedea0SLionel Sambuc
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc * Copyright (c) 1995 - 2006 Kungliga Tekniska Högskolan
5ebfedea0SLionel Sambuc * (Royal Institute of Technology, Stockholm, Sweden).
6ebfedea0SLionel Sambuc * All rights reserved.
7ebfedea0SLionel Sambuc *
8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
10ebfedea0SLionel Sambuc * are met:
11ebfedea0SLionel Sambuc *
12ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
13ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
14ebfedea0SLionel Sambuc *
15ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution.
18ebfedea0SLionel Sambuc *
19ebfedea0SLionel Sambuc * 3. Neither the name of the Institute nor the names of its contributors
20ebfedea0SLionel Sambuc * may be used to endorse or promote products derived from this software
21ebfedea0SLionel Sambuc * without specific prior written permission.
22ebfedea0SLionel Sambuc *
23ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ebfedea0SLionel Sambuc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ebfedea0SLionel Sambuc * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ebfedea0SLionel Sambuc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ebfedea0SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ebfedea0SLionel Sambuc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ebfedea0SLionel Sambuc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ebfedea0SLionel Sambuc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ebfedea0SLionel Sambuc * SUCH DAMAGE.
34ebfedea0SLionel Sambuc */
35ebfedea0SLionel Sambuc
36ebfedea0SLionel Sambuc
37ebfedea0SLionel Sambuc #include <config.h>
38ebfedea0SLionel Sambuc
39ebfedea0SLionel Sambuc #include <krb5/roken.h>
40ebfedea0SLionel Sambuc #ifdef HAVE_ARPA_NAMESER_H
41ebfedea0SLionel Sambuc #include <arpa/nameser.h>
42ebfedea0SLionel Sambuc #endif
43ebfedea0SLionel Sambuc #ifdef HAVE_RESOLV_H
44ebfedea0SLionel Sambuc #include <resolv.h>
45ebfedea0SLionel Sambuc #endif
46ebfedea0SLionel Sambuc #ifdef HAVE_DNS_H
47ebfedea0SLionel Sambuc #include <dns.h>
48ebfedea0SLionel Sambuc #endif
49ebfedea0SLionel Sambuc #include <krb5/resolve.h>
50ebfedea0SLionel Sambuc
51ebfedea0SLionel Sambuc #include <assert.h>
52ebfedea0SLionel Sambuc
53ebfedea0SLionel Sambuc #ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */
54ebfedea0SLionel Sambuc #undef HAVE_RES_NSEARCH
55ebfedea0SLionel Sambuc #endif
56ebfedea0SLionel Sambuc
57ebfedea0SLionel Sambuc #define DECL(X) {#X, rk_ns_t_##X}
58ebfedea0SLionel Sambuc
59ebfedea0SLionel Sambuc static struct stot{
60ebfedea0SLionel Sambuc const char *name;
61ebfedea0SLionel Sambuc int type;
62ebfedea0SLionel Sambuc }stot[] = {
63ebfedea0SLionel Sambuc DECL(a),
64ebfedea0SLionel Sambuc DECL(aaaa),
65ebfedea0SLionel Sambuc DECL(ns),
66ebfedea0SLionel Sambuc DECL(cname),
67ebfedea0SLionel Sambuc DECL(soa),
68ebfedea0SLionel Sambuc DECL(ptr),
69ebfedea0SLionel Sambuc DECL(mx),
70ebfedea0SLionel Sambuc DECL(txt),
71ebfedea0SLionel Sambuc DECL(afsdb),
72ebfedea0SLionel Sambuc DECL(sig),
73ebfedea0SLionel Sambuc DECL(key),
74ebfedea0SLionel Sambuc DECL(srv),
75ebfedea0SLionel Sambuc DECL(naptr),
76ebfedea0SLionel Sambuc DECL(sshfp),
77ebfedea0SLionel Sambuc DECL(ds),
78ebfedea0SLionel Sambuc {NULL, 0}
79ebfedea0SLionel Sambuc };
80ebfedea0SLionel Sambuc
81ebfedea0SLionel Sambuc int _resolve_debug = 0;
82ebfedea0SLionel Sambuc
83ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
rk_dns_string_to_type(const char * name)84ebfedea0SLionel Sambuc rk_dns_string_to_type(const char *name)
85ebfedea0SLionel Sambuc {
86ebfedea0SLionel Sambuc struct stot *p = stot;
87ebfedea0SLionel Sambuc for(p = stot; p->name; p++)
88ebfedea0SLionel Sambuc if(strcasecmp(name, p->name) == 0)
89ebfedea0SLionel Sambuc return p->type;
90ebfedea0SLionel Sambuc return -1;
91ebfedea0SLionel Sambuc }
92ebfedea0SLionel Sambuc
93ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION const char * ROKEN_LIB_CALL
rk_dns_type_to_string(int type)94ebfedea0SLionel Sambuc rk_dns_type_to_string(int type)
95ebfedea0SLionel Sambuc {
96ebfedea0SLionel Sambuc struct stot *p = stot;
97ebfedea0SLionel Sambuc for(p = stot; p->name; p++)
98ebfedea0SLionel Sambuc if(type == p->type)
99ebfedea0SLionel Sambuc return p->name;
100ebfedea0SLionel Sambuc return NULL;
101ebfedea0SLionel Sambuc }
102ebfedea0SLionel Sambuc
103ebfedea0SLionel Sambuc #if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS)
104ebfedea0SLionel Sambuc
105ebfedea0SLionel Sambuc static void
dns_free_rr(struct rk_resource_record * rr)106ebfedea0SLionel Sambuc dns_free_rr(struct rk_resource_record *rr)
107ebfedea0SLionel Sambuc {
108ebfedea0SLionel Sambuc if(rr->domain)
109ebfedea0SLionel Sambuc free(rr->domain);
110ebfedea0SLionel Sambuc if(rr->u.data)
111ebfedea0SLionel Sambuc free(rr->u.data);
112ebfedea0SLionel Sambuc free(rr);
113ebfedea0SLionel Sambuc }
114ebfedea0SLionel Sambuc
115ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_free_data(struct rk_dns_reply * r)116ebfedea0SLionel Sambuc rk_dns_free_data(struct rk_dns_reply *r)
117ebfedea0SLionel Sambuc {
118ebfedea0SLionel Sambuc struct rk_resource_record *rr;
119ebfedea0SLionel Sambuc if(r->q.domain)
120ebfedea0SLionel Sambuc free(r->q.domain);
121ebfedea0SLionel Sambuc for(rr = r->head; rr;){
122ebfedea0SLionel Sambuc struct rk_resource_record *tmp = rr;
123ebfedea0SLionel Sambuc rr = rr->next;
124ebfedea0SLionel Sambuc dns_free_rr(tmp);
125ebfedea0SLionel Sambuc }
126ebfedea0SLionel Sambuc free (r);
127ebfedea0SLionel Sambuc }
128ebfedea0SLionel Sambuc
129ebfedea0SLionel Sambuc #ifndef HAVE_WINDNS
130ebfedea0SLionel Sambuc
131ebfedea0SLionel Sambuc static int
parse_record(const unsigned char * data,const unsigned char * end_data,const unsigned char ** pp,struct rk_resource_record ** ret_rr)132ebfedea0SLionel Sambuc parse_record(const unsigned char *data, const unsigned char *end_data,
133ebfedea0SLionel Sambuc const unsigned char **pp, struct rk_resource_record **ret_rr)
134ebfedea0SLionel Sambuc {
135ebfedea0SLionel Sambuc struct rk_resource_record *rr;
136ebfedea0SLionel Sambuc int type, class, ttl;
137ebfedea0SLionel Sambuc unsigned size;
138ebfedea0SLionel Sambuc int status;
139ebfedea0SLionel Sambuc char host[MAXDNAME];
140ebfedea0SLionel Sambuc const unsigned char *p = *pp;
141ebfedea0SLionel Sambuc
142ebfedea0SLionel Sambuc *ret_rr = NULL;
143ebfedea0SLionel Sambuc
144ebfedea0SLionel Sambuc status = dn_expand(data, end_data, p, host, sizeof(host));
145ebfedea0SLionel Sambuc if(status < 0)
146ebfedea0SLionel Sambuc return -1;
147ebfedea0SLionel Sambuc if (p + status + 10 > end_data)
148ebfedea0SLionel Sambuc return -1;
149ebfedea0SLionel Sambuc
150ebfedea0SLionel Sambuc p += status;
151ebfedea0SLionel Sambuc type = (p[0] << 8) | p[1];
152ebfedea0SLionel Sambuc p += 2;
153ebfedea0SLionel Sambuc class = (p[0] << 8) | p[1];
154ebfedea0SLionel Sambuc p += 2;
155ebfedea0SLionel Sambuc ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
156ebfedea0SLionel Sambuc p += 4;
157ebfedea0SLionel Sambuc size = (p[0] << 8) | p[1];
158ebfedea0SLionel Sambuc p += 2;
159ebfedea0SLionel Sambuc
160ebfedea0SLionel Sambuc if (p + size > end_data)
161ebfedea0SLionel Sambuc return -1;
162ebfedea0SLionel Sambuc
163ebfedea0SLionel Sambuc rr = calloc(1, sizeof(*rr));
164ebfedea0SLionel Sambuc if(rr == NULL)
165ebfedea0SLionel Sambuc return -1;
166ebfedea0SLionel Sambuc rr->domain = strdup(host);
167ebfedea0SLionel Sambuc if(rr->domain == NULL) {
168ebfedea0SLionel Sambuc dns_free_rr(rr);
169ebfedea0SLionel Sambuc return -1;
170ebfedea0SLionel Sambuc }
171ebfedea0SLionel Sambuc rr->type = type;
172ebfedea0SLionel Sambuc rr->class = class;
173ebfedea0SLionel Sambuc rr->ttl = ttl;
174ebfedea0SLionel Sambuc rr->size = size;
175ebfedea0SLionel Sambuc switch(type){
176ebfedea0SLionel Sambuc case rk_ns_t_ns:
177ebfedea0SLionel Sambuc case rk_ns_t_cname:
178ebfedea0SLionel Sambuc case rk_ns_t_ptr:
179ebfedea0SLionel Sambuc status = dn_expand(data, end_data, p, host, sizeof(host));
180ebfedea0SLionel Sambuc if(status < 0) {
181ebfedea0SLionel Sambuc dns_free_rr(rr);
182ebfedea0SLionel Sambuc return -1;
183ebfedea0SLionel Sambuc }
184ebfedea0SLionel Sambuc rr->u.txt = strdup(host);
185ebfedea0SLionel Sambuc if(rr->u.txt == NULL) {
186ebfedea0SLionel Sambuc dns_free_rr(rr);
187ebfedea0SLionel Sambuc return -1;
188ebfedea0SLionel Sambuc }
189ebfedea0SLionel Sambuc break;
190ebfedea0SLionel Sambuc case rk_ns_t_mx:
191ebfedea0SLionel Sambuc case rk_ns_t_afsdb:{
192ebfedea0SLionel Sambuc size_t hostlen;
193ebfedea0SLionel Sambuc
194ebfedea0SLionel Sambuc status = dn_expand(data, end_data, p + 2, host, sizeof(host));
195ebfedea0SLionel Sambuc if(status < 0){
196ebfedea0SLionel Sambuc dns_free_rr(rr);
197ebfedea0SLionel Sambuc return -1;
198ebfedea0SLionel Sambuc }
199*0a6a1f1dSLionel Sambuc if ((size_t)status + 2 > size) {
200ebfedea0SLionel Sambuc dns_free_rr(rr);
201ebfedea0SLionel Sambuc return -1;
202ebfedea0SLionel Sambuc }
203ebfedea0SLionel Sambuc
204ebfedea0SLionel Sambuc hostlen = strlen(host);
205ebfedea0SLionel Sambuc rr->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
206ebfedea0SLionel Sambuc hostlen);
207ebfedea0SLionel Sambuc if(rr->u.mx == NULL) {
208ebfedea0SLionel Sambuc dns_free_rr(rr);
209ebfedea0SLionel Sambuc return -1;
210ebfedea0SLionel Sambuc }
211ebfedea0SLionel Sambuc rr->u.mx->preference = (p[0] << 8) | p[1];
212ebfedea0SLionel Sambuc strlcpy(rr->u.mx->domain, host, hostlen + 1);
213ebfedea0SLionel Sambuc break;
214ebfedea0SLionel Sambuc }
215ebfedea0SLionel Sambuc case rk_ns_t_srv:{
216ebfedea0SLionel Sambuc size_t hostlen;
217ebfedea0SLionel Sambuc status = dn_expand(data, end_data, p + 6, host, sizeof(host));
218ebfedea0SLionel Sambuc if(status < 0){
219ebfedea0SLionel Sambuc dns_free_rr(rr);
220ebfedea0SLionel Sambuc return -1;
221ebfedea0SLionel Sambuc }
222*0a6a1f1dSLionel Sambuc if ((size_t)status + 6 > size) {
223ebfedea0SLionel Sambuc dns_free_rr(rr);
224ebfedea0SLionel Sambuc return -1;
225ebfedea0SLionel Sambuc }
226ebfedea0SLionel Sambuc
227ebfedea0SLionel Sambuc hostlen = strlen(host);
228ebfedea0SLionel Sambuc rr->u.srv =
229ebfedea0SLionel Sambuc (struct srv_record*)malloc(sizeof(struct srv_record) +
230ebfedea0SLionel Sambuc hostlen);
231ebfedea0SLionel Sambuc if(rr->u.srv == NULL) {
232ebfedea0SLionel Sambuc dns_free_rr(rr);
233ebfedea0SLionel Sambuc return -1;
234ebfedea0SLionel Sambuc }
235ebfedea0SLionel Sambuc rr->u.srv->priority = (p[0] << 8) | p[1];
236ebfedea0SLionel Sambuc rr->u.srv->weight = (p[2] << 8) | p[3];
237ebfedea0SLionel Sambuc rr->u.srv->port = (p[4] << 8) | p[5];
238ebfedea0SLionel Sambuc strlcpy(rr->u.srv->target, host, hostlen + 1);
239ebfedea0SLionel Sambuc break;
240ebfedea0SLionel Sambuc }
241ebfedea0SLionel Sambuc case rk_ns_t_txt:{
242*0a6a1f1dSLionel Sambuc if(size == 0 || size < (unsigned)(*p + 1)) {
243ebfedea0SLionel Sambuc dns_free_rr(rr);
244ebfedea0SLionel Sambuc return -1;
245ebfedea0SLionel Sambuc }
246ebfedea0SLionel Sambuc rr->u.txt = (char*)malloc(*p + 1);
247ebfedea0SLionel Sambuc if(rr->u.txt == NULL) {
248ebfedea0SLionel Sambuc dns_free_rr(rr);
249ebfedea0SLionel Sambuc return -1;
250ebfedea0SLionel Sambuc }
251ebfedea0SLionel Sambuc strncpy(rr->u.txt, (const char*)(p + 1), *p);
252ebfedea0SLionel Sambuc rr->u.txt[*p] = '\0';
253ebfedea0SLionel Sambuc break;
254ebfedea0SLionel Sambuc }
255ebfedea0SLionel Sambuc case rk_ns_t_key : {
256ebfedea0SLionel Sambuc size_t key_len;
257ebfedea0SLionel Sambuc
258ebfedea0SLionel Sambuc if (size < 4) {
259ebfedea0SLionel Sambuc dns_free_rr(rr);
260ebfedea0SLionel Sambuc return -1;
261ebfedea0SLionel Sambuc }
262ebfedea0SLionel Sambuc
263ebfedea0SLionel Sambuc key_len = size - 4;
264ebfedea0SLionel Sambuc rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
265ebfedea0SLionel Sambuc if (rr->u.key == NULL) {
266ebfedea0SLionel Sambuc dns_free_rr(rr);
267ebfedea0SLionel Sambuc return -1;
268ebfedea0SLionel Sambuc }
269ebfedea0SLionel Sambuc
270ebfedea0SLionel Sambuc rr->u.key->flags = (p[0] << 8) | p[1];
271ebfedea0SLionel Sambuc rr->u.key->protocol = p[2];
272ebfedea0SLionel Sambuc rr->u.key->algorithm = p[3];
273ebfedea0SLionel Sambuc rr->u.key->key_len = key_len;
274ebfedea0SLionel Sambuc memcpy (rr->u.key->key_data, p + 4, key_len);
275ebfedea0SLionel Sambuc break;
276ebfedea0SLionel Sambuc }
277ebfedea0SLionel Sambuc case rk_ns_t_sig : {
278ebfedea0SLionel Sambuc size_t sig_len, hostlen;
279ebfedea0SLionel Sambuc
280ebfedea0SLionel Sambuc if(size <= 18) {
281ebfedea0SLionel Sambuc dns_free_rr(rr);
282ebfedea0SLionel Sambuc return -1;
283ebfedea0SLionel Sambuc }
284ebfedea0SLionel Sambuc status = dn_expand (data, end_data, p + 18, host, sizeof(host));
285ebfedea0SLionel Sambuc if (status < 0) {
286ebfedea0SLionel Sambuc dns_free_rr(rr);
287ebfedea0SLionel Sambuc return -1;
288ebfedea0SLionel Sambuc }
289*0a6a1f1dSLionel Sambuc if ((size_t)status + 18 > size) {
290ebfedea0SLionel Sambuc dns_free_rr(rr);
291ebfedea0SLionel Sambuc return -1;
292ebfedea0SLionel Sambuc }
293ebfedea0SLionel Sambuc
294ebfedea0SLionel Sambuc /* the signer name is placed after the sig_data, to make it
295ebfedea0SLionel Sambuc easy to free this structure; the size calculation below
296ebfedea0SLionel Sambuc includes the zero-termination if the structure itself.
297ebfedea0SLionel Sambuc don't you just love C?
298ebfedea0SLionel Sambuc */
299ebfedea0SLionel Sambuc sig_len = size - 18 - status;
300ebfedea0SLionel Sambuc hostlen = strlen(host);
301ebfedea0SLionel Sambuc rr->u.sig = malloc(sizeof(*rr->u.sig)
302ebfedea0SLionel Sambuc + hostlen + sig_len);
303ebfedea0SLionel Sambuc if (rr->u.sig == NULL) {
304ebfedea0SLionel Sambuc dns_free_rr(rr);
305ebfedea0SLionel Sambuc return -1;
306ebfedea0SLionel Sambuc }
307ebfedea0SLionel Sambuc rr->u.sig->type = (p[0] << 8) | p[1];
308ebfedea0SLionel Sambuc rr->u.sig->algorithm = p[2];
309ebfedea0SLionel Sambuc rr->u.sig->labels = p[3];
310ebfedea0SLionel Sambuc rr->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16)
311ebfedea0SLionel Sambuc | (p[6] << 8) | p[7];
312ebfedea0SLionel Sambuc rr->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
313ebfedea0SLionel Sambuc | (p[10] << 8) | p[11];
314ebfedea0SLionel Sambuc rr->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16)
315ebfedea0SLionel Sambuc | (p[14] << 8) | p[15];
316ebfedea0SLionel Sambuc rr->u.sig->key_tag = (p[16] << 8) | p[17];
317ebfedea0SLionel Sambuc rr->u.sig->sig_len = sig_len;
318ebfedea0SLionel Sambuc memcpy (rr->u.sig->sig_data, p + 18 + status, sig_len);
319ebfedea0SLionel Sambuc rr->u.sig->signer = &rr->u.sig->sig_data[sig_len];
320ebfedea0SLionel Sambuc strlcpy(rr->u.sig->signer, host, hostlen + 1);
321ebfedea0SLionel Sambuc break;
322ebfedea0SLionel Sambuc }
323ebfedea0SLionel Sambuc
324ebfedea0SLionel Sambuc case rk_ns_t_cert : {
325ebfedea0SLionel Sambuc size_t cert_len;
326ebfedea0SLionel Sambuc
327ebfedea0SLionel Sambuc if (size < 5) {
328ebfedea0SLionel Sambuc dns_free_rr(rr);
329ebfedea0SLionel Sambuc return -1;
330ebfedea0SLionel Sambuc }
331ebfedea0SLionel Sambuc
332ebfedea0SLionel Sambuc cert_len = size - 5;
333ebfedea0SLionel Sambuc rr->u.cert = malloc (sizeof(*rr->u.cert) + cert_len - 1);
334ebfedea0SLionel Sambuc if (rr->u.cert == NULL) {
335ebfedea0SLionel Sambuc dns_free_rr(rr);
336ebfedea0SLionel Sambuc return -1;
337ebfedea0SLionel Sambuc }
338ebfedea0SLionel Sambuc
339ebfedea0SLionel Sambuc rr->u.cert->type = (p[0] << 8) | p[1];
340ebfedea0SLionel Sambuc rr->u.cert->tag = (p[2] << 8) | p[3];
341ebfedea0SLionel Sambuc rr->u.cert->algorithm = p[4];
342ebfedea0SLionel Sambuc rr->u.cert->cert_len = cert_len;
343ebfedea0SLionel Sambuc memcpy (rr->u.cert->cert_data, p + 5, cert_len);
344ebfedea0SLionel Sambuc break;
345ebfedea0SLionel Sambuc }
346ebfedea0SLionel Sambuc case rk_ns_t_sshfp : {
347ebfedea0SLionel Sambuc size_t sshfp_len;
348ebfedea0SLionel Sambuc
349ebfedea0SLionel Sambuc if (size < 2) {
350ebfedea0SLionel Sambuc dns_free_rr(rr);
351ebfedea0SLionel Sambuc return -1;
352ebfedea0SLionel Sambuc }
353ebfedea0SLionel Sambuc
354ebfedea0SLionel Sambuc sshfp_len = size - 2;
355ebfedea0SLionel Sambuc
356ebfedea0SLionel Sambuc rr->u.sshfp = malloc (sizeof(*rr->u.sshfp) + sshfp_len - 1);
357ebfedea0SLionel Sambuc if (rr->u.sshfp == NULL) {
358ebfedea0SLionel Sambuc dns_free_rr(rr);
359ebfedea0SLionel Sambuc return -1;
360ebfedea0SLionel Sambuc }
361ebfedea0SLionel Sambuc
362ebfedea0SLionel Sambuc rr->u.sshfp->algorithm = p[0];
363ebfedea0SLionel Sambuc rr->u.sshfp->type = p[1];
364ebfedea0SLionel Sambuc rr->u.sshfp->sshfp_len = sshfp_len;
365ebfedea0SLionel Sambuc memcpy (rr->u.sshfp->sshfp_data, p + 2, sshfp_len);
366ebfedea0SLionel Sambuc break;
367ebfedea0SLionel Sambuc }
368ebfedea0SLionel Sambuc case rk_ns_t_ds: {
369ebfedea0SLionel Sambuc size_t digest_len;
370ebfedea0SLionel Sambuc
371ebfedea0SLionel Sambuc if (size < 4) {
372ebfedea0SLionel Sambuc dns_free_rr(rr);
373ebfedea0SLionel Sambuc return -1;
374ebfedea0SLionel Sambuc }
375ebfedea0SLionel Sambuc
376ebfedea0SLionel Sambuc digest_len = size - 4;
377ebfedea0SLionel Sambuc
378ebfedea0SLionel Sambuc rr->u.ds = malloc (sizeof(*rr->u.ds) + digest_len - 1);
379ebfedea0SLionel Sambuc if (rr->u.ds == NULL) {
380ebfedea0SLionel Sambuc dns_free_rr(rr);
381ebfedea0SLionel Sambuc return -1;
382ebfedea0SLionel Sambuc }
383ebfedea0SLionel Sambuc
384ebfedea0SLionel Sambuc rr->u.ds->key_tag = (p[0] << 8) | p[1];
385ebfedea0SLionel Sambuc rr->u.ds->algorithm = p[2];
386ebfedea0SLionel Sambuc rr->u.ds->digest_type = p[3];
387ebfedea0SLionel Sambuc rr->u.ds->digest_len = digest_len;
388ebfedea0SLionel Sambuc memcpy (rr->u.ds->digest_data, p + 4, digest_len);
389ebfedea0SLionel Sambuc break;
390ebfedea0SLionel Sambuc }
391ebfedea0SLionel Sambuc default:
392ebfedea0SLionel Sambuc rr->u.data = (unsigned char*)malloc(size);
393ebfedea0SLionel Sambuc if(size != 0 && rr->u.data == NULL) {
394ebfedea0SLionel Sambuc dns_free_rr(rr);
395ebfedea0SLionel Sambuc return -1;
396ebfedea0SLionel Sambuc }
397ebfedea0SLionel Sambuc if (size)
398ebfedea0SLionel Sambuc memcpy(rr->u.data, p, size);
399ebfedea0SLionel Sambuc }
400ebfedea0SLionel Sambuc *pp = p + size;
401ebfedea0SLionel Sambuc *ret_rr = rr;
402ebfedea0SLionel Sambuc
403ebfedea0SLionel Sambuc return 0;
404ebfedea0SLionel Sambuc }
405ebfedea0SLionel Sambuc
406ebfedea0SLionel Sambuc #ifndef TEST_RESOLVE
407ebfedea0SLionel Sambuc static
408ebfedea0SLionel Sambuc #endif
409ebfedea0SLionel Sambuc struct rk_dns_reply*
parse_reply(const unsigned char * data,size_t len)410ebfedea0SLionel Sambuc parse_reply(const unsigned char *data, size_t len)
411ebfedea0SLionel Sambuc {
412ebfedea0SLionel Sambuc const unsigned char *p;
413ebfedea0SLionel Sambuc int status;
414*0a6a1f1dSLionel Sambuc size_t i;
415ebfedea0SLionel Sambuc char host[MAXDNAME];
416ebfedea0SLionel Sambuc const unsigned char *end_data = data + len;
417ebfedea0SLionel Sambuc struct rk_dns_reply *r;
418ebfedea0SLionel Sambuc struct rk_resource_record **rr;
419ebfedea0SLionel Sambuc
420ebfedea0SLionel Sambuc r = calloc(1, sizeof(*r));
421ebfedea0SLionel Sambuc if (r == NULL)
422ebfedea0SLionel Sambuc return NULL;
423ebfedea0SLionel Sambuc
424ebfedea0SLionel Sambuc p = data;
425ebfedea0SLionel Sambuc
426ebfedea0SLionel Sambuc r->h.id = (p[0] << 8) | p[1];
427ebfedea0SLionel Sambuc r->h.flags = 0;
428ebfedea0SLionel Sambuc if (p[2] & 0x01)
429ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG;
430ebfedea0SLionel Sambuc r->h.opcode = (p[2] >> 1) & 0xf;
431ebfedea0SLionel Sambuc if (p[2] & 0x20)
432ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
433ebfedea0SLionel Sambuc if (p[2] & 0x40)
434ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE;
435ebfedea0SLionel Sambuc if (p[2] & 0x80)
436ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED;
437ebfedea0SLionel Sambuc if (p[3] & 0x01)
438ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE;
439ebfedea0SLionel Sambuc if (p[3] & 0x04)
440ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
441ebfedea0SLionel Sambuc if (p[3] & 0x08)
442ebfedea0SLionel Sambuc r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED;
443ebfedea0SLionel Sambuc r->h.response_code = (p[3] >> 4) & 0xf;
444ebfedea0SLionel Sambuc r->h.qdcount = (p[4] << 8) | p[5];
445ebfedea0SLionel Sambuc r->h.ancount = (p[6] << 8) | p[7];
446ebfedea0SLionel Sambuc r->h.nscount = (p[8] << 8) | p[9];
447ebfedea0SLionel Sambuc r->h.arcount = (p[10] << 8) | p[11];
448ebfedea0SLionel Sambuc
449ebfedea0SLionel Sambuc p += 12;
450ebfedea0SLionel Sambuc
451ebfedea0SLionel Sambuc if(r->h.qdcount != 1) {
452ebfedea0SLionel Sambuc free(r);
453ebfedea0SLionel Sambuc return NULL;
454ebfedea0SLionel Sambuc }
455ebfedea0SLionel Sambuc status = dn_expand(data, end_data, p, host, sizeof(host));
456ebfedea0SLionel Sambuc if(status < 0){
457ebfedea0SLionel Sambuc rk_dns_free_data(r);
458ebfedea0SLionel Sambuc return NULL;
459ebfedea0SLionel Sambuc }
460ebfedea0SLionel Sambuc r->q.domain = strdup(host);
461ebfedea0SLionel Sambuc if(r->q.domain == NULL) {
462ebfedea0SLionel Sambuc rk_dns_free_data(r);
463ebfedea0SLionel Sambuc return NULL;
464ebfedea0SLionel Sambuc }
465ebfedea0SLionel Sambuc if (p + status + 4 > end_data) {
466ebfedea0SLionel Sambuc rk_dns_free_data(r);
467ebfedea0SLionel Sambuc return NULL;
468ebfedea0SLionel Sambuc }
469ebfedea0SLionel Sambuc p += status;
470ebfedea0SLionel Sambuc r->q.type = (p[0] << 8 | p[1]);
471ebfedea0SLionel Sambuc p += 2;
472ebfedea0SLionel Sambuc r->q.class = (p[0] << 8 | p[1]);
473ebfedea0SLionel Sambuc p += 2;
474ebfedea0SLionel Sambuc
475ebfedea0SLionel Sambuc rr = &r->head;
476ebfedea0SLionel Sambuc for(i = 0; i < r->h.ancount; i++) {
477ebfedea0SLionel Sambuc if(parse_record(data, end_data, &p, rr) != 0) {
478ebfedea0SLionel Sambuc rk_dns_free_data(r);
479ebfedea0SLionel Sambuc return NULL;
480ebfedea0SLionel Sambuc }
481ebfedea0SLionel Sambuc rr = &(*rr)->next;
482ebfedea0SLionel Sambuc }
483ebfedea0SLionel Sambuc for(i = 0; i < r->h.nscount; i++) {
484ebfedea0SLionel Sambuc if(parse_record(data, end_data, &p, rr) != 0) {
485ebfedea0SLionel Sambuc rk_dns_free_data(r);
486ebfedea0SLionel Sambuc return NULL;
487ebfedea0SLionel Sambuc }
488ebfedea0SLionel Sambuc rr = &(*rr)->next;
489ebfedea0SLionel Sambuc }
490ebfedea0SLionel Sambuc for(i = 0; i < r->h.arcount; i++) {
491ebfedea0SLionel Sambuc if(parse_record(data, end_data, &p, rr) != 0) {
492ebfedea0SLionel Sambuc rk_dns_free_data(r);
493ebfedea0SLionel Sambuc return NULL;
494ebfedea0SLionel Sambuc }
495ebfedea0SLionel Sambuc rr = &(*rr)->next;
496ebfedea0SLionel Sambuc }
497ebfedea0SLionel Sambuc *rr = NULL;
498ebfedea0SLionel Sambuc return r;
499ebfedea0SLionel Sambuc }
500ebfedea0SLionel Sambuc
501ebfedea0SLionel Sambuc #ifdef HAVE_RES_NSEARCH
502ebfedea0SLionel Sambuc #ifdef HAVE_RES_NDESTROY
503ebfedea0SLionel Sambuc #define rk_res_free(x) res_ndestroy(x)
504ebfedea0SLionel Sambuc #else
505ebfedea0SLionel Sambuc #define rk_res_free(x) res_nclose(x)
506ebfedea0SLionel Sambuc #endif
507ebfedea0SLionel Sambuc #endif
508ebfedea0SLionel Sambuc
509ebfedea0SLionel Sambuc #if defined(HAVE_DNS_SEARCH)
510ebfedea0SLionel Sambuc #define resolve_search(h,n,c,t,r,l) \
511ebfedea0SLionel Sambuc ((int)dns_search(h,n,c,t,r,l,(struct sockaddr *)&from,&fromsize))
512ebfedea0SLionel Sambuc #define resolve_free_handle(h) dns_free(h)
513ebfedea0SLionel Sambuc #elif defined(HAVE_RES_NSEARCH)
514ebfedea0SLionel Sambuc #define resolve_search(h,n,c,t,r,l) res_nsearch(h,n,c,t,r,l)
515ebfedea0SLionel Sambuc #define resolve_free_handle(h) rk_res_free(h);
516ebfedea0SLionel Sambuc #else
517ebfedea0SLionel Sambuc #define resolve_search(h,n,c,t,r,l) res_search(n,c,t,r,l)
518ebfedea0SLionel Sambuc #define handle 0
519ebfedea0SLionel Sambuc #define resolve_free_handle(h)
520ebfedea0SLionel Sambuc #endif
521ebfedea0SLionel Sambuc
522ebfedea0SLionel Sambuc
523ebfedea0SLionel Sambuc static struct rk_dns_reply *
dns_lookup_int(const char * domain,int rr_class,int rr_type)524ebfedea0SLionel Sambuc dns_lookup_int(const char *domain, int rr_class, int rr_type)
525ebfedea0SLionel Sambuc {
526ebfedea0SLionel Sambuc struct rk_dns_reply *r;
527ebfedea0SLionel Sambuc void *reply = NULL;
528ebfedea0SLionel Sambuc int size, len;
529ebfedea0SLionel Sambuc #if defined(HAVE_DNS_SEARCH)
530ebfedea0SLionel Sambuc struct sockaddr_storage from;
531ebfedea0SLionel Sambuc uint32_t fromsize = sizeof(from);
532ebfedea0SLionel Sambuc dns_handle_t handle;
533ebfedea0SLionel Sambuc
534ebfedea0SLionel Sambuc handle = dns_open(NULL);
535ebfedea0SLionel Sambuc if (handle == NULL)
536ebfedea0SLionel Sambuc return NULL;
537ebfedea0SLionel Sambuc #elif defined(HAVE_RES_NSEARCH)
538ebfedea0SLionel Sambuc struct __res_state state;
539ebfedea0SLionel Sambuc struct __res_state *handle = &state;
540ebfedea0SLionel Sambuc
541ebfedea0SLionel Sambuc memset(&state, 0, sizeof(state));
542ebfedea0SLionel Sambuc if(res_ninit(handle))
543ebfedea0SLionel Sambuc return NULL; /* is this the best we can do? */
544ebfedea0SLionel Sambuc #endif
545ebfedea0SLionel Sambuc
546ebfedea0SLionel Sambuc len = 1500;
547ebfedea0SLionel Sambuc while(1) {
548ebfedea0SLionel Sambuc if (reply) {
549ebfedea0SLionel Sambuc free(reply);
550ebfedea0SLionel Sambuc reply = NULL;
551ebfedea0SLionel Sambuc }
552ebfedea0SLionel Sambuc if (_resolve_debug) {
553ebfedea0SLionel Sambuc #if defined(HAVE_DNS_SEARCH)
554ebfedea0SLionel Sambuc dns_set_debug(handle, 1);
555ebfedea0SLionel Sambuc #elif defined(HAVE_RES_NSEARCH)
556ebfedea0SLionel Sambuc state.options |= RES_DEBUG;
557ebfedea0SLionel Sambuc #endif
558ebfedea0SLionel Sambuc fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
559ebfedea0SLionel Sambuc rr_class, rk_dns_type_to_string(rr_type), len);
560ebfedea0SLionel Sambuc }
561ebfedea0SLionel Sambuc reply = malloc(len);
562ebfedea0SLionel Sambuc if (reply == NULL) {
563ebfedea0SLionel Sambuc resolve_free_handle(handle);
564ebfedea0SLionel Sambuc return NULL;
565ebfedea0SLionel Sambuc }
566ebfedea0SLionel Sambuc
567ebfedea0SLionel Sambuc size = resolve_search(handle, domain, rr_class, rr_type, reply, len);
568ebfedea0SLionel Sambuc
569ebfedea0SLionel Sambuc if (_resolve_debug) {
570ebfedea0SLionel Sambuc fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
571ebfedea0SLionel Sambuc domain, rr_class, rk_dns_type_to_string(rr_type), size);
572ebfedea0SLionel Sambuc }
573ebfedea0SLionel Sambuc if (size > len) {
574ebfedea0SLionel Sambuc /* resolver thinks it know better, go for it */
575ebfedea0SLionel Sambuc len = size;
576ebfedea0SLionel Sambuc } else if (size > 0) {
577ebfedea0SLionel Sambuc /* got a good reply */
578ebfedea0SLionel Sambuc break;
579ebfedea0SLionel Sambuc } else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) {
580ebfedea0SLionel Sambuc len *= 2;
581ebfedea0SLionel Sambuc if (len > rk_DNS_MAX_PACKET_SIZE)
582ebfedea0SLionel Sambuc len = rk_DNS_MAX_PACKET_SIZE;
583ebfedea0SLionel Sambuc } else {
584ebfedea0SLionel Sambuc /* the end, leave */
585ebfedea0SLionel Sambuc resolve_free_handle(handle);
586ebfedea0SLionel Sambuc free(reply);
587ebfedea0SLionel Sambuc return NULL;
588ebfedea0SLionel Sambuc }
589ebfedea0SLionel Sambuc }
590ebfedea0SLionel Sambuc
591ebfedea0SLionel Sambuc len = min(len, size);
592ebfedea0SLionel Sambuc r = parse_reply(reply, len);
593ebfedea0SLionel Sambuc free(reply);
594*0a6a1f1dSLionel Sambuc
595*0a6a1f1dSLionel Sambuc resolve_free_handle(handle);
596*0a6a1f1dSLionel Sambuc
597ebfedea0SLionel Sambuc return r;
598ebfedea0SLionel Sambuc }
599ebfedea0SLionel Sambuc
600ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)601ebfedea0SLionel Sambuc rk_dns_lookup(const char *domain, const char *type_name)
602ebfedea0SLionel Sambuc {
603ebfedea0SLionel Sambuc int type;
604ebfedea0SLionel Sambuc
605ebfedea0SLionel Sambuc type = rk_dns_string_to_type(type_name);
606ebfedea0SLionel Sambuc if(type == -1) {
607ebfedea0SLionel Sambuc if(_resolve_debug)
608ebfedea0SLionel Sambuc fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
609ebfedea0SLionel Sambuc type_name);
610ebfedea0SLionel Sambuc return NULL;
611ebfedea0SLionel Sambuc }
612ebfedea0SLionel Sambuc return dns_lookup_int(domain, rk_ns_c_in, type);
613ebfedea0SLionel Sambuc }
614ebfedea0SLionel Sambuc
615ebfedea0SLionel Sambuc #endif /* !HAVE_WINDNS */
616ebfedea0SLionel Sambuc
617ebfedea0SLionel Sambuc static int
compare_srv(const void * a,const void * b)618ebfedea0SLionel Sambuc compare_srv(const void *a, const void *b)
619ebfedea0SLionel Sambuc {
620ebfedea0SLionel Sambuc const struct rk_resource_record *const* aa = a, *const* bb = b;
621ebfedea0SLionel Sambuc
622ebfedea0SLionel Sambuc if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
623ebfedea0SLionel Sambuc return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
624ebfedea0SLionel Sambuc return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
625ebfedea0SLionel Sambuc }
626ebfedea0SLionel Sambuc
627ebfedea0SLionel Sambuc /* try to rearrange the srv-records by the algorithm in RFC2782 */
628ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_srv_order(struct rk_dns_reply * r)629ebfedea0SLionel Sambuc rk_dns_srv_order(struct rk_dns_reply *r)
630ebfedea0SLionel Sambuc {
631ebfedea0SLionel Sambuc struct rk_resource_record **srvs, **ss, **headp;
632ebfedea0SLionel Sambuc struct rk_resource_record *rr;
633ebfedea0SLionel Sambuc int num_srv = 0;
634ebfedea0SLionel Sambuc
635ebfedea0SLionel Sambuc rk_random_init();
636ebfedea0SLionel Sambuc
637ebfedea0SLionel Sambuc for(rr = r->head; rr; rr = rr->next)
638ebfedea0SLionel Sambuc if(rr->type == rk_ns_t_srv)
639ebfedea0SLionel Sambuc num_srv++;
640ebfedea0SLionel Sambuc
641ebfedea0SLionel Sambuc if(num_srv == 0)
642ebfedea0SLionel Sambuc return;
643ebfedea0SLionel Sambuc
644ebfedea0SLionel Sambuc srvs = malloc(num_srv * sizeof(*srvs));
645ebfedea0SLionel Sambuc if(srvs == NULL)
646ebfedea0SLionel Sambuc return; /* XXX not much to do here */
647ebfedea0SLionel Sambuc
648ebfedea0SLionel Sambuc /* unlink all srv-records from the linked list and put them in
649ebfedea0SLionel Sambuc a vector */
650ebfedea0SLionel Sambuc for(ss = srvs, headp = &r->head; *headp; )
651ebfedea0SLionel Sambuc if((*headp)->type == rk_ns_t_srv) {
652ebfedea0SLionel Sambuc *ss = *headp;
653ebfedea0SLionel Sambuc *headp = (*headp)->next;
654ebfedea0SLionel Sambuc (*ss)->next = NULL;
655ebfedea0SLionel Sambuc ss++;
656ebfedea0SLionel Sambuc } else
657ebfedea0SLionel Sambuc headp = &(*headp)->next;
658ebfedea0SLionel Sambuc
659ebfedea0SLionel Sambuc /* sort them by priority and weight */
660ebfedea0SLionel Sambuc qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
661ebfedea0SLionel Sambuc
662ebfedea0SLionel Sambuc headp = &r->head;
663ebfedea0SLionel Sambuc
664ebfedea0SLionel Sambuc for(ss = srvs; ss < srvs + num_srv; ) {
665ebfedea0SLionel Sambuc int sum, rnd, count;
666ebfedea0SLionel Sambuc struct rk_resource_record **ee, **tt;
667ebfedea0SLionel Sambuc /* find the last record with the same priority and count the
668ebfedea0SLionel Sambuc sum of all weights */
669ebfedea0SLionel Sambuc for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
670ebfedea0SLionel Sambuc assert(*tt != NULL);
671ebfedea0SLionel Sambuc if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
672ebfedea0SLionel Sambuc break;
673ebfedea0SLionel Sambuc sum += (*tt)->u.srv->weight;
674ebfedea0SLionel Sambuc }
675ebfedea0SLionel Sambuc ee = tt;
676ebfedea0SLionel Sambuc /* ss is now the first record of this priority and ee is the
677ebfedea0SLionel Sambuc first of the next */
678ebfedea0SLionel Sambuc while(ss < ee) {
679ebfedea0SLionel Sambuc rnd = rk_random() % (sum + 1);
680ebfedea0SLionel Sambuc for(count = 0, tt = ss; ; tt++) {
681ebfedea0SLionel Sambuc if(*tt == NULL)
682ebfedea0SLionel Sambuc continue;
683ebfedea0SLionel Sambuc count += (*tt)->u.srv->weight;
684ebfedea0SLionel Sambuc if(count >= rnd)
685ebfedea0SLionel Sambuc break;
686ebfedea0SLionel Sambuc }
687ebfedea0SLionel Sambuc
688ebfedea0SLionel Sambuc assert(tt < ee);
689ebfedea0SLionel Sambuc
690ebfedea0SLionel Sambuc /* insert the selected record at the tail (of the head) of
691ebfedea0SLionel Sambuc the list */
692ebfedea0SLionel Sambuc (*tt)->next = *headp;
693ebfedea0SLionel Sambuc *headp = *tt;
694ebfedea0SLionel Sambuc headp = &(*tt)->next;
695ebfedea0SLionel Sambuc sum -= (*tt)->u.srv->weight;
696ebfedea0SLionel Sambuc *tt = NULL;
697ebfedea0SLionel Sambuc while(ss < ee && *ss == NULL)
698ebfedea0SLionel Sambuc ss++;
699ebfedea0SLionel Sambuc }
700ebfedea0SLionel Sambuc }
701ebfedea0SLionel Sambuc
702ebfedea0SLionel Sambuc free(srvs);
703ebfedea0SLionel Sambuc return;
704ebfedea0SLionel Sambuc }
705ebfedea0SLionel Sambuc
706ebfedea0SLionel Sambuc #ifdef HAVE_WINDNS
707ebfedea0SLionel Sambuc
708ebfedea0SLionel Sambuc #include <WinDNS.h>
709ebfedea0SLionel Sambuc
710ebfedea0SLionel Sambuc static struct rk_resource_record *
parse_dns_record(PDNS_RECORD pRec)711ebfedea0SLionel Sambuc parse_dns_record(PDNS_RECORD pRec)
712ebfedea0SLionel Sambuc {
713ebfedea0SLionel Sambuc struct rk_resource_record * rr;
714ebfedea0SLionel Sambuc
715ebfedea0SLionel Sambuc if (pRec == NULL)
716ebfedea0SLionel Sambuc return NULL;
717ebfedea0SLionel Sambuc
718ebfedea0SLionel Sambuc rr = calloc(1, sizeof(*rr));
719ebfedea0SLionel Sambuc
720ebfedea0SLionel Sambuc rr->domain = strdup(pRec->pName);
721ebfedea0SLionel Sambuc rr->type = pRec->wType;
722ebfedea0SLionel Sambuc rr->class = 0;
723ebfedea0SLionel Sambuc rr->ttl = pRec->dwTtl;
724ebfedea0SLionel Sambuc rr->size = 0;
725ebfedea0SLionel Sambuc
726ebfedea0SLionel Sambuc switch (rr->type) {
727ebfedea0SLionel Sambuc case rk_ns_t_ns:
728ebfedea0SLionel Sambuc case rk_ns_t_cname:
729ebfedea0SLionel Sambuc case rk_ns_t_ptr:
730ebfedea0SLionel Sambuc rr->u.txt = strdup(pRec->Data.NS.pNameHost);
731ebfedea0SLionel Sambuc if(rr->u.txt == NULL) {
732ebfedea0SLionel Sambuc dns_free_rr(rr);
733ebfedea0SLionel Sambuc return NULL;
734ebfedea0SLionel Sambuc }
735ebfedea0SLionel Sambuc break;
736ebfedea0SLionel Sambuc
737ebfedea0SLionel Sambuc case rk_ns_t_mx:
738ebfedea0SLionel Sambuc case rk_ns_t_afsdb:{
739ebfedea0SLionel Sambuc size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH);
740ebfedea0SLionel Sambuc
741ebfedea0SLionel Sambuc rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) +
742ebfedea0SLionel Sambuc hostlen);
743ebfedea0SLionel Sambuc if (rr->u.mx == NULL) {
744ebfedea0SLionel Sambuc dns_free_rr(rr);
745ebfedea0SLionel Sambuc return NULL;
746ebfedea0SLionel Sambuc }
747ebfedea0SLionel Sambuc
748ebfedea0SLionel Sambuc strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange);
749ebfedea0SLionel Sambuc rr->u.mx->preference = pRec->Data.MX.wPreference;
750ebfedea0SLionel Sambuc break;
751ebfedea0SLionel Sambuc }
752ebfedea0SLionel Sambuc
753ebfedea0SLionel Sambuc case rk_ns_t_srv:{
754ebfedea0SLionel Sambuc size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH);
755ebfedea0SLionel Sambuc
756ebfedea0SLionel Sambuc rr->u.srv =
757ebfedea0SLionel Sambuc (struct srv_record*)malloc(sizeof(struct srv_record) +
758ebfedea0SLionel Sambuc hostlen);
759ebfedea0SLionel Sambuc if(rr->u.srv == NULL) {
760ebfedea0SLionel Sambuc dns_free_rr(rr);
761ebfedea0SLionel Sambuc return NULL;
762ebfedea0SLionel Sambuc }
763ebfedea0SLionel Sambuc
764ebfedea0SLionel Sambuc rr->u.srv->priority = pRec->Data.SRV.wPriority;
765ebfedea0SLionel Sambuc rr->u.srv->weight = pRec->Data.SRV.wWeight;
766ebfedea0SLionel Sambuc rr->u.srv->port = pRec->Data.SRV.wPort;
767ebfedea0SLionel Sambuc strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget);
768ebfedea0SLionel Sambuc
769ebfedea0SLionel Sambuc break;
770ebfedea0SLionel Sambuc }
771ebfedea0SLionel Sambuc
772ebfedea0SLionel Sambuc case rk_ns_t_txt:{
773ebfedea0SLionel Sambuc size_t len;
774ebfedea0SLionel Sambuc
775ebfedea0SLionel Sambuc if (pRec->Data.TXT.dwStringCount == 0) {
776ebfedea0SLionel Sambuc rr->u.txt = strdup("");
777ebfedea0SLionel Sambuc break;
778ebfedea0SLionel Sambuc }
779ebfedea0SLionel Sambuc
780ebfedea0SLionel Sambuc len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH);
781ebfedea0SLionel Sambuc
782ebfedea0SLionel Sambuc rr->u.txt = (char *)malloc(len + 1);
783ebfedea0SLionel Sambuc strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]);
784ebfedea0SLionel Sambuc
785ebfedea0SLionel Sambuc break;
786ebfedea0SLionel Sambuc }
787ebfedea0SLionel Sambuc
788ebfedea0SLionel Sambuc case rk_ns_t_key : {
789ebfedea0SLionel Sambuc size_t key_len;
790ebfedea0SLionel Sambuc
791ebfedea0SLionel Sambuc if (pRec->wDataLength < 4) {
792ebfedea0SLionel Sambuc dns_free_rr(rr);
793ebfedea0SLionel Sambuc return NULL;
794ebfedea0SLionel Sambuc }
795ebfedea0SLionel Sambuc
796ebfedea0SLionel Sambuc key_len = pRec->wDataLength - 4;
797ebfedea0SLionel Sambuc rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
798ebfedea0SLionel Sambuc if (rr->u.key == NULL) {
799ebfedea0SLionel Sambuc dns_free_rr(rr);
800ebfedea0SLionel Sambuc return NULL;
801ebfedea0SLionel Sambuc }
802ebfedea0SLionel Sambuc
803ebfedea0SLionel Sambuc rr->u.key->flags = pRec->Data.KEY.wFlags;
804ebfedea0SLionel Sambuc rr->u.key->protocol = pRec->Data.KEY.chProtocol;
805ebfedea0SLionel Sambuc rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm;
806ebfedea0SLionel Sambuc rr->u.key->key_len = key_len;
807ebfedea0SLionel Sambuc memcpy_s (rr->u.key->key_data, key_len,
808ebfedea0SLionel Sambuc pRec->Data.KEY.Key, key_len);
809ebfedea0SLionel Sambuc break;
810ebfedea0SLionel Sambuc }
811ebfedea0SLionel Sambuc
812ebfedea0SLionel Sambuc case rk_ns_t_sig : {
813ebfedea0SLionel Sambuc size_t sig_len, hostlen;
814ebfedea0SLionel Sambuc
815ebfedea0SLionel Sambuc if(pRec->wDataLength <= 18) {
816ebfedea0SLionel Sambuc dns_free_rr(rr);
817ebfedea0SLionel Sambuc return NULL;
818ebfedea0SLionel Sambuc }
819ebfedea0SLionel Sambuc
820ebfedea0SLionel Sambuc sig_len = pRec->wDataLength;
821ebfedea0SLionel Sambuc
822ebfedea0SLionel Sambuc hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH);
823ebfedea0SLionel Sambuc
824ebfedea0SLionel Sambuc rr->u.sig = malloc(sizeof(*rr->u.sig)
825ebfedea0SLionel Sambuc + hostlen + sig_len);
826ebfedea0SLionel Sambuc if (rr->u.sig == NULL) {
827ebfedea0SLionel Sambuc dns_free_rr(rr);
828ebfedea0SLionel Sambuc return NULL;
829ebfedea0SLionel Sambuc }
830ebfedea0SLionel Sambuc rr->u.sig->type = pRec->Data.SIG.wTypeCovered;
831ebfedea0SLionel Sambuc rr->u.sig->algorithm = pRec->Data.SIG.chAlgorithm;
832ebfedea0SLionel Sambuc rr->u.sig->labels = pRec->Data.SIG.chLabelCount;
833ebfedea0SLionel Sambuc rr->u.sig->orig_ttl = pRec->Data.SIG.dwOriginalTtl;
834ebfedea0SLionel Sambuc rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration;
835ebfedea0SLionel Sambuc rr->u.sig->sig_inception = pRec->Data.SIG.dwTimeSigned;
836ebfedea0SLionel Sambuc rr->u.sig->key_tag = pRec->Data.SIG.wKeyTag;
837ebfedea0SLionel Sambuc rr->u.sig->sig_len = sig_len;
838ebfedea0SLionel Sambuc memcpy_s (rr->u.sig->sig_data, sig_len,
839ebfedea0SLionel Sambuc pRec->Data.SIG.Signature, sig_len);
840ebfedea0SLionel Sambuc rr->u.sig->signer = &rr->u.sig->sig_data[sig_len];
841ebfedea0SLionel Sambuc strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner);
842ebfedea0SLionel Sambuc break;
843ebfedea0SLionel Sambuc }
844ebfedea0SLionel Sambuc
845ebfedea0SLionel Sambuc #ifdef DNS_TYPE_DS
846ebfedea0SLionel Sambuc case rk_ns_t_ds: {
847ebfedea0SLionel Sambuc rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1);
848ebfedea0SLionel Sambuc if (rr->u.ds == NULL) {
849ebfedea0SLionel Sambuc dns_free_rr(rr);
850ebfedea0SLionel Sambuc return NULL;
851ebfedea0SLionel Sambuc }
852ebfedea0SLionel Sambuc
853ebfedea0SLionel Sambuc rr->u.ds->key_tag = pRec->Data.DS.wKeyTag;
854ebfedea0SLionel Sambuc rr->u.ds->algorithm = pRec->Data.DS.chAlgorithm;
855ebfedea0SLionel Sambuc rr->u.ds->digest_type = pRec->Data.DS.chDigestType;
856ebfedea0SLionel Sambuc rr->u.ds->digest_len = pRec->Data.DS.wDigestLength;
857ebfedea0SLionel Sambuc memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength,
858ebfedea0SLionel Sambuc pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength);
859ebfedea0SLionel Sambuc break;
860ebfedea0SLionel Sambuc }
861ebfedea0SLionel Sambuc #endif
862ebfedea0SLionel Sambuc
863ebfedea0SLionel Sambuc default:
864ebfedea0SLionel Sambuc dns_free_rr(rr);
865ebfedea0SLionel Sambuc return NULL;
866ebfedea0SLionel Sambuc }
867ebfedea0SLionel Sambuc
868ebfedea0SLionel Sambuc rr->next = parse_dns_record(pRec->pNext);
869ebfedea0SLionel Sambuc return rr;
870ebfedea0SLionel Sambuc }
871ebfedea0SLionel Sambuc
872ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)873ebfedea0SLionel Sambuc rk_dns_lookup(const char *domain, const char *type_name)
874ebfedea0SLionel Sambuc {
875ebfedea0SLionel Sambuc DNS_STATUS status;
876ebfedea0SLionel Sambuc int type;
877ebfedea0SLionel Sambuc PDNS_RECORD pRec = NULL;
878ebfedea0SLionel Sambuc struct rk_dns_reply * r = NULL;
879ebfedea0SLionel Sambuc
880ebfedea0SLionel Sambuc __try {
881ebfedea0SLionel Sambuc
882ebfedea0SLionel Sambuc type = rk_dns_string_to_type(type_name);
883ebfedea0SLionel Sambuc if(type == -1) {
884ebfedea0SLionel Sambuc if(_resolve_debug)
885ebfedea0SLionel Sambuc fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
886ebfedea0SLionel Sambuc type_name);
887ebfedea0SLionel Sambuc return NULL;
888ebfedea0SLionel Sambuc }
889ebfedea0SLionel Sambuc
890ebfedea0SLionel Sambuc status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL,
891ebfedea0SLionel Sambuc &pRec, NULL);
892ebfedea0SLionel Sambuc if (status != ERROR_SUCCESS)
893ebfedea0SLionel Sambuc return NULL;
894ebfedea0SLionel Sambuc
895ebfedea0SLionel Sambuc r = calloc(1, sizeof(*r));
896ebfedea0SLionel Sambuc r->q.domain = strdup(domain);
897ebfedea0SLionel Sambuc r->q.type = type;
898ebfedea0SLionel Sambuc r->q.class = 0;
899ebfedea0SLionel Sambuc
900ebfedea0SLionel Sambuc r->head = parse_dns_record(pRec);
901ebfedea0SLionel Sambuc
902ebfedea0SLionel Sambuc if (r->head == NULL) {
903ebfedea0SLionel Sambuc rk_dns_free_data(r);
904ebfedea0SLionel Sambuc return NULL;
905ebfedea0SLionel Sambuc } else {
906ebfedea0SLionel Sambuc return r;
907ebfedea0SLionel Sambuc }
908ebfedea0SLionel Sambuc
909ebfedea0SLionel Sambuc } __finally {
910ebfedea0SLionel Sambuc
911ebfedea0SLionel Sambuc if (pRec)
912ebfedea0SLionel Sambuc DnsRecordListFree(pRec, DnsFreeRecordList);
913ebfedea0SLionel Sambuc
914ebfedea0SLionel Sambuc }
915ebfedea0SLionel Sambuc }
916ebfedea0SLionel Sambuc #endif /* HAVE_WINDNS */
917ebfedea0SLionel Sambuc
918ebfedea0SLionel Sambuc #else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
919ebfedea0SLionel Sambuc
920ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char * domain,const char * type_name)921ebfedea0SLionel Sambuc rk_dns_lookup(const char *domain, const char *type_name)
922ebfedea0SLionel Sambuc {
923ebfedea0SLionel Sambuc return NULL;
924ebfedea0SLionel Sambuc }
925ebfedea0SLionel Sambuc
926ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_free_data(struct rk_dns_reply * r)927ebfedea0SLionel Sambuc rk_dns_free_data(struct rk_dns_reply *r)
928ebfedea0SLionel Sambuc {
929ebfedea0SLionel Sambuc }
930ebfedea0SLionel Sambuc
931ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
rk_dns_srv_order(struct rk_dns_reply * r)932ebfedea0SLionel Sambuc rk_dns_srv_order(struct rk_dns_reply *r)
933ebfedea0SLionel Sambuc {
934ebfedea0SLionel Sambuc }
935ebfedea0SLionel Sambuc
936ebfedea0SLionel Sambuc #endif
937