resolve.c revision 102644
155682Smarkm/*
2102644Snectar * Copyright (c) 1995 - 2002 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#ifdef HAVE_CONFIG_H
3555682Smarkm#include <config.h>
3655682Smarkm#endif
3755682Smarkm#include "roken.h"
3855682Smarkm#ifdef HAVE_ARPA_NAMESER_H
3955682Smarkm#include <arpa/nameser.h>
4055682Smarkm#endif
4155682Smarkm#ifdef HAVE_RESOLV_H
4255682Smarkm#include <resolv.h>
4355682Smarkm#endif
4455682Smarkm#include "resolve.h"
4555682Smarkm
4690926Snectar#include <assert.h>
4755682Smarkm
48102644SnectarRCSID("$Id: resolve.c,v 1.33 2002/08/28 20:07:24 joda Exp $");
4990926Snectar
5055682Smarkm#if defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND)
5155682Smarkm
5255682Smarkm#define DECL(X) {#X, T_##X}
5355682Smarkm
5455682Smarkmstatic struct stot{
5555682Smarkm    const char *name;
5655682Smarkm    int type;
5755682Smarkm}stot[] = {
5855682Smarkm    DECL(A),
5955682Smarkm    DECL(NS),
6055682Smarkm    DECL(CNAME),
6172445Sassar    DECL(SOA),
6255682Smarkm    DECL(PTR),
6355682Smarkm    DECL(MX),
6455682Smarkm    DECL(TXT),
6555682Smarkm    DECL(AFSDB),
6672445Sassar    DECL(SIG),
6772445Sassar    DECL(KEY),
6855682Smarkm    DECL(SRV),
6972445Sassar    DECL(NAPTR),
7055682Smarkm    {NULL, 	0}
7155682Smarkm};
7255682Smarkm
7372445Sassarint _resolve_debug = 0;
7455682Smarkm
7572445Sassarint
7672445Sassardns_string_to_type(const char *name)
7755682Smarkm{
7855682Smarkm    struct stot *p = stot;
7955682Smarkm    for(p = stot; p->name; p++)
8055682Smarkm	if(strcasecmp(name, p->name) == 0)
8155682Smarkm	    return p->type;
8255682Smarkm    return -1;
8355682Smarkm}
8455682Smarkm
8572445Sassarconst char *
8672445Sassardns_type_to_string(int type)
8755682Smarkm{
8855682Smarkm    struct stot *p = stot;
8955682Smarkm    for(p = stot; p->name; p++)
9055682Smarkm	if(type == p->type)
9155682Smarkm	    return p->name;
9255682Smarkm    return NULL;
9355682Smarkm}
9455682Smarkm
9555682Smarkmvoid
9655682Smarkmdns_free_data(struct dns_reply *r)
9755682Smarkm{
9855682Smarkm    struct resource_record *rr;
9955682Smarkm    if(r->q.domain)
10055682Smarkm	free(r->q.domain);
10155682Smarkm    for(rr = r->head; rr;){
10255682Smarkm	struct resource_record *tmp = rr;
10355682Smarkm	if(rr->domain)
10455682Smarkm	    free(rr->domain);
10555682Smarkm	if(rr->u.data)
10655682Smarkm	    free(rr->u.data);
10755682Smarkm	rr = rr->next;
10855682Smarkm	free(tmp);
10955682Smarkm    }
11055682Smarkm    free (r);
11155682Smarkm}
11255682Smarkm
11355682Smarkmstatic struct dns_reply*
11455682Smarkmparse_reply(unsigned char *data, int len)
11555682Smarkm{
116102644Snectar    const unsigned char *p;
11755682Smarkm    char host[128];
11855682Smarkm    int status;
119102644Snectar    const unsigned char *end_data = data + len;
12055682Smarkm    struct dns_reply *r;
12155682Smarkm    struct resource_record **rr;
12255682Smarkm
12355682Smarkm    r = calloc(1, sizeof(*r));
12455682Smarkm    if (r == NULL)
12555682Smarkm	return NULL;
12655682Smarkm
12755682Smarkm    p = data;
12855682Smarkm#if 0
12955682Smarkm    /* doesn't work on Crays */
13055682Smarkm    memcpy(&r->h, p, sizeof(HEADER));
13155682Smarkm    p += sizeof(HEADER);
13255682Smarkm#else
13355682Smarkm    memcpy(&r->h, p, 12); /* XXX this will probably be mostly garbage */
13455682Smarkm    p += 12;
13555682Smarkm#endif
136102644Snectar    status = dn_expand(data, end_data, p, host, sizeof(host));
13755682Smarkm    if(status < 0){
13855682Smarkm	dns_free_data(r);
13955682Smarkm	return NULL;
14055682Smarkm    }
14155682Smarkm    r->q.domain = strdup(host);
14255682Smarkm    if(r->q.domain == NULL) {
14355682Smarkm	dns_free_data(r);
14455682Smarkm	return NULL;
14555682Smarkm    }
146102644Snectar    if (p + status + 4 > end_data) {
147102644Snectar	dns_free_data(r);
148102644Snectar	return NULL;
149102644Snectar    }
15055682Smarkm    p += status;
15155682Smarkm    r->q.type = (p[0] << 8 | p[1]);
15255682Smarkm    p += 2;
15355682Smarkm    r->q.class = (p[0] << 8 | p[1]);
15455682Smarkm    p += 2;
15555682Smarkm    rr = &r->head;
156102644Snectar    while(p < end_data){
15755682Smarkm	int type, class, ttl, size;
158102644Snectar	status = dn_expand(data, end_data, p, host, sizeof(host));
15955682Smarkm	if(status < 0){
16055682Smarkm	    dns_free_data(r);
16155682Smarkm	    return NULL;
16255682Smarkm	}
163102644Snectar	if (p + status + 10 > end_data) {
164102644Snectar	    dns_free_data(r);
165102644Snectar	    return NULL;
166102644Snectar	}
16755682Smarkm	p += status;
16855682Smarkm	type = (p[0] << 8) | p[1];
16955682Smarkm	p += 2;
17055682Smarkm	class = (p[0] << 8) | p[1];
17155682Smarkm	p += 2;
17255682Smarkm	ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
17355682Smarkm	p += 4;
17455682Smarkm	size = (p[0] << 8) | p[1];
17555682Smarkm	p += 2;
176102644Snectar
177102644Snectar	if (p + size > end_data) {
178102644Snectar	    dns_free_data(r);
179102644Snectar	    return NULL;
180102644Snectar	}
181102644Snectar
18255682Smarkm	*rr = (struct resource_record*)calloc(1,
18355682Smarkm					      sizeof(struct resource_record));
18455682Smarkm	if(*rr == NULL) {
18555682Smarkm	    dns_free_data(r);
18655682Smarkm	    return NULL;
18755682Smarkm	}
18855682Smarkm	(*rr)->domain = strdup(host);
18955682Smarkm	if((*rr)->domain == NULL) {
19055682Smarkm	    dns_free_data(r);
19155682Smarkm	    return NULL;
19255682Smarkm	}
19355682Smarkm	(*rr)->type = type;
19455682Smarkm	(*rr)->class = class;
19555682Smarkm	(*rr)->ttl = ttl;
19655682Smarkm	(*rr)->size = size;
19755682Smarkm	switch(type){
19855682Smarkm	case T_NS:
19955682Smarkm	case T_CNAME:
20055682Smarkm	case T_PTR:
201102644Snectar	    status = dn_expand(data, end_data, p, host, sizeof(host));
20255682Smarkm	    if(status < 0){
20355682Smarkm		dns_free_data(r);
20455682Smarkm		return NULL;
20555682Smarkm	    }
20655682Smarkm	    (*rr)->u.txt = strdup(host);
20755682Smarkm	    if((*rr)->u.txt == NULL) {
20855682Smarkm		dns_free_data(r);
20955682Smarkm		return NULL;
21055682Smarkm	    }
21155682Smarkm	    break;
21255682Smarkm	case T_MX:
21355682Smarkm	case T_AFSDB:{
214102644Snectar	    status = dn_expand(data, end_data, p + 2, host, sizeof(host));
21555682Smarkm	    if(status < 0){
21655682Smarkm		dns_free_data(r);
21755682Smarkm		return NULL;
21855682Smarkm	    }
219102644Snectar	    if (status + 2 > size) {
220102644Snectar		dns_free_data(r);
221102644Snectar		return NULL;
222102644Snectar	    }
223102644Snectar
22455682Smarkm	    (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
22555682Smarkm						    strlen(host));
22655682Smarkm	    if((*rr)->u.mx == NULL) {
22755682Smarkm		dns_free_data(r);
22855682Smarkm		return NULL;
22955682Smarkm	    }
23055682Smarkm	    (*rr)->u.mx->preference = (p[0] << 8) | p[1];
23155682Smarkm	    strcpy((*rr)->u.mx->domain, host);
23255682Smarkm	    break;
23355682Smarkm	}
23455682Smarkm	case T_SRV:{
235102644Snectar	    status = dn_expand(data, end_data, p + 6, host, sizeof(host));
23655682Smarkm	    if(status < 0){
23755682Smarkm		dns_free_data(r);
23855682Smarkm		return NULL;
23955682Smarkm	    }
240102644Snectar	    if (status + 6 > size) {
241102644Snectar		dns_free_data(r);
242102644Snectar		return NULL;
243102644Snectar	    }
244102644Snectar
24555682Smarkm	    (*rr)->u.srv =
24655682Smarkm		(struct srv_record*)malloc(sizeof(struct srv_record) +
24755682Smarkm					   strlen(host));
24855682Smarkm	    if((*rr)->u.srv == NULL) {
24955682Smarkm		dns_free_data(r);
25055682Smarkm		return NULL;
25155682Smarkm	    }
25255682Smarkm	    (*rr)->u.srv->priority = (p[0] << 8) | p[1];
25355682Smarkm	    (*rr)->u.srv->weight = (p[2] << 8) | p[3];
25455682Smarkm	    (*rr)->u.srv->port = (p[4] << 8) | p[5];
25555682Smarkm	    strcpy((*rr)->u.srv->target, host);
25655682Smarkm	    break;
25755682Smarkm	}
25855682Smarkm	case T_TXT:{
25955682Smarkm	    (*rr)->u.txt = (char*)malloc(size + 1);
26055682Smarkm	    if((*rr)->u.txt == NULL) {
26155682Smarkm		dns_free_data(r);
26255682Smarkm		return NULL;
26355682Smarkm	    }
26455682Smarkm	    strncpy((*rr)->u.txt, (char*)p + 1, *p);
26555682Smarkm	    (*rr)->u.txt[*p] = 0;
26655682Smarkm	    break;
26755682Smarkm	}
26872445Sassar	case T_KEY : {
26972445Sassar	    size_t key_len;
27072445Sassar
271102644Snectar	    if (size < 4) {
272102644Snectar		dns_free_data (r);
273102644Snectar		return NULL;
274102644Snectar	    }
275102644Snectar
27672445Sassar	    key_len = size - 4;
27772445Sassar	    (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1);
27872445Sassar	    if ((*rr)->u.key == NULL) {
27972445Sassar		dns_free_data (r);
28072445Sassar		return NULL;
28172445Sassar	    }
28272445Sassar
28372445Sassar	    (*rr)->u.key->flags     = (p[0] << 8) | p[1];
28472445Sassar	    (*rr)->u.key->protocol  = p[2];
28572445Sassar	    (*rr)->u.key->algorithm = p[3];
28672445Sassar	    (*rr)->u.key->key_len   = key_len;
28772445Sassar	    memcpy ((*rr)->u.key->key_data, p + 4, key_len);
28872445Sassar	    break;
28972445Sassar	}
29072445Sassar	case T_SIG : {
29172445Sassar	    size_t sig_len;
29272445Sassar
293102644Snectar	    status = dn_expand (data, end_data, p + 18, host, sizeof(host));
29472445Sassar	    if (status < 0) {
29572445Sassar		dns_free_data (r);
29672445Sassar		return NULL;
29772445Sassar	    }
298102644Snectar	    if (status + 18 > size) {
299102644Snectar		dns_free_data(r);
300102644Snectar		return NULL;
301102644Snectar	    }
302102644Snectar
30372445Sassar	    sig_len = len - 18 - status;
30472445Sassar	    (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig)
30572445Sassar				  + strlen(host) + sig_len);
30672445Sassar	    if ((*rr)->u.sig == NULL) {
30772445Sassar		dns_free_data (r);
30872445Sassar		return NULL;
30972445Sassar	    }
31072445Sassar	    (*rr)->u.sig->type           = (p[0] << 8) | p[1];
31172445Sassar	    (*rr)->u.sig->algorithm      = p[2];
31272445Sassar	    (*rr)->u.sig->labels         = p[3];
31372445Sassar	    (*rr)->u.sig->orig_ttl       = (p[4] << 24) | (p[5] << 16)
31472445Sassar		| (p[6] << 8) | p[7];
31572445Sassar	    (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
31672445Sassar		| (p[10] << 8) | p[11];
31772445Sassar	    (*rr)->u.sig->sig_inception  = (p[12] << 24) | (p[13] << 16)
31872445Sassar		| (p[14] << 8) | p[15];
31972445Sassar	    (*rr)->u.sig->key_tag        = (p[16] << 8) | p[17];
32072445Sassar	    (*rr)->u.sig->sig_len        = sig_len;
32172445Sassar	    memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len);
32272445Sassar	    (*rr)->u.sig->signer         = &(*rr)->u.sig->sig_data[sig_len];
32372445Sassar	    strcpy((*rr)->u.sig->signer, host);
32472445Sassar	    break;
32572445Sassar	}
32672445Sassar
32772445Sassar	case T_CERT : {
32872445Sassar	    size_t cert_len;
32972445Sassar
330102644Snectar	    if (size < 5) {
331102644Snectar		dns_free_data(r);
332102644Snectar		return NULL;
333102644Snectar	    }
334102644Snectar
33572445Sassar	    cert_len = size - 5;
33672445Sassar	    (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1);
33772445Sassar	    if ((*rr)->u.cert == NULL) {
33872445Sassar		dns_free_data (r);
33972445Sassar		return NULL;
34072445Sassar	    }
34172445Sassar
34272445Sassar	    (*rr)->u.cert->type      = (p[0] << 8) | p[1];
34372445Sassar	    (*rr)->u.cert->tag       = (p[2] << 8) | p[3];
34472445Sassar	    (*rr)->u.cert->algorithm = p[4];
34572445Sassar	    (*rr)->u.cert->cert_len  = cert_len;
34672445Sassar	    memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len);
34772445Sassar	    break;
34872445Sassar	}
34955682Smarkm	default:
35055682Smarkm	    (*rr)->u.data = (unsigned char*)malloc(size);
35155682Smarkm	    if(size != 0 && (*rr)->u.data == NULL) {
35255682Smarkm		dns_free_data(r);
35355682Smarkm		return NULL;
35455682Smarkm	    }
35555682Smarkm	    memcpy((*rr)->u.data, p, size);
35655682Smarkm	}
35755682Smarkm	p += size;
35855682Smarkm	rr = &(*rr)->next;
35955682Smarkm    }
36055682Smarkm    *rr = NULL;
36155682Smarkm    return r;
36255682Smarkm}
36355682Smarkm
36455682Smarkmstatic struct dns_reply *
36555682Smarkmdns_lookup_int(const char *domain, int rr_class, int rr_type)
36655682Smarkm{
36755682Smarkm    unsigned char reply[1024];
36855682Smarkm    int len;
369102644Snectar#ifdef HAVE__RES
37055682Smarkm    u_long old_options = 0;
371102644Snectar#endif
37255682Smarkm
37355682Smarkm    if (_resolve_debug) {
374102644Snectar#ifdef HAVE__RES
37555682Smarkm        old_options = _res.options;
37655682Smarkm	_res.options |= RES_DEBUG;
377102644Snectar#endif
37855682Smarkm	fprintf(stderr, "dns_lookup(%s, %d, %s)\n", domain,
37972445Sassar		rr_class, dns_type_to_string(rr_type));
38055682Smarkm    }
38155682Smarkm    len = res_search(domain, rr_class, rr_type, reply, sizeof(reply));
38255682Smarkm    if (_resolve_debug) {
383102644Snectar#ifdef HAVE__RES
38455682Smarkm        _res.options = old_options;
385102644Snectar#endif
38655682Smarkm	fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
38772445Sassar		domain, rr_class, dns_type_to_string(rr_type), len);
38855682Smarkm    }
389102644Snectar    if(len < 0) {
390102644Snectar	return NULL;
391102644Snectar    } else {
392102644Snectar	len = min(len, sizeof(reply));
393102644Snectar	return parse_reply(reply, len);
394102644Snectar    }
39555682Smarkm}
39655682Smarkm
39755682Smarkmstruct dns_reply *
39855682Smarkmdns_lookup(const char *domain, const char *type_name)
39955682Smarkm{
40055682Smarkm    int type;
40155682Smarkm
40272445Sassar    type = dns_string_to_type(type_name);
40355682Smarkm    if(type == -1) {
40455682Smarkm	if(_resolve_debug)
40555682Smarkm	    fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
40655682Smarkm		    type_name);
40755682Smarkm	return NULL;
40855682Smarkm    }
40955682Smarkm    return dns_lookup_int(domain, C_IN, type);
41055682Smarkm}
41155682Smarkm
41290926Snectarstatic int
41390926Snectarcompare_srv(const void *a, const void *b)
41490926Snectar{
41590926Snectar    const struct resource_record *const* aa = a, *const* bb = b;
41690926Snectar
41790926Snectar    if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
41890926Snectar	return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
41990926Snectar    return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
42090926Snectar}
42190926Snectar
42290926Snectar#ifndef HAVE_RANDOM
42390926Snectar#define random() rand()
42490926Snectar#endif
42590926Snectar
42690926Snectar/* try to rearrange the srv-records by the algorithm in RFC2782 */
42790926Snectarvoid
42890926Snectardns_srv_order(struct dns_reply *r)
42990926Snectar{
43090926Snectar    struct resource_record **srvs, **ss, **headp;
43190926Snectar    struct resource_record *rr;
43290926Snectar    int num_srv = 0;
43390926Snectar
43490926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
435102644Snectar    int state[256 / sizeof(int)];
436102644Snectar    char *oldstate;
43790926Snectar#endif
43890926Snectar
43990926Snectar    for(rr = r->head; rr; rr = rr->next)
44090926Snectar	if(rr->type == T_SRV)
44190926Snectar	    num_srv++;
44290926Snectar
44390926Snectar    if(num_srv == 0)
44490926Snectar	return;
44590926Snectar
44690926Snectar    srvs = malloc(num_srv * sizeof(*srvs));
44790926Snectar    if(srvs == NULL)
44890926Snectar	return; /* XXX not much to do here */
44990926Snectar
45090926Snectar    /* unlink all srv-records from the linked list and put them in
45190926Snectar       a vector */
45290926Snectar    for(ss = srvs, headp = &r->head; *headp; )
45390926Snectar	if((*headp)->type == T_SRV) {
45490926Snectar	    *ss = *headp;
45590926Snectar	    *headp = (*headp)->next;
45690926Snectar	    (*ss)->next = NULL;
45790926Snectar	    ss++;
45890926Snectar	} else
45990926Snectar	    headp = &(*headp)->next;
46090926Snectar
46190926Snectar    /* sort them by priority and weight */
46290926Snectar    qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
46390926Snectar
46490926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
465102644Snectar    oldstate = initstate(time(NULL), (char*)state, sizeof(state));
46690926Snectar#endif
46790926Snectar
46890926Snectar    headp = &r->head;
46990926Snectar
47090926Snectar    for(ss = srvs; ss < srvs + num_srv; ) {
47190926Snectar	int sum, rnd, count;
47290926Snectar	struct resource_record **ee, **tt;
47390926Snectar	/* find the last record with the same priority and count the
47490926Snectar           sum of all weights */
47590926Snectar	for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
47690926Snectar	    if(*tt == NULL)
47790926Snectar		continue;
47890926Snectar	    if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
47990926Snectar		break;
48090926Snectar	    sum += (*tt)->u.srv->weight;
48190926Snectar	}
48290926Snectar	ee = tt;
48390926Snectar	/* ss is now the first record of this priority and ee is the
48490926Snectar           first of the next */
48590926Snectar	while(ss < ee) {
48690926Snectar	    rnd = random() % (sum + 1);
48790926Snectar	    for(count = 0, tt = ss; ; tt++) {
48890926Snectar		if(*tt == NULL)
48990926Snectar		    continue;
49090926Snectar		count += (*tt)->u.srv->weight;
49190926Snectar		if(count >= rnd)
49290926Snectar		    break;
49390926Snectar	    }
49490926Snectar
49590926Snectar	    assert(tt < ee);
49690926Snectar
49790926Snectar	    /* insert the selected record at the tail (of the head) of
49890926Snectar               the list */
49990926Snectar	    (*tt)->next = *headp;
50090926Snectar	    *headp = *tt;
50190926Snectar	    headp = &(*tt)->next;
50290926Snectar	    sum -= (*tt)->u.srv->weight;
50390926Snectar	    *tt = NULL;
50490926Snectar	    while(ss < ee && *ss == NULL)
50590926Snectar		ss++;
50690926Snectar	}
50790926Snectar    }
50890926Snectar
50990926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
51090926Snectar    setstate(oldstate);
51190926Snectar#endif
51290926Snectar    free(srvs);
51390926Snectar    return;
51490926Snectar}
51590926Snectar
51655682Smarkm#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
51755682Smarkm
51855682Smarkmstruct dns_reply *
51955682Smarkmdns_lookup(const char *domain, const char *type_name)
52055682Smarkm{
52155682Smarkm    return NULL;
52255682Smarkm}
52355682Smarkm
52455682Smarkmvoid
52555682Smarkmdns_free_data(struct dns_reply *r)
52655682Smarkm{
52755682Smarkm}
52855682Smarkm
52990926Snectarvoid
53090926Snectardns_srv_order(struct dns_reply *r)
53190926Snectar{
53290926Snectar}
53390926Snectar
53455682Smarkm#endif
53555682Smarkm
53655682Smarkm#ifdef TEST
53755682Smarkmint
53855682Smarkmmain(int argc, char **argv)
53955682Smarkm{
54055682Smarkm    struct dns_reply *r;
54155682Smarkm    struct resource_record *rr;
54255682Smarkm    r = dns_lookup(argv[1], argv[2]);
54355682Smarkm    if(r == NULL){
54455682Smarkm	printf("No reply.\n");
54555682Smarkm	return 1;
54655682Smarkm    }
54790926Snectar    if(r->q.type == T_SRV)
54890926Snectar	dns_srv_order(r);
54990926Snectar
55055682Smarkm    for(rr = r->head; rr;rr=rr->next){
55172445Sassar	printf("%s %s %d ", rr->domain, dns_type_to_string(rr->type), rr->ttl);
55255682Smarkm	switch(rr->type){
55355682Smarkm	case T_NS:
55472445Sassar	case T_CNAME:
55572445Sassar	case T_PTR:
55655682Smarkm	    printf("%s\n", (char*)rr->u.data);
55755682Smarkm	    break;
55855682Smarkm	case T_A:
55972445Sassar	    printf("%s\n", inet_ntoa(*rr->u.a));
56055682Smarkm	    break;
56155682Smarkm	case T_MX:
56255682Smarkm	case T_AFSDB:{
56372445Sassar	    printf("%d %s\n", rr->u.mx->preference, rr->u.mx->domain);
56455682Smarkm	    break;
56555682Smarkm	}
56655682Smarkm	case T_SRV:{
56772445Sassar	    struct srv_record *srv = rr->u.srv;
56855682Smarkm	    printf("%d %d %d %s\n", srv->priority, srv->weight,
56955682Smarkm		   srv->port, srv->target);
57055682Smarkm	    break;
57155682Smarkm	}
57272445Sassar	case T_TXT: {
57372445Sassar	    printf("%s\n", rr->u.txt);
57472445Sassar	    break;
57572445Sassar	}
57672445Sassar	case T_SIG : {
57772445Sassar	    struct sig_record *sig = rr->u.sig;
57872445Sassar	    const char *type_string = dns_type_to_string (sig->type);
57972445Sassar
58072445Sassar	    printf ("type %u (%s), algorithm %u, labels %u, orig_ttl %u, sig_expiration %u, sig_inception %u, key_tag %u, signer %s\n",
58172445Sassar		    sig->type, type_string ? type_string : "",
58272445Sassar		    sig->algorithm, sig->labels, sig->orig_ttl,
58372445Sassar		    sig->sig_expiration, sig->sig_inception, sig->key_tag,
58472445Sassar		    sig->signer);
58572445Sassar	    break;
58672445Sassar	}
58772445Sassar	case T_KEY : {
58872445Sassar	    struct key_record *key = rr->u.key;
58972445Sassar
59072445Sassar	    printf ("flags %u, protocol %u, algorithm %u\n",
59172445Sassar		    key->flags, key->protocol, key->algorithm);
59272445Sassar	    break;
59372445Sassar	}
59455682Smarkm	default:
59555682Smarkm	    printf("\n");
59655682Smarkm	    break;
59755682Smarkm	}
59855682Smarkm    }
59955682Smarkm
60055682Smarkm    return 0;
60155682Smarkm}
60255682Smarkm#endif
603