1
2/* Copyright (C) 2009-2010 by Daniel Stenberg
3 *
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of M.I.T. not be used in
10 * advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission.
12 * M.I.T. makes no representations about the suitability of
13 * this software for any purpose.  It is provided "as is"
14 * without express or implied warranty.
15 */
16
17
18#include "ares_setup.h"
19
20#include <stddef.h>
21
22#include "ares.h"
23#include "ares_data.h"
24#include "ares_private.h"
25
26
27/*
28** ares_free_data() - c-ares external API function.
29**
30** This function must be used by the application to free data memory that
31** has been internally allocated by some c-ares function and for which a
32** pointer has already been returned to the calling application. The list
33** of c-ares functions returning pointers that must be free'ed using this
34** function is:
35**
36**   ares_get_servers()
37**   ares_parse_srv_reply()
38**   ares_parse_txt_reply()
39*/
40
41void ares_free_data(void *dataptr)
42{
43  struct ares_data *ptr;
44
45  if (!dataptr)
46    return;
47
48#ifdef __INTEL_COMPILER
49#  pragma warning(push)
50#  pragma warning(disable:1684)
51   /* 1684: conversion from pointer to same-sized integral type */
52#endif
53
54  ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
55
56#ifdef __INTEL_COMPILER
57#  pragma warning(pop)
58#endif
59
60  if (ptr->mark != ARES_DATATYPE_MARK)
61    return;
62
63  switch (ptr->type)
64    {
65      case ARES_DATATYPE_MX_REPLY:
66
67        if (ptr->data.mx_reply.next)
68          ares_free_data(ptr->data.mx_reply.next);
69        if (ptr->data.mx_reply.host)
70          free(ptr->data.mx_reply.host);
71        break;
72
73      case ARES_DATATYPE_SRV_REPLY:
74
75        if (ptr->data.srv_reply.next)
76          ares_free_data(ptr->data.srv_reply.next);
77        if (ptr->data.srv_reply.host)
78          free(ptr->data.srv_reply.host);
79        break;
80
81      case ARES_DATATYPE_TXT_REPLY:
82
83        if (ptr->data.txt_reply.next)
84          ares_free_data(ptr->data.txt_reply.next);
85        if (ptr->data.txt_reply.txt)
86          free(ptr->data.txt_reply.txt);
87        break;
88
89      case ARES_DATATYPE_ADDR_NODE:
90
91        if (ptr->data.addr_node.next)
92          ares_free_data(ptr->data.addr_node.next);
93        break;
94
95      default:
96        return;
97    }
98
99  free(ptr);
100}
101
102
103/*
104** ares_malloc_data() - c-ares internal helper function.
105**
106** This function allocates memory for a c-ares private ares_data struct
107** for the specified ares_datatype, initializes c-ares private fields
108** and zero initializes those which later might be used from the public
109** API. It returns an interior pointer which can be passed by c-ares
110** functions to the calling application, and that must be free'ed using
111** c-ares external API function ares_free_data().
112*/
113
114void *ares_malloc_data(ares_datatype type)
115{
116  struct ares_data *ptr;
117
118  ptr = malloc(sizeof(struct ares_data));
119  if (!ptr)
120    return NULL;
121
122  switch (type)
123    {
124      case ARES_DATATYPE_MX_REPLY:
125        ptr->data.mx_reply.next = NULL;
126        ptr->data.mx_reply.host = NULL;
127        ptr->data.mx_reply.priority = 0;
128        break;
129
130      case ARES_DATATYPE_SRV_REPLY:
131        ptr->data.srv_reply.next = NULL;
132        ptr->data.srv_reply.host = NULL;
133        ptr->data.srv_reply.priority = 0;
134        ptr->data.srv_reply.weight = 0;
135        ptr->data.srv_reply.port = 0;
136        break;
137
138      case ARES_DATATYPE_TXT_REPLY:
139        ptr->data.txt_reply.next = NULL;
140        ptr->data.txt_reply.txt = NULL;
141        ptr->data.txt_reply.length  = 0;
142        break;
143
144      case ARES_DATATYPE_ADDR_NODE:
145        ptr->data.addr_node.next = NULL;
146        ptr->data.addr_node.family = 0;
147        memset(&ptr->data.addr_node.addrV6, 0,
148               sizeof(ptr->data.addr_node.addrV6));
149        break;
150
151      default:
152        free(ptr);
153        return NULL;
154    }
155
156  ptr->mark = ARES_DATATYPE_MARK;
157  ptr->type = type;
158
159  return &ptr->data;
160}
161
162
163/*
164** ares_get_datatype() - c-ares internal helper function.
165**
166** This function returns the ares_datatype of the data stored in a
167** private ares_data struct when given the public API pointer.
168*/
169
170ares_datatype ares_get_datatype(void * dataptr)
171{
172  struct ares_data *ptr;
173
174#ifdef __INTEL_COMPILER
175#  pragma warning(push)
176#  pragma warning(disable:1684)
177   /* 1684: conversion from pointer to same-sized integral type */
178#endif
179
180  ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
181
182#ifdef __INTEL_COMPILER
183#  pragma warning(pop)
184#endif
185
186  if (ptr->mark == ARES_DATATYPE_MARK)
187    return ptr->type;
188
189  return ARES_DATATYPE_UNKNOWN;
190}
191