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