]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
MdeModulePkg: IP4 should re-initiate a DHCP if it detects network reconnection
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Impl.c
CommitLineData
772db4bb 1/** @file\r
2\r
1f6729ff 3Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 4This program and the accompanying materials\r
772db4bb 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
772db4bb 12**/\r
13\r
14#include "Ip4Impl.h"\r
15\r
705f53a9 16EFI_IPSEC2_PROTOCOL *mIpSec = NULL;\r
a1503a32 17\r
5405e9a6 18/**\r
19 Gets the current operational settings for this instance of the EFI IPv4 Protocol driver.\r
e2851998 20\r
5405e9a6 21 The GetModeData() function returns the current operational mode data for this\r
22 driver instance. The data fields in EFI_IP4_MODE_DATA are read only. This\r
23 function is used optionally to retrieve the operational mode data of underlying\r
24 networks or drivers.\r
25\r
3e8c18da 26 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
27 @param[out] Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure.\r
28 @param[out] MnpConfigData Pointer to the managed network configuration data structure.\r
29 @param[out] SnpModeData Pointer to the simple network mode data structure.\r
5405e9a6 30\r
31 @retval EFI_SUCCESS The operation completed successfully.\r
32 @retval EFI_INVALID_PARAMETER This is NULL.\r
33 @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.\r
772db4bb 34\r
5405e9a6 35**/\r
36EFI_STATUS\r
37EFIAPI\r
38EfiIp4GetModeData (\r
39 IN CONST EFI_IP4_PROTOCOL *This,\r
24af132f 40 OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,\r
41 OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,\r
5405e9a6 42 OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL\r
43 );\r
e2851998 44\r
772db4bb 45/**\r
5405e9a6 46 Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance.\r
e2851998 47\r
5405e9a6 48 The Configure() function is used to set, change, or reset the operational\r
49 parameters and filter settings for this EFI IPv4 Protocol instance. Until these\r
50 parameters have been set, no network traffic can be sent or received by this\r
51 instance. Once the parameters have been reset (by calling this function with\r
52 IpConfigData set to NULL), no more traffic can be sent or received until these\r
53 parameters have been set again. Each EFI IPv4 Protocol instance can be started\r
54 and stopped independently of each other by enabling or disabling their receive\r
55 filter settings with the Configure() function.\r
e2851998 56\r
5405e9a6 57 When IpConfigData.UseDefaultAddress is set to FALSE, the new station address will\r
58 be appended as an alias address into the addresses list in the EFI IPv4 Protocol\r
59 driver. While set to TRUE, Configure() will trigger the EFI_IP4_CONFIG_PROTOCOL\r
60 to retrieve the default IPv4 address if it is not available yet. Clients could\r
61 frequently call GetModeData() to check the status to ensure that the default IPv4\r
62 address is ready.\r
e2851998 63\r
5405e9a6 64 If operational parameters are reset or changed, any pending transmit and receive\r
65 requests will be cancelled. Their completion token status will be set to EFI_ABORTED\r
66 and their events will be signaled.\r
67\r
3e8c18da 68 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
69 @param[in] IpConfigData Pointer to the EFI IPv4 Protocol configuration data structure.\r
5405e9a6 70\r
71 @retval EFI_SUCCESS The driver instance was successfully opened.\r
72 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
73 RARP, etc.) is not finished yet.\r
74 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
75 @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE:\r
76 A configuration protocol (DHCP, BOOTP, RARP, etc.) could\r
77 not be located when clients choose to use the default IPv4\r
78 address. This EFI IPv4 Protocol implementation does not\r
79 support this requested filter or timeout setting.\r
80 @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated.\r
81 @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the\r
82 IPv4 address or subnet mask can be changed. The interface must\r
83 also be stopped when switching to/from raw packet mode.\r
84 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4\r
85 Protocol driver instance is not opened.\r
772db4bb 86\r
5405e9a6 87**/\r
88EFI_STATUS\r
89EFIAPI\r
90EfiIp4Configure (\r
91 IN EFI_IP4_PROTOCOL *This,\r
92 IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL\r
93 );\r
e2851998 94\r
5405e9a6 95/**\r
96 Joins and leaves multicast groups.\r
e2851998 97\r
5405e9a6 98 The Groups() function is used to join and leave multicast group sessions. Joining\r
99 a group will enable reception of matching multicast packets. Leaving a group will\r
100 disable the multicast packet reception.\r
e2851998 101\r
5405e9a6 102 If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.\r
103\r
3e8c18da 104 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
105 @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.\r
106 @param[in] GroupAddress Pointer to the IPv4 multicast address.\r
5405e9a6 107\r
108 @retval EFI_SUCCESS The operation completed successfully.\r
109 @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:\r
110 - This is NULL.\r
111 - JoinFlag is TRUE and GroupAddress is NULL.\r
112 - GroupAddress is not NULL and *GroupAddress is\r
113 not a multicast IPv4 address.\r
114 @retval EFI_NOT_STARTED This instance has not been started.\r
115 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
116 RARP, etc.) is not finished yet.\r
117 @retval EFI_OUT_OF_RESOURCES System resources could not be allocated.\r
118 @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups.\r
119 @retval EFI_ALREADY_STARTED The group address is already in the group table (when\r
120 JoinFlag is TRUE).\r
121 @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).\r
122 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 123\r
5405e9a6 124**/\r
125EFI_STATUS\r
126EFIAPI\r
127EfiIp4Groups (\r
128 IN EFI_IP4_PROTOCOL *This,\r
129 IN BOOLEAN JoinFlag,\r
130 IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL\r
131 );\r
e2851998 132\r
5405e9a6 133/**\r
134 Adds and deletes routing table entries.\r
135\r
136 The Routes() function adds a route to or deletes a route from the routing table.\r
e2851998 137\r
5405e9a6 138 Routes are determined by comparing the SubnetAddress with the destination IPv4\r
139 address arithmetically AND-ed with the SubnetMask. The gateway address must be\r
140 on the same subnet as the configured station address.\r
e2851998 141\r
5405e9a6 142 The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0.\r
143 The default route matches all destination IPv4 addresses that do not match any\r
144 other routes.\r
e2851998 145\r
5405e9a6 146 A GatewayAddress that is zero is a nonroute. Packets are sent to the destination\r
147 IP address if it can be found in the ARP cache or on the local subnet. One automatic\r
148 nonroute entry will be inserted into the routing table for outgoing packets that\r
149 are addressed to a local subnet (gateway address of 0.0.0.0).\r
e2851998 150\r
5405e9a6 151 Each EFI IPv4 Protocol instance has its own independent routing table. Those EFI\r
152 IPv4 Protocol instances that use the default IPv4 address will also have copies\r
153 of the routing table that was provided by the EFI_IP4_CONFIG_PROTOCOL, and these\r
154 copies will be updated whenever the EIF IPv4 Protocol driver reconfigures its\r
155 instances. As a result, client modification to the routing table will be lost.\r
156\r
3e8c18da 157 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
158 @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to\r
159 FALSE to add this route to the routing table. SubnetAddress\r
160 and SubnetMask are used as the key to each route entry.\r
161 @param[in] SubnetAddress The address of the subnet that needs to be routed.\r
162 @param[in] SubnetMask The subnet mask of SubnetAddress.\r
163 @param[in] GatewayAddress The unicast gateway IPv4 address for this route.\r
5405e9a6 164\r
165 @retval EFI_SUCCESS The operation completed successfully.\r
166 @retval EFI_NOT_STARTED The driver instance has not been started.\r
167 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
168 RARP, etc.) is not finished yet.\r
169 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
170 - This is NULL.\r
171 - SubnetAddress is NULL.\r
172 - SubnetMask is NULL.\r
173 - GatewayAddress is NULL.\r
174 - *SubnetAddress is not a valid subnet address.\r
175 - *SubnetMask is not a valid subnet mask.\r
176 - *GatewayAddress is not a valid unicast IPv4 address.\r
177 @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.\r
178 @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).\r
179 @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when\r
180 DeleteRoute is FALSE).\r
e2851998 181\r
5405e9a6 182**/\r
183EFI_STATUS\r
184EFIAPI\r
185EfiIp4Routes (\r
186 IN EFI_IP4_PROTOCOL *This,\r
187 IN BOOLEAN DeleteRoute,\r
188 IN EFI_IPv4_ADDRESS *SubnetAddress,\r
189 IN EFI_IPv4_ADDRESS *SubnetMask,\r
190 IN EFI_IPv4_ADDRESS *GatewayAddress\r
191 );\r
e2851998 192\r
5405e9a6 193/**\r
194 Places outgoing data packets into the transmit queue.\r
195\r
196 The Transmit() function places a sending request in the transmit queue of this\r
197 EFI IPv4 Protocol instance. Whenever the packet in the token is sent out or some\r
198 errors occur, the event in the token will be signaled and the status is updated.\r
199\r
3e8c18da 200 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
201 @param[in] Token Pointer to the transmit token.\r
5405e9a6 202\r
203 @retval EFI_SUCCESS The data has been queued for transmission.\r
204 @retval EFI_NOT_STARTED This instance has not been started.\r
205 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
206 RARP, etc.) is not finished yet.\r
207 @retval EFI_INVALID_PARAMETER One or more pameters are invalid.\r
208 @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event\r
209 was already in the transmit queue.\r
210 @retval EFI_NOT_READY The completion token could not be queued because the transmit\r
e2851998 211 queue is full.\r
5405e9a6 212 @retval EFI_NOT_FOUND Not route is found to destination address.\r
213 @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.\r
214 @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too\r
215 short to transmit.\r
216 @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is\r
217 greater than MTU (or greater than the maximum packet size if\r
218 Token.Packet.TxData.OverrideData.\r
219 DoNotFragment is TRUE.)\r
220\r
221**/\r
222EFI_STATUS\r
223EFIAPI\r
224EfiIp4Transmit (\r
225 IN EFI_IP4_PROTOCOL *This,\r
226 IN EFI_IP4_COMPLETION_TOKEN *Token\r
227 );\r
e2851998 228\r
5405e9a6 229/**\r
230 Places a receiving request into the receiving queue.\r
e2851998 231\r
5405e9a6 232 The Receive() function places a completion token into the receive packet queue.\r
233 This function is always asynchronous.\r
e2851998 234\r
5405e9a6 235 The Token.Event field in the completion token must be filled in by the caller\r
236 and cannot be NULL. When the receive operation completes, the EFI IPv4 Protocol\r
237 driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event\r
238 is signaled.\r
239\r
3e8c18da 240 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
241 @param[in] Token Pointer to a token that is associated with the receive data descriptor.\r
5405e9a6 242\r
243 @retval EFI_SUCCESS The receive completion token was cached.\r
244 @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.\r
245 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.)\r
246 is not finished yet.\r
247 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
248 - This is NULL.\r
249 - Token is NULL.\r
250 - Token.Event is NULL.\r
251 @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system\r
252 resources (usually memory).\r
253 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
254 The EFI IPv4 Protocol instance has been reset to startup defaults.\r
255 EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already\r
256 in the receive queue.\r
257 @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.\r
258 @retval EFI_ICMP_ERROR An ICMP error packet was received.\r
259\r
260**/\r
261EFI_STATUS\r
262EFIAPI\r
263EfiIp4Receive (\r
264 IN EFI_IP4_PROTOCOL *This,\r
265 IN EFI_IP4_COMPLETION_TOKEN *Token\r
266 );\r
e2851998 267\r
5405e9a6 268/**\r
269 Abort an asynchronous transmit or receive request.\r
e2851998 270\r
5405e9a6 271 The Cancel() function is used to abort a pending transmit or receive request.\r
272 If the token is in the transmit or receive request queues, after calling this\r
273 function, Token->Status will be set to EFI_ABORTED and then Token->Event will\r
274 be signaled. If the token is not in one of the queues, which usually means the\r
275 asynchronous operation has completed, this function will not signal the token\r
276 and EFI_NOT_FOUND is returned.\r
277\r
3e8c18da 278 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
279 @param[in] Token Pointer to a token that has been issued by\r
280 EFI_IP4_PROTOCOL.Transmit() or\r
281 EFI_IP4_PROTOCOL.Receive(). If NULL, all pending\r
282 tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is\r
283 defined in EFI_IP4_PROTOCOL.Transmit().\r
5405e9a6 284\r
285 @retval EFI_SUCCESS The asynchronous I/O request was aborted and\r
286 Token.->Event was signaled. When Token is NULL, all\r
287 pending requests were aborted and their events were signaled.\r
288 @retval EFI_INVALID_PARAMETER This is NULL.\r
289 @retval EFI_NOT_STARTED This instance has not been started.\r
290 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
291 RARP, etc.) is not finished yet.\r
292 @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was\r
293 not found in the transmit or receive queue. It has either completed\r
294 or was not issued by Transmit() and Receive().\r
295\r
296**/\r
297EFI_STATUS\r
298EFIAPI\r
299EfiIp4Cancel (\r
300 IN EFI_IP4_PROTOCOL *This,\r
301 IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL\r
302 );\r
e2851998 303\r
5405e9a6 304/**\r
305 Polls for incoming data packets and processes outgoing data packets.\r
e2851998 306\r
5405e9a6 307 The Poll() function polls for incoming data packets and processes outgoing data\r
308 packets. Network drivers and applications can call the EFI_IP4_PROTOCOL.Poll()\r
309 function to increase the rate that data packets are moved between the communications\r
310 device and the transmit and receive queues.\r
e2851998 311\r
5405e9a6 312 In some systems the periodic timer event may not poll the underlying communications\r
313 device fast enough to transmit and/or receive all data packets without missing\r
314 incoming packets or dropping outgoing packets. Drivers and applications that are\r
315 experiencing packet loss should try calling the EFI_IP4_PROTOCOL.Poll() function\r
316 more often.\r
317\r
3e8c18da 318 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
5405e9a6 319\r
320 @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
321 @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.\r
322 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
323 RARP, etc.) is not finished yet.\r
324 @retval EFI_INVALID_PARAMETER This is NULL.\r
325 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
326 @retval EFI_NOT_READY No incoming or outgoing data is processed.\r
327 @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.\r
328 Consider increasing the polling rate.\r
329\r
330**/\r
331EFI_STATUS\r
332EFIAPI\r
333EfiIp4Poll (\r
334 IN EFI_IP4_PROTOCOL *This\r
335 );\r
336\r
337EFI_IP4_PROTOCOL\r
338mEfiIp4ProtocolTemplete = {\r
339 EfiIp4GetModeData,\r
340 EfiIp4Configure,\r
341 EfiIp4Groups,\r
342 EfiIp4Routes,\r
343 EfiIp4Transmit,\r
344 EfiIp4Receive,\r
345 EfiIp4Cancel,\r
346 EfiIp4Poll\r
347};\r
348\r
349/**\r
350 Gets the current operational settings for this instance of the EFI IPv4 Protocol driver.\r
e2851998 351\r
5405e9a6 352 The GetModeData() function returns the current operational mode data for this\r
353 driver instance. The data fields in EFI_IP4_MODE_DATA are read only. This\r
354 function is used optionally to retrieve the operational mode data of underlying\r
355 networks or drivers.\r
356\r
3e8c18da 357 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
358 @param[out] Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure.\r
359 @param[out] MnpConfigData Pointer to the managed network configuration data structure.\r
360 @param[out] SnpModeData Pointer to the simple network mode data structure.\r
5405e9a6 361\r
362 @retval EFI_SUCCESS The operation completed successfully.\r
363 @retval EFI_INVALID_PARAMETER This is NULL.\r
364 @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.\r
772db4bb 365\r
366**/\r
772db4bb 367EFI_STATUS\r
368EFIAPI\r
369EfiIp4GetModeData (\r
370 IN CONST EFI_IP4_PROTOCOL *This,\r
24af132f 371 OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,\r
372 OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,\r
772db4bb 373 OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL\r
374 )\r
375{\r
376 IP4_PROTOCOL *IpInstance;\r
377 IP4_SERVICE *IpSb;\r
378 EFI_IP4_CONFIG_DATA *Config;\r
379 EFI_STATUS Status;\r
380 EFI_TPL OldTpl;\r
381 IP4_ADDR Ip;\r
382\r
383 if (This == NULL) {\r
384 return EFI_INVALID_PARAMETER;\r
385 }\r
386\r
e48e37fc 387 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 388 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
389 IpSb = IpInstance->Service;\r
390\r
391 if (Ip4ModeData != NULL) {\r
392 //\r
393 // IsStarted is "whether the EfiIp4Configure has been called".\r
394 // IsConfigured is "whether the station address has been configured"\r
395 //\r
396 Ip4ModeData->IsStarted = (BOOLEAN)(IpInstance->State == IP4_STATE_CONFIGED);\r
687a2e5f 397 CopyMem (&Ip4ModeData->ConfigData, &IpInstance->ConfigData, sizeof (Ip4ModeData->ConfigData));\r
772db4bb 398 Ip4ModeData->IsConfigured = FALSE;\r
399\r
400 Ip4ModeData->GroupCount = IpInstance->GroupCount;\r
401 Ip4ModeData->GroupTable = (EFI_IPv4_ADDRESS *) IpInstance->Groups;\r
402\r
403 Ip4ModeData->IcmpTypeCount = 23;\r
404 Ip4ModeData->IcmpTypeList = mIp4SupportedIcmp;\r
405\r
406 Ip4ModeData->RouteTable = NULL;\r
407 Ip4ModeData->RouteCount = 0;\r
408\r
a1503a32 409 Ip4ModeData->MaxPacketSize = IpSb->MaxPacketSize;\r
410\r
772db4bb 411 //\r
412 // return the current station address for this IP child. So,\r
413 // the user can get the default address through this. Some\r
414 // application wants to know it station address even it is\r
415 // using the default one, such as a ftp server.\r
416 //\r
417 if (Ip4ModeData->IsStarted) {\r
418 Config = &Ip4ModeData->ConfigData;\r
419\r
420 Ip = HTONL (IpInstance->Interface->Ip);\r
e48e37fc 421 CopyMem (&Config->StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 422\r
423 Ip = HTONL (IpInstance->Interface->SubnetMask);\r
e48e37fc 424 CopyMem (&Config->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 425\r
426 Ip4ModeData->IsConfigured = IpInstance->Interface->Configured;\r
427\r
428 //\r
429 // Build a EFI route table for user from the internal route table.\r
430 //\r
431 Status = Ip4BuildEfiRouteTable (IpInstance);\r
432\r
433 if (EFI_ERROR (Status)) {\r
e48e37fc 434 gBS->RestoreTPL (OldTpl);\r
772db4bb 435 return Status;\r
436 }\r
437\r
438 Ip4ModeData->RouteTable = IpInstance->EfiRouteTable;\r
439 Ip4ModeData->RouteCount = IpInstance->EfiRouteCount;\r
440 }\r
441 }\r
442\r
dd29f3ed 443 //\r
444 // Get fresh mode data from MNP, since underlying media status may change\r
445 //\r
446 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, MnpConfigData, SnpModeData);\r
772db4bb 447\r
e48e37fc 448 gBS->RestoreTPL (OldTpl);\r
dd29f3ed 449 return Status;\r
772db4bb 450}\r
451\r
452\r
453/**\r
454 Config the MNP parameter used by IP. The IP driver use one MNP\r
455 child to transmit/receive frames. By default, it configures MNP\r
456 to receive unicast/multicast/broadcast. And it will enable/disable\r
457 the promiscous receive according to whether there is IP child\r
5405e9a6 458 enable that or not. If Force is FALSE, it will iterate through\r
772db4bb 459 all the IP children to check whether the promiscuous receive\r
460 setting has been changed. If it hasn't been changed, it won't\r
5405e9a6 461 reconfigure the MNP. If Force is TRUE, the MNP is configured no\r
772db4bb 462 matter whether that is changed or not.\r
463\r
3e8c18da 464 @param[in] IpSb The IP4 service instance that is to be changed.\r
465 @param[in] Force Force the configuration or not.\r
772db4bb 466\r
467 @retval EFI_SUCCESS The MNP is successfully configured/reconfigured.\r
468 @retval Others Configuration failed.\r
469\r
470**/\r
471EFI_STATUS\r
472Ip4ServiceConfigMnp (\r
473 IN IP4_SERVICE *IpSb,\r
474 IN BOOLEAN Force\r
475 )\r
476{\r
e48e37fc 477 LIST_ENTRY *Entry;\r
478 LIST_ENTRY *ProtoEntry;\r
772db4bb 479 IP4_INTERFACE *IpIf;\r
480 IP4_PROTOCOL *IpInstance;\r
481 BOOLEAN Reconfig;\r
482 BOOLEAN PromiscReceive;\r
483 EFI_STATUS Status;\r
484\r
485 Reconfig = FALSE;\r
486 PromiscReceive = FALSE;\r
487\r
488 if (!Force) {\r
489 //\r
490 // Iterate through the IP children to check whether promiscuous\r
491 // receive setting has been changed. Update the interface's receive\r
492 // filter also.\r
493 //\r
494 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
495\r
496 IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
497 IpIf->PromiscRecv = FALSE;\r
498\r
499 NET_LIST_FOR_EACH (ProtoEntry, &IpIf->IpInstances) {\r
500 IpInstance = NET_LIST_USER_STRUCT (ProtoEntry, IP4_PROTOCOL, AddrLink);\r
501\r
502 if (IpInstance->ConfigData.AcceptPromiscuous) {\r
503 IpIf->PromiscRecv = TRUE;\r
504 PromiscReceive = TRUE;\r
505 }\r
506 }\r
507 }\r
508\r
509 //\r
510 // If promiscuous receive isn't changed, it isn't necessary to reconfigure.\r
511 //\r
512 if (PromiscReceive == IpSb->MnpConfigData.EnablePromiscuousReceive) {\r
513 return EFI_SUCCESS;\r
514 }\r
515\r
516 Reconfig = TRUE;\r
517 IpSb->MnpConfigData.EnablePromiscuousReceive = PromiscReceive;\r
518 }\r
519\r
520 Status = IpSb->Mnp->Configure (IpSb->Mnp, &IpSb->MnpConfigData);\r
521\r
522 //\r
523 // recover the original configuration if failed to set the configure.\r
524 //\r
525 if (EFI_ERROR (Status) && Reconfig) {\r
687a2e5f 526 IpSb->MnpConfigData.EnablePromiscuousReceive = (BOOLEAN) !PromiscReceive;\r
772db4bb 527 }\r
528\r
529 return Status;\r
530}\r
531\r
532\r
772db4bb 533/**\r
534 Intiialize the IP4_PROTOCOL structure to the unconfigured states.\r
535\r
536 @param IpSb The IP4 service instance.\r
537 @param IpInstance The IP4 child instance.\r
538\r
772db4bb 539**/\r
540VOID\r
541Ip4InitProtocol (\r
5405e9a6 542 IN IP4_SERVICE *IpSb,\r
543 IN OUT IP4_PROTOCOL *IpInstance\r
772db4bb 544 )\r
545{\r
546 ASSERT ((IpSb != NULL) && (IpInstance != NULL));\r
547\r
e48e37fc 548 ZeroMem (IpInstance, sizeof (IP4_PROTOCOL));\r
772db4bb 549\r
550 IpInstance->Signature = IP4_PROTOCOL_SIGNATURE;\r
687a2e5f 551 CopyMem (&IpInstance->Ip4Proto, &mEfiIp4ProtocolTemplete, sizeof (IpInstance->Ip4Proto));\r
772db4bb 552 IpInstance->State = IP4_STATE_UNCONFIGED;\r
553 IpInstance->Service = IpSb;\r
554\r
e48e37fc 555 InitializeListHead (&IpInstance->Link);\r
772db4bb 556 NetMapInit (&IpInstance->RxTokens);\r
557 NetMapInit (&IpInstance->TxTokens);\r
e48e37fc 558 InitializeListHead (&IpInstance->Received);\r
559 InitializeListHead (&IpInstance->Delivered);\r
560 InitializeListHead (&IpInstance->AddrLink);\r
772db4bb 561\r
e48e37fc 562 EfiInitializeLock (&IpInstance->RecycleLock, TPL_NOTIFY);\r
772db4bb 563}\r
564\r
565\r
2c320007
JW
566/**\r
567 The event handle for IP4 auto reconfiguration. The original default\r
568 interface and route table will be removed as the default.\r
569\r
570 @param[in] Context The IP4 service binding instance.\r
571\r
572**/\r
573VOID\r
574EFIAPI\r
575Ip4AutoReconfigCallBackDpc (\r
576 IN VOID *Context\r
577 )\r
578{\r
579 IP4_SERVICE *IpSb;\r
580\r
581 IpSb = (IP4_SERVICE *) Context;\r
582 NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
583\r
584 if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
585 IpSb->State = IP4_SERVICE_UNSTARTED;\r
586 }\r
587\r
588 Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
589\r
590 return ;\r
591}\r
592\r
593\r
594/**\r
595 Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.\r
596\r
597 @param Event The event that is signalled.\r
598 @param Context The IP4 service binding instance.\r
599\r
600**/\r
601VOID\r
602EFIAPI\r
603Ip4AutoReconfigCallBack (\r
604 IN EFI_EVENT Event,\r
605 IN VOID *Context\r
606 )\r
607{\r
608 //\r
609 // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK\r
610 //\r
611 QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);\r
612}\r
613\r
1f6729ff 614\r
772db4bb 615/**\r
616 Configure the IP4 child. If the child is already configured,\r
617 change the configuration parameter. Otherwise configure it\r
618 for the first time. The caller should validate the configuration\r
619 before deliver them to it. It also don't do configure NULL.\r
620\r
3e8c18da 621 @param[in, out] IpInstance The IP4 child to configure.\r
622 @param[in] Config The configure data.\r
772db4bb 623\r
624 @retval EFI_SUCCESS The IP4 child is successfully configured.\r
625 @retval EFI_DEVICE_ERROR Failed to free the pending transive or to\r
626 configure underlying MNP or other errors.\r
627 @retval EFI_NO_MAPPING The IP4 child is configured to use default\r
628 address, but the default address hasn't been\r
629 configured. The IP4 child doesn't need to be\r
630 reconfigured when default address is configured.\r
5405e9a6 631 @retval EFI_OUT_OF_RESOURCES No more memory space is available.\r
632 @retval other Other error occurs.\r
772db4bb 633\r
634**/\r
635EFI_STATUS\r
636Ip4ConfigProtocol (\r
5405e9a6 637 IN OUT IP4_PROTOCOL *IpInstance,\r
638 IN EFI_IP4_CONFIG_DATA *Config\r
772db4bb 639 )\r
640{\r
641 IP4_SERVICE *IpSb;\r
642 IP4_INTERFACE *IpIf;\r
643 EFI_STATUS Status;\r
644 IP4_ADDR Ip;\r
645 IP4_ADDR Netmask;\r
216f7970 646 EFI_ARP_PROTOCOL *Arp;\r
772db4bb 647\r
648 IpSb = IpInstance->Service;\r
649\r
650 //\r
651 // User is changing packet filters. It must be stopped\r
652 // before the station address can be changed.\r
653 //\r
654 if (IpInstance->State == IP4_STATE_CONFIGED) {\r
655 //\r
656 // Cancel all the pending transmit/receive from upper layer\r
657 //\r
658 Status = Ip4Cancel (IpInstance, NULL);\r
659\r
660 if (EFI_ERROR (Status)) {\r
661 return EFI_DEVICE_ERROR;\r
662 }\r
663\r
687a2e5f 664 CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData));\r
772db4bb 665 return EFI_SUCCESS;\r
666 }\r
667\r
668 //\r
669 // Configure a fresh IP4 protocol instance. Create a route table.\r
670 // Each IP child has its own route table, which may point to the\r
671 // default table if it is using default address.\r
672 //\r
673 Status = EFI_OUT_OF_RESOURCES;\r
674 IpInstance->RouteTable = Ip4CreateRouteTable ();\r
675\r
676 if (IpInstance->RouteTable == NULL) {\r
677 return Status;\r
678 }\r
679\r
680 //\r
681 // Set up the interface.\r
682 //\r
e48e37fc 683 CopyMem (&Ip, &Config->StationAddress, sizeof (IP4_ADDR));\r
684 CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
772db4bb 685\r
686 Ip = NTOHL (Ip);\r
687 Netmask = NTOHL (Netmask);\r
688\r
689 if (!Config->UseDefaultAddress) {\r
690 //\r
691 // Find whether there is already an interface with the same\r
692 // station address. All the instances with the same station\r
693 // address shares one interface.\r
694 //\r
695 IpIf = Ip4FindStationAddress (IpSb, Ip, Netmask);\r
696\r
697 if (IpIf != NULL) {\r
698 NET_GET_REF (IpIf);\r
699\r
700 } else {\r
701 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
702\r
703 if (IpIf == NULL) {\r
704 goto ON_ERROR;\r
705 }\r
706\r
707 Status = Ip4SetAddress (IpIf, Ip, Netmask);\r
708\r
709 if (EFI_ERROR (Status)) {\r
710 Status = EFI_DEVICE_ERROR;\r
711 Ip4FreeInterface (IpIf, IpInstance);\r
712 goto ON_ERROR;\r
713 }\r
714\r
e48e37fc 715 InsertTailList (&IpSb->Interfaces, &IpIf->Link);\r
772db4bb 716 }\r
717\r
718 //\r
719 // Add a route to this connected network in the route table\r
720 //\r
721 Ip4AddRoute (IpInstance->RouteTable, Ip, Netmask, IP4_ALLZERO_ADDRESS);\r
722\r
723 } else {\r
724 //\r
725 // Use the default address. If the default configuration hasn't\r
726 // been started, start it.\r
727 //\r
728 if (IpSb->State == IP4_SERVICE_UNSTARTED) {\r
2c320007
JW
729 //\r
730 // Create the ReconfigEvent to start the new configuration.\r
731 //\r
732 if (IpSb->ReconfigEvent == NULL) {\r
733 Status = gBS->CreateEvent (\r
734 EVT_NOTIFY_SIGNAL,\r
735 TPL_NOTIFY,\r
736 Ip4AutoReconfigCallBack,\r
737 IpSb,\r
738 &IpSb->ReconfigEvent\r
739 );\r
740\r
741 if (EFI_ERROR (Status)) {\r
742 goto ON_ERROR;\r
743 }\r
744 }\r
745 \r
3d0a49ad
JW
746 Status = Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
747\r
748 if (EFI_ERROR (Status)) {\r
2c320007 749 goto CLOSE_RECONFIG_EVENT;\r
3d0a49ad 750 }\r
772db4bb 751 }\r
752\r
753 IpIf = IpSb->DefaultInterface;\r
754 NET_GET_REF (IpSb->DefaultInterface);\r
755\r
756 //\r
757 // If default address is used, so is the default route table.\r
758 // Any route set by the instance has the precedence over the\r
759 // routes in the default route table. Link the default table\r
760 // after the instance's table. Routing will search the local\r
761 // table first.\r
762 //\r
763 NET_GET_REF (IpSb->DefaultRouteTable);\r
764 IpInstance->RouteTable->Next = IpSb->DefaultRouteTable;\r
765 }\r
766\r
767 IpInstance->Interface = IpIf;\r
216f7970 768 if (IpIf->Arp != NULL) {\r
769 Arp = NULL;\r
770 Status = gBS->OpenProtocol (\r
771 IpIf->ArpHandle,\r
772 &gEfiArpProtocolGuid,\r
773 (VOID **) &Arp,\r
774 gIp4DriverBinding.DriverBindingHandle,\r
775 IpInstance->Handle,\r
776 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
777 );\r
778 if (EFI_ERROR (Status)) {\r
2c320007 779 goto CLOSE_RECONFIG_EVENT;\r
216f7970 780 }\r
781 }\r
e48e37fc 782 InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink);\r
772db4bb 783\r
687a2e5f 784 CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData));\r
772db4bb 785 IpInstance->State = IP4_STATE_CONFIGED;\r
786\r
787 //\r
788 // Although EFI_NO_MAPPING is an error code, the IP child has been\r
789 // successfully configured and doesn't need reconfiguration when\r
790 // default address is acquired.\r
791 //\r
792 if (Config->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
793 return EFI_NO_MAPPING;\r
794 }\r
795\r
796 return EFI_SUCCESS;\r
797\r
2c320007
JW
798CLOSE_RECONFIG_EVENT:\r
799 if (IpSb->ReconfigEvent != NULL) {\r
800 gBS->CloseEvent (IpSb->ReconfigEvent);\r
801 IpSb->ReconfigEvent = NULL;\r
802 }\r
803\r
772db4bb 804ON_ERROR:\r
805 Ip4FreeRouteTable (IpInstance->RouteTable);\r
806 IpInstance->RouteTable = NULL;\r
807 return Status;\r
808}\r
809\r
810\r
811/**\r
812 Clean up the IP4 child, release all the resources used by it.\r
813\r
3e8c18da 814 @param[in] IpInstance The IP4 child to clean up.\r
772db4bb 815\r
1f6729ff 816 @retval EFI_SUCCESS The IP4 child is cleaned up.\r
817 @retval EFI_DEVICE_ERROR Some resources failed to be released.\r
772db4bb 818\r
819**/\r
820EFI_STATUS\r
821Ip4CleanProtocol (\r
822 IN IP4_PROTOCOL *IpInstance\r
823 )\r
824{\r
825 if (EFI_ERROR (Ip4Cancel (IpInstance, NULL))) {\r
826 return EFI_DEVICE_ERROR;\r
827 }\r
828\r
829 if (EFI_ERROR (Ip4Groups (IpInstance, FALSE, NULL))) {\r
830 return EFI_DEVICE_ERROR;\r
831 }\r
832\r
833 //\r
834 // Some packets haven't been recycled. It is because either the\r
835 // user forgets to recycle the packets, or because the callback\r
836 // hasn't been called. Just leave it alone.\r
837 //\r
e48e37fc 838 if (!IsListEmpty (&IpInstance->Delivered)) {\r
772db4bb 839 ;\r
840 }\r
841\r
842 if (IpInstance->Interface != NULL) {\r
e48e37fc 843 RemoveEntryList (&IpInstance->AddrLink);\r
216f7970 844 if (IpInstance->Interface->Arp != NULL) {\r
845 gBS->CloseProtocol (\r
846 IpInstance->Interface->ArpHandle,\r
847 &gEfiArpProtocolGuid,\r
848 gIp4DriverBinding.DriverBindingHandle,\r
849 IpInstance->Handle\r
850 );\r
851 }\r
772db4bb 852 Ip4FreeInterface (IpInstance->Interface, IpInstance);\r
853 IpInstance->Interface = NULL;\r
854 }\r
855\r
856 if (IpInstance->RouteTable != NULL) {\r
857 if (IpInstance->RouteTable->Next != NULL) {\r
858 Ip4FreeRouteTable (IpInstance->RouteTable->Next);\r
859 }\r
860\r
861 Ip4FreeRouteTable (IpInstance->RouteTable);\r
862 IpInstance->RouteTable = NULL;\r
863 }\r
864\r
865 if (IpInstance->EfiRouteTable != NULL) {\r
766c7483 866 FreePool (IpInstance->EfiRouteTable);\r
772db4bb 867 IpInstance->EfiRouteTable = NULL;\r
868 IpInstance->EfiRouteCount = 0;\r
869 }\r
870\r
871 if (IpInstance->Groups != NULL) {\r
766c7483 872 FreePool (IpInstance->Groups);\r
772db4bb 873 IpInstance->Groups = NULL;\r
874 IpInstance->GroupCount = 0;\r
875 }\r
876\r
877 NetMapClean (&IpInstance->TxTokens);\r
878\r
879 NetMapClean (&IpInstance->RxTokens);\r
880\r
881 return EFI_SUCCESS;\r
882}\r
883\r
884\r
885/**\r
886 Validate that Ip/Netmask pair is OK to be used as station\r
887 address. Only continuous netmasks are supported. and check\r
888 that StationAddress is a unicast address on the newtwork.\r
889\r
1f6729ff 890 @param[in] Ip The IP address to validate.\r
891 @param[in] Netmask The netmaks of the IP.\r
772db4bb 892\r
1f6729ff 893 @retval TRUE The Ip/Netmask pair is valid.\r
894 @retval FALSE The Ip/Netmask pair is invalid.\r
772db4bb 895\r
896**/\r
897BOOLEAN\r
898Ip4StationAddressValid (\r
899 IN IP4_ADDR Ip,\r
900 IN IP4_ADDR Netmask\r
901 )\r
902{\r
903 IP4_ADDR NetBrdcastMask;\r
904 INTN Len;\r
905 INTN Type;\r
906\r
907 //\r
908 // Only support the station address with 0.0.0.0/0 to enable DHCP client.\r
909 //\r
910 if (Netmask == IP4_ALLZERO_ADDRESS) {\r
911 return (BOOLEAN) (Ip == IP4_ALLZERO_ADDRESS);\r
912 }\r
913\r
914 //\r
915 // Only support the continuous net masks\r
916 //\r
917 if ((Len = NetGetMaskLength (Netmask)) == IP4_MASK_NUM) {\r
918 return FALSE;\r
919 }\r
920\r
921 //\r
922 // Station address can't be class D or class E address\r
923 //\r
924 if ((Type = NetGetIpClass (Ip)) > IP4_ADDR_CLASSC) {\r
925 return FALSE;\r
926 }\r
927\r
928 //\r
929 // Station address can't be subnet broadcast/net broadcast address\r
930 //\r
931 if ((Ip == (Ip & Netmask)) || (Ip == (Ip | ~Netmask))) {\r
932 return FALSE;\r
933 }\r
934\r
2a86ff1c 935 NetBrdcastMask = gIp4AllMasks[MIN (Len, Type << 3)];\r
772db4bb 936\r
937 if (Ip == (Ip | ~NetBrdcastMask)) {\r
938 return FALSE;\r
939 }\r
940\r
941 return TRUE;\r
942}\r
943\r
944\r
945/**\r
5405e9a6 946 Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance.\r
e2851998 947\r
5405e9a6 948 The Configure() function is used to set, change, or reset the operational\r
949 parameters and filter settings for this EFI IPv4 Protocol instance. Until these\r
950 parameters have been set, no network traffic can be sent or received by this\r
951 instance. Once the parameters have been reset (by calling this function with\r
952 IpConfigData set to NULL), no more traffic can be sent or received until these\r
953 parameters have been set again. Each EFI IPv4 Protocol instance can be started\r
954 and stopped independently of each other by enabling or disabling their receive\r
955 filter settings with the Configure() function.\r
e2851998 956\r
5405e9a6 957 When IpConfigData.UseDefaultAddress is set to FALSE, the new station address will\r
958 be appended as an alias address into the addresses list in the EFI IPv4 Protocol\r
959 driver. While set to TRUE, Configure() will trigger the EFI_IP4_CONFIG_PROTOCOL\r
960 to retrieve the default IPv4 address if it is not available yet. Clients could\r
961 frequently call GetModeData() to check the status to ensure that the default IPv4\r
962 address is ready.\r
e2851998 963\r
5405e9a6 964 If operational parameters are reset or changed, any pending transmit and receive\r
965 requests will be cancelled. Their completion token status will be set to EFI_ABORTED\r
966 and their events will be signaled.\r
967\r
3e8c18da 968 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
969 @param[in] IpConfigData Pointer to the EFI IPv4 Protocol configuration data structure.\r
5405e9a6 970\r
971 @retval EFI_SUCCESS The driver instance was successfully opened.\r
972 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
973 RARP, etc.) is not finished yet.\r
974 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
975 @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE:\r
976 A configuration protocol (DHCP, BOOTP, RARP, etc.) could\r
977 not be located when clients choose to use the default IPv4\r
978 address. This EFI IPv4 Protocol implementation does not\r
979 support this requested filter or timeout setting.\r
980 @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated.\r
981 @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the\r
982 IPv4 address or subnet mask can be changed. The interface must\r
983 also be stopped when switching to/from raw packet mode.\r
984 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4\r
985 Protocol driver instance is not opened.\r
772db4bb 986\r
987**/\r
772db4bb 988EFI_STATUS\r
989EFIAPI\r
990EfiIp4Configure (\r
991 IN EFI_IP4_PROTOCOL *This,\r
992 IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL\r
993 )\r
994{\r
995 IP4_PROTOCOL *IpInstance;\r
996 EFI_IP4_CONFIG_DATA *Current;\r
997 EFI_TPL OldTpl;\r
998 EFI_STATUS Status;\r
999 BOOLEAN AddrOk;\r
1000 IP4_ADDR IpAddress;\r
1001 IP4_ADDR SubnetMask;\r
1002\r
1003 //\r
1004 // First, validate the parameters\r
1005 //\r
1006 if (This == NULL) {\r
1007 return EFI_INVALID_PARAMETER;\r
1008 }\r
1009\r
1010 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
e48e37fc 1011 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1012\r
1013 //\r
1014 // Validate the configuration first.\r
1015 //\r
1016 if (IpConfigData != NULL) {\r
772db4bb 1017\r
e48e37fc 1018 CopyMem (&IpAddress, &IpConfigData->StationAddress, sizeof (IP4_ADDR));\r
1019 CopyMem (&SubnetMask, &IpConfigData->SubnetMask, sizeof (IP4_ADDR));\r
772db4bb 1020\r
1021 IpAddress = NTOHL (IpAddress);\r
1022 SubnetMask = NTOHL (SubnetMask);\r
1023\r
1024 //\r
1025 // Check whether the station address is a valid unicast address\r
1026 //\r
1027 if (!IpConfigData->UseDefaultAddress) {\r
1028 AddrOk = Ip4StationAddressValid (IpAddress, SubnetMask);\r
1029\r
1030 if (!AddrOk) {\r
1031 Status = EFI_INVALID_PARAMETER;\r
1032 goto ON_EXIT;\r
1033 }\r
1034 }\r
1035\r
1036 //\r
1037 // User can only update packet filters when already configured.\r
1038 // If it wants to change the station address, it must configure(NULL)\r
1039 // the instance first.\r
1040 //\r
1041 if (IpInstance->State == IP4_STATE_CONFIGED) {\r
1042 Current = &IpInstance->ConfigData;\r
1043\r
1044 if (Current->UseDefaultAddress != IpConfigData->UseDefaultAddress) {\r
1045 Status = EFI_ALREADY_STARTED;\r
1046 goto ON_EXIT;\r
1047 }\r
1048\r
1049 if (!Current->UseDefaultAddress &&\r
84b5c78e 1050 (!EFI_IP4_EQUAL (&Current->StationAddress, &IpConfigData->StationAddress) ||\r
1051 !EFI_IP4_EQUAL (&Current->SubnetMask, &IpConfigData->SubnetMask))) {\r
772db4bb 1052 Status = EFI_ALREADY_STARTED;\r
1053 goto ON_EXIT;\r
1054 }\r
1055\r
1056 if (Current->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
ae0a0b06 1057 Status = EFI_NO_MAPPING;\r
1058 goto ON_EXIT;\r
772db4bb 1059 }\r
1060 }\r
1061 }\r
1062\r
1063 //\r
1064 // Configure the instance or clean it up.\r
1065 //\r
1066 if (IpConfigData != NULL) {\r
1067 Status = Ip4ConfigProtocol (IpInstance, IpConfigData);\r
1068 } else {\r
1069 Status = Ip4CleanProtocol (IpInstance);\r
1070\r
1071 //\r
75dce340 1072 // Don't change the state if it is DESTROY, consider the following\r
772db4bb 1073 // valid sequence: Mnp is unloaded-->Ip Stopped-->Udp Stopped,\r
1074 // Configure (ThisIp, NULL). If the state is changed to UNCONFIGED,\r
1075 // the unload fails miserably.\r
1076 //\r
1077 if (IpInstance->State == IP4_STATE_CONFIGED) {\r
1078 IpInstance->State = IP4_STATE_UNCONFIGED;\r
1079 }\r
1080 }\r
1081\r
1082 //\r
1083 // Update the MNP's configure data. Ip4ServiceConfigMnp will check\r
1084 // whether it is necessary to reconfigure the MNP.\r
1085 //\r
1086 Ip4ServiceConfigMnp (IpInstance->Service, FALSE);\r
1087\r
772db4bb 1088ON_EXIT:\r
e48e37fc 1089 gBS->RestoreTPL (OldTpl);\r
772db4bb 1090 return Status;\r
1091\r
1092}\r
1093\r
1094\r
1095/**\r
1096 Change the IP4 child's multicast setting. The caller\r
1097 should make sure that the parameters is valid.\r
1098\r
3e8c18da 1099 @param[in] IpInstance The IP4 child to change the setting.\r
1f6729ff 1100 @param[in] JoinFlag TRUE to join the group, otherwise leave it.\r
1101 @param[in] GroupAddress The target group address.\r
772db4bb 1102\r
1f6729ff 1103 @retval EFI_ALREADY_STARTED Want to join the group, but already a member of it.\r
772db4bb 1104 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.\r
1f6729ff 1105 @retval EFI_DEVICE_ERROR Failed to set the group configuraton.\r
772db4bb 1106 @retval EFI_SUCCESS Successfully updated the group setting.\r
1107 @retval EFI_NOT_FOUND Try to leave the group which it isn't a member.\r
1108\r
1109**/\r
1110EFI_STATUS\r
1111Ip4Groups (\r
1112 IN IP4_PROTOCOL *IpInstance,\r
1113 IN BOOLEAN JoinFlag,\r
1114 IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL\r
1115 )\r
1116{\r
1117 IP4_ADDR *Members;\r
1118 IP4_ADDR Group;\r
1119 UINT32 Index;\r
1120\r
1121 //\r
1122 // Add it to the instance's Groups, and join the group by IGMP.\r
1123 // IpInstance->Groups is in network byte order. IGMP operates in\r
1124 // host byte order\r
1125 //\r
1126 if (JoinFlag) {\r
e2851998 1127 //\r
894d038a 1128 // When JoinFlag is TRUE, GroupAddress shouldn't be NULL.\r
1129 //\r
1130 ASSERT (GroupAddress != NULL);\r
e48e37fc 1131 CopyMem (&Group, GroupAddress, sizeof (IP4_ADDR));\r
772db4bb 1132\r
1133 for (Index = 0; Index < IpInstance->GroupCount; Index++) {\r
1134 if (IpInstance->Groups[Index] == Group) {\r
1135 return EFI_ALREADY_STARTED;\r
1136 }\r
1137 }\r
1138\r
1139 Members = Ip4CombineGroups (IpInstance->Groups, IpInstance->GroupCount, Group);\r
1140\r
1141 if (Members == NULL) {\r
1142 return EFI_OUT_OF_RESOURCES;\r
1143 }\r
1144\r
1145 if (EFI_ERROR (Ip4JoinGroup (IpInstance, NTOHL (Group)))) {\r
766c7483 1146 FreePool (Members);\r
772db4bb 1147 return EFI_DEVICE_ERROR;\r
1148 }\r
1149\r
1150 if (IpInstance->Groups != NULL) {\r
766c7483 1151 FreePool (IpInstance->Groups);\r
772db4bb 1152 }\r
1153\r
1154 IpInstance->Groups = Members;\r
1155 IpInstance->GroupCount++;\r
1156\r
1157 return EFI_SUCCESS;\r
1158 }\r
1159\r
1160 //\r
1161 // Leave the group. Leave all the groups if GroupAddress is NULL.\r
1162 // Must iterate from the end to the beginning because the GroupCount\r
1163 // is decreamented each time an address is removed..\r
1164 //\r
1165 for (Index = IpInstance->GroupCount; Index > 0 ; Index--) {\r
1166 Group = IpInstance->Groups[Index - 1];\r
1167\r
84b5c78e 1168 if ((GroupAddress == NULL) || EFI_IP4_EQUAL (&Group, GroupAddress)) {\r
772db4bb 1169 if (EFI_ERROR (Ip4LeaveGroup (IpInstance, NTOHL (Group)))) {\r
1170 return EFI_DEVICE_ERROR;\r
1171 }\r
1172\r
1173 Ip4RemoveGroupAddr (IpInstance->Groups, IpInstance->GroupCount, Group);\r
1174 IpInstance->GroupCount--;\r
1175\r
1176 if (IpInstance->GroupCount == 0) {\r
1177 ASSERT (Index == 1);\r
1178\r
766c7483 1179 FreePool (IpInstance->Groups);\r
772db4bb 1180 IpInstance->Groups = NULL;\r
1181 }\r
1182\r
1183 if (GroupAddress != NULL) {\r
1184 return EFI_SUCCESS;\r
1185 }\r
1186 }\r
1187 }\r
1188\r
1189 return ((GroupAddress != NULL) ? EFI_NOT_FOUND : EFI_SUCCESS);\r
1190}\r
1191\r
1192\r
1193/**\r
5405e9a6 1194 Joins and leaves multicast groups.\r
e2851998 1195\r
5405e9a6 1196 The Groups() function is used to join and leave multicast group sessions. Joining\r
1197 a group will enable reception of matching multicast packets. Leaving a group will\r
1198 disable the multicast packet reception.\r
e2851998 1199\r
5405e9a6 1200 If JoinFlag is FALSE and GroupAddress is NULL, all joined groups will be left.\r
1201\r
3e8c18da 1202 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
1203 @param[in] JoinFlag Set to TRUE to join the multicast group session and FALSE to leave.\r
1204 @param[in] GroupAddress Pointer to the IPv4 multicast address.\r
5405e9a6 1205\r
1206 @retval EFI_SUCCESS The operation completed successfully.\r
1207 @retval EFI_INVALID_PARAMETER One or more of the following is TRUE:\r
1208 - This is NULL.\r
1209 - JoinFlag is TRUE and GroupAddress is NULL.\r
1210 - GroupAddress is not NULL and *GroupAddress is\r
1211 not a multicast IPv4 address.\r
1212 @retval EFI_NOT_STARTED This instance has not been started.\r
1213 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
1214 RARP, etc.) is not finished yet.\r
1215 @retval EFI_OUT_OF_RESOURCES System resources could not be allocated.\r
1216 @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups.\r
1217 @retval EFI_ALREADY_STARTED The group address is already in the group table (when\r
1218 JoinFlag is TRUE).\r
1219 @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE).\r
1220 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 1221\r
1222**/\r
772db4bb 1223EFI_STATUS\r
1224EFIAPI\r
1225EfiIp4Groups (\r
1226 IN EFI_IP4_PROTOCOL *This,\r
1227 IN BOOLEAN JoinFlag,\r
1228 IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL\r
1229 )\r
1230{\r
1231 IP4_PROTOCOL *IpInstance;\r
1232 EFI_STATUS Status;\r
1233 EFI_TPL OldTpl;\r
1234 IP4_ADDR McastIp;\r
1235\r
1236 if ((This == NULL) || (JoinFlag && (GroupAddress == NULL))) {\r
1237 return EFI_INVALID_PARAMETER;\r
1238 }\r
1239\r
1240 if (GroupAddress != NULL) {\r
e48e37fc 1241 CopyMem (&McastIp, GroupAddress, sizeof (IP4_ADDR));\r
772db4bb 1242\r
1243 if (!IP4_IS_MULTICAST (NTOHL (McastIp))) {\r
1244 return EFI_INVALID_PARAMETER;\r
1245 }\r
1246 }\r
1247\r
1248 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
e48e37fc 1249 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1250\r
1251 if (IpInstance->State != IP4_STATE_CONFIGED) {\r
1252 Status = EFI_NOT_STARTED;\r
1253 goto ON_EXIT;\r
1254 }\r
1255\r
1256 if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
1257 Status = EFI_NO_MAPPING;\r
1258 goto ON_EXIT;\r
1259 }\r
1260\r
1261 Status = Ip4Groups (IpInstance, JoinFlag, GroupAddress);\r
1262\r
1263ON_EXIT:\r
e48e37fc 1264 gBS->RestoreTPL (OldTpl);\r
772db4bb 1265 return Status;\r
1266}\r
1267\r
1268\r
1269/**\r
5405e9a6 1270 Adds and deletes routing table entries.\r
1271\r
1272 The Routes() function adds a route to or deletes a route from the routing table.\r
e2851998 1273\r
5405e9a6 1274 Routes are determined by comparing the SubnetAddress with the destination IPv4\r
1275 address arithmetically AND-ed with the SubnetMask. The gateway address must be\r
1276 on the same subnet as the configured station address.\r
e2851998 1277\r
5405e9a6 1278 The default route is added with SubnetAddress and SubnetMask both set to 0.0.0.0.\r
1279 The default route matches all destination IPv4 addresses that do not match any\r
1280 other routes.\r
e2851998 1281\r
5405e9a6 1282 A GatewayAddress that is zero is a nonroute. Packets are sent to the destination\r
1283 IP address if it can be found in the ARP cache or on the local subnet. One automatic\r
1284 nonroute entry will be inserted into the routing table for outgoing packets that\r
1285 are addressed to a local subnet (gateway address of 0.0.0.0).\r
e2851998 1286\r
5405e9a6 1287 Each EFI IPv4 Protocol instance has its own independent routing table. Those EFI\r
1288 IPv4 Protocol instances that use the default IPv4 address will also have copies\r
1289 of the routing table that was provided by the EFI_IP4_CONFIG_PROTOCOL, and these\r
1290 copies will be updated whenever the EIF IPv4 Protocol driver reconfigures its\r
1291 instances. As a result, client modification to the routing table will be lost.\r
1292\r
3e8c18da 1293 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
1294 @param[in] DeleteRoute Set to TRUE to delete this route from the routing table. Set to\r
1295 FALSE to add this route to the routing table. SubnetAddress\r
1296 and SubnetMask are used as the key to each route entry.\r
1297 @param[in] SubnetAddress The address of the subnet that needs to be routed.\r
1298 @param[in] SubnetMask The subnet mask of SubnetAddress.\r
1299 @param[in] GatewayAddress The unicast gateway IPv4 address for this route.\r
5405e9a6 1300\r
1301 @retval EFI_SUCCESS The operation completed successfully.\r
1302 @retval EFI_NOT_STARTED The driver instance has not been started.\r
1303 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
1304 RARP, etc.) is not finished yet.\r
1305 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
1306 - This is NULL.\r
1307 - SubnetAddress is NULL.\r
1308 - SubnetMask is NULL.\r
1309 - GatewayAddress is NULL.\r
1310 - *SubnetAddress is not a valid subnet address.\r
1311 - *SubnetMask is not a valid subnet mask.\r
1312 - *GatewayAddress is not a valid unicast IPv4 address.\r
1313 @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.\r
1314 @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE).\r
1315 @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when\r
1316 DeleteRoute is FALSE).\r
e2851998 1317\r
772db4bb 1318**/\r
772db4bb 1319EFI_STATUS\r
1320EFIAPI\r
1321EfiIp4Routes (\r
1322 IN EFI_IP4_PROTOCOL *This,\r
1323 IN BOOLEAN DeleteRoute,\r
1324 IN EFI_IPv4_ADDRESS *SubnetAddress,\r
1325 IN EFI_IPv4_ADDRESS *SubnetMask,\r
1326 IN EFI_IPv4_ADDRESS *GatewayAddress\r
1327 )\r
1328{\r
1329 IP4_PROTOCOL *IpInstance;\r
1330 IP4_INTERFACE *IpIf;\r
1331 IP4_ADDR Dest;\r
1332 IP4_ADDR Netmask;\r
1333 IP4_ADDR Nexthop;\r
1334 EFI_STATUS Status;\r
1335 EFI_TPL OldTpl;\r
1336\r
1337 //\r
1338 // First, validate the parameters\r
1339 //\r
1340 if ((This == NULL) || (SubnetAddress == NULL) ||\r
1341 (SubnetMask == NULL) || (GatewayAddress == NULL)) {\r
1342 return EFI_INVALID_PARAMETER;\r
1343 }\r
1344\r
1345 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
e48e37fc 1346 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1347\r
1348 if (IpInstance->State != IP4_STATE_CONFIGED) {\r
1349 Status = EFI_NOT_STARTED;\r
1350 goto ON_EXIT;\r
1351 }\r
1352\r
1353 if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
1354 Status = EFI_NO_MAPPING;\r
1355 goto ON_EXIT;\r
1356 }\r
1357\r
e48e37fc 1358 CopyMem (&Dest, SubnetAddress, sizeof (IP4_ADDR));\r
1359 CopyMem (&Netmask, SubnetMask, sizeof (IP4_ADDR));\r
1360 CopyMem (&Nexthop, GatewayAddress, sizeof (IP4_ADDR));\r
772db4bb 1361\r
1362 Dest = NTOHL (Dest);\r
1363 Netmask = NTOHL (Netmask);\r
1364 Nexthop = NTOHL (Nexthop);\r
1365\r
1366 IpIf = IpInstance->Interface;\r
1367\r
1368 if (!IP4_IS_VALID_NETMASK (Netmask)) {\r
1369 Status = EFI_INVALID_PARAMETER;\r
1370 goto ON_EXIT;\r
1371 }\r
1372\r
1373 //\r
1374 // the gateway address must be a unicast on the connected network if not zero.\r
1375 //\r
1376 if ((Nexthop != IP4_ALLZERO_ADDRESS) &&\r
1377 (!IP4_NET_EQUAL (Nexthop, IpIf->Ip, IpIf->SubnetMask) ||\r
1378 IP4_IS_BROADCAST (Ip4GetNetCast (Nexthop, IpIf)))) {\r
1379\r
1380 Status = EFI_INVALID_PARAMETER;\r
1381 goto ON_EXIT;\r
1382 }\r
1383\r
1384 if (DeleteRoute) {\r
1385 Status = Ip4DelRoute (IpInstance->RouteTable, Dest, Netmask, Nexthop);\r
1386 } else {\r
1387 Status = Ip4AddRoute (IpInstance->RouteTable, Dest, Netmask, Nexthop);\r
1388 }\r
1389\r
1390ON_EXIT:\r
e48e37fc 1391 gBS->RestoreTPL (OldTpl);\r
772db4bb 1392 return Status;\r
1393}\r
1394\r
1395\r
1396/**\r
1397 Check whether the user's token or event has already\r
5405e9a6 1398 been enqueued on IP4's list.\r
772db4bb 1399\r
3e8c18da 1400 @param[in] Map The container of either user's transmit or receive\r
1401 token.\r
1f6729ff 1402 @param[in] Item Current item to check against.\r
3e8c18da 1403 @param[in] Context The Token to check againist.\r
772db4bb 1404\r
1f6729ff 1405 @retval EFI_ACCESS_DENIED The token or event has already been enqueued in IP.\r
772db4bb 1406 @retval EFI_SUCCESS The current item isn't the same token/event as the\r
1407 context.\r
1408\r
1409**/\r
772db4bb 1410EFI_STATUS\r
e798cd87 1411EFIAPI\r
772db4bb 1412Ip4TokenExist (\r
1413 IN NET_MAP *Map,\r
1414 IN NET_MAP_ITEM *Item,\r
1415 IN VOID *Context\r
1416 )\r
1417{\r
1418 EFI_IP4_COMPLETION_TOKEN *Token;\r
1419 EFI_IP4_COMPLETION_TOKEN *TokenInItem;\r
1420\r
1421 Token = (EFI_IP4_COMPLETION_TOKEN *) Context;\r
1422 TokenInItem = (EFI_IP4_COMPLETION_TOKEN *) Item->Key;\r
1423\r
1424 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
1425 return EFI_ACCESS_DENIED;\r
1426 }\r
1427\r
1428 return EFI_SUCCESS;\r
1429}\r
1430\r
772db4bb 1431/**\r
1432 Validate the user's token against current station address.\r
1433\r
216f7970 1434 @param[in] Token User's token to validate.\r
1435 @param[in] IpIf The IP4 child's interface.\r
1436 @param[in] RawData Set to TRUE to send unformatted packets.\r
772db4bb 1437\r
216f7970 1438 @retval EFI_INVALID_PARAMETER Some parameters are invalid.\r
772db4bb 1439 @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long.\r
216f7970 1440 @retval EFI_SUCCESS The token is valid.\r
772db4bb 1441\r
1442**/\r
772db4bb 1443EFI_STATUS\r
1444Ip4TxTokenValid (\r
1445 IN EFI_IP4_COMPLETION_TOKEN *Token,\r
216f7970 1446 IN IP4_INTERFACE *IpIf,\r
1447 IN BOOLEAN RawData\r
772db4bb 1448 )\r
1449{\r
1450 EFI_IP4_TRANSMIT_DATA *TxData;\r
1451 EFI_IP4_OVERRIDE_DATA *Override;\r
1452 IP4_ADDR Src;\r
1453 IP4_ADDR Gateway;\r
1454 UINT32 Offset;\r
1455 UINT32 Index;\r
1456 UINT32 HeadLen;\r
1457\r
1458 if ((Token == NULL) || (Token->Event == NULL) || (Token->Packet.TxData == NULL)) {\r
1459 return EFI_INVALID_PARAMETER;\r
1460 }\r
1461\r
1462 TxData = Token->Packet.TxData;\r
1463\r
1464 //\r
216f7970 1465 // Check the fragment table: no empty fragment, and length isn't bogus.\r
772db4bb 1466 //\r
1467 if ((TxData->TotalDataLength == 0) || (TxData->FragmentCount == 0)) {\r
1468 return EFI_INVALID_PARAMETER;\r
1469 }\r
1470\r
1471 Offset = TxData->TotalDataLength;\r
1472\r
216f7970 1473 if (Offset > IP4_MAX_PACKET_SIZE) {\r
1474 return EFI_BAD_BUFFER_SIZE;\r
1475 }\r
1476\r
772db4bb 1477 for (Index = 0; Index < TxData->FragmentCount; Index++) {\r
1478 if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) ||\r
1479 (TxData->FragmentTable[Index].FragmentLength == 0)) {\r
1480\r
1481 return EFI_INVALID_PARAMETER;\r
1482 }\r
1483\r
1484 Offset -= TxData->FragmentTable[Index].FragmentLength;\r
1485 }\r
1486\r
1487 if (Offset != 0) {\r
1488 return EFI_INVALID_PARAMETER;\r
1489 }\r
1490\r
216f7970 1491 //\r
1492 // NOTE that OptionsLength/OptionsBuffer/OverrideData are ignored if RawData\r
1493 // is TRUE.\r
1494 //\r
1495 if (RawData) {\r
1496 return EFI_SUCCESS;\r
1497 }\r
1498\r
1499 //\r
1500 // Check the IP options: no more than 40 bytes and format is OK\r
1501 //\r
1502 if (TxData->OptionsLength != 0) {\r
1503 if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) {\r
1504 return EFI_INVALID_PARAMETER;\r
1505 }\r
1506\r
1507 if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) {\r
1508 return EFI_INVALID_PARAMETER;\r
1509 }\r
1510 }\r
1511\r
772db4bb 1512 //\r
1513 // Check the source and gateway: they must be a valid unicast.\r
1514 // Gateway must also be on the connected network.\r
1515 //\r
e2851998 1516 if (TxData->OverrideData != NULL) {\r
772db4bb 1517 Override = TxData->OverrideData;\r
1518\r
e48e37fc 1519 CopyMem (&Src, &Override->SourceAddress, sizeof (IP4_ADDR));\r
1520 CopyMem (&Gateway, &Override->GatewayAddress, sizeof (IP4_ADDR));\r
772db4bb 1521\r
1522 Src = NTOHL (Src);\r
1523 Gateway = NTOHL (Gateway);\r
1524\r
1525 if ((NetGetIpClass (Src) > IP4_ADDR_CLASSC) ||\r
1526 (Src == IP4_ALLONE_ADDRESS) ||\r
1527 IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {\r
1528\r
1529 return EFI_INVALID_PARAMETER;\r
1530 }\r
1531\r
1532 //\r
1533 // If gateway isn't zero, it must be a unicast address, and\r
1534 // on the connected network.\r
1535 //\r
1536 if ((Gateway != IP4_ALLZERO_ADDRESS) &&\r
1537 ((NetGetIpClass (Gateway) > IP4_ADDR_CLASSC) ||\r
1538 !IP4_NET_EQUAL (Gateway, IpIf->Ip, IpIf->SubnetMask) ||\r
1539 IP4_IS_BROADCAST (Ip4GetNetCast (Gateway, IpIf)))) {\r
1540\r
1541 return EFI_INVALID_PARAMETER;\r
1542 }\r
1543 }\r
1544\r
1545 //\r
1546 // Check the packet length: Head length and packet length all has a limit\r
1547 //\r
1548 HeadLen = sizeof (IP4_HEAD) + ((TxData->OptionsLength + 3) &~0x03);\r
1549\r
1550 if ((HeadLen > IP4_MAX_HEADLEN) ||\r
1551 (TxData->TotalDataLength + HeadLen > IP4_MAX_PACKET_SIZE)) {\r
1552\r
1553 return EFI_BAD_BUFFER_SIZE;\r
1554 }\r
1555\r
1556 return EFI_SUCCESS;\r
1557}\r
1558\r
1559\r
1560/**\r
1561 The callback function for the net buffer which wraps the user's\r
1562 transmit token. Although it seems this function is pretty simple,\r
1563 there are some subtle things.\r
1564 When user requests the IP to transmit a packet by passing it a\r
1565 token, the token is wrapped in an IP4_TXTOKEN_WRAP and the data\r
1566 is wrapped in an net buffer. the net buffer's Free function is\r
1567 set to Ip4FreeTxToken. The Token and token wrap are added to the\r
1568 IP child's TxToken map. Then the buffer is passed to Ip4Output for\r
1569 transmission. If something error happened before that, the buffer\r
1570 is freed, which in turn will free the token wrap. The wrap may\r
1571 have been added to the TxToken map or not, and the user's event\r
1572 shouldn't be fired because we are still in the EfiIp4Transmit. If\r
1573 the buffer has been sent by Ip4Output, it should be removed from\r
1574 the TxToken map and user's event signaled. The token wrap and buffer\r
1575 are bound together. Check the comments in Ip4Output for information\r
1576 about IP fragmentation.\r
1577\r
1f6729ff 1578 @param[in] Context The token's wrap.\r
772db4bb 1579\r
1580**/\r
772db4bb 1581VOID\r
e798cd87 1582EFIAPI\r
772db4bb 1583Ip4FreeTxToken (\r
1584 IN VOID *Context\r
1585 )\r
1586{\r
1587 IP4_TXTOKEN_WRAP *Wrap;\r
1588 NET_MAP_ITEM *Item;\r
1589\r
1590 Wrap = (IP4_TXTOKEN_WRAP *) Context;\r
1591\r
a1503a32 1592 //\r
1593 // Signal IpSecRecycleEvent to inform IPsec free the memory\r
1594 //\r
1595 if (Wrap->IpSecRecycleSignal != NULL) {\r
1596 gBS->SignalEvent (Wrap->IpSecRecycleSignal);\r
1597 }\r
1598\r
772db4bb 1599 //\r
1600 // Find the token in the instance's map. EfiIp4Transmit put the\r
1601 // token to the map. If that failed, NetMapFindKey will return NULL.\r
1602 //\r
1603 Item = NetMapFindKey (&Wrap->IpInstance->TxTokens, Wrap->Token);\r
1604\r
1605 if (Item != NULL) {\r
1606 NetMapRemoveItem (&Wrap->IpInstance->TxTokens, Item, NULL);\r
1607 }\r
1608\r
1609 if (Wrap->Sent) {\r
1610 gBS->SignalEvent (Wrap->Token->Event);\r
36ee91ca 1611\r
1612 //\r
1613 // Dispatch the DPC queued by the NotifyFunction of Token->Event.\r
1614 //\r
d8d26fb2 1615 DispatchDpc ();\r
772db4bb 1616 }\r
1617\r
766c7483 1618 FreePool (Wrap);\r
772db4bb 1619}\r
1620\r
1621\r
1622/**\r
1623 The callback function to Ip4Output to update the transmit status.\r
1624\r
1625 @param Ip4Instance The Ip4Instance that request the transmit.\r
1f6729ff 1626 @param Packet The user's transmit request.\r
1627 @param IoStatus The result of the transmission.\r
1628 @param Flag Not used during transmission.\r
772db4bb 1629 @param Context The token's wrap.\r
1630\r
772db4bb 1631**/\r
772db4bb 1632VOID\r
1633Ip4OnPacketSent (\r
1634 IP4_PROTOCOL *Ip4Instance,\r
1635 NET_BUF *Packet,\r
1636 EFI_STATUS IoStatus,\r
1637 UINT32 Flag,\r
1638 VOID *Context\r
1639 )\r
1640{\r
1641 IP4_TXTOKEN_WRAP *Wrap;\r
1642\r
1643 //\r
1644 // This is the transmission request from upper layer,\r
1645 // not the IP4 driver itself.\r
1646 //\r
1647 ASSERT (Ip4Instance != NULL);\r
1648\r
1649 //\r
1650 // The first fragment of the packet has been sent. Update\r
1651 // the token's status. That is, if fragmented, the transmit's\r
1652 // status is the first fragment's status. The Wrap will be\r
1653 // release when all the fragments are release. Check the comments\r
1654 // in Ip4FreeTxToken and Ip4Output for information.\r
1655 //\r
1656 Wrap = (IP4_TXTOKEN_WRAP *) Context;\r
1657 Wrap->Token->Status = IoStatus;\r
1658\r
1659 NetbufFree (Wrap->Packet);\r
1660}\r
1661\r
1662\r
1663/**\r
5405e9a6 1664 Places outgoing data packets into the transmit queue.\r
1665\r
1666 The Transmit() function places a sending request in the transmit queue of this\r
1667 EFI IPv4 Protocol instance. Whenever the packet in the token is sent out or some\r
1668 errors occur, the event in the token will be signaled and the status is updated.\r
1669\r
3e8c18da 1670 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
1671 @param[in] Token Pointer to the transmit token.\r
5405e9a6 1672\r
1673 @retval EFI_SUCCESS The data has been queued for transmission.\r
1674 @retval EFI_NOT_STARTED This instance has not been started.\r
1675 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
1676 RARP, etc.) is not finished yet.\r
1677 @retval EFI_INVALID_PARAMETER One or more pameters are invalid.\r
1678 @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event\r
1679 was already in the transmit queue.\r
1680 @retval EFI_NOT_READY The completion token could not be queued because the transmit\r
e2851998 1681 queue is full.\r
5405e9a6 1682 @retval EFI_NOT_FOUND Not route is found to destination address.\r
1683 @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.\r
1684 @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too\r
1685 short to transmit.\r
1686 @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is\r
1687 greater than MTU (or greater than the maximum packet size if\r
1688 Token.Packet.TxData.OverrideData.\r
1f6729ff 1689 DoNotFragment is TRUE).\r
772db4bb 1690\r
1691**/\r
772db4bb 1692EFI_STATUS\r
1693EFIAPI\r
1694EfiIp4Transmit (\r
1695 IN EFI_IP4_PROTOCOL *This,\r
1696 IN EFI_IP4_COMPLETION_TOKEN *Token\r
1697 )\r
1698{\r
1699 IP4_SERVICE *IpSb;\r
1700 IP4_PROTOCOL *IpInstance;\r
1701 IP4_INTERFACE *IpIf;\r
1702 IP4_TXTOKEN_WRAP *Wrap;\r
1703 EFI_IP4_TRANSMIT_DATA *TxData;\r
1704 EFI_IP4_CONFIG_DATA *Config;\r
1705 EFI_IP4_OVERRIDE_DATA *Override;\r
1706 IP4_HEAD Head;\r
1707 IP4_ADDR GateWay;\r
1708 EFI_STATUS Status;\r
1709 EFI_TPL OldTpl;\r
1710 BOOLEAN DontFragment;\r
1711 UINT32 HeadLen;\r
216f7970 1712 UINT8 RawHdrLen;\r
1713 UINT32 OptionsLength;\r
1714 UINT8 *OptionsBuffer;\r
1715 VOID *FirstFragment;\r
772db4bb 1716\r
1717 if (This == NULL) {\r
1718 return EFI_INVALID_PARAMETER;\r
1719 }\r
1720\r
1721 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
1722\r
1723 if (IpInstance->State != IP4_STATE_CONFIGED) {\r
1724 return EFI_NOT_STARTED;\r
1725 }\r
1726\r
e48e37fc 1727 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1728\r
1729 IpSb = IpInstance->Service;\r
1730 IpIf = IpInstance->Interface;\r
1731 Config = &IpInstance->ConfigData;\r
1732\r
1733 if (Config->UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
1734 Status = EFI_NO_MAPPING;\r
1735 goto ON_EXIT;\r
1736 }\r
1737\r
1738 //\r
1739 // make sure that token is properly formated\r
1740 //\r
216f7970 1741 Status = Ip4TxTokenValid (Token, IpIf, Config->RawData);\r
772db4bb 1742\r
1743 if (EFI_ERROR (Status)) {\r
1744 goto ON_EXIT;\r
1745 }\r
1746\r
1747 //\r
1748 // Check whether the token or signal already existed.\r
1749 //\r
1750 if (EFI_ERROR (NetMapIterate (&IpInstance->TxTokens, Ip4TokenExist, Token))) {\r
1751 Status = EFI_ACCESS_DENIED;\r
1752 goto ON_EXIT;\r
1753 }\r
1754\r
1755 //\r
1756 // Build the IP header, need to fill in the Tos, TotalLen, Id,\r
1757 // fragment, Ttl, protocol, Src, and Dst.\r
1758 //\r
1759 TxData = Token->Packet.TxData;\r
1760\r
216f7970 1761 FirstFragment = NULL;\r
772db4bb 1762\r
216f7970 1763 if (Config->RawData) {\r
1764 //\r
1765 // When RawData is TRUE, first buffer in FragmentTable points to a raw\r
1766 // IPv4 fragment including IPv4 header and options.\r
1767 //\r
1768 FirstFragment = TxData->FragmentTable[0].FragmentBuffer;\r
1769 CopyMem (&RawHdrLen, FirstFragment, sizeof (UINT8));\r
772db4bb 1770\r
216f7970 1771 RawHdrLen = (UINT8) (RawHdrLen & 0x0f);\r
1772 if (RawHdrLen < 5) {\r
098e9f49
FS
1773 Status = EFI_INVALID_PARAMETER;\r
1774 goto ON_EXIT;\r
216f7970 1775 }\r
1776\r
1777 RawHdrLen = (UINT8) (RawHdrLen << 2);\r
1778 \r
1779 CopyMem (&Head, FirstFragment, IP4_MIN_HEADLEN);\r
1780\r
1781 Ip4NtohHead (&Head);\r
1782 HeadLen = 0;\r
1783 DontFragment = IP4_DO_NOT_FRAGMENT (Head.Fragment);\r
772db4bb 1784\r
216f7970 1785 if (!DontFragment) {\r
098e9f49
FS
1786 Status = EFI_INVALID_PARAMETER;\r
1787 goto ON_EXIT;\r
216f7970 1788 }\r
1789\r
1790 GateWay = IP4_ALLZERO_ADDRESS;\r
1791\r
1792 //\r
1793 // Get IPv4 options from first fragment.\r
1794 //\r
1795 if (RawHdrLen == IP4_MIN_HEADLEN) {\r
1796 OptionsLength = 0;\r
1797 OptionsBuffer = NULL;\r
1798 } else {\r
1799 OptionsLength = RawHdrLen - IP4_MIN_HEADLEN;\r
1800 OptionsBuffer = (UINT8 *) FirstFragment + IP4_MIN_HEADLEN;\r
1801 }\r
1802\r
1803 //\r
1804 // Trim off IPv4 header and options from first fragment.\r
1805 //\r
1806 TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment + RawHdrLen;\r
1807 TxData->FragmentTable[0].FragmentLength = TxData->FragmentTable[0].FragmentLength - RawHdrLen;\r
772db4bb 1808 } else {\r
216f7970 1809 CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR));\r
1810 Head.Dst = NTOHL (Head.Dst);\r
772db4bb 1811\r
216f7970 1812 if (TxData->OverrideData != NULL) {\r
1813 Override = TxData->OverrideData;\r
1814 Head.Protocol = Override->Protocol;\r
1815 Head.Tos = Override->TypeOfService;\r
1816 Head.Ttl = Override->TimeToLive;\r
1817 DontFragment = Override->DoNotFragment;\r
1818\r
1819 CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR));\r
1820 CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR));\r
1821\r
1822 Head.Src = NTOHL (Head.Src);\r
1823 GateWay = NTOHL (GateWay);\r
1824 } else {\r
1825 Head.Src = IpIf->Ip;\r
1826 GateWay = IP4_ALLZERO_ADDRESS;\r
1827 Head.Protocol = Config->DefaultProtocol;\r
1828 Head.Tos = Config->TypeOfService;\r
1829 Head.Ttl = Config->TimeToLive;\r
1830 DontFragment = Config->DoNotFragment;\r
1831 }\r
1832\r
1833 Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0);\r
1834 HeadLen = (TxData->OptionsLength + 3) & (~0x03);\r
1835\r
1836 OptionsLength = TxData->OptionsLength;\r
1837 OptionsBuffer = (UINT8 *) (TxData->OptionsBuffer);\r
1838 }\r
772db4bb 1839\r
1840 //\r
1841 // If don't fragment and fragment needed, return error\r
1842 //\r
a1503a32 1843 if (DontFragment && (TxData->TotalDataLength + HeadLen > IpSb->MaxPacketSize)) {\r
772db4bb 1844 Status = EFI_BAD_BUFFER_SIZE;\r
1845 goto ON_EXIT;\r
1846 }\r
1847\r
1848 //\r
1849 // OK, it survives all the validation check. Wrap the token in\r
1850 // a IP4_TXTOKEN_WRAP and the data in a netbuf\r
1851 //\r
1852 Status = EFI_OUT_OF_RESOURCES;\r
f6b7393c 1853 Wrap = AllocateZeroPool (sizeof (IP4_TXTOKEN_WRAP));\r
772db4bb 1854 if (Wrap == NULL) {\r
1855 goto ON_EXIT;\r
1856 }\r
1857\r
1858 Wrap->IpInstance = IpInstance;\r
1859 Wrap->Token = Token;\r
1860 Wrap->Sent = FALSE;\r
1861 Wrap->Life = IP4_US_TO_SEC (Config->TransmitTimeout);\r
1862 Wrap->Packet = NetbufFromExt (\r
1863 (NET_FRAGMENT *) TxData->FragmentTable,\r
1864 TxData->FragmentCount,\r
1865 IP4_MAX_HEADLEN,\r
1866 0,\r
1867 Ip4FreeTxToken,\r
1868 Wrap\r
1869 );\r
1870\r
1871 if (Wrap->Packet == NULL) {\r
766c7483 1872 FreePool (Wrap);\r
772db4bb 1873 goto ON_EXIT;\r
1874 }\r
1875\r
1876 Token->Status = EFI_NOT_READY;\r
1877\r
1878 if (EFI_ERROR (NetMapInsertTail (&IpInstance->TxTokens, Token, Wrap))) {\r
1879 //\r
1880 // NetbufFree will call Ip4FreeTxToken, which in turn will\r
1881 // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been\r
1882 // enqueued.\r
1883 //\r
216f7970 1884 if (Config->RawData) {\r
1885 //\r
1886 // Restore pointer of first fragment in RawData mode.\r
1887 //\r
1888 TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
1889 }\r
1890\r
772db4bb 1891 NetbufFree (Wrap->Packet);\r
1892 goto ON_EXIT;\r
1893 }\r
1894\r
36ee91ca 1895 //\r
1896 // Mark the packet sent before output it. Mark it not sent again if the\r
1897 // returned status is not EFI_SUCCESS;\r
1898 //\r
1899 Wrap->Sent = TRUE;\r
1900\r
772db4bb 1901 Status = Ip4Output (\r
1902 IpSb,\r
1903 IpInstance,\r
1904 Wrap->Packet,\r
1905 &Head,\r
216f7970 1906 OptionsBuffer,\r
1907 OptionsLength,\r
772db4bb 1908 GateWay,\r
1909 Ip4OnPacketSent,\r
1910 Wrap\r
1911 );\r
1912\r
1913 if (EFI_ERROR (Status)) {\r
36ee91ca 1914 Wrap->Sent = FALSE;\r
216f7970 1915\r
1916 if (Config->RawData) {\r
1917 //\r
1918 // Restore pointer of first fragment in RawData mode.\r
1919 //\r
1920 TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
1921 }\r
1922\r
772db4bb 1923 NetbufFree (Wrap->Packet);\r
772db4bb 1924 }\r
1925\r
216f7970 1926 if (Config->RawData) {\r
1927 //\r
1928 // Restore pointer of first fragment in RawData mode.\r
1929 //\r
1930 TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment;\r
1931 }\r
1932\r
772db4bb 1933ON_EXIT:\r
e48e37fc 1934 gBS->RestoreTPL (OldTpl);\r
772db4bb 1935 return Status;\r
1936}\r
1937\r
1938\r
1939/**\r
5405e9a6 1940 Places a receiving request into the receiving queue.\r
e2851998 1941\r
5405e9a6 1942 The Receive() function places a completion token into the receive packet queue.\r
1943 This function is always asynchronous.\r
e2851998 1944\r
5405e9a6 1945 The Token.Event field in the completion token must be filled in by the caller\r
1946 and cannot be NULL. When the receive operation completes, the EFI IPv4 Protocol\r
1947 driver updates the Token.Status and Token.Packet.RxData fields and the Token.Event\r
1948 is signaled.\r
1949\r
3e8c18da 1950 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
1951 @param[in] Token Pointer to a token that is associated with the receive data descriptor.\r
5405e9a6 1952\r
1953 @retval EFI_SUCCESS The receive completion token was cached.\r
1954 @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.\r
1955 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.)\r
1956 is not finished yet.\r
1957 @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
1958 - This is NULL.\r
1959 - Token is NULL.\r
1960 - Token.Event is NULL.\r
1961 @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system\r
1962 resources (usually memory).\r
1963 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
1964 The EFI IPv4 Protocol instance has been reset to startup defaults.\r
1965 EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already\r
1966 in the receive queue.\r
1967 @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full.\r
1968 @retval EFI_ICMP_ERROR An ICMP error packet was received.\r
772db4bb 1969\r
1970**/\r
772db4bb 1971EFI_STATUS\r
1972EFIAPI\r
1973EfiIp4Receive (\r
1974 IN EFI_IP4_PROTOCOL *This,\r
1975 IN EFI_IP4_COMPLETION_TOKEN *Token\r
1976 )\r
1977{\r
1978 IP4_PROTOCOL *IpInstance;\r
772db4bb 1979 EFI_STATUS Status;\r
1980 EFI_TPL OldTpl;\r
1981\r
1982 //\r
1983 // First validate the parameters\r
1984 //\r
1985 if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {\r
1986 return EFI_INVALID_PARAMETER;\r
1987 }\r
1988\r
1989 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
1990\r
e48e37fc 1991 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1992\r
1993 if (IpInstance->State != IP4_STATE_CONFIGED) {\r
1994 Status = EFI_NOT_STARTED;\r
1995 goto ON_EXIT;\r
1996 }\r
1997\r
772db4bb 1998 //\r
1999 // Check whether the toke is already on the receive queue.\r
2000 //\r
2001 Status = NetMapIterate (&IpInstance->RxTokens, Ip4TokenExist, Token);\r
2002\r
2003 if (EFI_ERROR (Status)) {\r
2004 Status = EFI_ACCESS_DENIED;\r
2005 goto ON_EXIT;\r
2006 }\r
2007\r
2008 //\r
2009 // Queue the token then check whether there is pending received packet.\r
2010 //\r
2011 Status = NetMapInsertTail (&IpInstance->RxTokens, Token, NULL);\r
2012\r
2013 if (EFI_ERROR (Status)) {\r
2014 goto ON_EXIT;\r
2015 }\r
2016\r
2017 Status = Ip4InstanceDeliverPacket (IpInstance);\r
2018\r
36ee91ca 2019 //\r
2020 // Dispatch the DPC queued by the NotifyFunction of this instane's receive\r
2021 // event.\r
2022 //\r
d8d26fb2 2023 DispatchDpc ();\r
36ee91ca 2024\r
772db4bb 2025ON_EXIT:\r
e48e37fc 2026 gBS->RestoreTPL (OldTpl);\r
772db4bb 2027 return Status;\r
2028}\r
2029\r
2030\r
2031/**\r
2032 Cancel the transmitted but not recycled packet. If a matching\r
2033 token is found, it will call Ip4CancelPacket to cancel the\r
2034 packet. Ip4CancelPacket will cancel all the fragments of the\r
2035 packet. When all the fragments are freed, the IP4_TXTOKEN_WRAP\r
2036 will be deleted from the Map, and user's event signalled.\r
2037 Because Ip4CancelPacket and other functions are all called in\r
2038 line, so, after Ip4CancelPacket returns, the Item has been freed.\r
2039\r
1f6729ff 2040 @param[in] Map The IP4 child's transmit queue.\r
2041 @param[in] Item The current transmitted packet to test.\r
2042 @param[in] Context The user's token to cancel.\r
772db4bb 2043\r
2044 @retval EFI_SUCCESS Continue to check the next Item.\r
2045 @retval EFI_ABORTED The user's Token (Token != NULL) is cancelled.\r
2046\r
2047**/\r
772db4bb 2048EFI_STATUS\r
e798cd87 2049EFIAPI\r
772db4bb 2050Ip4CancelTxTokens (\r
2051 IN NET_MAP *Map,\r
2052 IN NET_MAP_ITEM *Item,\r
2053 IN VOID *Context\r
2054 )\r
2055{\r
2056 EFI_IP4_COMPLETION_TOKEN *Token;\r
2057 IP4_TXTOKEN_WRAP *Wrap;\r
2058\r
2059 Token = (EFI_IP4_COMPLETION_TOKEN *) Context;\r
2060\r
2061 //\r
2062 // Return EFI_SUCCESS to check the next item in the map if\r
2063 // this one doesn't match.\r
2064 //\r
2065 if ((Token != NULL) && (Token != Item->Key)) {\r
2066 return EFI_SUCCESS;\r
2067 }\r
2068\r
2069 Wrap = (IP4_TXTOKEN_WRAP *) Item->Value;\r
2070 ASSERT (Wrap != NULL);\r
2071\r
2072 //\r
2073 // Don't access the Item, Wrap and Token's members after this point.\r
2074 // Item and wrap has been freed. And we no longer own the Token.\r
2075 //\r
2076 Ip4CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);\r
2077\r
2078 //\r
2079 // If only one item is to be cancel, return EFI_ABORTED to stop\r
2080 // iterating the map any more.\r
2081 //\r
2082 if (Token != NULL) {\r
2083 return EFI_ABORTED;\r
2084 }\r
2085\r
2086 return EFI_SUCCESS;\r
2087}\r
2088\r
2089\r
2090/**\r
2091 Cancel the receive request. This is quiet simple, because\r
2092 it is only enqueued in our local receive map.\r
2093\r
1f6729ff 2094 @param[in] Map The IP4 child's receive queue.\r
2095 @param[in] Item Current receive request to cancel.\r
2096 @param[in] Context The user's token to cancel.\r
772db4bb 2097\r
2098 @retval EFI_SUCCESS Continue to check the next receive request on the\r
2099 queue.\r
2100 @retval EFI_ABORTED The user's token (token != NULL) has been\r
2101 cancelled.\r
2102\r
2103**/\r
772db4bb 2104EFI_STATUS\r
e798cd87 2105EFIAPI\r
772db4bb 2106Ip4CancelRxTokens (\r
2107 IN NET_MAP *Map,\r
2108 IN NET_MAP_ITEM *Item,\r
2109 IN VOID *Context\r
2110 )\r
2111{\r
2112 EFI_IP4_COMPLETION_TOKEN *Token;\r
2113 EFI_IP4_COMPLETION_TOKEN *This;\r
2114\r
2115 Token = (EFI_IP4_COMPLETION_TOKEN *) Context;\r
2116 This = Item->Key;\r
2117\r
2118 if ((Token != NULL) && (Token != This)) {\r
2119 return EFI_SUCCESS;\r
2120 }\r
2121\r
2122 NetMapRemoveItem (Map, Item, NULL);\r
2123\r
2124 This->Status = EFI_ABORTED;\r
2125 This->Packet.RxData = NULL;\r
2126 gBS->SignalEvent (This->Event);\r
2127\r
2128 if (Token != NULL) {\r
2129 return EFI_ABORTED;\r
2130 }\r
2131\r
2132 return EFI_SUCCESS;\r
2133}\r
2134\r
2135\r
2136/**\r
2137 Cancel the user's receive/transmit request.\r
2138\r
1f6729ff 2139 @param[in] IpInstance The IP4 child.\r
3e8c18da 2140 @param[in] Token The token to cancel. If NULL, all token will be\r
772db4bb 2141 cancelled.\r
2142\r
1f6729ff 2143 @retval EFI_SUCCESS The token is cancelled.\r
772db4bb 2144 @retval EFI_NOT_FOUND The token isn't found on either the\r
1f6729ff 2145 transmit/receive queue.\r
772db4bb 2146 @retval EFI_DEVICE_ERROR Not all token is cancelled when Token is NULL.\r
2147\r
2148**/\r
2149EFI_STATUS\r
2150Ip4Cancel (\r
2151 IN IP4_PROTOCOL *IpInstance,\r
2152 IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL\r
2153 )\r
2154{\r
2155 EFI_STATUS Status;\r
2156\r
2157 //\r
2158 // First check the transmitted packet. Ip4CancelTxTokens returns\r
2159 // EFI_ABORTED to mean that the token has been cancelled when\r
2160 // token != NULL. So, return EFI_SUCCESS for this condition.\r
2161 //\r
2162 Status = NetMapIterate (&IpInstance->TxTokens, Ip4CancelTxTokens, Token);\r
2163\r
2164 if (EFI_ERROR (Status)) {\r
2165 if ((Token != NULL) && (Status == EFI_ABORTED)) {\r
2166 return EFI_SUCCESS;\r
2167 }\r
2168\r
2169 return Status;\r
2170 }\r
2171\r
2172 //\r
2173 // Check the receive queue. Ip4CancelRxTokens also returns EFI_ABORT\r
2174 // for Token!=NULL and it is cancelled.\r
2175 //\r
2176 Status = NetMapIterate (&IpInstance->RxTokens, Ip4CancelRxTokens, Token);\r
36ee91ca 2177 //\r
2178 // Dispatch the DPCs queued by the NotifyFunction of the canceled rx token's\r
2179 // events.\r
2180 //\r
d8d26fb2 2181 DispatchDpc ();\r
772db4bb 2182 if (EFI_ERROR (Status)) {\r
2183 if ((Token != NULL) && (Status == EFI_ABORTED)) {\r
2184 return EFI_SUCCESS;\r
2185 }\r
2186\r
2187 return Status;\r
2188 }\r
2189\r
2190 //\r
2191 // OK, if the Token is found when Token != NULL, the NetMapIterate\r
2192 // will return EFI_ABORTED, which has been interrupted as EFI_SUCCESS.\r
2193 //\r
2194 if (Token != NULL) {\r
2195 return EFI_NOT_FOUND;\r
2196 }\r
2197\r
2198 //\r
2199 // If Token == NULL, cancel all the tokens. return error if no\r
2200 // all of them are cancelled.\r
2201 //\r
2202 if (!NetMapIsEmpty (&IpInstance->TxTokens) ||\r
2203 !NetMapIsEmpty (&IpInstance->RxTokens)) {\r
2204\r
2205 return EFI_DEVICE_ERROR;\r
2206 }\r
2207\r
2208 return EFI_SUCCESS;\r
2209}\r
2210\r
2211\r
2212/**\r
5405e9a6 2213 Abort an asynchronous transmit or receive request.\r
e2851998 2214\r
5405e9a6 2215 The Cancel() function is used to abort a pending transmit or receive request.\r
2216 If the token is in the transmit or receive request queues, after calling this\r
2217 function, Token->Status will be set to EFI_ABORTED and then Token->Event will\r
2218 be signaled. If the token is not in one of the queues, which usually means the\r
2219 asynchronous operation has completed, this function will not signal the token\r
2220 and EFI_NOT_FOUND is returned.\r
2221\r
3e8c18da 2222 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
2223 @param[in] Token Pointer to a token that has been issued by\r
2224 EFI_IP4_PROTOCOL.Transmit() or\r
2225 EFI_IP4_PROTOCOL.Receive(). If NULL, all pending\r
2226 tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is\r
2227 defined in EFI_IP4_PROTOCOL.Transmit().\r
5405e9a6 2228\r
2229 @retval EFI_SUCCESS The asynchronous I/O request was aborted and\r
2230 Token.->Event was signaled. When Token is NULL, all\r
2231 pending requests were aborted and their events were signaled.\r
2232 @retval EFI_INVALID_PARAMETER This is NULL.\r
2233 @retval EFI_NOT_STARTED This instance has not been started.\r
2234 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
2235 RARP, etc.) is not finished yet.\r
2236 @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was\r
2237 not found in the transmit or receive queue. It has either completed\r
2238 or was not issued by Transmit() and Receive().\r
772db4bb 2239\r
2240**/\r
772db4bb 2241EFI_STATUS\r
2242EFIAPI\r
2243EfiIp4Cancel (\r
2244 IN EFI_IP4_PROTOCOL *This,\r
2245 IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL\r
2246 )\r
2247{\r
2248 IP4_PROTOCOL *IpInstance;\r
2249 EFI_STATUS Status;\r
2250 EFI_TPL OldTpl;\r
2251\r
2252 if (This == NULL) {\r
2253 return EFI_INVALID_PARAMETER;\r
2254 }\r
2255\r
2256 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
2257\r
e48e37fc 2258 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 2259\r
2260 if (IpInstance->State != IP4_STATE_CONFIGED) {\r
2261 Status = EFI_NOT_STARTED;\r
2262 goto ON_EXIT;\r
2263 }\r
2264\r
2265 if (IpInstance->ConfigData.UseDefaultAddress && IP4_NO_MAPPING (IpInstance)) {\r
2266 Status = EFI_NO_MAPPING;\r
2267 goto ON_EXIT;\r
2268 }\r
2269\r
2270 Status = Ip4Cancel (IpInstance, Token);\r
2271\r
2272ON_EXIT:\r
e48e37fc 2273 gBS->RestoreTPL (OldTpl);\r
772db4bb 2274 return Status;\r
2275}\r
2276\r
2277\r
2278/**\r
5405e9a6 2279 Polls for incoming data packets and processes outgoing data packets.\r
e2851998 2280\r
5405e9a6 2281 The Poll() function polls for incoming data packets and processes outgoing data\r
2282 packets. Network drivers and applications can call the EFI_IP4_PROTOCOL.Poll()\r
2283 function to increase the rate that data packets are moved between the communications\r
2284 device and the transmit and receive queues.\r
e2851998 2285\r
5405e9a6 2286 In some systems the periodic timer event may not poll the underlying communications\r
2287 device fast enough to transmit and/or receive all data packets without missing\r
2288 incoming packets or dropping outgoing packets. Drivers and applications that are\r
2289 experiencing packet loss should try calling the EFI_IP4_PROTOCOL.Poll() function\r
2290 more often.\r
2291\r
3e8c18da 2292 @param[in] This Pointer to the EFI_IP4_PROTOCOL instance.\r
5405e9a6 2293\r
2294 @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
2295 @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started.\r
2296 @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP,\r
2297 RARP, etc.) is not finished yet.\r
2298 @retval EFI_INVALID_PARAMETER This is NULL.\r
2299 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
2300 @retval EFI_NOT_READY No incoming or outgoing data is processed.\r
2301 @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue.\r
2302 Consider increasing the polling rate.\r
772db4bb 2303\r
2304**/\r
772db4bb 2305EFI_STATUS\r
2306EFIAPI\r
2307EfiIp4Poll (\r
2308 IN EFI_IP4_PROTOCOL *This\r
2309 )\r
2310{\r
2311 IP4_PROTOCOL *IpInstance;\r
2312 EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r
2313\r
2314 if (This == NULL) {\r
2315 return EFI_INVALID_PARAMETER;\r
2316 }\r
2317\r
2318 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);\r
2319\r
2320 if (IpInstance->State == IP4_STATE_UNCONFIGED) {\r
2321 return EFI_NOT_STARTED;\r
2322 }\r
2323\r
2324 Mnp = IpInstance->Service->Mnp;\r
2325\r
2326 //\r
2327 // Don't lock the Poll function to enable the deliver of\r
2328 // the packet polled up.\r
2329 //\r
2330 return Mnp->Poll (Mnp);\r
2331}\r
2332\r
772db4bb 2333/**\r
2334 Decrease the life of the transmitted packets. If it is\r
2335 decreased to zero, cancel the packet. This function is\r
96e1079f 2336 called by Ip4PacketTimerTicking which time out both the\r
772db4bb 2337 received-but-not-delivered and transmitted-but-not-recycle\r
2338 packets.\r
2339\r
3e8c18da 2340 @param[in] Map The IP4 child's transmit map.\r
1f6729ff 2341 @param[in] Item Current transmitted packet.\r
3e8c18da 2342 @param[in] Context Not used.\r
772db4bb 2343\r
1f6729ff 2344 @retval EFI_SUCCESS Always returns EFI_SUCCESS.\r
772db4bb 2345\r
2346**/\r
2347EFI_STATUS\r
e798cd87 2348EFIAPI\r
772db4bb 2349Ip4SentPacketTicking (\r
2350 IN NET_MAP *Map,\r
2351 IN NET_MAP_ITEM *Item,\r
2352 IN VOID *Context\r
2353 )\r
2354{\r
2355 IP4_TXTOKEN_WRAP *Wrap;\r
2356\r
2357 Wrap = (IP4_TXTOKEN_WRAP *) Item->Value;\r
2358 ASSERT (Wrap != NULL);\r
2359\r
2360 if ((Wrap->Life > 0) && (--Wrap->Life == 0)) {\r
2361 Ip4CancelPacket (Wrap->IpInstance->Interface, Wrap->Packet, EFI_ABORTED);\r
2362 }\r
2363\r
2364 return EFI_SUCCESS;\r
2365}\r
2366\r
2367\r
2368/**\r
2c320007
JW
2369 There are two steps for this the heart beat timer of IP4 service instance. \r
2370 First, it times out all of its IP4 children's received-but-not-delivered \r
2371 and transmitted-but-not-recycle packets, and provides time input for its \r
2372 IGMP protocol.\r
2373 Second, a dedicated timer is used to poll underlying media status. In case \r
2374 of cable swap, a new round auto configuration will be initiated. The timer \r
2375 will signal the IP4 to run DHCP configuration again. IP4 driver will free\r
2376 old IP address related resource, such as route table and Interface, then\r
2377 initiate a DHCP process to acquire new IP, eventually create route table \r
2378 for new IP address.\r
772db4bb 2379\r
3e8c18da 2380 @param[in] Event The IP4 service instance's heart beat timer.\r
2381 @param[in] Context The IP4 service instance.\r
772db4bb 2382\r
2383**/\r
2384VOID\r
2385EFIAPI\r
2386Ip4TimerTicking (\r
2387 IN EFI_EVENT Event,\r
2388 IN VOID *Context\r
2389 )\r
2390{\r
2391 IP4_SERVICE *IpSb;\r
2c320007
JW
2392 BOOLEAN OldMediaPresent;\r
2393 EFI_STATUS Status;\r
2394 EFI_SIMPLE_NETWORK_MODE SnpModeData;\r
772db4bb 2395\r
2396 IpSb = (IP4_SERVICE *) Context;\r
2397 NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
2c320007
JW
2398 \r
2399 OldMediaPresent = IpSb->MediaPresent;\r
772db4bb 2400\r
2401 Ip4PacketTimerTicking (IpSb);\r
2402 Ip4IgmpTicking (IpSb);\r
2c320007
JW
2403\r
2404 //\r
2405 // Get fresh mode data from MNP, since underlying media status may change. \r
2406 // Here, it needs to mention that the MediaPresent can also be checked even if \r
2407 // EFI_NOT_STARTED returned while this MNP child driver instance isn't configured.\r
2408 //\r
2409 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &SnpModeData);\r
2410 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
2411 return;\r
2412 }\r
2413\r
2414 IpSb->MediaPresent = SnpModeData.MediaPresent;\r
2415 //\r
2416 // Media transimit Unpresent to Present means new link movement is detected.\r
2417 //\r
2418 if (!OldMediaPresent && IpSb->MediaPresent) {\r
2419 //\r
2420 // Signal the IP4 to run the dhcp configuration again. IP4 driver will free\r
2421 // old IP address related resource, such as route table and Interface, then \r
2422 // initiate a DHCP round to acquire new IP, eventually \r
2423 // create route table for new IP address.\r
2424 //\r
2425 if (IpSb->ReconfigEvent != NULL) {\r
2426 Status = gBS->SignalEvent (IpSb->ReconfigEvent);\r
2427 DispatchDpc ();\r
2428 }\r
2429 }\r
772db4bb 2430}\r