]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4RenewRebind.c
Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / PxeDhcp4Dxe / PxeDhcp4RenewRebind.c
1 /** @file
2
3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13 PxeDhcp4RenewRebind.c
14
15 Abstract:
16
17
18 **/
19
20
21 #include "PxeDhcp4.h"
22
23 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
24
25 /**
26 Parameters:
27
28 @return -2 = ignore, stop waiting
29 @return -1 = ignore, keep waiting
30 @return 0 = accept, keep waiting
31 @return 1 = accept, stop waiting
32
33 **/
34 STATIC
35 INTN
36 acknak_verify (
37 IN PXE_DHCP4_PRIVATE_DATA *Private,
38 IN DHCP4_PACKET *tx_pkt,
39 IN DHCP4_PACKET *rx_pkt,
40 IN UINTN rx_pkt_size
41 )
42 {
43 EFI_STATUS efi_status;
44 DHCP4_OP *msg_type_op;
45 DHCP4_OP *srvid_op;
46 DHCP4_OP *renew_op;
47 DHCP4_OP *rebind_op;
48 DHCP4_OP *lease_time_op;
49 UINT32 magik;
50
51 //
52 // Verify parameters. Unused parameters are also touched
53 // to make the compiler happy.
54 //
55 ASSERT (Private);
56 ASSERT (rx_pkt);
57
58 if (Private == NULL || rx_pkt == NULL) {
59 return -2;
60 }
61
62 tx_pkt = tx_pkt;
63 rx_pkt_size = rx_pkt_size;
64
65 //
66 // This must be a DHCP Ack message.
67 //
68 magik = htonl (DHCP4_MAGIK_NUMBER);
69
70 if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {
71 return -1;
72 }
73
74 efi_status = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);
75
76 if (EFI_ERROR (efi_status)) {
77 return -1;
78 }
79
80 if (msg_type_op->len != 1) {
81 return -1;
82 }
83
84 if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) {
85 return -1;
86 }
87 //
88 // There must be a server identifier.
89 //
90 efi_status = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op);
91
92 if (EFI_ERROR (efi_status)) {
93 return -1;
94 }
95
96 if (srvid_op->len != 4) {
97 return -1;
98 }
99 //
100 // There should be a renewal time.
101 // If there is not, we will default to the 7/8 of the rebinding time.
102 //
103 efi_status = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op);
104
105 if (EFI_ERROR (efi_status)) {
106 renew_op = NULL;
107 } else if (renew_op->len != 4) {
108 renew_op = NULL;
109 }
110 //
111 // There should be a rebinding time.
112 // If there is not, we will default to 7/8 of the lease time.
113 //
114 efi_status = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op);
115
116 if (EFI_ERROR (efi_status)) {
117 rebind_op = NULL;
118 } else if (rebind_op->len != 4) {
119 rebind_op = NULL;
120 }
121 //
122 // There should be a lease time.
123 // If there is not, we will default to one week.
124 //
125 efi_status = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op);
126
127 if (EFI_ERROR (efi_status)) {
128 lease_time_op = NULL;
129 } else if (lease_time_op->len != 4) {
130 lease_time_op = NULL;
131 }
132 //
133 // Packet looks good. Double check the renew, rebind and lease times.
134 //
135 CopyMem (&Private->ServerIp, srvid_op->data, 4);
136
137 if (renew_op != NULL) {
138 CopyMem (&Private->RenewTime, renew_op->data, 4);
139 Private->RenewTime = htonl (Private->RenewTime);
140 } else {
141 Private->RenewTime = 0;
142 }
143
144 if (rebind_op != NULL) {
145 CopyMem (&Private->RebindTime, rebind_op->data, 4);
146 Private->RebindTime = htonl (Private->RebindTime);
147 } else {
148 Private->RebindTime = 0;
149 }
150
151 if (lease_time_op != NULL) {
152 CopyMem (&Private->LeaseTime, lease_time_op->data, 4);
153 Private->LeaseTime = htonl (Private->LeaseTime);
154 } else {
155 Private->LeaseTime = 0;
156 }
157
158 if (Private->LeaseTime < 60) {
159 Private->LeaseTime = 7 * 86400;
160 }
161
162 if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) {
163 Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8;
164 }
165
166 if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) {
167 Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8;
168 }
169
170 return 1;
171 }
172
173 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
174 STATIC
175 EFI_STATUS
176 EFIAPI
177 renew_rebind (
178 IN EFI_PXE_DHCP4_PROTOCOL *This,
179 IN UINTN seconds_timeout,
180 IN BOOLEAN renew
181 )
182 {
183 PXE_DHCP4_PRIVATE_DATA *Private;
184 EFI_IP_ADDRESS ServerIp;
185 EFI_IP_ADDRESS client_ip;
186 EFI_IP_ADDRESS subnet_mask;
187 EFI_IP_ADDRESS gateway_ip;
188 DHCP4_PACKET Request;
189 DHCP4_PACKET AckNak;
190 DHCP4_OP *op;
191 EFI_STATUS efi_status;
192
193 //
194 // Check for invalid parameters.
195 //
196 if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS) {
197 return EFI_INVALID_PARAMETER;
198 }
199 //
200 // Check for proper protocol state.
201 //
202 if (This->Data == NULL) {
203 return EFI_NOT_STARTED;
204 }
205
206 if (!This->Data->SelectCompleted) {
207 return EFI_NOT_READY;
208 }
209
210 if (This->Data->IsBootp) {
211 return EFI_SUCCESS;
212 }
213
214 if (!This->Data->IsAck) {
215 return EFI_INVALID_PARAMETER;
216 }
217 //
218 // Get pointer to instance data.
219 //
220 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
221
222 if (Private == NULL) {
223 return EFI_INVALID_PARAMETER;
224 }
225
226 if (Private->PxeBc == NULL) {
227 return EFI_DEVICE_ERROR;
228 }
229 //
230 // Copy Discover packet to temporary request packet
231 // to be used for Renew/Rebind operation.
232 //
233 CopyMem (&Request, &This->Data->Discover, sizeof (DHCP4_PACKET));
234
235 CopyMem (&Request.dhcp4.ciaddr, &This->Data->AckNak.dhcp4.yiaddr, 4);
236
237 Request.dhcp4.flags = 0; /* Reply does not need to be broadcast. */
238
239 //
240 // Change message type from discover to request.
241 //
242 efi_status = find_opt (&Request, DHCP4_MESSAGE_TYPE, 0, &op);
243
244 if (EFI_ERROR (efi_status)) {
245 return EFI_INVALID_PARAMETER;
246 }
247
248 if (op->len != 1) {
249 return EFI_INVALID_PARAMETER;
250 }
251
252 op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;
253
254 //
255 // Need a subnet mask.
256 //
257 efi_status = find_opt (
258 &This->Data->AckNak,
259 DHCP4_SUBNET_MASK,
260 0,
261 &op
262 );
263
264 if (EFI_ERROR (efi_status)) {
265 return EFI_INVALID_PARAMETER;
266 }
267
268 if (op->len != 4) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));
273 CopyMem (&subnet_mask, op->data, 4);
274
275 //
276 // Need a server IP address (renew) or a broadcast
277 // IP address (rebind).
278 //
279 ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));
280
281 if (renew) {
282 efi_status = find_opt (
283 &This->Data->AckNak,
284 DHCP4_SERVER_IDENTIFIER,
285 0,
286 &op
287 );
288
289 if (EFI_ERROR (efi_status)) {
290 return EFI_INVALID_PARAMETER;
291 }
292
293 if (op->len != 4) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS));
298 CopyMem (&ServerIp, op->data, 4);
299
300 //
301 //
302 //
303 if (CompareMem (&This->Data->AckNak.dhcp4.giaddr, &gateway_ip, 4)) {
304 CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);
305 }
306 } else {
307 SetMem (&ServerIp, sizeof (EFI_IP_ADDRESS), 0xFF);
308 }
309 //
310 // Need a client IP address.
311 //
312 ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));
313 CopyMem (&client_ip, &Request.dhcp4.ciaddr, 4);
314
315 //
316 //
317 //
318 efi_status = gBS->HandleProtocol (
319 Private->Handle,
320 &gEfiPxeDhcp4CallbackProtocolGuid,
321 (VOID *) &Private->callback
322 );
323
324 if (EFI_ERROR (efi_status)) {
325 Private->callback = NULL;
326 }
327
328 Private->function = renew ? EFI_PXE_DHCP4_FUNCTION_RENEW : EFI_PXE_DHCP4_FUNCTION_REBIND;
329
330 //
331 // Transimit DHCP request and wait for DHCP ack...
332 //
333 efi_status = tx_rx_udp (
334 Private,
335 &ServerIp,
336 &gateway_ip,
337 &client_ip,
338 &subnet_mask,
339 &Request,
340 &AckNak,
341 &acknak_verify,
342 seconds_timeout
343 );
344
345 if (EFI_ERROR (efi_status)) {
346 Private->callback = NULL;
347 return efi_status;
348 }
349 //
350 // Copy server identifier, renewal time and rebinding time
351 // from temporary ack/nak packet into cached ack/nak packet.
352 //
353 efi_status = find_opt (
354 &This->Data->AckNak,
355 DHCP4_SERVER_IDENTIFIER,
356 0,
357 &op
358 );
359
360 if (!EFI_ERROR (efi_status)) {
361 if (op->len == 4) {
362 CopyMem (op->data, &Private->ServerIp, 4);
363 }
364 }
365
366 efi_status = find_opt (&This->Data->AckNak, DHCP4_RENEWAL_TIME, 0, &op);
367
368 if (!EFI_ERROR (efi_status)) {
369 if (op->len == 4) {
370 CopyMem (op->data, &Private->RenewTime, 4);
371 }
372 }
373
374 efi_status = find_opt (&This->Data->AckNak, DHCP4_REBINDING_TIME, 0, &op);
375
376 if (!EFI_ERROR (efi_status)) {
377 if (op->len == 4) {
378 CopyMem (op->data, &Private->RebindTime, 4);
379 }
380 }
381
382 Private->callback = NULL;
383 return efi_status;
384 }
385
386 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
387 EFI_STATUS
388 EFIAPI
389 PxeDhcp4Renew (
390 IN EFI_PXE_DHCP4_PROTOCOL *This,
391 IN UINTN seconds_timeout
392 )
393 {
394 return renew_rebind (This, seconds_timeout, TRUE);
395 }
396
397 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
398 EFI_STATUS
399 EFIAPI
400 PxeDhcp4Rebind (
401 IN EFI_PXE_DHCP4_PROTOCOL *This,
402 IN UINTN seconds_timeout
403 )
404 {
405 return renew_rebind (This, seconds_timeout, FALSE);
406 }
407
408 /* eof - PxeDhcp4RenewRebind.c */