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