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