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