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 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 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 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 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 * 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 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 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 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 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 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 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 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