Browse Source

[dhcp] Use a random DHCP transaction identifier (xid)

iPXE currently uses the last four bytes of the MAC address as the DHCP
transaction identifier.  Reduce the probability of collisions by
generating a random transaction identifier.

Originally-implemented-by: Amos Kong <akong@redhat.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
12767d2202
3 changed files with 36 additions and 29 deletions
  1. 6
    3
      src/include/ipxe/dhcp.h
  2. 6
    3
      src/net/fakedhcp.c
  3. 24
    23
      src/net/udp/dhcp.c

+ 6
- 3
src/include/ipxe/dhcp.h View File

660
 /** Setting block name used for BootServerDHCP responses */
660
 /** Setting block name used for BootServerDHCP responses */
661
 #define PXEBS_SETTINGS_NAME "pxebs"
661
 #define PXEBS_SETTINGS_NAME "pxebs"
662
 
662
 
663
+extern uint32_t dhcp_last_xid;
663
 extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
664
 extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
664
 				  uint16_t *flags );
665
 				  uint16_t *flags );
665
 extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
666
 extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
666
 				struct net_device *netdev, uint8_t msgtype,
667
 				struct net_device *netdev, uint8_t msgtype,
667
-				const void *options, size_t options_len,
668
-				void *data, size_t max_len );
668
+				uint32_t xid, const void *options,
669
+				size_t options_len, void *data,
670
+				size_t max_len );
669
 extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
671
 extern int dhcp_create_request ( struct dhcp_packet *dhcppkt,
670
 				 struct net_device *netdev,
672
 				 struct net_device *netdev,
671
-				 unsigned int msgtype, struct in_addr ciaddr,
673
+				 unsigned int msgtype, uint32_t xid,
674
+				 struct in_addr ciaddr,
672
 				 void *data, size_t max_len );
675
 				 void *data, size_t max_len );
673
 extern int start_dhcp ( struct interface *job, struct net_device *netdev );
676
 extern int start_dhcp ( struct interface *job, struct net_device *netdev );
674
 extern int start_pxebs ( struct interface *job, struct net_device *netdev,
677
 extern int start_pxebs ( struct interface *job, struct net_device *netdev,

+ 6
- 3
src/net/fakedhcp.c View File

114
 	int rc;
114
 	int rc;
115
 
115
 
116
 	if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
116
 	if ( ( rc = dhcp_create_request ( &dhcppkt, netdev, DHCPDISCOVER,
117
-					  ciaddr, data, max_len ) ) != 0 ) {
117
+					  dhcp_last_xid, ciaddr, data,
118
+					  max_len ) ) != 0 ) {
118
 		DBG ( "Could not create DHCPDISCOVER: %s\n",
119
 		DBG ( "Could not create DHCPDISCOVER: %s\n",
119
 		      strerror ( rc ) );
120
 		      strerror ( rc ) );
120
 		return rc;
121
 		return rc;
139
 	int rc;
140
 	int rc;
140
 
141
 
141
 	/* Create base DHCPACK packet */
142
 	/* Create base DHCPACK packet */
142
-	if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
143
+	if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
144
+					 dhcp_last_xid, NULL, 0,
143
 					 data, max_len ) ) != 0 ) {
145
 					 data, max_len ) ) != 0 ) {
144
 		DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
146
 		DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
145
 		return rc;
147
 		return rc;
190
 	}
192
 	}
191
 
193
 
192
 	/* Create base DHCPACK packet */
194
 	/* Create base DHCPACK packet */
193
-	if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK, NULL, 0,
195
+	if ( ( rc = dhcp_create_packet ( &dhcppkt, netdev, DHCPACK,
196
+					 dhcp_last_xid, NULL, 0,
194
 					 data, max_len ) ) != 0 ) {
197
 					 data, max_len ) ) != 0 ) {
195
 		DBG ( "Could not create PXE BS ACK: %s\n",
198
 		DBG ( "Could not create PXE BS ACK: %s\n",
196
 		      strerror ( rc ) );
199
 		      strerror ( rc ) );

+ 24
- 23
src/net/udp/dhcp.c View File

116
 	.type = &setting_type_uint8,
116
 	.type = &setting_type_uint8,
117
 };
117
 };
118
 
118
 
119
+/**
120
+ * Most recent DHCP transaction ID
121
+ *
122
+ * This is exposed for use by the fakedhcp code when reconstructing
123
+ * DHCP packets for PXE NBPs.
124
+ */
125
+uint32_t dhcp_last_xid;
126
+
119
 /**
127
 /**
120
  * Name a DHCP packet type
128
  * Name a DHCP packet type
121
  *
129
  *
137
 	}
145
 	}
138
 }
146
 }
139
 
147
 
140
-/**
141
- * Calculate DHCP transaction ID for a network device
142
- *
143
- * @v netdev		Network device
144
- * @ret xid		DHCP XID
145
- *
146
- * Extract the least significant bits of the hardware address for use
147
- * as the transaction ID.
148
- */
149
-static uint32_t dhcp_xid ( struct net_device *netdev ) {
150
-	uint32_t xid;
151
-
152
-	memcpy ( &xid, ( netdev->ll_addr + netdev->ll_protocol->ll_addr_len
153
-			 - sizeof ( xid ) ), sizeof ( xid ) );
154
-	return xid;
155
-}
156
-
157
 /****************************************************************************
148
 /****************************************************************************
158
  *
149
  *
159
  * DHCP session
150
  * DHCP session
219
 	struct sockaddr_in local;
210
 	struct sockaddr_in local;
220
 	/** State of the session */
211
 	/** State of the session */
221
 	struct dhcp_session_state *state;
212
 	struct dhcp_session_state *state;
213
+	/** Transaction ID (in network-endian order) */
214
+	uint32_t xid;
222
 
215
 
223
 	/** Offered IP address */
216
 	/** Offered IP address */
224
 	struct in_addr offer;
217
 	struct in_addr offer;
916
  * @v dhcppkt		DHCP packet structure to fill in
909
  * @v dhcppkt		DHCP packet structure to fill in
917
  * @v netdev		Network device
910
  * @v netdev		Network device
918
  * @v msgtype		DHCP message type
911
  * @v msgtype		DHCP message type
912
+ * @v xid		Transaction ID (in network-endian order)
919
  * @v options		Initial options to include (or NULL)
913
  * @v options		Initial options to include (or NULL)
920
  * @v options_len	Length of initial options
914
  * @v options_len	Length of initial options
921
  * @v data		Buffer for DHCP packet
915
  * @v data		Buffer for DHCP packet
927
  */
921
  */
928
 int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
922
 int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
929
 			 struct net_device *netdev, uint8_t msgtype,
923
 			 struct net_device *netdev, uint8_t msgtype,
930
-			 const void *options, size_t options_len,
924
+			 uint32_t xid, const void *options, size_t options_len,
931
 			 void *data, size_t max_len ) {
925
 			 void *data, size_t max_len ) {
932
 	struct dhcphdr *dhcphdr = data;
926
 	struct dhcphdr *dhcphdr = data;
933
 	int rc;
927
 	int rc;
938
 
932
 
939
 	/* Initialise DHCP packet content */
933
 	/* Initialise DHCP packet content */
940
 	memset ( dhcphdr, 0, max_len );
934
 	memset ( dhcphdr, 0, max_len );
941
-	dhcphdr->xid = dhcp_xid ( netdev );
935
+	dhcphdr->xid = xid;
942
 	dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
936
 	dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
943
 	dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
937
 	dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
944
 	dhcphdr->op = dhcp_op[msgtype];
938
 	dhcphdr->op = dhcp_op[msgtype];
964
  * @v dhcppkt		DHCP packet structure to fill in
958
  * @v dhcppkt		DHCP packet structure to fill in
965
  * @v netdev		Network device
959
  * @v netdev		Network device
966
  * @v msgtype		DHCP message type
960
  * @v msgtype		DHCP message type
961
+ * @v xid		Transaction ID (in network-endian order)
967
  * @v ciaddr		Client IP address
962
  * @v ciaddr		Client IP address
968
  * @v data		Buffer for DHCP packet
963
  * @v data		Buffer for DHCP packet
969
  * @v max_len		Size of DHCP packet buffer
964
  * @v max_len		Size of DHCP packet buffer
974
  */
969
  */
975
 int dhcp_create_request ( struct dhcp_packet *dhcppkt,
970
 int dhcp_create_request ( struct dhcp_packet *dhcppkt,
976
 			  struct net_device *netdev, unsigned int msgtype,
971
 			  struct net_device *netdev, unsigned int msgtype,
977
-			  struct in_addr ciaddr, void *data, size_t max_len ) {
972
+			  uint32_t xid, struct in_addr ciaddr,
973
+			  void *data, size_t max_len ) {
978
 	struct dhcp_netdev_desc dhcp_desc;
974
 	struct dhcp_netdev_desc dhcp_desc;
979
 	struct dhcp_client_id client_id;
975
 	struct dhcp_client_id client_id;
980
 	struct dhcp_client_uuid client_uuid;
976
 	struct dhcp_client_uuid client_uuid;
985
 	int rc;
981
 	int rc;
986
 
982
 
987
 	/* Create DHCP packet */
983
 	/* Create DHCP packet */
988
-	if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype,
984
+	if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
989
 					 dhcp_request_options_data,
985
 					 dhcp_request_options_data,
990
 					 sizeof ( dhcp_request_options_data ),
986
 					 sizeof ( dhcp_request_options_data ),
991
 					 data, max_len ) ) != 0 ) {
987
 					 data, max_len ) ) != 0 ) {
1099
 
1095
 
1100
 	/* Create basic DHCP packet in temporary buffer */
1096
 	/* Create basic DHCP packet in temporary buffer */
1101
 	if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
1097
 	if ( ( rc = dhcp_create_request ( &dhcppkt, dhcp->netdev, msgtype,
1102
-					  dhcp->local.sin_addr, iobuf->data,
1098
+					  dhcp->xid, dhcp->local.sin_addr,
1099
+					  iobuf->data,
1103
 					  iob_tailroom ( iobuf ) ) ) != 0 ) {
1100
 					  iob_tailroom ( iobuf ) ) ) != 0 ) {
1104
 		DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
1101
 		DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
1105
 		       dhcp, strerror ( rc ) );
1102
 		       dhcp, strerror ( rc ) );
1187
 			&server_id, sizeof ( server_id ) );
1184
 			&server_id, sizeof ( server_id ) );
1188
 
1185
 
1189
 	/* Check for matching transaction ID */
1186
 	/* Check for matching transaction ID */
1190
-	if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
1187
+	if ( dhcphdr->xid != dhcp->xid ) {
1191
 		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1188
 		DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
1192
 		       "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
1189
 		       "ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
1193
 		       inet_ntoa ( peer->sin_addr ),
1190
 		       inet_ntoa ( peer->sin_addr ),
1311
 	dhcp->netdev = netdev_get ( netdev );
1308
 	dhcp->netdev = netdev_get ( netdev );
1312
 	dhcp->local.sin_family = AF_INET;
1309
 	dhcp->local.sin_family = AF_INET;
1313
 	dhcp->local.sin_port = htons ( BOOTPC_PORT );
1310
 	dhcp->local.sin_port = htons ( BOOTPC_PORT );
1311
+	dhcp->xid = random();
1312
+
1313
+	/* Store DHCP transaction ID for fakedhcp code */
1314
+	dhcp_last_xid = dhcp->xid;
1314
 
1315
 
1315
 	/* Instantiate child objects and attach to our interfaces */
1316
 	/* Instantiate child objects and attach to our interfaces */
1316
 	if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
1317
 	if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,

Loading…
Cancel
Save