From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZQMg281T; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by passt.top (Postfix) with ESMTPS id A1A325A026D for ; Mon, 18 May 2026 15:20:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1779110431; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zJ5z/Gee4Lf9ZcqrsV43fUaVCMswm3m3DIGloykmiP0=; b=ZQMg281TNwAovQddCSBRkn9PK9clUSwvsL/7O2pkZQlRWeSZ3KOpnhFb3UB98gbFoup9rd zeN5GlFSCKQ6jEkBfzP4ODHdzoaQST9QdgnWJnH0YY0kuLkJNlcUddrMUCOJpnBFRLEeVl 9I0BPFkSJfeslhgTuh5XmbTyZks7zHM= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-97-cgi0zw-sN_2VQpHXLkVUcA-1; Mon, 18 May 2026 09:20:28 -0400 X-MC-Unique: cgi0zw-sN_2VQpHXLkVUcA-1 X-Mimecast-MFC-AGG-ID: cgi0zw-sN_2VQpHXLkVUcA_1779110427 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 681FD19560A7; Mon, 18 May 2026 13:20:27 +0000 (UTC) Received: from anskuma-thinkpadp1gen7.bengluru.csb (unknown [10.74.80.120]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1F00318004A3; Mon, 18 May 2026 13:20:23 +0000 (UTC) From: Anshu Kumari To: anskuma@redhat.com, sbrivio@redhat.com, passt-dev@passt.top Subject: [PATCH 5/6] dhcp: Add option overload Date: Mon, 18 May 2026 18:50:01 +0530 Message-ID: <20260518132002.418296-6-anskuma@redhat.com> In-Reply-To: <20260518132002.418296-5-anskuma@redhat.com> References: <20260518132002.418296-1-anskuma@redhat.com> <20260518132002.418296-2-anskuma@redhat.com> <20260518132002.418296-3-anskuma@redhat.com> <20260518132002.418296-4-anskuma@redhat.com> <20260518132002.418296-5-anskuma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 7EGVAQdgUbxjCt45otnneJS14k-TtCL0WShHF6Tx8lU_1779110427 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: MTPBNJTNG5GSFI5UDSSGUB7H65IAHVAV X-Message-ID-Hash: MTPBNJTNG5GSFI5UDSSGUB7H65IAHVAV X-MailFrom: anskuma@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: lvivier@redhat.com, jmaloy@redhat.com, david@gibson.dropbear.id.au X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- 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