LTP GCOV extension - code coverage report
Current view: directory - lib/roken - resolve.c
Test: samba_4_0_test.lcov.info
Date: 2010-08-06 Instrumented lines: 361
Code covered: 0.0 % Executed lines: 0

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

Generated by: LTP GCOV extension version 1.6