From: Anshu Kumari <anskuma@redhat.com>
To: anskuma@redhat.com, sbrivio@redhat.com, passt-dev@passt.top
Cc: lvivier@redhat.com, jmaloy@redhat.com, david@gibson.dropbear.id.au
Subject: [PATCH 5/6] dhcp: Add option overload
Date: Mon, 18 May 2026 18:50:01 +0530 [thread overview]
Message-ID: <20260518132002.418296-6-anskuma@redhat.com> (raw)
In-Reply-To: <20260518132002.418296-5-anskuma@redhat.com>
A user can enter lots of options in command-line which may not fit in
existing buffer, So when the options field is full, overflow remaining
DHCP options into the file and sname fields per RFC 2132 option 52.
Also, when the file field is not used for overload, copy the boot
file URL there directly for legacy PXE clients.
Link: https://bugs.passt.top/show_bug.cgi?id=192
Signed-off-by: Anshu Kumari <anskuma@redhat.com>
---
dhcp.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 78 insertions(+), 10 deletions(-)
diff --git a/dhcp.c b/dhcp.c
index a966c34..fde5d57 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -386,13 +386,53 @@ static bool fill_one(uint8_t *buf, size_t cap, int o, int *offset)
}
/**
- * fill() - Fill options in message
+ * fill_overflow() - Fill remaining options into file and sname fields
+ * @m: Message whose file/sname fields may be used for overflow
+ *
+ * Return: option 52 overload value: 0 if no overflow, 1 for file,
+ * 2 for sname, 3 for both
+ */
+static int fill_overflow(struct msg *m)
+{
+ int file_off = 0, sname_off = 0, overload = 0;
+ int o;
+
+ for (o = 0; o < 255; o++) {
+ if (opts[o].slen == -1 || opts[o].sent)
+ continue;
+ fill_one(m->file, sizeof(m->file) - 1, o, &file_off);
+ }
+
+ for (o = 0; o < 255; o++) {
+ if (opts[o].slen == -1 || opts[o].sent)
+ continue;
+ if (fill_one(m->sname, sizeof(m->sname) - 1, o, &sname_off))
+ debug("DHCP: skipping option %i (overload full)", o);
+ }
+
+ if (file_off) {
+ m->file[file_off] = 255;
+ overload |= 1;
+ }
+
+ if (sname_off) {
+ m->sname[sname_off] = 255;
+ overload |= 2;
+ }
+
+ return overload;
+}
+
+/**
+ * fill() - Fill options in message, with overload into file/sname if needed
* @m: Message to fill
+ * @overload: Set to option 52 value (0 if none, 1/2/3 per RFC 2132)
*
* Return: current size of options field
*/
-static int fill(struct msg *m)
+static int fill(struct msg *m, int *overload)
{
+ size_t cap = OPT_MAX - 3;
int i, o, offset = 0;
for (o = 0; o < 255; o++)
@@ -403,20 +443,25 @@ static int fill(struct msg *m)
* Put it there explicitly, unless requested via option 55.
*/
if (opts[55].clen > 0 && !memchr(opts[55].c, 53, opts[55].clen))
- if (fill_one(m->o, OPT_MAX, 53, &offset))
- debug("DHCP: skipping option 53");
+ fill_one(m->o, cap, 53, &offset);
for (i = 0; i < opts[55].clen; i++) {
o = opts[55].c[i];
if (opts[o].slen != -1)
- if (fill_one(m->o, OPT_MAX, o, &offset))
- debug("DHCP: skipping option %i", o);
+ fill_one(m->o, cap, o, &offset);
}
for (o = 0; o < 255; o++) {
if (opts[o].slen != -1 && !opts[o].sent)
- if (fill_one(m->o, OPT_MAX, o, &offset))
- debug("DHCP: skipping option %i", o);
+ fill_one(m->o, cap, o, &offset);
+ }
+
+ *overload = fill_overflow(m);
+
+ if (*overload) {
+ m->o[offset++] = 52;
+ m->o[offset++] = 1;
+ m->o[offset++] = *overload;
}
m->o[offset++] = 255;
@@ -541,6 +586,7 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
struct msg const *m;
struct msg reply;
unsigned int i;
+ int overload;
eh = IOV_REMOVE_HEADER(data, eh_storage);
iph = IOV_PEEK_HEADER(data, iph_storage);
@@ -690,9 +736,31 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
}
if (!c->no_dhcp_dns_search)
- opt_set_dns_search(c, sizeof(m->o));
+ opt_set_dns_search(c, sizeof(m->o) + sizeof(m->file)
+ + sizeof(m->sname));
+
+ if (c->dhcp_boot[0]) {
+ size_t boot_len = strlen(c->dhcp_boot);
+
+ if (boot_len <= sizeof(opts[67].s)) {
+ opts[67].slen = boot_len;
+ memcpy(opts[67].s, c->dhcp_boot, boot_len);
+ }
+ }
+
+ for (i = 0; i < (unsigned int)c->custom_opts_count; i++) {
+ uint8_t code = c->custom_opts[i].code;
+
+ opts[code].slen = c->custom_opts[i].len;
+ memcpy(opts[code].s, c->custom_opts[i].val,
+ c->custom_opts[i].len);
+ }
+
+ dlen = offsetof(struct msg, o) + fill(&reply, &overload);
- dlen = offsetof(struct msg, o) + fill(&reply);
+ if (!(overload & 1) &&
+ c->dhcp_boot[0] && strlen(c->dhcp_boot) < sizeof(reply.file))
+ memcpy(&reply.file, c->dhcp_boot, strlen(c->dhcp_boot) + 1);
if (m->flags & FLAG_BROADCAST)
dst = in4addr_broadcast;
--
2.54.0
next prev parent reply other threads:[~2026-05-18 13:20 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-18 13:19 [PATCH 0/6] Add --dhcp-boot and --dhcp-opt options Anshu Kumari
2026-05-18 13:19 ` [PATCH 1/6] conf: Add --dhcp-opt command-line option Anshu Kumari
2026-05-18 13:19 ` [PATCH 2/6] conf: Add --dhcp-boot " Anshu Kumari
2026-05-18 13:19 ` [PATCH 3/6] dhcp: Add option type table and value parser Anshu Kumari
2026-05-18 13:20 ` [PATCH 4/6] dhcp: Refactor fill_one() to operate on a generic buffer Anshu Kumari
2026-05-18 13:20 ` Anshu Kumari [this message]
2026-05-18 13:20 ` [PATCH 6/6] doc: Add --dhcp-boot and --dhcp-opt to man page Anshu Kumari
2026-05-19 6:11 ` [PATCH 5/6] dhcp: Add option overload David Gibson
2026-05-19 6:02 ` [PATCH 4/6] dhcp: Refactor fill_one() to operate on a generic buffer David Gibson
2026-05-19 5:59 ` [PATCH 3/6] dhcp: Add option type table and value parser David Gibson
2026-05-19 5:35 ` [PATCH 2/6] conf: Add --dhcp-boot command-line option David Gibson
2026-05-19 5:33 ` [PATCH 1/6] conf: Add --dhcp-opt " David Gibson
2026-05-19 5:30 ` [PATCH 0/6] Add --dhcp-boot and --dhcp-opt options 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=20260518132002.418296-6-anskuma@redhat.com \
--to=anskuma@redhat.com \
--cc=david@gibson.dropbear.id.au \
--cc=jmaloy@redhat.com \
--cc=lvivier@redhat.com \
--cc=passt-dev@passt.top \
--cc=sbrivio@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).