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=ZsrspUEC; 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 DB89A5A0271 for ; Thu, 01 Oct 2026 15:16:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1790860586; 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=d6QMkT+oMGV6nbMHzEz68m6GvWDKMYEn/pZhTiRkuzI=; b=ZsrspUECMZ8hIltaaPJb4o1oR/t7Il2CMkXjf8f/2HpKno6KhHiGf2EvY1xmi65XqwZunb C9p+ujXL8VMVhcP2IMFJpfVjyk+HbV23pVFxRD6Q9YZzTmOq3nK+f0w9o/WBgmdj5bqxbR Ngxxl/h0gqtpeUgW6UQGEMyUrYBJ+9c= Received: from mx-prod-mc-03.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-507-iuTQcwDoP0allcR46n3oxw-1; Thu, 01 Oct 2026 09:16:24 -0400 X-MC-Unique: iuTQcwDoP0allcR46n3oxw-1 X-Mimecast-MFC-AGG-ID: iuTQcwDoP0allcR46n3oxw_1790860584 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E442C1955F43 for ; Thu, 1 Oct 2026 13:16:23 +0000 (UTC) Received: from anskuma-thinkpadp1gen7.bengluru.csb (unknown [10.74.80.122]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 05FFC1800446; Thu, 1 Oct 2026 13:16:21 +0000 (UTC) From: Anshu Kumari To: sbrivio@redhat.com, passt-dev@passt.top Subject: [PATCH v7 6/7] dhcp: Add option overload Date: Thu, 1 Oct 2026 18:45:59 +0530 Message-ID: <20261001131602.653553-7-anskuma@redhat.com> In-Reply-To: <20261001131602.653553-1-anskuma@redhat.com> References: <20261001131602.653553-1-anskuma@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: REhqzuYUNEIRoQI89fRkT4uv1ceJhLDzLxQ4m46jY-w_1790860584 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: WQE5E7TXYQGOKVO4AVAHZ3AAAG7D4SDW X-Message-ID-Hash: WQE5E7TXYQGOKVO4AVAHZ3AAAG7D4SDW 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, anskuma@redhat.com 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: 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 --- v7: - Removed overload function parameter - Added foreach_opt() macro to iterate option table Till v6 both "patch 5/7" and "patch 6/7" were one. --- dhcp.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/dhcp.c b/dhcp.c index 6f69fd62..63ac8e3d 100644 --- a/dhcp.c +++ b/dhcp.c @@ -67,6 +67,8 @@ struct opt { static struct opt opts[256]; +#define foreach_opt(o) for ((o) = 0; (size_t)(o) < ARRAY_SIZE(opts); (o)++) + #define DHCPDISCOVER 1 #define DHCPOFFER 2 #define DHCPREQUEST 3 @@ -440,13 +442,30 @@ static void 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 = 0, + DHCP_OVERLOAD_FILE = 1, + DHCP_OVERLOAD_SNAME = 2, +}; + +/** + * fill() - Fill options in message, with overload into file/sname if needed + * @m: Message to fill + * @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, bool has_bootfile) { + enum dhcp_overload overload = DHCP_OVERLOAD_NONE; + int sname_off = 0, file_off = 0; + /* Reserve 3 bytes for option 52 (overload) if needed */ + size_t size = OPT_MAX - 3; int i, o, offset = 0; for (o = 0; o < 255; o++) @@ -457,17 +476,54 @@ 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)) - fill_one(m->o, OPT_MAX, 53, &offset); + fill_one(m->o, size, 53, &offset); for (i = 0; i < opts[55].clen; i++) { o = opts[55].c[i]; if (opts[o].conf != OPT_UNSET) - fill_one(m->o, OPT_MAX, o, &offset); + fill_one(m->o, size, o, &offset); } for (o = 0; o < 255; o++) { if (opts[o].conf != OPT_UNSET && !opts[o].sent) - fill_one(m->o, OPT_MAX, o, &offset); + fill_one(m->o, size, o, &offset); + } + + /* Overflow unsent options into sname, then file */ + foreach_opt(o) { + if (opts[o].conf == OPT_UNSET || opts[o].sent) + continue; + fill_one(m->sname, sizeof(m->sname) - 1, o, &sname_off); + } + + if (!has_bootfile) { + foreach_opt(o) { + if (opts[o].conf == OPT_UNSET || opts[o].sent) + continue; + fill_one(m->file, sizeof(m->file) - 1, o, &file_off); + } + } + + /* Report any options that could not be sent */ + foreach_opt(o) { + if (opts[o].conf != OPT_UNSET && !opts[o].sent) + debug("DHCP: skipping option %i", o); + } + + if (sname_off) { + m->sname[sname_off] = 255; + overload |= DHCP_OVERLOAD_SNAME; + } + + if (file_off) { + m->file[file_off] = 255; + overload |= DHCP_OVERLOAD_FILE; + } + + if (overload) { + m->o[offset++] = 52; + m->o[offset++] = 1; + m->o[offset++] = overload; } m->o[offset++] = 255; @@ -761,16 +817,18 @@ int dhcp(const struct ctx *c, struct iov_tail *data) } } - if (!c->no_dhcp_dns_search) - opt_set_dns_search(c, sizeof(m->o)); + if (!c->no_dhcp_dns_search) { + /* 3 bytes reserved for option 52 (code, length, value) */ + opt_set_dns_search(c, OPT_MAX - 3); + } /* RFC 2132, Section 9.5: put boot file name in the 'file' header - * field. + * field. Reserve the file field from overload. */ has_bootfile = opts[67].slen > 0 && (size_t)opts[67].slen < sizeof(reply.file); - dlen = offsetof(struct msg, o) + fill(&reply); + dlen = offsetof(struct msg, o) + fill(&reply, has_bootfile); if (has_bootfile) memcpy(reply.file, opts[67].s, opts[67].slen); -- 2.55.0