summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Gerstner <matthias.gerstner@suse.de>2022-10-27 12:32:52 +0200
committerDaniel Wagner <wagi@monom.org>2022-11-03 08:10:30 +0100
commit3a5fdf558e84a3a0697d39a2222e82d037388325 (patch)
tree93f53df5921eebe93eccd589f38d7f2445fc9a7f
parent6d2cec47445bdb1ca5bd8848215dac804a884c7e (diff)
downloadconnman-3a5fdf558e84a3a0697d39a2222e82d037388325.tar.gz
dnsproxy: refactor and document strip_domains() to make it less confusing
-rw-r--r--src/dnsproxy.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/src/dnsproxy.c b/src/dnsproxy.c
index b093e87d..dec0e8f1 100644
--- a/src/dnsproxy.c
+++ b/src/dnsproxy.c
@@ -1882,45 +1882,70 @@ out:
return NULL;
}
-static int strip_domains(char *name, char *answers, int maxlen)
+/*
+ * removes the qualified domain name part from the given answer sections
+ * starting at 'answers', consisting of 'length' bytes.
+ *
+ * 'name' points the start of the unqualified host label including the leading
+ * length octet.
+ *
+ * returns the new (possibly shorter) length of remaining payload in the
+ * answers buffer, or a negative (errno) value to indicate error conditions.
+ */
+static int strip_domains(const char *name, char *answers, size_t length)
{
uint16_t data_len;
+ struct domain_rr *rr;
+ /* length of the name label including the length header octet */
const size_t name_len = strlen(name);
- const char *start = answers, *end = answers + maxlen;
+ const char *end = answers + length;
- while (maxlen > 0) {
+ while (answers < end) {
char *ptr = strstr(answers, name);
if (ptr) {
char *domain = ptr + name_len;
+ /* this now points to the domain part length octet. */
if (*domain) {
+ /*
+ * length of the rest of the labels up to the
+ * null label (zero byte).
+ */
const size_t domain_len = strlen(domain);
+ char *remaining = domain + domain_len;
- memmove(answers + name_len,
- domain + domain_len,
- end - (domain + domain_len));
+ /*
+ * now shift the rest of the answer sections
+ * to the left to get rid of the domain label
+ * part
+ */
+ memmove(ptr + name_len,
+ remaining,
+ end - remaining);
end -= domain_len;
- maxlen -= domain_len;
+ length -= domain_len;
}
- } else {
- ptr = answers;
}
- answers += strlen(answers) + 1;
- answers += 2 + 2 + 4; /* skip type, class and ttl fields */
-
- data_len = answers[0] << 8 | answers[1];
- answers += 2; /* skip the length field */
+ /* skip to the next answer section */
- if (answers + data_len > end)
+ /* the labels up to the root null label */
+ answers += strlen(answers) + 1;
+ /* the fixed part of the RR */
+ rr = (void*)answers;
+ if (answers + sizeof(*rr) > end)
return -EINVAL;
-
+ data_len = htons(rr->rdlen);
+ /* skip the rest of the RR */
+ answers += sizeof(*rr);
answers += data_len;
- maxlen -= answers - ptr;
}
- return end - start;
+ if (answers > end)
+ return -EINVAL;
+
+ return length;
}
static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,