|
@@ -116,6 +116,14 @@ struct setting use_cached_setting __setting ( SETTING_MISC ) = {
|
116
|
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
|
128
|
* Name a DHCP packet type
|
121
|
129
|
*
|
|
@@ -137,23 +145,6 @@ static inline const char * dhcp_msgtype_name ( unsigned int msgtype ) {
|
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
|
150
|
* DHCP session
|
|
@@ -219,6 +210,8 @@ struct dhcp_session {
|
219
|
210
|
struct sockaddr_in local;
|
220
|
211
|
/** State of the session */
|
221
|
212
|
struct dhcp_session_state *state;
|
|
213
|
+ /** Transaction ID (in network-endian order) */
|
|
214
|
+ uint32_t xid;
|
222
|
215
|
|
223
|
216
|
/** Offered IP address */
|
224
|
217
|
struct in_addr offer;
|
|
@@ -916,6 +909,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
|
916
|
909
|
* @v dhcppkt DHCP packet structure to fill in
|
917
|
910
|
* @v netdev Network device
|
918
|
911
|
* @v msgtype DHCP message type
|
|
912
|
+ * @v xid Transaction ID (in network-endian order)
|
919
|
913
|
* @v options Initial options to include (or NULL)
|
920
|
914
|
* @v options_len Length of initial options
|
921
|
915
|
* @v data Buffer for DHCP packet
|
|
@@ -927,7 +921,7 @@ unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr,
|
927
|
921
|
*/
|
928
|
922
|
int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
929
|
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
|
925
|
void *data, size_t max_len ) {
|
932
|
926
|
struct dhcphdr *dhcphdr = data;
|
933
|
927
|
int rc;
|
|
@@ -938,7 +932,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
938
|
932
|
|
939
|
933
|
/* Initialise DHCP packet content */
|
940
|
934
|
memset ( dhcphdr, 0, max_len );
|
941
|
|
- dhcphdr->xid = dhcp_xid ( netdev );
|
|
935
|
+ dhcphdr->xid = xid;
|
942
|
936
|
dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE );
|
943
|
937
|
dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto );
|
944
|
938
|
dhcphdr->op = dhcp_op[msgtype];
|
|
@@ -964,6 +958,7 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
964
|
958
|
* @v dhcppkt DHCP packet structure to fill in
|
965
|
959
|
* @v netdev Network device
|
966
|
960
|
* @v msgtype DHCP message type
|
|
961
|
+ * @v xid Transaction ID (in network-endian order)
|
967
|
962
|
* @v ciaddr Client IP address
|
968
|
963
|
* @v data Buffer for DHCP packet
|
969
|
964
|
* @v max_len Size of DHCP packet buffer
|
|
@@ -974,7 +969,8 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt,
|
974
|
969
|
*/
|
975
|
970
|
int dhcp_create_request ( struct dhcp_packet *dhcppkt,
|
976
|
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
|
974
|
struct dhcp_netdev_desc dhcp_desc;
|
979
|
975
|
struct dhcp_client_id client_id;
|
980
|
976
|
struct dhcp_client_uuid client_uuid;
|
|
@@ -985,7 +981,7 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt,
|
985
|
981
|
int rc;
|
986
|
982
|
|
987
|
983
|
/* Create DHCP packet */
|
988
|
|
- if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype,
|
|
984
|
+ if ( ( rc = dhcp_create_packet ( dhcppkt, netdev, msgtype, xid,
|
989
|
985
|
dhcp_request_options_data,
|
990
|
986
|
sizeof ( dhcp_request_options_data ),
|
991
|
987
|
data, max_len ) ) != 0 ) {
|
|
@@ -1099,7 +1095,8 @@ static int dhcp_tx ( struct dhcp_session *dhcp ) {
|
1099
|
1095
|
|
1100
|
1096
|
/* Create basic DHCP packet in temporary buffer */
|
1101
|
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
|
1100
|
iob_tailroom ( iobuf ) ) ) != 0 ) {
|
1104
|
1101
|
DBGC ( dhcp, "DHCP %p could not construct DHCP request: %s\n",
|
1105
|
1102
|
dhcp, strerror ( rc ) );
|
|
@@ -1187,7 +1184,7 @@ static int dhcp_deliver ( struct dhcp_session *dhcp,
|
1187
|
1184
|
&server_id, sizeof ( server_id ) );
|
1188
|
1185
|
|
1189
|
1186
|
/* Check for matching transaction ID */
|
1190
|
|
- if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
|
|
1187
|
+ if ( dhcphdr->xid != dhcp->xid ) {
|
1191
|
1188
|
DBGC ( dhcp, "DHCP %p %s from %s:%d has bad transaction "
|
1192
|
1189
|
"ID\n", dhcp, dhcp_msgtype_name ( msgtype ),
|
1193
|
1190
|
inet_ntoa ( peer->sin_addr ),
|
|
@@ -1311,6 +1308,10 @@ int start_dhcp ( struct interface *job, struct net_device *netdev ) {
|
1311
|
1308
|
dhcp->netdev = netdev_get ( netdev );
|
1312
|
1309
|
dhcp->local.sin_family = AF_INET;
|
1313
|
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
|
1316
|
/* Instantiate child objects and attach to our interfaces */
|
1316
|
1317
|
if ( ( rc = xfer_open_socket ( &dhcp->xfer, SOCK_DGRAM, &dhcp_peer,
|