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