source: mainline/uspace/srv/net/dnsrsrv/dns_msg.c@ 368ee04

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 368ee04 was b5f716b, checked in by Vojtech Horky <vojtechhorky@…>, 11 years ago

Unbreak optimized-for-size builds (fix maybe-uninitialized)

When possible, converted the maybe-unitialized (in all cases, false alarms)
variables to an assignment with assertion testing that reasonable value
was added.

  • Property mode set to 100644
File size: 15.4 KB
RevLine 
[adae30d]1/*
[dc95342]2 * Copyright (c) 2013 Jiri Svoboda
[adae30d]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup dnsres
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <bitops.h>
[08a6382]37#include <byteorder.h>
[adae30d]38#include <errno.h>
[ef904895]39#include <io/log.h>
[0041cd6d]40#include <macros.h>
[adae30d]41#include <stdint.h>
42#include <stdlib.h>
43#include <str.h>
44
45#include "dns_msg.h"
46#include "dns_std.h"
47
48#define NAME "dnsres"
49
[f1dcf6d]50static uint16_t dns_uint16_t_decode(uint8_t *, size_t);
51
[9f029aa]52/** Extend dynamically allocated string with suffix.
53 *
54 * @a *dstr points to a dynamically alocated buffer containing a string.
55 * Reallocate this buffer so that concatenation of @a *dstr and @a suff can
56 * fit in and append @a suff.
57 */
[7262f89]58static int dns_dstr_ext(char **dstr, const char *suff)
59{
60 size_t s1, s2;
61 size_t nsize;
62 char *nstr;
63
64 if (*dstr == NULL) {
65 *dstr = str_dup(suff);
66 if (*dstr == NULL)
67 return ENOMEM;
68 return EOK;
69 }
70
71 s1 = str_size(*dstr);
72 s2 = str_size(suff);
73 nsize = s1 + s2 + 1;
74
75 nstr = realloc(*dstr, nsize);
76 if (nstr == NULL)
77 return ENOMEM;
78
79 str_cpy((*dstr) + s1, nsize - s1, suff);
80
81 *dstr = nstr;
82 return EOK;
83}
84
[9f029aa]85/** Encode DNS name.
86 *
87 * Encode DNS name or measure the size of encoded name (with @a buf NULL,
88 * and @a buf_size 0).
89 *
90 * @param name String to encode
91 * @param buf Buffer or NULL
92 * @param buf_size Buffer size or 0 if @a buf is NULL
93 * @param act_size Place to store actual encoded size
94 */
[adae30d]95static int dns_name_encode(char *name, uint8_t *buf, size_t buf_size,
96 size_t *act_size)
97{
98 size_t off;
99 wchar_t c;
100 size_t lsize;
101 size_t pi, di;
102
103 pi = 0;
104 di = 1;
[f85ed4b]105 off = 0;
[adae30d]106
107 lsize = 0;
108 while (true) {
109 c = str_decode(name, &off, STR_NO_LIMIT);
[7262f89]110 if (c >= 127) {
[adae30d]111 /* Non-ASCII character */
[ef904895]112 log_msg(LOG_DEFAULT, LVL_DEBUG, "Non-ascii character");
[adae30d]113 return EINVAL;
114 }
115
116 if (c == '.' || c == '\0') {
117 /* Empty string, starting with period or two consecutive periods. */
[f85ed4b]118 if (lsize == 0) {
[ef904895]119 log_msg(LOG_DEFAULT, LVL_DEBUG, "Empty token");
[adae30d]120 return EINVAL;
[f85ed4b]121 }
[adae30d]122
123 if (lsize > DNS_LABEL_MAX_SIZE) {
124 /* Label too long */
[ef904895]125 log_msg(LOG_DEFAULT, LVL_DEBUG, "Label too long");
[adae30d]126 return EINVAL;
127 }
128
129 if (buf != NULL && pi < buf_size)
130 buf[pi] = (uint8_t)lsize;
131
[08a6382]132 lsize = 0;
[adae30d]133 pi = di;
134 ++di;
[08a6382]135
136 if (c == '\0')
137 break;
[adae30d]138 } else {
139 if (buf != NULL && di < buf_size)
[08a6382]140 buf[di] = c;
141 ++di;
142 ++lsize;
[adae30d]143 }
144 }
145
146 if (buf != NULL && pi < buf_size)
147 buf[pi] = 0;
148
149 *act_size = di;
150 return EOK;
151}
152
[9f029aa]153/** Decode DNS name.
154 *
155 * @param pdu PDU from which we are decoding
156 * @param boff Starting offset within PDU
157 * @param rname Place to return dynamically allocated string
158 * @param eoff Place to store end offset (offset after last decoded byte)
159 */
160int dns_name_decode(dns_pdu_t *pdu, size_t boff, char **rname,
[9d8bd3ac]161 size_t *eoff)
[0041cd6d]162{
163 uint8_t *bp;
164 size_t bsize;
165 size_t lsize;
166 size_t i;
[f1dcf6d]167 size_t ptr;
168 size_t eptr;
[7262f89]169 char *name;
170 char dbuf[2];
171 int rc;
172 bool first;
173
174 name = NULL;
[0041cd6d]175
[9f029aa]176 if (boff > pdu->size)
[9d8bd3ac]177 return EINVAL;
178
[9f029aa]179 bp = pdu->data + boff;
180 bsize = min(pdu->size - boff, DNS_NAME_MAX_SIZE);
[7262f89]181 first = true;
182 *eoff = 0;
[0041cd6d]183
184 while (true) {
185 if (bsize == 0) {
[7262f89]186 rc = EINVAL;
187 goto error;
[0041cd6d]188 }
189
190 lsize = *bp;
191 ++bp;
192 --bsize;
193
194 if (lsize == 0)
195 break;
196
[7262f89]197 if (!first) {
198 rc = dns_dstr_ext(&name, ".");
199 if (rc != EOK) {
200 rc = ENOMEM;
201 goto error;
202 }
203 }
[0041cd6d]204
205 if ((lsize & 0xc0) == 0xc0) {
206 /* Pointer */
[f1dcf6d]207 if (bsize < 1) {
[ef904895]208 log_msg(LOG_DEFAULT, LVL_DEBUG, "Pointer- bsize < 1");
[7262f89]209 rc = EINVAL;
210 goto error;
[f1dcf6d]211 }
212
213 ptr = dns_uint16_t_decode(bp - 1, bsize) & 0x3fff;
[7262f89]214 ++bp;
215 --bsize;
216
[9f029aa]217 if (ptr >= (size_t)(bp - pdu->data)) {
[ef904895]218 log_msg(LOG_DEFAULT, LVL_DEBUG,
[716357f]219 "Pointer- forward ref %zu, pos=%zu",
[9f029aa]220 ptr, (size_t)(bp - pdu->data));
[f1dcf6d]221 /* Forward reference */
[7262f89]222 rc = EINVAL;
223 goto error;
[f1dcf6d]224 }
225
226 /*
227 * Make sure we will not decode any byte twice.
228 * XXX Is assumption correct?
229 */
[9f029aa]230 eptr = bp - pdu->data;
[7262f89]231 /*
232 * This is where encoded name ends in terms where
233 * the message continues
234 */
235 *eoff = eptr;
[f1dcf6d]236
[9f029aa]237 bp = pdu->data + ptr;
[f1dcf6d]238 bsize = eptr - ptr;
239 continue;
[0041cd6d]240 }
241
242 if (lsize > bsize) {
[7262f89]243 rc = EINVAL;
244 goto error;
[0041cd6d]245 }
246
247 for (i = 0; i < lsize; i++) {
[7262f89]248 if (*bp < 32 || *bp >= 127) {
249 rc = EINVAL;
250 goto error;
251 }
252
253 dbuf[0] = *bp;
254 dbuf[1] = '\0';
255
256 rc = dns_dstr_ext(&name, dbuf);
257 if (rc != EOK) {
258 rc = ENOMEM;
259 goto error;
260 }
[0041cd6d]261 ++bp;
262 --bsize;
263 }
[7262f89]264
265 first = false;
[0041cd6d]266 }
267
[7262f89]268 *rname = name;
269 if (*eoff == 0)
[9f029aa]270 *eoff = bp - pdu->data;
[0041cd6d]271 return EOK;
[7262f89]272error:
273 free(name);
274 return rc;
[0041cd6d]275}
276
277/** Decode unaligned big-endian 16-bit integer */
278static uint16_t dns_uint16_t_decode(uint8_t *buf, size_t buf_size)
279{
280 assert(buf_size >= 2);
281
282 return ((uint16_t)buf[0] << 8) + buf[1];
283}
284
285/** Encode unaligned big-endian 16-bit integer */
[adae30d]286static void dns_uint16_t_encode(uint16_t w, uint8_t *buf, size_t buf_size)
287{
288 if (buf != NULL && buf_size >= 1)
289 buf[0] = w >> 8;
290
291 if (buf != NULL && buf_size >= 2)
292 buf[1] = w & 0xff;
293}
294
[0041cd6d]295/** Decode unaligned big-endian 32-bit integer */
[7262f89]296uint32_t dns_uint32_t_decode(uint8_t *buf, size_t buf_size)
[0041cd6d]297{
298 assert(buf_size >= 4);
[0aa70f4]299
300 uint32_t w = ((uint32_t) buf[0] << 24) +
[3e66428]301 ((uint32_t) buf[1] << 16) +
302 ((uint32_t) buf[2] << 8) +
[7262f89]303 buf[3];
[0aa70f4]304
[7262f89]305 return w;
[0041cd6d]306}
307
[0aa70f4]308/** Decode unaligned big-endian 128-bit integer */
309void dns_addr128_t_decode(uint8_t *buf, size_t buf_size, addr128_t addr)
310{
311 assert(buf_size >= 16);
312
313 addr128_t_be2host(buf, addr);
314}
315
[9f029aa]316/** Encode DNS question.
317 *
318 * Encode DNS question or measure the size of encoded question (with @a buf NULL,
319 * and @a buf_size 0).
320 *
321 * @param question Question to encode
322 * @param buf Buffer or NULL
323 * @param buf_size Buffer size or 0 if @a buf is NULL
324 * @param act_size Place to store actual encoded size
325 */
[adae30d]326static int dns_question_encode(dns_question_t *question, uint8_t *buf,
327 size_t buf_size, size_t *act_size)
328{
329 size_t name_size;
330 size_t di;
331 int rc;
332
333 rc = dns_name_encode(question->qname, buf, buf_size, &name_size);
334 if (rc != EOK)
335 return rc;
336
337 *act_size = name_size + sizeof(uint16_t) + sizeof(uint16_t);
[f85ed4b]338 if (buf == NULL)
339 return EOK;
340
[adae30d]341 di = name_size;
342
343 dns_uint16_t_encode(question->qtype, buf + di, buf_size - di);
344 di += sizeof(uint16_t);
345
346 dns_uint16_t_encode(question->qclass, buf + di, buf_size - di);
347 di += sizeof(uint16_t);
348
349 return EOK;
350}
351
[9f029aa]352/** Decode DNS question.
353 *
354 * @param pdu PDU from which we are decoding
355 * @param boff Starting offset within PDU
356 * @param rquestion Place to return dynamically allocated question
357 * @param eoff Place to store end offset (offset after last decoded byte)
358 */
359static int dns_question_decode(dns_pdu_t *pdu, size_t boff,
[9d8bd3ac]360 dns_question_t **rquestion, size_t *eoff)
[0041cd6d]361{
362 dns_question_t *question;
[9d8bd3ac]363 size_t name_eoff;
[0041cd6d]364 int rc;
365
366 question = calloc(1, sizeof (dns_question_t));
367 if (question == NULL)
368 return ENOMEM;
369
[9f029aa]370 rc = dns_name_decode(pdu, boff, &question->qname, &name_eoff);
[0041cd6d]371 if (rc != EOK) {
[ef904895]372 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error decoding name");
[0041cd6d]373 free(question);
374 return ENOMEM;
375 }
376
[9f029aa]377 if (name_eoff + 2 * sizeof(uint16_t) > pdu->size) {
[0041cd6d]378 free(question);
379 return EINVAL;
380 }
381
[9f029aa]382 question->qtype = dns_uint16_t_decode(pdu->data + name_eoff,
383 pdu->size - name_eoff);
384 question->qclass = dns_uint16_t_decode(pdu->data + sizeof(uint16_t)
385 + name_eoff, pdu->size - sizeof(uint16_t) - name_eoff);
[9d8bd3ac]386 *eoff = name_eoff + 2 * sizeof(uint16_t);
[0041cd6d]387
388 *rquestion = question;
389 return EOK;
390}
391
[9f029aa]392/** Decode DNS resource record.
393 *
394 * @param pdu PDU from which we are decoding
395 * @param boff Starting offset within PDU
396 * @param retrr Place to return dynamically allocated resource record
397 * @param eoff Place to store end offset (offset after last decoded byte)
398 */
399static int dns_rr_decode(dns_pdu_t *pdu, size_t boff, dns_rr_t **retrr,
400 size_t *eoff)
[0041cd6d]401{
402 dns_rr_t *rr;
[9d8bd3ac]403 size_t name_eoff;
[0041cd6d]404 uint8_t *bp;
405 size_t bsz;
406 size_t rdlength;
407 int rc;
408
[0aa70f4]409 rr = calloc(1, sizeof(dns_rr_t));
[0041cd6d]410 if (rr == NULL)
411 return ENOMEM;
412
[9f029aa]413 rc = dns_name_decode(pdu, boff, &rr->name, &name_eoff);
[0041cd6d]414 if (rc != EOK) {
[ef904895]415 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error decoding name");
[0041cd6d]416 free(rr);
417 return ENOMEM;
418 }
419
[9f029aa]420 if (name_eoff + 2 * sizeof(uint16_t) > pdu->size) {
[0041cd6d]421 free(rr->name);
422 free(rr);
423 return EINVAL;
424 }
425
[9f029aa]426 bp = pdu->data + name_eoff;
427 bsz = pdu->size - name_eoff;
[0041cd6d]428
429 if (bsz < 3 * sizeof(uint16_t) + sizeof(uint32_t)) {
430 free(rr->name);
431 free(rr);
432 return EINVAL;
433 }
434
435 rr->rtype = dns_uint16_t_decode(bp, bsz);
[0aa70f4]436 bp += sizeof(uint16_t);
437 bsz -= sizeof(uint16_t);
[0041cd6d]438
439 rr->rclass = dns_uint16_t_decode(bp, bsz);
[0aa70f4]440 bp += sizeof(uint16_t);
441 bsz -= sizeof(uint16_t);
[0041cd6d]442
443 rr->ttl = dns_uint32_t_decode(bp, bsz);
[0aa70f4]444 bp += sizeof(uint32_t);
445 bsz -= sizeof(uint32_t);
[0041cd6d]446
447 rdlength = dns_uint16_t_decode(bp, bsz);
[0aa70f4]448 bp += sizeof(uint16_t);
449 bsz -= sizeof(uint16_t);
[0041cd6d]450
451 if (rdlength > bsz) {
452 free(rr->name);
453 free(rr);
454 return EINVAL;
455 }
456
457 rr->rdata_size = rdlength;
458 rr->rdata = calloc(1, sizeof(rdlength));
459 if (rr->rdata == NULL) {
460 free(rr->name);
461 free(rr);
462 return ENOMEM;
463 }
464
465 memcpy(rr->rdata, bp, rdlength);
[9f029aa]466 rr->roff = bp - pdu->data;
[0041cd6d]467 bp += rdlength;
468 bsz -= rdlength;
469
[9f029aa]470 *eoff = bp - pdu->data;
[0041cd6d]471 *retrr = rr;
472 return EOK;
473}
474
[9f029aa]475/** Encode DNS message.
476 *
477 * @param msg Message
478 * @param rdata Place to store encoded data pointer
479 * @param rsize Place to store encoded data size
480 *
481 * @return EOK on success, EINVAL if message contains invalid data,
482 * ENOMEM if out of memory
483 */
[adae30d]484int dns_message_encode(dns_message_t *msg, void **rdata, size_t *rsize)
485{
486 uint8_t *data;
487 size_t size;
488 dns_header_t hdr;
[b5f716b]489 size_t q_size = 0;
[adae30d]490 size_t di;
491 int rc;
492
[08a6382]493 hdr.id = host2uint16_t_be(msg->id);
[adae30d]494
[08a6382]495 hdr.opbits = host2uint16_t_be(
[adae30d]496 (msg->qr << OPB_QR) |
497 (msg->opcode << OPB_OPCODE_l) |
498 (msg->aa ? BIT_V(uint16_t, OPB_AA) : 0) |
499 (msg->tc ? BIT_V(uint16_t, OPB_TC) : 0) |
500 (msg->rd ? BIT_V(uint16_t, OPB_RD) : 0) |
501 (msg->ra ? BIT_V(uint16_t, OPB_RA) : 0) |
[08a6382]502 msg->rcode
503 );
[adae30d]504
[08a6382]505 hdr.qd_count = host2uint16_t_be(list_count(&msg->question));
[adae30d]506 hdr.an_count = 0;
507 hdr.ns_count = 0;
508 hdr.ar_count = 0;
509
510 size = sizeof(dns_header_t);
511
[feeac0d]512 list_foreach(msg->question, msg, dns_question_t, q) {
[adae30d]513 rc = dns_question_encode(q, NULL, 0, &q_size);
514 if (rc != EOK)
515 return rc;
516
[b5f716b]517 assert(q_size > 0);
518
[adae30d]519 size += q_size;
520 }
521
522 data = calloc(1, size);
523 if (data == NULL)
524 return ENOMEM;
525
526 memcpy(data, &hdr, sizeof(dns_header_t));
527 di = sizeof(dns_header_t);
528
[feeac0d]529 list_foreach(msg->question, msg, dns_question_t, q) {
[adae30d]530 rc = dns_question_encode(q, data + di, size - di, &q_size);
[dc95342]531 if (rc != EOK) {
532 assert(rc == ENOMEM || rc == EINVAL);
533 free(data);
534 return rc;
535 }
[adae30d]536
[b5f716b]537 assert(q_size > 0);
538
[adae30d]539 di += q_size;
540 }
541
542 *rdata = data;
543 *rsize = size;
544 return EOK;
545}
546
[9f029aa]547/** Decode DNS message.
548 *
549 * @param data Encoded PDU data
550 * @param size Encoded PDU size
551 * @param rmsg Place to store pointer to decoded message
552 *
553 * @return EOK on success, EINVAL if message contains invalid data,
554 * ENOMEM if out of memory
555 */
[0041cd6d]556int dns_message_decode(void *data, size_t size, dns_message_t **rmsg)
557{
558 dns_message_t *msg;
559 dns_header_t *hdr;
[9d8bd3ac]560 size_t doff;
561 size_t field_eoff;
[0041cd6d]562 dns_question_t *question;
563 dns_rr_t *rr;
564 size_t qd_count;
565 size_t an_count;
566 size_t i;
567 int rc;
568
[a0d97f83]569 msg = dns_message_new();
[0041cd6d]570 if (msg == NULL)
571 return ENOMEM;
572
[d531bd6]573 if (size < sizeof(dns_header_t)) {
574 rc = EINVAL;
575 goto error;
576 }
577
578 /* Store a copy of raw message data for string decompression */
579
[9f029aa]580 msg->pdu.data = malloc(size);
581 if (msg->pdu.data == NULL) {
582 rc = ENOMEM;
[d531bd6]583 goto error;
584 }
585
[9f029aa]586 memcpy(msg->pdu.data, data, size);
587 msg->pdu.size = size;
588 log_msg(LOG_DEFAULT, LVL_NOTE, "dns_message_decode: pdu->data = %p, "
589 "pdu->size=%zu", msg->pdu.data, msg->pdu.size);
[0041cd6d]590
591 hdr = data;
592
593 msg->id = uint16_t_be2host(hdr->id);
594 msg->qr = BIT_RANGE_EXTRACT(uint16_t, OPB_QR, OPB_QR, hdr->opbits);
595 msg->opcode = BIT_RANGE_EXTRACT(uint16_t, OPB_OPCODE_h, OPB_OPCODE_l,
596 hdr->opbits);
597 msg->aa = BIT_RANGE_EXTRACT(uint16_t, OPB_AA, OPB_AA, hdr->opbits);
598 msg->tc = BIT_RANGE_EXTRACT(uint16_t, OPB_TC, OPB_TC, hdr->opbits);
599 msg->rd = BIT_RANGE_EXTRACT(uint16_t, OPB_RD, OPB_RD, hdr->opbits);
600 msg->ra = BIT_RANGE_EXTRACT(uint16_t, OPB_RA, OPB_RA, hdr->opbits);
601 msg->rcode = BIT_RANGE_EXTRACT(uint16_t, OPB_RCODE_h, OPB_RCODE_l,
602 hdr->opbits);
603
[9d8bd3ac]604 doff = sizeof(dns_header_t);
[0041cd6d]605
606 qd_count = uint16_t_be2host(hdr->qd_count);
607
608 for (i = 0; i < qd_count; i++) {
[9f029aa]609 rc = dns_question_decode(&msg->pdu, doff, &question, &field_eoff);
[0041cd6d]610 if (rc != EOK) {
[ef904895]611 log_msg(LOG_DEFAULT, LVL_DEBUG, "error decoding question");
[0041cd6d]612 goto error;
613 }
614
[7262f89]615 list_append(&question->msg, &msg->question);
[9d8bd3ac]616 doff = field_eoff;
[0041cd6d]617 }
618
619 an_count = uint16_t_be2host(hdr->an_count);
620
621 for (i = 0; i < an_count; i++) {
[9f029aa]622 rc = dns_rr_decode(&msg->pdu, doff, &rr, &field_eoff);
[0041cd6d]623 if (rc != EOK) {
[ef904895]624 log_msg(LOG_DEFAULT, LVL_DEBUG, "Error decoding answer");
[0041cd6d]625 goto error;
626 }
627
[7262f89]628 list_append(&rr->msg, &msg->answer);
[9d8bd3ac]629 doff = field_eoff;
[0041cd6d]630 }
631
632 *rmsg = msg;
633 return EOK;
634error:
[dc95342]635 dns_message_destroy(msg);
[0041cd6d]636 return rc;
637}
638
[9f029aa]639/** Destroy question. */
[dc95342]640static void dns_question_destroy(dns_question_t *question)
641{
642 free(question->qname);
643 free(question);
644}
645
[9f029aa]646/** Destroy resource record. */
[dc95342]647static void dns_rr_destroy(dns_rr_t *rr)
648{
649 free(rr->name);
650 free(rr->rdata);
651 free(rr);
652}
653
[9f029aa]654/** Create new empty message. */
[a0d97f83]655dns_message_t *dns_message_new(void)
656{
657 dns_message_t *msg;
658
659 msg = calloc(1, sizeof(dns_message_t));
660 if (msg == NULL)
661 return NULL;
662
663 list_initialize(&msg->question);
664 list_initialize(&msg->answer);
665 list_initialize(&msg->authority);
666 list_initialize(&msg->additional);
667
668 return msg;
669}
670
[9f029aa]671/** Destroy message. */
[dc95342]672void dns_message_destroy(dns_message_t *msg)
673{
674 link_t *link;
675 dns_question_t *question;
676 dns_rr_t *rr;
677
678 while (!list_empty(&msg->question)) {
679 link = list_first(&msg->question);
680 question = list_get_instance(link, dns_question_t, msg);
681 list_remove(&question->msg);
682 dns_question_destroy(question);
683 }
684
685 while (!list_empty(&msg->answer)) {
686 link = list_first(&msg->answer);
687 rr = list_get_instance(link, dns_rr_t, msg);
688 list_remove(&rr->msg);
689 dns_rr_destroy(rr);
690 }
691
692 while (!list_empty(&msg->authority)) {
693 link = list_first(&msg->authority);
694 rr = list_get_instance(link, dns_rr_t, msg);
695 list_remove(&rr->msg);
696 dns_rr_destroy(rr);
697 }
698
699 while (!list_empty(&msg->additional)) {
700 link = list_first(&msg->additional);
701 rr = list_get_instance(link, dns_rr_t, msg);
702 list_remove(&rr->msg);
703 dns_rr_destroy(rr);
704 }
705
[9f029aa]706 free(msg->pdu.data);
[dc95342]707 free(msg);
708}
709
[adae30d]710/** @}
711 */
Note: See TracBrowser for help on using the repository browser.