public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
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


  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).