1 /**
2  *
3  * \file convert.c
4  * @brief getdns label conversion functions
5  *
6  */
7 
8 /*
9  * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions are met:
14  * * Redistributions of source code must retain the above copyright
15  *   notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above copyright
17  *   notice, this list of conditions and the following disclaimer in the
18  *   documentation and/or other materials provided with the distribution.
19  * * Neither the names of the copyright holders nor the
20  *   names of its contributors may be used to endorse or promote products
21  *   derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include "config.h"
36 #include <stdio.h>
37 #include <string.h>
38 #include <locale.h>
39 #ifndef USE_WINSOCK
40 #include <arpa/inet.h>
41 #endif
42 #if defined(HAVE_LIBIDN2)
43 #include <idn2.h>
44 #elif defined(HAVE_LIBIDN)
45 #include <stringprep.h>
46 #include <idna.h>
47 #endif
48 #include "getdns/getdns.h"
49 #include "getdns/getdns_extra.h"
50 #include "util-internal.h"
51 #include "gldns/wire2str.h"
52 #include "gldns/str2wire.h"
53 #include "gldns/parseutil.h"
54 #include "const-info.h"
55 #include "types-internal.h"	/* For getdns_item */
56 #include "dict.h"
57 #include "list.h"
58 #include "jsmn/jsmn.h"
59 #ifdef USE_YAML_CONFIG
60 #include "yaml/convert_yaml_to_json.h"
61 #endif
62 #include "convert.h"
63 #include "debug.h"
64 
65 getdns_return_t
getdns_convert_dns_name_to_fqdn(const getdns_bindata * dns_name_wire_fmt,char ** fqdn_as_string)66 getdns_convert_dns_name_to_fqdn(
67     const getdns_bindata *dns_name_wire_fmt, char **fqdn_as_string)
68 {
69 	char *r;
70 
71 	if (!dns_name_wire_fmt || !fqdn_as_string)
72 		return GETDNS_RETURN_INVALID_PARAMETER;
73 
74 	if (!(r = gldns_wire2str_dname(
75 	    dns_name_wire_fmt->data, dns_name_wire_fmt->size)))
76 		return GETDNS_RETURN_GENERIC_ERROR;
77 
78 	*fqdn_as_string = r;
79 	return GETDNS_RETURN_GOOD;
80 }
81 
82 getdns_return_t
getdns_convert_fqdn_to_dns_name(const char * fqdn_as_string,getdns_bindata ** dns_name_wire_fmt)83 getdns_convert_fqdn_to_dns_name(
84     const char *fqdn_as_string, getdns_bindata **dns_name_wire_fmt)
85 {
86 	getdns_bindata *r;
87 	uint8_t *dname;
88 	size_t len;
89 
90 	if (!fqdn_as_string || !dns_name_wire_fmt)
91 		return GETDNS_RETURN_INVALID_PARAMETER;
92 
93 	if (!(r = malloc(sizeof(getdns_bindata))))
94 		return GETDNS_RETURN_MEMORY_ERROR;
95 
96 	if (!(dname = gldns_str2wire_dname(fqdn_as_string, &len))) {
97 		free(r);
98 		return GETDNS_RETURN_GENERIC_ERROR;
99 	}
100 	r->size = len;
101 	r->data = dname;
102 	*dns_name_wire_fmt = r;
103 	return GETDNS_RETURN_GOOD;
104 }
105 
106 /*---------------------------------------- getdns_convert_alabel_to_ulabel */
107 /**
108  * Convert UTF-8 string into an ACE-encoded domain
109  * It is the application programmer's responsibility to free()
110  * the returned buffer after use
111  *
112  * @param ulabel the UTF-8-encoded domain name to convert
113  * @return pointer to ACE-encoded string
114  * @return NULL if conversion fails
115  */
116 
117 char *
getdns_convert_ulabel_to_alabel(const char * ulabel)118 getdns_convert_ulabel_to_alabel(const char *ulabel)
119 {
120 #if defined(HAVE_LIBIDN2)
121 	uint8_t *alabel;
122 
123 	if (!ulabel) return NULL;
124 
125 	if (idn2_lookup_u8((uint8_t *)ulabel, &alabel, IDN2_TRANSITIONAL) == IDN2_OK)
126 		return (char *)alabel;
127 
128 #elif defined(HAVE_LIBIDN)
129 	char *alabel;
130 	char *prepped;
131 	char  prepped2[BUFSIZ];
132 
133 	if (!ulabel) return NULL;
134 
135 	setlocale(LC_ALL, "");
136 	if ((prepped = stringprep_locale_to_utf8(ulabel))) {
137 		if(strlen(prepped)+1 > BUFSIZ) {
138 			free(prepped);
139 			return NULL;
140 		}
141 		memcpy(prepped2, prepped, strlen(prepped)+1);
142 		free(prepped);
143 
144 		/* convert to utf8 fails, which it can, but continue anyway */
145 	} else if (strlen(ulabel)+1 > BUFSIZ)
146 		return NULL;
147 	else
148 		memcpy(prepped2, ulabel, strlen(ulabel)+1);
149 
150 	if (stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep) == STRINGPREP_OK
151 	&&  idna_to_ascii_8z(prepped2, &alabel, 0) == IDNA_SUCCESS)
152 		return alabel;
153 #else
154 	(void)ulabel;
155 #endif
156 	return NULL;
157 }
158 
159 /*---------------------------------------- getdns_convert_alabel_to_ulabel */
160 /**
161  * Convert ACE-encoded domain name into a UTF-8 string.
162  * It is the application programmer's responsibility to free()
163  * the returned buffer after use
164  *
165  * @param alabel the ACE-encoded domain name to convert
166  * @return pointer to UTF-8 string
167  * @return NULL if conversion fails
168  */
169 
170 char *
getdns_convert_alabel_to_ulabel(const char * alabel)171 getdns_convert_alabel_to_ulabel(const char *alabel)
172 {
173 #if defined(HAVE_LIBIDN2) || defined(HAVE_LIBIDN)
174 	char *ulabel;
175 
176 	if (!alabel) return NULL;
177 
178 # if defined(HAVE_LIBIDN2)
179 	if (idn2_to_unicode_8z8z(alabel, &ulabel, 0) == IDN2_OK)
180 # else
181 	if (idna_to_unicode_8z8z(alabel, &ulabel, 0) == IDNA_SUCCESS)
182 # endif
183 		return ulabel;
184 #else
185 	(void)alabel;
186 #endif
187 	return NULL;
188 }
189 
190 
191 char *
getdns_display_ip_address(const struct getdns_bindata * bindata_of_ipv4_or_ipv6_address)192 getdns_display_ip_address(const struct getdns_bindata
193     *bindata_of_ipv4_or_ipv6_address)
194 {
195 	char buff[256];
196 	if (!bindata_of_ipv4_or_ipv6_address ||
197 	    bindata_of_ipv4_or_ipv6_address->size == 0 ||
198 	    !bindata_of_ipv4_or_ipv6_address->data) {
199 		return NULL;
200 	}
201 	if (bindata_of_ipv4_or_ipv6_address->size == 4) {
202 		const char *ipStr = inet_ntop(AF_INET,
203 		    bindata_of_ipv4_or_ipv6_address->data,
204 		    buff,
205 		    256);
206 		if (ipStr) {
207 			return strdup(ipStr);
208 		}
209 	} else if (bindata_of_ipv4_or_ipv6_address->size == 16) {
210 		const char *ipStr = inet_ntop(AF_INET6,
211 		    bindata_of_ipv4_or_ipv6_address->data,
212 		    buff,
213 		    256);
214 		if (ipStr) {
215 			return strdup(ipStr);
216 		}
217 	}
218 	return NULL;
219 }
220 
221 getdns_return_t
getdns_strerror(getdns_return_t err,char * buf,size_t buflen)222 getdns_strerror(getdns_return_t err, char *buf, size_t buflen)
223 {
224 	const char *err_str = getdns_get_errorstr_by_id(err);
225 
226 	(void) snprintf(buf, buflen, "%s",
227 	    err_str ? err_str : "/* <unknown getdns value> */");
228 
229 	return GETDNS_RETURN_GOOD;
230 }				/* getdns_strerror */
231 
232 
233 /* --------------------- rr_dict, wire, str conversions --------------------- */
234 
235 
236 getdns_return_t
getdns_rr_dict2wire(const getdns_dict * rr_dict,uint8_t ** wire,size_t * wire_sz)237 getdns_rr_dict2wire(
238     const getdns_dict *rr_dict, uint8_t **wire, size_t *wire_sz)
239 {
240 	uint8_t buf_spc[4096], *buf;
241 	size_t buf_len = sizeof(buf_spc);
242 	getdns_return_t r = getdns_rr_dict2wire_buf(
243 	    rr_dict, buf_spc, &buf_len);
244 
245 	if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
246 		return r;
247 
248 	if (!(buf = malloc(buf_len ? buf_len : 1)))
249 		return GETDNS_RETURN_MEMORY_ERROR;
250 
251 	if (!r)
252 		memcpy(buf, buf_spc, buf_len);
253 
254 	else if ((r = getdns_rr_dict2wire_buf(rr_dict, buf, &buf_len))) {
255 		free(buf);
256 		return r;
257 	}
258 	*wire = buf;
259 	*wire_sz = buf_len;
260 	return GETDNS_RETURN_GOOD;
261 }
262 
263 getdns_return_t
getdns_rr_dict2wire_buf(const getdns_dict * rr_dict,uint8_t * wire,size_t * wire_sz)264 getdns_rr_dict2wire_buf(
265     const getdns_dict *rr_dict, uint8_t *wire, size_t *wire_sz)
266 {
267 	int my_wire_sz;
268 	getdns_return_t r;
269 
270 	if (!wire_sz)
271 		return GETDNS_RETURN_INVALID_PARAMETER;
272 	else
273 		my_wire_sz = *wire_sz;
274 
275 	r = getdns_rr_dict2wire_scan(rr_dict, &wire, &my_wire_sz);
276 	if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
277 		*wire_sz -= my_wire_sz;
278 	return r;
279 }
280 
281 getdns_return_t
getdns_rr_dict2wire_scan(const getdns_dict * rr_dict,uint8_t ** wire,int * wire_sz)282 getdns_rr_dict2wire_scan(
283     const getdns_dict *rr_dict, uint8_t **wire, int *wire_sz)
284 {
285 	getdns_return_t r;
286 	gldns_buffer gbuf;
287 
288 	if (!rr_dict || !wire || !*wire || !wire_sz)
289 		return GETDNS_RETURN_INVALID_PARAMETER;
290 
291 
292 	gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz);
293 	if ((r = _getdns_rr_dict2wire(rr_dict, &gbuf)))
294 		return r;
295 
296 	if (gldns_buffer_position(&gbuf) == 0)
297 		return GETDNS_RETURN_GENERIC_ERROR;
298 
299 	*wire += gldns_buffer_position(&gbuf);
300 	*wire_sz -= gldns_buffer_position(&gbuf);
301 	if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
302 		return GETDNS_RETURN_NEED_MORE_SPACE;
303 	else
304 		return GETDNS_RETURN_GOOD;
305 }
306 
307 static struct mem_funcs _getdns_plain_mem_funcs = {
308 	MF_PLAIN, .mf.pln = { malloc, realloc, free }
309 };
310 
311 getdns_return_t
_getdns_wire2rr_dict(struct mem_funcs * mf,const uint8_t * wire,size_t wire_len,getdns_dict ** rr_dict)312 _getdns_wire2rr_dict(struct mem_funcs *mf,
313     const uint8_t *wire, size_t wire_len, getdns_dict **rr_dict)
314 {
315 	return _getdns_wire2rr_dict_scan(mf, &wire, &wire_len, rr_dict);
316 }
317 getdns_return_t
getdns_wire2rr_dict(const uint8_t * wire,size_t wire_len,getdns_dict ** rr_dict)318 getdns_wire2rr_dict(
319     const uint8_t *wire, size_t wire_len, getdns_dict **rr_dict)
320 {
321 	return _getdns_wire2rr_dict(
322 	    &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
323 }
324 
325 getdns_return_t
_getdns_wire2rr_dict_buf(struct mem_funcs * mf,const uint8_t * wire,size_t * wire_len,getdns_dict ** rr_dict)326 _getdns_wire2rr_dict_buf(struct mem_funcs *mf,
327     const uint8_t *wire, size_t *wire_len, getdns_dict **rr_dict)
328 {
329 	size_t my_wire_len;
330 	getdns_return_t r;
331 
332 	if (!wire_len)
333 		return GETDNS_RETURN_INVALID_PARAMETER;
334 	else
335 		my_wire_len = *wire_len;
336 
337 	if ((r = _getdns_wire2rr_dict_scan(mf, &wire, &my_wire_len, rr_dict)))
338 		return r;
339 
340 	*wire_len -= my_wire_len;
341 	return GETDNS_RETURN_GOOD;
342 }
343 getdns_return_t
getdns_wire2rr_dict_buf(const uint8_t * wire,size_t * wire_len,getdns_dict ** rr_dict)344 getdns_wire2rr_dict_buf(
345     const uint8_t *wire, size_t *wire_len, getdns_dict **rr_dict)
346 {
347 	return _getdns_wire2rr_dict_buf(
348 	    &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
349 }
350 
351 getdns_return_t
_getdns_wire2rr_dict_scan(struct mem_funcs * mf,const uint8_t ** wire,size_t * wire_len,getdns_dict ** rr_dict)352 _getdns_wire2rr_dict_scan(struct mem_funcs *mf,
353     const uint8_t **wire, size_t *wire_len, getdns_dict **rr_dict)
354 {
355 	_getdns_rr_iter rr_iter_spc, *rr_iter;
356 
357 	if (!wire || !*wire || !wire_len || !rr_dict)
358 		return GETDNS_RETURN_INVALID_PARAMETER;
359 
360 	if (!(rr_iter = _getdns_single_rr_iter_init(
361 	    &rr_iter_spc, *wire, *wire_len)))
362 		return GETDNS_RETURN_GENERIC_ERROR;
363 
364 	if (!(*rr_dict = _getdns_rr_iter2rr_dict(mf, rr_iter)))
365 		return GETDNS_RETURN_MEMORY_ERROR;
366 
367 	*wire_len -= (rr_iter->nxt - rr_iter->pos);
368 	*wire = rr_iter->nxt;
369 
370 	return GETDNS_RETURN_GOOD;
371 }
372 getdns_return_t
getdns_wire2rr_dict_scan(const uint8_t ** wire,size_t * wire_len,getdns_dict ** rr_dict)373 getdns_wire2rr_dict_scan(
374     const uint8_t **wire, size_t *wire_len, getdns_dict **rr_dict)
375 {
376 	return _getdns_wire2rr_dict_scan(
377 	    &_getdns_plain_mem_funcs, wire, wire_len, rr_dict);
378 }
379 
380 
381 getdns_return_t
getdns_rr_dict2str(const getdns_dict * rr_dict,char ** str)382 getdns_rr_dict2str(
383     const getdns_dict *rr_dict, char **str)
384 {
385 	char buf_spc[4096], *buf;
386 	size_t buf_len = sizeof(buf_spc) - 1;
387 	getdns_return_t r = getdns_rr_dict2str_buf(
388 	    rr_dict, buf_spc, &buf_len);
389 
390 	if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
391 		return r;
392 
393 	buf_len += 1;
394 	if (!(buf = malloc(buf_len)))
395 		return GETDNS_RETURN_MEMORY_ERROR;
396 
397 	if (!r)
398 		memcpy(buf, buf_spc, buf_len);
399 
400 	else if ((r = getdns_rr_dict2str_buf(rr_dict, buf, &buf_len))) {
401 		free(buf);
402 		return r;
403 	}
404 	*str = buf;
405 	return GETDNS_RETURN_GOOD;
406 }
407 
408 getdns_return_t
getdns_rr_dict2str_buf(const getdns_dict * rr_dict,char * str,size_t * str_len)409 getdns_rr_dict2str_buf(
410     const getdns_dict *rr_dict, char *str, size_t *str_len)
411 {
412 	int my_str_len;
413 	getdns_return_t r;
414 
415 	if (!str_len)
416 		return GETDNS_RETURN_INVALID_PARAMETER;
417 	else
418 		my_str_len = *str_len;
419 
420 	r = getdns_rr_dict2str_scan(rr_dict, &str, &my_str_len);
421 	if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
422 		*str_len -= my_str_len;
423 	return r;
424 
425 }
426 
427 getdns_return_t
getdns_rr_dict2str_scan(const getdns_dict * rr_dict,char ** str,int * str_len)428 getdns_rr_dict2str_scan(
429     const getdns_dict *rr_dict, char **str, int *str_len)
430 {
431 	getdns_return_t r;
432 	gldns_buffer gbuf;
433 	uint8_t buf_spc[4096], *buf = buf_spc, *scan_buf;
434 	size_t sz, scan_sz;
435 	int prev_str_len;
436 	char *prev_str;
437 	int sz_needed;
438 
439 	if (!rr_dict || !str || !*str || !str_len)
440 		return GETDNS_RETURN_INVALID_PARAMETER;
441 
442 	gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc));
443 	r = _getdns_rr_dict2wire(rr_dict, &gbuf);
444 	if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
445 		if (!(buf = GETDNS_XMALLOC(
446 		    rr_dict->mf, uint8_t, (sz = gldns_buffer_position(&gbuf))))) {
447 			return GETDNS_RETURN_MEMORY_ERROR;
448 		}
449 		gldns_buffer_init_frm_data(&gbuf, buf, sz);
450 		r = _getdns_rr_dict2wire(rr_dict, &gbuf);
451 	}
452 	if (r) {
453 		if (buf != buf_spc)
454 			GETDNS_FREE(rr_dict->mf, buf);
455 		return r;
456 	}
457 	scan_buf = gldns_buffer_begin(&gbuf);
458 	scan_sz  = gldns_buffer_position(&gbuf);
459 	prev_str = *str;
460 	prev_str_len = *str_len;
461 	sz = (size_t)*str_len;
462 	sz_needed = gldns_wire2str_rr_scan(
463 	    &scan_buf, &scan_sz, str, &sz, NULL, 0);
464 
465 	if (sz_needed > prev_str_len) {
466 		*str = prev_str + sz_needed;
467 		*str_len = prev_str_len - sz_needed;
468 		r = GETDNS_RETURN_NEED_MORE_SPACE;
469 	} else  {
470 		*str_len = sz;
471 		**str = 0;
472 	}
473 	if (buf != buf_spc)
474 		GETDNS_FREE(rr_dict->mf, buf);
475 	return r;
476 }
477 
478 
479 getdns_return_t
_getdns_str2rr_dict(struct mem_funcs * mf,const char * str,getdns_dict ** rr_dict,const char * origin,uint32_t default_ttl)480 _getdns_str2rr_dict(struct mem_funcs *mf,
481     const char *str, getdns_dict **rr_dict, const char *origin, uint32_t default_ttl)
482 {
483 	uint8_t wire_spc[4096], *wire = wire_spc;
484 	uint8_t origin_spc[256], *origin_wf;
485 	size_t origin_len = sizeof(origin_spc), wire_len = sizeof(wire_spc);
486 	int e;
487 	getdns_return_t r;
488 
489 	if (!str || !rr_dict)
490 		return GETDNS_RETURN_INVALID_PARAMETER;
491 
492 	if (!origin)
493 		origin_wf = NULL;
494 
495 	else if (gldns_str2wire_dname_buf(origin, origin_spc, &origin_len))
496 		return GETDNS_RETURN_GENERIC_ERROR;
497 	else
498 		origin_wf = origin_spc;
499 
500 	e = gldns_str2wire_rr_buf(str, wire, &wire_len,
501 	    NULL, default_ttl, origin_wf, origin_len, NULL, 0);
502 	if (GLDNS_WIREPARSE_ERROR(e) == GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL) {
503 
504 		if (!(wire = GETDNS_XMALLOC(
505 		    *mf, uint8_t, (wire_len = GLDNS_RR_BUF_SIZE))))
506 			return GETDNS_RETURN_MEMORY_ERROR;
507 		e = gldns_str2wire_rr_buf(str, wire, &wire_len,
508 	            NULL, default_ttl, origin_wf, origin_len, NULL, 0);
509 	}
510 	if (e) {
511 		if (wire != wire_spc)
512 			GETDNS_FREE(*mf, wire);
513 		return GETDNS_RETURN_GENERIC_ERROR;
514 	}
515 	r = _getdns_wire2rr_dict(mf, wire, wire_len, rr_dict);
516 	if (wire != wire_spc)
517 		GETDNS_FREE(*mf, wire);
518 	return r;
519 }
520 getdns_return_t
getdns_str2rr_dict(const char * str,getdns_dict ** rr_dict,const char * origin,uint32_t default_ttl)521 getdns_str2rr_dict(
522     const char *str, getdns_dict **rr_dict, const char *origin, uint32_t default_ttl)
523 {
524 	return _getdns_str2rr_dict(
525 	    &_getdns_plain_mem_funcs, str, rr_dict, origin, default_ttl);
526 }
527 
528 
529 getdns_return_t
_getdns_fp2rr_list(struct mem_funcs * mf,FILE * in,getdns_list ** rr_list,const char * origin,uint32_t default_ttl)530 _getdns_fp2rr_list(struct mem_funcs *mf,
531     FILE *in, getdns_list **rr_list, const char *origin, uint32_t default_ttl)
532 {
533 	struct gldns_file_parse_state pst;
534 	getdns_list *rrs;
535 	getdns_return_t r = GETDNS_RETURN_GOOD;
536 	uint8_t *rr;
537 	size_t len, dname_len;
538 	getdns_dict *rr_dict;
539 
540 	if (!in || !rr_list)
541 		return GETDNS_RETURN_INVALID_PARAMETER;
542 
543 	if (!origin) {
544 		*pst.origin = 0;
545 		pst.origin_len = 1;
546 
547 	} else if (gldns_str2wire_dname_buf(origin,pst.origin,&pst.origin_len))
548 		return GETDNS_RETURN_GENERIC_ERROR;
549 
550 	*pst.prev_rr = 0;
551 	pst.prev_rr_len = 1;
552 	pst.default_ttl = default_ttl;
553 	pst.lineno = 1;
554 
555 	if (!(rrs = _getdns_list_create_with_mf(mf)))
556 		return GETDNS_RETURN_MEMORY_ERROR;
557 
558 
559 	if (!(rr = GETDNS_XMALLOC(*mf, uint8_t, GLDNS_RR_BUF_SIZE)))
560 		r = GETDNS_RETURN_MEMORY_ERROR;
561 
562 	else while (r == GETDNS_RETURN_GOOD && !feof(in)) {
563 		len = GLDNS_RR_BUF_SIZE;
564 		dname_len = 0;
565 		if (gldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst))
566 			break;
567 		if (dname_len && dname_len < sizeof(pst.prev_rr)) {
568 			memcpy(pst.prev_rr, rr, dname_len);
569 			pst.prev_rr_len = dname_len;
570 		}
571 		if (len == 0)
572 			continue;
573 		if ((r = _getdns_wire2rr_dict(mf, rr, len, &rr_dict)))
574 			break;
575 		if ((r = _getdns_list_append_this_dict(rrs, rr_dict)))
576 			getdns_dict_destroy(rr_dict);
577 	}
578 	if (rr)
579 		GETDNS_FREE(*mf, rr);
580 	if (r)
581 		getdns_list_destroy(rrs);
582 	else
583 		*rr_list = rrs;
584 	return r;
585 }
586 
587 getdns_return_t
getdns_fp2rr_list(FILE * in,getdns_list ** rr_list,const char * origin,uint32_t default_ttl)588 getdns_fp2rr_list(
589     FILE *in, getdns_list **rr_list, const char *origin, uint32_t default_ttl)
590 {
591 	return _getdns_fp2rr_list(
592 	    &_getdns_plain_mem_funcs, in, rr_list, origin, default_ttl);
593 }
594 
595 #define SET_WIRE_INT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
596                               GLDNS_ ## Y ## _WIRE(*wire))) goto error
597 #define SET_WIRE_BIT(X,Y) if (getdns_dict_set_int(header, #X , \
598                               GLDNS_ ## Y ## _WIRE(*wire) ? 1 : 0)) goto error
599 #define SET_WIRE_CNT(X,Y) if (getdns_dict_set_int(header, #X , (int) \
600                               GLDNS_ ## Y (*wire))) goto error
601 
602 getdns_return_t
_getdns_wire2msg_dict_scan(struct mem_funcs * mf,const uint8_t ** wire,size_t * wire_len,getdns_dict ** msg_dict)603 _getdns_wire2msg_dict_scan(struct mem_funcs *mf,
604     const uint8_t **wire, size_t *wire_len, getdns_dict **msg_dict)
605 {
606 	getdns_return_t r = GETDNS_RETURN_GOOD;
607 	getdns_dict *result = NULL, *header = NULL, *rr_dict = NULL;
608 	_getdns_rr_iter rr_iter_storage, *rr_iter;
609 	_getdns_section section;
610 	getdns_list *sections[16] = { NULL, NULL, NULL, NULL
611 	                            , NULL, NULL, NULL, NULL
612 	                            , NULL, NULL, NULL, NULL
613 	                            , NULL, NULL, NULL, NULL };
614 	const uint8_t *eop; /* end of packet */
615 
616 	if (!wire || !*wire || !wire_len || !msg_dict)
617 		return GETDNS_RETURN_INVALID_PARAMETER;
618 
619 #if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
620 	do {
621 		char *str = gldns_wire2str_pkt((uint8_t *)*wire, *wire_len);
622 		DEBUG_SERVER("_getdns_wire2msg_dict_scan for a packet size: %d: %s\n",
623 		    (int)*wire_len, str);
624 		free(str);
625 	} while(0);
626 #endif
627 
628        	if (!(result = _getdns_dict_create_with_mf(mf)) ||
629 	    !(header = _getdns_dict_create_with_mf(mf)) ||
630 	    !(sections[SECTION_ANSWER]
631 	             = _getdns_list_create_with_mf(mf)) ||
632 	    !(sections[SECTION_AUTHORITY]
633 	             = _getdns_list_create_with_mf(mf)) ||
634 	    !(sections[SECTION_ADDITIONAL]
635 	             = _getdns_list_create_with_mf(mf))) {
636 		r = GETDNS_RETURN_MEMORY_ERROR;
637 		goto error;
638 	}
639 	SET_WIRE_INT(id, ID);
640 	SET_WIRE_BIT(qr, QR);
641 	SET_WIRE_BIT(aa, AA);
642 	SET_WIRE_BIT(tc, TC);
643 	SET_WIRE_BIT(rd, RD);
644 	SET_WIRE_BIT(cd, CD);
645 	SET_WIRE_BIT(ra, RA);
646 	SET_WIRE_BIT(ad, AD);
647 	SET_WIRE_INT(opcode, OPCODE);
648 	SET_WIRE_INT(rcode, RCODE);
649 	SET_WIRE_BIT(z, Z);
650 
651 	SET_WIRE_CNT(qdcount, QDCOUNT);
652 	SET_WIRE_CNT(ancount, ANCOUNT);
653 	SET_WIRE_CNT(nscount, NSCOUNT);
654 	SET_WIRE_CNT(arcount, ARCOUNT);
655 
656 	/* header */
657     	if ((r = _getdns_dict_set_this_dict(result, "header", header)))
658 		goto error;
659 	header = NULL;
660 	eop = *wire + 12;
661 
662 	for ( rr_iter = _getdns_rr_iter_init(&rr_iter_storage,*wire,*wire_len)
663 	    ; rr_iter
664 	    ; rr_iter = _getdns_rr_iter_next(rr_iter)) {
665 
666 		if (rr_iter->nxt > eop)
667 			eop = rr_iter->nxt;
668 
669 		if (!(rr_dict = _getdns_rr_iter2rr_dict(mf, rr_iter)))
670 			continue;
671 
672 		switch ((section = _getdns_rr_iter_section(rr_iter))) {
673 		case SECTION_QUESTION:
674 			if ((r = _getdns_dict_set_this_dict(
675 			     result, "question", rr_dict)))
676 				goto error;
677 			break;
678 		case SECTION_ANSWER:
679 		case SECTION_AUTHORITY:
680 		case SECTION_ADDITIONAL:
681 			if ((r = _getdns_list_append_this_dict(
682 			     sections[section], rr_dict)))
683 				goto error;
684 			break;
685 		default:
686 			r = GETDNS_RETURN_GENERIC_ERROR;
687 			goto error;
688 		}
689 		rr_dict = NULL;
690 	}
691 	if (!(r = _getdns_dict_set_this_list(result, "answer",
692 	    sections[SECTION_ANSWER])))
693 		sections[SECTION_ANSWER] = NULL;
694 	else	goto error;
695 
696 	if (!(r = _getdns_dict_set_this_list(result, "authority",
697 	    sections[SECTION_AUTHORITY])))
698 		sections[SECTION_AUTHORITY] = NULL;
699 	else	goto error;
700 
701 	if (!(r = _getdns_dict_set_this_list(result, "additional",
702 	    sections[SECTION_ADDITIONAL])))
703 		sections[SECTION_ADDITIONAL] = NULL;
704 	else	goto error;
705 
706 	*wire_len -= (eop - *wire);
707 	*wire = eop;
708 error:
709 	getdns_dict_destroy(rr_dict);
710 	getdns_list_destroy(sections[SECTION_ADDITIONAL]);
711 	getdns_list_destroy(sections[SECTION_AUTHORITY]);
712 	getdns_list_destroy(sections[SECTION_ANSWER]);
713 	getdns_dict_destroy(header);
714 	if (r)
715 		getdns_dict_destroy(result);
716 	else
717 		*msg_dict = result;
718 
719 	return r;
720 }
721 
722 
723 getdns_return_t
_getdns_wire2msg_dict(struct mem_funcs * mf,const uint8_t * wire,size_t wire_len,getdns_dict ** msg_dict)724 _getdns_wire2msg_dict(struct mem_funcs *mf,
725     const uint8_t *wire, size_t wire_len, getdns_dict **msg_dict)
726 {
727 	return _getdns_wire2msg_dict_scan(mf, &wire, &wire_len, msg_dict);
728 }
729 getdns_return_t
getdns_wire2msg_dict(const uint8_t * wire,size_t wire_len,getdns_dict ** msg_dict)730 getdns_wire2msg_dict(
731     const uint8_t *wire, size_t wire_len, getdns_dict **msg_dict)
732 {
733 	return _getdns_wire2msg_dict(
734 	    &_getdns_plain_mem_funcs, wire, wire_len, msg_dict);
735 }
736 
737 getdns_return_t
_getdns_wire2msg_dict_buf(struct mem_funcs * mf,const uint8_t * wire,size_t * wire_len,getdns_dict ** msg_dict)738 _getdns_wire2msg_dict_buf(struct mem_funcs *mf,
739     const uint8_t *wire, size_t *wire_len, getdns_dict **msg_dict)
740 {
741 	size_t my_wire_len;
742 	getdns_return_t r;
743 
744 	if (!wire_len)
745 		return GETDNS_RETURN_INVALID_PARAMETER;
746 	else
747 		my_wire_len = *wire_len;
748 
749 	if ((r = _getdns_wire2msg_dict_scan(mf, &wire, &my_wire_len, msg_dict)))
750 		return r;
751 
752 	*wire_len -= my_wire_len;
753 	return GETDNS_RETURN_GOOD;
754 }
755 getdns_return_t
getdns_wire2msg_dict_buf(const uint8_t * wire,size_t * wire_len,getdns_dict ** msg_dict)756 getdns_wire2msg_dict_buf(
757     const uint8_t *wire, size_t *wire_len, getdns_dict **msg_dict)
758 {
759 	return _getdns_wire2msg_dict_buf(
760 	    &_getdns_plain_mem_funcs, wire, wire_len, msg_dict);
761 }
762 
763 getdns_return_t
getdns_wire2msg_dict_scan(const uint8_t ** wire,size_t * wire_len,getdns_dict ** msg_dict)764 getdns_wire2msg_dict_scan(
765     const uint8_t **wire, size_t *wire_len, getdns_dict **msg_dict)
766 {
767 	return _getdns_wire2msg_dict_scan(
768 	    &_getdns_plain_mem_funcs, wire, wire_len, msg_dict);
769 }
770 
771 #define SET_HEADER_INT(X,Y) \
772 	if (!getdns_dict_get_int(reply, "/header/" #X, &n)) \
773 		GLDNS_ ## Y ## _SET(header, n);
774 #define SET_HEADER_BIT(X,Y) \
775 	if (!getdns_dict_get_int(reply, "/header/" #X, &n)) { \
776 		if (n) GLDNS_ ## Y ## _SET(header); \
777 		else   GLDNS_ ## Y ## _CLR(header); \
778 	}
779 
780 getdns_return_t
_getdns_reply_dict2wire(const getdns_dict * reply,gldns_buffer * buf,int reuse_header)781 _getdns_reply_dict2wire(
782     const getdns_dict *reply, gldns_buffer *buf, int reuse_header)
783 {
784 	uint8_t header_spc[GLDNS_HEADER_SIZE], *header;
785 	uint32_t n, qtype, qclass = GETDNS_RRCLASS_IN, rr_type;
786 	size_t pkt_start, i;
787 	getdns_list *section;
788 	getdns_dict *rr_dict;
789 	getdns_bindata *qname;
790 	int remove_dnssec;
791 
792 	pkt_start = gldns_buffer_position(buf);
793 	if (reuse_header) {
794 		if (gldns_buffer_remaining(buf) < GLDNS_HEADER_SIZE)
795 			return GETDNS_RETURN_NEED_MORE_SPACE;
796 		header = gldns_buffer_current(buf);
797 		gldns_buffer_skip(buf, GLDNS_HEADER_SIZE);
798 	} else
799 		(void) memset((header = header_spc), 0, GLDNS_HEADER_SIZE);
800 
801 	SET_HEADER_INT(id, ID);
802 	SET_HEADER_BIT(qr, QR);
803 	SET_HEADER_BIT(aa, AA);
804 	SET_HEADER_BIT(tc, TC);
805 	SET_HEADER_BIT(rd, RD);
806 	SET_HEADER_BIT(cd, CD);
807 	SET_HEADER_BIT(ra, RA);
808 	SET_HEADER_BIT(ad, AD);
809 	SET_HEADER_INT(opcode, OPCODE);
810 	SET_HEADER_INT(rcode, RCODE);
811 	SET_HEADER_BIT(z, Z);
812 
813 	if (!reuse_header)
814 		gldns_buffer_write(buf, header, GLDNS_HEADER_SIZE);
815 
816 	if (!getdns_dict_get_bindata(reply, "/question/qname", &qname) &&
817 	    !getdns_dict_get_int(reply, "/question/qtype", &qtype)) {
818 		(void)getdns_dict_get_int(reply, "/question/qclass", &qclass);
819 		gldns_buffer_write(buf, qname->data, qname->size);
820 		gldns_buffer_write_u16(buf, (uint16_t)qtype);
821 		gldns_buffer_write_u16(buf, (uint16_t)qclass);
822 		gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_QDCOUNT_OFF, 1);
823 		if (reuse_header) {
824 			gldns_buffer_write_u16_at(
825 			    buf, pkt_start+GLDNS_ANCOUNT_OFF, 0);
826 			gldns_buffer_write_u16_at(
827 			    buf, pkt_start+GLDNS_NSCOUNT_OFF, 0);
828 			gldns_buffer_write_u16_at(
829 			    buf, pkt_start+GLDNS_ARCOUNT_OFF, 0);
830 		}
831 	}
832 	remove_dnssec = !getdns_dict_get_int(reply, "/header/do", &n) && n == 0;
833 
834 	if (!getdns_dict_get_list(reply, "answer", &section)) {
835 		for ( n = 0, i = 0
836 		    ; !getdns_list_get_dict(section, i, &rr_dict); i++) {
837 
838 			if (remove_dnssec &&
839 			    !getdns_dict_get_int(rr_dict, "type", &rr_type) &&
840 			    rr_type == GETDNS_RRTYPE_RRSIG)
841 				continue;
842 			if (!_getdns_rr_dict2wire(rr_dict, buf))
843 				 n++;
844 		}
845 		gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ANCOUNT_OFF, n);
846 	}
847 	if (!getdns_dict_get_list(reply, "authority", &section)) {
848 		for ( n = 0, i = 0
849 		    ; !getdns_list_get_dict(section, i, &rr_dict); i++) {
850 
851 			if (remove_dnssec &&
852 			    !getdns_dict_get_int(rr_dict, "type", &rr_type) &&
853 			    (  rr_type == GETDNS_RRTYPE_RRSIG
854 			    || rr_type == GETDNS_RRTYPE_NSEC
855 			    || rr_type == GETDNS_RRTYPE_NSEC3
856 			    || rr_type == GETDNS_RRTYPE_DS
857 			    ))
858 				continue;
859 			if (!_getdns_rr_dict2wire(rr_dict, buf))
860 				 n++;
861 		}
862 		gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_NSCOUNT_OFF, n);
863 	}
864 	if (!getdns_dict_get_list(reply, "additional", &section)) {
865 		for ( n = 0, i = 0
866 		    ; !getdns_list_get_dict(section, i, &rr_dict); i++) {
867 
868 			if (remove_dnssec &&
869 			    !getdns_dict_get_int(rr_dict, "type", &rr_type) &&
870 			    rr_type == GETDNS_RRTYPE_RRSIG)
871 				continue;
872 			 if (!_getdns_rr_dict2wire(rr_dict, buf))
873 				 n++;
874 		}
875 		gldns_buffer_write_u16_at(buf, pkt_start+GLDNS_ARCOUNT_OFF, n);
876 	}
877 	return GETDNS_RETURN_GOOD;
878 }
879 
880 getdns_return_t
_getdns_msg_dict2wire_buf(const getdns_dict * msg_dict,gldns_buffer * gbuf)881 _getdns_msg_dict2wire_buf(const getdns_dict *msg_dict, gldns_buffer *gbuf)
882 {
883 	getdns_return_t r;
884 	getdns_list *replies;
885 	getdns_dict *reply;
886 	size_t i;
887 
888 	if ((r = getdns_dict_get_list(msg_dict, "replies_tree", &replies))) {
889 		if (r != GETDNS_RETURN_NO_SUCH_DICT_NAME)
890 			return r;
891 		return _getdns_reply_dict2wire(msg_dict, gbuf, 0);
892 	}
893 	for (i = 0; r == GETDNS_RETURN_GOOD; i++) {
894 		if (!(r = getdns_list_get_dict(replies, i, &reply)))
895 			r = _getdns_reply_dict2wire(reply, gbuf, 0);
896 	}
897 	return r == GETDNS_RETURN_NO_SUCH_LIST_ITEM ? GETDNS_RETURN_GOOD : r;
898 }
899 
900 getdns_return_t
getdns_msg_dict2wire(const getdns_dict * msg_dict,uint8_t ** wire,size_t * wire_sz)901 getdns_msg_dict2wire(
902     const getdns_dict *msg_dict, uint8_t **wire, size_t *wire_sz)
903 {
904 	uint8_t buf_spc[4096], *buf;
905 	size_t buf_len = sizeof(buf_spc);
906 	getdns_return_t r = getdns_msg_dict2wire_buf(
907 	    msg_dict, buf_spc, &buf_len);
908 
909 	if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
910 		return r;
911 
912 	if (!(buf = malloc(buf_len ? buf_len : 1)))
913 		return GETDNS_RETURN_MEMORY_ERROR;
914 
915 	if (!r)
916 		memcpy(buf, buf_spc, buf_len);
917 
918 	else if ((r = getdns_msg_dict2wire_buf(msg_dict, buf, &buf_len))) {
919 		free(buf);
920 		return r;
921 	}
922 	*wire = buf;
923 	*wire_sz = buf_len;
924 	return GETDNS_RETURN_GOOD;
925 }
926 
927 getdns_return_t
getdns_msg_dict2wire_buf(const getdns_dict * msg_dict,uint8_t * wire,size_t * wire_sz)928 getdns_msg_dict2wire_buf(
929     const getdns_dict *msg_dict, uint8_t *wire, size_t *wire_sz)
930 {
931 	int my_wire_sz;
932 	getdns_return_t r;
933 
934 	if (!wire_sz)
935 		return GETDNS_RETURN_INVALID_PARAMETER;
936 	else
937 		my_wire_sz = *wire_sz;
938 
939 	r = getdns_msg_dict2wire_scan(msg_dict, &wire, &my_wire_sz);
940 	if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
941 		*wire_sz -= my_wire_sz;
942 	return r;
943 }
944 
945 getdns_return_t
getdns_msg_dict2wire_scan(const getdns_dict * msg_dict,uint8_t ** wire,int * wire_sz)946 getdns_msg_dict2wire_scan(
947     const getdns_dict *msg_dict, uint8_t **wire, int *wire_sz)
948 {
949 	getdns_return_t r;
950 	gldns_buffer gbuf;
951 
952 	if (!msg_dict || !wire || !wire_sz || (!*wire && *wire_sz))
953 		return GETDNS_RETURN_INVALID_PARAMETER;
954 
955 	gldns_buffer_init_vfixed_frm_data(&gbuf, *wire, *wire_sz);
956 	if ((r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf)))
957 		return r;
958 
959 	if (gldns_buffer_position(&gbuf) == 0)
960 		return GETDNS_RETURN_GENERIC_ERROR;
961 
962 	*wire += gldns_buffer_position(&gbuf);
963 	*wire_sz -= gldns_buffer_position(&gbuf);
964 	if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
965 		return GETDNS_RETURN_NEED_MORE_SPACE;
966 	else
967 		return GETDNS_RETURN_GOOD;
968 }
969 
970 getdns_return_t
getdns_msg_dict2str(const getdns_dict * msg_dict,char ** str)971 getdns_msg_dict2str(
972     const getdns_dict *msg_dict, char **str)
973 {
974 	char buf_spc[4096], *buf;
975 	size_t buf_len = sizeof(buf_spc) - 1;
976 	getdns_return_t r = getdns_msg_dict2str_buf(
977 	    msg_dict, buf_spc, &buf_len);
978 
979 	if (r != GETDNS_RETURN_GOOD && r != GETDNS_RETURN_NEED_MORE_SPACE)
980 		return r;
981 
982 	buf_len += 1;
983 	if (!(buf = malloc(buf_len)))
984 		return GETDNS_RETURN_MEMORY_ERROR;
985 
986 	if (!r)
987 		memcpy(buf, buf_spc, buf_len);
988 
989 	else if ((r = getdns_msg_dict2str_buf(msg_dict, buf, &buf_len))) {
990 		free(buf);
991 		return r;
992 	}
993 	*str = buf;
994 	return GETDNS_RETURN_GOOD;
995 }
996 
997 getdns_return_t
getdns_msg_dict2str_buf(const getdns_dict * msg_dict,char * str,size_t * str_len)998 getdns_msg_dict2str_buf(
999     const getdns_dict *msg_dict, char *str, size_t *str_len)
1000 {
1001 	int my_str_len;
1002 	getdns_return_t r;
1003 
1004 	if (!str_len)
1005 		return GETDNS_RETURN_INVALID_PARAMETER;
1006 	else
1007 		my_str_len = *str_len;
1008 
1009 	r = getdns_msg_dict2str_scan(msg_dict, &str, &my_str_len);
1010 	if (r == GETDNS_RETURN_GOOD || r == GETDNS_RETURN_NEED_MORE_SPACE)
1011 		*str_len -= my_str_len;
1012 	return r;
1013 
1014 }
1015 
1016 getdns_return_t
getdns_msg_dict2str_scan(const getdns_dict * msg_dict,char ** str,int * str_len)1017 getdns_msg_dict2str_scan(
1018     const getdns_dict *msg_dict, char **str, int *str_len)
1019 {
1020 	getdns_return_t r;
1021 	gldns_buffer gbuf;
1022 	uint8_t buf_spc[4096], *buf = buf_spc, *scan_buf;
1023 	size_t sz, scan_sz;
1024 	int prev_str_len;
1025 	char *prev_str;
1026 	int sz_needed;
1027 
1028 	if (!msg_dict || !str || !*str || !str_len)
1029 		return GETDNS_RETURN_INVALID_PARAMETER;
1030 
1031 	gldns_buffer_init_vfixed_frm_data(&gbuf, buf, sizeof(buf_spc));
1032 	r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf);
1033 	if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
1034 		if (!(buf = GETDNS_XMALLOC(
1035 		    msg_dict->mf, uint8_t, (sz = gldns_buffer_position(&gbuf))))) {
1036 			return GETDNS_RETURN_MEMORY_ERROR;
1037 		}
1038 		gldns_buffer_init_frm_data(&gbuf, buf, sz);
1039 		r = _getdns_msg_dict2wire_buf(msg_dict, &gbuf);
1040 	}
1041 	if (r) {
1042 		if (buf != buf_spc)
1043 			GETDNS_FREE(msg_dict->mf, buf);
1044 		return r;
1045 	}
1046 	scan_buf = gldns_buffer_begin(&gbuf);
1047 	scan_sz  = gldns_buffer_position(&gbuf);
1048 	prev_str = *str;
1049 	prev_str_len = *str_len;
1050 	sz = (size_t)*str_len;
1051 	sz_needed = gldns_wire2str_pkt_scan(
1052 	    &scan_buf, &scan_sz, str, &sz);
1053 
1054 	if (sz_needed > prev_str_len) {
1055 		*str = prev_str + sz_needed;
1056 		*str_len = prev_str_len - sz_needed;
1057 		r = GETDNS_RETURN_NEED_MORE_SPACE;
1058 	} else  {
1059 		*str_len = sz;
1060 		**str = 0;
1061 	}
1062 	if (buf != buf_spc)
1063 		GETDNS_FREE(msg_dict->mf, buf);
1064 	return r;
1065 }
1066 
1067 static getdns_dict *
_getdns_ipaddr_dict_mf(struct mem_funcs * mf,const char * ipstr)1068 _getdns_ipaddr_dict_mf(struct mem_funcs *mf, const char *ipstr)
1069 {
1070 	getdns_dict *r = _getdns_dict_create_with_mf(mf);
1071 	char *s = strchr(ipstr, '%'), *scope_id_str = "";
1072 	char *p = strchr(ipstr, '@'), *portstr = "";
1073 	char *t = strchr(ipstr, '#'), *tls_portstr = "";
1074 	char *n = strchr(ipstr, '~'), *tls_namestr = "";
1075 	/* ^[alg:]name:key */
1076 	char *T = strchr(ipstr, '^'), *tsig_name_str = ""
1077 	                            , *tsig_secret_str = ""
1078 	                            , *tsig_algorithm_str = "";
1079 	char *br, *c;
1080 	int            tsig_secret_size;
1081 	uint8_t        tsig_secret_buf[256]; /* 4 times SHA512 */
1082 	getdns_bindata tsig_secret;
1083 	uint8_t buf[sizeof(struct in6_addr)];
1084 	getdns_bindata addr;
1085 
1086 	addr.data = buf;
1087 
1088 	if (!r) return NULL;
1089 
1090 	if (*ipstr == '[') {
1091 		char *br = strchr(ipstr, ']');
1092 		if (br) {
1093 			ipstr += 1;
1094 			*br = 0;
1095 			if ((c = strchr(br + 1, ':'))) {
1096 				p = c;
1097 			}
1098 		}
1099 	} else if ((br = strchr(ipstr, '.')) && (c = strchr(br + 1, ':'))
1100 	    && (T == NULL || c < T))
1101 		p = c;
1102 
1103 	else if ((*ipstr == '*') && (c = strchr(ipstr+1, ':')))
1104 		p = c;
1105 
1106 	if (s) {
1107 		*s = 0;
1108 		scope_id_str = s + 1;
1109 	}
1110 	if (p) {
1111 		*p = 0;
1112 		portstr = p + 1;
1113 	}
1114 	if (t) {
1115 		*t = 0;
1116 		tls_portstr = t + 1;
1117 	}
1118 	if (n) {
1119 		*n = 0;
1120 		tls_namestr = n + 1;
1121 	}
1122 	if (T) {
1123 		*T = 0;
1124 		tsig_name_str = T + 1;
1125 		if ((T = strchr(tsig_name_str, ':'))) {
1126 			*T = 0;
1127 			tsig_secret_str = T + 1;
1128 			if ((T = strchr(tsig_secret_str, ':'))) {
1129 				*T = 0;
1130 				tsig_algorithm_str  = tsig_name_str;
1131 				tsig_name_str = tsig_secret_str;
1132 				tsig_secret_str  = T + 1;
1133 			}
1134 		} else {
1135 			tsig_name_str = "";
1136 		}
1137 	}
1138 	if (*ipstr == '*') {
1139 		getdns_dict_util_set_string(r, "address_type", "IPv6");
1140 		addr.size = 16;
1141 		(void) memset(buf, 0, 16);
1142 	} else if (strchr(ipstr, ':')) {
1143 		getdns_dict_util_set_string(r, "address_type", "IPv6");
1144 		addr.size = 16;
1145 		if (inet_pton(AF_INET6, ipstr, buf) <= 0) {
1146 			getdns_dict_destroy(r);
1147 			return NULL;
1148 		}
1149 	} else {
1150 		getdns_dict_util_set_string(r, "address_type", "IPv4");
1151 		addr.size = 4;
1152 		if (inet_pton(AF_INET, ipstr, buf) <= 0) {
1153 			getdns_dict_destroy(r);
1154 			return NULL;
1155 		}
1156 	}
1157 	getdns_dict_set_bindata(r, "address_data", &addr);
1158 	if (*portstr)
1159 		getdns_dict_set_int(r, "port", (int32_t)atoi(portstr));
1160 	if (*tls_portstr)
1161 		getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr));
1162 	if (*tls_namestr) {
1163 		getdns_dict_util_set_string(r, "tls_auth_name", tls_namestr);
1164 	}
1165 	if (*scope_id_str)
1166 		getdns_dict_util_set_string(r, "scope_id", scope_id_str);
1167 	if (*tsig_name_str)
1168 		getdns_dict_util_set_string(r, "tsig_name", tsig_name_str);
1169 	if (*tsig_algorithm_str)
1170 		getdns_dict_util_set_string(r, "tsig_algorithm", tsig_algorithm_str);
1171 	if (*tsig_secret_str) {
1172 		tsig_secret_size = gldns_b64_pton(
1173 		    tsig_secret_str, tsig_secret_buf, sizeof(tsig_secret_buf));
1174 		if (tsig_secret_size > 0) {
1175 			tsig_secret.size = tsig_secret_size;
1176 			tsig_secret.data = tsig_secret_buf;
1177 			getdns_dict_set_bindata(r, "tsig_secret", &tsig_secret);
1178 		}
1179 	}
1180 	return r;
1181 }
1182 
_jsmn_get_ipdict(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_dict ** value)1183 static int _jsmn_get_ipdict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1184     getdns_dict **value)
1185 {
1186 	char value_str[3072];
1187 	int size = t->end - t->start;
1188 
1189 	if (size <= 0 || size >= (int)sizeof(value_str))
1190 		return 0;
1191 
1192 	(void) memcpy(value_str, js + t->start, size);
1193 	value_str[size] = '\0';
1194 
1195 	*value = _getdns_ipaddr_dict_mf(mf, value_str);
1196 	return *value != NULL;
1197 }
1198 
_jsmn_get_base64_data(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_bindata ** value)1199 static int _jsmn_get_base64_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1200     getdns_bindata **value)
1201 {
1202 	int e, i;
1203 	int size = t->end - t->start;
1204 	char value_str_buf[1025];
1205 	char *value_str;
1206 	size_t target_buf_size;
1207 
1208 	assert(size >= 4);
1209 
1210 	if (size % 4 != 0)
1211 		return 0;
1212 
1213 	e = t->end;
1214 	if (js[e - 1] == '=') e -= 1;
1215 	if (js[e - 1] == '=') e -= 1;
1216 
1217 	for (i = t->start; i < e; i++)
1218 		if (!((js[i] >= '0' && js[i] <= '9')
1219 		    ||(js[i] >= 'a' && js[i] <= 'z')
1220 		    ||(js[i] >= 'A' && js[i] <= 'Z')
1221 		    || js[i] == '+' || js[i] == '/'))
1222 			return 0;
1223 
1224 	target_buf_size = gldns_b64_pton_calculate_size(size);
1225 	if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
1226 		return 0;
1227 
1228 	else if (!((*value)->data = GETDNS_XMALLOC(
1229 	    *mf, uint8_t, target_buf_size))) {
1230 		GETDNS_FREE(*mf, *value);
1231 		return 0;
1232 	}
1233 	if ((size_t)size >= sizeof(value_str_buf))
1234 		value_str = GETDNS_XMALLOC(*mf, char, size + 1);
1235 	else	value_str = value_str_buf;
1236 
1237 	if (value_str) {
1238 		(void) memcpy(value_str, js + t->start, size);
1239 		value_str[size] = '\0';
1240 
1241 		e = gldns_b64_pton(value_str, (*value)->data, target_buf_size);
1242 
1243 		if (value_str != value_str_buf)
1244 			GETDNS_FREE(*mf, value_str);
1245 
1246 		if (e > 0) {
1247 			(*value)->size = e;
1248 			return 1;
1249 		}
1250 	}
1251 	GETDNS_FREE(*mf, (*value)->data);
1252 	GETDNS_FREE(*mf,  *value);
1253 	return 0;
1254 }
1255 
_jsmn_get_data(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_bindata ** value)1256 static int _jsmn_get_data(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1257     getdns_bindata **value)
1258 {
1259 	int i;
1260 	size_t j;
1261 	uint8_t h, l;
1262 
1263 	if ((t->end - t->start) < 4 || (t->end - t->start) % 2 == 1)
1264 		return 0;
1265 
1266 	if (js[t->start] != '0' || js[t->start + 1] != 'x')
1267 		return _jsmn_get_base64_data(mf, js, t, value);
1268 
1269 	for (i = t->start + 2; i < t->end; i++)
1270 		if (!((js[i] >= '0' && js[i] <= '9')
1271 		    ||(js[i] >= 'a' && js[i] <= 'f')
1272 		    ||(js[i] >= 'A' && js[i] <= 'F')))
1273 			return _jsmn_get_base64_data(mf, js, t, value);
1274 
1275 	if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
1276 		return 0;
1277 
1278 	else if (!((*value)->data = GETDNS_XMALLOC(
1279 	    *mf, uint8_t, (t->end - t->start) / 2 - 1))) {
1280 		GETDNS_FREE(*mf, *value);
1281 		return 0;
1282 	}
1283 	for (i = t->start + 2, j = 0; i < t->end; i++, j++) {
1284 		h = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
1285 		  : js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
1286 		                                 : js[i] + 10 - 'a';
1287 		h <<= 4;
1288 		i++;
1289 		l = js[i] >= '0' && js[i] <= '9' ? js[i] - '0'
1290 		  : js[i] >= 'A' && js[i] <= 'F' ? js[i] + 10 - 'A'
1291 		                                 : js[i] + 10 - 'a';
1292 		(*value)->data[j] = h | l;
1293 	}
1294 	(*value)->size = j;
1295 	return 1;
1296 }
1297 
_jsmn_get_dname(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_bindata ** value)1298 static int _jsmn_get_dname(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1299     getdns_bindata **value)
1300 {
1301 	char value_str[1025];
1302 	int size = t->end - t->start;
1303 	(void)mf; /* TODO: Fix to use  mf */
1304 
1305 	if (size <= 0 || size >= (int)sizeof(value_str) || js[t->end - 1] != '.')
1306 		return 0;
1307 
1308 	(void) memcpy(value_str, js + t->start, size);
1309 	value_str[size] = '\0';
1310 
1311 	return !getdns_convert_fqdn_to_dns_name(value_str, value);
1312 }
1313 
_jsmn_get_ipv4(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_bindata ** value)1314 static int _jsmn_get_ipv4(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1315     getdns_bindata **value)
1316 {
1317 	char value_str[16];
1318 	int size = t->end - t->start;
1319 	uint8_t buf[4];
1320 
1321 	if (size <= 0 || size >= (int)sizeof(value_str))
1322 		return 0;
1323 
1324 	(void) memcpy(value_str, js + t->start, size);
1325 	value_str[size] = '\0';
1326 
1327 	if (inet_pton(AF_INET, value_str, buf) <= 0)
1328 		; /* pass */
1329 
1330 	else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
1331 		; /* pass */
1332 
1333 	else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 4)))
1334 		GETDNS_FREE(*mf, *value);
1335 
1336 	else {
1337 		(*value)->size = 4;
1338 		(void) memcpy((*value)->data, buf, 4);
1339 		return 1;
1340 	}
1341 	return 0;
1342 }
1343 
_jsmn_get_ipv6(struct mem_funcs * mf,const char * js,jsmntok_t * t,getdns_bindata ** value)1344 static int _jsmn_get_ipv6(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1345     getdns_bindata **value)
1346 {
1347 	char value_str[40];
1348 	int size = t->end - t->start;
1349 	uint8_t buf[16];
1350 
1351 	if (size <= 0 || size >= (int)sizeof(value_str))
1352 		return 0;
1353 
1354 	(void) memcpy(value_str, js + t->start, size);
1355 	value_str[size] = '\0';
1356 
1357 	if (inet_pton(AF_INET6, value_str, buf) <= 0)
1358 		; /* pass */
1359 
1360 	else if (!(*value = GETDNS_MALLOC(*mf, getdns_bindata)))
1361 		; /* pass */
1362 
1363 	else if (!((*value)->data = GETDNS_XMALLOC(*mf, uint8_t, 16)))
1364 		GETDNS_FREE(*mf, *value);
1365 
1366 	else {
1367 		(*value)->size = 16;
1368 		(void) memcpy((*value)->data, buf, 16);
1369 		return 1;
1370 	}
1371 	return 0;
1372 }
1373 
_jsmn_get_int(const char * js,jsmntok_t * t,uint32_t * value)1374 static int _jsmn_get_int(const char *js, jsmntok_t *t, uint32_t *value)
1375 {
1376 	char value_str[11];
1377 	int size = t->end - t->start;
1378 	char *endptr;
1379 
1380 	if (size <= 0 || size >= (int)sizeof(value_str))
1381 		return 0;
1382 
1383 	(void) memcpy(value_str, js + t->start, size);
1384 	value_str[size] = '\0';
1385 
1386 	*value = (uint32_t)strtoul(value_str, &endptr, 10);
1387 	return *value_str != '\0' && *endptr == '\0';
1388 }
1389 
_jsmn_get_const(const char * js,jsmntok_t * t,uint32_t * value)1390 static int _jsmn_get_const(const char *js, jsmntok_t *t, uint32_t *value)
1391 {
1392 	char value_str[80];
1393 	int size = t->end - t->start;
1394 
1395 	if (size <= 0 || size >= (int)sizeof(value_str))
1396 		return 0;
1397 
1398 	(void) memcpy(value_str, js + t->start, size);
1399 	value_str[size] = '\0';
1400 
1401 	return _getdns_get_const_name_info(value_str, value);
1402 }
1403 
1404 static void
_getdns_destroy_item_data(struct mem_funcs * mf,getdns_item * item)1405 _getdns_destroy_item_data(struct mem_funcs *mf, getdns_item *item)
1406 {
1407 	switch (item->dtype) {
1408 	case t_dict:
1409 		getdns_dict_destroy(item->data.dict);
1410 		break;
1411 
1412 	case t_list:
1413 		getdns_list_destroy(item->data.list);
1414 		break;
1415 
1416 	case t_bindata:
1417 		GETDNS_FREE(*mf, item->data.bindata->data);
1418 		GETDNS_FREE(*mf, item->data.bindata);
1419 	default:
1420 		break;
1421 	}
1422 }
1423 static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1424     size_t count, getdns_item *item, getdns_return_t *r);
1425 
_jsmn_get_dict(struct mem_funcs * mf,const char * js,jsmntok_t * t,size_t count,getdns_dict * dict,getdns_return_t * r)1426 static int _jsmn_get_dict(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1427     size_t count, getdns_dict *dict, getdns_return_t *r)
1428 {
1429 	int i;
1430 	size_t j = 1;
1431 	char key_spc[1024], *key = NULL;
1432 	getdns_item child_item;
1433 
1434 	if (t->size <= 0)
1435 		*r = GETDNS_RETURN_GOOD;
1436 
1437 	else for (i = 0; i < t->size; i++) {
1438 		if (t[j].type != JSMN_STRING &&
1439 		    t[j].type != JSMN_PRIMITIVE) {
1440 
1441 			/* Key must be string or primitive */
1442 			*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1443 			break;
1444 		}
1445 		if (t[j].end <= t[j].start) {
1446 			/* Key must be at least 1 character */
1447 			*r = GETDNS_RETURN_GENERIC_ERROR; /* range error */
1448 			break;
1449 		}
1450 		if (t[j].end - t[j].start < (int)sizeof(key_spc))
1451 			key = key_spc;
1452 
1453 		else if (!(key = GETDNS_XMALLOC(
1454 		    *mf, char, t[j].end - t[j].start + 1))) {
1455 
1456 			*r = GETDNS_RETURN_MEMORY_ERROR;
1457 			break;
1458 		}
1459 		(void) memcpy(key, js + t[j].start, t[j].end - t[j].start);
1460 		key[t[j].end - t[j].start] = '\0';
1461 		j += 1;
1462 
1463 		j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
1464 		if (*r) break;
1465 
1466 		switch (child_item.dtype) {
1467 		case t_int:
1468 			*r = getdns_dict_set_int(dict, key,
1469 			    child_item.data.n);
1470 			break;
1471 		case t_bindata:
1472 			*r = getdns_dict_set_bindata(dict, key,
1473 			    child_item.data.bindata);
1474 			break;
1475 		case t_list:
1476 			*r = getdns_dict_set_list(dict, key,
1477 			    child_item.data.list);
1478 			break;
1479 		case t_dict:
1480 			*r = getdns_dict_set_dict(dict, key,
1481 			    child_item.data.dict);
1482 			break;
1483 		default:
1484 			*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1485 			break;
1486 
1487 		}
1488 		_getdns_destroy_item_data(mf, &child_item);
1489 		if (*r) break;
1490 		if (key && key != key_spc) {
1491 			GETDNS_FREE(*mf, key);
1492 			key = NULL;
1493 		}
1494 	}
1495 	if (key && key != key_spc)
1496 		GETDNS_FREE(*mf, key);
1497 
1498 	if (*r) {
1499 		getdns_dict_destroy(dict);
1500 		return 0;
1501 	}
1502 	return j;
1503 }
1504 
_jsmn_get_list(struct mem_funcs * mf,const char * js,jsmntok_t * t,size_t count,getdns_list * list,getdns_return_t * r)1505 static int _jsmn_get_list(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1506     size_t count, getdns_list *list, getdns_return_t *r)
1507 {
1508 	int i;
1509 	size_t j = 1, index = 0;
1510 	getdns_item child_item;
1511 
1512 	if (t->size <= 0)
1513 		*r = GETDNS_RETURN_GOOD;
1514 
1515 	else for (i = 0; i < t->size; i++) {
1516 		j += _jsmn_get_item(mf, js, t + j, count - j, &child_item, r);
1517 		if (*r) break;
1518 
1519 		switch (child_item.dtype) {
1520 		case t_int:
1521 			*r = getdns_list_set_int(list, index++,
1522 			    child_item.data.n);
1523 			break;
1524 		case t_bindata:
1525 			*r = getdns_list_set_bindata(list, index++,
1526 			    child_item.data.bindata);
1527 			break;
1528 		case t_list:
1529 			*r = getdns_list_set_list(list, index++,
1530 			    child_item.data.list);
1531 			break;
1532 		case t_dict:
1533 			*r = getdns_list_set_dict(list, index++,
1534 			    child_item.data.dict);
1535 			break;
1536 		default:
1537 			*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1538 			break;
1539 
1540 		}
1541 		_getdns_destroy_item_data(mf, &child_item);
1542 		if (*r) break;
1543 	}
1544 	if (*r) {
1545 		getdns_list_destroy(list);
1546 		return 0;
1547 	}
1548 	return j;
1549 }
1550 
_jsmn_get_item(struct mem_funcs * mf,const char * js,jsmntok_t * t,size_t count,getdns_item * item,getdns_return_t * r)1551 static int _jsmn_get_item(struct mem_funcs *mf, const char *js, jsmntok_t *t,
1552     size_t count, getdns_item *item, getdns_return_t *r)
1553 {
1554 	assert(item);
1555 
1556 	switch (t->type) {
1557 	case JSMN_STRING:
1558 		if (t->end < t->start)
1559 			*r = GETDNS_RETURN_GENERIC_ERROR;
1560 
1561 		else if (!(item->data.bindata =
1562 		    GETDNS_MALLOC(*mf, getdns_bindata)))
1563 			*r = GETDNS_RETURN_MEMORY_ERROR;
1564 
1565 		else if (!(item->data.bindata->data = GETDNS_XMALLOC(
1566 		    *mf, uint8_t, t->end - t->start + 1))) {
1567 			GETDNS_FREE(*mf, item->data.bindata);
1568 			*r = GETDNS_RETURN_MEMORY_ERROR;
1569 		} else {
1570 			item->dtype = t_bindata;
1571 			if (t->end - t->start) {
1572 				(void) memcpy(item->data.bindata->data,
1573 				    js + t->start, t->end - t->start);
1574 			}
1575 			item->data.bindata->data[t->end - t->start] = '\0';
1576 			item->data.bindata->size = t->end - t->start;
1577 			*r = GETDNS_RETURN_GOOD;
1578 			return 1;
1579 		}
1580 		break;
1581 
1582 	case JSMN_PRIMITIVE:
1583 		/* There is no such thing as an empty primitive */
1584 		if (t->end <= t->start) {
1585 			*r = GETDNS_RETURN_GENERIC_ERROR;
1586 			break;
1587 
1588 		} else if (_jsmn_get_int(js, t, &item->data.n)
1589 		    || _jsmn_get_const(js, t, &item->data.n)) {
1590 
1591 			item->dtype = t_int;
1592 		}
1593 		else if (_jsmn_get_data(mf, js, t, &item->data.bindata)
1594 		    || _jsmn_get_dname(mf, js, t,  &item->data.bindata)
1595 		    || _jsmn_get_ipv4(mf, js, t,  &item->data.bindata)
1596 		    || _jsmn_get_ipv6(mf, js, t,  &item->data.bindata))
1597 
1598 			item->dtype = t_bindata;
1599 
1600 		else if (_jsmn_get_ipdict(mf, js, t, &item->data.dict))
1601 
1602 			item->dtype = t_dict;
1603 		else {
1604 			*r = GETDNS_RETURN_GENERIC_ERROR;
1605 			break;
1606 		}
1607 		*r = GETDNS_RETURN_GOOD;
1608 		return 1;
1609 
1610 	case JSMN_OBJECT:
1611 		if (!(item->data.dict = _getdns_dict_create_with_mf(mf))) {
1612 			*r = GETDNS_RETURN_MEMORY_ERROR;
1613 			break;
1614 		}
1615 		item->dtype = t_dict;
1616 		return _jsmn_get_dict(mf, js, t, count, item->data.dict, r);
1617 
1618 	case JSMN_ARRAY:
1619 		if (!(item->data.list = _getdns_list_create_with_mf(mf))) {
1620 			*r = GETDNS_RETURN_MEMORY_ERROR;
1621 			break;
1622 		}
1623 		item->dtype = t_list;
1624 		return _jsmn_get_list(mf, js, t, count, item->data.list, r);
1625 
1626 	default:
1627 		*r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1628 		break;
1629 	}
1630 	return 0;
1631 }
1632 
1633 static getdns_return_t
_getdns_str2item_mf(struct mem_funcs * mf,const char * str,getdns_item * item)1634 _getdns_str2item_mf(struct mem_funcs *mf, const char *str, getdns_item *item)
1635 {
1636 	jsmn_parser p;
1637 	jsmntok_t *tok = NULL, *new_tok;
1638 	size_t tokcount = 100;
1639 	int r;
1640 	getdns_return_t gr;
1641 
1642 	jsmn_init(&p);
1643 	tok = GETDNS_XMALLOC(*mf, jsmntok_t, tokcount);
1644 	do {
1645 		r = jsmn_parse(&p, str, strlen(str), tok, tokcount);
1646 		if (r == JSMN_ERROR_NOMEM) {
1647 			tokcount *= 2;
1648 			if (!(new_tok = GETDNS_XREALLOC(
1649 			    *mf, tok, jsmntok_t, tokcount))) {
1650 				GETDNS_FREE(*mf, tok);
1651 				return GETDNS_RETURN_MEMORY_ERROR;
1652 			}
1653 			tok  = new_tok;
1654 		}
1655 	} while (r == JSMN_ERROR_NOMEM);
1656 	if (r < 0)
1657 		gr = GETDNS_RETURN_GENERIC_ERROR;
1658 	else
1659 		(void) _jsmn_get_item(mf, str, tok, p.toknext, item, &gr);
1660 	GETDNS_FREE(*mf, tok);
1661 	return gr;
1662 }
1663 
1664 getdns_return_t
getdns_str2dict(const char * str,getdns_dict ** dict)1665 getdns_str2dict(const char *str, getdns_dict **dict)
1666 {
1667 	getdns_item item;
1668 	getdns_return_t r;
1669 
1670 	if (!str || !dict)
1671 		return GETDNS_RETURN_INVALID_PARAMETER;
1672 
1673 	while (*str && isspace((unsigned char)*str))
1674 		str++;
1675 
1676 	if (*str != '{') {
1677 		char value_buf[3072], *value_str = value_buf;
1678 
1679 		if (strlen(str) > sizeof(value_str) - 1)
1680 			value_str = strdup(str);
1681 		else
1682 			(void)strncpy(value_buf, str, sizeof(value_buf));
1683 
1684 		getdns_dict *dict_r = _getdns_ipaddr_dict_mf(
1685 		    &_getdns_plain_mem_funcs, value_str);
1686 
1687 		if (value_str != value_buf)
1688 			free(value_str);
1689 
1690 		if (dict_r) {
1691 			*dict = dict_r;
1692 			return GETDNS_RETURN_GOOD;
1693 		}
1694 	}
1695 	if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
1696 		return r;
1697 
1698 	else if (item.dtype != t_dict) {
1699 		uint8_t buf[16];
1700 		getdns_dict *dict_r;
1701 
1702 		if (item.dtype != t_bindata)
1703 			r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1704 
1705 		else if (item.data.bindata->size == 4 &&
1706 		    inet_pton(AF_INET, str, buf) == 1) {
1707 
1708 			if (!(dict_r = getdns_dict_create()))
1709 				r = GETDNS_RETURN_MEMORY_ERROR;
1710 
1711 			else if ((r = getdns_dict_util_set_string(
1712 			    dict_r, "address_type", "IPv4")))
1713 				getdns_dict_destroy(dict_r);
1714 
1715 			else if ((r = getdns_dict_set_bindata(
1716 			    dict_r, "address_data", item.data.bindata)))
1717 				getdns_dict_destroy(dict_r);
1718 			else
1719 				*dict = dict_r;
1720 
1721 		} else if (item.data.bindata->size == 16 &&
1722 		    inet_pton(AF_INET6, str, buf) == 1) {
1723 
1724 			if (!(dict_r = getdns_dict_create()))
1725 				r = GETDNS_RETURN_MEMORY_ERROR;
1726 
1727 			else if ((r = getdns_dict_util_set_string(
1728 			    dict_r, "address_type", "IPv6")))
1729 				getdns_dict_destroy(dict_r);
1730 
1731 			else if ((r = getdns_dict_set_bindata(
1732 			    dict_r, "address_data", item.data.bindata)))
1733 				getdns_dict_destroy(dict_r);
1734 			else
1735 				*dict = dict_r;
1736 		} else
1737 			r = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1738 
1739 		_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
1740 		return r;
1741 	}
1742 	*dict = item.data.dict;
1743 	return GETDNS_RETURN_GOOD;
1744 }
1745 
1746 getdns_return_t
getdns_str2list(const char * str,getdns_list ** list)1747 getdns_str2list(const char *str, getdns_list **list)
1748 {
1749 	getdns_item item;
1750 	getdns_return_t r;
1751 
1752 	if (!str || !list)
1753 		return GETDNS_RETURN_INVALID_PARAMETER;
1754 
1755 	if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
1756 		return r;
1757 
1758 	else if (item.dtype != t_list) {
1759 		_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
1760 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1761 	}
1762 	*list = item.data.list;
1763 	return GETDNS_RETURN_GOOD;
1764 }
1765 
1766 getdns_return_t
getdns_str2bindata(const char * str,getdns_bindata ** bindata)1767 getdns_str2bindata(const char *str, getdns_bindata **bindata)
1768 {
1769 	getdns_item item;
1770 	getdns_return_t r;
1771 
1772 	if (!str || !bindata)
1773 		return GETDNS_RETURN_INVALID_PARAMETER;
1774 
1775 	if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
1776 		return r;
1777 
1778 	else if (item.dtype != t_bindata) {
1779 		_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
1780 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1781 	}
1782 	*bindata = item.data.bindata;
1783 	return GETDNS_RETURN_GOOD;
1784 }
1785 
1786 getdns_return_t
getdns_str2int(const char * str,uint32_t * value)1787 getdns_str2int(const char *str, uint32_t *value)
1788 {
1789 	getdns_item item;
1790 	getdns_return_t r;
1791 
1792 	if (!str || !value)
1793 		return GETDNS_RETURN_INVALID_PARAMETER;
1794 
1795 	if ((r = _getdns_str2item_mf(&_getdns_plain_mem_funcs, str, &item)))
1796 		return r;
1797 
1798 	else if (item.dtype != t_int) {
1799 		_getdns_destroy_item_data(&_getdns_plain_mem_funcs, &item);
1800 		return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
1801 	}
1802 	*value = item.data.n;
1803 	return GETDNS_RETURN_GOOD;
1804 }
1805 
1806 #ifdef USE_YAML_CONFIG
1807 getdns_return_t
getdns_yaml2dict(const char * str,getdns_dict ** dict)1808 getdns_yaml2dict(const char *str, getdns_dict **dict)
1809 {
1810 	char *jsonstr;
1811 
1812 	if (!str || !dict)
1813 		return GETDNS_RETURN_INVALID_PARAMETER;
1814 
1815 	jsonstr = yaml_string_to_json_string(str);
1816 	if (jsonstr) {
1817 		getdns_return_t res = getdns_str2dict(jsonstr, dict);
1818 		free(jsonstr);
1819 		return res;
1820 	} else {
1821 		return GETDNS_RETURN_GENERIC_ERROR;
1822 	}
1823 }
1824 #endif /* USE_YAML_CONFIG */
1825 
1826 /* WT: I am not certain about the value of yaml2list...
1827  *     I don't see how yaml2bindata and yaml2int  would be different from
1828  *     the str2bindata and str2int ones.
1829  */
1830 #if 0
1831 
1832 getdns_return_t
1833 getdns_yaml2list(const char *str, getdns_list **list)
1834 {
1835 #ifdef USE_YAML_CONFIG
1836 	char *jsonstr;
1837 
1838 	if (!str || !list)
1839 		return GETDNS_RETURN_INVALID_PARAMETER;
1840 
1841 	jsonstr = yaml_string_to_json_string(str);
1842 	if (jsonstr) {
1843 		getdns_return_t res = getdns_str2list(jsonstr, list);
1844 		free(jsonstr);
1845 		return res;
1846 	} else {
1847 		return GETDNS_RETURN_GENERIC_ERROR;
1848 	}
1849 #else /* USE_YAML_CONFIG */
1850 	(void) str;
1851 	(void) list;
1852 	return GETDNS_RETURN_NOT_IMPLEMENTED;
1853 #endif /* USE_YAML_CONFIG */
1854 }
1855 
1856 getdns_return_t
1857 getdns_yaml2bindata(const char *str, getdns_bindata **bindata)
1858 {
1859 #ifdef USE_YAML_CONFIG
1860 	char *jsonstr;
1861 
1862 	if (!str || !bindata)
1863 		return GETDNS_RETURN_INVALID_PARAMETER;
1864 
1865 	jsonstr = yaml_string_to_json_string(str);
1866 	if (jsonstr) {
1867 		getdns_return_t res = getdns_str2bindata(jsonstr, bindata);
1868 		free(jsonstr);
1869 		return res;
1870 	} else {
1871 		return GETDNS_RETURN_GENERIC_ERROR;
1872 	}
1873 #else /* USE_YAML_CONFIG */
1874 	(void) str;
1875 	(void) bindata;
1876 	return GETDNS_RETURN_NOT_IMPLEMENTED;
1877 #endif /* USE_YAML_CONFIG */
1878 }
1879 
1880 getdns_return_t
1881 getdns_yaml2int(const char *str, uint32_t *value)
1882 {
1883 #ifdef USE_YAML_CONFIG
1884 	char *jsonstr;
1885 
1886 	if (!str || !value)
1887 		return GETDNS_RETURN_INVALID_PARAMETER;
1888 
1889 	jsonstr = yaml_string_to_json_string(str);
1890 	if (jsonstr) {
1891 		getdns_return_t res = getdns_str2int(jsonstr, value);
1892 		free(jsonstr);
1893 		return res;
1894 	} else {
1895 		return GETDNS_RETURN_GENERIC_ERROR;
1896 	}
1897 #else /* USE_YAML_CONFIG */
1898 	(void) str;
1899 	(void) value;
1900 	return GETDNS_RETURN_NOT_IMPLEMENTED;
1901 #endif /* USE_YAML_CONFIG */
1902 }
1903 #endif
1904