"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/src/lib/ares_parse_ns_reply.c" (8 Aug 2021, 4966 Bytes) of package /linux/misc/dns/c-ares-1.17.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ares_parse_ns_reply.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.17.1_vs_1.17.2.

    1 /* Copyright 1998 by the Massachusetts Institute of Technology.
    2  *
    3  * Permission to use, copy, modify, and distribute this
    4  * software and its documentation for any purpose and without
    5  * fee is hereby granted, provided that the above copyright
    6  * notice appear in all copies and that both that copyright
    7  * notice and this permission notice appear in supporting
    8  * documentation, and that the name of M.I.T. not be used in
    9  * advertising or publicity pertaining to distribution of the
   10  * software without specific, written prior permission.
   11  * M.I.T. makes no representations about the suitability of
   12  * this software for any purpose.  It is provided "as is"
   13  * without express or implied warranty.
   14  */
   15 
   16 /*
   17  * ares_parse_ns_reply created by Vlad Dinulescu <vlad.dinulescu@avira.com>
   18  *      on behalf of AVIRA Gmbh - http://www.avira.com
   19  */
   20 
   21 #include "ares_setup.h"
   22 
   23 #ifdef HAVE_NETINET_IN_H
   24 #  include <netinet/in.h>
   25 #endif
   26 #ifdef HAVE_NETDB_H
   27 #  include <netdb.h>
   28 #endif
   29 #ifdef HAVE_ARPA_INET_H
   30 #  include <arpa/inet.h>
   31 #endif
   32 
   33 #include "ares_nameser.h"
   34 
   35 #include "ares.h"
   36 #include "ares_dns.h"
   37 #include "ares_private.h"
   38 
   39 int ares_parse_ns_reply( const unsigned char* abuf, int alen,
   40                          struct hostent** host )
   41 {
   42   unsigned int qdcount, ancount;
   43   int status, i, rr_type, rr_class, rr_len;
   44   int nameservers_num;
   45   long len;
   46   const unsigned char *aptr;
   47   char* hostname, *rr_name, *rr_data, **nameservers;
   48   struct hostent *hostent;
   49 
   50   /* Set *host to NULL for all failure cases. */
   51   *host = NULL;
   52 
   53   /* Give up if abuf doesn't have room for a header. */
   54   if ( alen < HFIXEDSZ )
   55     return ARES_EBADRESP;
   56 
   57   /* Fetch the question and answer count from the header. */
   58   qdcount = DNS_HEADER_QDCOUNT( abuf );
   59   ancount = DNS_HEADER_ANCOUNT( abuf );
   60   if ( qdcount != 1 )
   61     return ARES_EBADRESP;
   62 
   63   /* Expand the name from the question, and skip past the question. */
   64   aptr = abuf + HFIXEDSZ;
   65   status = ares__expand_name_for_response( aptr, abuf, alen, &hostname, &len, 0);
   66   if ( status != ARES_SUCCESS )
   67     return status;
   68   if ( aptr + len + QFIXEDSZ > abuf + alen )
   69   {
   70     ares_free( hostname );
   71     return ARES_EBADRESP;
   72   }
   73   aptr += len + QFIXEDSZ;
   74 
   75   /* Allocate nameservers array; ancount gives an upper bound */
   76   nameservers = ares_malloc( ( ancount + 1 ) * sizeof( char * ) );
   77   if ( !nameservers )
   78   {
   79     ares_free( hostname );
   80     return ARES_ENOMEM;
   81   }
   82   nameservers_num = 0;
   83 
   84   /* Examine each answer resource record (RR) in turn. */
   85   for ( i = 0; i < ( int ) ancount; i++ )
   86   {
   87     /* Decode the RR up to the data field. */
   88     status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len, 0);
   89     if ( status != ARES_SUCCESS )
   90       break;
   91     aptr += len;
   92     if ( aptr + RRFIXEDSZ > abuf + alen )
   93     {
   94       status = ARES_EBADRESP;
   95       ares_free(rr_name);
   96       break;
   97     }
   98     rr_type = DNS_RR_TYPE( aptr );
   99     rr_class = DNS_RR_CLASS( aptr );
  100     rr_len = DNS_RR_LEN( aptr );
  101     aptr += RRFIXEDSZ;
  102     if (aptr + rr_len > abuf + alen)
  103       {
  104         ares_free(rr_name);
  105         status = ARES_EBADRESP;
  106         break;
  107       }
  108 
  109     if ( rr_class == C_IN && rr_type == T_NS )
  110     {
  111       /* Decode the RR data and add it to the nameservers list */
  112       status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data,
  113                                                &len, 1);
  114       if ( status != ARES_SUCCESS )
  115       {
  116         ares_free(rr_name);
  117         break;
  118       }
  119 
  120       nameservers[nameservers_num] = ares_malloc(strlen(rr_data)+1);
  121 
  122       if (nameservers[nameservers_num]==NULL)
  123       {
  124         ares_free(rr_name);
  125         ares_free(rr_data);
  126         status=ARES_ENOMEM;
  127         break;
  128       }
  129       strcpy(nameservers[nameservers_num],rr_data);
  130       ares_free(rr_data);
  131 
  132       nameservers_num++;
  133     }
  134 
  135     ares_free( rr_name );
  136 
  137     aptr += rr_len;
  138     if ( aptr > abuf + alen )
  139     {  /* LCOV_EXCL_START: already checked above */
  140       status = ARES_EBADRESP;
  141       break;
  142     }  /* LCOV_EXCL_STOP */
  143   }
  144 
  145   if ( status == ARES_SUCCESS && nameservers_num == 0 )
  146   {
  147     status = ARES_ENODATA;
  148   }
  149   if ( status == ARES_SUCCESS )
  150   {
  151     /* We got our answer.  Allocate memory to build the host entry. */
  152     nameservers[nameservers_num] = NULL;
  153     hostent = ares_malloc( sizeof( struct hostent ) );
  154     if ( hostent )
  155     {
  156       hostent->h_addr_list = ares_malloc( 1 * sizeof( char * ) );
  157       if ( hostent->h_addr_list )
  158       {
  159         /* Fill in the hostent and return successfully. */
  160         hostent->h_name = hostname;
  161         hostent->h_aliases = nameservers;
  162         hostent->h_addrtype = AF_INET;
  163         hostent->h_length = sizeof( struct in_addr );
  164         hostent->h_addr_list[0] = NULL;
  165         *host = hostent;
  166         return ARES_SUCCESS;
  167       }
  168       ares_free( hostent );
  169     }
  170     status = ARES_ENOMEM;
  171   }
  172   for ( i = 0; i < nameservers_num; i++ )
  173     ares_free( nameservers[i] );
  174   ares_free( nameservers );
  175   ares_free( hostname );
  176   return status;
  177 }