1 /*
2  * DNS Reply Tool (drool)
3  *
4  * Copyright (c) 2017-2018, OARC, Inc.
5  * Copyright (c) 2017, Comcast Corporation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. Neither the name of the copyright holder nor the names of its
21  *    contributors may be used to endorse or promote products derived
22  *    from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "config.h"
39 
40 #include "query.h"
41 #include "assert.h"
42 
43 #include <string.h>
44 #include <stdlib.h>
45 
46 /*
47  * New/Free
48  */
49 
query_new(void)50 drool_query_t* query_new(void)
51 {
52     return calloc(1, sizeof(drool_query_t));
53 }
54 
query_free(drool_query_t * query)55 void query_free(drool_query_t* query)
56 {
57     drool_assert(query);
58     if (query) {
59         if (query->raw) {
60             free(query->raw);
61         }
62         free(query);
63     }
64 }
65 
66 /*
67  * Have functions
68  */
69 
query_is_udp(const drool_query_t * query)70 inline int query_is_udp(const drool_query_t* query)
71 {
72     drool_assert(query);
73     return query->is_udp;
74 }
75 
query_is_tcp(const drool_query_t * query)76 inline int query_is_tcp(const drool_query_t* query)
77 {
78     drool_assert(query);
79     return query->is_tcp;
80 }
81 
query_have_ipv4(const drool_query_t * query)82 inline int query_have_ipv4(const drool_query_t* query)
83 {
84     drool_assert(query);
85     return query->have_ipv4;
86 }
87 
query_have_ipv6(const drool_query_t * query)88 inline int query_have_ipv6(const drool_query_t* query)
89 {
90     drool_assert(query);
91     return query->have_ipv6;
92 }
93 
query_have_port(const drool_query_t * query)94 inline int query_have_port(const drool_query_t* query)
95 {
96     drool_assert(query);
97     return query->have_port;
98 }
99 
query_have_raw(const drool_query_t * query)100 inline int query_have_raw(const drool_query_t* query)
101 {
102     drool_assert(query);
103     return query->have_raw;
104 }
105 
106 /*
107  * Get functions
108  */
109 
query_ip(const drool_query_t * query)110 inline const struct in_addr* query_ip(const drool_query_t* query)
111 {
112     drool_assert(query);
113 
114     if (!query->have_ipv4)
115         return 0;
116 
117     return &(query->addr.ip_dst);
118 }
119 
query_ip6(const drool_query_t * query)120 inline const struct in6_addr* query_ip6(const drool_query_t* query)
121 {
122     drool_assert(query);
123 
124     if (!query->have_ipv6)
125         return 0;
126 
127     return &(query->addr.ip6_dst);
128 }
129 
query_port(const drool_query_t * query)130 inline uint16_t query_port(const drool_query_t* query)
131 {
132     drool_assert(query);
133     return query->port;
134 }
135 
query_length(const drool_query_t * query)136 inline size_t query_length(const drool_query_t* query)
137 {
138     drool_assert(query);
139     return query->length;
140 }
141 
query_raw(const drool_query_t * query)142 inline const u_char* query_raw(const drool_query_t* query)
143 {
144     drool_assert(query);
145     return query->raw ? query->raw : query->small;
146 }
147 
148 /*
149  * Set functions
150  */
151 
query_set_udp(drool_query_t * query)152 int query_set_udp(drool_query_t* query)
153 {
154     drool_assert(query);
155     if (!query) {
156         return 1;
157     }
158     if (query->is_tcp) {
159         return 1;
160     }
161 
162     query->is_udp = 1;
163 
164     return 0;
165 }
166 
query_set_tcp(drool_query_t * query)167 int query_set_tcp(drool_query_t* query)
168 {
169     drool_assert(query);
170     if (!query) {
171         return 1;
172     }
173     if (query->is_udp) {
174         return 1;
175     }
176 
177     query->is_tcp = 1;
178 
179     return 0;
180 }
181 
query_set_ip(drool_query_t * query,const struct in_addr * addr)182 int query_set_ip(drool_query_t* query, const struct in_addr* addr)
183 {
184     drool_assert(query);
185     if (!query) {
186         return 1;
187     }
188     if (!addr) {
189         return 1;
190     }
191     if (query->have_ipv6) {
192         return 1;
193     }
194 
195     memcpy(&(query->addr.ip_dst), addr, sizeof(struct in_addr));
196     query->have_ipv4 = 1;
197 
198     return 0;
199 }
200 
query_set_ip6(drool_query_t * query,const struct in6_addr * addr)201 int query_set_ip6(drool_query_t* query, const struct in6_addr* addr)
202 {
203     drool_assert(query);
204     if (!addr) {
205         return 1;
206     }
207     if (query->have_ipv4) {
208         return 1;
209     }
210 
211     memcpy(&(query->addr.ip6_dst), addr, sizeof(struct in6_addr));
212     query->have_ipv6 = 1;
213 
214     return 0;
215 }
216 
query_set_port(drool_query_t * query,uint16_t port)217 int query_set_port(drool_query_t* query, uint16_t port)
218 {
219     drool_assert(query);
220     if (!query) {
221         return 1;
222     }
223     if (!port) {
224         return 1;
225     }
226 
227     query->port = port;
228 
229     return 0;
230 }
231 
query_set_raw(drool_query_t * query,const u_char * raw,size_t length)232 int query_set_raw(drool_query_t* query, const u_char* raw, size_t length)
233 {
234     drool_assert(query);
235     if (!query) {
236         return 1;
237     }
238     if (!raw) {
239         return 1;
240     }
241     if (!length) {
242         return 1;
243     }
244 
245     if (query->raw) {
246         free(query->raw);
247         query->raw      = 0;
248         query->length   = 0;
249         query->have_raw = 0;
250     }
251     if (length > sizeof(query->small)) {
252         if (!(query->raw = calloc(length, 1))) {
253             return 1;
254         }
255         memcpy(query->raw, raw, length);
256     } else {
257         memcpy(query->small, raw, length);
258     }
259     query->length   = length;
260     query->have_raw = 1;
261 
262     return 0;
263 }
264