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