resolve.c revision 107207
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 48107207SnectarRCSID("$Id: resolve.c,v 1.36.4.1 2002/10/21 14:48:15 joda Exp $"); 4990926Snectar 50103423Snectar#undef HAVE_RES_NSEARCH 51103423Snectar#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND) 5255682Smarkm 5355682Smarkm#define DECL(X) {#X, T_##X} 5455682Smarkm 5555682Smarkmstatic struct stot{ 5655682Smarkm const char *name; 5755682Smarkm int type; 5855682Smarkm}stot[] = { 5955682Smarkm DECL(A), 6055682Smarkm DECL(NS), 6155682Smarkm DECL(CNAME), 6272445Sassar DECL(SOA), 6355682Smarkm DECL(PTR), 6455682Smarkm DECL(MX), 6555682Smarkm DECL(TXT), 6655682Smarkm DECL(AFSDB), 6772445Sassar DECL(SIG), 6872445Sassar DECL(KEY), 6955682Smarkm DECL(SRV), 7072445Sassar DECL(NAPTR), 7155682Smarkm {NULL, 0} 7255682Smarkm}; 7355682Smarkm 7472445Sassarint _resolve_debug = 0; 7555682Smarkm 7672445Sassarint 7772445Sassardns_string_to_type(const char *name) 7855682Smarkm{ 7955682Smarkm struct stot *p = stot; 8055682Smarkm for(p = stot; p->name; p++) 8155682Smarkm if(strcasecmp(name, p->name) == 0) 8255682Smarkm return p->type; 8355682Smarkm return -1; 8455682Smarkm} 8555682Smarkm 8672445Sassarconst char * 8772445Sassardns_type_to_string(int type) 8855682Smarkm{ 8955682Smarkm struct stot *p = stot; 9055682Smarkm for(p = stot; p->name; p++) 9155682Smarkm if(type == p->type) 9255682Smarkm return p->name; 9355682Smarkm return NULL; 9455682Smarkm} 9555682Smarkm 9655682Smarkmvoid 9755682Smarkmdns_free_data(struct dns_reply *r) 9855682Smarkm{ 9955682Smarkm struct resource_record *rr; 10055682Smarkm if(r->q.domain) 10155682Smarkm free(r->q.domain); 10255682Smarkm for(rr = r->head; rr;){ 10355682Smarkm struct resource_record *tmp = rr; 10455682Smarkm if(rr->domain) 10555682Smarkm free(rr->domain); 10655682Smarkm if(rr->u.data) 10755682Smarkm free(rr->u.data); 10855682Smarkm rr = rr->next; 10955682Smarkm free(tmp); 11055682Smarkm } 11155682Smarkm free (r); 11255682Smarkm} 11355682Smarkm 114107207Snectarstatic int 115107207Snectarparse_record(const unsigned char *data, const unsigned char *end_data, 116107207Snectar const unsigned char **pp, struct resource_record **rr) 117107207Snectar{ 118107207Snectar int type, class, ttl, size; 119107207Snectar int status; 120107207Snectar char host[MAXDNAME]; 121107207Snectar const unsigned char *p = *pp; 122107207Snectar status = dn_expand(data, end_data, p, host, sizeof(host)); 123107207Snectar if(status < 0) 124107207Snectar return -1; 125107207Snectar if (p + status + 10 > end_data) 126107207Snectar return -1; 127107207Snectar p += status; 128107207Snectar type = (p[0] << 8) | p[1]; 129107207Snectar p += 2; 130107207Snectar class = (p[0] << 8) | p[1]; 131107207Snectar p += 2; 132107207Snectar ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 133107207Snectar p += 4; 134107207Snectar size = (p[0] << 8) | p[1]; 135107207Snectar p += 2; 136107207Snectar 137107207Snectar if (p + size > end_data) 138107207Snectar return -1; 139107207Snectar 140107207Snectar *rr = calloc(1, sizeof(**rr)); 141107207Snectar if(*rr == NULL) 142107207Snectar return -1; 143107207Snectar (*rr)->domain = strdup(host); 144107207Snectar if((*rr)->domain == NULL) { 145107207Snectar free(*rr); 146107207Snectar return -1; 147107207Snectar } 148107207Snectar (*rr)->type = type; 149107207Snectar (*rr)->class = class; 150107207Snectar (*rr)->ttl = ttl; 151107207Snectar (*rr)->size = size; 152107207Snectar switch(type){ 153107207Snectar case T_NS: 154107207Snectar case T_CNAME: 155107207Snectar case T_PTR: 156107207Snectar status = dn_expand(data, end_data, p, host, sizeof(host)); 157107207Snectar if(status < 0) { 158107207Snectar free(*rr); 159107207Snectar return -1; 160107207Snectar } 161107207Snectar (*rr)->u.txt = strdup(host); 162107207Snectar if((*rr)->u.txt == NULL) { 163107207Snectar free(*rr); 164107207Snectar return -1; 165107207Snectar } 166107207Snectar break; 167107207Snectar case T_MX: 168107207Snectar case T_AFSDB:{ 169107207Snectar status = dn_expand(data, end_data, p + 2, host, sizeof(host)); 170107207Snectar if(status < 0){ 171107207Snectar free(*rr); 172107207Snectar return -1; 173107207Snectar } 174107207Snectar if (status + 2 > size) { 175107207Snectar free(*rr); 176107207Snectar return -1; 177107207Snectar } 178107207Snectar 179107207Snectar (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + 180107207Snectar strlen(host)); 181107207Snectar if((*rr)->u.mx == NULL) { 182107207Snectar free(*rr); 183107207Snectar return -1; 184107207Snectar } 185107207Snectar (*rr)->u.mx->preference = (p[0] << 8) | p[1]; 186107207Snectar strcpy((*rr)->u.mx->domain, host); 187107207Snectar break; 188107207Snectar } 189107207Snectar case T_SRV:{ 190107207Snectar status = dn_expand(data, end_data, p + 6, host, sizeof(host)); 191107207Snectar if(status < 0){ 192107207Snectar free(*rr); 193107207Snectar return -1; 194107207Snectar } 195107207Snectar if (status + 6 > size) { 196107207Snectar free(*rr); 197107207Snectar return -1; 198107207Snectar } 199107207Snectar 200107207Snectar (*rr)->u.srv = 201107207Snectar (struct srv_record*)malloc(sizeof(struct srv_record) + 202107207Snectar strlen(host)); 203107207Snectar if((*rr)->u.srv == NULL) { 204107207Snectar free(*rr); 205107207Snectar return -1; 206107207Snectar } 207107207Snectar (*rr)->u.srv->priority = (p[0] << 8) | p[1]; 208107207Snectar (*rr)->u.srv->weight = (p[2] << 8) | p[3]; 209107207Snectar (*rr)->u.srv->port = (p[4] << 8) | p[5]; 210107207Snectar strcpy((*rr)->u.srv->target, host); 211107207Snectar break; 212107207Snectar } 213107207Snectar case T_TXT:{ 214107207Snectar if(size == 0 || size < *p + 1) { 215107207Snectar free(*rr); 216107207Snectar return -1; 217107207Snectar } 218107207Snectar (*rr)->u.txt = (char*)malloc(*p + 1); 219107207Snectar if((*rr)->u.txt == NULL) { 220107207Snectar free(*rr); 221107207Snectar return -1; 222107207Snectar } 223107207Snectar strncpy((*rr)->u.txt, (char*)p + 1, *p); 224107207Snectar (*rr)->u.txt[*p] = '\0'; 225107207Snectar break; 226107207Snectar } 227107207Snectar case T_KEY : { 228107207Snectar size_t key_len; 229107207Snectar 230107207Snectar if (size < 4) { 231107207Snectar free(*rr); 232107207Snectar return -1; 233107207Snectar } 234107207Snectar 235107207Snectar key_len = size - 4; 236107207Snectar (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1); 237107207Snectar if ((*rr)->u.key == NULL) { 238107207Snectar free(*rr); 239107207Snectar return -1; 240107207Snectar } 241107207Snectar 242107207Snectar (*rr)->u.key->flags = (p[0] << 8) | p[1]; 243107207Snectar (*rr)->u.key->protocol = p[2]; 244107207Snectar (*rr)->u.key->algorithm = p[3]; 245107207Snectar (*rr)->u.key->key_len = key_len; 246107207Snectar memcpy ((*rr)->u.key->key_data, p + 4, key_len); 247107207Snectar break; 248107207Snectar } 249107207Snectar case T_SIG : { 250107207Snectar size_t sig_len; 251107207Snectar 252107207Snectar if(size <= 18) { 253107207Snectar free(*rr); 254107207Snectar return -1; 255107207Snectar } 256107207Snectar status = dn_expand (data, end_data, p + 18, host, sizeof(host)); 257107207Snectar if (status < 0) { 258107207Snectar free(*rr); 259107207Snectar return -1; 260107207Snectar } 261107207Snectar if (status + 18 > size) { 262107207Snectar free(*rr); 263107207Snectar return -1; 264107207Snectar } 265107207Snectar 266107207Snectar /* the signer name is placed after the sig_data, to make it 267107207Snectar easy to free this struture; the size calculation below 268107207Snectar includes the zero-termination if the structure itself. 269107207Snectar don't you just love C? 270107207Snectar */ 271107207Snectar sig_len = size - 18 - status; 272107207Snectar (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig) 273107207Snectar + strlen(host) + sig_len); 274107207Snectar if ((*rr)->u.sig == NULL) { 275107207Snectar free(*rr); 276107207Snectar return -1; 277107207Snectar } 278107207Snectar (*rr)->u.sig->type = (p[0] << 8) | p[1]; 279107207Snectar (*rr)->u.sig->algorithm = p[2]; 280107207Snectar (*rr)->u.sig->labels = p[3]; 281107207Snectar (*rr)->u.sig->orig_ttl = (p[4] << 24) | (p[5] << 16) 282107207Snectar | (p[6] << 8) | p[7]; 283107207Snectar (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16) 284107207Snectar | (p[10] << 8) | p[11]; 285107207Snectar (*rr)->u.sig->sig_inception = (p[12] << 24) | (p[13] << 16) 286107207Snectar | (p[14] << 8) | p[15]; 287107207Snectar (*rr)->u.sig->key_tag = (p[16] << 8) | p[17]; 288107207Snectar (*rr)->u.sig->sig_len = sig_len; 289107207Snectar memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len); 290107207Snectar (*rr)->u.sig->signer = &(*rr)->u.sig->sig_data[sig_len]; 291107207Snectar strcpy((*rr)->u.sig->signer, host); 292107207Snectar break; 293107207Snectar } 294107207Snectar 295107207Snectar case T_CERT : { 296107207Snectar size_t cert_len; 297107207Snectar 298107207Snectar if (size < 5) { 299107207Snectar free(*rr); 300107207Snectar return -1; 301107207Snectar } 302107207Snectar 303107207Snectar cert_len = size - 5; 304107207Snectar (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1); 305107207Snectar if ((*rr)->u.cert == NULL) { 306107207Snectar free(*rr); 307107207Snectar return -1; 308107207Snectar } 309107207Snectar 310107207Snectar (*rr)->u.cert->type = (p[0] << 8) | p[1]; 311107207Snectar (*rr)->u.cert->tag = (p[2] << 8) | p[3]; 312107207Snectar (*rr)->u.cert->algorithm = p[4]; 313107207Snectar (*rr)->u.cert->cert_len = cert_len; 314107207Snectar memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len); 315107207Snectar break; 316107207Snectar } 317107207Snectar default: 318107207Snectar (*rr)->u.data = (unsigned char*)malloc(size); 319107207Snectar if(size != 0 && (*rr)->u.data == NULL) { 320107207Snectar free(*rr); 321107207Snectar return -1; 322107207Snectar } 323107207Snectar memcpy((*rr)->u.data, p, size); 324107207Snectar } 325107207Snectar *pp = p + size; 326107207Snectar return 0; 327107207Snectar} 328107207Snectar 329103423Snectar#ifndef TEST_RESOLVE 330103423Snectarstatic 331103423Snectar#endif 332103423Snectarstruct dns_reply* 333103423Snectarparse_reply(const unsigned char *data, size_t len) 33455682Smarkm{ 335102644Snectar const unsigned char *p; 33655682Smarkm int status; 337107207Snectar int i; 338107207Snectar char host[MAXDNAME]; 339102644Snectar const unsigned char *end_data = data + len; 34055682Smarkm struct dns_reply *r; 34155682Smarkm struct resource_record **rr; 34255682Smarkm 34355682Smarkm r = calloc(1, sizeof(*r)); 34455682Smarkm if (r == NULL) 34555682Smarkm return NULL; 34655682Smarkm 34755682Smarkm p = data; 34855682Smarkm#if 0 34955682Smarkm /* doesn't work on Crays */ 35055682Smarkm memcpy(&r->h, p, sizeof(HEADER)); 35155682Smarkm p += sizeof(HEADER); 35255682Smarkm#else 35355682Smarkm memcpy(&r->h, p, 12); /* XXX this will probably be mostly garbage */ 35455682Smarkm p += 12; 35555682Smarkm#endif 356107207Snectar if(ntohs(r->h.qdcount) != 1) { 357107207Snectar free(r); 358107207Snectar return NULL; 359107207Snectar } 360102644Snectar status = dn_expand(data, end_data, p, host, sizeof(host)); 36155682Smarkm if(status < 0){ 36255682Smarkm dns_free_data(r); 36355682Smarkm return NULL; 36455682Smarkm } 36555682Smarkm r->q.domain = strdup(host); 36655682Smarkm if(r->q.domain == NULL) { 36755682Smarkm dns_free_data(r); 36855682Smarkm return NULL; 36955682Smarkm } 370102644Snectar if (p + status + 4 > end_data) { 371102644Snectar dns_free_data(r); 372102644Snectar return NULL; 373102644Snectar } 37455682Smarkm p += status; 37555682Smarkm r->q.type = (p[0] << 8 | p[1]); 37655682Smarkm p += 2; 37755682Smarkm r->q.class = (p[0] << 8 | p[1]); 37855682Smarkm p += 2; 379107207Snectar 38055682Smarkm rr = &r->head; 381107207Snectar for(i = 0; i < ntohs(r->h.ancount); i++) { 382107207Snectar if(parse_record(data, end_data, &p, rr) != 0) { 38355682Smarkm dns_free_data(r); 38455682Smarkm return NULL; 38555682Smarkm } 386107207Snectar rr = &(*rr)->next; 387107207Snectar } 388107207Snectar for(i = 0; i < ntohs(r->h.nscount); i++) { 389107207Snectar if(parse_record(data, end_data, &p, rr) != 0) { 390102644Snectar dns_free_data(r); 391102644Snectar return NULL; 392102644Snectar } 393107207Snectar rr = &(*rr)->next; 394107207Snectar } 395107207Snectar for(i = 0; i < ntohs(r->h.arcount); i++) { 396107207Snectar if(parse_record(data, end_data, &p, rr) != 0) { 397102644Snectar dns_free_data(r); 398102644Snectar return NULL; 399102644Snectar } 40055682Smarkm rr = &(*rr)->next; 40155682Smarkm } 40255682Smarkm *rr = NULL; 40355682Smarkm return r; 40455682Smarkm} 40555682Smarkm 40655682Smarkmstatic struct dns_reply * 40755682Smarkmdns_lookup_int(const char *domain, int rr_class, int rr_type) 40855682Smarkm{ 40955682Smarkm unsigned char reply[1024]; 41055682Smarkm int len; 411103423Snectar#ifdef HAVE_RES_NSEARCH 412103423Snectar struct __res_state stat; 413103423Snectar memset(&stat, 0, sizeof(stat)); 414103423Snectar if(res_ninit(&stat)) 415103423Snectar return NULL; /* is this the best we can do? */ 416103423Snectar#elif defined(HAVE__RES) 41755682Smarkm u_long old_options = 0; 418102644Snectar#endif 41955682Smarkm 42055682Smarkm if (_resolve_debug) { 421103423Snectar#ifdef HAVE_RES_NSEARCH 422103423Snectar stat.options |= RES_DEBUG; 423103423Snectar#elif defined(HAVE__RES) 42455682Smarkm old_options = _res.options; 42555682Smarkm _res.options |= RES_DEBUG; 426102644Snectar#endif 42755682Smarkm fprintf(stderr, "dns_lookup(%s, %d, %s)\n", domain, 42872445Sassar rr_class, dns_type_to_string(rr_type)); 42955682Smarkm } 430103423Snectar#ifdef HAVE_RES_NSEARCH 431103423Snectar len = res_nsearch(&stat, domain, rr_class, rr_type, reply, sizeof(reply)); 432103423Snectar#else 43355682Smarkm len = res_search(domain, rr_class, rr_type, reply, sizeof(reply)); 434103423Snectar#endif 43555682Smarkm if (_resolve_debug) { 436103423Snectar#if defined(HAVE__RES) && !defined(HAVE_RES_NSEARCH) 43755682Smarkm _res.options = old_options; 438102644Snectar#endif 43955682Smarkm fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n", 44072445Sassar domain, rr_class, dns_type_to_string(rr_type), len); 44155682Smarkm } 442103423Snectar#ifdef HAVE_RES_NSEARCH 443103423Snectar res_nclose(&stat); 444103423Snectar#endif 445102644Snectar if(len < 0) { 446102644Snectar return NULL; 447102644Snectar } else { 448102644Snectar len = min(len, sizeof(reply)); 449102644Snectar return parse_reply(reply, len); 450102644Snectar } 45155682Smarkm} 45255682Smarkm 45355682Smarkmstruct dns_reply * 45455682Smarkmdns_lookup(const char *domain, const char *type_name) 45555682Smarkm{ 45655682Smarkm int type; 45755682Smarkm 45872445Sassar type = dns_string_to_type(type_name); 45955682Smarkm if(type == -1) { 46055682Smarkm if(_resolve_debug) 46155682Smarkm fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", 46255682Smarkm type_name); 46355682Smarkm return NULL; 46455682Smarkm } 46555682Smarkm return dns_lookup_int(domain, C_IN, type); 46655682Smarkm} 46755682Smarkm 46890926Snectarstatic int 46990926Snectarcompare_srv(const void *a, const void *b) 47090926Snectar{ 47190926Snectar const struct resource_record *const* aa = a, *const* bb = b; 47290926Snectar 47390926Snectar if((*aa)->u.srv->priority == (*bb)->u.srv->priority) 47490926Snectar return ((*aa)->u.srv->weight - (*bb)->u.srv->weight); 47590926Snectar return ((*aa)->u.srv->priority - (*bb)->u.srv->priority); 47690926Snectar} 47790926Snectar 47890926Snectar#ifndef HAVE_RANDOM 47990926Snectar#define random() rand() 48090926Snectar#endif 48190926Snectar 48290926Snectar/* try to rearrange the srv-records by the algorithm in RFC2782 */ 48390926Snectarvoid 48490926Snectardns_srv_order(struct dns_reply *r) 48590926Snectar{ 48690926Snectar struct resource_record **srvs, **ss, **headp; 48790926Snectar struct resource_record *rr; 48890926Snectar int num_srv = 0; 48990926Snectar 49090926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE) 491102644Snectar int state[256 / sizeof(int)]; 492102644Snectar char *oldstate; 49390926Snectar#endif 49490926Snectar 49590926Snectar for(rr = r->head; rr; rr = rr->next) 49690926Snectar if(rr->type == T_SRV) 49790926Snectar num_srv++; 49890926Snectar 49990926Snectar if(num_srv == 0) 50090926Snectar return; 50190926Snectar 50290926Snectar srvs = malloc(num_srv * sizeof(*srvs)); 50390926Snectar if(srvs == NULL) 50490926Snectar return; /* XXX not much to do here */ 50590926Snectar 50690926Snectar /* unlink all srv-records from the linked list and put them in 50790926Snectar a vector */ 50890926Snectar for(ss = srvs, headp = &r->head; *headp; ) 50990926Snectar if((*headp)->type == T_SRV) { 51090926Snectar *ss = *headp; 51190926Snectar *headp = (*headp)->next; 51290926Snectar (*ss)->next = NULL; 51390926Snectar ss++; 51490926Snectar } else 51590926Snectar headp = &(*headp)->next; 51690926Snectar 51790926Snectar /* sort them by priority and weight */ 51890926Snectar qsort(srvs, num_srv, sizeof(*srvs), compare_srv); 51990926Snectar 52090926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE) 521102644Snectar oldstate = initstate(time(NULL), (char*)state, sizeof(state)); 52290926Snectar#endif 52390926Snectar 52490926Snectar headp = &r->head; 52590926Snectar 52690926Snectar for(ss = srvs; ss < srvs + num_srv; ) { 52790926Snectar int sum, rnd, count; 52890926Snectar struct resource_record **ee, **tt; 52990926Snectar /* find the last record with the same priority and count the 53090926Snectar sum of all weights */ 53190926Snectar for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) { 53290926Snectar if(*tt == NULL) 53390926Snectar continue; 53490926Snectar if((*tt)->u.srv->priority != (*ss)->u.srv->priority) 53590926Snectar break; 53690926Snectar sum += (*tt)->u.srv->weight; 53790926Snectar } 53890926Snectar ee = tt; 53990926Snectar /* ss is now the first record of this priority and ee is the 54090926Snectar first of the next */ 54190926Snectar while(ss < ee) { 54290926Snectar rnd = random() % (sum + 1); 54390926Snectar for(count = 0, tt = ss; ; tt++) { 54490926Snectar if(*tt == NULL) 54590926Snectar continue; 54690926Snectar count += (*tt)->u.srv->weight; 54790926Snectar if(count >= rnd) 54890926Snectar break; 54990926Snectar } 55090926Snectar 55190926Snectar assert(tt < ee); 55290926Snectar 55390926Snectar /* insert the selected record at the tail (of the head) of 55490926Snectar the list */ 55590926Snectar (*tt)->next = *headp; 55690926Snectar *headp = *tt; 55790926Snectar headp = &(*tt)->next; 55890926Snectar sum -= (*tt)->u.srv->weight; 55990926Snectar *tt = NULL; 56090926Snectar while(ss < ee && *ss == NULL) 56190926Snectar ss++; 56290926Snectar } 56390926Snectar } 56490926Snectar 56590926Snectar#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE) 56690926Snectar setstate(oldstate); 56790926Snectar#endif 56890926Snectar free(srvs); 56990926Snectar return; 57090926Snectar} 57190926Snectar 57255682Smarkm#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */ 57355682Smarkm 57455682Smarkmstruct dns_reply * 57555682Smarkmdns_lookup(const char *domain, const char *type_name) 57655682Smarkm{ 57755682Smarkm return NULL; 57855682Smarkm} 57955682Smarkm 58055682Smarkmvoid 58155682Smarkmdns_free_data(struct dns_reply *r) 58255682Smarkm{ 58355682Smarkm} 58455682Smarkm 58590926Snectarvoid 58690926Snectardns_srv_order(struct dns_reply *r) 58790926Snectar{ 58890926Snectar} 58990926Snectar 59055682Smarkm#endif 59155682Smarkm 59255682Smarkm#ifdef TEST 59355682Smarkmint 59455682Smarkmmain(int argc, char **argv) 59555682Smarkm{ 59655682Smarkm struct dns_reply *r; 59755682Smarkm struct resource_record *rr; 59855682Smarkm r = dns_lookup(argv[1], argv[2]); 59955682Smarkm if(r == NULL){ 60055682Smarkm printf("No reply.\n"); 60155682Smarkm return 1; 60255682Smarkm } 60390926Snectar if(r->q.type == T_SRV) 60490926Snectar dns_srv_order(r); 60590926Snectar 60655682Smarkm for(rr = r->head; rr;rr=rr->next){ 607107207Snectar printf("%-30s %-5s %-6d ", rr->domain, dns_type_to_string(rr->type), rr->ttl); 60855682Smarkm switch(rr->type){ 60955682Smarkm case T_NS: 61072445Sassar case T_CNAME: 61172445Sassar case T_PTR: 61255682Smarkm printf("%s\n", (char*)rr->u.data); 61355682Smarkm break; 61455682Smarkm case T_A: 61572445Sassar printf("%s\n", inet_ntoa(*rr->u.a)); 61655682Smarkm break; 61755682Smarkm case T_MX: 61855682Smarkm case T_AFSDB:{ 61972445Sassar printf("%d %s\n", rr->u.mx->preference, rr->u.mx->domain); 62055682Smarkm break; 62155682Smarkm } 62255682Smarkm case T_SRV:{ 62372445Sassar struct srv_record *srv = rr->u.srv; 62455682Smarkm printf("%d %d %d %s\n", srv->priority, srv->weight, 62555682Smarkm srv->port, srv->target); 62655682Smarkm break; 62755682Smarkm } 62872445Sassar case T_TXT: { 62972445Sassar printf("%s\n", rr->u.txt); 63072445Sassar break; 63172445Sassar } 63272445Sassar case T_SIG : { 63372445Sassar struct sig_record *sig = rr->u.sig; 63472445Sassar const char *type_string = dns_type_to_string (sig->type); 63572445Sassar 63672445Sassar printf ("type %u (%s), algorithm %u, labels %u, orig_ttl %u, sig_expiration %u, sig_inception %u, key_tag %u, signer %s\n", 63772445Sassar sig->type, type_string ? type_string : "", 63872445Sassar sig->algorithm, sig->labels, sig->orig_ttl, 63972445Sassar sig->sig_expiration, sig->sig_inception, sig->key_tag, 64072445Sassar sig->signer); 64172445Sassar break; 64272445Sassar } 64372445Sassar case T_KEY : { 64472445Sassar struct key_record *key = rr->u.key; 64572445Sassar 64672445Sassar printf ("flags %u, protocol %u, algorithm %u\n", 64772445Sassar key->flags, key->protocol, key->algorithm); 64872445Sassar break; 64972445Sassar } 65055682Smarkm default: 65155682Smarkm printf("\n"); 65255682Smarkm break; 65355682Smarkm } 65455682Smarkm } 65555682Smarkm 65655682Smarkm return 0; 65755682Smarkm} 65855682Smarkm#endif 659