source: trunk/athena/lib/ares/ares_parse_ptr_reply.c @ 19791

Revision 19791, 3.8 KB checked in by mwhitson, 21 years ago (diff)
Modify ares_parse_{a,ptr}_reply() to use ares_parse_message() instead of doing their own reply parsing.
Line 
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
16static const char rcsid[] = "$Id: ares_parse_ptr_reply.c,v 1.4 2003-09-12 00:25:17 mwhitson Exp $";
17
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <netinet/in.h>
21#include <arpa/nameser.h>
22#include <stdlib.h>
23#include <string.h>
24#include <netdb.h>
25#include "ares.h"
26
27int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
28                         int addrlen, int family, struct hostent **host)
29{
30  int status, i, len;
31  char *ptrname, *hostname, *rr_data;
32  struct ares_dns_message *message;
33  struct ares_dns_rr *rr;
34  struct hostent *hostent;
35
36  /* Set *host to NULL for all failure cases. */
37  *host = NULL;
38
39  status = ares_parse_message(abuf, alen, &message);
40  if (status != ARES_SUCCESS)
41    return status;
42
43  if (message->qcount != 1)
44    {
45      ares_free_dns_message(message);
46      return ARES_EBADRESP;
47    }
48
49  ptrname = strdup(message->questions[0].name);
50  if (!ptrname)
51    {
52      ares_free_dns_message(message);
53      return ARES_ENOMEM;
54    }
55
56  /* Examine each answer resource record (RR) in turn. */
57  hostname = NULL;
58  for (i = 0; i < message->answers.count; i++)
59    {
60      rr = &message->answers.records[i];
61      if (rr->dnsclass == C_IN && rr->type == T_PTR
62          && strcasecmp(rr->name, ptrname) == 0)
63        {
64          /* Decode the RR data and set hostname to it. */
65
66          /* ares_parse_message() resolves compression pointers in the
67           * RR data, but the data still need to be expanded.  Since
68           * we know there is no indirection, use the data buffer
69           * itself as the containing buffer.
70           */
71          status = ares_expand_name(rr->data, rr->data, rr->len,
72                                    &rr_data, &len);
73          if (status != ARES_SUCCESS)
74            break;
75          if (hostname)
76            free(hostname);
77          hostname = rr_data;
78        }
79
80      if (rr->dnsclass == C_IN && rr->type == T_CNAME)
81        {
82          /* Decode the RR data and replace ptrname with it. */
83          status = ares_expand_name(rr->data, rr->data, rr->len,
84                                    &rr_data, &len);
85          if (status != ARES_SUCCESS)
86            break;
87          free(ptrname);
88          ptrname = rr_data;
89        }
90    }
91
92  if (status == ARES_SUCCESS && !hostname)
93    status = ARES_ENODATA;
94  if (status == ARES_SUCCESS)
95    {
96      /* We got our answer.  Allocate memory to build the host entry. */
97      hostent = malloc(sizeof(struct hostent));
98      if (hostent)
99        {
100          hostent->h_addr_list = malloc(2 * sizeof(char *));
101          if (hostent->h_addr_list)
102            {
103              hostent->h_addr_list[0] = malloc(addrlen);
104              if (hostent->h_addr_list[0])
105                {
106                  hostent->h_aliases = malloc(sizeof (char *));
107                  if (hostent->h_aliases)
108                    {
109                      /* Fill in the hostent and return successfully. */
110                      hostent->h_name = hostname;
111                      hostent->h_aliases[0] = NULL;
112                      hostent->h_addrtype = family;
113                      hostent->h_length = addrlen;
114                      memcpy(hostent->h_addr_list[0], addr, addrlen);
115                      hostent->h_addr_list[1] = NULL;
116                      *host = hostent;
117                      free(ptrname);
118                      ares_free_dns_message(message);
119                      return ARES_SUCCESS;
120                    }
121                  free(hostent->h_addr_list[0]);
122                }
123              free(hostent->h_addr_list);
124            }
125          free(hostent);
126        }
127      status = ARES_ENOMEM;
128    }
129  ares_free_dns_message(message);
130  if (hostname)
131    free(hostname);
132  free(ptrname);
133  return status;
134}
Note: See TracBrowser for help on using the repository browser.