Browse Source

[dhcp] Check for matching chaddr in received DHCP packets

On large networks a DHCP XID collision is possible.  Fix by explicitly
checking the chaddr in received DHCP packets.

Originally-fixed-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
08bcc0fe01
1 changed files with 37 additions and 0 deletions
  1. 37
    0
      src/net/udp/dhcp.c

+ 37
- 0
src/net/udp/dhcp.c View File

@@ -130,6 +130,29 @@ static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
130 130
 	}
131 131
 }
132 132
 
133
+/**
134
+ * Transcribe DHCP client hardware address (for debugging)
135
+ *
136
+ * @v chaddr		Client hardware address
137
+ * @v hlen		Client hardware address length
138
+ */
139
+static const char * dhcp_chaddr_ntoa ( const void *chaddr, size_t hlen ) {
140
+	static char buf[ 48 /* 16 x ( "xx" + ":" or NUL ) */ ];
141
+	const uint8_t *chaddr_bytes = chaddr;
142
+	char *tmp = buf;
143
+
144
+	/* Sanity check */
145
+	assert ( hlen < ( sizeof ( buf ) / 3 ) );
146
+
147
+	/* Transcribe address */
148
+	while ( hlen-- ) {
149
+		tmp += sprintf ( tmp, "%s%02x", ( ( tmp == buf ) ? "" : ":" ),
150
+				 *(chaddr_bytes++) );
151
+	}
152
+
153
+	return buf;
154
+}
155
+
133 156
 /****************************************************************************
134 157
  *
135 158
  * DHCP session
@@ -1159,6 +1182,8 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
1159 1182
 	struct dhcphdr *dhcphdr;
1160 1183
 	uint8_t msgtype = 0;
1161 1184
 	struct in_addr server_id = { 0 };
1185
+	uint8_t chaddr[ sizeof ( dhcphdr->chaddr ) ];
1186
+	unsigned int hlen;
1162 1187
 	int rc = 0;
1163 1188
 
1164 1189
 	/* Sanity checks */
@@ -1203,9 +1228,21 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
1203 1228
 		goto err_xid;
1204 1229
 	};
1205 1230
 
1231
+	/* Check for matching client hardware address */
1232
+	hlen = dhcp_chaddr ( dhcp->netdev, chaddr, NULL );
1233
+	if ( memcmp ( dhcphdr->chaddr, chaddr, hlen ) != 0 ) {
1234
+		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad chaddr %s\n",
1235
+		       dhcp, dhcp_msgtype_name ( msgtype ),
1236
+		       inet_ntoa ( peer->sin_addr ), ntohs ( peer->sin_port ),
1237
+		       dhcp_chaddr_ntoa ( dhcphdr->chaddr, hlen ) );
1238
+		rc = -EINVAL;
1239
+		goto err_chaddr;
1240
+	}
1241
+
1206 1242
 	/* Handle packet based on current state */
1207 1243
 	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
1208 1244
 
1245
+ err_chaddr:
1209 1246
  err_xid:
1210 1247
 	dhcppkt_put ( dhcppkt );
1211 1248
  err_alloc_dhcppkt:

Loading…
Cancel
Save