fa1179c
From f01a29a90269c98a86accb0923d65aecf5f59b44 Mon Sep 17 00:00:00 2001
9c49c9e
From: Pavel Zhukov <pzhukov@redhat.com>
9c49c9e
Date: Thu, 28 Feb 2019 16:40:38 +0100
fa1179c
Subject: [PATCH 23/28] option 97 - pxe-client-id
9c49c9e
9c49c9e
Bug-url: https://bugzilla.redhat.com/1058674
9c49c9e
ISC-Bugs #38110
9c49c9e
---
9c49c9e
 common/options.c        | 27 ++++++++++++++++++++-------
9c49c9e
 common/tables.c         |  3 ++-
9c49c9e
 includes/dhcp.h         |  1 +
9c49c9e
 server/dhcp.c           | 19 +++++++++++++++++++
9c49c9e
 server/dhcpd.conf.5     |  9 ++++++---
9c49c9e
 server/dhcpleasequery.c | 18 +++++++++++++++---
9c49c9e
 server/failover.c       |  3 +++
9c49c9e
 server/mdb.c            |  5 +++--
9c49c9e
 8 files changed, 69 insertions(+), 16 deletions(-)
9c49c9e
9c49c9e
diff --git a/common/options.c b/common/options.c
fa1179c
index 66433c4..4e26094 100644
9c49c9e
--- a/common/options.c
9c49c9e
+++ b/common/options.c
fa1179c
@@ -4551,13 +4551,26 @@ int validate_packet(struct packet *packet)
9c49c9e
 				"a future version of ISC DHCP will reject this");
9c49c9e
 		}
9c49c9e
 	} else {
9c49c9e
-		/*
9c49c9e
-		 * If hlen is 0 we don't have any identifier, we warn the user
9c49c9e
-		 * but continue processing the packet as we can.
9c49c9e
-		 */
9c49c9e
-		if (packet->raw->hlen == 0) {
9c49c9e
-			log_debug("Received DHCPv4 packet without client-id"
9c49c9e
-				  " option and empty hlen field.");
9c49c9e
+		oc = lookup_option (&dhcp_universe, packet->options,
9c49c9e
+				    DHO_PXE_CLIENT_ID);
9c49c9e
+		if (oc) {
9c49c9e
+			/* Let's check if pxe-client-id is sane */
9c49c9e
+			if ((oc->data.len < 2) ||
9c49c9e
+			    (oc->data.data[0] == '\0' &&
9c49c9e
+			     oc->data.len != 17)) {
9c49c9e
+				log_debug("Dropped DHCPv4 packet with wrong "
9c49c9e
+				    "(len == %d) pxe-client-id", oc->data.len);
9c49c9e
+				return (0);
9c49c9e
+			}
9c49c9e
+		} else {
9c49c9e
+			/*
9c49c9e
+			 * If hlen is 0 we don't have any identifier, we warn the user
9c49c9e
+			 * but continue processing the packet as we can.
9c49c9e
+			 */
9c49c9e
+			if (packet->raw->hlen == 0) {
9c49c9e
+				log_debug("Received DHCPv4 packet without client-id"
9c49c9e
+						" option and empty hlen field.");
9c49c9e
+			}
9c49c9e
 		}
9c49c9e
 	}
9c49c9e
 
9c49c9e
diff --git a/common/tables.c b/common/tables.c
fa1179c
index 96521a6..8034d94 100644
9c49c9e
--- a/common/tables.c
9c49c9e
+++ b/common/tables.c
fa1179c
@@ -200,8 +200,9 @@ static struct option dhcp_options[] = {
9c49c9e
 	/* Defined by RFC 4578 */
9c49c9e
 	{ "pxe-system-type", "Sa",		&dhcp_universe,  93, 1 },
9c49c9e
 	{ "pxe-interface-id", "BBB",		&dhcp_universe,  94, 1 },
9c49c9e
-	{ "pxe-client-id", "BX",		&dhcp_universe,  97, 1 },
9c49c9e
 #endif
9c49c9e
+	{ "pxe-client-id", "BX",		&dhcp_universe,  97, 1 },
9c49c9e
+
9c49c9e
 	{ "uap-servers", "t",			&dhcp_universe,  98, 1 },
9c49c9e
 #if defined(RFC4776_OPTIONS)
9c49c9e
         { "geoconf-civic", "X",                 &dhcp_universe, 99, 1 },
9c49c9e
diff --git a/includes/dhcp.h b/includes/dhcp.h
fa1179c
index 7202f1d..4ad3874 100644
9c49c9e
--- a/includes/dhcp.h
9c49c9e
+++ b/includes/dhcp.h
9c49c9e
@@ -158,6 +158,7 @@ struct dhcp_packet {
9c49c9e
 #define DHO_AUTHENTICATE			90  /* RFC3118, was 210 */
9c49c9e
 #define DHO_CLIENT_LAST_TRANSACTION_TIME	91
9c49c9e
 #define DHO_ASSOCIATED_IP			92
9c49c9e
+#define DHO_PXE_CLIENT_ID			97  /* RFC4578 */
fa1179c
 #define DHO_V6_ONLY_PREFERRED			108 /* RFC8925 */
9c49c9e
 #define DHO_SUBNET_SELECTION			118 /* RFC3011! */
9c49c9e
 #define DHO_DOMAIN_SEARCH			119 /* RFC3397 */
9c49c9e
diff --git a/server/dhcp.c b/server/dhcp.c
fa1179c
index 8363840..29d9c69 100644
9c49c9e
--- a/server/dhcp.c
9c49c9e
+++ b/server/dhcp.c
fa1179c
@@ -228,6 +228,10 @@ dhcp (struct packet *packet) {
9c49c9e
 		if (lease -> uid_len) {
9c49c9e
 			oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
 					    DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+			if (!oc)
9c49c9e
+				oc = lookup_option (&dhcp_universe,
9c49c9e
+						    packet -> options,
9c49c9e
+						    DHO_PXE_CLIENT_ID);
9c49c9e
 			if (!oc)
9c49c9e
 				goto nolease;
9c49c9e
 
fa1179c
@@ -826,6 +830,9 @@ void dhcprelease (packet, ms_nulltp)
9c49c9e
 
9c49c9e
 	oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
 			    DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+	if (!oc)
9c49c9e
+		oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
+				    DHO_PXE_CLIENT_ID);
9c49c9e
 	memset (&data, 0, sizeof data);
9c49c9e
 	if (oc &&
9c49c9e
 	    evaluate_option_cache (&data, packet, (struct lease *)0,
fa1179c
@@ -1338,6 +1345,9 @@ void dhcpinform (packet, ms_nulltp)
9c49c9e
          */
9c49c9e
 	oc = lookup_option(&dhcp_universe, packet->options,
9c49c9e
 			   DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+	if (!oc)
9c49c9e
+		oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
+				    DHO_PXE_CLIENT_ID);
9c49c9e
 	memset(&d1, 0, sizeof(d1));
9c49c9e
 	if (oc &&
9c49c9e
 	    evaluate_option_cache(&d1, packet, NULL, NULL,
fa1179c
@@ -2448,6 +2458,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
9c49c9e
 		   can be used. */
9c49c9e
 		oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
 				    DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+		if (!oc)
9c49c9e
+			oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
+					    DHO_PXE_CLIENT_ID);
9c49c9e
 		if (oc &&
9c49c9e
 		    evaluate_option_cache (&d1, packet, lease,
9c49c9e
 					   (struct client_state *)0,
fa1179c
@@ -3040,6 +3053,9 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
9c49c9e
 		/* Record the uid, if given... */
9c49c9e
 		oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
 				    DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+		if (!oc)
9c49c9e
+			oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
+					    DHO_PXE_CLIENT_ID);
9c49c9e
 		if (oc &&
9c49c9e
 		    evaluate_option_cache(&d1, packet, lease, NULL,
9c49c9e
 					  packet->options, state->options,
fa1179c
@@ -4258,6 +4274,9 @@ int find_lease (struct lease **lp,
9c49c9e
 	   specified unique client identifier. */
9c49c9e
 	oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
 			    DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+	if (!oc)
9c49c9e
+		oc = lookup_option (&dhcp_universe, packet -> options,
9c49c9e
+				    DHO_PXE_CLIENT_ID);
9c49c9e
 	memset (&client_identifier, 0, sizeof client_identifier);
9c49c9e
 	if (oc &&
9c49c9e
 	    evaluate_option_cache (&client_identifier,
9c49c9e
diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5
fa1179c
index b7e79ea..2354b1d 100644
9c49c9e
--- a/server/dhcpd.conf.5
9c49c9e
+++ b/server/dhcpd.conf.5
9c49c9e
@@ -1664,10 +1664,12 @@ should be a name identifying the host.  If a \fIhostname\fR option is
9c49c9e
 not specified for the host, \fIhostname\fR is used.
9c49c9e
 .PP
9c49c9e
 \fIHost\fR declarations are matched to actual DHCP or BOOTP clients
9c49c9e
-by matching the \fRdhcp-client-identifier\fR option specified in the
9c49c9e
+by matching the \fIdhcp-client-identifier\fR or \fIpxe-client-id\fR
9c49c9e
+options specified in the
9c49c9e
 \fIhost\fR declaration to the one supplied by the client, or, if the
9c49c9e
 \fIhost\fR declaration or the client does not provide a
9c49c9e
-\fRdhcp-client-identifier\fR option, by matching the \fIhardware\fR
9c49c9e
+\fIdhcp-client-identifier\fR or \fIpxe-client-id\fR options,
9c49c9e
+by matching the \fIhardware\fR
9c49c9e
 parameter in the \fIhost\fR declaration to the network hardware
9c49c9e
 address supplied by the client.  BOOTP clients do not normally
9c49c9e
 provide a \fIdhcp-client-identifier\fR, so the hardware address must
9c49c9e
@@ -1679,7 +1681,8 @@ to identify hosts.
9c49c9e
 .PP
9c49c9e
 Please be aware that
9c49c9e
 .B only
9c49c9e
-the \fIdhcp-client-identifier\fR option and the hardware address can be
9c49c9e
+the \fIdhcp-client-identifier\fR and \fIpxe-client-id\fR
9c49c9e
+options and the hardware address can be
9c49c9e
 used to match a host declaration, or the \fIhost-identifier option\fR
9c49c9e
 parameter for DHCPv6 servers.  For example, it is not possible to
9c49c9e
 match a host declaration to a \fIhost-name\fR option.  This is
9c49c9e
diff --git a/server/dhcpleasequery.c b/server/dhcpleasequery.c
fa1179c
index 0f1d4f7..dae4ae7 100644
9c49c9e
--- a/server/dhcpleasequery.c
9c49c9e
+++ b/server/dhcpleasequery.c
9c49c9e
@@ -276,7 +276,7 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
9c49c9e
 		 */
9c49c9e
 
9c49c9e
 		memset(&uid, 0, sizeof(uid));
9c49c9e
-		if (get_option(&uid, 
9c49c9e
+		i = get_option(&uid,
9c49c9e
 			       &dhcp_universe,
9c49c9e
 			       packet,
9c49c9e
 			       NULL,
9c49c9e
@@ -286,8 +286,20 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
9c49c9e
 			       packet->options, 
9c49c9e
 			       &global_scope,
9c49c9e
 			       DHO_DHCP_CLIENT_IDENTIFIER,
9c49c9e
-			       MDL)) {
9c49c9e
-
9c49c9e
+			       MDL);
9c49c9e
+		if (!i)
9c49c9e
+			i = get_option(&uid,
9c49c9e
+				       &dhcp_universe,
9c49c9e
+				       packet,
9c49c9e
+				       NULL,
9c49c9e
+				       NULL,
9c49c9e
+				       packet->options,
9c49c9e
+				       NULL,
9c49c9e
+				       packet->options,
9c49c9e
+				       &global_scope,
9c49c9e
+				       DHO_PXE_CLIENT_ID,
9c49c9e
+				       MDL);
9c49c9e
+		if (i) {
9c49c9e
 			snprintf(dbg_info, 
9c49c9e
 				 sizeof(dbg_info), 
9c49c9e
 				 "client-id %s",
9c49c9e
diff --git a/server/failover.c b/server/failover.c
fa1179c
index 5b36d3a..a641e86 100644
9c49c9e
--- a/server/failover.c
9c49c9e
+++ b/server/failover.c
9c49c9e
@@ -5988,6 +5988,9 @@ int load_balance_mine (struct packet *packet, dhcp_failover_state_t *state)
9c49c9e
 
9c49c9e
 	oc = lookup_option(&dhcp_universe, packet->options,
9c49c9e
 			   DHO_DHCP_CLIENT_IDENTIFIER);
9c49c9e
+	if (!oc)
9c49c9e
+		oc = lookup_option(&dhcp_universe, packet -> options,
9c49c9e
+				    DHO_PXE_CLIENT_ID);
9c49c9e
 	memset(&ds, 0, sizeof ds);
9c49c9e
 	if (oc &&
9c49c9e
 	    evaluate_option_cache(&ds, packet, NULL, NULL,
9c49c9e
diff --git a/server/mdb.c b/server/mdb.c
fa1179c
index 60a40e1..2cd5605 100644
9c49c9e
--- a/server/mdb.c
9c49c9e
+++ b/server/mdb.c
9c49c9e
@@ -129,8 +129,9 @@ static int find_uid_statement (struct executable_statement *esp,
9c49c9e
 	    esp -> data.option &&
9c49c9e
 	    (esp -> data.option -> option -> universe ==
9c49c9e
 	     &dhcp_universe) &&
9c49c9e
-	    (esp -> data.option -> option -> code ==
9c49c9e
-	     DHO_DHCP_CLIENT_IDENTIFIER)) {
9c49c9e
+	    ((esp -> data.option -> option -> code ==
9c49c9e
+						DHO_DHCP_CLIENT_IDENTIFIER) ||
9c49c9e
+	     (esp -> data.option -> option -> code == DHO_PXE_CLIENT_ID))) {
9c49c9e
 		if (condp) {
9c49c9e
 			log_error ("dhcp client identifier may not be %s",
9c49c9e
 				   "specified conditionally.");
9c49c9e
-- 
fa1179c
2.35.1
9c49c9e