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 
ares_free_data(void * dataptr)41 void 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 
ares_malloc_data(ares_datatype type)114 void *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 
ares_get_datatype(void * dataptr)170 ares_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