1 /**
2 *
3 * /brief getdns support functions for DNS Resource Records
4 *
5 * This file contains the tables with the information needed by getdns about
6 * individual RRs, such as their name and rdata fields and types.
7 * This information is provided via the response dict.
8 *
9 */
10 /*
11 * Copyright (c) 2013, NLnet Labs, Verisign, Inc.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
16 * * Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * * Neither the names of the copyright holders nor the
22 * names of its contributors may be used to endorse or promote products
23 * derived from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
29 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #include "rr-dict.h"
38 #include "gldns/gbuffer.h"
39 #include "util-internal.h"
40 #include "types-internal.h"
41 #include "context.h"
42 #include "dict.h"
43
44 #define ALEN(a) (sizeof(a)/sizeof(a[0]))
45 #define UNKNOWN_RDATA NULL
46
47 static const uint8_t *
apl_n_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)48 apl_n_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
49 {
50 (void)pkt;
51 return rdf < pkt_end ? rdf + 1 : NULL;
52 }
53 static getdns_return_t
apl_n_wire2dict(getdns_dict * dict,const uint8_t * rdf)54 apl_n_wire2dict(getdns_dict *dict, const uint8_t *rdf)
55 {
56 return getdns_dict_set_int(dict, "n", (*rdf >> 7));
57 }
58 static getdns_return_t
apl_n_2wire(uint32_t value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)59 apl_n_2wire(uint32_t value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
60 {
61 (void)rdata; /* unused parameter */
62
63 if (*rdf_len < 1) {
64 *rdf_len = 1;
65 return GETDNS_RETURN_NEED_MORE_SPACE;
66 }
67 *rdf_len = 1;
68 *rdf = value ? 0x80 : 0x00;
69 return GETDNS_RETURN_GOOD;
70 }
71 static getdns_return_t
apl_n_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)72 apl_n_dict2wire(const getdns_dict *dict,
73 uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
74 {
75 getdns_return_t r;
76 uint32_t value;
77
78 if ((r = getdns_dict_get_int(dict, "n", &value)))
79 return r;
80 else
81 return apl_n_2wire(value, rdata, rdf, rdf_len);
82 }
83 static _getdns_rdf_special apl_n = {
84 apl_n_rdf_end,
85 apl_n_wire2dict, NULL,
86 apl_n_dict2wire, NULL
87 };
88
89 static const uint8_t *
apl_afdpart_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)90 apl_afdpart_rdf_end(
91 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
92 {
93 const uint8_t *end = rdf + (rdf[-1] & 0x7F);
94 (void)(pkt);
95 return end <= pkt_end ? end : NULL;
96 }
97 static getdns_return_t
apl_afdpart_wire2dict(getdns_dict * dict,const uint8_t * rdf)98 apl_afdpart_wire2dict(getdns_dict *dict, const uint8_t *rdf)
99 {
100 return _getdns_dict_set_const_bindata(
101 dict, "afdpart", (rdf[-1] & 0x7F), rdf);
102 }
103 static getdns_return_t
apl_afdpart_2wire(const getdns_bindata * value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)104 apl_afdpart_2wire(
105 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
106 {
107 if (value->size > 0x7F)
108 return GETDNS_RETURN_INVALID_PARAMETER;
109
110 if (rdf - 1 < rdata)
111 return GETDNS_RETURN_GENERIC_ERROR;
112
113 if (*rdf_len < value->size) {
114 *rdf_len = value->size;
115 return GETDNS_RETURN_NEED_MORE_SPACE;
116 }
117 *rdf_len = value->size;
118
119 /* Keeping first bit is safe because value->size <= 0x7F */
120 rdf[-1] |= value->size;
121
122 (void) memcpy(rdf, value->data, value->size);
123 return GETDNS_RETURN_GOOD;
124 }
125 static getdns_return_t
apl_afdpart_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)126 apl_afdpart_dict2wire(
127 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
128 {
129 getdns_return_t r;
130 getdns_bindata *value;
131
132 if ((r = getdns_dict_get_bindata(dict, "afdpart", &value)))
133 return r;
134 else
135 return apl_afdpart_2wire(value, rdata, rdf, rdf_len);
136 }
137 static _getdns_rdf_special apl_afdpart = {
138 apl_afdpart_rdf_end,
139 apl_afdpart_wire2dict, NULL,
140 apl_afdpart_dict2wire, NULL
141 };
142
143 static const uint8_t *
ipseckey_gateway_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)144 ipseckey_gateway_rdf_end(
145 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
146 {
147 const uint8_t *end;
148
149 if (rdf - 5 < pkt)
150 return NULL;
151 switch (rdf[-2]) {
152 case 0: end = rdf;
153 break;
154 case 1: end = rdf + 4;
155 break;
156 case 2: end = rdf + 16;
157 break;
158 case 3: for (end = rdf; end < pkt_end; end += *end + 1)
159 if ((*end & 0xC0) == 0xC0)
160 end += 2;
161 else if (*end & 0xC0)
162 return NULL;
163 else if (!*end) {
164 end += 1;
165 break;
166 }
167 break;
168 default:
169 return NULL;
170 }
171 return end <= pkt_end ? end : NULL;
172 }
173 static getdns_return_t
ipseckey_gateway_equip_const_bindata(const uint8_t * rdf,size_t * size,const uint8_t ** data)174 ipseckey_gateway_equip_const_bindata(
175 const uint8_t *rdf, size_t *size, const uint8_t **data)
176 {
177 *data = rdf;
178 switch (rdf[-2]) {
179 case 0: *size = 0;
180 break;
181 case 1: *size = 4;
182 break;
183 case 2: *size = 16;
184 break;
185 case 3: while (*rdf)
186 if ((*rdf & 0xC0) == 0xC0)
187 rdf += 2;
188 else if (*rdf & 0xC0)
189 return GETDNS_RETURN_GENERIC_ERROR;
190 else
191 rdf += *rdf + 1;
192 *size = rdf + 1 - *data;
193 break;
194 default:
195 return GETDNS_RETURN_GENERIC_ERROR;
196 }
197 return GETDNS_RETURN_GOOD;
198 }
199
200 static getdns_return_t
ipseckey_gateway_wire2dict(getdns_dict * dict,const uint8_t * rdf)201 ipseckey_gateway_wire2dict(getdns_dict *dict, const uint8_t *rdf)
202 {
203 size_t size;
204 const uint8_t *data;
205
206 if (ipseckey_gateway_equip_const_bindata(rdf, &size, &data))
207 return GETDNS_RETURN_GENERIC_ERROR;
208
209 else if (! size)
210 return GETDNS_RETURN_GOOD;
211 else
212 return _getdns_dict_set_const_bindata(dict, "gateway", size, data);
213 }
214 static getdns_return_t
ipseckey_gateway_2wire(const getdns_bindata * value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)215 ipseckey_gateway_2wire(
216 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
217 {
218 assert(rdf - 2 >= rdata && rdf[-2] > 0);
219
220 switch (rdf[-2]) {
221 case 1: if (!value || value->size != 4)
222 return GETDNS_RETURN_INVALID_PARAMETER;
223 if (*rdf_len < 4) {
224 *rdf_len = 4;
225 return GETDNS_RETURN_NEED_MORE_SPACE;
226 }
227 *rdf_len = 4;
228 (void)memcpy(rdf, value->data, 4);
229 return GETDNS_RETURN_GOOD;
230 case 2: if (!value || value->size != 16)
231 return GETDNS_RETURN_INVALID_PARAMETER;
232 if (*rdf_len < 16) {
233 *rdf_len = 16;
234 return GETDNS_RETURN_NEED_MORE_SPACE;
235 }
236 *rdf_len = 16;
237 (void)memcpy(rdf, value->data, 16);
238 return GETDNS_RETURN_GOOD;
239 case 3: if (!value || value->size == 0)
240 return GETDNS_RETURN_INVALID_PARAMETER;
241 /* Assume bindata is a valid dname; garbage in, garbage out */
242 if (*rdf_len < value->size) {
243 *rdf_len = value->size;
244 return GETDNS_RETURN_NEED_MORE_SPACE;
245 }
246 *rdf_len = value->size;
247 (void)memcpy(rdf, value->data, value->size);
248 return GETDNS_RETURN_GOOD;
249 default:
250 return GETDNS_RETURN_GENERIC_ERROR;
251 }
252 return GETDNS_RETURN_GOOD;
253 }
254 static getdns_return_t
ipseckey_gateway_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)255 ipseckey_gateway_dict2wire(
256 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
257 {
258 getdns_return_t r;
259 getdns_bindata *value;
260
261 if (rdf - 2 < rdata)
262 return GETDNS_RETURN_GENERIC_ERROR;
263
264 else if (rdf[-2] == 0) {
265 *rdf_len = 0;
266 return GETDNS_RETURN_GOOD;
267 }
268 else if ((r = getdns_dict_get_bindata(dict, "gateway", &value)))
269 return r;
270 else
271 return ipseckey_gateway_2wire(value, rdata, rdf, rdf_len);
272 }
273 static _getdns_rdf_special ipseckey_gateway = {
274 ipseckey_gateway_rdf_end,
275 ipseckey_gateway_wire2dict, NULL,
276 ipseckey_gateway_dict2wire, NULL
277 };
278
279 static const uint8_t *
hip_pk_algorithm_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)280 hip_pk_algorithm_rdf_end(
281 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
282 {
283 (void)(pkt);
284 return rdf + 4 > pkt_end ? NULL
285 : rdf + 4 + *rdf + gldns_read_uint16(rdf + 2) > pkt_end ? NULL
286 : rdf + 1;
287 }
288 static getdns_return_t
hip_pk_algorithm_wire2dict(getdns_dict * dict,const uint8_t * rdf)289 hip_pk_algorithm_wire2dict(getdns_dict *dict, const uint8_t *rdf)
290 {
291 return getdns_dict_set_int(dict, "pk_algorithm", rdf[1]);
292 }
293 static getdns_return_t
hip_pk_algorithm_2wire(uint32_t value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)294 hip_pk_algorithm_2wire(uint32_t value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
295 {
296 if (rdata != rdf)
297 return GETDNS_RETURN_GENERIC_ERROR;
298 if (value > 0xFF)
299 return GETDNS_RETURN_INVALID_PARAMETER;
300 if (*rdf_len < 4) {
301 *rdf_len = 4;
302 return GETDNS_RETURN_NEED_MORE_SPACE;
303 }
304 *rdf_len = 4;
305 rdata[1] = value;
306 return GETDNS_RETURN_GOOD;
307 }
308 static getdns_return_t
hip_pk_algorithm_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)309 hip_pk_algorithm_dict2wire(
310 const getdns_dict *dict,uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
311 {
312 getdns_return_t r;
313 uint32_t value;
314
315 if ((r = getdns_dict_get_int(dict, "pk_algorithm", &value)))
316 return r;
317 else
318 return hip_pk_algorithm_2wire(value, rdata, rdf, rdf_len);
319 }
320 static _getdns_rdf_special hip_pk_algorithm = {
321 hip_pk_algorithm_rdf_end,
322 hip_pk_algorithm_wire2dict, NULL,
323 hip_pk_algorithm_dict2wire, NULL
324 };
325
326 static const uint8_t *
hip_hit_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)327 hip_hit_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
328 {
329 (void)(pkt);
330 return rdf + 3 > pkt_end ? NULL
331 : rdf + 3 + rdf[-1] + gldns_read_uint16(rdf + 1) > pkt_end ? NULL
332 : rdf + 1;
333 }
334 static getdns_return_t
hip_hit_wire2dict(getdns_dict * dict,const uint8_t * rdf)335 hip_hit_wire2dict(getdns_dict *dict, const uint8_t *rdf)
336 {
337 return _getdns_dict_set_const_bindata(dict, "hit", rdf[-1], rdf + 3);
338 }
339 static getdns_return_t
hip_hit_2wire(const getdns_bindata * value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)340 hip_hit_2wire(
341 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
342 {
343 if (rdata != rdf - 4)
344 return GETDNS_RETURN_GENERIC_ERROR;
345 if (value && value->size > 0xFF)
346 return GETDNS_RETURN_INVALID_PARAMETER;
347 if (!value || value->size == 0) {
348 rdata[0] = 0;
349 *rdf_len = 0;
350 return GETDNS_RETURN_GOOD;
351 }
352 if (value->size > *rdf_len) {
353 *rdf_len = value->size;
354 return GETDNS_RETURN_NEED_MORE_SPACE;
355 }
356 *rdf_len = value->size;
357 rdata[0] = (uint8_t) value->size;
358 (void)memcpy(rdf, value->data, value->size);
359 return GETDNS_RETURN_GOOD;
360 }
361 static getdns_return_t
hip_hit_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)362 hip_hit_dict2wire(
363 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
364 {
365 getdns_return_t r;
366 getdns_bindata *value;
367
368 if ((r = getdns_dict_get_bindata(dict, "hit", &value)))
369 return r;
370 else
371 return hip_hit_2wire(value, rdata, rdf, rdf_len);
372 }
373 static _getdns_rdf_special hip_hit = {
374 hip_hit_rdf_end,
375 hip_hit_wire2dict, NULL,
376 hip_hit_dict2wire, NULL
377 };
378
379 static const uint8_t *
hip_public_key_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)380 hip_public_key_rdf_end(
381 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
382 {
383 (void)(pkt);
384 return rdf + 2 > pkt_end ? NULL
385 : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf) > pkt_end ? NULL
386 : rdf + 2 + rdf[-2] + gldns_read_uint16(rdf);
387 }
388 static getdns_return_t
hip_public_key_wire2dict(getdns_dict * dict,const uint8_t * rdf)389 hip_public_key_wire2dict(getdns_dict *dict, const uint8_t *rdf)
390 {
391 return _getdns_dict_set_const_bindata(
392 dict, "public_key", gldns_read_uint16(rdf), rdf + 2 + rdf[-2]);
393 }
394 static getdns_return_t
hip_public_key_2wire(const getdns_bindata * value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)395 hip_public_key_2wire(
396 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
397 {
398 if (rdata > rdf - 4 || rdata + 4 + rdata[0] != rdf)
399 return GETDNS_RETURN_GENERIC_ERROR;
400 if (value && value->size > 0xFFFF)
401 return GETDNS_RETURN_INVALID_PARAMETER;
402 if (!value || value->size == 0) {
403 rdata[2] = rdata[3] = 0;
404 *rdf_len = 0;
405 return GETDNS_RETURN_GOOD;
406 }
407 if (value->size > *rdf_len) {
408 *rdf_len = value->size;
409 return GETDNS_RETURN_NEED_MORE_SPACE;
410 }
411 *rdf_len = value->size;
412 gldns_write_uint16(rdata + 2, (uint16_t) value->size);
413 (void)memcpy(rdf, value->data, value->size);
414 return GETDNS_RETURN_GOOD;
415 }
416 static getdns_return_t
hip_public_key_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)417 hip_public_key_dict2wire(
418 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
419 {
420 getdns_return_t r;
421 getdns_bindata *value;
422
423 if ((r = getdns_dict_get_bindata(dict, "public_key", &value)))
424 return r;
425 else
426 return hip_public_key_2wire(value, rdata, rdf, rdf_len);
427 }
428 static _getdns_rdf_special hip_public_key = {
429 hip_public_key_rdf_end,
430 hip_public_key_wire2dict, NULL,
431 hip_public_key_dict2wire, NULL
432 };
433
434 static const uint8_t *
amtrelay_D_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)435 amtrelay_D_rdf_end(const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
436 {
437 (void)pkt;
438 return rdf < pkt_end ? rdf + 1 : NULL;
439 }
440 static getdns_return_t
amtrelay_D_wire2dict(getdns_dict * dict,const uint8_t * rdf)441 amtrelay_D_wire2dict(getdns_dict *dict, const uint8_t *rdf)
442 {
443 return getdns_dict_set_int(dict, "discovery_optional", (*rdf >> 7));
444 }
445 static getdns_return_t
amtrelay_D_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)446 amtrelay_D_dict2wire(const getdns_dict *dict,
447 uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
448 {
449 getdns_return_t r;
450 uint32_t value;
451 (void)rdata; /* unused parameter */
452
453 if ((r = getdns_dict_get_int(dict, "discovery_optional", &value)))
454 return r;
455
456 *rdf_len = 1;
457 if (*rdf_len < 1)
458 return GETDNS_RETURN_NEED_MORE_SPACE;
459
460 *rdf_len = 1;
461 *rdf = value ? 0x80 : 0x00;
462 return GETDNS_RETURN_GOOD;
463 }
464 static _getdns_rdf_special amtrelay_D = {
465 amtrelay_D_rdf_end,
466 amtrelay_D_wire2dict, NULL,
467 amtrelay_D_dict2wire, NULL
468 };
469
470 static const uint8_t *
amtrelay_rtype_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)471 amtrelay_rtype_rdf_end(
472 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
473 {
474 (void)pkt; (void)pkt_end;
475 return rdf;
476 }
477 static getdns_return_t
amtrelay_rtype_wire2dict(getdns_dict * dict,const uint8_t * rdf)478 amtrelay_rtype_wire2dict(getdns_dict *dict, const uint8_t *rdf)
479 {
480 return getdns_dict_set_int(
481 dict, "replay_type", (rdf[-1] & 0x7F));
482 }
483 static getdns_return_t
amtrelay_rtype_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)484 amtrelay_rtype_dict2wire(
485 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
486 {
487 getdns_return_t r;
488 uint32_t value;
489
490 if ((r = getdns_dict_get_int(dict, "relay_type", &value)))
491 return r;
492
493 if (rdf - 1 < rdata)
494 return GETDNS_RETURN_GENERIC_ERROR;
495
496 *rdf_len = 0;
497 rdf[-1] |= (value & 0x7F);
498
499 return GETDNS_RETURN_GOOD;
500 }
501 static _getdns_rdf_special amtrelay_rtype = {
502 amtrelay_rtype_rdf_end,
503 amtrelay_rtype_wire2dict, NULL,
504 amtrelay_rtype_dict2wire, NULL
505 };
506
507 static const uint8_t *
amtrelay_relay_rdf_end(const uint8_t * pkt,const uint8_t * pkt_end,const uint8_t * rdf)508 amtrelay_relay_rdf_end(
509 const uint8_t *pkt, const uint8_t *pkt_end, const uint8_t *rdf)
510 {
511 const uint8_t *end;
512
513 if (rdf - 4 < pkt)
514 return NULL;
515 switch (rdf[-1] & 0x7F) {
516 case 0: end = rdf;
517 break;
518 case 1: end = rdf + 4;
519 break;
520 case 2: end = rdf + 16;
521 break;
522 case 3: for (end = rdf; end < pkt_end; end += *end + 1)
523 if ((*end & 0xC0) == 0xC0)
524 end += 2;
525 else if (*end & 0xC0)
526 return NULL;
527 else if (!*end) {
528 end += 1;
529 break;
530 }
531 break;
532 default:
533 return NULL;
534 }
535 return end <= pkt_end ? end : NULL;
536 }
537 static getdns_return_t
amtrelay_relay_equip_const_bindata(const uint8_t * rdf,size_t * size,const uint8_t ** data)538 amtrelay_relay_equip_const_bindata(
539 const uint8_t *rdf, size_t *size, const uint8_t **data)
540 {
541 *data = rdf;
542 switch (rdf[-1] & 0x7F) {
543 case 0: *size = 0;
544 break;
545 case 1: *size = 4;
546 break;
547 case 2: *size = 16;
548 break;
549 case 3: while (*rdf)
550 if ((*rdf & 0xC0) == 0xC0)
551 rdf += 2;
552 else if (*rdf & 0xC0)
553 return GETDNS_RETURN_GENERIC_ERROR;
554 else
555 rdf += *rdf + 1;
556 *size = rdf + 1 - *data;
557 break;
558 default:
559 return GETDNS_RETURN_GENERIC_ERROR;
560 }
561 return GETDNS_RETURN_GOOD;
562 }
563
564 static getdns_return_t
amtrelay_relay_wire2dict(getdns_dict * dict,const uint8_t * rdf)565 amtrelay_relay_wire2dict(getdns_dict *dict, const uint8_t *rdf)
566 {
567 size_t size;
568 const uint8_t *data;
569
570 if (amtrelay_relay_equip_const_bindata(rdf, &size, &data))
571 return GETDNS_RETURN_GENERIC_ERROR;
572
573 else if (! size)
574 return GETDNS_RETURN_GOOD;
575 else
576 return _getdns_dict_set_const_bindata(dict, "relay", size, data);
577 }
578 static getdns_return_t
amtrelay_relay_2wire(const getdns_bindata * value,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)579 amtrelay_relay_2wire(
580 const getdns_bindata *value, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
581 {
582 assert(rdf - 1 >= rdata && (rdf[-1] & 0x7F) > 0);
583
584 switch (rdf[-1] & 0x7F) {
585 case 1: if (!value || value->size != 4)
586 return GETDNS_RETURN_INVALID_PARAMETER;
587 if (*rdf_len < 4) {
588 *rdf_len = 4;
589 return GETDNS_RETURN_NEED_MORE_SPACE;
590 }
591 *rdf_len = 4;
592 (void)memcpy(rdf, value->data, 4);
593 return GETDNS_RETURN_GOOD;
594 case 2: if (!value || value->size != 16)
595 return GETDNS_RETURN_INVALID_PARAMETER;
596 if (*rdf_len < 16) {
597 *rdf_len = 16;
598 return GETDNS_RETURN_NEED_MORE_SPACE;
599 }
600 *rdf_len = 16;
601 (void)memcpy(rdf, value->data, 16);
602 return GETDNS_RETURN_GOOD;
603 case 3: if (!value || value->size == 0)
604 return GETDNS_RETURN_INVALID_PARAMETER;
605 /* Assume bindata is a valid dname; garbage in, garbage out */
606 if (*rdf_len < value->size) {
607 *rdf_len = value->size;
608 return GETDNS_RETURN_NEED_MORE_SPACE;
609 }
610 *rdf_len = value->size;
611 (void)memcpy(rdf, value->data, value->size);
612 return GETDNS_RETURN_GOOD;
613 default:
614 return GETDNS_RETURN_GENERIC_ERROR;
615 }
616 return GETDNS_RETURN_GOOD;
617 }
618 static getdns_return_t
amtrelay_relay_dict2wire(const getdns_dict * dict,uint8_t * rdata,uint8_t * rdf,size_t * rdf_len)619 amtrelay_relay_dict2wire(
620 const getdns_dict *dict, uint8_t *rdata, uint8_t *rdf, size_t *rdf_len)
621 {
622 getdns_return_t r;
623 getdns_bindata *value;
624
625 if (rdf - 1 < rdata)
626 return GETDNS_RETURN_GENERIC_ERROR;
627
628 else if ((rdf[-1] & 0x7F) == 0) {
629 *rdf_len = 0;
630 return GETDNS_RETURN_GOOD;
631 }
632 else if ((r = getdns_dict_get_bindata(dict, "relay", &value)))
633 return r;
634 else
635 return amtrelay_relay_2wire(value, rdata, rdf, rdf_len);
636 }
637 static _getdns_rdf_special amtrelay_relay = {
638 amtrelay_relay_rdf_end,
639 amtrelay_relay_wire2dict, NULL,
640 amtrelay_relay_dict2wire, NULL
641 };
642
643
644 static _getdns_rdata_def a_rdata[] = {
645 { "ipv4_address" , GETDNS_RDF_A , NULL }};
646 static _getdns_rdata_def ns_rdata[] = {
647 { "nsdname" , GETDNS_RDF_N_C , NULL }};
648 static _getdns_rdata_def md_rdata[] = {
649 { "madname" , GETDNS_RDF_N_C , NULL }};
650 static _getdns_rdata_def cname_rdata[] = {
651 { "cname" , GETDNS_RDF_N_C , NULL }};
652 static _getdns_rdata_def soa_rdata[] = {
653 { "mname" , GETDNS_RDF_N_C , NULL },
654 { "rname" , GETDNS_RDF_N_C , NULL },
655 { "serial" , GETDNS_RDF_I4 , NULL },
656 { "refresh" , GETDNS_RDF_I4 , NULL },
657 { "retry" , GETDNS_RDF_I4 , NULL },
658 { "expire" , GETDNS_RDF_I4 , NULL },
659 { "minimum" , GETDNS_RDF_I4 , NULL }};
660 static _getdns_rdata_def mg_rdata[] = {
661 { "mgmname" , GETDNS_RDF_N_C , NULL }};
662 static _getdns_rdata_def mr_rdata[] = {
663 { "newname" , GETDNS_RDF_N_C , NULL }};
664 static _getdns_rdata_def null_rdata[] = {
665 { "anything" , GETDNS_RDF_X , NULL }};
666 static _getdns_rdata_def wks_rdata[] = {
667 { "address" , GETDNS_RDF_A , NULL },
668 { "protocol" , GETDNS_RDF_I1 , NULL },
669 { "bitmap" , GETDNS_RDF_X , NULL }};
670 static _getdns_rdata_def ptr_rdata[] = {
671 { "ptrdname" , GETDNS_RDF_N_C , NULL }};
672 static _getdns_rdata_def hinfo_rdata[] = {
673 { "cpu" , GETDNS_RDF_S , NULL },
674 { "os" , GETDNS_RDF_S , NULL }};
675 static _getdns_rdata_def minfo_rdata[] = {
676 { "rmailbx" , GETDNS_RDF_N_C , NULL },
677 { "emailbx" , GETDNS_RDF_N_C , NULL }};
678 static _getdns_rdata_def mx_rdata[] = {
679 { "preference" , GETDNS_RDF_I2 , NULL },
680 { "exchange" , GETDNS_RDF_N_C , NULL }};
681 static _getdns_rdata_def txt_rdata[] = {
682 { "txt_strings" , GETDNS_RDF_S_M , NULL }};
683 static _getdns_rdata_def rp_rdata[] = {
684 { "mbox_dname" , GETDNS_RDF_N , NULL },
685 { "txt_dname" , GETDNS_RDF_N , NULL }};
686 static _getdns_rdata_def afsdb_rdata[] = {
687 { "subtype" , GETDNS_RDF_I2 , NULL },
688 { "hostname" , GETDNS_RDF_N , NULL }};
689 static _getdns_rdata_def x25_rdata[] = {
690 { "psdn_address" , GETDNS_RDF_S , NULL }};
691 static _getdns_rdata_def isdn_rdata[] = {
692 { "isdn_address" , GETDNS_RDF_S , NULL },
693 { "sa" , GETDNS_RDF_S , NULL }};
694 static _getdns_rdata_def rt_rdata[] = {
695 { "preference" , GETDNS_RDF_I2 , NULL },
696 { "intermediate_host" , GETDNS_RDF_N , NULL }};
697 static _getdns_rdata_def nsap_rdata[] = {
698 { "nsap" , GETDNS_RDF_X , NULL }};
699 static _getdns_rdata_def nsap_ptr_rdata[] = {
700 { "owner" , GETDNS_RDF_S , NULL }};
701 static _getdns_rdata_def sig_rdata[] = {
702 { "sig_obsolete" , GETDNS_RDF_X , NULL }};
703 static _getdns_rdata_def key_rdata[] = {
704 { "key_obsolete" , GETDNS_RDF_X , NULL }};
705 static _getdns_rdata_def px_rdata[] = {
706 { "preference" , GETDNS_RDF_I2 , NULL },
707 { "map822" , GETDNS_RDF_N , NULL },
708 { "mapx400" , GETDNS_RDF_N , NULL }};
709 static _getdns_rdata_def gpos_rdata[] = {
710 { "longitude" , GETDNS_RDF_S , NULL },
711 { "latitude" , GETDNS_RDF_S , NULL },
712 { "altitude" , GETDNS_RDF_S , NULL }};
713 static _getdns_rdata_def aaaa_rdata[] = {
714 { "ipv6_address" , GETDNS_RDF_AAAA , NULL }};
715 static _getdns_rdata_def loc_rdata[] = {
716 { "loc_obsolete" , GETDNS_RDF_X , NULL }};
717 static _getdns_rdata_def nxt_rdata[] = {
718 { "nxt_obsolete" , GETDNS_RDF_X , NULL }};
719 static _getdns_rdata_def eid_rdata[] = {
720 { "endpoint_identifier" , GETDNS_RDF_X , NULL }};
721 static _getdns_rdata_def nimloc_rdata[] = {
722 { "nimrod_locator" , GETDNS_RDF_X , NULL }};
723 static _getdns_rdata_def srv_rdata[] = {
724 { "priority" , GETDNS_RDF_I2 , NULL },
725 { "weight" , GETDNS_RDF_I2 , NULL },
726 { "port" , GETDNS_RDF_I2 , NULL },
727 { "target" , GETDNS_RDF_N , NULL }};
728 static _getdns_rdata_def atma_rdata[] = {
729 { "format" , GETDNS_RDF_X , NULL }};
730 static _getdns_rdata_def naptr_rdata[] = {
731 { "order" , GETDNS_RDF_I2 , NULL },
732 { "preference" , GETDNS_RDF_I2 , NULL },
733 { "flags" , GETDNS_RDF_S , NULL },
734 { "service" , GETDNS_RDF_S , NULL },
735 { "regexp" , GETDNS_RDF_S , NULL },
736 { "replacement" , GETDNS_RDF_N , NULL }};
737 static _getdns_rdata_def kx_rdata[] = {
738 { "preference" , GETDNS_RDF_I2 , NULL },
739 { "exchanger" , GETDNS_RDF_N , NULL }};
740 static _getdns_rdata_def cert_rdata[] = {
741 { "type" , GETDNS_RDF_I2 , NULL },
742 { "key_tag" , GETDNS_RDF_I2 , NULL },
743 { "algorithm" , GETDNS_RDF_I1 , NULL },
744 { "certificate_or_crl" , GETDNS_RDF_B , NULL }};
745 static _getdns_rdata_def a6_rdata[] = {
746 { "a6_obsolete" , GETDNS_RDF_X , NULL }};
747 static _getdns_rdata_def dname_rdata[] = {
748 { "target" , GETDNS_RDF_N , NULL }};
749 static _getdns_rdata_def opt_rdata[] = {
750 { "options" , GETDNS_RDF_R , NULL },
751 { "option_code" , GETDNS_RDF_I2 , NULL },
752 { "option_data" , GETDNS_RDF_X_S , NULL }};
753 static _getdns_rdata_def apl_rdata[] = {
754 { "apitems" , GETDNS_RDF_R , NULL },
755 { "address_family" , GETDNS_RDF_I2 , NULL },
756 { "prefix" , GETDNS_RDF_I1 , NULL },
757 { "n" , GETDNS_RDF_SPECIAL, &apl_n },
758 { "afdpart" , GETDNS_RDF_SPECIAL, &apl_afdpart }};
759 static _getdns_rdata_def ds_rdata[] = {
760 { "key_tag" , GETDNS_RDF_I2 , NULL },
761 { "algorithm" , GETDNS_RDF_I1 , NULL },
762 { "digest_type" , GETDNS_RDF_I1 , NULL },
763 { "digest" , GETDNS_RDF_X , NULL }};
764 static _getdns_rdata_def sshfp_rdata[] = {
765 { "algorithm" , GETDNS_RDF_I1 , NULL },
766 { "fp_type" , GETDNS_RDF_I1 , NULL },
767 { "fingerprint" , GETDNS_RDF_X , NULL }};
768 static _getdns_rdata_def ipseckey_rdata[] = {
769 { "algorithm" , GETDNS_RDF_I1 , NULL },
770 { "gateway_type" , GETDNS_RDF_I1 , NULL },
771 { "precedence" , GETDNS_RDF_I1 , NULL },
772 { "gateway" , GETDNS_RDF_SPECIAL, &ipseckey_gateway },
773 { "public_key" , GETDNS_RDF_B , NULL }};
774 static _getdns_rdata_def rrsig_rdata[] = {
775 { "type_covered" , GETDNS_RDF_I2 , NULL },
776 { "algorithm" , GETDNS_RDF_I1 , NULL },
777 { "labels" , GETDNS_RDF_I1 , NULL },
778 { "original_ttl" , GETDNS_RDF_I4 , NULL },
779 { "signature_expiration" , GETDNS_RDF_T , NULL },
780 { "signature_inception" , GETDNS_RDF_T , NULL },
781 { "key_tag" , GETDNS_RDF_I2 , NULL },
782 { "signers_name" , GETDNS_RDF_N , NULL },
783 { "signature" , GETDNS_RDF_B , NULL }};
784 static _getdns_rdata_def nsec_rdata[] = {
785 { "next_domain_name" , GETDNS_RDF_N , NULL },
786 { "type_bit_maps" , GETDNS_RDF_X , NULL }};
787 static _getdns_rdata_def dnskey_rdata[] = {
788 { "flags" , GETDNS_RDF_I2 , NULL },
789 { "protocol" , GETDNS_RDF_I1 , NULL },
790 { "algorithm" , GETDNS_RDF_I1 , NULL },
791 { "public_key" , GETDNS_RDF_B , NULL }};
792 static _getdns_rdata_def dhcid_rdata[] = {
793 { "dhcid_opaque" , GETDNS_RDF_B , NULL }};
794 static _getdns_rdata_def nsec3_rdata[] = {
795 { "hash_algorithm" , GETDNS_RDF_I1 , NULL },
796 { "flags" , GETDNS_RDF_I1 , NULL },
797 { "iterations" , GETDNS_RDF_I2 , NULL },
798 { "salt" , GETDNS_RDF_X_C , NULL },
799 { "next_hashed_owner_name" , GETDNS_RDF_B32_C , NULL },
800 { "type_bit_maps" , GETDNS_RDF_X , NULL }};
801 static _getdns_rdata_def nsec3param_rdata[] = {
802 { "hash_algorithm" , GETDNS_RDF_I1 , NULL },
803 { "flags" , GETDNS_RDF_I1 , NULL },
804 { "iterations" , GETDNS_RDF_I2 , NULL },
805 { "salt" , GETDNS_RDF_X_C , NULL }};
806 static _getdns_rdata_def tlsa_rdata[] = {
807 { "certificate_usage" , GETDNS_RDF_I1 , NULL },
808 { "selector" , GETDNS_RDF_I1 , NULL },
809 { "matching_type" , GETDNS_RDF_I1 , NULL },
810 { "certificate_association_data", GETDNS_RDF_X , NULL }};
811 static _getdns_rdata_def hip_rdata[] = {
812 { "pk_algorithm" , GETDNS_RDF_SPECIAL, &hip_pk_algorithm },
813 { "hit" , GETDNS_RDF_SPECIAL, &hip_hit },
814 { "public_key" , GETDNS_RDF_SPECIAL, &hip_public_key },
815 { "rendezvous_servers" , GETDNS_RDF_N_M , NULL }};
816 static _getdns_rdata_def talink_rdata[] = {
817 { "previous" , GETDNS_RDF_N , NULL },
818 { "next" , GETDNS_RDF_N , NULL }};
819 static _getdns_rdata_def openpgpkey_rdata[] = {
820 { "transferable_public_key" , GETDNS_RDF_B , NULL }};
821 static _getdns_rdata_def csync_rdata[] = {
822 { "serial" , GETDNS_RDF_I4 , NULL },
823 { "flags" , GETDNS_RDF_I2 , NULL },
824 { "type_bit_maps" , GETDNS_RDF_X , NULL }};
825 static _getdns_rdata_def zonemd_rdata[] = {
826 { "serial" , GETDNS_RDF_I4 , NULL },
827 { "digest_type" , GETDNS_RDF_I1 , NULL },
828 { "reserved" , GETDNS_RDF_I1 , NULL },
829 { "digest" , GETDNS_RDF_X , NULL }};
830 static _getdns_rdata_def spf_rdata[] = {
831 { "text" , GETDNS_RDF_S_M , NULL }};
832 static _getdns_rdata_def nid_rdata[] = {
833 { "preference" , GETDNS_RDF_I2 , NULL },
834 { "node_id" , GETDNS_RDF_AA , NULL }};
835 static _getdns_rdata_def l32_rdata[] = {
836 { "preference" , GETDNS_RDF_I2 , NULL },
837 { "locator32" , GETDNS_RDF_A , NULL }};
838 static _getdns_rdata_def l64_rdata[] = {
839 { "preference" , GETDNS_RDF_I2 , NULL },
840 { "locator64" , GETDNS_RDF_AA , NULL }};
841 static _getdns_rdata_def lp_rdata[] = {
842 { "preference" , GETDNS_RDF_I2 , NULL },
843 { "fqdn" , GETDNS_RDF_N , NULL }};
844 static _getdns_rdata_def eui48_rdata[] = {
845 { "eui48_address" , GETDNS_RDF_X6 , NULL }};
846 static _getdns_rdata_def eui64_rdata[] = {
847 { "eui64_address" , GETDNS_RDF_X8 , NULL }};
848 static _getdns_rdata_def tkey_rdata[] = {
849 { "algorithm" , GETDNS_RDF_N , NULL },
850 { "inception" , GETDNS_RDF_T , NULL },
851 { "expiration" , GETDNS_RDF_T , NULL },
852 { "mode" , GETDNS_RDF_I2 , NULL },
853 { "error" , GETDNS_RDF_I2 , NULL },
854 { "key_data" , GETDNS_RDF_X_S , NULL },
855 { "other_data" , GETDNS_RDF_X_S , NULL }};
856 static _getdns_rdata_def tsig_rdata[] = {
857 { "algorithm" , GETDNS_RDF_N , NULL },
858 { "time_signed" , GETDNS_RDF_T6 , NULL },
859 { "fudge" , GETDNS_RDF_I2 , NULL },
860 { "mac" , GETDNS_RDF_X_S , NULL },
861 { "original_id" , GETDNS_RDF_I2 , NULL },
862 { "error" , GETDNS_RDF_I2 , NULL },
863 { "other_data" , GETDNS_RDF_X_S , NULL }};
864 static _getdns_rdata_def uri_rdata[] = {
865 { "priority" , GETDNS_RDF_I2 , NULL },
866 { "weight" , GETDNS_RDF_I2 , NULL },
867 { "target" , GETDNS_RDF_S_L , NULL }};
868 static _getdns_rdata_def caa_rdata[] = {
869 { "flags" , GETDNS_RDF_I1 , NULL },
870 { "tag" , GETDNS_RDF_S , NULL },
871 { "value" , GETDNS_RDF_S_L , NULL }};
872 static _getdns_rdata_def dlv_rdata[] = {
873 { "key_tag" , GETDNS_RDF_I2 , NULL },
874 { "algorithm" , GETDNS_RDF_I1 , NULL },
875 { "digest_type" , GETDNS_RDF_I1 , NULL },
876 { "digest" , GETDNS_RDF_X , NULL }};
877 static _getdns_rdata_def doa_rdata[] = {
878 { "enterprise" , GETDNS_RDF_I4 , NULL },
879 { "type" , GETDNS_RDF_I4 , NULL },
880 { "location" , GETDNS_RDF_I1 , NULL },
881 { "media_type" , GETDNS_RDF_S , NULL },
882 { "data" , GETDNS_RDF_B , NULL }};
883 static _getdns_rdata_def amtrelay_rdata[] = {
884 { "precedence" , GETDNS_RDF_I1 , NULL },
885 { "discovery_optional" , GETDNS_RDF_SPECIAL, &amtrelay_D},
886 { "relay_type" , GETDNS_RDF_SPECIAL, &amtrelay_rtype },
887 { "relay" , GETDNS_RDF_SPECIAL, &amtrelay_relay }};
888
889 static _getdns_rr_def _getdns_rr_defs[] = {
890 { NULL, NULL, 0 },
891 { "A", a_rdata, ALEN( a_rdata) }, /* 1 - */
892 { "NS", ns_rdata, ALEN( ns_rdata) },
893 { "MD", md_rdata, ALEN( md_rdata) },
894 { "MF", md_rdata, ALEN( md_rdata) },
895 { "CNAME", cname_rdata, ALEN( cname_rdata) },
896 { "SOA", soa_rdata, ALEN( soa_rdata) },
897 { "MB", md_rdata, ALEN( md_rdata) },
898 { "MG", mg_rdata, ALEN( mg_rdata) },
899 { "MR", mr_rdata, ALEN( mr_rdata) },
900 { "NULL", null_rdata, ALEN( null_rdata) },
901 { "WKS", wks_rdata, ALEN( wks_rdata) },
902 { "PTR", ptr_rdata, ALEN( ptr_rdata) },
903 { "HINFO", hinfo_rdata, ALEN( hinfo_rdata) },
904 { "MINFO", minfo_rdata, ALEN( minfo_rdata) },
905 { "MX", mx_rdata, ALEN( mx_rdata) },
906 { "TXT", txt_rdata, ALEN( txt_rdata) },
907 { "RP", rp_rdata, ALEN( rp_rdata) },
908 { "AFSDB", afsdb_rdata, ALEN( afsdb_rdata) },
909 { "X25", x25_rdata, ALEN( x25_rdata) },
910 { "ISDN", isdn_rdata, ALEN( isdn_rdata) },
911 { "RT", rt_rdata, ALEN( rt_rdata) },
912 { "NSAP", nsap_rdata, ALEN( nsap_rdata) },
913 { "NSAP_PTR", nsap_ptr_rdata, ALEN( nsap_ptr_rdata) },
914 { "SIG", sig_rdata, ALEN( sig_rdata) },
915 { "KEY", key_rdata, ALEN( key_rdata) },
916 { "PX", px_rdata, ALEN( px_rdata) },
917 { "GPOS", gpos_rdata, ALEN( gpos_rdata) },
918 { "AAAA", aaaa_rdata, ALEN( aaaa_rdata) },
919 { "LOC", loc_rdata, ALEN( loc_rdata) },
920 { "NXT", nxt_rdata, ALEN( nxt_rdata) },
921 { "EID", eid_rdata, ALEN( eid_rdata) },
922 { "NIMLOC", nimloc_rdata, ALEN( nimloc_rdata) },
923 { "SRV", srv_rdata, ALEN( srv_rdata) },
924 { "ATMA", atma_rdata, ALEN( atma_rdata) },
925 { "NAPTR", naptr_rdata, ALEN( naptr_rdata) },
926 { "KX", kx_rdata, ALEN( kx_rdata) },
927 { "CERT", cert_rdata, ALEN( cert_rdata) },
928 { "A6", a6_rdata, ALEN( a6_rdata) },
929 { "DNAME", dname_rdata, ALEN( dname_rdata) },
930 { "SINK", UNKNOWN_RDATA, 0 },
931 { "OPT", opt_rdata, ALEN( opt_rdata) },
932 { "APL", apl_rdata, ALEN( apl_rdata) },
933 { "DS", ds_rdata, ALEN( ds_rdata) },
934 { "SSHFP", sshfp_rdata, ALEN( sshfp_rdata) },
935 { "IPSECKEY", ipseckey_rdata, ALEN( ipseckey_rdata) },
936 { "RRSIG", rrsig_rdata, ALEN( rrsig_rdata) },
937 { "NSEC", nsec_rdata, ALEN( nsec_rdata) },
938 { "DNSKEY", dnskey_rdata, ALEN( dnskey_rdata) },
939 { "DHCID", dhcid_rdata, ALEN( dhcid_rdata) },
940 { "NSEC3", nsec3_rdata, ALEN( nsec3_rdata) },
941 { "NSEC3PARAM", nsec3param_rdata, ALEN(nsec3param_rdata) },
942 { "TLSA", tlsa_rdata, ALEN( tlsa_rdata) },
943 { "SMIMEA", tlsa_rdata, ALEN( tlsa_rdata) }, /* - 53 */
944 { NULL, NULL, 0 },
945 { "HIP", hip_rdata, ALEN( hip_rdata) }, /* 55 - */
946 { "NINFO", UNKNOWN_RDATA, 0 },
947 { "RKEY", UNKNOWN_RDATA, 0 },
948 { "TALINK", talink_rdata, ALEN( talink_rdata) },
949 { "CDS", ds_rdata, ALEN( ds_rdata) },
950 { "CDNSKEY", dnskey_rdata, ALEN( dnskey_rdata) },
951 { "OPENPGPKEY", openpgpkey_rdata, ALEN(openpgpkey_rdata) },
952 { "CSYNC", csync_rdata, ALEN( csync_rdata) },
953 { "ZONEMD", zonemd_rdata, ALEN( zonemd_rdata) }, /* - 63 */
954 { NULL, NULL, 0 },
955 { NULL, NULL, 0 },
956 { NULL, NULL, 0 },
957 { NULL, NULL, 0 },
958 { NULL, NULL, 0 },
959 { NULL, NULL, 0 },
960 { NULL, NULL, 0 },
961 { NULL, NULL, 0 },
962 { NULL, NULL, 0 },
963 { NULL, NULL, 0 },
964 { NULL, NULL, 0 },
965 { NULL, NULL, 0 },
966 { NULL, NULL, 0 },
967 { NULL, NULL, 0 },
968 { NULL, NULL, 0 },
969 { NULL, NULL, 0 },
970 { NULL, NULL, 0 },
971 { NULL, NULL, 0 },
972 { NULL, NULL, 0 },
973 { NULL, NULL, 0 },
974 { NULL, NULL, 0 },
975 { NULL, NULL, 0 },
976 { NULL, NULL, 0 },
977 { NULL, NULL, 0 },
978 { NULL, NULL, 0 },
979 { NULL, NULL, 0 },
980 { NULL, NULL, 0 },
981 { NULL, NULL, 0 },
982 { NULL, NULL, 0 },
983 { NULL, NULL, 0 },
984 { NULL, NULL, 0 },
985 { NULL, NULL, 0 },
986 { NULL, NULL, 0 },
987 { NULL, NULL, 0 },
988 { NULL, NULL, 0 },
989 { "SPF", spf_rdata, ALEN( spf_rdata) }, /* 99 - */
990 { "UINFO", UNKNOWN_RDATA, 0 },
991 { "UID", UNKNOWN_RDATA, 0 },
992 { "GID", UNKNOWN_RDATA, 0 },
993 { "UNSPEC", UNKNOWN_RDATA, 0 },
994 { "NID", nid_rdata, ALEN( nid_rdata) },
995 { "L32", l32_rdata, ALEN( l32_rdata) },
996 { "L64", l64_rdata, ALEN( l64_rdata) },
997 { "LP", lp_rdata, ALEN( lp_rdata) },
998 { "EUI48", eui48_rdata, ALEN( eui48_rdata) },
999 { "EUI64", eui64_rdata, ALEN( eui64_rdata) }, /* - 109 */
1000 { NULL, NULL, 0 },
1001 { NULL, NULL, 0 },
1002 { NULL, NULL, 0 },
1003 { NULL, NULL, 0 },
1004 { NULL, NULL, 0 },
1005 { NULL, NULL, 0 },
1006 { NULL, NULL, 0 },
1007 { NULL, NULL, 0 },
1008 { NULL, NULL, 0 },
1009 { NULL, NULL, 0 },
1010 { NULL, NULL, 0 },
1011 { NULL, NULL, 0 },
1012 { NULL, NULL, 0 },
1013 { NULL, NULL, 0 },
1014 { NULL, NULL, 0 },
1015 { NULL, NULL, 0 },
1016 { NULL, NULL, 0 },
1017 { NULL, NULL, 0 },
1018 { NULL, NULL, 0 },
1019 { NULL, NULL, 0 },
1020 { NULL, NULL, 0 },
1021 { NULL, NULL, 0 },
1022 { NULL, NULL, 0 },
1023 { NULL, NULL, 0 },
1024 { NULL, NULL, 0 },
1025 { NULL, NULL, 0 },
1026 { NULL, NULL, 0 },
1027 { NULL, NULL, 0 },
1028 { NULL, NULL, 0 },
1029 { NULL, NULL, 0 },
1030 { NULL, NULL, 0 },
1031 { NULL, NULL, 0 },
1032 { NULL, NULL, 0 },
1033 { NULL, NULL, 0 },
1034 { NULL, NULL, 0 },
1035 { NULL, NULL, 0 },
1036 { NULL, NULL, 0 },
1037 { NULL, NULL, 0 },
1038 { NULL, NULL, 0 },
1039 { NULL, NULL, 0 },
1040 { NULL, NULL, 0 },
1041 { NULL, NULL, 0 },
1042 { NULL, NULL, 0 },
1043 { NULL, NULL, 0 },
1044 { NULL, NULL, 0 },
1045 { NULL, NULL, 0 },
1046 { NULL, NULL, 0 },
1047 { NULL, NULL, 0 },
1048 { NULL, NULL, 0 },
1049 { NULL, NULL, 0 },
1050 { NULL, NULL, 0 },
1051 { NULL, NULL, 0 },
1052 { NULL, NULL, 0 },
1053 { NULL, NULL, 0 },
1054 { NULL, NULL, 0 },
1055 { NULL, NULL, 0 },
1056 { NULL, NULL, 0 },
1057 { NULL, NULL, 0 },
1058 { NULL, NULL, 0 },
1059 { NULL, NULL, 0 },
1060 { NULL, NULL, 0 },
1061 { NULL, NULL, 0 },
1062 { NULL, NULL, 0 },
1063 { NULL, NULL, 0 },
1064 { NULL, NULL, 0 },
1065 { NULL, NULL, 0 },
1066 { NULL, NULL, 0 },
1067 { NULL, NULL, 0 },
1068 { NULL, NULL, 0 },
1069 { NULL, NULL, 0 },
1070 { NULL, NULL, 0 },
1071 { NULL, NULL, 0 },
1072 { NULL, NULL, 0 },
1073 { NULL, NULL, 0 },
1074 { NULL, NULL, 0 },
1075 { NULL, NULL, 0 },
1076 { NULL, NULL, 0 },
1077 { NULL, NULL, 0 },
1078 { NULL, NULL, 0 },
1079 { NULL, NULL, 0 },
1080 { NULL, NULL, 0 },
1081 { NULL, NULL, 0 },
1082 { NULL, NULL, 0 },
1083 { NULL, NULL, 0 },
1084 { NULL, NULL, 0 },
1085 { NULL, NULL, 0 },
1086 { NULL, NULL, 0 },
1087 { NULL, NULL, 0 },
1088 { NULL, NULL, 0 },
1089 { NULL, NULL, 0 },
1090 { NULL, NULL, 0 },
1091 { NULL, NULL, 0 },
1092 { NULL, NULL, 0 },
1093 { NULL, NULL, 0 },
1094 { NULL, NULL, 0 },
1095 { NULL, NULL, 0 },
1096 { NULL, NULL, 0 },
1097 { NULL, NULL, 0 },
1098 { NULL, NULL, 0 },
1099 { NULL, NULL, 0 },
1100 { NULL, NULL, 0 },
1101 { NULL, NULL, 0 },
1102 { NULL, NULL, 0 },
1103 { NULL, NULL, 0 },
1104 { NULL, NULL, 0 },
1105 { NULL, NULL, 0 },
1106 { NULL, NULL, 0 },
1107 { NULL, NULL, 0 },
1108 { NULL, NULL, 0 },
1109 { NULL, NULL, 0 },
1110 { NULL, NULL, 0 },
1111 { NULL, NULL, 0 },
1112 { NULL, NULL, 0 },
1113 { NULL, NULL, 0 },
1114 { NULL, NULL, 0 },
1115 { NULL, NULL, 0 },
1116 { NULL, NULL, 0 },
1117 { NULL, NULL, 0 },
1118 { NULL, NULL, 0 },
1119 { NULL, NULL, 0 },
1120 { NULL, NULL, 0 },
1121 { NULL, NULL, 0 },
1122 { NULL, NULL, 0 },
1123 { NULL, NULL, 0 },
1124 { NULL, NULL, 0 },
1125 { NULL, NULL, 0 },
1126 { NULL, NULL, 0 },
1127 { NULL, NULL, 0 },
1128 { NULL, NULL, 0 },
1129 { NULL, NULL, 0 },
1130 { NULL, NULL, 0 },
1131 { NULL, NULL, 0 },
1132 { NULL, NULL, 0 },
1133 { NULL, NULL, 0 },
1134 { NULL, NULL, 0 },
1135 { NULL, NULL, 0 },
1136 { NULL, NULL, 0 },
1137 { NULL, NULL, 0 },
1138 { NULL, NULL, 0 },
1139 { "TKEY", tkey_rdata, ALEN( tkey_rdata) }, /* 249 - */
1140 { "TSIG", tsig_rdata, ALEN( tsig_rdata) }, /* - 250 */
1141 { NULL, NULL, 0 },
1142 { NULL, NULL, 0 },
1143 { "MAILB", UNKNOWN_RDATA, 0 }, /* 253 - */
1144 { "MAILA", UNKNOWN_RDATA, 0 }, /* - 254 */
1145 { NULL, NULL, 0 },
1146 { "URI", uri_rdata, ALEN( uri_rdata) }, /* 256 - */
1147 { "CAA", caa_rdata, ALEN( caa_rdata) },
1148 { "AVC", txt_rdata, ALEN( txt_rdata) },
1149 { "DOA", doa_rdata, ALEN( doa_rdata) },
1150 { "AMTRELAY", amtrelay_rdata, ALEN( amtrelay_rdata) }, /* - 260 */
1151 { "TA", ds_rdata, ALEN( ds_rdata) }, /* 32768 */
1152 { "DLV", dlv_rdata, ALEN( dlv_rdata) } /* 32769 */
1153 };
1154
1155 const _getdns_rr_def *
_getdns_rr_def_lookup(uint16_t rr_type)1156 _getdns_rr_def_lookup(uint16_t rr_type)
1157 {
1158 if (rr_type <= 260)
1159 return &_getdns_rr_defs[rr_type];
1160 else if (rr_type == 32768)
1161 return &_getdns_rr_defs[261];
1162 else if (rr_type == 32769)
1163 return &_getdns_rr_defs[262];
1164 return _getdns_rr_defs;
1165 }
1166
1167 const char *
_getdns_rr_type_name(int rr_type)1168 _getdns_rr_type_name(int rr_type)
1169 {
1170 return _getdns_rr_def_lookup(rr_type)->name;
1171 }
1172
1173 static void
write_int_rdata(gldns_buffer * buf,_getdns_rdf_type type,uint32_t value)1174 write_int_rdata(gldns_buffer *buf, _getdns_rdf_type type, uint32_t value)
1175 {
1176 size_t j;
1177
1178 for (j = type & GETDNS_RDF_FIXEDSZ; j; j--)
1179 gldns_buffer_write_u8(buf,
1180 (uint8_t)(value >> (8 * (j - 1))) & 0xff);
1181 }
1182
1183 static void
write_bindata_rdata(gldns_buffer * buf,_getdns_rdf_type type,getdns_bindata * bindata)1184 write_bindata_rdata(gldns_buffer *buf,
1185 _getdns_rdf_type type, getdns_bindata *bindata)
1186 {
1187 if (type & GETDNS_RDF_LEN_VAL)
1188 write_int_rdata(buf, type >> 8, bindata->size);
1189
1190 gldns_buffer_write(buf, bindata->data, bindata->size);
1191 }
1192
1193
1194 static getdns_return_t
write_rdata_field(gldns_buffer * buf,uint8_t * rdata_start,const _getdns_rdata_def * rd_def,getdns_dict * rdata)1195 write_rdata_field(gldns_buffer *buf, uint8_t *rdata_start,
1196 const _getdns_rdata_def *rd_def, getdns_dict *rdata)
1197 {
1198 getdns_return_t r;
1199 getdns_list *list;
1200 uint32_t value;
1201 getdns_bindata *bindata;
1202 size_t i, rdf_len;
1203
1204 if (rd_def->type & GETDNS_RDF_INTEGER) {
1205 if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1206 if ((r = getdns_dict_get_int(
1207 rdata, rd_def->name, &value)))
1208 return r;
1209 else
1210 write_int_rdata(buf, rd_def->type, value);
1211
1212 } else if ((r = getdns_dict_get_list(
1213 rdata, rd_def->name, &list)))
1214
1215 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1216 ? GETDNS_RETURN_GOOD : r;
1217
1218 else for ( i = 0
1219 ; GETDNS_RETURN_GOOD ==
1220 (r = getdns_list_get_int(list, i, &value))
1221 ; i++)
1222 write_int_rdata(buf, rd_def->type, value);
1223
1224
1225 } else if (rd_def->type & GETDNS_RDF_BINDATA) {
1226
1227
1228 if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1229 if ((r = getdns_dict_get_bindata(
1230 rdata, rd_def->name, &bindata)))
1231 return r;
1232 else
1233 write_bindata_rdata(buf, rd_def->type, bindata);
1234
1235 } else if ((r = getdns_dict_get_list(
1236 rdata, rd_def->name, &list)))
1237
1238 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1239 ? GETDNS_RETURN_GOOD : r;
1240
1241 else for ( i = 0
1242 ; GETDNS_RETURN_GOOD ==
1243 (r = getdns_list_get_bindata(list, i, &bindata))
1244 ; i++)
1245 write_bindata_rdata(buf, rd_def->type, bindata);
1246
1247
1248 } else if (!(rd_def->type & GETDNS_RDF_SPECIAL)) {
1249 /* Unknown rdata type */
1250 return GETDNS_RETURN_GENERIC_ERROR;
1251
1252 } else if (!(rd_def->type & GETDNS_RDF_REPEAT)) {
1253 /*
1254 * Non repetitive special rdatafield,
1255 * We must have a dict2wire function
1256 */
1257 assert(rd_def->special->dict2wire);
1258
1259 rdf_len = gldns_buffer_remaining(buf);
1260 r = rd_def->special->dict2wire(rdata, rdata_start,
1261 gldns_buffer_current(buf), &rdf_len);
1262 if (r == GETDNS_RETURN_GOOD ||
1263 r == GETDNS_RETURN_NEED_MORE_SPACE)
1264 gldns_buffer_skip(buf, rdf_len);
1265 if (r)
1266 return r;
1267
1268 /* We do not have repetitive special rdata fields (yet)
1269 *
1270 * LCOV_EXCL_START
1271 */
1272 } else if ((r = getdns_dict_get_list(rdata, rd_def->name, &list))) {
1273
1274 return r == GETDNS_RETURN_NO_SUCH_DICT_NAME
1275 ? GETDNS_RETURN_GOOD : r;
1276
1277 } else for ( i = 0; r == GETDNS_RETURN_GOOD; i++ ) {
1278 /*
1279 * A repetitive special rdata field must have the list2wire
1280 * function.
1281 */
1282 assert(rd_def->special->list2wire);
1283
1284 rdf_len = gldns_buffer_remaining(buf);
1285 r = rd_def->special->list2wire(list, i, rdata_start,
1286 gldns_buffer_current(buf), &rdf_len);
1287 if (r == GETDNS_RETURN_GOOD ||
1288 r == GETDNS_RETURN_NEED_MORE_SPACE)
1289 gldns_buffer_skip(buf, rdf_len);
1290 }
1291 /* LCOV_EXCL_STOP */
1292
1293 return r != GETDNS_RETURN_NO_SUCH_LIST_ITEM ? r : GETDNS_RETURN_GOOD;
1294 }
1295
1296 getdns_return_t
_getdns_rr_dict2wire(const getdns_dict * rr_dict,gldns_buffer * buf)1297 _getdns_rr_dict2wire(const getdns_dict *rr_dict, gldns_buffer *buf)
1298 {
1299 getdns_return_t r = GETDNS_RETURN_GOOD;
1300 getdns_bindata root = { 1, (void *)"" };
1301 getdns_bindata *name;
1302 getdns_bindata *rdata_raw;
1303 getdns_dict *rdata;
1304 uint32_t rr_type;
1305 uint32_t rr_class = GETDNS_RRCLASS_IN;
1306 uint32_t rr_ttl = 0;
1307 uint32_t value;
1308 const _getdns_rr_def *rr_def;
1309 const _getdns_rdata_def *rd_def, *rep_rd_def;
1310 int n_rdata_fields, rep_n_rdata_fields;
1311 size_t rdata_size_mark;
1312 uint8_t *rdata_start;
1313 getdns_list *list;
1314 size_t i;
1315
1316 assert(rr_dict);
1317 assert(buf);
1318
1319 if ((r = getdns_dict_get_int(rr_dict, "type", &rr_type)))
1320 return r;
1321 if ((r = getdns_dict_get_bindata(rr_dict, "name", &name))) {
1322 if (r == GETDNS_RETURN_NO_SUCH_DICT_NAME &&
1323 rr_type == GETDNS_RRTYPE_OPT) {
1324 name = &root;
1325 } else
1326 return r;
1327 }
1328 gldns_buffer_write(buf, name->data, name->size);
1329 gldns_buffer_write_u16(buf, (uint16_t)rr_type);
1330
1331 (void) getdns_dict_get_int(rr_dict, "class", &rr_class);
1332 if (rr_type == GETDNS_RRTYPE_OPT)
1333 (void) getdns_dict_get_int(
1334 rr_dict, "udp_payload_size", &rr_class);
1335 gldns_buffer_write_u16(buf, (uint16_t)rr_class);
1336
1337 (void) getdns_dict_get_int(rr_dict, "ttl", &rr_ttl);
1338 if (rr_type == GETDNS_RRTYPE_OPT) {
1339 if (!getdns_dict_get_int(rr_dict, "extended_rcode", &value))
1340 rr_ttl = (rr_ttl & 0x00FFFFFF)|((value & 0xFF) << 24);
1341 if (!getdns_dict_get_int(rr_dict, "version", &value))
1342 rr_ttl = (rr_ttl & 0xFF00FFFF)|((value & 0xFF) << 16);
1343 if (!getdns_dict_get_int(rr_dict, "z", &value))
1344 rr_ttl = (rr_ttl & 0xFFFF0000)| (value & 0xFFFF);
1345 if (!getdns_dict_get_int(rr_dict, "do", &value))
1346 rr_ttl = (rr_ttl & 0xFFFF7FFF)| (value ? 0x8000 : 0);
1347 }
1348 gldns_buffer_write_u32(buf, rr_ttl);
1349
1350 /* Does rdata contain compressed names?
1351 * Because rdata_raw is unusable then.
1352 */
1353 rr_def = _getdns_rr_def_lookup(rr_type);
1354 for ( rd_def = rr_def->rdata
1355 , n_rdata_fields = rr_def->n_rdata_fields
1356 ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
1357
1358 if (rd_def->type & GETDNS_RDF_COMPRESSED)
1359 break;
1360 }
1361
1362 if ((r = getdns_dict_get_dict(rr_dict, "rdata", &rdata))) {
1363 if (r == GETDNS_RETURN_NO_SUCH_DICT_NAME) {
1364 gldns_buffer_write_u16(buf, 0);
1365 r = GETDNS_RETURN_GOOD;
1366 }
1367
1368 } else if (n_rdata_fields == 0 && GETDNS_RETURN_GOOD ==
1369 (r = getdns_dict_get_bindata(rdata, "rdata_raw", &rdata_raw))) {
1370
1371 gldns_buffer_write_u16(buf, (uint16_t)rdata_raw->size);
1372 gldns_buffer_write(buf, rdata_raw->data, rdata_raw->size);
1373
1374 } else if (n_rdata_fields || r == GETDNS_RETURN_NO_SUCH_DICT_NAME) {
1375
1376 r = GETDNS_RETURN_GOOD;
1377 rdata_size_mark = gldns_buffer_position(buf);
1378 gldns_buffer_skip(buf, 2);
1379 rdata_start = gldns_buffer_current(buf);
1380
1381 for ( rd_def = rr_def->rdata
1382 , n_rdata_fields = rr_def->n_rdata_fields
1383 ; n_rdata_fields ; n_rdata_fields-- , rd_def++ ) {
1384
1385 if (rd_def->type == GETDNS_RDF_REPEAT)
1386 break;
1387
1388 if ((r = write_rdata_field(buf,
1389 rdata_start, rd_def, rdata)))
1390 break;
1391 }
1392 if (n_rdata_fields == 0 || r) {
1393 /* pass */;
1394
1395 } else if ((r = getdns_dict_get_list(
1396 rdata, rd_def->name, &list))) {
1397 /* pass */;
1398
1399 } else for ( i = 0
1400 ; r == GETDNS_RETURN_GOOD
1401 ; i++) {
1402
1403 if ((r = getdns_list_get_dict(list, i, &rdata))) {
1404 if (r == GETDNS_RETURN_NO_SUCH_LIST_ITEM)
1405 r = GETDNS_RETURN_GOOD;
1406 break;
1407 }
1408 for ( rep_rd_def = rd_def + 1
1409 , rep_n_rdata_fields = n_rdata_fields - 1
1410 ; rep_n_rdata_fields
1411 ; rep_n_rdata_fields--, rep_rd_def++ ) {
1412
1413 if ((r = write_rdata_field(buf,
1414 rdata_start, rep_rd_def, rdata)))
1415 break;
1416 }
1417 }
1418 gldns_buffer_write_u16_at(buf, rdata_size_mark,
1419 (uint16_t)(gldns_buffer_position(buf)-rdata_size_mark-2));
1420 }
1421 return r;
1422 }
1423
1424