public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Stefano Brivio <sbrivio@redhat.com>
To: passt-dev@passt.top
Cc: Sebastian Mitterle <smitterl@redhat.com>
Subject: [PATCH] dhcpv6: Properly separate domain names in search list
Date: Wed, 20 Sep 2023 17:05:06 +0200	[thread overview]
Message-ID: <20230920150506.3341961-1-sbrivio@redhat.com> (raw)

If we go over the flattened list of search domains and just replace
dots and zero bytes with the length of the next label to implement
the encoding specified by section 3.1 of RFC 1035, if there are
multiple domains in the search list, we'll also replace separators
between two domain names with the length of the first label of the
second domain, plus one. Those should remain as zero bytes to
separate domains, though.

To distinguish between label separators and domain names separators,
for simplicity, introduce a dot before the first label of every
domain we copy to form the list. All dots are then replaced by label
lengths, and separators (zero bytes) remain as they are.

As we do this, we need to make sure we don't replace the trailing
dot, if present: that's already a separator. Skip copying it, and
just add separators as needed.

Now that we don't copy those, though, we might end up with
zero-length domains: skip them, as they're meaningless anyway.

And as we might skip domains, we can't use the index 'i' to check if
we're at the beginning of the option -- use 'srch' instead.

This is very similar to how we prepare the list for NDP option 31,
except that we don't need padding (RFC 8106, 5.2) here, and we should
refactor this into common functions, but it probably makes sense to
rework the NDP responder (https://bugs.passt.top/show_bug.cgi?id=21)
first.

Reported-by: Sebastian Mitterle <smitterl@redhat.com>
Link: https://bugs.passt.top/show_bug.cgi?id=75
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
 dhcpv6.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/dhcpv6.c b/dhcpv6.c
index fc42a84..58171bb 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -376,24 +376,34 @@ search:
 		return offset;
 
 	for (i = 0; *c->dns_search[i].n; i++) {
-		if (!i) {
+		size_t name_len = strlen(c->dns_search[i].n);
+
+		/* We already append separators, don't duplicate if present */
+		if (c->dns_search[i].n[name_len - 1] == '.')
+			name_len--;
+
+		/* Skip root-only search domains */
+		if (!name_len)
+			continue;
+
+		if (!srch) {
 			srch = (struct opt_dns_search *)(buf + offset);
 			offset += sizeof(struct opt_hdr);
 			srch->hdr.t = OPT_DNS_SEARCH;
 			srch->hdr.l = 0;
 			p = srch->list;
-			*p = 0;
 		}
 
-		p = stpcpy(p + 1, c->dns_search[i].n);
-		*(p++) = 0;
-		srch->hdr.l += strlen(c->dns_search[i].n) + 2;
-		offset += strlen(c->dns_search[i].n) + 2;
+		*p = '.';
+		p = stpncpy(p + 1, c->dns_search[i].n, name_len);
+		p++;
+		srch->hdr.l += name_len + 2;
+		offset += name_len + 2;
 	}
 
 	if (srch) {
 		for (i = 0; i < srch->hdr.l; i++) {
-			if (srch->list[i] == '.' || !srch->list[i]) {
+			if (srch->list[i] == '.') {
 				srch->list[i] = strcspn(srch->list + i + 1,
 							".");
 			}
-- 
@@ -376,24 +376,34 @@ search:
 		return offset;
 
 	for (i = 0; *c->dns_search[i].n; i++) {
-		if (!i) {
+		size_t name_len = strlen(c->dns_search[i].n);
+
+		/* We already append separators, don't duplicate if present */
+		if (c->dns_search[i].n[name_len - 1] == '.')
+			name_len--;
+
+		/* Skip root-only search domains */
+		if (!name_len)
+			continue;
+
+		if (!srch) {
 			srch = (struct opt_dns_search *)(buf + offset);
 			offset += sizeof(struct opt_hdr);
 			srch->hdr.t = OPT_DNS_SEARCH;
 			srch->hdr.l = 0;
 			p = srch->list;
-			*p = 0;
 		}
 
-		p = stpcpy(p + 1, c->dns_search[i].n);
-		*(p++) = 0;
-		srch->hdr.l += strlen(c->dns_search[i].n) + 2;
-		offset += strlen(c->dns_search[i].n) + 2;
+		*p = '.';
+		p = stpncpy(p + 1, c->dns_search[i].n, name_len);
+		p++;
+		srch->hdr.l += name_len + 2;
+		offset += name_len + 2;
 	}
 
 	if (srch) {
 		for (i = 0; i < srch->hdr.l; i++) {
-			if (srch->list[i] == '.' || !srch->list[i]) {
+			if (srch->list[i] == '.') {
 				srch->list[i] = strcspn(srch->list + i + 1,
 							".");
 			}
-- 
2.39.2


             reply	other threads:[~2023-09-20 15:05 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-20 15:05 Stefano Brivio [this message]
2023-09-20 23:55 ` [PATCH] dhcpv6: Properly separate domain names in search list David Gibson
2023-09-21 15:08   ` Stefano Brivio
2023-09-23  7:44     ` David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230920150506.3341961-1-sbrivio@redhat.com \
    --to=sbrivio@redhat.com \
    --cc=passt-dev@passt.top \
    --cc=smitterl@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).