2. Remove the GetTime() call when receiving Udp4/6 packets. Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye, Ting <ting.ye@intel.com> Reviewed-by: Wu, Jiaxin <jiaxin.wu@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15497 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			674 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			674 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The implementation of common functions shared by IP6 driver.
 | 
						|
 | 
						|
  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Ip6Impl.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
 | 
						|
  of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,
 | 
						|
  only the address count is returned.
 | 
						|
 | 
						|
  @param[in]  IpSb              The IP6 service binding instance.
 | 
						|
  @param[out] AddressCount      The number of returned addresses.
 | 
						|
  @param[out] AddressList       The pointer to the array of EFI_IP6_ADDRESS_INFO.
 | 
						|
                                This is an optional parameter.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The address array successfully built.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate the memory for the address info.
 | 
						|
  @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip6BuildEfiAddressList (
 | 
						|
  IN IP6_SERVICE            *IpSb,
 | 
						|
  OUT UINT32                *AddressCount,
 | 
						|
  OUT EFI_IP6_ADDRESS_INFO  **AddressList OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32                Count;
 | 
						|
  LIST_ENTRY            *Entry;
 | 
						|
  EFI_IP6_ADDRESS_INFO  *EfiAddrInfo;
 | 
						|
  IP6_ADDRESS_INFO      *AddrInfo;
 | 
						|
 | 
						|
  if (AddressCount == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IpSb->LinkLocalOk) {
 | 
						|
    Count = 1 + IpSb->DefaultInterface->AddressCount;
 | 
						|
  } else {
 | 
						|
    Count = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  *AddressCount = Count;
 | 
						|
 | 
						|
  if ((AddressList == NULL) || (Count == 0)) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*AddressList == NULL) {
 | 
						|
    *AddressList = AllocatePool (sizeof (EFI_IP6_ADDRESS_INFO) * Count);
 | 
						|
    if (*AddressList == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiAddrInfo = *AddressList;
 | 
						|
 | 
						|
  IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &IpSb->LinkLocalAddr);
 | 
						|
  EfiAddrInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
 | 
						|
 | 
						|
  EfiAddrInfo++;
 | 
						|
  Count = 1;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) {
 | 
						|
    AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
 | 
						|
 | 
						|
    IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &AddrInfo->Address);
 | 
						|
    EfiAddrInfo->PrefixLength = AddrInfo->PrefixLength;
 | 
						|
 | 
						|
    EfiAddrInfo++;
 | 
						|
    Count++;
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (Count == *AddressCount);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Generate the multicast addresses identify the group of all IPv6 nodes or IPv6
 | 
						|
  routers defined in RFC4291.
 | 
						|
 | 
						|
  All Nodes Addresses: FF01::1, FF02::1.
 | 
						|
  All Router Addresses: FF01::2, FF02::2, FF05::2.
 | 
						|
 | 
						|
  @param[in]  Router            If TRUE, generate all routers addresses,
 | 
						|
                                else generate all node addresses.
 | 
						|
  @param[in]  Scope             interface-local(1), link-local(2), or site-local(5)
 | 
						|
  @param[out] Ip6Addr           The generated multicast address.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
 | 
						|
  @retval EFI_SUCCESS           The address is generated.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip6SetToAllNodeMulticast (
 | 
						|
  IN  BOOLEAN          Router,
 | 
						|
  IN  UINT8            Scope,
 | 
						|
  OUT EFI_IPv6_ADDRESS *Ip6Addr
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Ip6Addr == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Router && Scope == IP6_SITE_LOCAL_SCOPE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (Ip6Addr, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
  Ip6Addr->Addr[0] = 0xFF;
 | 
						|
  Ip6Addr->Addr[1] = Scope;
 | 
						|
 | 
						|
  if (!Router) {
 | 
						|
    Ip6Addr->Addr[15] = 0x1;
 | 
						|
  } else {
 | 
						|
    Ip6Addr->Addr[15] = 0x2;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function converts MAC address to 64 bits interface ID according to RFC4291
 | 
						|
  and returns the interface ID. Currently only 48-bit MAC address is supported by
 | 
						|
  this function.
 | 
						|
 | 
						|
  @param[in, out]  IpSb      The IP6 service binding instance.
 | 
						|
 | 
						|
  @retval          NULL      The operation fails.
 | 
						|
  @return                    Pointer to the generated interface ID.
 | 
						|
 | 
						|
**/
 | 
						|
UINT8 *
 | 
						|
Ip6CreateInterfaceID (
 | 
						|
  IN OUT IP6_SERVICE         *IpSb
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                      InterfaceId[8];
 | 
						|
  UINT8                      Byte;
 | 
						|
  EFI_MAC_ADDRESS            *MacAddr;
 | 
						|
  UINT32                     AddrLen;
 | 
						|
 | 
						|
  NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
 | 
						|
 | 
						|
  AddrLen = IpSb->SnpMode.HwAddressSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Currently only IEEE 802 48-bit MACs are supported to create link local address.
 | 
						|
  //
 | 
						|
  if (AddrLen != IP6_MAC_LEN || IpSb->InterfaceIdLen != IP6_IF_ID_LEN) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  MacAddr = &IpSb->SnpMode.CurrentAddress;
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert MAC address to 64 bits interface ID according to Appendix A of RFC4291:
 | 
						|
  // 1. Insert 0xFFFE to the middle
 | 
						|
  // 2. Invert the universal/local bit - bit 6 in network order
 | 
						|
  //
 | 
						|
  CopyMem (InterfaceId, MacAddr, 3);
 | 
						|
  InterfaceId[3] = 0xFF;
 | 
						|
  InterfaceId[4] = 0xFE;
 | 
						|
  CopyMem (&InterfaceId[5], &MacAddr->Addr[3], 3);
 | 
						|
 | 
						|
  Byte = (UINT8) (InterfaceId[0] & IP6_U_BIT);
 | 
						|
  if (Byte == IP6_U_BIT) {
 | 
						|
    InterfaceId[0] &= ~IP6_U_BIT;
 | 
						|
  } else {
 | 
						|
    InterfaceId[0] |= IP6_U_BIT;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Return the interface ID.
 | 
						|
  //
 | 
						|
  return AllocateCopyPool (IpSb->InterfaceIdLen, InterfaceId);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function creates link-local address from interface identifier. The
 | 
						|
  interface identifier is normally created from MAC address. It might be manually
 | 
						|
  configured by administrator if the link-local address created from MAC address
 | 
						|
  is a duplicate address.
 | 
						|
 | 
						|
  @param[in, out]  IpSb      The IP6 service binding instance.
 | 
						|
 | 
						|
  @retval          NULL      If the operation fails.
 | 
						|
  @return                    The generated Link Local address, in network order.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_IPv6_ADDRESS *
 | 
						|
Ip6CreateLinkLocalAddr (
 | 
						|
  IN OUT IP6_SERVICE           *IpSb
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPv6_ADDRESS             *Ip6Addr;
 | 
						|
  EFI_IP6_CONFIG_PROTOCOL      *Ip6Config;
 | 
						|
  UINTN                        DataSize;
 | 
						|
  EFI_IP6_CONFIG_INTERFACE_ID  InterfaceId;
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
 | 
						|
  NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
 | 
						|
 | 
						|
  if (IpSb->InterfaceId != NULL) {
 | 
						|
    FreePool (IpSb->InterfaceId);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the interface id if it is manully configured.
 | 
						|
  //
 | 
						|
  Ip6Config = &IpSb->Ip6ConfigInstance.Ip6Config;
 | 
						|
  DataSize  = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
 | 
						|
  ZeroMem (&InterfaceId, DataSize);
 | 
						|
 | 
						|
  Status = Ip6Config->GetData (
 | 
						|
                        Ip6Config,
 | 
						|
                        Ip6ConfigDataTypeAltInterfaceId,
 | 
						|
                        &DataSize,
 | 
						|
                        &InterfaceId
 | 
						|
                        );
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    //
 | 
						|
    // Since the interface id is not configured, generate the interface id from
 | 
						|
    // MAC address.
 | 
						|
    //
 | 
						|
    IpSb->InterfaceId = Ip6CreateInterfaceID (IpSb);
 | 
						|
    if (IpSb->InterfaceId == NULL) {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (&InterfaceId, IpSb->InterfaceId, IpSb->InterfaceIdLen);
 | 
						|
    //
 | 
						|
    // Record the interface id.
 | 
						|
    //
 | 
						|
    Status = Ip6Config->SetData (
 | 
						|
                          Ip6Config,
 | 
						|
                          Ip6ConfigDataTypeAltInterfaceId,
 | 
						|
                          DataSize,
 | 
						|
                          &InterfaceId
 | 
						|
                          );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreePool (IpSb->InterfaceId);
 | 
						|
      IpSb->InterfaceId = NULL;
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  } else if (!EFI_ERROR (Status)) {
 | 
						|
    IpSb->InterfaceId = AllocateCopyPool (DataSize, &InterfaceId);
 | 
						|
    if (IpSb->InterfaceId == NULL) {
 | 
						|
      return NULL;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append FE80::/64 to the left of IPv6 address then return.
 | 
						|
  //
 | 
						|
  Ip6Addr = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
 | 
						|
  if (Ip6Addr == NULL) {
 | 
						|
    FreePool (IpSb->InterfaceId);
 | 
						|
    IpSb->InterfaceId = NULL;
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (&Ip6Addr->Addr[8], IpSb->InterfaceId, IpSb->InterfaceIdLen);
 | 
						|
  Ip6Addr->Addr[1] = 0x80;
 | 
						|
  Ip6Addr->Addr[0] = 0xFE;
 | 
						|
 | 
						|
  return Ip6Addr;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Compute the solicited-node multicast address for an unicast or anycast address,
 | 
						|
  by taking the low-order 24 bits of this address, and appending those bits to
 | 
						|
  the prefix FF02:0:0:0:0:1:FF00::/104.
 | 
						|
 | 
						|
  @param[in]  Ip6Addr               The unicast or anycast address, in network order.
 | 
						|
  @param[out] MulticastAddr         The generated solicited-node multicast address,
 | 
						|
                                    in network order.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip6CreateSNMulticastAddr (
 | 
						|
  IN EFI_IPv6_ADDRESS  *Ip6Addr,
 | 
						|
  OUT EFI_IPv6_ADDRESS *MulticastAddr
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (Ip6Addr != NULL && MulticastAddr != NULL);
 | 
						|
 | 
						|
  ZeroMem (MulticastAddr, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
  MulticastAddr->Addr[0]  = 0xFF;
 | 
						|
  MulticastAddr->Addr[1]  = 0x02;
 | 
						|
  MulticastAddr->Addr[11] = 0x1;
 | 
						|
  MulticastAddr->Addr[12] = 0xFF;
 | 
						|
 | 
						|
  CopyMem (&MulticastAddr->Addr[13], &Ip6Addr->Addr[13], 3);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert a node IP6_ADDRESS_INFO to an IP6 interface.
 | 
						|
 | 
						|
  @param[in, out]  IpIf             Points to an IP6 interface.
 | 
						|
  @param[in]       AddrInfo         Points to IP6_ADDRESS_INFO
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip6AddAddr (
 | 
						|
  IN OUT IP6_INTERFACE *IpIf,
 | 
						|
  IN IP6_ADDRESS_INFO  *AddrInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  InsertHeadList (&IpIf->AddressList, &AddrInfo->Link);
 | 
						|
  IpIf->AddressCount++;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Callback function which provided by user to remove one node in NetDestroyLinkList process.
 | 
						|
  
 | 
						|
  @param[in]    Entry           The entry to be removed.
 | 
						|
  @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The entry has been removed successfully.
 | 
						|
  @retval Others                Fail to remove the entry.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Ip6DestroyChildEntryByAddr (
 | 
						|
  IN LIST_ENTRY         *Entry,
 | 
						|
  IN VOID               *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  IP6_PROTOCOL                  *Instance;
 | 
						|
  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
 | 
						|
  EFI_IPv6_ADDRESS              *Address;
 | 
						|
  
 | 
						|
  Instance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
 | 
						|
  ServiceBinding = ((IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT*) Context)->ServiceBinding;
 | 
						|
  Address = ((IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT*) Context)->Address;
 | 
						|
 | 
						|
  if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, Address)) {
 | 
						|
    return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy the IP instance if its StationAddress is removed. It is the help function
 | 
						|
  for Ip6RemoveAddr().
 | 
						|
 | 
						|
  @param[in, out]  IpSb             Points to an IP6 service binding instance.
 | 
						|
  @param[in]       Address          The to be removed address
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip6DestroyInstanceByAddress (
 | 
						|
  IN OUT IP6_SERVICE   *IpSb,
 | 
						|
  IN EFI_IPv6_ADDRESS  *Address
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                    *List;
 | 
						|
  IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT  Context;
 | 
						|
 | 
						|
  NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
 | 
						|
 | 
						|
  List = &IpSb->Children;
 | 
						|
  Context.ServiceBinding = &IpSb->ServiceBinding;
 | 
						|
  Context.Address = Address;
 | 
						|
  NetDestroyLinkList (
 | 
						|
    List,
 | 
						|
    Ip6DestroyChildEntryByAddr,
 | 
						|
    &Context,
 | 
						|
    NULL
 | 
						|
    );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.
 | 
						|
 | 
						|
  This function removes the matching IPv6 addresses from the address list and
 | 
						|
  adjusts the address count of the address list. If IpSb is not NULL, this function
 | 
						|
  calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the
 | 
						|
  its solicited-node multicast MAC address from the filter list and sends out
 | 
						|
  a Multicast Listener Done. If Prefix is NULL, all address in the address list
 | 
						|
  will be removed. If Prefix is not NULL, the address that matching the Prefix
 | 
						|
  with PrefixLength in the address list will be removed.
 | 
						|
 | 
						|
  @param[in]       IpSb             NULL or points to IP6 service binding instance.
 | 
						|
  @param[in, out]  AddressList      Address list array.
 | 
						|
  @param[in, out]  AddressCount     The count of addresses in address list array.
 | 
						|
  @param[in]       Prefix           NULL or an IPv6 address prefix.
 | 
						|
  @param[in]       PrefixLength     The length of Prefix.
 | 
						|
 | 
						|
  @retval    EFI_SUCCESS            The operation completed successfully.
 | 
						|
  @retval    EFI_NOT_FOUND          The address matching the Prefix with PrefixLength
 | 
						|
                                    cannot be found in the address list.
 | 
						|
  @retval    EFI_INVALID_PARAMETER  Any input parameter is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip6RemoveAddr (
 | 
						|
  IN IP6_SERVICE       *IpSb          OPTIONAL,
 | 
						|
  IN OUT LIST_ENTRY    *AddressList,
 | 
						|
  IN OUT UINT32        *AddressCount,
 | 
						|
  IN EFI_IPv6_ADDRESS  *Prefix        OPTIONAL,
 | 
						|
  IN UINT8             PrefixLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  LIST_ENTRY           *Entry;
 | 
						|
  LIST_ENTRY           *Next;
 | 
						|
  IP6_ADDRESS_INFO     *AddrInfo;
 | 
						|
  EFI_IPv6_ADDRESS     SnMCastAddr;
 | 
						|
 | 
						|
  if (IsListEmpty (AddressList) || *AddressCount < 1 || PrefixLength > IP6_PREFIX_NUM) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_NOT_FOUND;
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH_SAFE (Entry, Next, AddressList) {
 | 
						|
    AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
 | 
						|
 | 
						|
    if (Prefix == NULL ||
 | 
						|
        (PrefixLength == 128 && EFI_IP6_EQUAL (Prefix, &AddrInfo->Address)) ||
 | 
						|
        (PrefixLength == AddrInfo->PrefixLength && NetIp6IsNetEqual (Prefix, &AddrInfo->Address, PrefixLength))
 | 
						|
        ) {
 | 
						|
      if (IpSb != NULL) {
 | 
						|
        NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
 | 
						|
        Ip6CreateSNMulticastAddr (&AddrInfo->Address, &SnMCastAddr);
 | 
						|
        Ip6LeaveGroup (IpSb, &SnMCastAddr);
 | 
						|
 | 
						|
        //
 | 
						|
        // Destroy any instance who is using the dying address as the source address.
 | 
						|
        //
 | 
						|
        Ip6DestroyInstanceByAddress (IpSb, &AddrInfo->Address);
 | 
						|
      }
 | 
						|
 | 
						|
      RemoveEntryList (Entry);
 | 
						|
      FreePool (AddrInfo);
 | 
						|
      (*AddressCount)--;
 | 
						|
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the incoming Ipv6 address is a solicited-node multicast address.
 | 
						|
 | 
						|
  @param[in]  Ip6               Ip6 address, in network order.
 | 
						|
 | 
						|
  @retval TRUE                  Yes, solicited-node multicast address
 | 
						|
  @retval FALSE                 No
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
Ip6IsSNMulticastAddr (
 | 
						|
  IN EFI_IPv6_ADDRESS *Ip6
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IPv6_ADDRESS    Sn;
 | 
						|
  BOOLEAN             Flag;
 | 
						|
 | 
						|
  Ip6CreateSNMulticastAddr (Ip6, &Sn);
 | 
						|
  Flag = FALSE;
 | 
						|
 | 
						|
  if (CompareMem (Sn.Addr, Ip6->Addr, 13) == 0) {
 | 
						|
    Flag = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return Flag;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the incoming IPv6 address is one of the maintained addresses in
 | 
						|
  the IP6 service binding instance.
 | 
						|
 | 
						|
  @param[in]  IpSb              Points to a IP6 service binding instance.
 | 
						|
  @param[in]  Address           The IP6 address to be checked.
 | 
						|
  @param[out] Interface         If not NULL, output the IP6 interface which
 | 
						|
                                maintains the Address.
 | 
						|
  @param[out] AddressInfo       If not NULL, output the IP6 address information
 | 
						|
                                of the Address.
 | 
						|
 | 
						|
  @retval TRUE                  Yes, it is one of the maintained address.
 | 
						|
  @retval FALSE                 No, it is not one of the maintained address.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
Ip6IsOneOfSetAddress (
 | 
						|
  IN  IP6_SERVICE           *IpSb,
 | 
						|
  IN  EFI_IPv6_ADDRESS      *Address,
 | 
						|
  OUT IP6_INTERFACE         **Interface   OPTIONAL,
 | 
						|
  OUT IP6_ADDRESS_INFO      **AddressInfo OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  LIST_ENTRY                *Entry;
 | 
						|
  LIST_ENTRY                *Entry2;
 | 
						|
  IP6_INTERFACE             *IpIf;
 | 
						|
  IP6_ADDRESS_INFO          *TmpAddressInfo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check link-local address first
 | 
						|
  //
 | 
						|
  if (IpSb->LinkLocalOk && EFI_IP6_EQUAL (&IpSb->LinkLocalAddr, Address)) {
 | 
						|
    if (Interface != NULL) {
 | 
						|
      *Interface = IpSb->DefaultInterface;
 | 
						|
    }
 | 
						|
 | 
						|
    if (AddressInfo != NULL) {
 | 
						|
      *AddressInfo = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
 | 
						|
    IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
 | 
						|
 | 
						|
    NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
 | 
						|
      TmpAddressInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
 | 
						|
 | 
						|
      if (EFI_IP6_EQUAL (&TmpAddressInfo->Address, Address)) {
 | 
						|
        if (Interface != NULL) {
 | 
						|
          *Interface = IpIf;
 | 
						|
        }
 | 
						|
 | 
						|
        if (AddressInfo != NULL) {
 | 
						|
          *AddressInfo = TmpAddressInfo;
 | 
						|
        }
 | 
						|
 | 
						|
        return TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the incoming MAC address is valid.
 | 
						|
 | 
						|
  @param[in]  IpSb              Points to a IP6 service binding instance.
 | 
						|
  @param[in]  LinkAddress       The MAC address.
 | 
						|
 | 
						|
  @retval TRUE                  Yes, it is valid.
 | 
						|
  @retval FALSE                 No, it is not valid.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
Ip6IsValidLinkAddress (
 | 
						|
  IN  IP6_SERVICE      *IpSb,
 | 
						|
  IN  EFI_MAC_ADDRESS  *LinkAddress
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32               Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // TODO: might be updated later to be more acceptable.
 | 
						|
  //
 | 
						|
  for (Index = IpSb->SnpMode.HwAddressSize; Index < sizeof (EFI_MAC_ADDRESS); Index++) {
 | 
						|
    if (LinkAddress->Addr[Index] != 0) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Copy the PrefixLength bits from Src to Dest.
 | 
						|
 | 
						|
  @param[out] Dest              A pointer to the buffer to copy to.
 | 
						|
  @param[in]  Src               A pointer to the buffer to copy from.
 | 
						|
  @param[in]  PrefixLength      The number of bits to copy.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip6CopyAddressByPrefix (
 | 
						|
  OUT EFI_IPv6_ADDRESS *Dest,
 | 
						|
  IN  EFI_IPv6_ADDRESS *Src,
 | 
						|
  IN  UINT8            PrefixLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8 Byte;
 | 
						|
  UINT8 Bit;
 | 
						|
  UINT8 Mask;
 | 
						|
 | 
						|
  ASSERT (Dest != NULL && Src != NULL);
 | 
						|
  ASSERT (PrefixLength < IP6_PREFIX_NUM);
 | 
						|
 | 
						|
  Byte = (UINT8) (PrefixLength / 8);
 | 
						|
  Bit  = (UINT8) (PrefixLength % 8);
 | 
						|
 | 
						|
  ZeroMem (Dest, sizeof (EFI_IPv6_ADDRESS));
 | 
						|
 | 
						|
  CopyMem (Dest, Src, Byte);
 | 
						|
 | 
						|
  if (Bit > 0) {
 | 
						|
    Mask = (UINT8) (0xFF << (8 - Bit));
 | 
						|
    ASSERT (Byte < 16);
 | 
						|
    Dest->Addr[Byte] = (UINT8) (Src->Addr[Byte] & Mask);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the MAC address for a multicast IP address. Call
 | 
						|
  Mnp's McastIpToMac to find the MAC address instead of
 | 
						|
  hard-coding the NIC to be Ethernet.
 | 
						|
 | 
						|
  @param[in]  Mnp                   The Mnp instance to get the MAC address.
 | 
						|
  @param[in]  Multicast             The multicast IP address to translate.
 | 
						|
  @param[out] Mac                   The buffer to hold the translated address.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               The multicast IP successfully
 | 
						|
                                    translated to a multicast MAC address.
 | 
						|
  @retval Other                     The address is not converted because an error occurred.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip6GetMulticastMac (
 | 
						|
  IN  EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
 | 
						|
  IN  EFI_IPv6_ADDRESS             *Multicast,
 | 
						|
  OUT EFI_MAC_ADDRESS              *Mac
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_IP_ADDRESS        EfiIp;
 | 
						|
 | 
						|
  IP6_COPY_ADDRESS (&EfiIp.v6, Multicast);
 | 
						|
 | 
						|
  return Mnp->McastIpToMac (Mnp, TRUE, &EfiIp, Mac);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the multibyte field in IP header's byter order.
 | 
						|
  In spite of its name, it can also be used to convert from
 | 
						|
  host to network byte order.
 | 
						|
 | 
						|
  @param[in, out]  Head                  The IP head to convert.
 | 
						|
 | 
						|
  @return Point to the converted IP head.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_IP6_HEADER *
 | 
						|
Ip6NtohHead (
 | 
						|
  IN OUT EFI_IP6_HEADER *Head
 | 
						|
  )
 | 
						|
{
 | 
						|
  Head->FlowLabelL    = NTOHS (Head->FlowLabelL);
 | 
						|
  Head->PayloadLength = NTOHS (Head->PayloadLength);
 | 
						|
 | 
						|
  return Head;
 | 
						|
}
 | 
						|
 |