aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/plugin_gnsrecord_dns.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
commit9ef4abad615bea12d13be542b8ae5fbeb2dfee32 (patch)
tree8875a687e004d331c9ea6a1d511a328c72b88113 /src/gnsrecord/plugin_gnsrecord_dns.c
parente95236b3ed78cd597c15f34b89385295702b627f (diff)
downloadgnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.tar.gz
gnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.zip
NEWS: Refactoring components under src/ into lib/, plugin/, cli/ and service/
This also includes a necessary API refactoring of crypto from IDENTITY to UTIL.
Diffstat (limited to 'src/gnsrecord/plugin_gnsrecord_dns.c')
-rw-r--r--src/gnsrecord/plugin_gnsrecord_dns.c818
1 files changed, 0 insertions, 818 deletions
diff --git a/src/gnsrecord/plugin_gnsrecord_dns.c b/src/gnsrecord/plugin_gnsrecord_dns.c
deleted file mode 100644
index 5844d9eda..000000000
--- a/src/gnsrecord/plugin_gnsrecord_dns.c
+++ /dev/null
@@ -1,818 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2013, 2014 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file gnsrecord/plugin_gnsrecord_dns.c
23 * @brief gnsrecord plugin to provide the API for basic DNS records
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_gnsrecord_plugin.h"
29
30
31/**
32 * Convert the 'value' of a record to a string.
33 *
34 * @param cls closure, unused
35 * @param type type of the record
36 * @param data value in binary encoding
37 * @param data_size number of bytes in @a data
38 * @return NULL on error, otherwise human-readable representation of the value
39 */
40static char *
41dns_value_to_string (void *cls,
42 uint32_t type,
43 const void *data,
44 size_t data_size)
45{
46 char *result;
47 char tmp[INET6_ADDRSTRLEN];
48
49 switch (type)
50 {
51 case GNUNET_DNSPARSER_TYPE_A:
52 if (data_size != sizeof(struct in_addr))
53 return NULL;
54 if (NULL == inet_ntop (AF_INET, data, tmp, sizeof(tmp)))
55 return NULL;
56 return GNUNET_strdup (tmp);
57
58 case GNUNET_DNSPARSER_TYPE_NS: {
59 char *ns;
60 size_t off;
61
62 off = 0;
63 ns = GNUNET_DNSPARSER_parse_name (data, data_size, &off);
64 if ((NULL == ns) || (off != data_size))
65 {
66 GNUNET_break_op (0);
67 GNUNET_free (ns);
68 return NULL;
69 }
70 return ns;
71 }
72
73 case GNUNET_DNSPARSER_TYPE_CNAME: {
74 char *cname;
75 size_t off;
76
77 off = 0;
78 cname = GNUNET_DNSPARSER_parse_name (data, data_size, &off);
79 if ((NULL == cname) || (off != data_size))
80 {
81 GNUNET_break_op (0);
82 GNUNET_free (cname);
83 return NULL;
84 }
85 return cname;
86 }
87
88 case GNUNET_DNSPARSER_TYPE_SOA: {
89 struct GNUNET_DNSPARSER_SoaRecord *soa;
90 size_t off;
91
92 off = 0;
93 soa = GNUNET_DNSPARSER_parse_soa (data, data_size, &off);
94 if ((NULL == soa) || (off != data_size))
95 {
96 GNUNET_break_op (0);
97 if (NULL != soa)
98 GNUNET_DNSPARSER_free_soa (soa);
99 return NULL;
100 }
101 GNUNET_asprintf (&result,
102 "%s %s ( %u %u %u %u %u )",
103 soa->rname,
104 soa->mname,
105 soa->serial,
106 soa->refresh,
107 soa->retry,
108 soa->expire,
109 soa->minimum_ttl);
110 GNUNET_DNSPARSER_free_soa (soa);
111 return result;
112 }
113
114 case GNUNET_DNSPARSER_TYPE_PTR: {
115 char *ptr;
116 size_t off;
117
118 off = 0;
119 ptr = GNUNET_DNSPARSER_parse_name (data, data_size, &off);
120 if ((NULL == ptr) || (off != data_size))
121 {
122 GNUNET_break_op (0);
123 GNUNET_free (ptr);
124 return NULL;
125 }
126 return ptr;
127 }
128
129 case GNUNET_DNSPARSER_TYPE_CERT: {
130 struct GNUNET_DNSPARSER_CertRecord *cert;
131 size_t off;
132 char *base64;
133 int len;
134
135 off = 0;
136 cert = GNUNET_DNSPARSER_parse_cert (data, data_size, &off);
137 if ((NULL == cert) || (off != data_size))
138 {
139 GNUNET_break_op (0);
140 GNUNET_DNSPARSER_free_cert (cert);
141 return NULL;
142 }
143 len = GNUNET_STRINGS_base64_encode (cert->certificate_data,
144 cert->certificate_size,
145 &base64);
146 GNUNET_asprintf (&result,
147 "%u %u %u %.*s",
148 cert->cert_type,
149 cert->cert_tag,
150 cert->algorithm,
151 len,
152 base64);
153 GNUNET_free (base64);
154 GNUNET_DNSPARSER_free_cert (cert);
155 return result;
156 }
157
158 case GNUNET_DNSPARSER_TYPE_MX: {
159 struct GNUNET_DNSPARSER_MxRecord *mx;
160 size_t off;
161
162 off = 0;
163 mx = GNUNET_DNSPARSER_parse_mx (data, data_size, &off);
164 if ((NULL == mx) || (off != data_size))
165 {
166 GNUNET_break_op (0);
167 GNUNET_DNSPARSER_free_mx (mx);
168 return NULL;
169 }
170 GNUNET_asprintf (&result,
171 "%u %s",
172 (unsigned int) mx->preference,
173 mx->mxhost);
174 GNUNET_DNSPARSER_free_mx (mx);
175 return result;
176 }
177
178 case GNUNET_DNSPARSER_TYPE_TXT:
179 return GNUNET_strndup (data, data_size);
180
181 case GNUNET_DNSPARSER_TYPE_AAAA:
182 if (data_size != sizeof(struct in6_addr))
183 return NULL;
184 if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof(tmp)))
185 return NULL;
186 return GNUNET_strdup (tmp);
187
188 case GNUNET_DNSPARSER_TYPE_SRV: {
189 struct GNUNET_DNSPARSER_SrvRecord *srv;
190 size_t off;
191
192 off = 0;
193 srv = GNUNET_DNSPARSER_parse_srv (data, data_size, &off);
194 if ((NULL == srv) || (off != data_size))
195 {
196 GNUNET_break_op (0);
197 if (NULL != srv)
198 GNUNET_DNSPARSER_free_srv (srv);
199 return NULL;
200 }
201 GNUNET_asprintf (&result,
202 "%d %d %d %s",
203 srv->priority,
204 srv->weight,
205 srv->port,
206 srv->target);
207 GNUNET_DNSPARSER_free_srv (srv);
208 return result;
209 }
210
211 case GNUNET_DNSPARSER_TYPE_TLSA: {
212 const struct GNUNET_TUN_DnsTlsaRecord *tlsa;
213 char *tlsa_str;
214 char *hex;
215
216 if (data_size < sizeof(struct GNUNET_TUN_DnsTlsaRecord))
217 return NULL; /* malformed */
218 tlsa = data;
219 hex =
220 GNUNET_DNSPARSER_bin_to_hex (&tlsa[1],
221 data_size
222 - sizeof(struct GNUNET_TUN_DnsTlsaRecord));
223 if (0 == GNUNET_asprintf (&tlsa_str,
224 "%u %u %u %s",
225 (unsigned int) tlsa->usage,
226 (unsigned int) tlsa->selector,
227 (unsigned int) tlsa->matching_type,
228 hex))
229 {
230 GNUNET_free (hex);
231 GNUNET_free (tlsa_str);
232 return NULL;
233 }
234 GNUNET_free (hex);
235 return tlsa_str;
236 }
237
238 case GNUNET_DNSPARSER_TYPE_CAA: { // RFC6844
239 const struct GNUNET_DNSPARSER_CaaRecord *caa;
240 char tag[15]; // between 1 and 15 bytes
241 char value[data_size];
242 char *caa_str;
243 if (data_size < sizeof(struct GNUNET_DNSPARSER_CaaRecord))
244 return NULL; /* malformed */
245 caa = data;
246 if ((1 > caa->tag_len) || (15 < caa->tag_len))
247 return NULL; /* malformed */
248 memset (tag, 0, sizeof(tag));
249 memset (value, 0, data_size);
250 memcpy (tag, &caa[1], caa->tag_len);
251 memcpy (value,
252 (char *) &caa[1] + caa->tag_len,
253 data_size - caa->tag_len - 2);
254 if (0 == GNUNET_asprintf (&caa_str,
255 "%u %s %s",
256 (unsigned int) caa->flags,
257 tag,
258 value))
259 {
260 GNUNET_free (caa_str);
261 return NULL;
262 }
263 return caa_str;
264 }
265
266 default:
267 return NULL;
268 }
269}
270
271
272/**
273 * Convert RFC 4394 Mnemonics to the corresponding integer values.
274 *
275 * @param mnemonic string to look up
276 * @return the value, 0 if not found
277 */
278static unsigned int
279rfc4398_mnemonic_to_value (const char *mnemonic)
280{
281 static struct
282 {
283 const char *mnemonic;
284 unsigned int val;
285 } table[] = { { "PKIX", 1 },
286 { "SPKI", 2 },
287 { "PGP", 3 },
288 { "IPKIX", 4 },
289 { "ISPKI", 5 },
290 { "IPGP", 6 },
291 { "ACPKIX", 7 },
292 { "IACPKIX", 8 },
293 { "URI", 253 },
294 { "OID", 254 },
295 { NULL, 0 } };
296 unsigned int i;
297
298 for (i = 0; NULL != table[i].mnemonic; i++)
299 if (0 == strcasecmp (mnemonic, table[i].mnemonic))
300 return table[i].val;
301 return 0;
302}
303
304
305/**
306 * Convert RFC 4034 algorithm types to the corresponding integer values.
307 *
308 * @param mnemonic string to look up
309 * @return the value, 0 if not found
310 */
311static unsigned int
312rfc4034_mnemonic_to_value (const char *mnemonic)
313{
314 static struct
315 {
316 const char *mnemonic;
317 unsigned int val;
318 } table[] = { { "RSAMD5", 1 },
319 { "DH", 2 },
320 { "DSA", 3 },
321 { "ECC", 4 },
322 { "RSASHA1", 5 },
323 { "INDIRECT", 252 },
324 { "PRIVATEDNS", 253 },
325 { "PRIVATEOID", 254 },
326 { NULL, 0 } };
327 unsigned int i;
328
329 for (i = 0; NULL != table[i].mnemonic; i++)
330 if (0 == strcasecmp (mnemonic, table[i].mnemonic))
331 return table[i].val;
332 return 0;
333}
334
335
336/**
337 * Convert human-readable version of a 'value' of a record to the binary
338 * representation.
339 *
340 * @param cls closure, unused
341 * @param type type of the record
342 * @param s human-readable string
343 * @param data set to value in binary encoding (will be allocated)
344 * @param data_size set to number of bytes in @a data
345 * @return #GNUNET_OK on success
346 */
347static int
348dns_string_to_value (void *cls,
349 uint32_t type,
350 const char *s,
351 void **data,
352 size_t *data_size)
353{
354 struct in_addr value_a;
355 struct in6_addr value_aaaa;
356 struct GNUNET_TUN_DnsTlsaRecord *tlsa;
357
358 if (NULL == s)
359 return GNUNET_SYSERR;
360 switch (type)
361 {
362 case GNUNET_DNSPARSER_TYPE_A:
363 if (1 != inet_pton (AF_INET, s, &value_a))
364 {
365 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
366 _ ("Unable to parse IPv4 address `%s'\n"),
367 s);
368 return GNUNET_SYSERR;
369 }
370 *data = GNUNET_new (struct in_addr);
371 GNUNET_memcpy (*data, &value_a, sizeof(value_a));
372 *data_size = sizeof(value_a);
373 return GNUNET_OK;
374
375 case GNUNET_DNSPARSER_TYPE_NS: {
376 char nsbuf[256];
377 size_t off;
378
379 off = 0;
380 if (GNUNET_OK !=
381 GNUNET_DNSPARSER_builder_add_name (nsbuf, sizeof(nsbuf), &off, s))
382 {
383 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
384 _ ("Failed to serialize NS record with value `%s'\n"),
385 s);
386 return GNUNET_SYSERR;
387 }
388 *data_size = off;
389 *data = GNUNET_malloc (off);
390 GNUNET_memcpy (*data, nsbuf, off);
391 return GNUNET_OK;
392 }
393
394 case GNUNET_DNSPARSER_TYPE_CNAME: {
395 char cnamebuf[256];
396 size_t off;
397
398 off = 0;
399 if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_name (cnamebuf,
400 sizeof(cnamebuf),
401 &off,
402 s))
403 {
404 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
405 _ ("Failed to serialize CNAME record with value `%s'\n"),
406 s);
407 return GNUNET_SYSERR;
408 }
409 *data_size = off;
410 *data = GNUNET_malloc (off);
411 GNUNET_memcpy (*data, cnamebuf, off);
412 return GNUNET_OK;
413 }
414
415 case GNUNET_DNSPARSER_TYPE_CERT: {
416 char *sdup;
417 const char *typep;
418 const char *keyp;
419 const char *algp;
420 const char *certp;
421 unsigned int type;
422 unsigned int key;
423 unsigned int alg;
424 size_t cert_size;
425 char *cert_data;
426 struct GNUNET_DNSPARSER_CertRecord cert;
427
428 sdup = GNUNET_strdup (s);
429 typep = strtok (sdup, " ");
430 if ((NULL == typep) ||
431 ((0 == (type = rfc4398_mnemonic_to_value (typep))) &&
432 ((1 != sscanf (typep, "%u", &type)) || (type > UINT16_MAX))))
433 {
434 GNUNET_free (sdup);
435 return GNUNET_SYSERR;
436 }
437 keyp = strtok (NULL, " ");
438 if ((NULL == keyp) || (1 != sscanf (keyp, "%u", &key)) ||
439 (key > UINT16_MAX))
440 {
441 GNUNET_free (sdup);
442 return GNUNET_SYSERR;
443 }
444 alg = 0;
445 algp = strtok (NULL, " ");
446 if ((NULL == algp) ||
447 ((0 == (type = rfc4034_mnemonic_to_value (typep))) &&
448 ((1 != sscanf (algp, "%u", &alg)) || (alg > UINT8_MAX))))
449 {
450 GNUNET_free (sdup);
451 return GNUNET_SYSERR;
452 }
453 certp = strtok (NULL, " ");
454 if ((NULL == certp) || (0 == strlen (certp)))
455 {
456 GNUNET_free (sdup);
457 return GNUNET_SYSERR;
458 }
459 cert_size = GNUNET_STRINGS_base64_decode (certp,
460 strlen (certp),
461 (void **) &cert_data);
462 GNUNET_free (sdup);
463 cert.cert_type = type;
464 cert.cert_tag = key;
465 cert.algorithm = alg;
466 cert.certificate_size = cert_size;
467 cert.certificate_data = cert_data;
468 {
469 char certbuf[cert_size + sizeof(struct GNUNET_TUN_DnsCertRecord)];
470 size_t off;
471
472 off = 0;
473 if (GNUNET_OK != GNUNET_DNSPARSER_builder_add_cert (certbuf,
474 sizeof(certbuf),
475 &off,
476 &cert))
477 {
478 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
479 _ ("Failed to serialize CERT record with %u bytes\n"),
480 (unsigned int) cert_size);
481 GNUNET_free (cert_data);
482 return GNUNET_SYSERR;
483 }
484 *data_size = off;
485 *data = GNUNET_malloc (off);
486 GNUNET_memcpy (*data, certbuf, off);
487 }
488 GNUNET_free (cert_data);
489 return GNUNET_OK;
490 }
491
492 case GNUNET_DNSPARSER_TYPE_SOA: {
493 struct GNUNET_DNSPARSER_SoaRecord soa;
494 char soabuf[540];
495 char soa_rname[253 + 1];
496 char soa_mname[253 + 1];
497 unsigned int soa_serial;
498 unsigned int soa_refresh;
499 unsigned int soa_retry;
500 unsigned int soa_expire;
501 unsigned int soa_min;
502 size_t off;
503
504 if (7 != sscanf (s,
505 "%253s %253s ( %u %u %u %u %u )",
506 soa_rname,
507 soa_mname,
508 &soa_serial,
509 &soa_refresh,
510 &soa_retry,
511 &soa_expire,
512 &soa_min))
513 {
514 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
515 _ ("Unable to parse SOA record `%s'\n"),
516 s);
517 return GNUNET_SYSERR;
518 }
519 soa.mname = soa_mname;
520 soa.rname = soa_rname;
521 soa.serial = (uint32_t) soa_serial;
522 soa.refresh = (uint32_t) soa_refresh;
523 soa.retry = (uint32_t) soa_retry;
524 soa.expire = (uint32_t) soa_expire;
525 soa.minimum_ttl = (uint32_t) soa_min;
526 off = 0;
527 if (GNUNET_OK !=
528 GNUNET_DNSPARSER_builder_add_soa (soabuf, sizeof(soabuf), &off, &soa))
529 {
530 GNUNET_log (
531 GNUNET_ERROR_TYPE_ERROR,
532 _ ("Failed to serialize SOA record with mname `%s' and rname `%s'\n"),
533 soa_mname,
534 soa_rname);
535 return GNUNET_SYSERR;
536 }
537 *data_size = off;
538 *data = GNUNET_malloc (off);
539 GNUNET_memcpy (*data, soabuf, off);
540 return GNUNET_OK;
541 }
542
543 case GNUNET_DNSPARSER_TYPE_PTR: {
544 char ptrbuf[256];
545 size_t off;
546
547 off = 0;
548 if (GNUNET_OK !=
549 GNUNET_DNSPARSER_builder_add_name (ptrbuf, sizeof(ptrbuf), &off, s))
550 {
551 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
552 _ ("Failed to serialize PTR record with value `%s'\n"),
553 s);
554 return GNUNET_SYSERR;
555 }
556 *data_size = off;
557 *data = GNUNET_malloc (off);
558 GNUNET_memcpy (*data, ptrbuf, off);
559 return GNUNET_OK;
560 }
561
562 case GNUNET_DNSPARSER_TYPE_MX: {
563 struct GNUNET_DNSPARSER_MxRecord mx;
564 char mxbuf[258];
565 char mxhost[253 + 1];
566 unsigned int mx_pref;
567 size_t off;
568
569 if (2 != sscanf (s, "%u %253s", &mx_pref, mxhost))
570 {
571 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
572 _ ("Unable to parse MX record `%s'\n"),
573 s);
574 return GNUNET_SYSERR;
575 }
576 mx.preference = (uint16_t) mx_pref;
577 mx.mxhost = mxhost;
578 off = 0;
579
580 if (GNUNET_OK !=
581 GNUNET_DNSPARSER_builder_add_mx (mxbuf, sizeof(mxbuf), &off, &mx))
582 {
583 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
584 _ ("Failed to serialize MX record with hostname `%s'\n"),
585 mxhost);
586 return GNUNET_SYSERR;
587 }
588 *data_size = off;
589 *data = GNUNET_malloc (off);
590 GNUNET_memcpy (*data, mxbuf, off);
591 return GNUNET_OK;
592 }
593
594 case GNUNET_DNSPARSER_TYPE_SRV: {
595 struct GNUNET_DNSPARSER_SrvRecord srv;
596 char srvbuf[270];
597 char srvtarget[253 + 1];
598 unsigned int priority;
599 unsigned int weight;
600 unsigned int port;
601 size_t off;
602
603 if (4 != sscanf (s, "%u %u %u %253s", &priority, &weight, &port,
604 srvtarget))
605 {
606 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
607 _ ("Unable to parse SRV record `%s'\n"),
608 s);
609 return GNUNET_SYSERR;
610 }
611 srv.priority = (uint16_t) priority;
612 srv.weight = (uint16_t) weight;
613 srv.port = (uint16_t) port;
614 srv.target = srvtarget;
615 off = 0;
616 if (GNUNET_OK !=
617 GNUNET_DNSPARSER_builder_add_srv (srvbuf, sizeof(srvbuf), &off, &srv))
618 {
619 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
620 _ ("Failed to serialize SRV record with target `%s'\n"),
621 srvtarget);
622 return GNUNET_SYSERR;
623 }
624 *data_size = off;
625 *data = GNUNET_malloc (off);
626 GNUNET_memcpy (*data, srvbuf, off);
627 return GNUNET_OK;
628 }
629
630 case GNUNET_DNSPARSER_TYPE_TXT:
631 *data = GNUNET_strdup (s);
632 *data_size = strlen (s);
633 return GNUNET_OK;
634
635 case GNUNET_DNSPARSER_TYPE_AAAA:
636 if (1 != inet_pton (AF_INET6, s, &value_aaaa))
637 {
638 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
639 _ ("Unable to parse IPv6 address `%s'\n"),
640 s);
641 return GNUNET_SYSERR;
642 }
643 *data = GNUNET_new (struct in6_addr);
644 *data_size = sizeof(struct in6_addr);
645 GNUNET_memcpy (*data, &value_aaaa, sizeof(value_aaaa));
646 return GNUNET_OK;
647
648 case GNUNET_DNSPARSER_TYPE_TLSA: {
649 unsigned int usage;
650 unsigned int selector;
651 unsigned int matching_type;
652 size_t slen = strlen (s) + 1;
653 char hex[slen];
654
655 if (4 != sscanf (s, "%u %u %u %s", &usage, &selector, &matching_type,
656 hex))
657 {
658 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
659 _ ("Unable to parse TLSA record string `%s'\n"),
660 s);
661 *data_size = 0;
662 return GNUNET_SYSERR;
663 }
664
665 *data_size = sizeof(struct GNUNET_TUN_DnsTlsaRecord) + strlen (hex) / 2;
666 *data = tlsa = GNUNET_malloc (*data_size);
667 tlsa->usage = (uint8_t) usage;
668 tlsa->selector = (uint8_t) selector;
669 tlsa->matching_type = (uint8_t) matching_type;
670 if (strlen (hex) / 2 != GNUNET_DNSPARSER_hex_to_bin (hex, &tlsa[1]))
671 {
672 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
673 _ ("Unable to parse TLSA record string `%s'\n"),
674 s);
675 GNUNET_free (*data);
676 *data = NULL;
677 *data_size = 0;
678 return GNUNET_SYSERR;
679 }
680 return GNUNET_OK;
681 }
682
683 case GNUNET_DNSPARSER_TYPE_CAA: { // RFC6844
684 struct GNUNET_DNSPARSER_CaaRecord *caa;
685 unsigned int flags;
686 char tag[15]; // Max tag length 15
687 char value[strlen (s) + 1]; // Should be more than enough
688
689 if (3 != sscanf (s, "%u %s %[^\n]", &flags, tag, value))
690 {
691 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
692 _ ("Unable to parse CAA record string `%s'\n"),
693 s);
694 *data_size = 0;
695 return GNUNET_SYSERR;
696 }
697 *data_size = sizeof(struct GNUNET_DNSPARSER_CaaRecord) + strlen (tag)
698 + strlen (value);
699 *data = caa = GNUNET_malloc (*data_size);
700 caa->flags = flags;
701 memcpy (&caa[1], tag, strlen (tag));
702 caa->tag_len = strlen (tag);
703 memcpy ((char *) &caa[1] + caa->tag_len, value, strlen (value));
704 return GNUNET_OK;
705 }
706
707 default:
708 return GNUNET_SYSERR;
709 }
710}
711
712
713/**
714 * Mapping of record type numbers to human-readable
715 * record type names.
716 */
717static struct
718{
719 const char *name;
720 uint32_t number;
721} name_map[] = { { "A", GNUNET_DNSPARSER_TYPE_A },
722 { "NS", GNUNET_DNSPARSER_TYPE_NS },
723 { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
724 { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
725 { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
726 { "MX", GNUNET_DNSPARSER_TYPE_MX },
727 { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
728 { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
729 { "SRV", GNUNET_DNSPARSER_TYPE_SRV },
730 { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
731 { "CERT", GNUNET_DNSPARSER_TYPE_CERT },
732 { "CAA", GNUNET_DNSPARSER_TYPE_CAA },
733 { NULL, UINT32_MAX } };
734
735
736/**
737 * Convert a type name (e.g. "AAAA") to the corresponding number.
738 *
739 * @param cls closure, unused
740 * @param dns_typename name to convert
741 * @return corresponding number, UINT32_MAX on error
742 */
743static uint32_t
744dns_typename_to_number (void *cls, const char *dns_typename)
745{
746 unsigned int i;
747
748 i = 0;
749 while ((NULL != name_map[i].name) &&
750 (0 != strcasecmp (dns_typename, name_map[i].name)))
751 i++;
752 return name_map[i].number;
753}
754
755
756/**
757 * Convert a type number to the corresponding type string (e.g. 1 to "A")
758 *
759 * @param cls closure, unused
760 * @param type number of a type to convert
761 * @return corresponding typestring, NULL on error
762 */
763static const char *
764dns_number_to_typename (void *cls, uint32_t type)
765{
766 unsigned int i;
767
768 i = 0;
769 while ((NULL != name_map[i].name) && (type != name_map[i].number))
770 i++;
771 return name_map[i].name;
772}
773
774
775static enum GNUNET_GenericReturnValue
776dns_is_critical (void *cls, uint32_t type)
777{
778 return GNUNET_NO;
779}
780
781/**
782 * Entry point for the plugin.
783 *
784 * @param cls NULL
785 * @return the exported block API
786 */
787void *
788libgnunet_plugin_gnsrecord_dns_init (void *cls)
789{
790 struct GNUNET_GNSRECORD_PluginFunctions *api;
791
792 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
793 api->value_to_string = &dns_value_to_string;
794 api->string_to_value = &dns_string_to_value;
795 api->typename_to_number = &dns_typename_to_number;
796 api->number_to_typename = &dns_number_to_typename;
797 api->is_critical = &dns_is_critical;
798 return api;
799}
800
801
802/**
803 * Exit point from the plugin.
804 *
805 * @param cls the return value from #libgnunet_plugin_block_test_init
806 * @return NULL
807 */
808void *
809libgnunet_plugin_gnsrecord_dns_done (void *cls)
810{
811 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
812
813 GNUNET_free (api);
814 return NULL;
815}
816
817
818/* end of plugin_gnsrecord_dns.c */