dns: explicitly endian-convert all fields in header and question
authorPaul Fertser <fercerpav@gmail.com>
Sat, 4 Apr 2020 10:25:14 +0000 (13:25 +0300)
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Sat, 4 Apr 2020 19:21:51 +0000 (20:21 +0100)
For added type-safety and to avoid possible alignment issues make all
conversions explicit. While at it, mark header struct as packed so that
its layout is guaranteed to match RFC.

Prompted by gcc 8 & 9 warning in dns.c:

dns.c:261:2: error: converting a packed ‘struct dns_question’
pointer (alignment 1) to a ‘uint16_t’ {aka ‘short unsigned int’} pointer
(alignment 2) may result in an unaligned pointer value
[-Werror=address-of-packed-member]

261 |  uint16_t *swap = (uint16_t *) q;

Signed-off-by: Paul Fertser <fercerpav@gmail.com>
[Tweak commit message]
Acked-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
dns.c
dns.h

diff --git a/dns.c b/dns.c
index aadfdd8f6927806cbdb7108d81c1031559100308..86e5ea3aaa6c7f44cc4d52d4082b8ec9580046e0 100644 (file)
--- a/dns.c
+++ b/dns.c
@@ -237,16 +237,16 @@ static struct dns_header*
 dns_consume_header(uint8_t **data, int *len)
 {
        struct dns_header *h = (struct dns_header *) *data;
-       uint16_t *swap = (uint16_t *) h;
-       int endianess = 6;
 
        if (*len < sizeof(struct dns_header))
                return NULL;
 
-       while (endianess--) {
-               *swap = be16_to_cpu(*swap);
-               swap++;
-       }
+       h->id = be16_to_cpu(h->id);
+       h->flags = be16_to_cpu(h->flags);
+       h->questions = be16_to_cpu(h->questions);
+       h->answers = be16_to_cpu(h->answers);
+       h->authority = be16_to_cpu(h->authority);
+       h->additional = be16_to_cpu(h->additional);
 
        *len -= sizeof(struct dns_header);
        *data += sizeof(struct dns_header);
@@ -258,16 +258,12 @@ static struct dns_question*
 dns_consume_question(uint8_t **data, int *len)
 {
        struct dns_question *q = (struct dns_question *) *data;
-       uint16_t *swap = (uint16_t *) q;
-       int endianess = 2;
 
        if (*len < sizeof(struct dns_question))
                return NULL;
 
-       while (endianess--) {
-               *swap = be16_to_cpu(*swap);
-               swap++;
-       }
+       q->type = be16_to_cpu(q->type);
+       q->class = be16_to_cpu(q->class);
 
        *len -= sizeof(struct dns_question);
        *data += sizeof(struct dns_question);
diff --git a/dns.h b/dns.h
index f1f021203697a56689e9553e6684c8757ac0edba..91570bd6c703762f5cccb7e08144571a1111d068 100644 (file)
--- a/dns.h
+++ b/dns.h
@@ -49,7 +49,7 @@ struct dns_header {
        uint16_t answers;
        uint16_t authority;
        uint16_t additional;
-};
+} __attribute__((packed));
 
 struct dns_srv_data {
        uint16_t priority;