From: Stefano Brivio <sbrivio@redhat.com>
To: Anshu Kumari <anskuma@redhat.com>
Cc: passt-dev@passt.top, lvivier@redhat.com
Subject: Re: [PATCH v7 3/7] dhcp: Add --dhcp-opt with option table and value parser
Date: Thu, 08 Oct 2026 00:06:17 +0200 (CEST) [thread overview]
Message-ID: <20261008000617.0f8f22a9@elisabeth> (raw)
In-Reply-To: <20261001131602.653553-4-anskuma@redhat.com>
On Thu, 1 Oct 2026 18:45:56 +0530
Anshu Kumari <anskuma@redhat.com> wrote:
> Add a --dhcp-opt CODE,VALUE flag that sets any DHCP option by
> numeric code with type-aware parsing per RFC 2132.
>
> A type lookup table maps option codes to RFC 2132 value types
> (IPv4, IPv4 list, integer, string). dhcp_opt_parse() converts
> CLI strings to binary wire format; parsed options are stored in
> opts[] and injected into DHCP replies. Options set via --dhcp-opt
> (OPT_USER) take priority over host-derived defaults (OPT_DEFAULT).
>
> Link: https://bugs.passt.top/show_bug.cgi?id=192
> Signed-off-by: Anshu Kumari <anskuma@redhat.com>
> ---
> v7:
> - Removed client-only options 50 (Requested IP) and 57 (Max Message Size)
> from dhcp_opt_types[]
> - Switched integer parsing from strtoul()/strtol() to parse_unsigned()
> for UINT8/UINT16/UINT32 types
> - Fixed alignment: use htons()/htonl() + memcpy() instead of direct
> pointer casts for UINT16/UINT32 encoding.
> - Used explicit OPT_DEFAULT check instead of != OPT_USER where the condition
> body does not set conf.
> - Removed unnecessary OPT_USER guard on option 121
> - Checked inet_ntop() return value in dhcp_opt_to_str()
>
> v6:
> - dropped option 53.
> - Used parse_unsigned(), parse_literal(), parse_ipv4()
> from parse.c instead of manual strtoul/inet_pton.
> - Moved option-parsing variables into case 34 block
> scope.
This change comes from David's suggestion in:
https://archives.passt.top/passt-dev/al2c8QVZUuQB69HV@zatzit/
...but back then it was three variables. Now it's one:
> [...]
>
> @@ -1589,6 +1596,24 @@ void conf(struct ctx *c, int argc, char **argv)
> case 32:
> c->chroot_fallback = true;
> break;
> + case 34: {
> + unsigned long optcode;
...which I think could happily be declared at the top of the function
along with max_mtu.
In general, I think it would be good to avoid mixing up scoping logic
in case switches (we almost always avoid extra blocks, except for a few
cases here which I missed during review), because if we do the code
becomes a bit more surprising (where do you look for variable
declarations?).
Other than that, I see the point of keeping variable scope limited. But
here it's just one variable, so I think it could really be declared at
the beginning of the function without much thinking.
> [...]
>
> +/**
> + * dhcp_opt_to_str() - Render a binary DHCP option value to a printable string
> + * @code: DHCP option code
> + * @buf: Output string buffer
> + * @buf_len: Size of output buffer
> + *
> + * Return: pointer to @buf if option is set, NULL otherwise
> + */
> +const char *dhcp_opt_to_str(uint8_t code, char *buf, size_t buf_len)
> +{
> + enum dhcp_opt_type type;
> + unsigned int i;
> + int off = 0;
> +
> + if (opts[code].conf == OPT_UNSET)
> + return NULL;
> +
> + assert(code < ARRAY_SIZE(dhcp_opt_types));
> +
> + type = dhcp_opt_types[code];
> +
> + switch (type) {
> + case DHCP_OPT_IPV4:
> + case DHCP_OPT_IPV4_LIST:
> + for (i = 0; i + sizeof(struct in_addr) <= (unsigned int)opts[code].slen;
Given that opts[code].slen doesn't change in this loop, perhaps a
temporary variable holding it would make this more readable.
> + i += sizeof(struct in_addr)) {
> + if (off) {
> + if (off + 1 >= (int)buf_len)
> + return NULL;
> + buf[off++] = ',';
> + }
> + if (!inet_ntop(AF_INET, opts[code].s + i,
> + buf + off, buf_len - off))
> + return NULL;
> + off += strlen(buf + off);
> + }
> + return buf;
> + case DHCP_OPT_UINT8:
> + case DHCP_OPT_UINT16:
> + case DHCP_OPT_UINT32: {
Same here ('uval'?).
> + uint32_t val = 0;
> +
> + if (opts[code].slen == 1) {
> + val = opts[code].s[0];
> + } else if (opts[code].slen == 2) {
> + uint16_t v16;
> + memcpy(&v16, opts[code].s, sizeof(v16));
> + val = ntohs(v16);
> + } else if (opts[code].slen == 4) {
> + memcpy(&val, opts[code].s, sizeof(val));
> + val = ntohl(val);
> + }
> +
> + if (snprintf(buf, buf_len, "%u", val) >= (int)buf_len)
> + return NULL;
> + return buf;
> + }
> + case DHCP_OPT_INT32: {
> + int32_t val;
And here. This one is especially surprising because there's another
'val' just above, and if you miss that curly bracket then you would
think that the usual style / scoping applies, but it doesn't.
> + uint32_t v32;
> +
> + assert(opts[code].slen == 4);
> + memcpy(&v32, opts[code].s, sizeof(v32));
> + val = (int32_t)ntohl(v32);
> +
> + if (snprintf(buf, buf_len, "%d", val) >= (int)buf_len)
> + return NULL;
> + return buf;
> + }
> + case DHCP_OPT_STR:
> + (void)snprintf(buf, buf_len, "%.*s",
> + opts[code].slen, opts[code].s);
> + return buf;
> + default:
> + assert(0);
> + }
> +}
> +
>
> [...]
--
Stefano
next prev parent reply other threads:[~2026-10-07 22:06 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 13:15 [PATCH v7 0/7] Add --dhcp-boot and --dhcp-opt options Anshu Kumari
2026-10-01 13:15 ` [PATCH v7 1/7] dhcp: Refactor fill_one() to operate on a generic buffer Anshu Kumari
2026-10-01 13:15 ` [PATCH v7 2/7] dhcp: Add option configuration tracking with enum opt_conf Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio
2026-10-01 13:15 ` [PATCH v7 3/7] dhcp: Add --dhcp-opt with option table and value parser Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio [this message]
2026-10-01 13:15 ` [PATCH v7 4/7] dhcp: Add --dhcp-boot command-line option Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio
2026-10-01 13:15 ` [PATCH v7 5/7] dhcp: Change fill_one() to return void Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio
2026-10-01 13:15 ` [PATCH v7 6/7] dhcp: Add option overload Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio
2026-10-01 13:16 ` [PATCH v7 7/7] dhcp: Add RFC 3396 option splitting for concatenation-requiring options Anshu Kumari
2026-10-07 22:06 ` Stefano Brivio
2026-10-07 22:06 ` [PATCH v7 0/7] Add --dhcp-boot and --dhcp-opt options Stefano Brivio
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=20261008000617.0f8f22a9@elisabeth \
--to=sbrivio@redhat.com \
--cc=anskuma@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).