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 10 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
 	}
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
  * DHCP session
158
  * DHCP session
1159
 	struct dhcphdr *dhcphdr;
1182
 	struct dhcphdr *dhcphdr;
1160
 	uint8_t msgtype = 0;
1183
 	uint8_t msgtype = 0;
1161
 	struct in_addr server_id = { 0 };
1184
 	struct in_addr server_id = { 0 };
1185
+	uint8_t chaddr[ sizeof ( dhcphdr->chaddr ) ];
1186
+	unsigned int hlen;
1162
 	int rc = 0;
1187
 	int rc = 0;
1163
 
1188
 
1164
 	/* Sanity checks */
1189
 	/* Sanity checks */
1203
 		goto err_xid;
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
 	/* Handle packet based on current state */
1242
 	/* Handle packet based on current state */
1207
 	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
1243
 	dhcp->state->rx ( dhcp, dhcppkt, peer, msgtype, server_id );
1208
 
1244
 
1245
+ err_chaddr:
1209
  err_xid:
1246
  err_xid:
1210
 	dhcppkt_put ( dhcppkt );
1247
 	dhcppkt_put ( dhcppkt );
1211
  err_alloc_dhcppkt:
1248
  err_alloc_dhcppkt:

Loading…
Cancel
Save