resolve.c revision 90926
155682Smarkm/*
290926Snectar * Copyright (c) 1995 - 2001 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
4890926SnectarRCSID("$Id: resolve.c,v 1.30 2001/10/02 15:39:41 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{
11655682Smarkm    unsigned char *p;
11755682Smarkm    char host[128];
11855682Smarkm    int status;
11955682Smarkm
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
13655682Smarkm    status = dn_expand(data, data + len, 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    }
14655682Smarkm    p += status;
14755682Smarkm    r->q.type = (p[0] << 8 | p[1]);
14855682Smarkm    p += 2;
14955682Smarkm    r->q.class = (p[0] << 8 | p[1]);
15055682Smarkm    p += 2;
15155682Smarkm    rr = &r->head;
15255682Smarkm    while(p < data + len){
15355682Smarkm	int type, class, ttl, size;
15455682Smarkm	status = dn_expand(data, data + len, p, host, sizeof(host));
15555682Smarkm	if(status < 0){
15655682Smarkm	    dns_free_data(r);
15755682Smarkm	    return NULL;
15855682Smarkm	}
15955682Smarkm	p += status;
16055682Smarkm	type = (p[0] << 8) | p[1];
16155682Smarkm	p += 2;
16255682Smarkm	class = (p[0] << 8) | p[1];
16355682Smarkm	p += 2;
16455682Smarkm	ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
16555682Smarkm	p += 4;
16655682Smarkm	size = (p[0] << 8) | p[1];
16755682Smarkm	p += 2;
16855682Smarkm	*rr = (struct resource_record*)calloc(1,
16955682Smarkm					      sizeof(struct resource_record));
17055682Smarkm	if(*rr == NULL) {
17155682Smarkm	    dns_free_data(r);
17255682Smarkm	    return NULL;
17355682Smarkm	}
17455682Smarkm	(*rr)->domain = strdup(host);
17555682Smarkm	if((*rr)->domain == NULL) {
17655682Smarkm	    dns_free_data(r);
17755682Smarkm	    return NULL;
17855682Smarkm	}
17955682Smarkm	(*rr)->type = type;
18055682Smarkm	(*rr)->class = class;
18155682Smarkm	(*rr)->ttl = ttl;
18255682Smarkm	(*rr)->size = size;
18355682Smarkm	switch(type){
18455682Smarkm	case T_NS:
18555682Smarkm	case T_CNAME:
18655682Smarkm	case T_PTR:
18755682Smarkm	    status = dn_expand(data, data + len, p, host, sizeof(host));
18855682Smarkm	    if(status < 0){
18955682Smarkm		dns_free_data(r);
19055682Smarkm		return NULL;
19155682Smarkm	    }
19255682Smarkm	    (*rr)->u.txt = strdup(host);
19355682Smarkm	    if((*rr)->u.txt == NULL) {
19455682Smarkm		dns_free_data(r);
19555682Smarkm		return NULL;
19655682Smarkm	    }
19755682Smarkm	    break;
19855682Smarkm	case T_MX:
19955682Smarkm	case T_AFSDB:{
20055682Smarkm	    status = dn_expand(data, data + len, p + 2, host, sizeof(host));
20155682Smarkm	    if(status < 0){
20255682Smarkm		dns_free_data(r);
20355682Smarkm		return NULL;
20455682Smarkm	    }
20555682Smarkm	    (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) +
20655682Smarkm						    strlen(host));
20755682Smarkm	    if((*rr)->u.mx == NULL) {
20855682Smarkm		dns_free_data(r);
20955682Smarkm		return NULL;
21055682Smarkm	    }
21155682Smarkm	    (*rr)->u.mx->preference = (p[0] << 8) | p[1];
21255682Smarkm	    strcpy((*rr)->u.mx->domain, host);
21355682Smarkm	    break;
21455682Smarkm	}
21555682Smarkm	case T_SRV:{
21655682Smarkm	    status = dn_expand(data, data + len, p + 6, host, sizeof(host));
21755682Smarkm	    if(status < 0){
21855682Smarkm		dns_free_data(r);
21955682Smarkm		return NULL;
22055682Smarkm	    }
22155682Smarkm	    (*rr)->u.srv =
22255682Smarkm		(struct srv_record*)malloc(sizeof(struct srv_record) +
22355682Smarkm					   strlen(host));
22455682Smarkm	    if((*rr)->u.srv == NULL) {
22555682Smarkm		dns_free_data(r);
22655682Smarkm		return NULL;
22755682Smarkm	    }
22855682Smarkm	    (*rr)->u.srv->priority = (p[0] << 8) | p[1];
22955682Smarkm	    (*rr)->u.srv->weight = (p[2] << 8) | p[3];
23055682Smarkm	    (*rr)->u.srv->port = (p[4] << 8) | p[5];
23155682Smarkm	    strcpy((*rr)->u.srv->target, host);
23255682Smarkm	    break;
23355682Smarkm	}
23455682Smarkm	case T_TXT:{
23555682Smarkm	    (*rr)->u.txt = (char*)malloc(size + 1);
23655682Smarkm	    if((*rr)->u.txt == NULL) {
23755682Smarkm		dns_free_data(r);
23855682Smarkm		return NULL;
23955682Smarkm	    }
24055682Smarkm	    strncpy((*rr)->u.txt, (char*)p + 1, *p);
24155682Smarkm	    (*rr)->u.txt[*p] = 0;
24255682Smarkm	    break;
24355682Smarkm	}
24472445Sassar	case T_KEY : {
24572445Sassar	    size_t key_len;
24672445Sassar
24772445Sassar	    key_len = size - 4;
24872445Sassar	    (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1);
24972445Sassar	    if ((*rr)->u.key == NULL) {
25072445Sassar		dns_free_data (r);
25172445Sassar		return NULL;
25272445Sassar	    }
25372445Sassar
25472445Sassar	    (*rr)->u.key->flags     = (p[0] << 8) | p[1];
25572445Sassar	    (*rr)->u.key->protocol  = p[2];
25672445Sassar	    (*rr)->u.key->algorithm = p[3];
25772445Sassar	    (*rr)->u.key->key_len   = key_len;
25872445Sassar	    memcpy ((*rr)->u.key->key_data, p + 4, key_len);
25972445Sassar	    break;
26072445Sassar	}
26172445Sassar	case T_SIG : {
26272445Sassar	    size_t sig_len;
26372445Sassar
26472445Sassar	    status = dn_expand (data, data + len, p + 18, host, sizeof(host));
26572445Sassar	    if (status < 0) {
26672445Sassar		dns_free_data (r);
26772445Sassar		return NULL;
26872445Sassar	    }
26972445Sassar	    sig_len = len - 18 - status;
27072445Sassar	    (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig)
27172445Sassar				  + strlen(host) + sig_len);
27272445Sassar	    if ((*rr)->u.sig == NULL) {
27372445Sassar		dns_free_data (r);
27472445Sassar		return NULL;
27572445Sassar	    }
27672445Sassar	    (*rr)->u.sig->type           = (p[0] << 8) | p[1];
27772445Sassar	    (*rr)->u.sig->algorithm      = p[2];
27872445Sassar	    (*rr)->u.sig->labels         = p[3];
27972445Sassar	    (*rr)->u.sig->orig_ttl       = (p[4] << 24) | (p[5] << 16)
28072445Sassar		| (p[6] << 8) | p[7];
28172445Sassar	    (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
28272445Sassar		| (p[10] << 8) | p[11];
28372445Sassar	    (*rr)->u.sig->sig_inception  = (p[12] << 24) | (p[13] << 16)
28472445Sassar		| (p[14] << 8) | p[15];
28572445Sassar	    (*rr)->u.sig->key_tag        = (p[16] << 8) | p[17];
28672445Sassar	    (*rr)->u.sig->sig_len        = sig_len;
28772445Sassar	    memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len);
28872445Sassar	    (*rr)->u.sig->signer         = &(*rr)->u.sig->sig_data[sig_len];
28972445Sassar	    strcpy((*rr)->u.sig->signer, host);
29072445Sassar	    break;
29172445Sassar	}
29272445Sassar
29372445Sassar	case T_CERT : {
29472445Sassar	    size_t cert_len;
29572445Sassar
29672445Sassar	    cert_len = size - 5;
29772445Sassar	    (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1);
29872445Sassar	    if ((*rr)->u.cert == NULL) {
29972445Sassar		dns_free_data (r);
30072445Sassar		return NULL;
30172445Sassar	    }
30272445Sassar
30372445Sassar	    (*rr)->u.cert->type      = (p[0] << 8) | p[1];
30472445Sassar	    (*rr)->u.cert->tag       = (p[2] << 8) | p[3];
30572445Sassar	    (*rr)->u.cert->algorithm = p[4];
30672445Sassar	    (*rr)->u.cert->cert_len  = cert_len;
30772445Sassar	    memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len);
30872445Sassar	    break;
30972445Sassar	}
31055682Smarkm	default:
31155682Smarkm	    (*rr)->u.data = (unsigned char*)malloc(size);
31255682Smarkm	    if(size != 0 && (*rr)->u.data == NULL) {
31355682Smarkm		dns_free_data(r);
31455682Smarkm		return NULL;
31555682Smarkm	    }
31655682Smarkm	    memcpy((*rr)->u.data, p, size);
31755682Smarkm	}
31855682Smarkm	p += size;
31955682Smarkm	rr = &(*rr)->next;
32055682Smarkm    }
32155682Smarkm    *rr = NULL;
32255682Smarkm    return r;
32355682Smarkm}
32455682Smarkm
32555682Smarkmstatic struct dns_reply *
32655682Smarkmdns_lookup_int(const char *domain, int rr_class, int rr_type)
32755682Smarkm{
32855682Smarkm    unsigned char reply[1024];
32955682Smarkm    int len;
33055682Smarkm    struct dns_reply *r = NULL;
33155682Smarkm    u_long old_options = 0;
33255682Smarkm
33355682Smarkm    if (_resolve_debug) {
33455682Smarkm        old_options = _res.options;
33555682Smarkm	_res.options |= RES_DEBUG;
33655682Smarkm	fprintf(stderr, "dns_lookup(%s, %d, %s)\n", domain,
33772445Sassar		rr_class, dns_type_to_string(rr_type));
33855682Smarkm    }
33955682Smarkm    len = res_search(domain, rr_class, rr_type, reply, sizeof(reply));
34055682Smarkm    if (_resolve_debug) {
34155682Smarkm        _res.options = old_options;
34255682Smarkm	fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
34372445Sassar		domain, rr_class, dns_type_to_string(rr_type), len);
34455682Smarkm    }
34555682Smarkm    if (len >= 0)
34655682Smarkm	r = parse_reply(reply, len);
34755682Smarkm    return r;
34855682Smarkm}
34955682Smarkm
35055682Smarkmstruct dns_reply *
35155682Smarkmdns_lookup(const char *domain, const char *type_name)
35255682Smarkm{
35355682Smarkm    int type;
35455682Smarkm
35572445Sassar    type = dns_string_to_type(type_name);
35655682Smarkm    if(type == -1) {
35755682Smarkm	if(_resolve_debug)
35855682Smarkm	    fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
35955682Smarkm		    type_name);
36055682Smarkm	return NULL;
36155682Smarkm    }
36255682Smarkm    return dns_lookup_int(domain, C_IN, type);
36355682Smarkm}
36455682Smarkm
36590926Snectarstatic int
36690926Snectarcompare_srv(const void *a, const void *b)
36790926Snectar{
36890926Snectar    const struct resource_record *const* aa = a, *const* bb = b;
36990926Snectar
37090926Snectar    if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
37190926Snectar	return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
37290926Snectar    return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
37390926Snectar}
37490926Snectar
37590926Snectar#ifndef HAVE_RANDOM
37690926Snectar#define random() rand()
37790926Snectar#endif
37890926Snectar
37990926Snectar/* try to rearrange the srv-records by the algorithm in RFC2782 */
38090926Snectarvoid
38190926Snectardns_srv_order(struct dns_reply *r)
38290926Snectar{
38390926Snectar    struct resource_record **srvs, **ss, **headp;
38490926Snectar    struct resource_record *rr;
38590926Snectar    int num_srv = 0;
38690926Snectar
38790926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
38890926Snectar    char state[256], *oldstate;
38990926Snectar#endif
39090926Snectar
39190926Snectar    for(rr = r->head; rr; rr = rr->next)
39290926Snectar	if(rr->type == T_SRV)
39390926Snectar	    num_srv++;
39490926Snectar
39590926Snectar    if(num_srv == 0)
39690926Snectar	return;
39790926Snectar
39890926Snectar    srvs = malloc(num_srv * sizeof(*srvs));
39990926Snectar    if(srvs == NULL)
40090926Snectar	return; /* XXX not much to do here */
40190926Snectar
40290926Snectar    /* unlink all srv-records from the linked list and put them in
40390926Snectar       a vector */
40490926Snectar    for(ss = srvs, headp = &r->head; *headp; )
40590926Snectar	if((*headp)->type == T_SRV) {
40690926Snectar	    *ss = *headp;
40790926Snectar	    *headp = (*headp)->next;
40890926Snectar	    (*ss)->next = NULL;
40990926Snectar	    ss++;
41090926Snectar	} else
41190926Snectar	    headp = &(*headp)->next;
41290926Snectar
41390926Snectar    /* sort them by priority and weight */
41490926Snectar    qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
41590926Snectar
41690926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
41790926Snectar    oldstate = initstate(time(NULL), state, sizeof(state));
41890926Snectar#endif
41990926Snectar
42090926Snectar    headp = &r->head;
42190926Snectar
42290926Snectar    for(ss = srvs; ss < srvs + num_srv; ) {
42390926Snectar	int sum, rnd, count;
42490926Snectar	struct resource_record **ee, **tt;
42590926Snectar	/* find the last record with the same priority and count the
42690926Snectar           sum of all weights */
42790926Snectar	for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
42890926Snectar	    if(*tt == NULL)
42990926Snectar		continue;
43090926Snectar	    if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
43190926Snectar		break;
43290926Snectar	    sum += (*tt)->u.srv->weight;
43390926Snectar	}
43490926Snectar	ee = tt;
43590926Snectar	/* ss is now the first record of this priority and ee is the
43690926Snectar           first of the next */
43790926Snectar	while(ss < ee) {
43890926Snectar	    rnd = random() % (sum + 1);
43990926Snectar	    for(count = 0, tt = ss; ; tt++) {
44090926Snectar		if(*tt == NULL)
44190926Snectar		    continue;
44290926Snectar		count += (*tt)->u.srv->weight;
44390926Snectar		if(count >= rnd)
44490926Snectar		    break;
44590926Snectar	    }
44690926Snectar
44790926Snectar	    assert(tt < ee);
44890926Snectar
44990926Snectar	    /* insert the selected record at the tail (of the head) of
45090926Snectar               the list */
45190926Snectar	    (*tt)->next = *headp;
45290926Snectar	    *headp = *tt;
45390926Snectar	    headp = &(*tt)->next;
45490926Snectar	    sum -= (*tt)->u.srv->weight;
45590926Snectar	    *tt = NULL;
45690926Snectar	    while(ss < ee && *ss == NULL)
45790926Snectar		ss++;
45890926Snectar	}
45990926Snectar    }
46090926Snectar
46190926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
46290926Snectar    setstate(oldstate);
46390926Snectar#endif
46490926Snectar    free(srvs);
46590926Snectar    return;
46690926Snectar}
46790926Snectar
46855682Smarkm#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
46955682Smarkm
47055682Smarkmstruct dns_reply *
47155682Smarkmdns_lookup(const char *domain, const char *type_name)
47255682Smarkm{
47355682Smarkm    return NULL;
47455682Smarkm}
47555682Smarkm
47655682Smarkmvoid
47755682Smarkmdns_free_data(struct dns_reply *r)
47855682Smarkm{
47955682Smarkm}
48055682Smarkm
48190926Snectarvoid
48290926Snectardns_srv_order(struct dns_reply *r)
48390926Snectar{
48490926Snectar}
48590926Snectar
48655682Smarkm#endif
48755682Smarkm
48855682Smarkm#ifdef TEST
48955682Smarkmint
49055682Smarkmmain(int argc, char **argv)
49155682Smarkm{
49255682Smarkm    struct dns_reply *r;
49355682Smarkm    struct resource_record *rr;
49455682Smarkm    r = dns_lookup(argv[1], argv[2]);
49555682Smarkm    if(r == NULL){
49655682Smarkm	printf("No reply.\n");
49755682Smarkm	return 1;
49855682Smarkm    }
49990926Snectar    if(r->q.type == T_SRV)
50090926Snectar	dns_srv_order(r);
50190926Snectar
50255682Smarkm    for(rr = r->head; rr;rr=rr->next){
50372445Sassar	printf("%s %s %d ", rr->domain, dns_type_to_string(rr->type), rr->ttl);
50455682Smarkm	switch(rr->type){
50555682Smarkm	case T_NS:
50672445Sassar	case T_CNAME:
50772445Sassar	case T_PTR:
50855682Smarkm	    printf("%s\n", (char*)rr->u.data);
50955682Smarkm	    break;
51055682Smarkm	case T_A:
51172445Sassar	    printf("%s\n", inet_ntoa(*rr->u.a));
51255682Smarkm	    break;
51355682Smarkm	case T_MX:
51455682Smarkm	case T_AFSDB:{
51572445Sassar	    printf("%d %s\n", rr->u.mx->preference, rr->u.mx->domain);
51655682Smarkm	    break;
51755682Smarkm	}
51855682Smarkm	case T_SRV:{
51972445Sassar	    struct srv_record *srv = rr->u.srv;
52055682Smarkm	    printf("%d %d %d %s\n", srv->priority, srv->weight,
52155682Smarkm		   srv->port, srv->target);
52255682Smarkm	    break;
52355682Smarkm	}
52472445Sassar	case T_TXT: {
52572445Sassar	    printf("%s\n", rr->u.txt);
52672445Sassar	    break;
52772445Sassar	}
52872445Sassar	case T_SIG : {
52972445Sassar	    struct sig_record *sig = rr->u.sig;
53072445Sassar	    const char *type_string = dns_type_to_string (sig->type);
53172445Sassar
53272445Sassar	    printf ("type %u (%s), algorithm %u, labels %u, orig_ttl %u, sig_expiration %u, sig_inception %u, key_tag %u, signer %s\n",
53372445Sassar		    sig->type, type_string ? type_string : "",
53472445Sassar		    sig->algorithm, sig->labels, sig->orig_ttl,
53572445Sassar		    sig->sig_expiration, sig->sig_inception, sig->key_tag,
53672445Sassar		    sig->signer);
53772445Sassar	    break;
53872445Sassar	}
53972445Sassar	case T_KEY : {
54072445Sassar	    struct key_record *key = rr->u.key;
54172445Sassar
54272445Sassar	    printf ("flags %u, protocol %u, algorithm %u\n",
54372445Sassar		    key->flags, key->protocol, key->algorithm);
54472445Sassar	    break;
54572445Sassar	}
54655682Smarkm	default:
54755682Smarkm	    printf("\n");
54855682Smarkm	    break;
54955682Smarkm	}
55055682Smarkm    }
55155682Smarkm
55255682Smarkm    return 0;
55355682Smarkm}
55455682Smarkm#endif
555