"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/src/lib/ares_parse_mx_reply.c" (8 Aug 2021, 4343 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_mx_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) 2010 Jeremy Lal <kapouer@melix.org>
    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 #include "ares.h"
   33 #include "ares_dns.h"
   34 #include "ares_data.h"
   35 #include "ares_private.h"
   36 
   37 int
   38 ares_parse_mx_reply (const unsigned char *abuf, int alen,
   39                      struct ares_mx_reply **mx_out)
   40 {
   41   unsigned int qdcount, ancount, i;
   42   const unsigned char *aptr, *vptr;
   43   int status, rr_type, rr_class, rr_len;
   44   long len;
   45   char *hostname = NULL, *rr_name = NULL;
   46   struct ares_mx_reply *mx_head = NULL;
   47   struct ares_mx_reply *mx_last = NULL;
   48   struct ares_mx_reply *mx_curr;
   49 
   50   /* Set *mx_out to NULL for all failure cases. */
   51   *mx_out = 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   if (ancount == 0)
   63     return ARES_ENODATA;
   64 
   65   /* Expand the name from the question, and skip past the question. */
   66   aptr = abuf + HFIXEDSZ;
   67   status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
   68   if (status != ARES_SUCCESS)
   69     return status;
   70 
   71   if (aptr + len + QFIXEDSZ > abuf + alen)
   72     {
   73       ares_free (hostname);
   74       return ARES_EBADRESP;
   75     }
   76   aptr += len + QFIXEDSZ;
   77 
   78   /* Examine each answer resource record (RR) in turn. */
   79   for (i = 0; i < ancount; i++)
   80     {
   81       /* Decode the RR up to the data field. */
   82       status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
   83       if (status != ARES_SUCCESS)
   84         {
   85           break;
   86         }
   87       aptr += len;
   88       if (aptr + RRFIXEDSZ > abuf + alen)
   89         {
   90           status = ARES_EBADRESP;
   91           break;
   92         }
   93       rr_type = DNS_RR_TYPE (aptr);
   94       rr_class = DNS_RR_CLASS (aptr);
   95       rr_len = DNS_RR_LEN (aptr);
   96       aptr += RRFIXEDSZ;
   97       if (aptr + rr_len > abuf + alen)
   98         {
   99           status = ARES_EBADRESP;
  100           break;
  101         }
  102 
  103       /* Check if we are really looking at a MX record */
  104       if (rr_class == C_IN && rr_type == T_MX)
  105         {
  106           /* parse the MX record itself */
  107           if (rr_len < 2)
  108             {
  109               status = ARES_EBADRESP;
  110               break;
  111             }
  112 
  113           /* Allocate storage for this MX answer appending it to the list */
  114           mx_curr = ares_malloc_data(ARES_DATATYPE_MX_REPLY);
  115           if (!mx_curr)
  116             {
  117               status = ARES_ENOMEM;
  118               break;
  119             }
  120           if (mx_last)
  121             {
  122               mx_last->next = mx_curr;
  123             }
  124           else
  125             {
  126               mx_head = mx_curr;
  127             }
  128           mx_last = mx_curr;
  129 
  130           vptr = aptr;
  131           mx_curr->priority = DNS__16BIT(vptr);
  132           vptr += sizeof(unsigned short);
  133 
  134           status = ares_expand_name (vptr, abuf, alen, &mx_curr->host, &len);
  135           if (status != ARES_SUCCESS)
  136             break;
  137         }
  138 
  139       /* Don't lose memory in the next iteration */
  140       ares_free (rr_name);
  141       rr_name = NULL;
  142 
  143       /* Move on to the next record */
  144       aptr += rr_len;
  145     }
  146 
  147   if (hostname)
  148     ares_free (hostname);
  149   if (rr_name)
  150     ares_free (rr_name);
  151 
  152   /* clean up on error */
  153   if (status != ARES_SUCCESS)
  154     {
  155       if (mx_head)
  156         ares_free_data (mx_head);
  157       return status;
  158     }
  159 
  160   /* everything looks fine, return the data */
  161   *mx_out = mx_head;
  162 
  163   return ARES_SUCCESS;
  164 }