1 /* MIT License
2 *
3 * Copyright (c) 2023 Brad House
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 * SPDX-License-Identifier: MIT
25 */
26 #include "ares_setup.h"
27 #include "ares.h"
28 #include "ares_private.h"
29 #include <limits.h>
30 #ifdef HAVE_STDINT_H
31 # include <stdint.h>
32 #endif
33
34
ares_dns_write_header(const ares_dns_record_t * dnsrec,ares__buf_t * buf)35 static ares_status_t ares_dns_write_header(const ares_dns_record_t *dnsrec,
36 ares__buf_t *buf)
37 {
38 unsigned short u16;
39 unsigned short opcode;
40 unsigned short rcode;
41
42 ares_status_t status;
43
44 /* ID */
45 status = ares__buf_append_be16(buf, dnsrec->id);
46 if (status != ARES_SUCCESS) {
47 return status;
48 }
49
50 /* Flags */
51 u16 = 0;
52
53 /* QR */
54 if (dnsrec->flags & ARES_FLAG_QR) {
55 u16 |= 0x8000;
56 }
57
58 /* OPCODE */
59 opcode = (unsigned short)(dnsrec->opcode & 0xF);
60 opcode <<= 11;
61 u16 |= opcode;
62
63 /* AA */
64 if (dnsrec->flags & ARES_FLAG_AA) {
65 u16 |= 0x400;
66 }
67
68 /* TC */
69 if (dnsrec->flags & ARES_FLAG_TC) {
70 u16 |= 0x200;
71 }
72
73 /* RD */
74 if (dnsrec->flags & ARES_FLAG_RD) {
75 u16 |= 0x100;
76 }
77
78 /* RA */
79 if (dnsrec->flags & ARES_FLAG_RA) {
80 u16 |= 0x80;
81 }
82
83 /* Z -- unused */
84
85 /* AD */
86 if (dnsrec->flags & ARES_FLAG_AD) {
87 u16 |= 0x20;
88 }
89
90 /* CD */
91 if (dnsrec->flags & ARES_FLAG_CD) {
92 u16 |= 0x10;
93 }
94
95 /* RCODE */
96 if (dnsrec->rcode > 15 && !ares_dns_has_opt_rr(dnsrec)) {
97 /* Must have OPT RR in order to write extended error codes */
98 rcode = ARES_RCODE_SERVFAIL;
99 } else {
100 rcode = (unsigned short)(dnsrec->rcode & 0xF);
101 }
102 u16 |= rcode;
103
104 status = ares__buf_append_be16(buf, u16);
105 if (status != ARES_SUCCESS) {
106 return status;
107 }
108
109 /* QDCOUNT */
110 status = ares__buf_append_be16(buf, (unsigned short)dnsrec->qdcount);
111 if (status != ARES_SUCCESS) {
112 return status;
113 }
114
115 /* ANCOUNT */
116 status = ares__buf_append_be16(buf, (unsigned short)dnsrec->ancount);
117 if (status != ARES_SUCCESS) {
118 return status;
119 }
120
121 /* NSCOUNT */
122 status = ares__buf_append_be16(buf, (unsigned short)dnsrec->nscount);
123 if (status != ARES_SUCCESS) {
124 return status;
125 }
126
127 /* ARCOUNT */
128 status = ares__buf_append_be16(buf, (unsigned short)dnsrec->arcount);
129 if (status != ARES_SUCCESS) {
130 return status;
131 }
132
133 return ARES_SUCCESS;
134 }
135
ares_dns_write_questions(const ares_dns_record_t * dnsrec,ares__llist_t ** namelist,ares__buf_t * buf)136 static ares_status_t ares_dns_write_questions(const ares_dns_record_t *dnsrec,
137 ares__llist_t **namelist,
138 ares__buf_t *buf)
139 {
140 size_t i;
141
142 for (i = 0; i < ares_dns_record_query_cnt(dnsrec); i++) {
143 ares_status_t status;
144 const char *name = NULL;
145 ares_dns_rec_type_t qtype;
146 ares_dns_class_t qclass;
147
148 status = ares_dns_record_query_get(dnsrec, i, &name, &qtype, &qclass);
149 if (status != ARES_SUCCESS) {
150 return status;
151 }
152
153 /* Name */
154 status = ares__dns_name_write(buf, namelist, ARES_TRUE, name);
155 if (status != ARES_SUCCESS) {
156 return status;
157 }
158
159 /* Type */
160 status = ares__buf_append_be16(buf, (unsigned short)qtype);
161 if (status != ARES_SUCCESS) {
162 return status;
163 }
164
165 /* Class */
166 status = ares__buf_append_be16(buf, (unsigned short)qclass);
167 if (status != ARES_SUCCESS) {
168 return status;
169 }
170 }
171
172 return ARES_SUCCESS;
173 }
174
ares_dns_write_rr_name(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist,ares_bool_t validate_hostname,ares_dns_rr_key_t key)175 static ares_status_t ares_dns_write_rr_name(ares__buf_t *buf,
176 const ares_dns_rr_t *rr,
177 ares__llist_t **namelist,
178 ares_bool_t validate_hostname,
179 ares_dns_rr_key_t key)
180 {
181 const char *name;
182
183 name = ares_dns_rr_get_str(rr, key);
184 if (name == NULL) {
185 return ARES_EFORMERR;
186 }
187
188 return ares__dns_name_write(buf, namelist, validate_hostname, name);
189 }
190
ares_dns_write_rr_str(ares__buf_t * buf,const ares_dns_rr_t * rr,ares_dns_rr_key_t key)191 static ares_status_t ares_dns_write_rr_str(ares__buf_t *buf,
192 const ares_dns_rr_t *rr,
193 ares_dns_rr_key_t key)
194 {
195 const char *str;
196 size_t len;
197 ares_status_t status;
198
199 str = ares_dns_rr_get_str(rr, key);
200 if (str == NULL) {
201 return ARES_EFORMERR;
202 }
203
204 len = ares_strlen(str);
205 if (len > 255) {
206 return ARES_EFORMERR;
207 }
208
209 /* Write 1 byte length */
210 status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
211 if (status != ARES_SUCCESS) {
212 return status;
213 }
214
215 if (len == 0) {
216 return ARES_SUCCESS;
217 }
218
219 /* Write string */
220 return ares__buf_append(buf, (const unsigned char *)str, len);
221 }
222
ares_dns_write_rr_binstrs(ares__buf_t * buf,const ares_dns_rr_t * rr,ares_dns_rr_key_t key)223 static ares_status_t ares_dns_write_rr_binstrs(ares__buf_t *buf,
224 const ares_dns_rr_t *rr,
225 ares_dns_rr_key_t key)
226 {
227 const unsigned char *bin;
228 const unsigned char *ptr;
229 size_t bin_len;
230 size_t ptr_len;
231 ares_status_t status;
232
233 bin = ares_dns_rr_get_bin(rr, key, &bin_len);
234 if (bin == NULL) {
235 return ARES_EFORMERR;
236 }
237 /* split into possible multiple 255-byte or less length strings */
238 ptr = bin;
239 ptr_len = bin_len;
240 do {
241 size_t len = ptr_len;
242 if (len > 255) {
243 len = 255;
244 }
245
246 /* Length */
247 status = ares__buf_append_byte(buf, (unsigned char)(len & 0xFF));
248 if (status != ARES_SUCCESS) {
249 return status;
250 }
251
252 /* String */
253 if (len) {
254 status = ares__buf_append(buf, ptr, len);
255 if (status != ARES_SUCCESS) {
256 return status;
257 }
258 }
259
260 ptr += len;
261 ptr_len -= len;
262 } while (ptr_len > 0);
263
264 return ARES_SUCCESS;
265 }
266
ares_dns_write_rr_be32(ares__buf_t * buf,const ares_dns_rr_t * rr,ares_dns_rr_key_t key)267 static ares_status_t ares_dns_write_rr_be32(ares__buf_t *buf,
268 const ares_dns_rr_t *rr,
269 ares_dns_rr_key_t key)
270 {
271 if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U32) {
272 return ARES_EFORMERR;
273 }
274 return ares__buf_append_be32(buf, ares_dns_rr_get_u32(rr, key));
275 }
276
ares_dns_write_rr_be16(ares__buf_t * buf,const ares_dns_rr_t * rr,ares_dns_rr_key_t key)277 static ares_status_t ares_dns_write_rr_be16(ares__buf_t *buf,
278 const ares_dns_rr_t *rr,
279 ares_dns_rr_key_t key)
280 {
281 if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U16) {
282 return ARES_EFORMERR;
283 }
284 return ares__buf_append_be16(buf, ares_dns_rr_get_u16(rr, key));
285 }
286
ares_dns_write_rr_u8(ares__buf_t * buf,const ares_dns_rr_t * rr,ares_dns_rr_key_t key)287 static ares_status_t ares_dns_write_rr_u8(ares__buf_t *buf,
288 const ares_dns_rr_t *rr,
289 ares_dns_rr_key_t key)
290 {
291 if (ares_dns_rr_key_datatype(key) != ARES_DATATYPE_U8) {
292 return ARES_EFORMERR;
293 }
294 return ares__buf_append_byte(buf, ares_dns_rr_get_u8(rr, key));
295 }
296
ares_dns_write_rr_a(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)297 static ares_status_t ares_dns_write_rr_a(ares__buf_t *buf,
298 const ares_dns_rr_t *rr,
299 ares__llist_t **namelist)
300 {
301 const struct in_addr *addr;
302 (void)namelist;
303
304 addr = ares_dns_rr_get_addr(rr, ARES_RR_A_ADDR);
305 if (addr == NULL) {
306 return ARES_EFORMERR;
307 }
308
309 return ares__buf_append(buf, (const unsigned char *)addr, sizeof(*addr));
310 }
311
ares_dns_write_rr_ns(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)312 static ares_status_t ares_dns_write_rr_ns(ares__buf_t *buf,
313 const ares_dns_rr_t *rr,
314 ares__llist_t **namelist)
315 {
316 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
317 ARES_RR_NS_NSDNAME);
318 }
319
ares_dns_write_rr_cname(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)320 static ares_status_t ares_dns_write_rr_cname(ares__buf_t *buf,
321 const ares_dns_rr_t *rr,
322 ares__llist_t **namelist)
323 {
324 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
325 ARES_RR_CNAME_CNAME);
326 }
327
ares_dns_write_rr_soa(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)328 static ares_status_t ares_dns_write_rr_soa(ares__buf_t *buf,
329 const ares_dns_rr_t *rr,
330 ares__llist_t **namelist)
331 {
332 ares_status_t status;
333
334 /* MNAME */
335 status =
336 ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE, ARES_RR_SOA_MNAME);
337 if (status != ARES_SUCCESS) {
338 return status;
339 }
340
341 /* RNAME */
342 status =
343 ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE, ARES_RR_SOA_RNAME);
344 if (status != ARES_SUCCESS) {
345 return status;
346 }
347
348 /* SERIAL */
349 status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_SERIAL);
350 if (status != ARES_SUCCESS) {
351 return status;
352 }
353
354 /* REFRESH */
355 status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_REFRESH);
356 if (status != ARES_SUCCESS) {
357 return status;
358 }
359
360 /* RETRY */
361 status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_RETRY);
362 if (status != ARES_SUCCESS) {
363 return status;
364 }
365
366 /* EXPIRE */
367 status = ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_EXPIRE);
368 if (status != ARES_SUCCESS) {
369 return status;
370 }
371
372 /* MINIMUM */
373 return ares_dns_write_rr_be32(buf, rr, ARES_RR_SOA_MINIMUM);
374 }
375
ares_dns_write_rr_ptr(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)376 static ares_status_t ares_dns_write_rr_ptr(ares__buf_t *buf,
377 const ares_dns_rr_t *rr,
378 ares__llist_t **namelist)
379 {
380 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
381 ARES_RR_PTR_DNAME);
382 }
383
ares_dns_write_rr_hinfo(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)384 static ares_status_t ares_dns_write_rr_hinfo(ares__buf_t *buf,
385 const ares_dns_rr_t *rr,
386 ares__llist_t **namelist)
387 {
388 ares_status_t status;
389
390 (void)namelist;
391
392 /* CPU */
393 status = ares_dns_write_rr_str(buf, rr, ARES_RR_HINFO_CPU);
394 if (status != ARES_SUCCESS) {
395 return status;
396 }
397
398 /* OS */
399 return ares_dns_write_rr_str(buf, rr, ARES_RR_HINFO_OS);
400 }
401
ares_dns_write_rr_mx(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)402 static ares_status_t ares_dns_write_rr_mx(ares__buf_t *buf,
403 const ares_dns_rr_t *rr,
404 ares__llist_t **namelist)
405 {
406 ares_status_t status;
407
408 /* PREFERENCE */
409 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_MX_PREFERENCE);
410 if (status != ARES_SUCCESS) {
411 return status;
412 }
413
414 /* EXCHANGE */
415 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
416 ARES_RR_MX_EXCHANGE);
417 }
418
ares_dns_write_rr_txt(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)419 static ares_status_t ares_dns_write_rr_txt(ares__buf_t *buf,
420 const ares_dns_rr_t *rr,
421 ares__llist_t **namelist)
422 {
423 (void)namelist;
424 return ares_dns_write_rr_binstrs(buf, rr, ARES_RR_TXT_DATA);
425 }
426
ares_dns_write_rr_aaaa(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)427 static ares_status_t ares_dns_write_rr_aaaa(ares__buf_t *buf,
428 const ares_dns_rr_t *rr,
429 ares__llist_t **namelist)
430 {
431 const struct ares_in6_addr *addr;
432 (void)namelist;
433
434 addr = ares_dns_rr_get_addr6(rr, ARES_RR_AAAA_ADDR);
435 if (addr == NULL) {
436 return ARES_EFORMERR;
437 }
438
439 return ares__buf_append(buf, (const unsigned char *)addr, sizeof(*addr));
440 }
441
ares_dns_write_rr_srv(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)442 static ares_status_t ares_dns_write_rr_srv(ares__buf_t *buf,
443 const ares_dns_rr_t *rr,
444 ares__llist_t **namelist)
445 {
446 ares_status_t status;
447
448 /* PRIORITY */
449 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_PRIORITY);
450 if (status != ARES_SUCCESS) {
451 return status;
452 }
453
454 /* WEIGHT */
455 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_WEIGHT);
456 if (status != ARES_SUCCESS) {
457 return status;
458 }
459
460 /* PORT */
461 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SRV_PORT);
462 if (status != ARES_SUCCESS) {
463 return status;
464 }
465
466 /* TARGET */
467 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
468 ARES_RR_SRV_TARGET);
469 }
470
ares_dns_write_rr_naptr(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)471 static ares_status_t ares_dns_write_rr_naptr(ares__buf_t *buf,
472 const ares_dns_rr_t *rr,
473 ares__llist_t **namelist)
474 {
475 ares_status_t status;
476
477 /* ORDER */
478 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_NAPTR_ORDER);
479 if (status != ARES_SUCCESS) {
480 return status;
481 }
482
483 /* PREFERENCE */
484 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_NAPTR_PREFERENCE);
485 if (status != ARES_SUCCESS) {
486 return status;
487 }
488
489 /* FLAGS */
490 status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_FLAGS);
491 if (status != ARES_SUCCESS) {
492 return status;
493 }
494
495 /* SERVICES */
496 status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_SERVICES);
497 if (status != ARES_SUCCESS) {
498 return status;
499 }
500
501 /* REGEXP */
502 status = ares_dns_write_rr_str(buf, rr, ARES_RR_NAPTR_REGEXP);
503 if (status != ARES_SUCCESS) {
504 return status;
505 }
506
507 /* REPLACEMENT */
508 return ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE,
509 ARES_RR_NAPTR_REPLACEMENT);
510 }
511
ares_dns_write_rr_opt(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)512 static ares_status_t ares_dns_write_rr_opt(ares__buf_t *buf,
513 const ares_dns_rr_t *rr,
514 ares__llist_t **namelist)
515 {
516 size_t len = ares__buf_len(buf);
517 ares_status_t status;
518 unsigned int ttl = 0;
519 size_t i;
520 unsigned short rcode = (unsigned short)((rr->parent->rcode >> 4) & 0xFF);
521
522 (void)namelist;
523
524 /* We need to go back and overwrite the class and ttl that were emitted as
525 * the OPT record overloads them for its own use (yes, very strange!) */
526 status = ares__buf_set_length(buf, len - 2 /* RDLENGTH */
527 - 4 /* TTL */
528 - 2 /* CLASS */);
529 if (status != ARES_SUCCESS) {
530 return status;
531 }
532
533 /* Class -> UDP Size */
534 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_OPT_UDP_SIZE);
535 if (status != ARES_SUCCESS) {
536 return status;
537 }
538
539 /* TTL -> rcode (u8) << 24 | version (u8) << 16 | flags (u16) */
540 ttl |= (unsigned int)rcode << 24;
541 ttl |= (unsigned int)ares_dns_rr_get_u8(rr, ARES_RR_OPT_VERSION) << 16;
542 ttl |= (unsigned int)ares_dns_rr_get_u16(rr, ARES_RR_OPT_FLAGS);
543
544 status = ares__buf_append_be32(buf, ttl);
545 if (status != ARES_SUCCESS) {
546 return status;
547 }
548
549 /* Now go back to real end */
550 status = ares__buf_set_length(buf, len);
551 if (status != ARES_SUCCESS) {
552 return status;
553 }
554
555 /* Append Options */
556 for (i = 0; i < ares_dns_rr_get_opt_cnt(rr, ARES_RR_OPT_OPTIONS); i++) {
557 unsigned short opt;
558 size_t val_len;
559 const unsigned char *val;
560
561 opt = ares_dns_rr_get_opt(rr, ARES_RR_OPT_OPTIONS, i, &val, &val_len);
562
563 /* BE16 option */
564 status = ares__buf_append_be16(buf, opt);
565 if (status != ARES_SUCCESS) {
566 return status;
567 }
568
569 /* BE16 length */
570 status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
571 if (status != ARES_SUCCESS) {
572 return status;
573 }
574
575 /* Value */
576 if (val && val_len) {
577 status = ares__buf_append(buf, val, val_len);
578 if (status != ARES_SUCCESS) {
579 return status;
580 }
581 }
582 }
583
584 return ARES_SUCCESS;
585 }
586
ares_dns_write_rr_tlsa(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)587 static ares_status_t ares_dns_write_rr_tlsa(ares__buf_t *buf,
588 const ares_dns_rr_t *rr,
589 ares__llist_t **namelist)
590 {
591 ares_status_t status;
592 const unsigned char *data;
593 size_t len = 0;
594
595 (void)namelist;
596
597 /* CERT_USAGE */
598 status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_CERT_USAGE);
599 if (status != ARES_SUCCESS) {
600 return status;
601 }
602
603 /* SELECTOR */
604 status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_SELECTOR);
605 if (status != ARES_SUCCESS) {
606 return status;
607 }
608
609 /* MATCH */
610 status = ares_dns_write_rr_u8(buf, rr, ARES_RR_TLSA_MATCH);
611 if (status != ARES_SUCCESS) {
612 return status;
613 }
614
615 /* DATA -- binary, rest of buffer, required to be non-zero length */
616 data = ares_dns_rr_get_bin(rr, ARES_RR_TLSA_DATA, &len);
617 if (data == NULL || len == 0) {
618 return ARES_EFORMERR;
619 }
620
621 return ares__buf_append(buf, data, len);
622 }
623
ares_dns_write_rr_svcb(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)624 static ares_status_t ares_dns_write_rr_svcb(ares__buf_t *buf,
625 const ares_dns_rr_t *rr,
626 ares__llist_t **namelist)
627 {
628 ares_status_t status;
629 size_t i;
630
631 /* PRIORITY */
632 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_SVCB_PRIORITY);
633 if (status != ARES_SUCCESS) {
634 return status;
635 }
636
637 /* TARGET */
638 status =
639 ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE, ARES_RR_SVCB_TARGET);
640 if (status != ARES_SUCCESS) {
641 return status;
642 }
643
644 /* Append Params */
645 for (i = 0; i < ares_dns_rr_get_opt_cnt(rr, ARES_RR_SVCB_PARAMS); i++) {
646 unsigned short opt;
647 size_t val_len;
648 const unsigned char *val;
649
650 opt = ares_dns_rr_get_opt(rr, ARES_RR_SVCB_PARAMS, i, &val, &val_len);
651
652 /* BE16 option */
653 status = ares__buf_append_be16(buf, opt);
654 if (status != ARES_SUCCESS) {
655 return status;
656 }
657
658 /* BE16 length */
659 status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
660 if (status != ARES_SUCCESS) {
661 return status;
662 }
663
664 /* Value */
665 if (val && val_len) {
666 status = ares__buf_append(buf, val, val_len);
667 if (status != ARES_SUCCESS) {
668 return status;
669 }
670 }
671 }
672 return ARES_SUCCESS;
673 }
674
ares_dns_write_rr_https(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)675 static ares_status_t ares_dns_write_rr_https(ares__buf_t *buf,
676 const ares_dns_rr_t *rr,
677 ares__llist_t **namelist)
678 {
679 ares_status_t status;
680 size_t i;
681
682 /* PRIORITY */
683 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_HTTPS_PRIORITY);
684 if (status != ARES_SUCCESS) {
685 return status;
686 }
687
688 /* TARGET */
689 status =
690 ares_dns_write_rr_name(buf, rr, namelist, ARES_FALSE, ARES_RR_HTTPS_TARGET);
691 if (status != ARES_SUCCESS) {
692 return status;
693 }
694
695 /* Append Params */
696 for (i = 0; i < ares_dns_rr_get_opt_cnt(rr, ARES_RR_HTTPS_PARAMS); i++) {
697 unsigned short opt;
698 size_t val_len;
699 const unsigned char *val;
700
701 opt = ares_dns_rr_get_opt(rr, ARES_RR_HTTPS_PARAMS, i, &val, &val_len);
702
703 /* BE16 option */
704 status = ares__buf_append_be16(buf, opt);
705 if (status != ARES_SUCCESS) {
706 return status;
707 }
708
709 /* BE16 length */
710 status = ares__buf_append_be16(buf, (unsigned short)(val_len & 0xFFFF));
711 if (status != ARES_SUCCESS) {
712 return status;
713 }
714
715 /* Value */
716 if (val && val_len) {
717 status = ares__buf_append(buf, val, val_len);
718 if (status != ARES_SUCCESS) {
719 return status;
720 }
721 }
722 }
723 return ARES_SUCCESS;
724 }
725
ares_dns_write_rr_uri(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)726 static ares_status_t ares_dns_write_rr_uri(ares__buf_t *buf,
727 const ares_dns_rr_t *rr,
728 ares__llist_t **namelist)
729 {
730 ares_status_t status;
731 const char *target;
732
733 (void)namelist;
734
735 /* PRIORITY */
736 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_URI_PRIORITY);
737 if (status != ARES_SUCCESS) {
738 return status;
739 }
740
741 /* WEIGHT */
742 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_URI_WEIGHT);
743 if (status != ARES_SUCCESS) {
744 return status;
745 }
746
747 /* TARGET -- not in DNS string format, rest of buffer, required to be
748 * non-zero length */
749 target = ares_dns_rr_get_str(rr, ARES_RR_URI_TARGET);
750 if (target == NULL || ares_strlen(target) == 0) {
751 return ARES_EFORMERR;
752 }
753
754 return ares__buf_append(buf, (const unsigned char *)target,
755 ares_strlen(target));
756 }
757
ares_dns_write_rr_caa(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)758 static ares_status_t ares_dns_write_rr_caa(ares__buf_t *buf,
759 const ares_dns_rr_t *rr,
760 ares__llist_t **namelist)
761 {
762 const unsigned char *data = NULL;
763 size_t data_len = 0;
764 ares_status_t status;
765
766 (void)namelist;
767
768 /* CRITICAL */
769 status = ares_dns_write_rr_u8(buf, rr, ARES_RR_CAA_CRITICAL);
770 if (status != ARES_SUCCESS) {
771 return status;
772 }
773
774 /* Tag */
775 status = ares_dns_write_rr_str(buf, rr, ARES_RR_CAA_TAG);
776 if (status != ARES_SUCCESS) {
777 return status;
778 }
779
780 /* Value - binary! (remaining buffer */
781 data = ares_dns_rr_get_bin(rr, ARES_RR_CAA_VALUE, &data_len);
782 if (data == NULL || data_len == 0) {
783 return ARES_EFORMERR;
784 }
785
786 return ares__buf_append(buf, data, data_len);
787 }
788
ares_dns_write_rr_raw_rr(ares__buf_t * buf,const ares_dns_rr_t * rr,ares__llist_t ** namelist)789 static ares_status_t ares_dns_write_rr_raw_rr(ares__buf_t *buf,
790 const ares_dns_rr_t *rr,
791 ares__llist_t **namelist)
792 {
793 size_t len = ares__buf_len(buf);
794 ares_status_t status;
795 const unsigned char *data = NULL;
796 size_t data_len = 0;
797
798 (void)namelist;
799
800 /* We need to go back and overwrite the type that was emitted by the parent
801 * function */
802 status = ares__buf_set_length(buf, len - 2 /* RDLENGTH */
803 - 4 /* TTL */
804 - 2 /* CLASS */
805 - 2 /* TYPE */);
806 if (status != ARES_SUCCESS) {
807 return status;
808 }
809
810 status = ares_dns_write_rr_be16(buf, rr, ARES_RR_RAW_RR_TYPE);
811 if (status != ARES_SUCCESS) {
812 return status;
813 }
814
815 /* Now go back to real end */
816 status = ares__buf_set_length(buf, len);
817 if (status != ARES_SUCCESS) {
818 return status;
819 }
820
821 /* Output raw data */
822 data = ares_dns_rr_get_bin(rr, ARES_RR_RAW_RR_DATA, &data_len);
823 if (data == NULL) {
824 return ARES_EFORMERR;
825 }
826
827 if (data_len == 0) {
828 return ARES_SUCCESS;
829 }
830
831 return ares__buf_append(buf, data, data_len);
832 }
833
ares_dns_write_rr(ares_dns_record_t * dnsrec,ares__llist_t ** namelist,ares_dns_section_t section,ares__buf_t * buf)834 static ares_status_t ares_dns_write_rr(ares_dns_record_t *dnsrec,
835 ares__llist_t **namelist,
836 ares_dns_section_t section,
837 ares__buf_t *buf)
838 {
839 size_t i;
840
841 for (i = 0; i < ares_dns_record_rr_cnt(dnsrec, section); i++) {
842 const ares_dns_rr_t *rr;
843 ares_dns_rec_type_t type;
844 ares_bool_t allow_compress;
845 ares__llist_t **namelistptr = NULL;
846 size_t pos_len;
847 ares_status_t status;
848 size_t rdlength;
849 size_t end_length;
850 unsigned int ttl;
851
852 rr = ares_dns_record_rr_get(dnsrec, section, i);
853 if (rr == NULL) {
854 return ARES_EFORMERR;
855 }
856
857 type = ares_dns_rr_get_type(rr);
858 allow_compress = ares_dns_rec_type_allow_name_compression(type);
859 if (allow_compress) {
860 namelistptr = namelist;
861 }
862
863 /* Name */
864 status =
865 ares__dns_name_write(buf, namelist, ARES_TRUE, ares_dns_rr_get_name(rr));
866 if (status != ARES_SUCCESS) {
867 return status;
868 }
869
870 /* Type */
871 status = ares__buf_append_be16(buf, (unsigned short)type);
872 if (status != ARES_SUCCESS) {
873 return status;
874 }
875
876 /* Class */
877 status =
878 ares__buf_append_be16(buf, (unsigned short)ares_dns_rr_get_class(rr));
879 if (status != ARES_SUCCESS) {
880 return status;
881 }
882
883 /* TTL */
884 ttl = ares_dns_rr_get_ttl(rr);
885 if (rr->parent->ttl_decrement > ttl) {
886 ttl = 0;
887 } else {
888 ttl -= rr->parent->ttl_decrement;
889 }
890 status = ares__buf_append_be32(buf, ttl);
891 if (status != ARES_SUCCESS) {
892 return status;
893 }
894
895 /* Length */
896 pos_len = ares__buf_len(buf); /* Save to write real length later */
897 status = ares__buf_append_be16(buf, 0);
898 if (status != ARES_SUCCESS) {
899 return status;
900 }
901
902 /* Data */
903 switch (type) {
904 case ARES_REC_TYPE_A:
905 status = ares_dns_write_rr_a(buf, rr, namelistptr);
906 break;
907 case ARES_REC_TYPE_NS:
908 status = ares_dns_write_rr_ns(buf, rr, namelistptr);
909 break;
910 case ARES_REC_TYPE_CNAME:
911 status = ares_dns_write_rr_cname(buf, rr, namelistptr);
912 break;
913 case ARES_REC_TYPE_SOA:
914 status = ares_dns_write_rr_soa(buf, rr, namelistptr);
915 break;
916 case ARES_REC_TYPE_PTR:
917 status = ares_dns_write_rr_ptr(buf, rr, namelistptr);
918 break;
919 case ARES_REC_TYPE_HINFO:
920 status = ares_dns_write_rr_hinfo(buf, rr, namelistptr);
921 break;
922 case ARES_REC_TYPE_MX:
923 status = ares_dns_write_rr_mx(buf, rr, namelistptr);
924 break;
925 case ARES_REC_TYPE_TXT:
926 status = ares_dns_write_rr_txt(buf, rr, namelistptr);
927 break;
928 case ARES_REC_TYPE_AAAA:
929 status = ares_dns_write_rr_aaaa(buf, rr, namelistptr);
930 break;
931 case ARES_REC_TYPE_SRV:
932 status = ares_dns_write_rr_srv(buf, rr, namelistptr);
933 break;
934 case ARES_REC_TYPE_NAPTR:
935 status = ares_dns_write_rr_naptr(buf, rr, namelistptr);
936 break;
937 case ARES_REC_TYPE_ANY:
938 status = ARES_EFORMERR;
939 break;
940 case ARES_REC_TYPE_OPT:
941 status = ares_dns_write_rr_opt(buf, rr, namelistptr);
942 break;
943 case ARES_REC_TYPE_TLSA:
944 status = ares_dns_write_rr_tlsa(buf, rr, namelistptr);
945 break;
946 case ARES_REC_TYPE_SVCB:
947 status = ares_dns_write_rr_svcb(buf, rr, namelistptr);
948 break;
949 case ARES_REC_TYPE_HTTPS:
950 status = ares_dns_write_rr_https(buf, rr, namelistptr);
951 break;
952 case ARES_REC_TYPE_URI:
953 status = ares_dns_write_rr_uri(buf, rr, namelistptr);
954 break;
955 case ARES_REC_TYPE_CAA:
956 status = ares_dns_write_rr_caa(buf, rr, namelistptr);
957 break;
958 case ARES_REC_TYPE_RAW_RR:
959 status = ares_dns_write_rr_raw_rr(buf, rr, namelistptr);
960 break;
961 }
962
963 if (status != ARES_SUCCESS) {
964 return status;
965 }
966
967 /* Back off write pointer, write real length, then go back to proper
968 * position */
969 end_length = ares__buf_len(buf);
970 rdlength = end_length - pos_len - 2;
971
972 status = ares__buf_set_length(buf, pos_len);
973 if (status != ARES_SUCCESS) {
974 return status;
975 }
976
977 status = ares__buf_append_be16(buf, (unsigned short)(rdlength & 0xFFFF));
978 if (status != ARES_SUCCESS) {
979 return status;
980 }
981
982 status = ares__buf_set_length(buf, end_length);
983 if (status != ARES_SUCCESS) {
984 return status;
985 }
986 }
987
988 return ARES_SUCCESS;
989 }
990
ares_dns_write(ares_dns_record_t * dnsrec,unsigned char ** buf,size_t * buf_len)991 ares_status_t ares_dns_write(ares_dns_record_t *dnsrec, unsigned char **buf,
992 size_t *buf_len)
993 {
994 ares__buf_t *b = NULL;
995 ares_status_t status;
996 ares__llist_t *namelist = NULL;
997
998 if (buf == NULL || buf_len == NULL || dnsrec == NULL) {
999 return ARES_EFORMERR;
1000 }
1001
1002 *buf = NULL;
1003 *buf_len = 0;
1004
1005 b = ares__buf_create();
1006 if (b == NULL) {
1007 return ARES_ENOMEM;
1008 }
1009
1010 status = ares_dns_write_header(dnsrec, b);
1011 if (status != ARES_SUCCESS) {
1012 goto done;
1013 }
1014
1015 status = ares_dns_write_questions(dnsrec, &namelist, b);
1016 if (status != ARES_SUCCESS) {
1017 goto done;
1018 }
1019
1020 status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ANSWER, b);
1021 if (status != ARES_SUCCESS) {
1022 goto done;
1023 }
1024
1025 status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_AUTHORITY, b);
1026 if (status != ARES_SUCCESS) {
1027 goto done;
1028 }
1029
1030 status = ares_dns_write_rr(dnsrec, &namelist, ARES_SECTION_ADDITIONAL, b);
1031 if (status != ARES_SUCCESS) {
1032 goto done;
1033 }
1034
1035 done:
1036 ares__llist_destroy(namelist);
1037
1038 if (status != ARES_SUCCESS) {
1039 ares__buf_destroy(b);
1040 return status;
1041 }
1042
1043 *buf = ares__buf_finish_bin(b, buf_len);
1044 return status;
1045 }
1046
ares_dns_record_write_ttl_decrement(ares_dns_record_t * dnsrec,unsigned int ttl_decrement)1047 void ares_dns_record_write_ttl_decrement(ares_dns_record_t *dnsrec,
1048 unsigned int ttl_decrement)
1049 {
1050 if (dnsrec == NULL) {
1051 return;
1052 }
1053 dnsrec->ttl_decrement = ttl_decrement;
1054 }
1055