/** @file
  Help functions to access UDP service, it is used by both the DHCP and MTFTP.

Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Uefi.h>

#include <Protocol/Udp4.h>
#include <Protocol/Udp6.h>

#include <Library/UdpIoLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DpcLib.h>

/**
  Free a UDP_TX_TOKEN. The TX event is closed.

  @param[in]  TxToken                 The UDP_TX_TOKEN to release.

**/
VOID
UdpIoFreeTxToken (
  IN UDP_TX_TOKEN  *TxToken
  )
{
  if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    gBS->CloseEvent (TxToken->Token.Udp4.Event);
  } else if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
    gBS->CloseEvent (TxToken->Token.Udp6.Event);
  } else {
    ASSERT (FALSE);
  }

  FreePool (TxToken);
}

/**
  Free a UDP_RX_TOKEN. The RX event is closed.

  @param[in]  RxToken                 The UDP_RX_TOKEN to release.

**/
VOID
UdpIoFreeRxToken (
  IN UDP_RX_TOKEN  *RxToken
  )
{
  if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    gBS->CloseEvent (RxToken->Token.Udp4.Event);
  } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
    gBS->CloseEvent (RxToken->Token.Udp6.Event);
  } else {
    ASSERT (FALSE);
  }

  FreePool (RxToken);
}

/**
  The callback function when the packet is sent by UDP.

  It will remove the packet from the local list then call
  the packet owner's callback function set by UdpIoSendDatagram.

  @param[in]  Context               The UDP TX Token.

**/
VOID
EFIAPI
UdpIoOnDgramSentDpc (
  IN VOID  *Context
  )
{
  UDP_TX_TOKEN  *TxToken;

  TxToken = (UDP_TX_TOKEN *)Context;
  ASSERT (TxToken->Signature == UDP_IO_TX_SIGNATURE);
  ASSERT (
    (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  RemoveEntryList (&TxToken->Link);

  if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp4.Status, TxToken->Context);
  } else {
    TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp6.Status, TxToken->Context);
  }

  UdpIoFreeTxToken (TxToken);
}

/**
  Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.

  @param[in]  Event                 The event signaled.
  @param[in]  Context               The UDP TX Token.

**/
VOID
EFIAPI
UdpIoOnDgramSent (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  //
  // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK
  //
  QueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);
}

/**
  Recycle the received UDP data.

  @param[in]  Context               The UDP_RX_TOKEN.

**/
VOID
EFIAPI
UdpIoRecycleDgram (
  IN VOID  *Context
  )
{
  UDP_RX_TOKEN  *RxToken;

  RxToken = (UDP_RX_TOKEN *)Context;

  if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    gBS->SignalEvent (RxToken->Token.Udp4.Packet.RxData->RecycleSignal);
  } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {
    gBS->SignalEvent (RxToken->Token.Udp6.Packet.RxData->RecycleSignal);
  } else {
    ASSERT (FALSE);
  }

  UdpIoFreeRxToken (RxToken);
}

/**
  The event handle for UDP receive request.

  It will build a NET_BUF from the received UDP data, then deliver it
  to the receiver.

  @param[in]  Context               The UDP RX token.

**/
VOID
EFIAPI
UdpIoOnDgramRcvdDpc (
  IN VOID  *Context
  )
{
  EFI_STATUS     Status;
  VOID           *Token;
  VOID           *RxData;
  VOID           *Session;
  UDP_RX_TOKEN   *RxToken;
  UDP_END_POINT  EndPoint;
  NET_BUF        *Netbuf;

  RxToken = (UDP_RX_TOKEN *)Context;

  ZeroMem (&EndPoint, sizeof (UDP_END_POINT));

  ASSERT (
    (RxToken->Signature == UDP_IO_RX_SIGNATURE) &&
    (RxToken == RxToken->UdpIo->RecvRequest)
    );

  ASSERT (
    (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  //
  // Clear the receive request first in case that the caller
  // wants to restart the receive in the callback.
  //
  RxToken->UdpIo->RecvRequest = NULL;

  if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    Token  = &RxToken->Token.Udp4;
    RxData = ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Packet.RxData;
    Status = ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Status;
  } else {
    Token  = &RxToken->Token.Udp6;
    RxData = ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Packet.RxData;
    Status = ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Status;
  }

  if (EFI_ERROR (Status) || (RxData == NULL)) {
    if (Status != EFI_ABORTED) {
      //
      // Invoke the CallBack only if the reception is not actively aborted.
      //
      RxToken->CallBack (NULL, NULL, Status, RxToken->Context);
    }

    UdpIoFreeRxToken (RxToken);
    return;
  }

  //
  // Build a NET_BUF from the UDP receive data, then deliver it up.
  //
  if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    if (((EFI_UDP4_RECEIVE_DATA *)RxData)->DataLength == 0) {
      //
      // Discard zero length data payload packet.
      //
      goto Resume;
    }

    Netbuf = NetbufFromExt (
               (NET_FRAGMENT *)((EFI_UDP4_RECEIVE_DATA *)RxData)->FragmentTable,
               ((EFI_UDP4_RECEIVE_DATA *)RxData)->FragmentCount,
               0,
               (UINT32)RxToken->HeadLen,
               UdpIoRecycleDgram,
               RxToken
               );

    if (Netbuf == NULL) {
      gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *)RxData)->RecycleSignal);
      RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);

      UdpIoFreeRxToken (RxToken);
      return;
    }

    Session             = &((EFI_UDP4_RECEIVE_DATA *)RxData)->UdpSession;
    EndPoint.LocalPort  = ((EFI_UDP4_SESSION_DATA *)Session)->DestinationPort;
    EndPoint.RemotePort = ((EFI_UDP4_SESSION_DATA *)Session)->SourcePort;

    CopyMem (
      &EndPoint.LocalAddr,
      &((EFI_UDP4_SESSION_DATA *)Session)->DestinationAddress,
      sizeof (EFI_IPv4_ADDRESS)
      );

    CopyMem (
      &EndPoint.RemoteAddr,
      &((EFI_UDP4_SESSION_DATA *)Session)->SourceAddress,
      sizeof (EFI_IPv4_ADDRESS)
      );

    EndPoint.LocalAddr.Addr[0]  = NTOHL (EndPoint.LocalAddr.Addr[0]);
    EndPoint.RemoteAddr.Addr[0] = NTOHL (EndPoint.RemoteAddr.Addr[0]);
  } else {
    if (((EFI_UDP6_RECEIVE_DATA *)RxData)->DataLength == 0) {
      //
      // Discard zero length data payload packet.
      //
      goto Resume;
    }

    Netbuf = NetbufFromExt (
               (NET_FRAGMENT *)((EFI_UDP6_RECEIVE_DATA *)RxData)->FragmentTable,
               ((EFI_UDP6_RECEIVE_DATA *)RxData)->FragmentCount,
               0,
               (UINT32)RxToken->HeadLen,
               UdpIoRecycleDgram,
               RxToken
               );

    if (Netbuf == NULL) {
      gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *)RxData)->RecycleSignal);
      RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);

      UdpIoFreeRxToken (RxToken);
      return;
    }

    Session             = &((EFI_UDP6_RECEIVE_DATA *)RxData)->UdpSession;
    EndPoint.LocalPort  = ((EFI_UDP6_SESSION_DATA *)Session)->DestinationPort;
    EndPoint.RemotePort = ((EFI_UDP6_SESSION_DATA *)Session)->SourcePort;

    CopyMem (
      &EndPoint.LocalAddr,
      &((EFI_UDP6_SESSION_DATA *)Session)->DestinationAddress,
      sizeof (EFI_IPv6_ADDRESS)
      );

    CopyMem (
      &EndPoint.RemoteAddr,
      &((EFI_UDP6_SESSION_DATA *)Session)->SourceAddress,
      sizeof (EFI_IPv6_ADDRESS)
      );

    Ip6Swap128 (&EndPoint.LocalAddr.v6);
    Ip6Swap128 (&EndPoint.RemoteAddr.v6);
  }

  RxToken->CallBack (Netbuf, &EndPoint, EFI_SUCCESS, RxToken->Context);
  return;

Resume:
  if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *)RxData)->RecycleSignal);
    RxToken->UdpIo->Protocol.Udp4->Receive (RxToken->UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
  } else {
    gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *)RxData)->RecycleSignal);
    RxToken->UdpIo->Protocol.Udp6->Receive (RxToken->UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
  }
}

/**
  Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.

  @param[in]  Event                 The UDP receive request event.
  @param[in]  Context               The UDP RX token.

**/
VOID
EFIAPI
UdpIoOnDgramRcvd (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  //
  // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
  //
  QueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);
}

/**
  Create a UDP_RX_TOKEN to wrap the request.

  @param[in]  UdpIo                 The UdpIo to receive packets from.
  @param[in]  CallBack              The function to call when receive finished.
  @param[in]  Context               The opaque parameter to the CallBack.
  @param[in]  HeadLen               The head length to reserve for the packet.

  @return The Wrapped request or NULL if failed to allocate resources or some errors happened.

**/
UDP_RX_TOKEN *
UdpIoCreateRxToken (
  IN UDP_IO           *UdpIo,
  IN UDP_IO_CALLBACK  CallBack,
  IN VOID             *Context,
  IN UINT32           HeadLen
  )
{
  UDP_RX_TOKEN  *Token;
  EFI_STATUS    Status;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  Token = AllocatePool (sizeof (UDP_RX_TOKEN));

  if (Token == NULL) {
    return NULL;
  }

  Token->Signature = UDP_IO_RX_SIGNATURE;
  Token->UdpIo     = UdpIo;
  Token->CallBack  = CallBack;
  Token->Context   = Context;
  Token->HeadLen   = HeadLen;

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    Token->Token.Udp4.Status        = EFI_NOT_READY;
    Token->Token.Udp4.Packet.RxData = NULL;

    Status = gBS->CreateEvent (
                    EVT_NOTIFY_SIGNAL,
                    TPL_NOTIFY,
                    UdpIoOnDgramRcvd,
                    Token,
                    &Token->Token.Udp4.Event
                    );
  } else {
    Token->Token.Udp6.Status        = EFI_NOT_READY;
    Token->Token.Udp6.Packet.RxData = NULL;

    Status = gBS->CreateEvent (
                    EVT_NOTIFY_SIGNAL,
                    TPL_NOTIFY,
                    UdpIoOnDgramRcvd,
                    Token,
                    &Token->Token.Udp6.Event
                    );
  }

  if (EFI_ERROR (Status)) {
    FreePool (Token);
    return NULL;
  }

  return Token;
}

/**
  Wrap a transmit request into a new created UDP_TX_TOKEN.

  If Packet is NULL, then ASSERT().
  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  @param[in]  UdpIo                 The UdpIo to send packet to.
  @param[in]  Packet                The user's packet.
  @param[in]  EndPoint              The local and remote access point.
  @param[in]  Gateway               The overridden next hop.
  @param[in]  CallBack              The function to call when transmission completed.
  @param[in]  Context               The opaque parameter to the call back.

  @return The wrapped transmission request or NULL if failed to allocate resources
          or for some errors.

**/
UDP_TX_TOKEN *
UdpIoCreateTxToken (
  IN UDP_IO           *UdpIo,
  IN NET_BUF          *Packet,
  IN UDP_END_POINT    *EndPoint OPTIONAL,
  IN EFI_IP_ADDRESS   *Gateway  OPTIONAL,
  IN UDP_IO_CALLBACK  CallBack,
  IN VOID             *Context
  )
{
  UDP_TX_TOKEN  *TxToken;
  VOID          *Token;
  VOID          *Data;
  EFI_STATUS    Status;
  UINT32        Count;
  UINTN         Size;
  IP4_ADDR      Ip;

  ASSERT (Packet != NULL);
  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);
  } else {
    Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP6_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);
  }

  TxToken = AllocatePool (Size);

  if (TxToken == NULL) {
    return NULL;
  }

  TxToken->Signature = UDP_IO_TX_SIGNATURE;
  InitializeListHead (&TxToken->Link);

  TxToken->UdpIo    = UdpIo;
  TxToken->CallBack = CallBack;
  TxToken->Packet   = Packet;
  TxToken->Context  = Context;

  Token = &(TxToken->Token);
  Count = Packet->BlockOpNum;

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Status = EFI_NOT_READY;

    Status = gBS->CreateEvent (
                    EVT_NOTIFY_SIGNAL,
                    TPL_NOTIFY,
                    UdpIoOnDgramSent,
                    TxToken,
                    &((EFI_UDP4_COMPLETION_TOKEN *)Token)->Event
                    );

    if (EFI_ERROR (Status)) {
      FreePool (TxToken);
      return NULL;
    }

    Data                                                = &(TxToken->Data.Udp4);
    ((EFI_UDP4_COMPLETION_TOKEN *)Token)->Packet.TxData = Data;

    ((EFI_UDP4_TRANSMIT_DATA *)Data)->UdpSessionData = NULL;
    ((EFI_UDP4_TRANSMIT_DATA *)Data)->GatewayAddress = NULL;
    ((EFI_UDP4_TRANSMIT_DATA *)Data)->DataLength     = Packet->TotalSize;

    NetbufBuildExt (
      Packet,
      (NET_FRAGMENT *)((EFI_UDP4_TRANSMIT_DATA *)Data)->FragmentTable,
      &Count
      );

    ((EFI_UDP4_TRANSMIT_DATA *)Data)->FragmentCount = Count;

    if (EndPoint != NULL) {
      Ip = HTONL (EndPoint->LocalAddr.Addr[0]);
      CopyMem (
        &TxToken->Session.Udp4.SourceAddress,
        &Ip,
        sizeof (EFI_IPv4_ADDRESS)
        );

      Ip = HTONL (EndPoint->RemoteAddr.Addr[0]);
      CopyMem (
        &TxToken->Session.Udp4.DestinationAddress,
        &Ip,
        sizeof (EFI_IPv4_ADDRESS)
        );

      TxToken->Session.Udp4.SourcePort                 = EndPoint->LocalPort;
      TxToken->Session.Udp4.DestinationPort            = EndPoint->RemotePort;
      ((EFI_UDP4_TRANSMIT_DATA *)Data)->UdpSessionData = &(TxToken->Session.Udp4);
    }

    if ((Gateway != NULL) && (Gateway->Addr[0] != 0)) {
      Ip = HTONL (Gateway->Addr[0]);
      CopyMem (&TxToken->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));
      ((EFI_UDP4_TRANSMIT_DATA *)Data)->GatewayAddress = &TxToken->Gateway;
    }
  } else {
    ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Status = EFI_NOT_READY;

    Status = gBS->CreateEvent (
                    EVT_NOTIFY_SIGNAL,
                    TPL_NOTIFY,
                    UdpIoOnDgramSent,
                    TxToken,
                    &((EFI_UDP6_COMPLETION_TOKEN *)Token)->Event
                    );

    if (EFI_ERROR (Status)) {
      FreePool (TxToken);
      return NULL;
    }

    Data                                                = &(TxToken->Data.Udp6);
    ((EFI_UDP6_COMPLETION_TOKEN *)Token)->Packet.TxData = Data;
    ((EFI_UDP6_TRANSMIT_DATA *)Data)->UdpSessionData    = NULL;
    ((EFI_UDP6_TRANSMIT_DATA *)Data)->DataLength        = Packet->TotalSize;

    NetbufBuildExt (
      Packet,
      (NET_FRAGMENT *)((EFI_UDP6_TRANSMIT_DATA *)Data)->FragmentTable,
      &Count
      );

    ((EFI_UDP6_TRANSMIT_DATA *)Data)->FragmentCount = Count;

    if (EndPoint != NULL) {
      CopyMem (
        &TxToken->Session.Udp6.SourceAddress,
        &EndPoint->LocalAddr.v6,
        sizeof (EFI_IPv6_ADDRESS)
        );

      CopyMem (
        &TxToken->Session.Udp6.DestinationAddress,
        &EndPoint->RemoteAddr.v6,
        sizeof (EFI_IPv6_ADDRESS)
        );

      TxToken->Session.Udp6.SourcePort                 = EndPoint->LocalPort;
      TxToken->Session.Udp6.DestinationPort            = EndPoint->RemotePort;
      ((EFI_UDP6_TRANSMIT_DATA *)Data)->UdpSessionData = &(TxToken->Session.Udp6);
    }
  }

  return TxToken;
}

/**
  Creates a UDP_IO to access the UDP service. It creates and configures
  a UDP child.

  If Configure is NULL, then ASSERT().
  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  It locates the UDP service binding prototype on the Controller parameter
  uses the UDP service binding prototype to create a UDP child (also known as
  a UDP instance) configures the UDP child by calling Configure function prototype.
  Any failures in creating or configuring the UDP child return NULL for failure.

  @param[in]  Controller            The controller that has the UDP service binding.
                                    protocol installed.
  @param[in]  ImageHandle           The image handle for the driver.
  @param[in]  Configure             The function to configure the created UDP child.
  @param[in]  UdpVersion            The UDP protocol version, UDP4 or UDP6.
  @param[in]  Context               The opaque parameter for the Configure function.

  @return Newly-created UDP_IO or NULL if failed.

**/
UDP_IO *
EFIAPI
UdpIoCreateIo (
  IN  EFI_HANDLE     Controller,
  IN  EFI_HANDLE     ImageHandle,
  IN  UDP_IO_CONFIG  Configure,
  IN  UINT8          UdpVersion,
  IN  VOID           *Context
  )
{
  UDP_IO      *UdpIo;
  EFI_STATUS  Status;

  ASSERT (Configure != NULL);
  ASSERT ((UdpVersion == UDP_IO_UDP4_VERSION) || (UdpVersion == UDP_IO_UDP6_VERSION));

  UdpIo = AllocatePool (sizeof (UDP_IO));

  if (UdpIo == NULL) {
    return NULL;
  }

  UdpIo->UdpVersion = UdpVersion;
  UdpIo->Signature  = UDP_IO_SIGNATURE;
  InitializeListHead (&UdpIo->Link);
  UdpIo->RefCnt = 1;

  UdpIo->Controller = Controller;
  UdpIo->Image      = ImageHandle;

  InitializeListHead (&UdpIo->SentDatagram);
  UdpIo->RecvRequest = NULL;
  UdpIo->UdpHandle   = NULL;

  if (UdpVersion == UDP_IO_UDP4_VERSION) {
    //
    // Create a UDP child then open and configure it
    //
    Status = NetLibCreateServiceChild (
               Controller,
               ImageHandle,
               &gEfiUdp4ServiceBindingProtocolGuid,
               &UdpIo->UdpHandle
               );

    if (EFI_ERROR (Status)) {
      goto FREE_MEM;
    }

    Status = gBS->OpenProtocol (
                    UdpIo->UdpHandle,
                    &gEfiUdp4ProtocolGuid,
                    (VOID **)&UdpIo->Protocol.Udp4,
                    ImageHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );

    if (EFI_ERROR (Status)) {
      goto FREE_CHILD;
    }

    if (EFI_ERROR (Configure (UdpIo, Context))) {
      goto CLOSE_PROTOCOL;
    }

    Status = UdpIo->Protocol.Udp4->GetModeData (
                                     UdpIo->Protocol.Udp4,
                                     NULL,
                                     NULL,
                                     NULL,
                                     &UdpIo->SnpMode
                                     );

    if (EFI_ERROR (Status)) {
      goto CLOSE_PROTOCOL;
    }
  } else {
    Status = NetLibCreateServiceChild (
               Controller,
               ImageHandle,
               &gEfiUdp6ServiceBindingProtocolGuid,
               &UdpIo->UdpHandle
               );

    if (EFI_ERROR (Status)) {
      goto FREE_MEM;
    }

    Status = gBS->OpenProtocol (
                    UdpIo->UdpHandle,
                    &gEfiUdp6ProtocolGuid,
                    (VOID **)&UdpIo->Protocol.Udp6,
                    ImageHandle,
                    Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );

    if (EFI_ERROR (Status)) {
      goto FREE_CHILD;
    }

    if (EFI_ERROR (Configure (UdpIo, Context))) {
      goto CLOSE_PROTOCOL;
    }

    Status = UdpIo->Protocol.Udp6->GetModeData (
                                     UdpIo->Protocol.Udp6,
                                     NULL,
                                     NULL,
                                     NULL,
                                     &UdpIo->SnpMode
                                     );

    if (EFI_ERROR (Status)) {
      goto CLOSE_PROTOCOL;
    }
  }

  return UdpIo;

CLOSE_PROTOCOL:
  if (UdpVersion == UDP_IO_UDP4_VERSION) {
    gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, ImageHandle, Controller);
  } else {
    gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp6ProtocolGuid, ImageHandle, Controller);
  }

FREE_CHILD:
  if (UdpVersion == UDP_IO_UDP4_VERSION) {
    NetLibDestroyServiceChild (
      Controller,
      ImageHandle,
      &gEfiUdp4ServiceBindingProtocolGuid,
      UdpIo->UdpHandle
      );
  } else {
    NetLibDestroyServiceChild (
      Controller,
      ImageHandle,
      &gEfiUdp6ServiceBindingProtocolGuid,
      UdpIo->UdpHandle
      );
  }

FREE_MEM:
  FreePool (UdpIo);
  return NULL;
}

/**
  Cancel all the sent datagram that pass the selection criteria of ToCancel.

  If ToCancel is NULL, all the datagrams are cancelled.
  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  @param[in]  UdpIo                 The UDP_IO to cancel packet.
  @param[in]  IoStatus              The IoStatus to return to the packet owners.
  @param[in]  ToCancel              The select function to test whether to cancel this
                                    packet or not.
  @param[in]  Context               The opaque parameter to the ToCancel.

**/
VOID
EFIAPI
UdpIoCancelDgrams (
  IN UDP_IO            *UdpIo,
  IN EFI_STATUS        IoStatus,
  IN UDP_IO_TO_CANCEL  ToCancel         OPTIONAL,
  IN VOID              *Context         OPTIONAL
  )
{
  LIST_ENTRY    *Entry;
  LIST_ENTRY    *Next;
  UDP_TX_TOKEN  *TxToken;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {
    TxToken = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);

    if ((ToCancel == NULL) || (ToCancel (TxToken, Context))) {
      if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
        UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);
      } else {
        UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);
      }
    }
  }
}

/**
  Free the UDP_IO and all its related resources.

  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  The function will cancel all sent datagram and receive request.

  @param[in]  UdpIo             The UDP_IO to free.

  @retval EFI_SUCCESS           The UDP_IO is freed.
  @retval Others                Failed to free UDP_IO.

**/
EFI_STATUS
EFIAPI
UdpIoFreeIo (
  IN  UDP_IO  *UdpIo
  )
{
  EFI_STATUS    Status;
  UDP_RX_TOKEN  *RxToken;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  //
  // Cancel all the sent datagram and receive requests. The
  // callbacks of transmit requests are executed to allow the
  // caller to release the resource. The callback of receive
  // request are NOT executed. This is because it is most
  // likely that the current user of the UDP IO port is closing
  // itself.
  //
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    if ((RxToken = UdpIo->RecvRequest) != NULL) {
      Status = UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Close then destroy the Udp4 child
    //
    Status = gBS->CloseProtocol (
                    UdpIo->UdpHandle,
                    &gEfiUdp4ProtocolGuid,
                    UdpIo->Image,
                    UdpIo->Controller
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = NetLibDestroyServiceChild (
               UdpIo->Controller,
               UdpIo->Image,
               &gEfiUdp4ServiceBindingProtocolGuid,
               UdpIo->UdpHandle
               );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  } else {
    if ((RxToken = UdpIo->RecvRequest) != NULL) {
      Status = UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
      if (EFI_ERROR (Status)) {
        return Status;
      }
    }

    //
    // Close then destroy the Udp6 child
    //
    Status = gBS->CloseProtocol (
                    UdpIo->UdpHandle,
                    &gEfiUdp6ProtocolGuid,
                    UdpIo->Image,
                    UdpIo->Controller
                    );
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = NetLibDestroyServiceChild (
               UdpIo->Controller,
               UdpIo->Image,
               &gEfiUdp6ServiceBindingProtocolGuid,
               UdpIo->UdpHandle
               );
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  if (!IsListEmpty (&UdpIo->Link)) {
    RemoveEntryList (&UdpIo->Link);
  }

  FreePool (UdpIo);
  return EFI_SUCCESS;
}

/**
  Clean up the UDP_IO without freeing it. The function is called when
  user wants to re-use the UDP_IO later.

  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  It will release all the transmitted datagrams and receive request. It will
  also configure NULL for the UDP instance.

  @param[in]  UdpIo                 The UDP_IO to clean up.

**/
VOID
EFIAPI
UdpIoCleanIo (
  IN  UDP_IO  *UdpIo
  )
{
  UDP_RX_TOKEN  *RxToken;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  //
  // Cancel all the sent datagram and receive requests.
  //
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    if ((RxToken = UdpIo->RecvRequest) != NULL) {
      UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
    }

    UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);
  } else {
    if ((RxToken = UdpIo->RecvRequest) != NULL) {
      UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
    }

    UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, NULL);
  }
}

/**
  Send a packet through the UDP_IO.

  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  The packet will be wrapped in UDP_TX_TOKEN. Function Callback will be called
  when the packet is sent. The optional parameter EndPoint overrides the default
  address pair if specified.

  @param[in]  UdpIo                 The UDP_IO to send the packet through.
  @param[in]  Packet                The packet to send.
  @param[in]  EndPoint              The local and remote access point. Override the
                                    default address pair set during configuration.
  @param[in]  Gateway               The gateway to use.
  @param[in]  CallBack              The function being called when packet is
                                    transmitted or failed.
  @param[in]  Context               The opaque parameter passed to CallBack.

  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource for the packet.
  @retval EFI_SUCCESS           The packet is successfully delivered to UDP  for
                                transmission.

**/
EFI_STATUS
EFIAPI
UdpIoSendDatagram (
  IN  UDP_IO           *UdpIo,
  IN  NET_BUF          *Packet,
  IN  UDP_END_POINT    *EndPoint OPTIONAL,
  IN  EFI_IP_ADDRESS   *Gateway  OPTIONAL,
  IN  UDP_IO_CALLBACK  CallBack,
  IN  VOID             *Context
  )
{
  UDP_TX_TOKEN  *TxToken;
  EFI_STATUS    Status;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  TxToken = UdpIoCreateTxToken (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);

  if (TxToken == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Insert the tx token into SendDatagram list before transmitting it. Remove
  // it from the list if the returned status is not EFI_SUCCESS.
  //
  InsertHeadList (&UdpIo->SentDatagram, &TxToken->Link);

  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    Status = UdpIo->Protocol.Udp4->Transmit (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);
  } else {
    Status = UdpIo->Protocol.Udp6->Transmit (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);
  }

  if (EFI_ERROR (Status)) {
    RemoveEntryList (&TxToken->Link);
    UdpIoFreeTxToken (TxToken);
    return Status;
  }

  return EFI_SUCCESS;
}

/**
  The select function to cancel a single sent datagram.

  @param[in]  Token                 The UDP_TX_TOKEN to test against
  @param[in]  Context               The NET_BUF of the sent datagram

  @retval TRUE              The packet is to be cancelled.
  @retval FALSE             The packet is not to be cancelled.
**/
BOOLEAN
EFIAPI
UdpIoCancelSingleDgram (
  IN UDP_TX_TOKEN  *Token,
  IN VOID          *Context
  )
{
  NET_BUF  *Packet;

  Packet = (NET_BUF *)Context;

  if (Token->Packet == Packet) {
    return TRUE;
  }

  return FALSE;
}

/**
  Cancel a single sent datagram.

  @param[in]  UdpIo                 The UDP_IO to cancel the packet from
  @param[in]  Packet                The packet to cancel

**/
VOID
EFIAPI
UdpIoCancelSentDatagram (
  IN  UDP_IO   *UdpIo,
  IN  NET_BUF  *Packet
  )
{
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);
}

/**
  Issue a receive request to the UDP_IO.

  If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().

  This function is called when upper-layer needs packet from UDP for processing.
  Only one receive request is acceptable at a time so a common usage model is
  to invoke this function inside its Callback function when the former packet
  is processed.

  @param[in]  UdpIo                 The UDP_IO to receive the packet from.
  @param[in]  CallBack              The call back function to execute when the packet
                                    is received.
  @param[in]  Context               The opaque context passed to Callback.
  @param[in]  HeadLen               The length of the upper-layer's protocol header.

  @retval EFI_ALREADY_STARTED   There is already a pending receive request. Only
                                one receive request is supported at a time.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
  @retval EFI_SUCCESS           The receive request is issued successfully.
  @retval EFI_UNSUPPORTED       The UDP version in UDP_IO is not supported.

**/
EFI_STATUS
EFIAPI
UdpIoRecvDatagram (
  IN  UDP_IO           *UdpIo,
  IN  UDP_IO_CALLBACK  CallBack,
  IN  VOID             *Context,
  IN  UINT32           HeadLen
  )
{
  UDP_RX_TOKEN  *RxToken;
  EFI_STATUS    Status;

  ASSERT (
    (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||
    (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION)
    );

  if (UdpIo->RecvRequest != NULL) {
    return EFI_ALREADY_STARTED;
  }

  RxToken = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);

  if (RxToken == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  UdpIo->RecvRequest = RxToken;
  if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {
    Status = UdpIo->Protocol.Udp4->Receive (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);
  } else {
    Status = UdpIo->Protocol.Udp6->Receive (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);
  }

  if (EFI_ERROR (Status)) {
    UdpIo->RecvRequest = NULL;
    UdpIoFreeRxToken (RxToken);
  }

  return Status;
}
