linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] net: ipv4: ipconfig: Support RFC 4361/3315 DHCP client ID in hex format
@ 2025-06-10 14:35 Petr Zejdl
  2025-06-13  2:17 ` Jakub Kicinski
  0 siblings, 1 reply; 3+ messages in thread
From: Petr Zejdl @ 2025-06-10 14:35 UTC (permalink / raw)
  To: petr.zejdl
  Cc: David S. Miller, David Ahern, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, netdev, linux-kernel

Allow specifying a DHCP client ID in the hexadecimal format resembling
MAC address format (e.g., "01:23:45:67:89:ab .. ef").

The client ID can now be passed on the kernel command line using:
  ip=dhcp,<hex-client-id>

This format is the same as that used in ISC-DHCP server configuration,
allowing compatibility with widely used user-space tooling.

This is a backward-compatible extension to the existing:
  ip=dhcp,<client-id-type>,<client-id-value>

The existing format expects a text string as the client-id-value,
which is not compatible with binary client IDs. This adds support
for binary client IDs as specified in RFC 4361 and RFC 3315.
Binary client IDs are used in embedded systems, including geographical
addressing schemes (e.g., HPM-3-style client IDs in ATCA crates).

Signed-off-by: Petr Zejdl <petr.zejdl@cern.ch>
---
 net/ipv4/ipconfig.c | 63 ++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 54 insertions(+), 9 deletions(-)

diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index c56b6fe6f0d7..000d918cc811 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -146,7 +146,8 @@ u8 root_server_path[256] = { 0, };	/* Path to mount as root */
 static char vendor_class_identifier[253] __initdata;
 
 #if defined(CONFIG_IP_PNP_DHCP)
-static char dhcp_client_identifier[253] __initdata;
+static u8 dhcp_client_identifier[253] __initdata;
+static int dhcp_client_identifier_len __initdata;
 #endif
 
 /* Persistent data: */
@@ -740,15 +741,22 @@ ic_dhcp_init_options(u8 *options, struct ic_device *d)
 			memcpy(e, vendor_class_identifier, len);
 			e += len;
 		}
-		len = strlen(dhcp_client_identifier + 1);
 		/* the minimum length of identifier is 2, include 1 byte type,
 		 * and can not be larger than the length of options
 		 */
-		if (len >= 1 && len < 312 - (e - options) - 1) {
-			*e++ = 61;
-			*e++ = len + 1;
-			memcpy(e, dhcp_client_identifier, len + 1);
-			e += len + 1;
+		if (dhcp_client_identifier_len >= 2) {
+			if (dhcp_client_identifier_len <= 312 - (e - options) - 3) {
+				pr_debug("DHCP: sending client identifier %*phC\n",
+					 dhcp_client_identifier_len,
+					 dhcp_client_identifier);
+				*e++ = 61;
+				*e++ = dhcp_client_identifier_len;
+				memcpy(e, dhcp_client_identifier,
+				       dhcp_client_identifier_len);
+				e += dhcp_client_identifier_len;
+			} else {
+				pr_warn("DHCP: client identifier doesn't fit in the packet\n");
+			}
 		}
 	}
 
@@ -1661,6 +1669,33 @@ static int __init ip_auto_config(void)
 
 late_initcall(ip_auto_config);
 
+#ifdef CONFIG_IP_PNP_DHCP
+/*
+ *  Parses DHCP Client ID in the hex form "XX:XX ... :XX" (like MAC address).
+ *  Returns the length (min 2, max 253) or -EINVAL on parsing error.
+ */
+static int __init parse_client_id(const char *s, u8 *buf)
+{
+	int slen = strlen(s);
+	int len = (slen + 1) / 3;
+	int i;
+
+	/* Format: XX:XX ... :XX */
+	if (len * 3 - 1 != slen || len < 2 || len > 253)
+		return -EINVAL;
+
+	for (i = 0; i < len; i++) {
+		if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1]))
+			return -EINVAL;
+		if (i != len - 1 && s[i * 3 + 2] != ':')
+			return -EINVAL;
+
+		buf[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
+	}
+
+	return i;
+}
+#endif
 
 /*
  *  Decode any IP configuration options in the "ip=" or "nfsaddrs=" kernel
@@ -1685,12 +1720,22 @@ static int __init ic_proto_name(char *name)
 
 			client_id = client_id + 5;
 			v = strchr(client_id, ',');
-			if (!v)
+			if (!v) {
+				int len = parse_client_id(client_id,
+							  dhcp_client_identifier);
+				if (len < 0)
+					pr_warn("DHCP: Invalid client identifier \"%s\"\n",
+						client_id);
+				else
+					dhcp_client_identifier_len = len;
 				return 1;
+			}
+			/* Client ID in the text form */
 			*v = 0;
 			if (kstrtou8(client_id, 0, dhcp_client_identifier))
-				pr_debug("DHCP: Invalid client identifier type\n");
+				pr_warn("DHCP: Invalid client identifier type\n");
 			strncpy(dhcp_client_identifier + 1, v + 1, 251);
+			dhcp_client_identifier_len = strlen(dhcp_client_identifier + 1) + 1;
 			*v = ',';
 		}
 		return 1;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] net: ipv4: ipconfig: Support RFC 4361/3315 DHCP client ID in hex format
  2025-06-10 14:35 [PATCH] net: ipv4: ipconfig: Support RFC 4361/3315 DHCP client ID in hex format Petr Zejdl
@ 2025-06-13  2:17 ` Jakub Kicinski
  2025-06-13 22:37   ` Petr Zejdl
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Kicinski @ 2025-06-13  2:17 UTC (permalink / raw)
  To: Petr Zejdl
  Cc: David S. Miller, David Ahern, Eric Dumazet, Paolo Abeni,
	Simon Horman, netdev, linux-kernel

On Tue, 10 Jun 2025 16:35:03 +0200 Petr Zejdl wrote:
> -		len = strlen(dhcp_client_identifier + 1);

maybe keep using len here? Assign dhcp_client_identifier_len to it?
I don't think switching to dhcp_client_identifier_len improves the
readability and it inflates the diff.

>  		/* the minimum length of identifier is 2, include 1 byte type,
>  		 * and can not be larger than the length of options
>  		 */
> -		if (len >= 1 && len < 312 - (e - options) - 1) {
> -			*e++ = 61;
> -			*e++ = len + 1;
> -			memcpy(e, dhcp_client_identifier, len + 1);
> -			e += len + 1;
> +		if (dhcp_client_identifier_len >= 2) {
> +			if (dhcp_client_identifier_len <= 312 - (e - options) - 3) {
> +				pr_debug("DHCP: sending client identifier %*phC\n",
> +					 dhcp_client_identifier_len,
> +					 dhcp_client_identifier);
> +				*e++ = 61;
> +				*e++ = dhcp_client_identifier_len;
> +				memcpy(e, dhcp_client_identifier,
> +				       dhcp_client_identifier_len);
> +				e += dhcp_client_identifier_len;
> +			} else {
> +				pr_warn("DHCP: client identifier doesn't fit in the packet\n");
> +			}
>  		}
>  	}
>  
> @@ -1661,6 +1669,33 @@ static int __init ip_auto_config(void)
>  
>  late_initcall(ip_auto_config);
>  
> +#ifdef CONFIG_IP_PNP_DHCP
> +/*
> + *  Parses DHCP Client ID in the hex form "XX:XX ... :XX" (like MAC address).
> + *  Returns the length (min 2, max 253) or -EINVAL on parsing error.
> + */
> +static int __init parse_client_id(const char *s, u8 *buf)
> +{
> +	int slen = strlen(s);
> +	int len = (slen + 1) / 3;
> +	int i;
> +
> +	/* Format: XX:XX ... :XX */
> +	if (len * 3 - 1 != slen || len < 2 || len > 253)
> +		return -EINVAL;
> +
> +	for (i = 0; i < len; i++) {
> +		if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1]))
> +			return -EINVAL;
> +		if (i != len - 1 && s[i * 3 + 2] != ':')
> +			return -EINVAL;
> +
> +		buf[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
> +	}
> +
> +	return i;
> +}

Feels like this helper should live in lib/net_utils.c or lib/hexdump.c
as a generic thing?
-- 
pw-bot: cr

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] net: ipv4: ipconfig: Support RFC 4361/3315 DHCP client ID in hex format
  2025-06-13  2:17 ` Jakub Kicinski
@ 2025-06-13 22:37   ` Petr Zejdl
  0 siblings, 0 replies; 3+ messages in thread
From: Petr Zejdl @ 2025-06-13 22:37 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: petr.zejdl, David S. Miller, David Ahern, Eric Dumazet,
	Paolo Abeni, Simon Horman, netdev, linux-kernel

I'm sorry, now in the correct format.

On 13.06.2025 4:17, Jakub Kicinski wrote:
> On Tue, 10 Jun 2025 16:35:03 +0200 Petr Zejdl wrote:
>> -		len = strlen(dhcp_client_identifier + 1);
> maybe keep using len here? Assign dhcp_client_identifier_len to it?
> I don't think switching to dhcp_client_identifier_len improves the
> readability and it inflates the diff.

Indeed.

>> +/*
>> + *  Parses DHCP Client ID in the hex form "XX:XX ... :XX" (like MAC address).
>> + *  Returns the length (min 2, max 253) or -EINVAL on parsing error.
>> + */
>> +static int __init parse_client_id(const char *s, u8 *buf)
>> ...
> Feels like this helper should live in lib/net_utils.c or lib/hexdump.c
> as a generic thing?

Sounds good, will come with a new version.

I should also update 'Documentation/admin-guide/nfs/nfsroot.rst' with
the new Client ID format.

Thank you for the review.

Best regards,
Petr


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-06-13 22:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-10 14:35 [PATCH] net: ipv4: ipconfig: Support RFC 4361/3315 DHCP client ID in hex format Petr Zejdl
2025-06-13  2:17 ` Jakub Kicinski
2025-06-13 22:37   ` Petr Zejdl

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 NNTP newsgroup(s).