Skip to content

Commit ef10937

Browse files
committed
net: dns: Make dns_unpack_answer() to check non-compressed answers
Modify dns_unpack_answer() function to check if the answer is compressed or not, and return correct values regardless. Fixes #16594 Signed-off-by: Jukka Rissanen <[email protected]>
1 parent f7697c4 commit ef10937

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

subsys/net/lib/dns/dns_pack.c

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ static inline void set_dns_msg_response(struct dns_msg_t *dns_msg, int type,
7474

7575
int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, u32_t *ttl)
7676
{
77+
int dname_len = DNS_COMMON_UINT_SIZE;
78+
int i = 0;
7779
u16_t buf_size;
7880
u16_t pos;
7981
u16_t len;
@@ -82,14 +84,33 @@ int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, u32_t *ttl)
8284

8385
answer = dns_msg->msg + dns_msg->answer_offset;
8486

85-
if (answer[0] < DNS_LABEL_MAX_SIZE) {
86-
return -ENOMEM;
87-
}
87+
if (answer[i] == 0xc0 && answer[i + 1] == 0x0c) {
88+
check_pointer:
89+
if (answer[i] < DNS_LABEL_MAX_SIZE) {
90+
return -ENOMEM;
91+
}
8892

89-
/* Recovery of the pointer value */
90-
ptr = (((answer[0] & DNS_LABEL_MAX_SIZE) << 8) + answer[1]);
91-
if (ptr != dname_ptr) {
92-
return -ENOMEM;
93+
/* Recovery of the pointer value */
94+
ptr = ((answer[i] & DNS_LABEL_MAX_SIZE) << 8) + answer[i + 1];
95+
if (ptr != dname_ptr) {
96+
return -ENOMEM;
97+
}
98+
} else {
99+
dname_len = answer[i++] + 1;
100+
while (answer[i]) {
101+
if (answer[i] == 0xc0 && answer[i + 1] == 0x0c) {
102+
dname_len += DNS_COMMON_UINT_SIZE;
103+
goto check_pointer;
104+
}
105+
106+
if (answer[i] < DNS_LABEL_MAX_SIZE) {
107+
dname_len += answer[i] + 1;
108+
}
109+
110+
i++;
111+
}
112+
113+
dname_len++;
93114
}
94115

95116
/*
@@ -111,16 +132,20 @@ int dns_unpack_answer(struct dns_msg_t *dns_msg, int dname_ptr, u32_t *ttl)
111132
/* Only DNS_CLASS_IN answers
112133
* Here we use 2 as an offset because a ptr uses only 2 bytes.
113134
*/
114-
if (dns_answer_class(DNS_COMMON_UINT_SIZE, answer) != DNS_CLASS_IN) {
135+
if (dns_answer_class(dname_len, answer) != DNS_CLASS_IN) {
115136
return -EINVAL;
116137
}
117138

118139
/* TTL value */
119-
*ttl = dns_answer_ttl(DNS_COMMON_UINT_SIZE, answer);
120-
pos = dns_msg->answer_offset + DNS_ANSWER_MIN_SIZE;
121-
len = dns_answer_rdlength(DNS_COMMON_UINT_SIZE, answer);
122-
123-
switch (dns_answer_type(DNS_COMMON_UINT_SIZE, answer)) {
140+
*ttl = dns_answer_ttl(dname_len, answer);
141+
len = dns_answer_rdlength(dname_len, answer);
142+
pos = dns_msg->answer_offset + dname_len +
143+
DNS_COMMON_UINT_SIZE + /* class length */
144+
DNS_COMMON_UINT_SIZE + /* type length */
145+
DNS_TTL_LEN +
146+
DNS_RDLENGTH_LEN;
147+
148+
switch (dns_answer_type(dname_len, answer)) {
124149
case DNS_RR_TYPE_A:
125150
case DNS_RR_TYPE_AAAA:
126151
set_dns_msg_response(dns_msg, DNS_RESPONSE_IP, pos, len);

0 commit comments

Comments
 (0)