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", §ion)) {
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", §ion)) {
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", §ion)) {
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