"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/src/lib/ares_parse_a_reply.c" (8 Aug 2021, 4894 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_a_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 
    2 /* Copyright 1998 by the Massachusetts Institute of Technology.
    3  * Copyright (C) 2019 by Andrew Selivanov
    4  *
    5  * Permission to use, copy, modify, and distribute this
    6  * software and its documentation for any purpose and without
    7  * fee is hereby granted, provided that the above copyright
    8  * notice appear in all copies and that both that copyright
    9  * notice and this permission notice appear in supporting
   10  * documentation, and that the name of M.I.T. not be used in
   11  * advertising or publicity pertaining to distribution of the
   12  * software without specific, written prior permission.
   13  * M.I.T. makes no representations about the suitability of
   14  * this software for any purpose.  It is provided "as is"
   15  * without express or implied warranty.
   16  */
   17 
   18 #include "ares_setup.h"
   19 
   20 #ifdef HAVE_NETINET_IN_H
   21 #  include <netinet/in.h>
   22 #endif
   23 #ifdef HAVE_NETDB_H
   24 #  include <netdb.h>
   25 #endif
   26 #ifdef HAVE_ARPA_INET_H
   27 #  include <arpa/inet.h>
   28 #endif
   29 
   30 #include "ares_nameser.h"
   31 
   32 #ifdef HAVE_STRINGS_H
   33 #  include <strings.h>
   34 #endif
   35 
   36 #ifdef HAVE_LIMITS_H
   37 #  include <limits.h>
   38 #endif
   39 
   40 #include "ares.h"
   41 #include "ares_dns.h"
   42 #include "ares_private.h"
   43 
   44 int ares_parse_a_reply(const unsigned char *abuf, int alen,
   45                        struct hostent **host,
   46                        struct ares_addrttl *addrttls, int *naddrttls)
   47 {
   48   struct ares_addrinfo ai;
   49   struct ares_addrinfo_node *next;
   50   struct ares_addrinfo_cname *next_cname;
   51   char **aliases = NULL;
   52   char *question_hostname = NULL;
   53   struct hostent *hostent = NULL;
   54   struct in_addr *addrs = NULL;
   55   int naliases = 0, naddrs = 0, alias = 0, i;
   56   int cname_ttl = INT_MAX;
   57   int status;
   58 
   59   memset(&ai, 0, sizeof(ai));
   60 
   61   status = ares__parse_into_addrinfo2(abuf, alen, &question_hostname, &ai);
   62   if (status != ARES_SUCCESS)
   63     {
   64       ares_free(question_hostname);
   65 
   66       if (naddrttls)
   67         {
   68           *naddrttls = 0;
   69         }
   70 
   71       return status;
   72     }
   73 
   74   hostent = ares_malloc(sizeof(struct hostent));
   75   if (!hostent)
   76     {
   77       goto enomem;
   78     }
   79 
   80   next = ai.nodes;
   81   while (next)
   82     {
   83       if (next->ai_family == AF_INET)
   84         {
   85           ++naddrs;
   86         }
   87       next = next->ai_next;
   88     }
   89 
   90   next_cname = ai.cnames;
   91   while (next_cname)
   92     {
   93       if(next_cname->alias)
   94         ++naliases;
   95       next_cname = next_cname->next;
   96     }
   97 
   98   aliases = ares_malloc((naliases + 1) * sizeof(char *));
   99   if (!aliases)
  100     {
  101       goto enomem;
  102     }
  103 
  104   if (naliases)
  105     {
  106       next_cname = ai.cnames;
  107       while (next_cname)
  108         {
  109           if(next_cname->alias)
  110             aliases[alias++] = ares_strdup(next_cname->alias);
  111           if(next_cname->ttl < cname_ttl)
  112             cname_ttl = next_cname->ttl;
  113           next_cname = next_cname->next;
  114         }
  115     }
  116 
  117   aliases[alias] = NULL;
  118 
  119   hostent->h_addr_list = ares_malloc((naddrs + 1) * sizeof(char *));
  120   if (!hostent->h_addr_list)
  121     {
  122       goto enomem;
  123     }
  124 
  125   for (i = 0; i < naddrs + 1; ++i)
  126     {
  127       hostent->h_addr_list[i] = NULL;
  128     }
  129 
  130   if (ai.cnames)
  131     {
  132       hostent->h_name = ares_strdup(ai.cnames->name);
  133       ares_free(question_hostname);
  134     }
  135   else
  136     {
  137       hostent->h_name = question_hostname;
  138     }
  139 
  140   hostent->h_aliases = aliases;
  141   hostent->h_addrtype = AF_INET;
  142   hostent->h_length = sizeof(struct in_addr);
  143 
  144   if (naddrs)
  145     {
  146       addrs = ares_malloc(naddrs * sizeof(struct in_addr));
  147       if (!addrs)
  148         {
  149           goto enomem;
  150         }
  151 
  152       i = 0;
  153       next = ai.nodes;
  154       while (next)
  155         {
  156           if (next->ai_family == AF_INET)
  157             {
  158               hostent->h_addr_list[i] = (char *)&addrs[i];
  159               memcpy(hostent->h_addr_list[i],
  160                      &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
  161                      sizeof(struct in_addr));
  162               if (naddrttls && i < *naddrttls)
  163                 {
  164                   if (next->ai_ttl > cname_ttl)
  165                     addrttls[i].ttl = cname_ttl;
  166                   else
  167                     addrttls[i].ttl = next->ai_ttl;
  168 
  169                   memcpy(&addrttls[i].ipaddr,
  170                          &(CARES_INADDR_CAST(struct sockaddr_in *, next->ai_addr)->sin_addr),
  171                          sizeof(struct in_addr));
  172                 }
  173               ++i;
  174             }
  175           next = next->ai_next;
  176         }
  177       if (i == 0)
  178         {
  179           ares_free(addrs);
  180         }
  181     }
  182 
  183   if (host)
  184     {
  185       *host = hostent;
  186     }
  187   else
  188     {
  189       ares_free_hostent(hostent);
  190     }
  191 
  192   if (naddrttls)
  193     {
  194       /* Truncated to at most *naddrttls entries */
  195       *naddrttls = (naddrs > *naddrttls)?*naddrttls:naddrs;
  196     }
  197 
  198   ares__freeaddrinfo_cnames(ai.cnames);
  199   ares__freeaddrinfo_nodes(ai.nodes);
  200   return ARES_SUCCESS;
  201 
  202 enomem:
  203   ares_free(aliases);
  204   ares_free(hostent);
  205   ares__freeaddrinfo_cnames(ai.cnames);
  206   ares__freeaddrinfo_nodes(ai.nodes);
  207   ares_free(question_hostname);
  208   return ARES_ENOMEM;
  209 }