LCOV - code coverage report
Current view: top level - openssh-6.6p1/openbsd-compat - getrrsetbyname.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 0 193 0.0 %
Date: 2014-08-01 Functions: 0 8 0.0 %
Branches: 0 145 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: getrrsetbyname.c,v 1.11 2007/10/11 18:36:41 jakob Exp $ */
       2                 :            : 
       3                 :            : /*
       4                 :            :  * Copyright (c) 2001 Jakob Schlyter. 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                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      18                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      19                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      20                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      21                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      22                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      23                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      24                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      25                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      26                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      27                 :            :  */
      28                 :            : 
      29                 :            : /*
      30                 :            :  * Portions Copyright (c) 1999-2001 Internet Software Consortium.
      31                 :            :  *
      32                 :            :  * Permission to use, copy, modify, and distribute this software for any
      33                 :            :  * purpose with or without fee is hereby granted, provided that the above
      34                 :            :  * copyright notice and this permission notice appear in all copies.
      35                 :            :  *
      36                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
      37                 :            :  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
      38                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
      39                 :            :  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
      40                 :            :  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
      41                 :            :  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
      42                 :            :  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
      43                 :            :  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      44                 :            :  */
      45                 :            : 
      46                 :            : /* OPENBSD ORIGINAL: lib/libc/net/getrrsetbyname.c */
      47                 :            : 
      48                 :            : #include "includes.h"
      49                 :            : 
      50                 :            : #if !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS)
      51                 :            : 
      52                 :            : #include <stdlib.h>
      53                 :            : #include <string.h>
      54                 :            : 
      55                 :            : #include <netinet/in.h>
      56                 :            : #include <arpa/inet.h>
      57                 :            : 
      58                 :            : #include "getrrsetbyname.h"
      59                 :            : 
      60                 :            : #if defined(HAVE_DECL_H_ERRNO) && !HAVE_DECL_H_ERRNO
      61                 :            : extern int h_errno;
      62                 :            : #endif
      63                 :            : 
      64                 :            : /* We don't need multithread support here */
      65                 :            : #ifdef _THREAD_PRIVATE
      66                 :            : # undef _THREAD_PRIVATE
      67                 :            : #endif
      68                 :            : #define _THREAD_PRIVATE(a,b,c) (c)
      69                 :            : 
      70                 :            : #ifndef HAVE__RES_EXTERN
      71                 :            : struct __res_state _res;
      72                 :            : #endif
      73                 :            : 
      74                 :            : /* Necessary functions and macros */
      75                 :            : 
      76                 :            : /*
      77                 :            :  * Inline versions of get/put short/long.  Pointer is advanced.
      78                 :            :  *
      79                 :            :  * These macros demonstrate the property of C whereby it can be
      80                 :            :  * portable or it can be elegant but rarely both.
      81                 :            :  */
      82                 :            : 
      83                 :            : #ifndef INT32SZ
      84                 :            : # define INT32SZ        4
      85                 :            : #endif
      86                 :            : #ifndef INT16SZ
      87                 :            : # define INT16SZ        2
      88                 :            : #endif
      89                 :            : 
      90                 :            : #ifndef GETSHORT
      91                 :            : #define GETSHORT(s, cp) { \
      92                 :            :         register u_char *t_cp = (u_char *)(cp); \
      93                 :            :         (s) = ((u_int16_t)t_cp[0] << 8) \
      94                 :            :             | ((u_int16_t)t_cp[1]) \
      95                 :            :             ; \
      96                 :            :         (cp) += INT16SZ; \
      97                 :            : }
      98                 :            : #endif
      99                 :            : 
     100                 :            : #ifndef GETLONG
     101                 :            : #define GETLONG(l, cp) { \
     102                 :            :         register u_char *t_cp = (u_char *)(cp); \
     103                 :            :         (l) = ((u_int32_t)t_cp[0] << 24) \
     104                 :            :             | ((u_int32_t)t_cp[1] << 16) \
     105                 :            :             | ((u_int32_t)t_cp[2] << 8) \
     106                 :            :             | ((u_int32_t)t_cp[3]) \
     107                 :            :             ; \
     108                 :            :         (cp) += INT32SZ; \
     109                 :            : }
     110                 :            : #endif
     111                 :            : 
     112                 :            : /*
     113                 :            :  * Routines to insert/extract short/long's.
     114                 :            :  */
     115                 :            : 
     116                 :            : #ifndef HAVE__GETSHORT
     117                 :            : static u_int16_t
     118                 :            : _getshort(msgp)
     119                 :            :         register const u_char *msgp;
     120                 :            : {
     121                 :            :         register u_int16_t u;
     122                 :            : 
     123                 :            :         GETSHORT(u, msgp);
     124                 :            :         return (u);
     125                 :            : }
     126                 :            : #elif defined(HAVE_DECL__GETSHORT) && (HAVE_DECL__GETSHORT == 0)
     127                 :            : u_int16_t _getshort(register const u_char *);
     128                 :            : #endif
     129                 :            : 
     130                 :            : #ifndef HAVE__GETLONG
     131                 :            : static u_int32_t
     132                 :            : _getlong(msgp)
     133                 :            :         register const u_char *msgp;
     134                 :            : {
     135                 :            :         register u_int32_t u;
     136                 :            : 
     137                 :            :         GETLONG(u, msgp);
     138                 :            :         return (u);
     139                 :            : }
     140                 :            : #elif defined(HAVE_DECL__GETLONG) && (HAVE_DECL__GETLONG == 0)
     141                 :            : u_int32_t _getlong(register const u_char *);
     142                 :            : #endif
     143                 :            : 
     144                 :            : /* ************** */
     145                 :            : 
     146                 :            : #define ANSWER_BUFFER_SIZE 0xffff
     147                 :            : 
     148                 :            : struct dns_query {
     149                 :            :         char                    *name;
     150                 :            :         u_int16_t               type;
     151                 :            :         u_int16_t               class;
     152                 :            :         struct dns_query        *next;
     153                 :            : };
     154                 :            : 
     155                 :            : struct dns_rr {
     156                 :            :         char                    *name;
     157                 :            :         u_int16_t               type;
     158                 :            :         u_int16_t               class;
     159                 :            :         u_int16_t               ttl;
     160                 :            :         u_int16_t               size;
     161                 :            :         void                    *rdata;
     162                 :            :         struct dns_rr           *next;
     163                 :            : };
     164                 :            : 
     165                 :            : struct dns_response {
     166                 :            :         HEADER                  header;
     167                 :            :         struct dns_query        *query;
     168                 :            :         struct dns_rr           *answer;
     169                 :            :         struct dns_rr           *authority;
     170                 :            :         struct dns_rr           *additional;
     171                 :            : };
     172                 :            : 
     173                 :            : static struct dns_response *parse_dns_response(const u_char *, int);
     174                 :            : static struct dns_query *parse_dns_qsection(const u_char *, int,
     175                 :            :     const u_char **, int);
     176                 :            : static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
     177                 :            :     int);
     178                 :            : 
     179                 :            : static void free_dns_query(struct dns_query *);
     180                 :            : static void free_dns_rr(struct dns_rr *);
     181                 :            : static void free_dns_response(struct dns_response *);
     182                 :            : 
     183                 :            : static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
     184                 :            : 
     185                 :            : int
     186                 :          0 : getrrsetbyname(const char *hostname, unsigned int rdclass,
     187                 :            :     unsigned int rdtype, unsigned int flags,
     188                 :            :     struct rrsetinfo **res)
     189                 :            : {
     190                 :          0 :         struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
     191                 :            :         int result;
     192                 :          0 :         struct rrsetinfo *rrset = NULL;
     193                 :          0 :         struct dns_response *response = NULL;
     194                 :            :         struct dns_rr *rr;
     195                 :            :         struct rdatainfo *rdata;
     196                 :            :         int length;
     197                 :            :         unsigned int index_ans, index_sig;
     198                 :            :         u_char answer[ANSWER_BUFFER_SIZE];
     199                 :            : 
     200                 :            :         /* check for invalid class and type */
     201         [ #  # ]:          0 :         if (rdclass > 0xffff || rdtype > 0xffff) {
     202                 :            :                 result = ERRSET_INVAL;
     203                 :            :                 goto fail;
     204                 :            :         }
     205                 :            : 
     206                 :            :         /* don't allow queries of class or type ANY */
     207         [ #  # ]:          0 :         if (rdclass == 0xff || rdtype == 0xff) {
     208                 :            :                 result = ERRSET_INVAL;
     209                 :            :                 goto fail;
     210                 :            :         }
     211                 :            : 
     212                 :            :         /* don't allow flags yet, unimplemented */
     213         [ #  # ]:          0 :         if (flags) {
     214                 :            :                 result = ERRSET_INVAL;
     215                 :            :                 goto fail;
     216                 :            :         }
     217                 :            : 
     218                 :            :         /* initialize resolver */
     219 [ #  # ][ #  # ]:          0 :         if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
     220                 :            :                 result = ERRSET_FAIL;
     221                 :            :                 goto fail;
     222                 :            :         }
     223                 :            : 
     224                 :            : #ifdef DEBUG
     225                 :            :         _resp->options |= RES_DEBUG;
     226                 :            : #endif /* DEBUG */
     227                 :            : 
     228                 :            : #ifdef RES_USE_DNSSEC
     229                 :            :         /* turn on DNSSEC if EDNS0 is configured */
     230         [ #  # ]:          0 :         if (_resp->options & RES_USE_EDNS0)
     231                 :          0 :                 _resp->options |= RES_USE_DNSSEC;
     232                 :            : #endif /* RES_USE_DNSEC */
     233                 :            : 
     234                 :            :         /* make query */
     235                 :          0 :         length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
     236                 :            :             answer, sizeof(answer));
     237         [ #  # ]:          0 :         if (length < 0) {
     238      [ #  #  # ]:          0 :                 switch(h_errno) {
     239                 :            :                 case HOST_NOT_FOUND:
     240                 :            :                         result = ERRSET_NONAME;
     241                 :            :                         goto fail;
     242                 :            :                 case NO_DATA:
     243                 :          0 :                         result = ERRSET_NODATA;
     244                 :          0 :                         goto fail;
     245                 :            :                 default:
     246                 :          0 :                         result = ERRSET_FAIL;
     247                 :          0 :                         goto fail;
     248                 :            :                 }
     249                 :            :         }
     250                 :            : 
     251                 :            :         /* parse result */
     252                 :          0 :         response = parse_dns_response(answer, length);
     253         [ #  # ]:          0 :         if (response == NULL) {
     254                 :            :                 result = ERRSET_FAIL;
     255                 :            :                 goto fail;
     256                 :            :         }
     257                 :            : 
     258         [ #  # ]:          0 :         if (response->header.qdcount != 1) {
     259                 :            :                 result = ERRSET_FAIL;
     260                 :            :                 goto fail;
     261                 :            :         }
     262                 :            : 
     263                 :            :         /* initialize rrset */
     264                 :          0 :         rrset = calloc(1, sizeof(struct rrsetinfo));
     265         [ #  # ]:          0 :         if (rrset == NULL) {
     266                 :            :                 result = ERRSET_NOMEMORY;
     267                 :            :                 goto fail;
     268                 :            :         }
     269                 :          0 :         rrset->rri_rdclass = response->query->class;
     270                 :          0 :         rrset->rri_rdtype = response->query->type;
     271                 :          0 :         rrset->rri_ttl = response->answer->ttl;
     272                 :          0 :         rrset->rri_nrdatas = response->header.ancount;
     273                 :            : 
     274                 :            : #ifdef HAVE_HEADER_AD
     275                 :            :         /* check for authenticated data */
     276         [ #  # ]:          0 :         if (response->header.ad == 1)
     277                 :          0 :                 rrset->rri_flags |= RRSET_VALIDATED;
     278                 :            : #endif
     279                 :            : 
     280                 :            :         /* copy name from answer section */
     281                 :          0 :         rrset->rri_name = strdup(response->answer->name);
     282         [ #  # ]:          0 :         if (rrset->rri_name == NULL) {
     283                 :            :                 result = ERRSET_NOMEMORY;
     284                 :            :                 goto fail;
     285                 :            :         }
     286                 :            : 
     287                 :            :         /* count answers */
     288                 :          0 :         rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
     289                 :          0 :             rrset->rri_rdtype);
     290                 :          0 :         rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
     291                 :            :             T_RRSIG);
     292                 :            : 
     293                 :            :         /* allocate memory for answers */
     294                 :          0 :         rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
     295                 :            :             sizeof(struct rdatainfo));
     296         [ #  # ]:          0 :         if (rrset->rri_rdatas == NULL) {
     297                 :            :                 result = ERRSET_NOMEMORY;
     298                 :            :                 goto fail;
     299                 :            :         }
     300                 :            : 
     301                 :            :         /* allocate memory for signatures */
     302         [ #  # ]:          0 :         if (rrset->rri_nsigs > 0) {
     303                 :          0 :                 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
     304         [ #  # ]:          0 :                 if (rrset->rri_sigs == NULL) {
     305                 :            :                         result = ERRSET_NOMEMORY;
     306                 :            :                         goto fail;
     307                 :            :                 }
     308                 :            :         }
     309                 :            : 
     310                 :            :         /* copy answers & signatures */
     311         [ #  # ]:          0 :         for (rr = response->answer, index_ans = 0, index_sig = 0;
     312                 :          0 :             rr; rr = rr->next) {
     313                 :            : 
     314                 :          0 :                 rdata = NULL;
     315                 :            : 
     316 [ #  # ][ #  # ]:          0 :                 if (rr->class == rrset->rri_rdclass &&
     317                 :          0 :                     rr->type  == rrset->rri_rdtype)
     318                 :          0 :                         rdata = &rrset->rri_rdatas[index_ans++];
     319                 :            : 
     320 [ #  # ][ #  # ]:          0 :                 if (rr->class == rrset->rri_rdclass &&
     321                 :          0 :                     rr->type  == T_RRSIG)
     322                 :          0 :                         rdata = &rrset->rri_sigs[index_sig++];
     323                 :            : 
     324         [ #  # ]:          0 :                 if (rdata) {
     325                 :          0 :                         rdata->rdi_length = rr->size;
     326                 :          0 :                         rdata->rdi_data   = malloc(rr->size);
     327                 :            : 
     328         [ #  # ]:          0 :                         if (rdata->rdi_data == NULL) {
     329                 :            :                                 result = ERRSET_NOMEMORY;
     330                 :            :                                 goto fail;
     331                 :            :                         }
     332                 :          0 :                         memcpy(rdata->rdi_data, rr->rdata, rr->size);
     333                 :            :                 }
     334                 :            :         }
     335                 :          0 :         free_dns_response(response);
     336                 :            : 
     337                 :          0 :         *res = rrset;
     338                 :          0 :         return (ERRSET_SUCCESS);
     339                 :            : 
     340                 :            : fail:
     341         [ #  # ]:          0 :         if (rrset != NULL)
     342                 :          0 :                 freerrset(rrset);
     343         [ #  # ]:          0 :         if (response != NULL)
     344                 :          0 :                 free_dns_response(response);
     345                 :          0 :         return (result);
     346                 :            : }
     347                 :            : 
     348                 :            : void
     349                 :          0 : freerrset(struct rrsetinfo *rrset)
     350                 :            : {
     351                 :            :         u_int16_t i;
     352                 :            : 
     353         [ #  # ]:          0 :         if (rrset == NULL)
     354                 :          0 :                 return;
     355                 :            : 
     356         [ #  # ]:          0 :         if (rrset->rri_rdatas) {
     357         [ #  # ]:          0 :                 for (i = 0; i < rrset->rri_nrdatas; i++) {
     358         [ #  # ]:          0 :                         if (rrset->rri_rdatas[i].rdi_data == NULL)
     359                 :            :                                 break;
     360                 :          0 :                         free(rrset->rri_rdatas[i].rdi_data);
     361                 :            :                 }
     362                 :          0 :                 free(rrset->rri_rdatas);
     363                 :            :         }
     364                 :            : 
     365         [ #  # ]:          0 :         if (rrset->rri_sigs) {
     366         [ #  # ]:          0 :                 for (i = 0; i < rrset->rri_nsigs; i++) {
     367         [ #  # ]:          0 :                         if (rrset->rri_sigs[i].rdi_data == NULL)
     368                 :            :                                 break;
     369                 :          0 :                         free(rrset->rri_sigs[i].rdi_data);
     370                 :            :                 }
     371                 :          0 :                 free(rrset->rri_sigs);
     372                 :            :         }
     373                 :            : 
     374         [ #  # ]:          0 :         if (rrset->rri_name)
     375                 :          0 :                 free(rrset->rri_name);
     376                 :          0 :         free(rrset);
     377                 :            : }
     378                 :            : 
     379                 :            : /*
     380                 :            :  * DNS response parsing routines
     381                 :            :  */
     382                 :            : static struct dns_response *
     383                 :          0 : parse_dns_response(const u_char *answer, int size)
     384                 :            : {
     385                 :            :         struct dns_response *resp;
     386                 :            :         const u_char *cp;
     387                 :            : 
     388                 :            :         /* allocate memory for the response */
     389                 :          0 :         resp = calloc(1, sizeof(*resp));
     390         [ #  # ]:          0 :         if (resp == NULL)
     391                 :            :                 return (NULL);
     392                 :            : 
     393                 :            :         /* initialize current pointer */
     394                 :          0 :         cp = answer;
     395                 :            : 
     396                 :            :         /* copy header */
     397                 :          0 :         memcpy(&resp->header, cp, HFIXEDSZ);
     398                 :          0 :         cp += HFIXEDSZ;
     399                 :            : 
     400                 :            :         /* fix header byte order */
     401         [ #  # ]:          0 :         resp->header.qdcount = ntohs(resp->header.qdcount);
     402         [ #  # ]:          0 :         resp->header.ancount = ntohs(resp->header.ancount);
     403         [ #  # ]:          0 :         resp->header.nscount = ntohs(resp->header.nscount);
     404         [ #  # ]:          0 :         resp->header.arcount = ntohs(resp->header.arcount);
     405                 :            : 
     406                 :            :         /* there must be at least one query */
     407         [ #  # ]:          0 :         if (resp->header.qdcount < 1) {
     408                 :          0 :                 free_dns_response(resp);
     409                 :          0 :                 return (NULL);
     410                 :            :         }
     411                 :            : 
     412                 :            :         /* parse query section */
     413                 :          0 :         resp->query = parse_dns_qsection(answer, size, &cp,
     414                 :            :             resp->header.qdcount);
     415 [ #  # ][ #  # ]:          0 :         if (resp->header.qdcount && resp->query == NULL) {
     416                 :          0 :                 free_dns_response(resp);
     417                 :          0 :                 return (NULL);
     418                 :            :         }
     419                 :            : 
     420                 :            :         /* parse answer section */
     421                 :          0 :         resp->answer = parse_dns_rrsection(answer, size, &cp,
     422                 :          0 :             resp->header.ancount);
     423 [ #  # ][ #  # ]:          0 :         if (resp->header.ancount && resp->answer == NULL) {
     424                 :          0 :                 free_dns_response(resp);
     425                 :          0 :                 return (NULL);
     426                 :            :         }
     427                 :            : 
     428                 :            :         /* parse authority section */
     429                 :          0 :         resp->authority = parse_dns_rrsection(answer, size, &cp,
     430                 :          0 :             resp->header.nscount);
     431 [ #  # ][ #  # ]:          0 :         if (resp->header.nscount && resp->authority == NULL) {
     432                 :          0 :                 free_dns_response(resp);
     433                 :          0 :                 return (NULL);
     434                 :            :         }
     435                 :            : 
     436                 :            :         /* parse additional section */
     437                 :          0 :         resp->additional = parse_dns_rrsection(answer, size, &cp,
     438                 :          0 :             resp->header.arcount);
     439 [ #  # ][ #  # ]:          0 :         if (resp->header.arcount && resp->additional == NULL) {
     440                 :          0 :                 free_dns_response(resp);
     441                 :          0 :                 return (NULL);
     442                 :            :         }
     443                 :            : 
     444                 :            :         return (resp);
     445                 :            : }
     446                 :            : 
     447                 :            : static struct dns_query *
     448                 :          0 : parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
     449                 :            : {
     450                 :            :         struct dns_query *head, *curr, *prev;
     451                 :            :         int i, length;
     452                 :            :         char name[MAXDNAME];
     453                 :            : 
     454         [ #  # ]:          0 :         for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
     455                 :            : 
     456                 :            :                 /* allocate and initialize struct */
     457                 :          0 :                 curr = calloc(1, sizeof(struct dns_query));
     458         [ #  # ]:          0 :                 if (curr == NULL) {
     459                 :          0 :                         free_dns_query(head);
     460                 :          0 :                         return (NULL);
     461                 :            :                 }
     462         [ #  # ]:          0 :                 if (head == NULL)
     463                 :          0 :                         head = curr;
     464         [ #  # ]:          0 :                 if (prev != NULL)
     465                 :          0 :                         prev->next = curr;
     466                 :            : 
     467                 :            :                 /* name */
     468                 :          0 :                 length = dn_expand(answer, answer + size, *cp, name,
     469                 :            :                     sizeof(name));
     470         [ #  # ]:          0 :                 if (length < 0) {
     471                 :          0 :                         free_dns_query(head);
     472                 :          0 :                         return (NULL);
     473                 :            :                 }
     474                 :          0 :                 curr->name = strdup(name);
     475         [ #  # ]:          0 :                 if (curr->name == NULL) {
     476                 :          0 :                         free_dns_query(head);
     477                 :          0 :                         return (NULL);
     478                 :            :                 }
     479                 :          0 :                 *cp += length;
     480                 :            : 
     481                 :            :                 /* type */
     482                 :          0 :                 curr->type = _getshort(*cp);
     483                 :          0 :                 *cp += INT16SZ;
     484                 :            : 
     485                 :            :                 /* class */
     486                 :          0 :                 curr->class = _getshort(*cp);
     487                 :          0 :                 *cp += INT16SZ;
     488                 :            :         }
     489                 :            : 
     490                 :            :         return (head);
     491                 :            : }
     492                 :            : 
     493                 :            : static struct dns_rr *
     494                 :          0 : parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
     495                 :            :     int count)
     496                 :            : {
     497                 :            :         struct dns_rr *head, *curr, *prev;
     498                 :            :         int i, length;
     499                 :            :         char name[MAXDNAME];
     500                 :            : 
     501         [ #  # ]:          0 :         for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
     502                 :            : 
     503                 :            :                 /* allocate and initialize struct */
     504                 :          0 :                 curr = calloc(1, sizeof(struct dns_rr));
     505         [ #  # ]:          0 :                 if (curr == NULL) {
     506                 :          0 :                         free_dns_rr(head);
     507                 :          0 :                         return (NULL);
     508                 :            :                 }
     509         [ #  # ]:          0 :                 if (head == NULL)
     510                 :          0 :                         head = curr;
     511         [ #  # ]:          0 :                 if (prev != NULL)
     512                 :          0 :                         prev->next = curr;
     513                 :            : 
     514                 :            :                 /* name */
     515                 :          0 :                 length = dn_expand(answer, answer + size, *cp, name,
     516                 :            :                     sizeof(name));
     517         [ #  # ]:          0 :                 if (length < 0) {
     518                 :          0 :                         free_dns_rr(head);
     519                 :          0 :                         return (NULL);
     520                 :            :                 }
     521                 :          0 :                 curr->name = strdup(name);
     522         [ #  # ]:          0 :                 if (curr->name == NULL) {
     523                 :          0 :                         free_dns_rr(head);
     524                 :          0 :                         return (NULL);
     525                 :            :                 }
     526                 :          0 :                 *cp += length;
     527                 :            : 
     528                 :            :                 /* type */
     529                 :          0 :                 curr->type = _getshort(*cp);
     530                 :          0 :                 *cp += INT16SZ;
     531                 :            : 
     532                 :            :                 /* class */
     533                 :          0 :                 curr->class = _getshort(*cp);
     534                 :          0 :                 *cp += INT16SZ;
     535                 :            : 
     536                 :            :                 /* ttl */
     537                 :          0 :                 curr->ttl = _getlong(*cp);
     538                 :          0 :                 *cp += INT32SZ;
     539                 :            : 
     540                 :            :                 /* rdata size */
     541                 :          0 :                 curr->size = _getshort(*cp);
     542                 :          0 :                 *cp += INT16SZ;
     543                 :            : 
     544                 :            :                 /* rdata itself */
     545                 :          0 :                 curr->rdata = malloc(curr->size);
     546         [ #  # ]:          0 :                 if (curr->rdata == NULL) {
     547                 :          0 :                         free_dns_rr(head);
     548                 :          0 :                         return (NULL);
     549                 :            :                 }
     550                 :          0 :                 memcpy(curr->rdata, *cp, curr->size);
     551                 :          0 :                 *cp += curr->size;
     552                 :            :         }
     553                 :            : 
     554                 :            :         return (head);
     555                 :            : }
     556                 :            : 
     557                 :            : static void
     558                 :          0 : free_dns_query(struct dns_query *p)
     559                 :            : {
     560         [ #  # ]:          0 :         if (p == NULL)
     561                 :          0 :                 return;
     562                 :            : 
     563         [ #  # ]:          0 :         if (p->name)
     564                 :          0 :                 free(p->name);
     565                 :          0 :         free_dns_query(p->next);
     566                 :          0 :         free(p);
     567                 :            : }
     568                 :            : 
     569                 :            : static void
     570                 :          0 : free_dns_rr(struct dns_rr *p)
     571                 :            : {
     572         [ #  # ]:          0 :         if (p == NULL)
     573                 :          0 :                 return;
     574                 :            : 
     575         [ #  # ]:          0 :         if (p->name)
     576                 :          0 :                 free(p->name);
     577         [ #  # ]:          0 :         if (p->rdata)
     578                 :          0 :                 free(p->rdata);
     579                 :          0 :         free_dns_rr(p->next);
     580                 :          0 :         free(p);
     581                 :            : }
     582                 :            : 
     583                 :            : static void
     584                 :          0 : free_dns_response(struct dns_response *p)
     585                 :            : {
     586         [ #  # ]:          0 :         if (p == NULL)
     587                 :          0 :                 return;
     588                 :            : 
     589                 :          0 :         free_dns_query(p->query);
     590                 :          0 :         free_dns_rr(p->answer);
     591                 :          0 :         free_dns_rr(p->authority);
     592                 :          0 :         free_dns_rr(p->additional);
     593                 :          0 :         free(p);
     594                 :            : }
     595                 :            : 
     596                 :            : static int
     597                 :            : count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
     598                 :            : {
     599                 :          0 :         int n = 0;
     600                 :            : 
     601 [ #  # ][ #  # ]:          0 :         while(p) {
     602 [ #  # ][ #  # ]:          0 :                 if (p->class == class && p->type == type)
         [ #  # ][ #  # ]
     603                 :          0 :                         n++;
     604                 :          0 :                 p = p->next;
     605                 :            :         }
     606                 :            : 
     607                 :            :         return (n);
     608                 :            : }
     609                 :            : 
     610                 :            : #endif /*  !defined (HAVE_GETRRSETBYNAME) && !defined (HAVE_LDNS) */

Generated by: LCOV version 1.9