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