NetworkPkg: Remove IpSecDxe and Ip4Config Protocol dependency.
[mirror_edk2.git] / StdLib / EfiSocketLib / Ip4.c
CommitLineData
a88c3163 1/** @file\r
2 Implement the IP4 driver support for the socket layer.\r
3\r
0e565888
OM
4 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials are licensed and made available\r
6 under the terms and conditions of the BSD License which accompanies this\r
7 distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
a88c3163 9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
a88c3163 12**/\r
a88c3163 13#include "Socket.h"\r
14\r
15\r
beaaa3b7 16/** Get the local socket address.\r
a88c3163 17\r
18 This routine returns the IPv4 address associated with the local\r
19 socket.\r
20\r
21 This routine is called by ::EslSocketGetLocalAddress to determine the\r
22 network address for the SOCK_RAW socket.\r
23\r
24 @param [in] pPort Address of an ::ESL_PORT structure.\r
a88c3163 25 @param [out] pAddress Network address to receive the local system address\r
a88c3163 26**/\r
27VOID\r
28EslIp4LocalAddressGet (\r
29 IN ESL_PORT * pPort,\r
30 OUT struct sockaddr * pAddress\r
31 )\r
32{\r
33 struct sockaddr_in * pLocalAddress;\r
34 ESL_IP4_CONTEXT * pIp4;\r
35\r
36 DBG_ENTER ( );\r
37\r
a88c3163 38 // Return the local address\r
a88c3163 39 pIp4 = &pPort->Context.Ip4;\r
40 pLocalAddress = (struct sockaddr_in *)pAddress;\r
41 pLocalAddress->sin_family = AF_INET;\r
42 CopyMem ( &pLocalAddress->sin_addr,\r
43 &pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
44 sizeof ( pLocalAddress->sin_addr ));\r
45\r
46 DBG_EXIT ( );\r
47}\r
48\r
49\r
beaaa3b7 50/** Set the local port address.\r
a88c3163 51\r
52 This routine sets the local port address.\r
53\r
54 This support routine is called by ::EslSocketPortAllocate.\r
55\r
56 @param [in] pPort Address of an ESL_PORT structure\r
57 @param [in] pSockAddr Address of a sockaddr structure that contains the\r
58 connection point on the local machine. An IPv4 address\r
59 of INADDR_ANY specifies that the connection is made to\r
60 all of the network stacks on the platform. Specifying a\r
61 specific IPv4 address restricts the connection to the\r
62 network stack supporting that address. Specifying zero\r
63 for the port causes the network layer to assign a port\r
64 number from the dynamic range. Specifying a specific\r
65 port number causes the network layer to use that port.\r
66\r
67 @param [in] bBindTest TRUE = run bind testing\r
68\r
69 @retval EFI_SUCCESS The operation was successful\r
a88c3163 70 **/\r
71EFI_STATUS\r
72EslIp4LocalAddressSet (\r
73 IN ESL_PORT * pPort,\r
74 IN CONST struct sockaddr * pSockAddr,\r
75 IN BOOLEAN bBindTest\r
76 )\r
77{\r
78 EFI_IP4_CONFIG_DATA * pConfig;\r
79 CONST struct sockaddr_in * pIpAddress;\r
80 CONST UINT8 * pIpv4Address;\r
81 EFI_STATUS Status;\r
82\r
83 DBG_ENTER ( );\r
84\r
a88c3163 85 // Validate the address\r
a88c3163 86 pIpAddress = (struct sockaddr_in *)pSockAddr;\r
87 if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
a88c3163 88 // The local address must not be the broadcast address\r
a88c3163 89 Status = EFI_INVALID_PARAMETER;\r
90 pPort->pSocket->errno = EADDRNOTAVAIL;\r
91 }\r
92 else {\r
93 Status = EFI_SUCCESS;\r
94\r
a88c3163 95 // Set the local address\r
a88c3163 96 pIpAddress = (struct sockaddr_in *)pSockAddr;\r
97 pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;\r
98 pConfig = &pPort->Context.Ip4.ModeData.ConfigData;\r
99 pConfig->StationAddress.Addr[0] = pIpv4Address[0];\r
100 pConfig->StationAddress.Addr[1] = pIpv4Address[1];\r
101 pConfig->StationAddress.Addr[2] = pIpv4Address[2];\r
102 pConfig->StationAddress.Addr[3] = pIpv4Address[3];\r
103\r
a88c3163 104 // Determine if the default address is used\r
a88c3163 105 pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
106\r
a88c3163 107 // Display the local address\r
a88c3163 108 DEBUG (( DEBUG_BIND,\r
109 "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",\r
110 pPort,\r
111 pConfig->StationAddress.Addr[0],\r
112 pConfig->StationAddress.Addr[1],\r
113 pConfig->StationAddress.Addr[2],\r
114 pConfig->StationAddress.Addr[3]));\r
115\r
a88c3163 116 // Set the subnet mask\r
a88c3163 117 if ( pConfig->UseDefaultAddress ) {\r
118 pConfig->SubnetMask.Addr[0] = 0;\r
119 pConfig->SubnetMask.Addr[1] = 0;\r
120 pConfig->SubnetMask.Addr[2] = 0;\r
121 pConfig->SubnetMask.Addr[3] = 0;\r
122 }\r
123 else {\r
124 pConfig->SubnetMask.Addr[0] = 0xff;\r
6e1450f3 125 pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
126 pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
127 pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
a88c3163 128 }\r
129 }\r
a88c3163 130 // Return the operation status\r
a88c3163 131 DBG_EXIT_STATUS ( Status );\r
132 return Status;\r
133}\r
134\r
135\r
beaaa3b7 136/** Get the option value.\r
a88c3163 137\r
138 This routine handles the IPv4 level options.\r
139\r
140 The ::EslSocketOptionGet routine calls this routine to retrieve\r
141 the IPv4 options one at a time by name.\r
142\r
143 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
144 @param [in] OptionName Name of the option\r
145 @param [out] ppOptionData Buffer to receive address of option value\r
146 @param [out] pOptionLength Buffer to receive the option length\r
147\r
148 @retval EFI_SUCCESS - Socket data successfully received\r
a88c3163 149 **/\r
150EFI_STATUS\r
151EslIp4OptionGet (\r
152 IN ESL_SOCKET * pSocket,\r
153 IN int OptionName,\r
154 OUT CONST void ** __restrict ppOptionData,\r
155 OUT socklen_t * __restrict pOptionLength\r
156 )\r
157{\r
158 EFI_STATUS Status;\r
159\r
160 DBG_ENTER ( );\r
161\r
a88c3163 162 // Assume success\r
a88c3163 163 pSocket->errno = 0;\r
164 Status = EFI_SUCCESS;\r
165\r
a88c3163 166 // Attempt to get the option\r
a88c3163 167 switch ( OptionName ) {\r
168 default:\r
a88c3163 169 // Option not supported\r
a88c3163 170 pSocket->errno = ENOPROTOOPT;\r
171 Status = EFI_INVALID_PARAMETER;\r
172 break;\r
173\r
174 case IP_HDRINCL:\r
58081f2c 175 *ppOptionData = (void *)&pSocket->bIncludeHeader;\r
a88c3163 176 *pOptionLength = sizeof ( pSocket->bIncludeHeader );\r
177 break;\r
178 }\r
a88c3163 179 // Return the operation status\r
a88c3163 180 DBG_EXIT_STATUS ( Status );\r
181 return Status;\r
182}\r
183\r
184\r
beaaa3b7 185/** Set the option value.\r
a88c3163 186\r
187 This routine handles the IPv4 level options.\r
188\r
189 The ::EslSocketOptionSet routine calls this routine to adjust\r
190 the IPv4 options one at a time by name.\r
191\r
192 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
193 @param [in] OptionName Name of the option\r
194 @param [in] pOptionValue Buffer containing the option value\r
195 @param [in] OptionLength Length of the buffer in bytes\r
196\r
197 @retval EFI_SUCCESS - Option successfully set\r
a88c3163 198 **/\r
199EFI_STATUS\r
200EslIp4OptionSet (\r
201 IN ESL_SOCKET * pSocket,\r
202 IN int OptionName,\r
203 IN CONST void * pOptionValue,\r
204 IN socklen_t OptionLength\r
205 )\r
206{\r
207 BOOLEAN bTrueFalse;\r
beaaa3b7
OM
208 //socklen_t LengthInBytes;\r
209 //UINT8 * pOptionData;\r
a88c3163 210 EFI_STATUS Status;\r
211\r
212 DBG_ENTER ( );\r
213\r
a88c3163 214 // Assume success\r
a88c3163 215 pSocket->errno = 0;\r
216 Status = EFI_SUCCESS;\r
217\r
a88c3163 218 // Determine if the option protocol matches\r
beaaa3b7
OM
219 //LengthInBytes = 0;\r
220 //pOptionData = NULL;\r
a88c3163 221 switch ( OptionName ) {\r
222 default:\r
a88c3163 223 // Protocol level not supported\r
a88c3163 224 DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));\r
225 pSocket->errno = ENOTSUP;\r
226 Status = EFI_UNSUPPORTED;\r
227 break;\r
228\r
229 case IP_HDRINCL:\r
230\r
a88c3163 231 // Validate the option length\r
a88c3163 232 if ( sizeof ( UINT32 ) == OptionLength ) {\r
a88c3163 233 // Restrict the input to TRUE or FALSE\r
a88c3163 234 bTrueFalse = TRUE;\r
235 if ( 0 == *(UINT32 *)pOptionValue ) {\r
236 bTrueFalse = FALSE;\r
237 }\r
238 pOptionValue = &bTrueFalse;\r
239\r
a88c3163 240 // Set the option value\r
beaaa3b7
OM
241 //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;\r
242 //LengthInBytes = sizeof ( pSocket->bIncludeHeader );\r
a88c3163 243 }\r
244 break;\r
245 }\r
a88c3163 246 // Return the operation status\r
a88c3163 247 DBG_EXIT_STATUS ( Status );\r
248 return Status;\r
249}\r
250\r
251\r
252/**\r
253 Free a receive packet\r
254\r
255 This routine performs the network specific operations necessary\r
256 to free a receive packet.\r
257\r
258 This routine is called by ::EslSocketPortCloseTxDone to free a\r
259 receive packet.\r
260\r
261 @param [in] pPacket Address of an ::ESL_PACKET structure.\r
262 @param [in, out] pRxBytes Address of the count of RX bytes\r
263\r
264**/\r
265VOID\r
266EslIp4PacketFree (\r
267 IN ESL_PACKET * pPacket,\r
268 IN OUT size_t * pRxBytes\r
269 )\r
270{\r
271 EFI_IP4_RECEIVE_DATA * pRxData;\r
272 DBG_ENTER ( );\r
273\r
274 //\r
275 // Account for the receive bytes\r
276 //\r
277 pRxData = pPacket->Op.Ip4Rx.pRxData;\r
278 *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;\r
279\r
280 //\r
281 // Disconnect the buffer from the packet\r
282 //\r
283 pPacket->Op.Ip4Rx.pRxData = NULL;\r
284\r
285 //\r
286 // Return the buffer to the IP4 driver\r
287 //\r
288 gBS->SignalEvent ( pRxData->RecycleSignal );\r
289 DBG_EXIT ( );\r
290}\r
291\r
292\r
293/**\r
294 Initialize the network specific portions of an ::ESL_PORT structure.\r
295\r
296 This routine initializes the network specific portions of an\r
297 ::ESL_PORT structure for use by the socket.\r
298\r
299 This support routine is called by ::EslSocketPortAllocate\r
300 to connect the socket with the underlying network adapter\r
301 running the IPv4 protocol.\r
302\r
303 @param [in] pPort Address of an ESL_PORT structure\r
304 @param [in] DebugFlags Flags for debug messages\r
305\r
306 @retval EFI_SUCCESS - Socket successfully created\r
307\r
308 **/\r
309EFI_STATUS\r
310EslIp4PortAllocate (\r
311 IN ESL_PORT * pPort,\r
312 IN UINTN DebugFlags\r
313 )\r
314{\r
315 EFI_IP4_CONFIG_DATA * pConfig;\r
316 ESL_SOCKET * pSocket;\r
317 EFI_STATUS Status;\r
318\r
319 DBG_ENTER ( );\r
320\r
321 //\r
322 // Initialize the port\r
323 //\r
324 pSocket = pPort->pSocket;\r
325 pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );\r
326 pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );\r
327 pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );\r
328\r
329 //\r
330 // Save the cancel, receive and transmit addresses\r
331 //\r
332 pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure;\r
333 pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;\r
3bdf9aae 334 pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll;\r
a88c3163 335 pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;\r
336 pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;\r
337\r
338 //\r
339 // Set the configuration flags\r
340 //\r
341 pConfig = &pPort->Context.Ip4.ModeData.ConfigData;\r
342 pConfig->AcceptIcmpErrors = FALSE;\r
343 pConfig->AcceptBroadcast = FALSE;\r
344 pConfig->AcceptPromiscuous = FALSE;\r
345 pConfig->TypeOfService = 0;\r
346 pConfig->TimeToLive = 255;\r
347 pConfig->DoNotFragment = FALSE;\r
348 pConfig->RawData = FALSE;\r
349 pConfig->ReceiveTimeout = 0;\r
350 pConfig->TransmitTimeout = 0;\r
351\r
352 //\r
353 // Set the default protocol\r
354 //\r
355 pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;\r
356 pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );\r
357 Status = EFI_SUCCESS;\r
358\r
359 //\r
360 // Return the operation status\r
361 //\r
362 DBG_EXIT_STATUS ( Status );\r
363 return Status;\r
364}\r
365\r
366\r
367/**\r
368 Receive data from a network connection.\r
369\r
370 This routine attempts to return buffered data to the caller. The\r
371 data is removed from the urgent queue if the message flag MSG_OOB\r
372 is specified, otherwise data is removed from the normal queue.\r
373 See the \ref ReceiveEngine section.\r
374\r
375 This routine is called by ::EslSocketReceive to handle the network\r
376 specific receive operation to support SOCK_RAW sockets.\r
377\r
378 @param [in] pPort Address of an ::ESL_PORT structure.\r
379\r
380 @param [in] pPacket Address of an ::ESL_PACKET structure.\r
0e565888 381\r
a88c3163 382 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\r
0e565888 383\r
a88c3163 384 @param [in] BufferLength Length of the the buffer\r
0e565888 385\r
a88c3163 386 @param [in] pBuffer Address of a buffer to receive the data.\r
0e565888 387\r
a88c3163 388 @param [in] pDataLength Number of received data bytes in the buffer.\r
389\r
390 @param [out] pAddress Network address to receive the remote system address\r
391\r
392 @param [out] pSkipBytes Address to receive the number of bytes skipped\r
393\r
394 @return Returns the address of the next free byte in the buffer.\r
395\r
396 **/\r
397UINT8 *\r
398EslIp4Receive (\r
399 IN ESL_PORT * pPort,\r
400 IN ESL_PACKET * pPacket,\r
401 IN BOOLEAN * pbConsumePacket,\r
402 IN size_t BufferLength,\r
403 IN UINT8 * pBuffer,\r
404 OUT size_t * pDataLength,\r
405 OUT struct sockaddr * pAddress,\r
406 OUT size_t * pSkipBytes\r
407 )\r
408{\r
409 size_t DataBytes;\r
410 size_t HeaderBytes;\r
411 size_t LengthInBytes;\r
412 struct sockaddr_in * pRemoteAddress;\r
413 EFI_IP4_RECEIVE_DATA * pRxData;\r
414\r
415 DBG_ENTER ( );\r
416\r
417 //\r
418 // Return the remote system address if requested\r
419 //\r
420 pRxData = pPacket->Op.Ip4Rx.pRxData;\r
421 if ( NULL != pAddress ) {\r
422 //\r
423 // Build the remote address\r
424 //\r
425 DEBUG (( DEBUG_RX,\r
426 "Getting packet remote address: %d.%d.%d.%d\r\n",\r
427 pRxData->Header->SourceAddress.Addr[0],\r
428 pRxData->Header->SourceAddress.Addr[1],\r
429 pRxData->Header->SourceAddress.Addr[2],\r
430 pRxData->Header->SourceAddress.Addr[3]));\r
431 pRemoteAddress = (struct sockaddr_in *)pAddress;\r
432 CopyMem ( &pRemoteAddress->sin_addr,\r
433 &pRxData->Header->SourceAddress.Addr[0],\r
434 sizeof ( pRemoteAddress->sin_addr ));\r
435 }\r
436\r
437 //\r
438 // Copy the IP header\r
439 //\r
440 HeaderBytes = pRxData->HeaderLength;\r
441 if ( HeaderBytes > BufferLength ) {\r
442 HeaderBytes = BufferLength;\r
443 }\r
444 DEBUG (( DEBUG_RX,\r
445 "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",\r
446 pRxData->Header,\r
447 pBuffer,\r
448 HeaderBytes ));\r
449 CopyMem ( pBuffer, pRxData->Header, HeaderBytes );\r
450 pBuffer += HeaderBytes;\r
451 LengthInBytes = HeaderBytes;\r
452\r
453 //\r
454 // Copy the received data\r
455 //\r
456 if ( 0 < ( BufferLength - LengthInBytes )) {\r
457 pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,\r
458 &pRxData->FragmentTable[0],\r
459 BufferLength - LengthInBytes,\r
460 pBuffer,\r
461 &DataBytes );\r
462 LengthInBytes += DataBytes;\r
463 }\r
464\r
465 //\r
466 // Determine if the data is being read\r
467 //\r
468 if ( *pbConsumePacket ) {\r
469 //\r
470 // Display for the bytes consumed\r
471 //\r
472 DEBUG (( DEBUG_RX,\r
473 "0x%08x: Port account for 0x%08x bytes\r\n",\r
474 pPort,\r
475 LengthInBytes ));\r
476\r
477 //\r
478 // Account for any discarded data\r
479 //\r
480 *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;\r
481 }\r
482\r
483 //\r
484 // Return the data length and the buffer address\r
485 //\r
486 *pDataLength = LengthInBytes;\r
487 DBG_EXIT_HEX ( pBuffer );\r
488 return pBuffer;\r
489}\r
490\r
491\r
492/**\r
493 Get the remote socket address\r
494\r
495 This routine returns the address of the remote connection point\r
496 associated with the SOCK_RAW socket.\r
497\r
498 This routine is called by ::EslSocketGetPeerAddress to detemine\r
499 the IPv4 address associated with the network adapter.\r
500\r
501 @param [in] pPort Address of an ::ESL_PORT structure.\r
502\r
503 @param [out] pAddress Network address to receive the remote system address\r
504\r
505**/\r
506VOID\r
507EslIp4RemoteAddressGet (\r
508 IN ESL_PORT * pPort,\r
509 OUT struct sockaddr * pAddress\r
510 )\r
511{\r
512 struct sockaddr_in * pRemoteAddress;\r
513 ESL_IP4_CONTEXT * pIp4;\r
514\r
515 DBG_ENTER ( );\r
516\r
517 //\r
518 // Return the remote address\r
519 //\r
520 pIp4 = &pPort->Context.Ip4;\r
521 pRemoteAddress = (struct sockaddr_in *)pAddress;\r
522 pRemoteAddress->sin_family = AF_INET;\r
523 CopyMem ( &pRemoteAddress->sin_addr,\r
524 &pIp4->DestinationAddress.Addr[0],\r
525 sizeof ( pRemoteAddress->sin_addr ));\r
526\r
527 DBG_EXIT ( );\r
528}\r
529\r
530\r
531/**\r
532 Set the remote address\r
533\r
534 This routine sets the remote address in the port.\r
535\r
536 This routine is called by ::EslSocketConnect to specify the\r
537 remote network address.\r
538\r
539 @param [in] pPort Address of an ::ESL_PORT structure.\r
540\r
541 @param [in] pSockAddr Network address of the remote system.\r
542\r
543 @param [in] SockAddrLength Length in bytes of the network address.\r
544\r
545 @retval EFI_SUCCESS The operation was successful\r
546\r
547 **/\r
548EFI_STATUS\r
549EslIp4RemoteAddressSet (\r
550 IN ESL_PORT * pPort,\r
551 IN CONST struct sockaddr * pSockAddr,\r
552 IN socklen_t SockAddrLength\r
553 )\r
554{\r
555 ESL_IP4_CONTEXT * pIp4;\r
556 CONST struct sockaddr_in * pRemoteAddress;\r
557 EFI_STATUS Status;\r
558\r
559 DBG_ENTER ( );\r
560\r
561 //\r
562 // Set the remote address\r
563 //\r
564 pIp4 = &pPort->Context.Ip4;\r
565 pRemoteAddress = (struct sockaddr_in *)pSockAddr;\r
566 pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );\r
567 pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
568 pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
569 pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
f74dc4bb 570 pPort->pSocket->bAddressSet = TRUE;\r
a88c3163 571 Status = EFI_SUCCESS;\r
572\r
573 //\r
574 // Return the operation status\r
575 //\r
576 DBG_EXIT_STATUS ( Status );\r
577 return Status;\r
578}\r
579\r
580\r
581/**\r
582 Process the receive completion\r
583\r
584 This routine keeps the IPv4 driver's buffer and queues it in\r
585 in FIFO order to the data queue. The IP4 driver's buffer will\r
586 be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.\r
587 See the \ref ReceiveEngine section.\r
588\r
589 This routine is called by the IPv4 driver when data is\r
590 received.\r
591\r
592 @param [in] Event The receive completion event\r
593\r
594 @param [in] pIo The address of an ::ESL_IO_MGMT structure\r
595\r
596**/\r
597VOID\r
598EslIp4RxComplete (\r
599 IN EFI_EVENT Event,\r
600 IN ESL_IO_MGMT * pIo\r
601 )\r
602{\r
603 size_t LengthInBytes;\r
a88c3163 604 ESL_PACKET * pPacket;\r
605 EFI_IP4_RECEIVE_DATA * pRxData;\r
606 EFI_STATUS Status;\r
0e565888 607\r
a88c3163 608 DBG_ENTER ( );\r
0e565888 609\r
a88c3163 610 //\r
611 // Get the operation status.\r
612 //\r
a88c3163 613 Status = pIo->Token.Ip4Rx.Status;\r
614\r
615 //\r
616 // Get the packet length\r
617 //\r
618 pRxData = pIo->Token.Ip4Rx.Packet.RxData;\r
619 LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;\r
620\r
0e565888 621 //{{\r
a88c3163 622 // +--------------------+ +----------------------+\r
623 // | ESL_IO_MGMT | | Data Buffer |\r
624 // | | | (Driver owned) |\r
625 // | +---------------+ +----------------------+\r
626 // | | Token | ^\r
627 // | | Rx Event | |\r
628 // | | | +----------------------+\r
629 // | | RxData --> | EFI_IP4_RECEIVE_DATA |\r
630 // +----+---------------+ | (Driver owned) |\r
631 // +----------------------+\r
632 // +--------------------+ ^\r
633 // | ESL_PACKET | .\r
634 // | | .\r
635 // | +---------------+ .\r
636 // | | pRxData --> NULL .......\r
637 // +----+---------------+\r
638 //\r
639 //\r
640 // Save the data in the packet\r
0e565888 641 //}}\r
a88c3163 642 pPacket = pIo->pPacket;\r
643 pPacket->Op.Ip4Rx.pRxData = pRxData;\r
644\r
645 //\r
646 // Complete this request\r
647 //\r
648 EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );\r
649 DBG_EXIT ( );\r
650}\r
651\r
652\r
653/**\r
654 Determine if the socket is configured.\r
655\r
656 This routine uses the flag ESL_SOCKET::bConfigured to determine\r
657 if the network layer's configuration routine has been called.\r
658 This routine calls the ::EslSocketBind and configuration routines\r
659 if they were not already called. After the port is configured,\r
660 the \ref ReceiveEngine is started.\r
661\r
662 This routine is called by EslSocketIsConfigured to verify\r
663 that the socket is configured.\r
664\r
665 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
0e565888 666\r
a88c3163 667 @retval EFI_SUCCESS - The port is connected\r
668 @retval EFI_NOT_STARTED - The port is not connected\r
669\r
670 **/\r
671 EFI_STATUS\r
672 EslIp4SocketIsConfigured (\r
673 IN ESL_SOCKET * pSocket\r
674 )\r
675{\r
676 UINTN Index;\r
677 ESL_PORT * pPort;\r
678 ESL_PORT * pNextPort;\r
679 ESL_IP4_CONTEXT * pIp4;\r
680 EFI_IP4_PROTOCOL * pIp4Protocol;\r
681 EFI_STATUS Status;\r
682 struct sockaddr_in LocalAddress;\r
683\r
684 DBG_ENTER ( );\r
685\r
686 //\r
687 // Assume success\r
688 //\r
689 Status = EFI_SUCCESS;\r
690\r
691 //\r
692 // Configure the port if necessary\r
693 //\r
694 if ( !pSocket->bConfigured ) {\r
695 //\r
696 // Fill in the port list if necessary\r
697 //\r
bb3aa953 698 pSocket->errno = ENETDOWN;\r
a88c3163 699 if ( NULL == pSocket->pPortList ) {\r
700 LocalAddress.sin_len = sizeof ( LocalAddress );\r
701 LocalAddress.sin_family = AF_INET;\r
702 LocalAddress.sin_addr.s_addr = 0;\r
703 LocalAddress.sin_port = 0;\r
704 Status = EslSocketBind ( &pSocket->SocketProtocol,\r
705 (struct sockaddr *)&LocalAddress,\r
706 LocalAddress.sin_len,\r
707 &pSocket->errno );\r
708 }\r
709\r
710 //\r
711 // Walk the port list\r
712 //\r
713 pPort = pSocket->pPortList;\r
714 while ( NULL != pPort ) {\r
715 //\r
716 // Update the raw setting\r
717 //\r
718 pIp4 = &pPort->Context.Ip4;\r
719 if ( pSocket->bIncludeHeader ) {\r
720 //\r
721 // IP header will be included with the data on transmit\r
722 //\r
723 pIp4->ModeData.ConfigData.RawData = TRUE;\r
724 }\r
725\r
726 //\r
727 // Attempt to configure the port\r
728 //\r
729 pNextPort = pPort->pLinkSocket;\r
730 pIp4Protocol = pPort->pProtocol.IPv4;\r
731 DEBUG (( DEBUG_TX,\r
732 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
733 pPort,\r
734 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
735 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
736 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
737 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
738 pIp4->DestinationAddress.Addr[0],\r
739 pIp4->DestinationAddress.Addr[1],\r
740 pIp4->DestinationAddress.Addr[2],\r
741 pIp4->DestinationAddress.Addr[3]));\r
742 Status = pIp4Protocol->Configure ( pIp4Protocol,\r
743 &pIp4->ModeData.ConfigData );\r
744 if ( !EFI_ERROR ( Status )) {\r
745 //\r
746 // Update the configuration data\r
747 //\r
748 Status = pIp4Protocol->GetModeData ( pIp4Protocol,\r
749 &pIp4->ModeData,\r
750 NULL,\r
751 NULL );\r
752 }\r
753 if ( EFI_ERROR ( Status )) {\r
bb3aa953 754 if ( !pSocket->bConfigured ) {\r
755 DEBUG (( DEBUG_LISTEN,\r
756 "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",\r
757 Status ));\r
758 switch ( Status ) {\r
759 case EFI_ACCESS_DENIED:\r
760 pSocket->errno = EACCES;\r
761 break;\r
762\r
763 default:\r
764 case EFI_DEVICE_ERROR:\r
765 pSocket->errno = EIO;\r
766 break;\r
767\r
768 case EFI_INVALID_PARAMETER:\r
769 pSocket->errno = EADDRNOTAVAIL;\r
770 break;\r
771\r
772 case EFI_NO_MAPPING:\r
773 pSocket->errno = EAFNOSUPPORT;\r
774 break;\r
775\r
776 case EFI_OUT_OF_RESOURCES:\r
777 pSocket->errno = ENOBUFS;\r
778 break;\r
779\r
780 case EFI_UNSUPPORTED:\r
781 pSocket->errno = EOPNOTSUPP;\r
782 break;\r
783 }\r
a88c3163 784 }\r
785 }\r
786 else {\r
787 DEBUG (( DEBUG_TX,\r
788 "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
789 pPort,\r
790 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
791 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
792 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
793 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
794 pIp4->DestinationAddress.Addr[0],\r
795 pIp4->DestinationAddress.Addr[1],\r
796 pIp4->DestinationAddress.Addr[2],\r
797 pIp4->DestinationAddress.Addr[3]));\r
798 DEBUG (( DEBUG_TX,\r
799 "Subnet Mask: %d.%d.%d.%d\r\n",\r
800 pIp4->ModeData.ConfigData.SubnetMask.Addr[0],\r
801 pIp4->ModeData.ConfigData.SubnetMask.Addr[1],\r
802 pIp4->ModeData.ConfigData.SubnetMask.Addr[2],\r
803 pIp4->ModeData.ConfigData.SubnetMask.Addr[3]));\r
804 DEBUG (( DEBUG_TX,\r
805 "Route Count: %d\r\n",\r
806 pIp4->ModeData.RouteCount ));\r
807 for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) {\r
808 if ( 0 == Index ) {\r
809 DEBUG (( DEBUG_TX, "Route Table:\r\n" ));\r
810 }\r
811 DEBUG (( DEBUG_TX,\r
812 "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",\r
813 Index,\r
814 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0],\r
815 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1],\r
816 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2],\r
817 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3],\r
818 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0],\r
819 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1],\r
820 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2],\r
821 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3],\r
822 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0],\r
823 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1],\r
824 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2],\r
825 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3]));\r
826 }\r
827 pPort->bConfigured = TRUE;\r
bb3aa953 828 pSocket->bConfigured = TRUE;\r
a88c3163 829\r
830 //\r
831 // Start the first read on the port\r
832 //\r
833 EslSocketRxStart ( pPort );\r
834\r
835 //\r
836 // The socket is connected\r
837 //\r
838 pSocket->State = SOCKET_STATE_CONNECTED;\r
bb3aa953 839 pSocket->errno = 0;\r
a88c3163 840 }\r
841\r
842 //\r
843 // Set the next port\r
844 //\r
845 pPort = pNextPort;\r
846 }\r
a88c3163 847 }\r
848\r
849 //\r
850 // Determine the socket configuration status\r
851 //\r
bb3aa953 852 Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
0e565888 853\r
a88c3163 854 //\r
855 // Return the port connected state.\r
856 //\r
857 DBG_EXIT_STATUS ( Status );\r
858 return Status;\r
859}\r
860\r
861\r
862/**\r
863 Buffer data for transmission over a network connection.\r
864\r
865 This routine buffers data for the transmit engine in the normal\r
866 data queue. When the \ref TransmitEngine has resources, this\r
867 routine will start the transmission of the next buffer on the\r
868 network connection.\r
869\r
870 This routine is called by ::EslSocketTransmit to buffer\r
871 data for transmission. The data is copied into a local buffer\r
872 freeing the application buffer for reuse upon return. When\r
873 necessary, this routine starts the transmit engine that\r
874 performs the data transmission on the network connection. The\r
875 transmit engine transmits the data a packet at a time over the\r
876 network connection.\r
877\r
878 Transmission errors are returned during the next transmission or\r
879 during the close operation. Only buffering errors are returned\r
880 during the current transmission attempt.\r
881\r
882 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
883\r
884 @param [in] Flags Message control flags\r
885\r
886 @param [in] BufferLength Length of the the buffer\r
887\r
888 @param [in] pBuffer Address of a buffer to receive the data.\r
889\r
890 @param [in] pDataLength Number of received data bytes in the buffer.\r
891\r
892 @param [in] pAddress Network address of the remote system address\r
893\r
894 @param [in] AddressLength Length of the remote network address structure\r
895\r
896 @retval EFI_SUCCESS - Socket data successfully buffered\r
897\r
898**/\r
899EFI_STATUS\r
900EslIp4TxBuffer (\r
901 IN ESL_SOCKET * pSocket,\r
902 IN int Flags,\r
903 IN size_t BufferLength,\r
904 IN CONST UINT8 * pBuffer,\r
905 OUT size_t * pDataLength,\r
906 IN const struct sockaddr * pAddress,\r
907 IN socklen_t AddressLength\r
908 )\r
909{\r
910 ESL_PACKET * pPacket;\r
911 ESL_PACKET * pPreviousPacket;\r
912 ESL_PORT * pPort;\r
913 const struct sockaddr_in * pRemoteAddress;\r
914 ESL_IP4_CONTEXT * pIp4;\r
915 size_t * pTxBytes;\r
916 ESL_IP4_TX_DATA * pTxData;\r
917 EFI_STATUS Status;\r
918 EFI_TPL TplPrevious;\r
919\r
920 DBG_ENTER ( );\r
921\r
922 //\r
923 // Assume failure\r
924 //\r
925 Status = EFI_UNSUPPORTED;\r
926 pSocket->errno = ENOTCONN;\r
927 *pDataLength = 0;\r
928\r
929 //\r
930 // Verify that the socket is connected\r
931 //\r
932 if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
933 //\r
884ed923 934 // Verify that there is enough room to buffer another\r
935 // transmit operation\r
a88c3163 936 //\r
884ed923 937 pTxBytes = &pSocket->TxBytes;\r
938 if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
a88c3163 939 //\r
884ed923 940 // Locate the port\r
a88c3163 941 //\r
884ed923 942 pPort = pSocket->pPortList;\r
943 while ( NULL != pPort ) {\r
944 //\r
945 // Determine the queue head\r
946 //\r
947 pIp4 = &pPort->Context.Ip4;\r
a88c3163 948\r
a88c3163 949 //\r
950 // Attempt to allocate the packet\r
951 //\r
952 Status = EslSocketPacketAllocate ( &pPacket,\r
953 sizeof ( pPacket->Op.Ip4Tx )\r
954 - sizeof ( pPacket->Op.Ip4Tx.Buffer )\r
955 + BufferLength,\r
956 0,\r
957 DEBUG_TX );\r
958 if ( !EFI_ERROR ( Status )) {\r
959 //\r
960 // Initialize the transmit operation\r
961 //\r
962 pTxData = &pPacket->Op.Ip4Tx;\r
963 pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0];\r
964 pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1];\r
965 pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2];\r
966 pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3];\r
967 pTxData->TxData.OverrideData = NULL;\r
968 pTxData->TxData.OptionsLength = 0;\r
969 pTxData->TxData.OptionsBuffer = NULL;\r
970 pTxData->TxData.TotalDataLength = (UINT32) BufferLength;\r
971 pTxData->TxData.FragmentCount = 1;\r
972 pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;\r
973 pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0];\r
974\r
975 //\r
976 // Set the remote system address if necessary\r
977 //\r
978 if ( NULL != pAddress ) {\r
979 pRemoteAddress = (const struct sockaddr_in *)pAddress;\r
980 pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0];\r
981 pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1];\r
982 pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2];\r
983 pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3];\r
984 pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;\r
985 pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
986 pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
987 pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
988 pTxData->Override.GatewayAddress.Addr[0] = 0;\r
989 pTxData->Override.GatewayAddress.Addr[1] = 0;\r
990 pTxData->Override.GatewayAddress.Addr[2] = 0;\r
991 pTxData->Override.GatewayAddress.Addr[3] = 0;\r
992 pTxData->Override.Protocol = (UINT8)pSocket->Protocol;\r
993 pTxData->Override.TypeOfService = 0;\r
994 pTxData->Override.TimeToLive = 255;\r
995 pTxData->Override.DoNotFragment = FALSE;\r
996\r
997 //\r
998 // Use the remote system address when sending this packet\r
999 //\r
1000 pTxData->TxData.OverrideData = &pTxData->Override;\r
1001 }\r
1002\r
1003 //\r
1004 // Copy the data into the buffer\r
1005 //\r
1006 CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0],\r
1007 pBuffer,\r
1008 BufferLength );\r
1009\r
1010 //\r
1011 // Synchronize with the socket layer\r
1012 //\r
1013 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
1014\r
1015 //\r
2dc09dd5 1016 // Display the request\r
a88c3163 1017 //\r
2dc09dd5
LL
1018 DEBUG (( DEBUG_TX,\r
1019 "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
1020 BufferLength,\r
1021 pBuffer,\r
1022 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
1023 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
1024 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
1025 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
1026 pTxData->TxData.DestinationAddress.Addr[0],\r
1027 pTxData->TxData.DestinationAddress.Addr[1],\r
1028 pTxData->TxData.DestinationAddress.Addr[2],\r
1029 pTxData->TxData.DestinationAddress.Addr[3]));\r
a88c3163 1030\r
2dc09dd5
LL
1031 //\r
1032 // Queue the data for transmission\r
1033 //\r
1034 pPacket->pNext = NULL;\r
1035 pPreviousPacket = pSocket->pTxPacketListTail;\r
1036 if ( NULL == pPreviousPacket ) {\r
1037 pSocket->pTxPacketListHead = pPacket;\r
a88c3163 1038 }\r
1039 else {\r
2dc09dd5
LL
1040 pPreviousPacket->pNext = pPacket;\r
1041 }\r
1042 pSocket->pTxPacketListTail = pPacket;\r
1043 DEBUG (( DEBUG_TX,\r
1044 "0x%08x: Packet on transmit list\r\n",\r
1045 pPacket ));\r
1046\r
1047 //\r
1048 // Account for the buffered data\r
1049 //\r
1050 *pTxBytes += BufferLength;\r
1051 *pDataLength = BufferLength;\r
1052\r
1053 //\r
1054 // Start the transmit engine if it is idle\r
1055 //\r
1056 if ( NULL != pPort->pTxFree ) {\r
1057 EslSocketTxStart ( pPort,\r
1058 &pSocket->pTxPacketListHead,\r
1059 &pSocket->pTxPacketListTail,\r
1060 &pPort->pTxActive,\r
1061 &pPort->pTxFree );\r
a88c3163 1062\r
1063 //\r
2dc09dd5 1064 // Ignore any transmit error\r
a88c3163 1065 //\r
2dc09dd5
LL
1066 if ( EFI_ERROR ( pSocket->TxError )) {\r
1067 DEBUG (( DEBUG_TX,\r
1068 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",\r
1069 pPort,\r
1070 pPacket,\r
1071 pSocket->TxError ));\r
1072 }\r
1073 pSocket->TxError = EFI_SUCCESS;\r
a88c3163 1074 }\r
1075\r
1076 //\r
1077 // Release the socket layer synchronization\r
1078 //\r
1079 RESTORE_TPL ( TplPrevious );\r
1080 }\r
1081 else {\r
1082 //\r
1083 // Packet allocation failed\r
1084 //\r
1085 pSocket->errno = ENOMEM;\r
884ed923 1086 break;\r
a88c3163 1087 }\r
884ed923 1088\r
a88c3163 1089 //\r
884ed923 1090 // Set the next port\r
a88c3163 1091 //\r
884ed923 1092 pPort = pPort->pLinkSocket;\r
a88c3163 1093 }\r
1094 }\r
884ed923 1095 else {\r
1096 //\r
1097 // Not enough buffer space available\r
1098 //\r
1099 pSocket->errno = EAGAIN;\r
1100 Status = EFI_NOT_READY;\r
1101 }\r
a88c3163 1102 }\r
1103\r
1104 //\r
1105 // Return the operation status\r
1106 //\r
1107 DBG_EXIT_STATUS ( Status );\r
1108 return Status;\r
1109}\r
1110\r
1111\r
1112/**\r
1113 Process the transmit completion\r
1114\r
1115 This routine use ::EslSocketTxComplete to perform the transmit\r
1116 completion processing for data packets.\r
1117\r
1118 This routine is called by the IPv4 network layer when a data\r
1119 transmit request completes.\r
1120\r
1121 @param [in] Event The normal transmit completion event\r
1122\r
1123 @param [in] pIo The address of an ::ESL_IO_MGMT structure\r
1124\r
1125**/\r
1126VOID\r
1127EslIp4TxComplete (\r
1128 IN EFI_EVENT Event,\r
1129 IN ESL_IO_MGMT * pIo\r
1130 )\r
1131{\r
1132 UINT32 LengthInBytes;\r
1133 ESL_PORT * pPort;\r
1134 ESL_PACKET * pPacket;\r
1135 ESL_SOCKET * pSocket;\r
1136 EFI_STATUS Status;\r
0e565888 1137\r
a88c3163 1138 DBG_ENTER ( );\r
0e565888 1139\r
a88c3163 1140 //\r
1141 // Locate the active transmit packet\r
1142 //\r
1143 pPacket = pIo->pPacket;\r
1144 pPort = pIo->pPort;\r
1145 pSocket = pPort->pSocket;\r
1146\r
1147 //\r
1148 // Get the transmit length and status\r
1149 //\r
1150 LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength;\r
1151 pSocket->TxBytes -= LengthInBytes;\r
1152 Status = pIo->Token.Ip4Tx.Status;\r
1153\r
2dc09dd5
LL
1154 //\r
1155 // Ignore the transmit error\r
1156 //\r
1157 if ( EFI_ERROR ( Status )) {\r
1158 DEBUG (( DEBUG_TX,\r
1159 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",\r
1160 pPort,\r
1161 pPacket,\r
1162 Status ));\r
1163 Status = EFI_SUCCESS;\r
1164 }\r
1165\r
a88c3163 1166 //\r
1167 // Complete the transmit operation\r
1168 //\r
1169 EslSocketTxComplete ( pIo,\r
1170 LengthInBytes,\r
1171 Status,\r
1172 "Raw ",\r
1173 &pSocket->pTxPacketListHead,\r
1174 &pSocket->pTxPacketListTail,\r
1175 &pPort->pTxActive,\r
1176 &pPort->pTxFree );\r
1177 DBG_EXIT ( );\r
1178}\r
1179\r
1180\r
2dc09dd5
LL
1181/**\r
1182 Verify the adapter's IP address\r
1183\r
1184 This support routine is called by EslSocketBindTest.\r
1185\r
1186 @param [in] pPort Address of an ::ESL_PORT structure.\r
1187 @param [in] pConfigData Address of the configuration data\r
1188\r
1189 @retval EFI_SUCCESS - The IP address is valid\r
1190 @retval EFI_NOT_STARTED - The IP address is invalid\r
1191\r
1192 **/\r
1193EFI_STATUS\r
1194EslIp4VerifyLocalIpAddress (\r
1195 IN ESL_PORT * pPort,\r
1196 IN EFI_IP4_CONFIG_DATA * pConfigData\r
1197 )\r
1198{\r
1199 UINTN DataSize;\r
1200 EFI_IP4_IPCONFIG_DATA * pIpConfigData;\r
1201 EFI_IP4_CONFIG_PROTOCOL * pIpConfigProtocol;\r
1202 ESL_SERVICE * pService;\r
1203 EFI_STATUS Status;\r
1204\r
1205 DBG_ENTER ( );\r
1206\r
1207 //\r
1208 // Use break instead of goto\r
1209 //\r
1210 pIpConfigData = NULL;\r
1211 for ( ; ; ) {\r
1212 //\r
1213 // Determine if the IP address is specified\r
1214 //\r
1215 DEBUG (( DEBUG_BIND,\r
1216 "UseDefaultAddress: %s\r\n",\r
1217 pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
1218 DEBUG (( DEBUG_BIND,\r
1219 "Requested IP address: %d.%d.%d.%d\r\n",\r
1220 pConfigData->StationAddress.Addr [ 0 ],\r
1221 pConfigData->StationAddress.Addr [ 1 ],\r
1222 pConfigData->StationAddress.Addr [ 2 ],\r
1223 pConfigData->StationAddress.Addr [ 3 ]));\r
1224 if ( pConfigData->UseDefaultAddress\r
1225 || (( 0 == pConfigData->StationAddress.Addr [ 0 ])\r
1226 && ( 0 == pConfigData->StationAddress.Addr [ 1 ])\r
1227 && ( 0 == pConfigData->StationAddress.Addr [ 2 ])\r
1228 && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))\r
1229 {\r
1230 Status = EFI_SUCCESS;\r
1231 break;\r
1232 }\r
1233\r
1234 //\r
1235 // Open the configuration protocol\r
1236 //\r
1237 pService = pPort->pService;\r
1238 Status = gBS->OpenProtocol ( pService->Controller,\r
1239 &gEfiIp4ConfigProtocolGuid,\r
1240 (VOID **)&pIpConfigProtocol,\r
1241 NULL,\r
1242 NULL,\r
1243 EFI_OPEN_PROTOCOL_GET_PROTOCOL );\r
1244 if ( EFI_ERROR ( Status )) {\r
1245 DEBUG (( DEBUG_ERROR,\r
1246 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
1247 Status ));\r
1248 break;\r
1249 }\r
1250\r
1251 //\r
1252 // Get the IP configuration data size\r
1253 //\r
1254 DataSize = 0;\r
1255 Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
1256 &DataSize,\r
1257 NULL );\r
1258 if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
1259 DEBUG (( DEBUG_ERROR,\r
1260 "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",\r
1261 Status ));\r
1262 break;\r
1263 }\r
1264\r
1265 //\r
1266 // Allocate the configuration data buffer\r
1267 //\r
1268 pIpConfigData = AllocatePool ( DataSize );\r
1269 if ( NULL == pIpConfigData ) {\r
1270 DEBUG (( DEBUG_ERROR,\r
1271 "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));\r
1272 Status = EFI_OUT_OF_RESOURCES;\r
1273 break;\r
1274 }\r
1275\r
1276 //\r
1277 // Get the IP configuration\r
1278 //\r
1279 Status = pIpConfigProtocol->GetData ( pIpConfigProtocol,\r
1280 &DataSize,\r
1281 pIpConfigData );\r
1282 if ( EFI_ERROR ( Status )) {\r
1283 DEBUG (( DEBUG_ERROR,\r
1284 "ERROR - Failed to return IP Configuration data, Status: %r\r\n",\r
1285 Status ));\r
1286 break;\r
1287 }\r
1288\r
1289 //\r
1290 // Display the current configuration\r
1291 //\r
1292 DEBUG (( DEBUG_BIND,\r
1293 "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
1294 pIpConfigData->StationAddress.Addr [ 0 ],\r
1295 pIpConfigData->StationAddress.Addr [ 1 ],\r
1296 pIpConfigData->StationAddress.Addr [ 2 ],\r
1297 pIpConfigData->StationAddress.Addr [ 3 ]));\r
1298\r
1299 //\r
1300 // Assume the port is not configured\r
1301 //\r
1302 Status = EFI_SUCCESS;\r
1303 if (( pConfigData->StationAddress.Addr [ 0 ] == pIpConfigData->StationAddress.Addr [ 0 ])\r
1304 && ( pConfigData->StationAddress.Addr [ 1 ] == pIpConfigData->StationAddress.Addr [ 1 ])\r
1305 && ( pConfigData->StationAddress.Addr [ 2 ] == pIpConfigData->StationAddress.Addr [ 2 ])\r
1306 && ( pConfigData->StationAddress.Addr [ 3 ] == pIpConfigData->StationAddress.Addr [ 3 ])) {\r
1307 break;\r
1308 }\r
1309\r
1310 //\r
1311 // The IP address did not match\r
1312 //\r
1313 Status = EFI_NOT_STARTED;\r
1314 break;\r
1315 }\r
1316\r
1317 //\r
1318 // Free the buffer if necessary\r
1319 //\r
1320 if ( NULL != pIpConfigData ) {\r
1321 FreePool ( pIpConfigData );\r
1322 }\r
1323\r
1324 //\r
1325 // Return the IP address status\r
1326 //\r
1327 DBG_EXIT_STATUS ( Status );\r
1328 return Status;\r
1329}\r
1330\r
1331\r
a88c3163 1332/**\r
1333 Interface between the socket layer and the network specific\r
1334 code that supports SOCK_RAW sockets over IPv4.\r
1335**/\r
1336CONST ESL_PROTOCOL_API cEslIp4Api = {\r
1337 "IPv4",\r
1338 IPPROTO_IP,\r
1339 OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ),\r
1340 OFFSET_OF ( ESL_LAYER, pIp4List ),\r
1341 OFFSET_OF ( struct sockaddr_in, sin_zero ),\r
1342 sizeof ( struct sockaddr_in ),\r
1343 AF_INET,\r
1344 sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),\r
1345 sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),\r
1346 OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),\r
1347 FALSE,\r
1348 EADDRNOTAVAIL,\r
1349 NULL, // Accept\r
1350 NULL, // ConnectPoll\r
1351 NULL, // ConnectStart\r
1352 EslIp4SocketIsConfigured,\r
1353 EslIp4LocalAddressGet,\r
1354 EslIp4LocalAddressSet,\r
1355 NULL, // Listen\r
1356 EslIp4OptionGet,\r
1357 EslIp4OptionSet,\r
1358 EslIp4PacketFree,\r
1359 EslIp4PortAllocate,\r
1360 NULL, // PortClose\r
1361 NULL, // PortCloseOp\r
1362 TRUE,\r
1363 EslIp4Receive,\r
1364 EslIp4RemoteAddressGet,\r
1365 EslIp4RemoteAddressSet,\r
1366 EslIp4RxComplete,\r
1367 NULL, // RxStart\r
1368 EslIp4TxBuffer,\r
1369 EslIp4TxComplete,\r
2dc09dd5 1370 NULL, // TxOobComplete\r
a93b0f45 1371 (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress\r
a88c3163 1372};\r