LCOV - code coverage report
Current view: top level - src - nb_dns.c (source / functions) Hit Total Coverage
Test: app.info Lines: 105 228 46.1 %
Date: 2010-12-13 Functions: 8 12 66.7 %
Branches: 38 99 38.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * See the file "COPYING" in the main distribution directory for copyright.
       3                 :            :  */
       4                 :            : #ifndef lint
       5                 :            : static const char rcsid[] =
       6                 :            :     "@(#) $Id: nb_dns.c 6219 2008-10-01 05:39:07Z vern $ (LBL)";
       7                 :            : #endif
       8                 :            : /*
       9                 :            :  * nb_dns - non-blocking dns routines
      10                 :            :  *
      11                 :            :  * This version works with BIND 9
      12                 :            :  *
      13                 :            :  * Note: The code here is way more complicated than it should be but
      14                 :            :  * although the interface to send requests is public, the routine to
      15                 :            :  * crack reply buffers is private.
      16                 :            :  */
      17                 :            : 
      18                 :            : #include "config.h"                   /* must appear before first ifdef */
      19                 :            : 
      20                 :            : #include <sys/types.h>
      21                 :            : #include <sys/socket.h>
      22                 :            : 
      23                 :            : #include <netinet/in.h>
      24                 :            : 
      25                 :            : #include <arpa/inet.h>
      26                 :            : #include <arpa/nameser.h>
      27                 :            : #ifdef NEED_NAMESER_COMPAT_H
      28                 :            : #include <arpa/nameser_compat.h>
      29                 :            : #endif
      30                 :            : 
      31                 :            : #include <errno.h>
      32                 :            : #ifdef HAVE_MEMORY_H
      33                 :            : #include <memory.h>
      34                 :            : #endif
      35                 :            : #include <netdb.h>
      36                 :            : #include <resolv.h>
      37                 :            : #include <stdio.h>
      38                 :            : #include <stdlib.h>
      39                 :            : #include <string.h>
      40                 :            : #include <unistd.h>
      41                 :            : 
      42                 :            : #ifdef notdef
      43                 :            : #include "gnuc.h"
      44                 :            : #ifdef HAVE_OS_PROTO_H
      45                 :            : #include "os-proto.h"
      46                 :            : #endif
      47                 :            : #endif
      48                 :            : 
      49                 :            : #include "nb_dns.h"
      50                 :            : 
      51                 :            : #if PACKETSZ > 1024
      52                 :            : #define MAXPACKET       PACKETSZ
      53                 :            : #else
      54                 :            : #define MAXPACKET       1024
      55                 :            : #endif
      56                 :            : 
      57                 :            : #ifdef DO_SOCK_DECL
      58                 :            : extern int socket(int, int, int);
      59                 :            : extern int connect(int, const struct sockaddr *, int);
      60                 :            : extern int send(int, const void *, int, int);
      61                 :            : extern int recvfrom(int, void *, int, int, struct sockaddr *, int *);
      62                 :            : #endif
      63                 :            : 
      64                 :            : /* Private data */
      65                 :            : struct nb_dns_entry {
      66                 :            :         struct nb_dns_entry *next;
      67                 :            :         char name[NS_MAXDNAME + 1];
      68                 :            :         int qtype;                      /* query type */
      69                 :            :         int atype;                      /* address family */
      70                 :            :         int asize;                      /* address size */
      71                 :            :         u_short id;
      72                 :            :         void *cookie;
      73                 :            : };
      74                 :            : 
      75                 :            : #ifndef MAXALIASES
      76                 :            : #define MAXALIASES      35
      77                 :            : #endif
      78                 :            : #ifndef MAXADDRS
      79                 :            : #define MAXADDRS        35
      80                 :            : #endif
      81                 :            : 
      82                 :            : struct nb_dns_hostent {
      83                 :            :         struct hostent hostent;
      84                 :            :         int numaliases;
      85                 :            :         int numaddrs;
      86                 :            :         char *host_aliases[MAXALIASES + 1];
      87                 :            :         char *h_addr_ptrs[MAXADDRS + 1];
      88                 :            :         char hostbuf[8 * 1024];
      89                 :            : };
      90                 :            : 
      91                 :            : struct nb_dns_info {
      92                 :            :         int s;                          /* Resolver file descriptor */
      93                 :            :         struct sockaddr_in server;      /* server address to bind to */
      94                 :            :         struct nb_dns_entry *list;      /* outstanding requests */
      95                 :            :         struct nb_dns_hostent dns_hostent;
      96                 :            : };
      97                 :            : 
      98                 :            : /* Forwards */
      99                 :            : static int _nb_dns_mkquery(struct nb_dns_info *, const char *, int, int,
     100                 :            :     void *, char *);
     101                 :            : static int _nb_dns_cmpsockaddr(struct sockaddr *, struct sockaddr *, char *);
     102                 :            : 
     103                 :            : static char *
     104                 :            : my_strerror(int errnum)
     105                 :          0 : {
     106                 :            : #ifdef HAVE_STRERROR
     107                 :            :         extern char *strerror(int);
     108                 :          0 :         return strerror(errnum);
     109                 :            : #else
     110                 :            :         static char errnum_buf[32];
     111                 :            :         snprintf(errnum_buf, sizeof(errnum_buf), "errno %d", errnum);
     112                 :            :         return errnum_buf;
     113                 :            : #endif
     114                 :            : }
     115                 :            : 
     116                 :            : struct nb_dns_info *
     117                 :            : nb_dns_init(char *errstr)
     118                 :          3 : {
     119                 :            :         register struct nb_dns_info *nd;
     120                 :            : 
     121                 :          3 :         nd = (struct nb_dns_info *)malloc(sizeof(*nd));
     122         [ -  + ]:          3 :         if (nd == NULL) {
     123                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "nb_dns_init: malloc(): %s",
     124                 :            :                     my_strerror(errno));
     125                 :          0 :                 return (NULL);
     126                 :            :         }
     127         [ -  + ]:          3 :         memset(nd, 0, sizeof(*nd));
     128                 :          3 :         nd->s = -1;
     129                 :            : 
     130                 :            :         /* XXX should be able to init static hostent struct some other way */
     131                 :          3 :         (void)gethostbyname("localhost.");
     132                 :            : 
     133   [ +  -  -  + ]:          3 :         if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
     134                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "res_init() failed");
     135                 :          0 :                 free(nd);
     136                 :          0 :                 return (NULL);
     137                 :            :         }
     138                 :          3 :         nd->s = socket(PF_INET, SOCK_DGRAM, 0);
     139         [ -  + ]:          3 :         if (nd->s < 0) {
     140                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "socket(): %s",
     141                 :            :                     my_strerror(errno));
     142                 :          0 :                 free(nd);
     143                 :          0 :                 return (NULL);
     144                 :            :         }
     145                 :            : 
     146                 :            :         /* XXX should use resolver config */
     147                 :          3 :         nd->server = _res.nsaddr_list[0];
     148                 :            : 
     149         [ -  + ]:          3 :         if (connect(nd->s, (struct sockaddr *)&nd->server,
     150                 :            :             sizeof(struct sockaddr)) < 0) {
     151                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "connect(%s): %s",
     152                 :            :                     inet_ntoa(nd->server.sin_addr), my_strerror(errno));
     153                 :          0 :                 close(nd->s);
     154                 :          0 :                 free(nd);
     155                 :          0 :                 return (NULL);
     156                 :            :         }
     157                 :            : 
     158                 :          3 :         return (nd);
     159                 :            : }
     160                 :            : 
     161                 :            : void
     162                 :            : nb_dns_finish(struct nb_dns_info *nd)
     163                 :          2 : {
     164                 :            :         register struct nb_dns_entry *ne, *ne2;
     165                 :            : 
     166                 :          2 :         ne = nd->list;
     167         [ -  + ]:          2 :         while (ne != NULL) {
     168                 :          0 :                 ne2 = ne;
     169                 :          0 :                 ne = ne->next;
     170                 :          0 :                 free(ne2);
     171                 :            :         }
     172                 :          2 :         close(nd->s);
     173                 :          2 :         free(nd);
     174                 :          2 : }
     175                 :            : 
     176                 :            : int
     177                 :            : nb_dns_fd(struct nb_dns_info *nd)
     178                 :        912 : {
     179                 :            : 
     180                 :        912 :         return (nd->s);
     181                 :            : }
     182                 :            : 
     183                 :            : static int
     184                 :            : _nb_dns_cmpsockaddr(register struct sockaddr *sa1,
     185                 :            :     register struct sockaddr *sa2, register char *errstr)
     186                 :         57 : {
     187                 :            :         register struct sockaddr_in *sin1, *sin2;
     188                 :            : #ifdef AF_INET6
     189                 :            :         register struct sockaddr_in6 *sin6a, *sin6b;
     190                 :            : #endif
     191                 :            :         static const char serr[] = "answer from wrong nameserver (%d)";
     192                 :            : 
     193                 :            :         if (sa1->sa_family != sa1->sa_family) {
     194                 :            :                 snprintf(errstr, NB_DNS_ERRSIZE, serr, 1);
     195                 :            :                 return (-1);
     196                 :            :         }
     197      [ +  -  - ]:         57 :         switch (sa1->sa_family) {
     198                 :            : 
     199                 :            :         case AF_INET:
     200                 :         57 :                 sin1 = (struct sockaddr_in *)sa1;
     201                 :         57 :                 sin2 = (struct sockaddr_in *)sa2;
     202         [ -  + ]:         57 :                 if (sin1->sin_port != sin2->sin_port) {
     203                 :          0 :                         snprintf(errstr, NB_DNS_ERRSIZE, serr, 2);
     204                 :          0 :                         return (-1);
     205                 :            :                 }
     206         [ -  + ]:         57 :                 if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr) {
     207                 :          0 :                         snprintf(errstr, NB_DNS_ERRSIZE, serr, 3);
     208                 :          0 :                         return (-1);
     209                 :            :                 }
     210                 :         57 :                 break;
     211                 :            : 
     212                 :            : #ifdef AF_INET6
     213                 :            :         case AF_INET6:
     214                 :          0 :                 sin6a = (struct sockaddr_in6 *)sa1;
     215                 :          0 :                 sin6b = (struct sockaddr_in6 *)sa2;
     216         [ #  # ]:          0 :                 if (sin6a->sin6_port != sin6b->sin6_port) {
     217                 :          0 :                         snprintf(errstr, NB_DNS_ERRSIZE, serr, 2);
     218                 :          0 :                         return (-1);
     219                 :            :                 }
     220         [ #  # ]:          0 :                 if (memcmp(&sin6a->sin6_addr, &sin6b->sin6_addr,
     221                 :            :                     sizeof(sin6a->sin6_addr)) != 0) {
     222                 :          0 :                         snprintf(errstr, NB_DNS_ERRSIZE, serr, 3);
     223                 :          0 :                         return (-1);
     224                 :            :                 }
     225                 :          0 :                 break;
     226                 :            : #endif
     227                 :            : 
     228                 :            :         default:
     229                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, serr, 4);
     230                 :          0 :                 return (-1);
     231                 :            :         }
     232                 :         57 :         return (0);
     233                 :            : }
     234                 :            : 
     235                 :            : static int
     236                 :            : _nb_dns_mkquery(register struct nb_dns_info *nd, register const char *name,
     237                 :            :     register int atype, register int qtype, register void * cookie,
     238                 :            :     register char *errstr)
     239                 :         57 : {
     240                 :            :         register struct nb_dns_entry *ne;
     241                 :            :         register HEADER *hp;
     242                 :            :         register int n;
     243                 :            :         u_long msg[MAXPACKET / sizeof(u_long)];
     244                 :            : 
     245                 :            :         /* Allocate an entry */
     246                 :         57 :         ne = (struct nb_dns_entry *)malloc(sizeof(*ne));
     247         [ -  + ]:         57 :         if (ne == NULL) {
     248                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "malloc(): %s",
     249                 :            :                     my_strerror(errno));
     250                 :          0 :                 return (-1);
     251                 :            :         }
     252         [ -  + ]:         57 :         memset(ne, 0, sizeof(*ne));
     253         [ -  + ]:         57 :         strncpy(ne->name, name, sizeof(ne->name));
     254                 :         57 :         ne->name[sizeof(ne->name) - 1] = '\0';
     255                 :         57 :         ne->qtype = qtype;
     256                 :         57 :         ne->atype = atype;
     257      [ +  -  - ]:         57 :         switch (atype) {
     258                 :            : 
     259                 :            :         case AF_INET:
     260                 :         57 :                 ne->asize = NS_INADDRSZ;
     261                 :         57 :                 break;
     262                 :            : 
     263                 :            : #ifdef AF_INET6
     264                 :            :         case AF_INET6:
     265                 :          0 :                 ne->asize = NS_IN6ADDRSZ;
     266                 :          0 :                 break;
     267                 :            : #endif
     268                 :            : 
     269                 :            :         default:
     270                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE,
     271                 :            :                     "_nb_dns_mkquery: bad family %d", atype);
     272                 :          0 :                 return (-1);
     273                 :            :         }
     274                 :            : 
     275                 :            :         /* Build the request */
     276                 :         57 :         n = res_mkquery(
     277                 :            :             ns_o_query,                 /* op code (query) */
     278                 :            :             name,                       /* domain name */
     279                 :            :             ns_c_in,                    /* query class (internet) */
     280                 :            :             qtype,                      /* query type */
     281                 :            :             NULL,                       /* data */
     282                 :            :             0,                          /* length of data */
     283                 :            :             NULL,                       /* new rr */
     284                 :            :             (u_char *)msg,              /* buffer */
     285                 :            :             sizeof(msg));               /* size of buffer */
     286         [ -  + ]:         57 :         if (n < 0) {
     287                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "res_mkquery() failed");
     288                 :          0 :                 free(ne);
     289                 :          0 :                 return (-1);
     290                 :            :         }
     291                 :            : 
     292                 :         57 :         hp = (HEADER *)msg;
     293                 :         57 :         ne->id = htons(hp->id);
     294                 :            : 
     295         [ -  + ]:         57 :         if (send(nd->s, (char *)msg, n, 0) != n) {
     296                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "send(): %s",
     297                 :            :                     my_strerror(errno));
     298                 :          0 :                 free(ne);
     299                 :          0 :                 return (-1);
     300                 :            :         }
     301                 :            : 
     302                 :         57 :         ne->next = nd->list;
     303                 :         57 :         ne->cookie = cookie;
     304                 :         57 :         nd->list = ne;
     305                 :            : 
     306                 :         57 :         return(0);
     307                 :            : }
     308                 :            : 
     309                 :            : int
     310                 :            : nb_dns_host_request(register struct nb_dns_info *nd, register const char *name,
     311                 :            :     register void *cookie, register char *errstr)
     312                 :         57 : {
     313                 :            : 
     314                 :         57 :         return (nb_dns_host_request2(nd, name, AF_INET, cookie, errstr));
     315                 :            : }
     316                 :            : 
     317                 :            : int
     318                 :            : nb_dns_host_request2(register struct nb_dns_info *nd, register const char *name,
     319                 :            :     register int af, register void *cookie, register char *errstr)
     320                 :         57 : {
     321                 :            :         register int qtype;
     322                 :            : 
     323      [ +  -  - ]:         57 :         switch (af) {
     324                 :            : 
     325                 :            :         case AF_INET:
     326                 :         57 :                 qtype = T_A;
     327                 :         57 :                 break;
     328                 :            : 
     329                 :            : #ifdef AF_INET6
     330                 :            :         case AF_INET6:
     331                 :          0 :                 qtype = T_AAAA;
     332                 :          0 :                 break;
     333                 :            : #endif
     334                 :            : 
     335                 :            :         default:
     336                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE,
     337                 :            :                     "nb_dns_host_request2(): uknown address family %d", af);
     338                 :          0 :                 return (-1);
     339                 :            :         }
     340                 :         57 :         return (_nb_dns_mkquery(nd, name, af, qtype, cookie, errstr));
     341                 :            : }
     342                 :            : 
     343                 :            : int
     344                 :            : nb_dns_addr_request(register struct nb_dns_info *nd, nb_uint32_t addr,
     345                 :            :     register void *cookie, register char *errstr)
     346                 :          0 : {
     347                 :            : 
     348                 :          0 :         return (nb_dns_addr_request2(nd, (char *)&addr, AF_INET,
     349                 :            :             cookie, errstr));
     350                 :            : }
     351                 :            : 
     352                 :            : int
     353                 :            : nb_dns_addr_request2(register struct nb_dns_info *nd, char *addrp,
     354                 :            :     register int af, register void *cookie, register char *errstr)
     355                 :          0 : {
     356                 :            : #ifdef AF_INET6
     357                 :            :         register char *cp;
     358                 :            :         register int n, i;
     359                 :            :         register size_t size;
     360                 :            : #endif
     361                 :            :         register u_char *uaddr;
     362                 :            :         char name[NS_MAXDNAME + 1];
     363                 :            : 
     364      [ #  #  # ]:          0 :         switch (af) {
     365                 :            : 
     366                 :            :         case AF_INET:
     367                 :          0 :                 uaddr = (u_char *)addrp;
     368                 :          0 :                 snprintf(name, sizeof(name), "%u.%u.%u.%u.in-addr.arpa",
     369                 :            :                     (uaddr[3] & 0xff),
     370                 :            :                     (uaddr[2] & 0xff),
     371                 :            :                     (uaddr[1] & 0xff),
     372                 :            :                     (uaddr[0] & 0xff));
     373                 :          0 :                 break;
     374                 :            : 
     375                 :            : #ifdef AF_INET6
     376                 :            :         case AF_INET6:
     377                 :          0 :                 uaddr = (u_char *)addrp;
     378                 :          0 :                 cp = name;
     379                 :          0 :                 size = sizeof(name);
     380         [ #  # ]:          0 :                 for (n = NS_IN6ADDRSZ - 1; n >= 0; --n) {
     381                 :          0 :                         snprintf(cp, size, "%x.%x.",
     382                 :            :                             (uaddr[n] & 0xf),
     383                 :            :                             (uaddr[n] >> 4) & 0xf);
     384                 :          0 :                         i = strlen(cp);
     385                 :          0 :                         size -= i;
     386                 :          0 :                         cp += i;
     387                 :            :                 }
     388                 :          0 :                 snprintf(cp, size, "ip6.int");
     389                 :          0 :                 break;
     390                 :            : #endif
     391                 :            : 
     392                 :            :         default:
     393                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE,
     394                 :            :                     "nb_dns_addr_request2(): uknown address family %d", af);
     395                 :          0 :                 return (-1);
     396                 :            :         }
     397                 :            : 
     398                 :          0 :         return (_nb_dns_mkquery(nd, name, af, T_PTR, cookie, errstr));
     399                 :            : }
     400                 :            : 
     401                 :            : int
     402                 :            : nb_dns_abort_request(struct nb_dns_info *nd, void *cookie)
     403                 :          0 : {
     404                 :            :         register struct nb_dns_entry *ne, *lastne;
     405                 :            : 
     406                 :            :         /* Try to find this request on the outstanding request list */
     407                 :          0 :         lastne = NULL;
     408         [ #  # ]:          0 :         for (ne = nd->list; ne != NULL; ne = ne->next) {
     409         [ #  # ]:          0 :                 if (ne->cookie == cookie)
     410                 :          0 :                         break;
     411                 :          0 :                 lastne = ne;
     412                 :            :         }
     413                 :            : 
     414                 :            :         /* Not a currently pending request */
     415         [ #  # ]:          0 :         if (ne == NULL)
     416                 :          0 :                 return (-1);
     417                 :            : 
     418                 :            :         /* Unlink this entry */
     419         [ #  # ]:          0 :         if (lastne == NULL)
     420                 :          0 :                 nd->list = ne->next;
     421                 :            :         else
     422                 :          0 :                 lastne->next = ne->next;
     423                 :          0 :         ne->next = NULL;
     424                 :            : 
     425                 :          0 :         return (0);
     426                 :            : }
     427                 :            : 
     428                 :            : /* Returns 1 with an answer, 0 when reply was old, -1 on fatal errors */
     429                 :            : int
     430                 :            : nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr)
     431                 :         57 : {
     432                 :            :         register int msglen, qtype, atype, n, i;
     433                 :            :         register struct nb_dns_entry *ne, *lastne;
     434                 :            :         socklen_t fromlen;
     435                 :            :         struct sockaddr from;
     436                 :            :         u_long msg[MAXPACKET / sizeof(u_long)];
     437                 :            :         register char *bp, *ep;
     438                 :            :         register char **ap, **hap;
     439                 :            :         register u_int16_t id;
     440                 :            :         register const u_char *rdata;
     441                 :            :         register struct hostent *he;
     442                 :            :         register size_t rdlen;
     443                 :            :         ns_msg handle;
     444                 :            :         ns_rr rr;
     445                 :            : 
     446                 :            :         /* This comes from the second half of do_query() */
     447                 :         57 :         fromlen = sizeof(from);
     448                 :         57 :         msglen = recvfrom(nd->s, (char *)msg, sizeof(msg), 0, &from, &fromlen);
     449         [ -  + ]:         57 :         if (msglen <= 0) {
     450                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): %s",
     451                 :            :                     my_strerror(errno));
     452                 :          0 :                 return (-1);
     453                 :            :         }
     454         [ -  + ]:         57 :         if (msglen < HFIXEDSZ) {
     455                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "recvfrom(): undersized: %d",
     456                 :            :                     msglen);
     457                 :          0 :                 return (-1);
     458                 :            :         }
     459         [ -  + ]:         57 :         if (ns_initparse((u_char *)msg, msglen, &handle) < 0) {
     460                 :          0 :                 snprintf(errstr, NB_DNS_ERRSIZE, "ns_initparse(): %s",
     461                 :            :                     my_strerror(errno));
     462                 :          0 :                 nr->host_errno = NO_RECOVERY;
     463                 :          0 :                 return (-1);
     464                 :            :         }
     465                 :            : 
     466                 :            :         /* RES_INSECURE1 style check */
     467         [ -  + ]:         57 :         if (_nb_dns_cmpsockaddr((struct sockaddr *)&nd->server, &from,
     468                 :            :             errstr) < 0) {
     469                 :          0 :                 nr->host_errno = NO_RECOVERY;
     470                 :          0 :                 return (-1);
     471                 :            :         }
     472                 :            : 
     473                 :            :         /* Search for this request */
     474                 :         57 :         lastne = NULL;
     475                 :         57 :         id = ns_msg_id(handle);
     476         [ +  - ]:         57 :         for (ne = nd->list; ne != NULL; ne = ne->next) {
     477         [ +  - ]:         57 :                 if (ne->id == id)
     478                 :         57 :                         break;
     479                 :          0 :                 lastne = ne;
     480                 :            :         }
     481                 :            : 
     482                 :            :         /* Not an answer to a question we care about anymore */
     483         [ -  + ]:         57 :         if (ne == NULL)
     484                 :          0 :                 return (0);
     485                 :            : 
     486                 :            :         /* Unlink this entry */
     487         [ +  - ]:         57 :         if (lastne == NULL)
     488                 :         57 :                 nd->list = ne->next;
     489                 :            :         else
     490                 :          0 :                 lastne->next = ne->next;
     491                 :         57 :         ne->next = NULL;
     492                 :            : 
     493                 :            :         /* RES_INSECURE2 style check */
     494                 :            :         /* XXX not implemented */
     495                 :            : 
     496                 :            :         /* Initialize result struct */
     497         [ -  + ]:         57 :         memset(nr, 0, sizeof(*nr));
     498                 :         57 :         nr->cookie = ne->cookie;
     499                 :         57 :         qtype = ne->qtype;
     500                 :            : 
     501                 :            :         /* Deal with various errors */
     502   [ -  -  +  - ]:         57 :         switch (ns_msg_getflag(handle, ns_f_rcode)) {
     503                 :            : 
     504                 :            :         case ns_r_nxdomain:
     505                 :          0 :                 nr->host_errno = HOST_NOT_FOUND;
     506                 :          0 :                 free(ne);
     507                 :          0 :                 return (1);
     508                 :            : 
     509                 :            :         case ns_r_servfail:
     510                 :          0 :                 nr->host_errno = TRY_AGAIN;
     511                 :          0 :                 free(ne);
     512                 :          0 :                 return (1);
     513                 :            : 
     514                 :            :         case ns_r_noerror:
     515                 :            :                 break;
     516                 :            : 
     517                 :            :         case ns_r_formerr:
     518                 :            :         case ns_r_notimpl:
     519                 :            :         case ns_r_refused:
     520                 :            :         default:
     521                 :          0 :                 nr->host_errno = NO_RECOVERY;
     522                 :          0 :                 free(ne);
     523                 :          0 :                 return (1);
     524                 :            :         }
     525                 :            : 
     526                 :            :         /* Loop through records in packet */
     527                 :         57 :         memset(&rr, 0, sizeof(rr));
     528         [ -  + ]:         57 :         memset(&nd->dns_hostent, 0, sizeof(nd->dns_hostent));
     529                 :         57 :         he = &nd->dns_hostent.hostent;
     530                 :            :         /* XXX no support for aliases */
     531                 :         57 :         he->h_aliases = nd->dns_hostent.host_aliases;
     532                 :         57 :         he->h_addr_list = nd->dns_hostent.h_addr_ptrs;
     533                 :         57 :         he->h_addrtype = ne->atype;
     534                 :         57 :         he->h_length = ne->asize;
     535                 :         57 :         free(ne);
     536                 :            : 
     537                 :         57 :         bp = nd->dns_hostent.hostbuf;
     538                 :         57 :         ep = bp + sizeof(nd->dns_hostent.hostbuf);
     539                 :         57 :         hap = he->h_addr_list;
     540                 :         57 :         ap = he->h_aliases;
     541                 :            : 
     542         [ +  + ]:        116 :         for (i = 0; i < ns_msg_count(handle, ns_s_an); i++) {
     543                 :            :                 /* Parse next record */
     544         [ -  + ]:         59 :                 if (ns_parserr(&handle, ns_s_an, i, &rr) < 0) {
     545         [ #  # ]:          0 :                         if (errno != ENODEV) {
     546                 :          0 :                                 nr->host_errno = NO_RECOVERY;
     547                 :          0 :                                 return (1);
     548                 :            :                         }
     549                 :            :                         /* All done */
     550                 :          0 :                         break;
     551                 :            :                 }
     552                 :            : 
     553                 :            :                 /* Ignore records that don't answer our query (e.g. CNAMEs) */
     554                 :         59 :                 atype = ns_rr_type(rr);
     555         [ +  + ]:         59 :                 if (atype != qtype)
     556                 :          2 :                         continue;
     557                 :            : 
     558                 :         57 :                 rdata = ns_rr_rdata(rr);
     559                 :         57 :                 rdlen = ns_rr_rdlen(rr);
     560      [ +  -  - ]:         57 :                 switch (atype) {
     561                 :            : 
     562                 :            :                 case T_A:
     563                 :            :                 case T_AAAA:
     564         [ -  + ]:         57 :                         if (rdlen != (unsigned int) he->h_length) {
     565                 :          0 :                                 snprintf(errstr, NB_DNS_ERRSIZE,
     566                 :            :                                     "nb_dns_activity(): bad rdlen %d",
     567                 :            :                                     (int) rdlen);
     568                 :          0 :                                 nr->host_errno = NO_RECOVERY;
     569                 :          0 :                                 return (-1);
     570                 :            :                         }
     571                 :            : 
     572         [ -  + ]:         57 :                         if (bp + rdlen >= ep) {
     573                 :          0 :                                 snprintf(errstr, NB_DNS_ERRSIZE,
     574                 :            :                                     "nb_dns_activity(): overflow 1");
     575                 :          0 :                                 nr->host_errno = NO_RECOVERY;
     576                 :          0 :                                 return (-1);
     577                 :            :                         }
     578         [ -  + ]:         57 :                         if (nd->dns_hostent.numaddrs + 1 >= MAXADDRS) {
     579                 :          0 :                                 snprintf(errstr, NB_DNS_ERRSIZE,
     580                 :            :                                     "nb_dns_activity(): overflow 2");
     581                 :          0 :                                 nr->host_errno = NO_RECOVERY;
     582                 :          0 :                                 return (-1);
     583                 :            :                         }
     584         [ -  + ]:         57 :                         memcpy(bp, rdata, rdlen);
     585                 :         57 :                         *hap++ = bp;
     586                 :         57 :                         bp += rdlen;
     587                 :         57 :                         ++nd->dns_hostent.numaddrs;
     588                 :            : 
     589                 :            :                         /* Keep looking for more A records */
     590                 :         57 :                         break;
     591                 :            : 
     592                 :            :                 case T_PTR:
     593                 :          0 :                         n = dn_expand((const u_char *)msg,
     594                 :            :                             (const u_char *)msg + msglen, rdata, bp, ep - bp);
     595         [ #  # ]:          0 :                         if (n < 0) {
     596                 :            :                                 /* XXX return -1 here ??? */
     597                 :          0 :                                 nr->host_errno = NO_RECOVERY;
     598                 :          0 :                                 return (1);
     599                 :            :                         }
     600                 :          0 :                         he->h_name = bp;
     601                 :            :                         /* XXX check for overflow */
     602                 :          0 :                         bp += n;                /* returned len includes EOS */
     603                 :            : 
     604                 :            :                         /* "Find first satisfactory answer" */
     605                 :          0 :                         nr->hostent = he;
     606                 :          0 :                         return (1);
     607                 :            :                 }
     608                 :            :         }
     609                 :            : 
     610                 :         57 :         nr->hostent = he;
     611                 :         57 :         return (1);
     612                 :            : }

Generated by: LCOV version 1.8