From: Stefano Brivio <sbrivio@redhat.com>
To: Anshu Kumari <anskuma@redhat.com>
Cc: passt-dev@passt.top, lvivier@redhat.com,
david@gibson.dropbear.id.au, jmaloy@redhat.com
Subject: Re: [PATCH v5 3/7] dhcp: Add option overload
Date: Mon, 27 Jul 2026 08:19:11 +0200 (CEST) [thread overview]
Message-ID: <20260727081910.1653e621@elisabeth> (raw)
In-Reply-To: <20260717175648.879152-4-anskuma@redhat.com>
On Fri, 17 Jul 2026 23:26:40 +0530
Anshu Kumari <anskuma@redhat.com> wrote:
> When the options field is full, overflow remaining DHCP options into
> the sname and file fields per RFC 2132 option 52.
>
> Per RFC 2132, Section 9.5, the boot file name is always placed in the
> 'file' header field. When a boot file is set, the file field is
> reserved from overload and overflow uses only the sname field.
>
> Link: https://bugs.passt.top/show_bug.cgi?id=192
> Signed-off-by: Anshu Kumari <anskuma@redhat.com>
> ---
> v5:
> - enhanced enum dhcp_overload to follow kernel-doc.
> - Inline fill_overflow() into fill()
> - Use state-based checks instead of slen
>
> v4:
> - Converted overload #defines to enum dhcp_overload.
> - Fixed missing whitespace in comment before */.
> - Boot file name always placed in 'file' header field per RFC 2132,
> Section 9.5; file field reserved from overload when bootfile is
> set; option 67 suppressed from options area.
>
> v3:
> - Added RFC 2132 Section 9.3 reference comment on overload
> constants.
> - Use ARRAY_SIZE(opts) instead of raw 255 in fill_overflow().
> - Swapped overflow order: try sname (64 bytes) first, then file
> (128 bytes) — better packing and keeps file field available for
> boot file name.
> - Removed '&' from &reply.file.
> - Removed '+1' from memcpy — reply.file already zeroed.
> - opt_set_dns_search() max_len: OPT_MAX - 3 instead of
> sizeof(m->o).
>
> v2:
> - Added #define DHCP_OVERLOAD_FILE and #define DHCP_OVERLOAD_SNAME constants
> - Added comment documenting space reservation: /* Reserve 3 bytes for option 52 */
> - Fixed DNS search length: sizeof(m->o) only, not combined with file+sname
> - Removed dhcp_boot references — reply.file copy now reads from opts[67]
> - Used DHCP_OVERLOAD_FILE constant in reply.file guard
>
> ---
> dhcp.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
> 1 file changed, 79 insertions(+), 9 deletions(-)
>
> diff --git a/dhcp.c b/dhcp.c
> index e5d89fc..39f7952 100644
> --- a/dhcp.c
> +++ b/dhcp.c
> @@ -176,13 +176,31 @@ static bool fill_one(uint8_t *buf, size_t size, int o, int *offset)
> }
>
> /**
> - * fill() - Fill options in message
> - * @m: Message to fill
> +* enum dhcp_overload - DHCP option overload values (RFC 2132, Section 9.3)
> + * @DHCP_OVERLOAD_NONE: No overload
> + * @DHCP_OVERLOAD_FILE: file field carries options
> + * @DHCP_OVERLOAD_SNAME: sname field carries options
> + */
> +enum dhcp_overload {
> + DHCP_OVERLOAD_NONE,
> + DHCP_OVERLOAD_FILE,
> + DHCP_OVERLOAD_SNAME,
> +};
> +
> +/**
> + * 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)
> + * @has_bootfile: Reserve file field for boot file name
> *
> * Return: current size of options field
> */
> -static int fill(struct msg *m)
> +static int fill(struct msg *m, enum dhcp_overload *overload, bool has_bootfile)
> {
> + int sname_off = 0, file_off = 0;
> + *overload = DHCP_OVERLOAD_NONE;
> + /* Reserve 3 bytes for option 52 (overload) if needed */
> + size_t size = OPT_MAX - 3;
Even though C11 admits this, for coding style reasons, we avoid mixing
code and declarations. You could simply assign *overload later.
> int i, o, offset = 0;
>
> for (o = 0; o < 255; o++)
> @@ -199,14 +217,47 @@ static int fill(struct msg *m)
> for (i = 0; i < opts[55].clen; i++) {
> o = opts[55].c[i];
> if (opts[o].state != OPT_UNSET)
> - if (fill_one(m->o, OPT_MAX, o, &offset))
> - debug("DHCP: skipping option %i", o);
> + fill_one(m->o, size, o, &offset);
> }
>
> for (o = 0; o < 255; o++) {
> if (opts[o].state != OPT_UNSET && !opts[o].sent)
> - if (fill_one(m->o, OPT_MAX, o, &offset))
> - debug("DHCP: skipping option %i", o);
> + fill_one(m->o, size, o, &offset);
> + }
> +
> + /* Overflow unsent options into sname, then file */
> + for (o = 0; (size_t)o < ARRAY_SIZE(opts); o++) {
> + if (opts[o].state == OPT_UNSET || opts[o].sent)
> + continue;
> + fill_one(m->sname, sizeof(m->sname) - 1, o, &sname_off);
> + }
> +
> + for (o = 0; (size_t)o < ARRAY_SIZE(opts); o++) {
> + if (opts[o].state == OPT_UNSET || opts[o].sent)
> + continue;
> +
> + if (!has_bootfile &&
> + fill_one(m->file, sizeof(m->file) - 1, o,
> + &file_off))
Nit: this should be indented like this:
if (!has_bootfile &&
fill_one(m->file, sizeof(m->file) - 1, o, &file_off))
so that terms that are logically on the same level are also aligned
visually. And:
> + debug("DHCP: skipping option %i"
> + " (overload full)", o);
...the indentation of this one if misleading (it looks like you have
two if clauses). On the other hand, if David's suggestion about making
fill() return void and print errors later works, this would go away
altogether.
> + }
> +
> + if (sname_off) {
> + m->sname[sname_off] = 255;
> + *overload |= DHCP_OVERLOAD_SNAME;
> + }
> +
> + if (file_off) {
> + m->file[file_off] = 255;
> + *overload |= DHCP_OVERLOAD_FILE;
> + }
> +
> +
Excess blank line.
> + if (*overload) {
> + m->o[offset++] = 52;
> + m->o[offset++] = 1;
> + m->o[offset++] = *overload;
> }
>
> m->o[offset++] = 255;
> @@ -320,6 +371,7 @@ static void opt_set_dns_search(const struct ctx *c, size_t max_len)
> int dhcp(const struct ctx *c, struct iov_tail *data)
> {
> char macstr[ETH_ADDRSTRLEN];
> + enum dhcp_overload overload;
> size_t mlen, dlen, opt_len;
> struct in_addr mask, dst;
> struct ethhdr eh_storage;
> @@ -328,9 +380,12 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
> const struct ethhdr *eh;
> const struct iphdr *iph;
> const struct udphdr *uh;
> + uint8_t bootfile[128];
> struct msg m_storage;
> struct msg const *m;
> + bool has_bootfile;
> struct msg reply;
> + int bootfile_len;
> unsigned int i;
>
> eh = IOV_REMOVE_HEADER(data, eh_storage);
> @@ -492,9 +547,24 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
> }
>
> if (!c->no_dhcp_dns_search)
> - opt_set_dns_search(c, sizeof(m->o));
> + /* 3 bytes reserved for option 52 (code, length, value) */
Nits: excess whitespace before /*.
Even if not needed, our coding style uses curly brackets whenever we
have multiple lines (not statements) inside an if clause.
> + opt_set_dns_search(c, OPT_MAX - 3);
> +
> + /* RFC 2132, Section 9.5: put boot file name in the 'file' header
> + * field. Suppress option 67 from the options area and reserve
> + * the file field from overload.
> + */
> + has_bootfile = opts[67].slen > 0 &&
> + (size_t)opts[67].slen < sizeof(reply.file);
This looks reasonable, I'm not sure if it's mandatory (I couldn't find
anything in the RFCs that would mandate it). If it's not, we might be
wasting precious space in the 'file' field if the filename is short,
and keeping it as an option would actually save space (think of a
filename that's 8 characters long).
On the other hand, deciding whether to send the filename as an option
or as 'file' is probably not trivial, so, unless you have a quick
solution in mind, I'd just skip that and keep things like this.
> + if (has_bootfile) {
> + memcpy(bootfile, opts[67].s, opts[67].slen);
> + bootfile_len = opts[67].slen;
> + }
> +
> + dlen = offsetof(struct msg, o) + fill(&reply, &overload, has_bootfile);
>
> - dlen = offsetof(struct msg, o) + fill(&reply);
> + if (has_bootfile)
> + memcpy(reply.file, bootfile, bootfile_len);
>
> if (m->flags & FLAG_BROADCAST)
> dst = in4addr_broadcast;
--
Stefano
next prev parent reply other threads:[~2026-07-27 6:19 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 17:56 [PATCH v5 0/7] Add --dhcp-boot and --dhcp-opt options Anshu Kumari
2026-07-17 17:56 ` [PATCH v5 1/7] dhcp: Refactor fill_one() to operate on a generic buffer Anshu Kumari
2026-07-20 1:18 ` David Gibson
2026-07-17 17:56 ` [PATCH v5 2/7] dhcp: Add option state management with enum opt_state Anshu Kumari
2026-07-20 1:36 ` David Gibson
2026-07-27 6:18 ` Stefano Brivio
2026-07-17 17:56 ` [PATCH v5 3/7] dhcp: Add option overload Anshu Kumari
2026-07-20 2:03 ` David Gibson
2026-07-27 6:19 ` Stefano Brivio [this message]
2026-07-17 17:56 ` [PATCH v5 4/7] dhcp: Add --dhcp-opt with option table and value parser Anshu Kumari
2026-07-20 3:58 ` David Gibson
2026-07-27 6:19 ` Stefano Brivio
2026-07-17 17:56 ` [PATCH v5 5/7] dhcp: Add --dhcp-boot command-line option Anshu Kumari
2026-07-20 4:06 ` David Gibson
2026-07-17 17:56 ` [PATCH v5 6/7] dhcp: Add RFC 3396 option splitting for concatenation-requiring options Anshu Kumari
2026-07-20 4:21 ` David Gibson
2026-07-20 9:14 ` Anshu Kumari
2026-07-27 3:00 ` David Gibson
2026-07-27 6:19 ` Stefano Brivio
2026-07-17 17:56 ` [PATCH v5 7/7] dhcp: Handle FQDN option with RFC 3396 concatenation Anshu Kumari
2026-07-20 4:23 ` David Gibson
2026-07-20 7:38 ` Anshu Kumari
2026-07-21 0:34 ` 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=20260727081910.1653e621@elisabeth \
--to=sbrivio@redhat.com \
--cc=anskuma@redhat.com \
--cc=david@gibson.dropbear.id.au \
--cc=jmaloy@redhat.com \
--cc=lvivier@redhat.com \
--cc=passt-dev@passt.top \
/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).