4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implementation of Neighbor Discovery support routines.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Ip6Impl.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_MAC_ADDRESS mZeroMacAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Update the ReachableTime in IP6 service binding instance data, in milliseconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] IpSb Points to the IP6_SERVICE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6UpdateReachableTime (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Random;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build a array of EFI_IP6_NEIGHBOR_CACHE to be returned to the caller. The number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync of EFI_IP6_NEIGHBOR_CACHE is also returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The pointer to IP6_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] NeighborCount The number of returned neighbor cache entries.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] NeighborCache The pointer to the array of EFI_IP6_NEIGHBOR_CACHE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The EFI_IP6_NEIGHBOR_CACHE successfully built.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the route table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6BuildEfiNeighborCache (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINT32 *NeighborCount,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT EFI_IP6_NEIGHBOR_CACHE **NeighborCache
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_NEIGHBOR_CACHE *EfiNeighborCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_NEIGHBOR_CACHE *NeighborCacheTmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (NeighborCount != NULL && NeighborCache != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = IpInstance->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Count == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCacheTmp = AllocatePool (Count * sizeof (EFI_IP6_NEIGHBOR_CACHE));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCacheTmp == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *NeighborCount = Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->NeighborTable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiNeighborCache = NeighborCacheTmp + Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiNeighborCache->State = Neighbor->State;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&EfiNeighborCache->Neighbor, &Neighbor->Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&EfiNeighborCache->LinkAddress, &Neighbor->LinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (*NeighborCount == Count);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *NeighborCache = NeighborCacheTmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync of prefix entries is also returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpInstance The pointer to IP6_PROTOCOL instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] PrefixCount The number of returned prefix entries.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] PrefixTable The pointer to the array of PrefixTable.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The prefix table successfully built.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the prefix table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6BuildPrefixTable (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PROTOCOL *IpInstance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT UINT32 *PrefixCount,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT EFI_IP6_ADDRESS_INFO **PrefixTable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_ADDRESS_INFO *EfiPrefix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_ADDRESS_INFO *PrefixTableTmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpInstance, IP6_PROTOCOL_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (PrefixCount != NULL && PrefixTable != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = IpInstance->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Count == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixTableTmp = AllocatePool (Count * sizeof (EFI_IP6_ADDRESS_INFO));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixTableTmp == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *PrefixCount = Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->OnlinkPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiPrefix = PrefixTableTmp + Count;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&EfiPrefix->Address, &PrefixList->Prefix);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiPrefix->PrefixLength = PrefixList->PrefixLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Count++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (*PrefixCount == Count);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *PrefixTable = PrefixTableTmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Allocate and initialize a IP6 prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] OnLinkOrAuto If TRUE, the entry is created for the on link prefix list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, it is created for the autoconfiguration prefix list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ValidLifetime The length of time in seconds that the prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is valid for the purpose of on-link determination.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PreferredLifetime The length of time in seconds that addresses
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync generated from the prefix via stateless address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync autoconfiguration remain preferred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PrefixLength The prefix length of the Prefix.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Prefix The prefix address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if it failed to allocate memory for the prefix node. Otherwise, point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to the created or existing prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_PREFIX_LIST_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreatePrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN OnLinkOrAuto,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ROUTE_ENTRY *RtEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *ListHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *TmpPrefixEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Prefix == NULL || PreferredLifetime > ValidLifetime || PrefixLength >= IP6_PREFIX_NUM) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry = Ip6FindPrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OnLinkOrAuto,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixEntry != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->RefCnt ++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PrefixEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry = AllocatePool (sizeof (IP6_PREFIX_LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->RefCnt = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->ValidLifetime = ValidLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->PreferredLifetime = PreferredLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->PrefixLength = PrefixLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&PrefixEntry->Prefix, Prefix);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ListHead = OnLinkOrAuto ? &IpSb->OnlinkPrefix : &IpSb->AutonomousPrefix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a direct route entry for on-link prefix and insert to route area.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OnLinkOrAuto) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RtEntry = Ip6CreateRouteEntry (Prefix, PrefixLength, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RtEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (PrefixEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RtEntry->Flag = IP6_DIRECT_ROUTE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (&IpSb->RouteTable->RouteArea[PrefixLength], &RtEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RouteTable->TotalNum++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert the prefix entry in the order that a prefix with longer prefix length
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is put ahead in the list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, ListHead) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TmpPrefixEntry = NET_LIST_USER_STRUCT(Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TmpPrefixEntry->PrefixLength < PrefixEntry->PrefixLength) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetListInsertBefore (Entry, &PrefixEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PrefixEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Destory a IP6 prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PrefixEntry The to be destroyed prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] OnLinkOrAuto If TRUE, the entry is removed from on link prefix list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise remove from autoconfiguration prefix list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ImmediateDelete If TRUE, remove the entry directly.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, check the reference count to see whether
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync it should be removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6DestroyPrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_PREFIX_LIST_ENTRY *PrefixEntry,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN OnLinkOrAuto,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN ImmediateDelete
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((!ImmediateDelete) && (PrefixEntry->RefCnt > 0) && ((--PrefixEntry->RefCnt) > 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OnLinkOrAuto) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the direct route for onlink prefix from route table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6DelRoute (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RouteTable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PrefixEntry->Prefix,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixEntry->PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (Status != EFI_NOT_FOUND);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the corresponding addresses generated from this autonomous prefix.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6RemoveAddr (IpSb, &IpIf->AddressList, &IpIf->AddressCount, &PrefixEntry->Prefix, PrefixEntry->PrefixLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&PrefixEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (PrefixEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search the list array to find an IP6 prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] OnLinkOrAuto If TRUE, the search the link prefix list,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise search the autoconfiguration prefix list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PrefixLength The prefix length of the Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Prefix The prefix address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if cannot find the IP6 prefix list entry. Otherwise, return the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pointer to the IP6 prefix list entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_PREFIX_LIST_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindPrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN OnLinkOrAuto,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *ListHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Prefix != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OnLinkOrAuto) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ListHead = &IpSb->OnlinkPrefix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ListHead = &IpSb->AutonomousPrefix;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, ListHead) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixLength != 255) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Perform exactly prefix match.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixList->PrefixLength == PrefixLength &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixLength)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Perform the longest prefix match. The list is already sorted with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the longest length prefix put at the head of the list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NetIp6IsNetEqual (&PrefixList->Prefix, Prefix, PrefixList->PrefixLength)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Release the resource in the prefix list table, and destroy the list entry and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync corresponding addresses or route entries.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ListHead The list entry head of the prefix list table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CleanPrefixListTable (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN LIST_ENTRY *ListHead
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN OnLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OnLink = (BOOLEAN) (ListHead == &IpSb->OnlinkPrefix);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (ListHead)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = NET_LIST_HEAD (ListHead, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Callback function when address resolution is finished. It will cancel
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync all the queued frames if the address resolution failed, or transmit them
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if the request succeeded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The context of the callback, a pointer to IP6_NEIGHBOR_ENTRY.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnArpResolved (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *ArpQue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_TX_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ArpQue = (IP6_NEIGHBOR_ENTRY *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((ArpQue == NULL) || (ArpQue->Interface == NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = ArpQue->Interface->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((IpSb == NULL) || (IpSb->Signature != IP6_SERVICE_SIGNATURE)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ARP resolve failed for some reason. Release all the frame
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and ARP queue itself. Ip6FreeArpQue will call the frame's
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // owner back.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NET_MAC_EQUAL (&ArpQue->LinkAddress, &mZeroMacAddress, IpSb->SnpMode.HwAddressSize)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeNeighborEntry (IpSb, ArpQue, FALSE, TRUE, EFI_NO_MAPPING, NULL, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ARP resolve succeeded, Transmit all the frame.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sent = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Token->DstMac, &ArpQue->LinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert the tx token before transmitting it via MNP as the FrameSentDpc
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // may be called before Mnp->Transmit returns which will remove this tx
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // token from the SentFrames list. Remove it from the list if the returned
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // FrameSentDpc won't be queued.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&ArpQue->Interface->SentFrames, &Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IpSb->Mnp->Transmit (IpSb->Mnp, &Token->MnpToken);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Token->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token->CallBack (Token->Packet, Status, 0, Token->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeLinkTxToken (Token);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sent = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the ArpQue only but not the whole neighbor entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeNeighborEntry (IpSb, ArpQue, FALSE, FALSE, EFI_SUCCESS, NULL, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Sent && (ArpQue->State == EfiNeighborStale)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ArpQue->State = EfiNeighborDelay;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ArpQue->Ticks = (UINT32) IP6_GET_TICKS (IP6_DELAY_FIRST_PROBE_TIME);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Allocate and initialize an IP6 neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] CallBack The callback function to be called when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync address resolution is finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ip6Address Points to the IPv6 address of the neighbor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] LinkAddress Points to the MAC address of the neighbor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ignored if NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if failed to allocate memory for the neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, point to the created neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_NEIGHBOR_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreateNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_ARP_CALLBACK CallBack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Ip6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *LinkAddress OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Ip6Address!= NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = AllocateZeroPool (sizeof (IP6_NEIGHBOR_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->RefCnt = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->IsRouter = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->ArpFree = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Dynamic = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->State = EfiNeighborInComplete;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Transmit = IP6_MAX_MULTICAST_SOLICIT + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->CallBack = CallBack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Interface = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Entry->Frames);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Entry->Neighbor, Ip6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LinkAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, LinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Entry->LinkAddress, &mZeroMacAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (&IpSb->NeighborTable, &Entry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If corresponding default router entry exists, establish the relationship.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6FindDefaultRouter (IpSb, Ip6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter->NeighborCache = Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search a IP6 neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ip6Address Points to the IPv6 address of the neighbor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if it failed to find the matching neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, point to the found neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_NEIGHBOR_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Ip6Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Ip6Address != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (Ip6Address, &Neighbor->Neighbor)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (&IpSb->NeighborTable, Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free a IP6 neighbor cache entry and remove all the frames on the address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync resolution queue that pass the FrameToCancel. That is, either FrameToCancel
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is NULL, or it returns true for the frame.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] NeighborCache The to be free neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SendIcmpError If TRUE, send out ICMP error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] FullFree If TRUE, remove the neighbor cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise remove the pending frames.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IoStatus The status returned to the cancelled frames'
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync callback function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] FrameToCancel Function to select which frame to cancel.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is an optional parameter that may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context Opaque parameter to the FrameToCancel.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ignored if FrameToCancel is NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The input parameter is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The operation finished successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FreeNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_NEIGHBOR_ENTRY *NeighborCache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN SendIcmpError,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN FullFree,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_STATUS IoStatus,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_TX_TOKEN *TxToken;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If FrameToCancel fails, the token will not be released.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // To avoid the memory leak, stop this usage model.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FullFree && FrameToCancel != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &NeighborCache->Frames) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TxToken = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SendIcmpError && !IP6_IS_MULTICAST (&TxToken->Packet->Ip.Ip6->DestinationAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SendIcmpError (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TxToken->Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &TxToken->Packet->Ip.Ip6->SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ICMP_V6_DEST_UNREACHABLE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ICMP_V6_ADDR_UNREACHABLE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((FrameToCancel == NULL) || FrameToCancel (TxToken, Context)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TxToken->CallBack (TxToken->Packet, IoStatus, 0, TxToken->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeLinkTxToken (TxToken);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->ArpFree && IsListEmpty (&NeighborCache->Frames)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&NeighborCache->ArpList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->ArpFree = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FullFree) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6FindDefaultRouter (IpSb, &NeighborCache->Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&NeighborCache->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (NeighborCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Allocate and initialize an IP6 default router entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ip6Address The IPv6 address of the default router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] RouterLifetime The lifetime associated with the default
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync router, in units of seconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if it failed to allocate memory for the default router node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, point to the created default router node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_DEFAULT_ROUTER *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CreateDefaultRouter (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Ip6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 RouterLifetime
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ROUTE_ENTRY *RtEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Ip6Address != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = AllocatePool (sizeof (IP6_DEFAULT_ROUTER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->RefCnt = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Lifetime = RouterLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->NeighborCache = Ip6FindNeighborEntry (IpSb, Ip6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Entry->Router, Ip6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add a default route into route table with both Destination and PrefixLength set to zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RtEntry = Ip6CreateRouteEntry (NULL, 0, Ip6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RtEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (&IpSb->RouteTable->RouteArea[0], &RtEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RouteTable->TotalNum++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&IpSb->DefaultRouterList, &Entry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Destroy an IP6 default router entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DefaultRouter The to be destroyed IP6_DEFAULT_ROUTER.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6DestroyDefaultRouter (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_DEFAULT_ROUTER *DefaultRouter
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&DefaultRouter->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the Destination Cache - all entries using the time-out router as next-hop
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // should perform next-hop determination again.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6DelRoute (IpSb->RouteTable, NULL, 0, &DefaultRouter->Router);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (Status != EFI_NOT_FOUND);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Clean an IP6 default router list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6CleanDefaultRouterList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (&IpSb->DefaultRouterList)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = NET_LIST_HEAD (&IpSb->DefaultRouterList, IP6_DEFAULT_ROUTER, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search a default router node from an IP6 default router list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Ip6Address The IPv6 address of the to be searched default router node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if it failed to find the matching default router node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, point to the found default router node.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_DEFAULT_ROUTER *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindDefaultRouter (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Ip6Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Ip6Address != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->DefaultRouterList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (Ip6Address, &DefaultRouter->Router)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The function to be called after DAD (Duplicate Address Detection) is performed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IsDadPassed If TRUE, the DAD operation succeed. Otherwise, the DAD operation failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpIf Points to the IP6_INTERFACE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DadEntry The DAD entry which already performed DAD.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6OnDADFinished (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN IsDadPassed,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *IpIf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_DAD_ENTRY *DadEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ADDRESS_INFO *AddrInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DHCP6_PROTOCOL *Dhcp6;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 OptBuf[4];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DHCP6_PACKET_OPTION *Oro;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_DHCP6_RETRANSMISSION InfoReqReXmit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = IpIf->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddrInfo = DadEntry->AddressInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDadPassed) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DAD succeed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (!IpSb->LinkLocalOk);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&IpSb->LinkLocalAddr, &AddrInfo->Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->LinkLocalOk = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf->Configured = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether DHCP6 need to be started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dhcp6 = IpSb->Ip6ConfigInstance.Dhcp6;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->Dhcp6NeedStart) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dhcp6->Start (Dhcp6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->Dhcp6NeedStart = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->Dhcp6NeedInfoRequest) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the exta options to send. Here we only want the option request option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // with DNS SERVERS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oro = (EFI_DHCP6_PACKET_OPTION *) OptBuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oro->OpCode = HTONS (IP6_CONFIG_DHCP6_OPTION_ORO);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oro->OpLen = HTONS (2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *((UINT16 *) &Oro->Data[0]) = HTONS (IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InfoReqReXmit.Irt = 4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InfoReqReXmit.Mrc = 64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InfoReqReXmit.Mrt = 60;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InfoReqReXmit.Mrd = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dhcp6->InfoRequest (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dhcp6,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oro,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &InfoReqReXmit,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->Ip6ConfigInstance.Dhcp6Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6ConfigOnDhcp6Reply,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->Ip6ConfigInstance
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add an on-link prefix for link-local address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CreatePrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT32) IP6_INFINIT_LIFETIME,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT32) IP6_INFINIT_LIFETIME,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_LINK_LOCAL_PREFIX_LENGTH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->LinkLocalAddr
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Global scope unicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6AddAddr (IpIf, AddrInfo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add an on-link prefix for this address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CreatePrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddrInfo->ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddrInfo->PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddrInfo->PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &AddrInfo->Address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf->Configured = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Leave the group we joined before.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6LeaveGroup (IpSb, &DadEntry->Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DadEntry->Callback != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DadEntry->Callback (IsDadPassed, &AddrInfo->Address, DadEntry->Context);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDadPassed && NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (AddrInfo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&DadEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DadEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable IP operation since link-local address is a duplicate address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->LinkLocalDadFail = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->Mnp->Configure (IpSb->Mnp, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDadPassed || NetIp6IsLinkLocalAddr (&AddrInfo->Address)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the AddressInfo we hold if DAD fails or it is a link-local address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (AddrInfo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&DadEntry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DadEntry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a DAD (Duplicate Address Detection) entry and queue it to be performed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpIf Points to the IP6_INTERFACE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] AddressInfo The address information which needs DAD performed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Callback The callback routine that will be called after DAD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is performed. This is an optional parameter that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The opaque parameter for a DAD callback routine.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This is an optional parameter that may be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The DAD entry was created and queued.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6InitDADProcess (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *IpIf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_ADDRESS_INFO *AddressInfo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_DAD_CALLBACK Callback OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS *DadXmits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 MaxDelayTick;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (AddressInfo != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = IpIf->Service;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DadXmits = &IpSb->Ip6ConfigInstance.DadXmits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate the resources and insert info
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = AllocatePool (sizeof (IP6_DAD_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Map the incoming unicast address to solicited-node multicast address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CreateSNMulticastAddr (&AddressInfo->Address, &Entry->Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Join in the solicited-node multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6JoinGroup (IpSb, IpIf, &Entry->Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Signature = IP6_DAD_ENTRY_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->MaxTransmit = DadXmits->DupAddrDetectTransmits;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Transmit = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Receive = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->AddressInfo = AddressInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Callback = Callback;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry->Context = Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&IpIf->DupAddrDetectList, &Entry->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry->MaxTransmit == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DAD is disabled on this interface, immediately mark this DAD successful.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnDADFinished (TRUE, IpIf, Entry);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search IP6_DAD_ENTRY from the Duplicate Address Detection List.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The pointer to the IP6_SERVICE instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Target The address information which needs DAD performed .
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Interface If not NULL, output the IP6 interface that configures
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the tentative address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return NULL if failed to find the matching DAD entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Otherwise, point to the found DAD entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIP6_DAD_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6FindDADEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *Target,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT IP6_INTERFACE **Interface OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *DupAddrDetect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ADDRESS_INFO *AddrInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry2, &IpIf->DupAddrDetectList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AddrInfo = DupAddrDetect->AddressInfo;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_IP6_EQUAL (&AddrInfo->Address, Target)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Interface != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Interface = IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return DupAddrDetect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate router solicit message and send it out to Destination Address or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync All Router Link Local scope multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service to send the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Interface If not NULL, points to the IP6 interface to send
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SourceAddress If not NULL, the source address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DestinationAddress If not NULL, the destination address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SourceLinkAddress If not NULL, the MAC address of the source.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync A source link-layer address option will be appended
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The router solicit message was successfully sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendRouterSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_INTERFACE *Interface OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *DestinationAddress OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_HEADER Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD *IcmpHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION *LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PayloadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf = Interface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpIf == NULL && IpSb->DefaultInterface != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf = IpSb->DefaultInterface;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the packet to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) sizeof (IP6_ICMP_INFORMATION_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceLinkAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen += sizeof (IP6_ETHER_ADDR_OPTION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the basic IPv6 header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelL = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelH = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.PayloadLength = HTONS (PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.NextHeader = IP6_ICMP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.HopLimit = IP6_HOP_LIMIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DestinationAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SetToAllNodeMulticast (TRUE, IP6_LINK_LOCAL_SCOPE, &Head.DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in the ICMP header, and Source link-layer address if contained.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead = (IP6_ICMP_INFORMATION_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IcmpHead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Type = ICMP_V6_ROUTER_SOLICIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Code = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceLinkAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = (IP6_ETHER_ADDR_OPTION *) NetbufAllocSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_ETHER_ADDR_OPTION),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (LinkLayerOption != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Type = Ip6OptionEtherSource;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Length = (UINT8) sizeof (IP6_ETHER_ADDR_OPTION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6Output (IpSb, IpIf, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate a Neighbor Advertisement message and send it out to Destination Address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service to send the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SourceAddress The source address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DestinationAddress The destination address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetIp6Address The target address field in the Neighbor Solicitation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync message that prompted this advertisement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetLinkAddress The MAC address for the target, i.e. the sender
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync of the advertisement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IsRouter If TRUE, indicates the sender is a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Override If TRUE, indicates the advertisement should override
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync an existing cache entry and update the MAC address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Solicited If TRUE, indicates the advertisement was sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync in response to a Neighbor Solicitation from
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the Destination address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendNeighborAdvertise (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *DestinationAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *TargetIp6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *TargetLinkAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN IsRouter,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Override,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Solicited
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_HEADER Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD *IcmpHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION *LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *Target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PayloadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Neighbor Advertisement message must include a Target link-layer address option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // when responding to multicast solicitation and should include such option when
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // responding to unicast solicitation. It also must include such option as unsolicited
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // advertisement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (DestinationAddress != NULL && TargetIp6Address != NULL && TargetLinkAddress != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) (sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS) + sizeof (IP6_ETHER_ADDR_OPTION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the packet to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the basic IPv6 header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelL = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelH = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.PayloadLength = HTONS (PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.NextHeader = IP6_ICMP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.HopLimit = IP6_HOP_LIMIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in the ICMP header, Target address, and Target link-layer address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the Router flag, Solicited flag and Override flag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead = (IP6_ICMP_INFORMATION_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IcmpHead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_ADVERTISE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Code = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Fourth |= IP6_IS_ROUTER_FLAG;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Solicited) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Fourth |= IP6_SOLICITED_FLAG;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Override) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Fourth |= IP6_OVERRIDE_FLAG;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Target = (EFI_IPv6_ADDRESS *) NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Target != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (Target, TargetIp6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = (IP6_ETHER_ADDR_OPTION *) NetbufAllocSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_ETHER_ADDR_OPTION),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (LinkLayerOption != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Type = Ip6OptionEtherTarget;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Length = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (LinkLayerOption->EtherAddr, TargetLinkAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6Output (IpSb, NULL, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate the Neighbor Solicitation message and send it to the Destination Address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service to send the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SourceAddress The source address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DestinationAddress The destination address of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetIp6Address The IP address of the target of the solicitation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It must not be a multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] SourceLinkAddress The MAC address for the sender. If not NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync a source link-layer address option will be appended
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync to the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The Neighbor Advertise message was successfully sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6SendNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *DestinationAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *TargetIp6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *SourceLinkAddress OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IP6_HEADER Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD *IcmpHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION *LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *Target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsDAD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 PayloadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check input parameters
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DestinationAddress == NULL || TargetIp6Address == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsDAD = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceAddress == NULL || (SourceAddress != NULL && NetIp6IsUnspecifiedAddr (SourceAddress))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsDAD = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Neighbor Solicitation message should include a source link-layer address option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if the solicitation is not sent by performing DAD - Duplicate Address Detection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Otherwise must not include it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) (sizeof (IP6_ICMP_INFORMATION_HEAD) + sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDAD) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceLinkAddress == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PayloadLen = (UINT16) (PayloadLen + sizeof (IP6_ETHER_ADDR_OPTION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the packet to be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NetbufAlloc (sizeof (EFI_IP6_HEADER) + (UINT32) PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the basic IPv6 header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelL = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.FlowLabelH = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.PayloadLength = HTONS (PayloadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.NextHeader = IP6_ICMP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head.HopLimit = IP6_HOP_LIMIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SourceAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.SourceAddress, SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Head.SourceAddress, sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Head.DestinationAddress, DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Packet, sizeof (EFI_IP6_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in the ICMP header, Target address, and Source link-layer address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead = (IP6_ICMP_INFORMATION_HEAD *) NetbufAllocSpace (Packet, sizeof (IP6_ICMP_INFORMATION_HEAD), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IcmpHead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (IcmpHead, sizeof (IP6_ICMP_INFORMATION_HEAD));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Type = ICMP_V6_NEIGHBOR_SOLICIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpHead->Head.Code = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Target = (EFI_IPv6_ADDRESS *) NetbufAllocSpace (Packet, sizeof (EFI_IPv6_ADDRESS), FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Target != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (Target, TargetIp6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDAD) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill in the source link-layer address option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = (IP6_ETHER_ADDR_OPTION *) NetbufAllocSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_ETHER_ADDR_OPTION),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (LinkLayerOption != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Type = Ip6OptionEtherSource;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption->Length = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (LinkLayerOption->EtherAddr, SourceLinkAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a Neighbor Cache entry in the INCOMPLETE state when performing
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // address resolution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDAD && Ip6IsSNMulticastAddr (DestinationAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Neighbor != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Ip6Output (IpSb, IpSb->DefaultInterface, NULL, Packet, &Head, NULL, 0, Ip6SysPacketSent, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the Neighbor Solicitation message. The message may be sent for Duplicate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Address Detection or Address Resolution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service that received the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the message with IP head removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The packet processed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The packet is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to process the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD Icmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsDAD;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsUnicast;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsMaintained;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *DupAddrDetect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Solicited;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN UpdateCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Dest;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Provided;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *MacAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Perform Message Validation:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP Hop Limit field has a value of 255, i.e., the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // could not possibly have been forwarded by a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP Code is 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Target Address is not a multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != IP6_HOP_LIMIT || Icmp.Head.Code != 0 || !NetIp6IsValidUnicast (&Target)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP length is 24 or more octets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->PayloadLength < IP6_ND_LENGTH) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = (UINT16) (Head->PayloadLength - IP6_ND_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Option != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All included options should have a length that is greater than zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsNDOptionValid (Option, OptionLen)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsDAD = NetIp6IsUnspecifiedAddr (&Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsUnicast = (BOOLEAN) !Ip6IsSNMulticastAddr (&Head->DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsMaintained = Ip6IsOneOfSetAddress (IpSb, &Target, &IpIf, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Provided = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ND_LENGTH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_ETHER_ADDR_OPTION),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) &LinkLayerOption
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The solicitation for neighbor discovery should include a source link-layer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // address option. If the option is not recognized, silently ignore it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LinkLayerOption.Type == Ip6OptionEtherSource) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDAD) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the IP source address is the unspecified address, the source
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // link-layer address option must not be included in the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Provided = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the IP source address is the unspecified address, the IP
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // destination address is a solicited-node multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDAD && IsUnicast) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the target address is tentative, and the source address is a unicast address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the solicitation's sender is performing address resolution on the target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the solicitation should be silently ignored.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDAD && !IsMaintained) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If received unicast neighbor solicitation but destination is not this node,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // drop the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsUnicast && !IsMaintained) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In DAD, when target address is a tentative address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // process the received neighbor solicitation message but not send out response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDAD && !IsMaintained) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DupAddrDetect != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DupAddrDetect->Transmit == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The NS is from another node to performing DAD on the same address since
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // we haven't send out any NS yet. Fail DAD for the tentative address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_ICMP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the MAC address of the incoming packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->RecvRequest.MnpToken.Packet.RxData == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MacAddress = IpSb->RecvRequest.MnpToken.Packet.RxData->SourceAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (MacAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareMem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MacAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->SnpMode.CurrentAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->SnpMode.HwAddressSize
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The NS is from another node to performing DAD on the same address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fail DAD for the tentative address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_ICMP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The below layer loopback the NS we sent. Record it and wait for more.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect->Receive++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the solicitation does not contain a link-layer address, DO NOT create or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // update the neighbor cache entries.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Provided) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdateCache = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &Head->SourceAddress, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdateCache = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdateCache = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UpdateCache) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send queued packets if exist.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->CallBack ((VOID *) Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sends a Neighbor Advertisement as response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the Router flag to zero since the node is a host.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the source address of the solicitation is unspeicifed, and target address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is one of the maintained address, reply a unsolicited multicast advertisement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsDAD && IsMaintained) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Solicited = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &Dest);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Solicited = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&Dest, &Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendNeighborAdvertise (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Target,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Dest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Target,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->SnpMode.CurrentAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Solicited
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the Neighbor Advertisement message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service that received the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the message with IP head removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The packet processed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The packet is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ICMP_ERROR The packet indicates that DAD is failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to process the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessNeighborAdvertise (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD Icmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Provided;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Compare;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Solicited;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Override;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *DupAddrDetect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, sizeof (Icmp), sizeof (Target), Target.Addr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the incoming Neighbor Advertisement
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP Hop Limit field has a value of 255, i.e., the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // could not possibly have been forwarded by a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP Code is 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Target Address is not a multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != IP6_HOP_LIMIT || Icmp.Head.Code != 0 || !NetIp6IsValidUnicast (&Target)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP length is 24 or more octets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Provided = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->PayloadLength < IP6_ND_LENGTH) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = (UINT16) (Head->PayloadLength - IP6_ND_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option = NetbufGetByte (Packet, IP6_ND_LENGTH, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Option != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All included options should have a length that is greater than zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsNDOptionValid (Option, OptionLen)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the IP destination address is a multicast address, Solicited Flag is ZERO.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Solicited = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Icmp.Fourth & IP6_SOLICITED_FLAG) == IP6_SOLICITED_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Solicited = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IP6_IS_MULTICAST (&Head->DestinationAddress) && Solicited) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DAD - Check whether the Target is one of our tentative address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DupAddrDetect != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DAD fails, some other node is using this address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_ICMP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Search the Neighbor Cache for the target's entry. If no entry exists,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the advertisement should be silently discarded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6FindNeighborEntry (IpSb, &Target);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get IsRouter Flag and Override Flag
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsRouter = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Icmp.Fourth & IP6_IS_ROUTER_FLAG) == IP6_IS_ROUTER_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsRouter = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Icmp.Fourth & IP6_OVERRIDE_FLAG) == IP6_OVERRIDE_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Override = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether link layer option is included.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen >= sizeof (IP6_ETHER_ADDR_OPTION)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ND_LENGTH,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (IP6_ETHER_ADDR_OPTION),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) &LinkLayerOption
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LinkLayerOption.Type == Ip6OptionEtherTarget) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Provided = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compare = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Provided) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compare = CompareMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Neighbor->IsRouter && IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter->NeighborCache = Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor->State == EfiNeighborInComplete) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the target's Neighbor Cache entry is in INCOMPLETE state and no
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Target Link-Layer address option is included while link layer has
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // address, the message should be silently discarded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Provided) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the Neighbor Cache
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Solicited) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborReachable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send any packets queued for the neighbor awaiting address resolution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->CallBack ((VOID *) Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->IsRouter = IsRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Override && Compare != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // When the Override Flag is clear and supplied link-layer address differs from
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // that in the cache, if the state of the entry is not REACHABLE, ignore the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // message. Otherwise set it to STALE but do not update the entry in any
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // other way.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor->State == EfiNeighborReachable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Compare != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Neighbor->LinkAddress.Addr, LinkLayerOption.EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the entry's state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Solicited) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborReachable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = IP6_GET_TICKS (IpSb->ReachableTime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Compare != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // When IsRouter is changed from TRUE to FALSE, remove the router from the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Default Router List and remove the Destination Cache entries for all destinations
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // using the neighbor as a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor->IsRouter && !IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6FindDefaultRouter (IpSb, &Target);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->IsRouter = IsRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor->State == EfiNeighborReachable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->CallBack ((VOID *) Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the Router Advertisement message according to RFC4861.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP service that received the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the message.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the message with the IP head removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The packet processed successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The packet is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Insufficient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to process the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessRouterAdvertise (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD Icmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 ReachableTime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 RetransTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 RouterLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Type;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Length;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Fourth;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 CurHopLimit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Mflag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Oflag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *NeighborCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MAC_ADDRESS LinkLayerAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_MTU_OPTION MTUOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_INFO_OPTION PrefixOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN OnLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Autonomous;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS StatelessAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IpSb->Ip6ConfigInstance.Policy != Ip6ConfigPolicyAutomatic) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Skip the process below as it's not required under the current policy.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, 0, sizeof (Icmp), (UINT8 *) &Icmp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the incoming Router Advertisement
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP source address must be a link-local address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP Hop Limit field has a value of 255, i.e. the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // could not possibly have been forwarded by a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP Code is 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP length (derived from the IP length) is 16 or more octets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != IP6_HOP_LIMIT || Icmp.Head.Code != 0 ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->PayloadLength < IP6_RA_LENGTH) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All included options have a length that is greater than zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = (UINT16) (Head->PayloadLength - IP6_RA_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option = NetbufGetByte (Packet, IP6_RA_LENGTH, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Option != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsNDOptionValid (Option, OptionLen)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process Fourth field.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In Router Advertisement, Fourth is composed of CurHopLimit (8bit), M flag, O flag,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and Router Lifetime (16 bit).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fourth = NTOHL (Icmp.Fourth);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&RouterLifetime, &Fourth, sizeof (UINT16));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the source address already in the default router list, update it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Otherwise create a new entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A Lifetime of zero indicates that the router is not a default router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6FindDefaultRouter (IpSb, &Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouterLifetime != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = Ip6CreateDefaultRouter (IpSb, &Head->SourceAddress, RouterLifetime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouterLifetime != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter->Lifetime = RouterLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the corresponding neighbor cache entry here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter->NeighborCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter->NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the address is in the host's default router list and the router lifetime is zero,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // immediately time-out the entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CurHopLimit = *((UINT8 *) &Fourth + 3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CurHopLimit != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->CurHopLimit = CurHopLimit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mflag = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oflag = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((*((UINT8 *) &Fourth + 2) & IP6_M_ADDR_CONFIG_FLAG) == IP6_M_ADDR_CONFIG_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mflag = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((*((UINT8 *) &Fourth + 2) & IP6_O_CONFIG_FLAG) == IP6_O_CONFIG_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Oflag = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Mflag || Oflag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use Ip6Config to get available addresses or other configuration from DHCP.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6ConfigStartStatefulAutoConfig (&IpSb->Ip6ConfigInstance, Oflag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process Reachable Time and Retrans Timer fields.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, sizeof (Icmp), sizeof (UINT32), (UINT8 *) &ReachableTime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, sizeof (Icmp) + sizeof (UINT32), sizeof (UINT32), (UINT8 *) &RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ReachableTime = NTOHL (ReachableTime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RetransTimer = NTOHL (RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ReachableTime != 0 && ReachableTime != IpSb->BaseReachableTime) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If new value is not unspecified and differs from the previous one, record it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in BaseReachableTime and recompute a ReachableTime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->BaseReachableTime = ReachableTime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6UpdateReachableTime (IpSb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RetransTimer != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RetransTimer = RetransTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // IsRouter flag must be set to TRUE if corresponding neighbor cache entry exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->SourceAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->IsRouter = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If an valid router advertisment is received, stops router solicitation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RouterAdvertiseReceived = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The only defined options that may appear are the Source
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Link-Layer Address, Prefix information and MTU options.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All included options have a length that is greater than zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = 16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Offset < Head->PayloadLength) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, Offset, sizeof (UINT8), &Type);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Type) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case Ip6OptionEtherSource:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the neighbor cache
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, Offset, sizeof (IP6_ETHER_ADDR_OPTION), (UINT8 *) &LinkLayerOption);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LinkLayerOption.Length <= 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = Ip6CreateNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnArpResolved,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head->SourceAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &LinkLayerAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->IsRouter = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Result = CompareMem (&LinkLayerAddress, &NeighborCache->LinkAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the link-local address is the same as that already in the cache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the cache entry's state remains unchanged. Otherwise update the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // reachability state to STALE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&NeighborCache->LinkAddress, &LinkLayerAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->State == EfiNeighborInComplete) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send queued packets if exist.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->CallBack ((VOID *) NeighborCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINT16) (Offset + (UINT16) LinkLayerOption.Length * 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case Ip6OptionPrefixInfo:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, Offset, sizeof (IP6_PREFIX_INFO_OPTION), (UINT8 *) &PrefixOption);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixOption.Length != 4) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.ValidLifetime = NTOHL (PrefixOption.ValidLifetime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PreferredLifetime = NTOHL (PrefixOption.PreferredLifetime);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get L and A flag, recorded in the lower 2 bits of Reserved1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OnLink = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption.Reserved1 & IP6_ON_LINK_FLAG) == IP6_ON_LINK_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OnLink = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Autonomous = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption.Reserved1 & IP6_AUTO_CONFIG_FLAG) == IP6_AUTO_CONFIG_FLAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Autonomous = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the prefix is the link-local prefix, silently ignore the prefix option.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixOption.PrefixLength == IP6_LINK_LOCAL_PREFIX_LENGTH &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetIp6IsLinkLocalAddr (&PrefixOption.Prefix)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset += sizeof (IP6_PREFIX_INFO_OPTION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do following if on-link flag is set according to RFC4861.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OnLink) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = Ip6FindPrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PrefixOption.Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a new entry for the prefix, if the ValidLifetime is zero,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // silently ignore the prefix option.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixList == NULL && PrefixOption.ValidLifetime != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = Ip6CreatePrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PrefixOption.Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (PrefixList != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixOption.ValidLifetime != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the prefix exists and incoming ValidLifetime is zero, immediately
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // remove the prefix.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyPrefixListEntry (IpSb, PrefixList, OnLink, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do following if Autonomous flag is set according to RFC4862.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Autonomous && PrefixOption.PreferredLifetime <= PrefixOption.ValidLifetime) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = Ip6FindPrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PrefixOption.Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a new entry for the prefix, and form an address by prefix + interface id
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the sum of the prefix length and interface identifier length
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // does not equal 128 bits, the Prefix Information option MUST be ignored.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixList == NULL &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.ValidLifetime != 0 &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength + IpSb->InterfaceIdLen * 8 == 128
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Form the address in network order.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&StatelessAddress, &PrefixOption.Prefix, sizeof (UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&StatelessAddress.Addr[8], IpSb->InterfaceId, sizeof (UINT64));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the address is not yet in the assigned address list, adds it into.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsOneOfSetAddress (IpSb, &StatelessAddress, NULL, NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // And also not in the DAD process, check its uniqeness firstly.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Ip6FindDADEntry (IpSb, &StatelessAddress, NULL) == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SetAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->DefaultInterface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &StatelessAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Adds the prefix option to stateless prefix option list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList = Ip6CreatePrefixListEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.ValidLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PreferredLifetime,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption.PrefixLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &PrefixOption.Prefix
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (PrefixList != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reset the preferred lifetime of the address if the advertised prefix exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Perform specific action to valid lifetime together.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList->PreferredLifetime = PrefixOption.PreferredLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption.ValidLifetime > 7200) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (PrefixOption.ValidLifetime > PrefixList->ValidLifetime)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the received Valid Lifetime is greater than 2 hours or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // greater than RemainingLifetime, set the valid lifetime of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // corresponding address to the advertised Valid Lifetime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList->ValidLifetime = PrefixOption.ValidLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (PrefixList->ValidLifetime <= 7200) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If RemainingLifetime is less than or equls to 2 hours, ignore the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Prefix Information option with regards to the valid lifetime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // TODO: If this option has been authenticated, set the valid lifetime.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Otherwise, reset the valid lifetime of the corresponding
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // address to 2 hours.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixList->ValidLifetime = 7200;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset += sizeof (IP6_PREFIX_INFO_OPTION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case Ip6OptionMtu:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, Offset, sizeof (IP6_MTU_OPTION), (UINT8 *) &MTUOption);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (MTUOption.Length != 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use IPv6 minimum link MTU 1280 bytes as the maximum packet size in order
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // to omit implementation of Path MTU Discovery. Thus ignore the MTU option
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in Router Advertisement.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset += sizeof (IP6_MTU_OPTION);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Silently ignore unrecognized options
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (Packet, Offset + sizeof (UINT8), sizeof (UINT8), &Length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Length <= 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = (UINT16) (Offset + (UINT16) Length * 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the ICMPv6 redirect message. Find the instance, then update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync its route cache.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance that received
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head The IP head of the received ICMPv6 packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The content of the ICMPv6 redirect packet with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the IP head removed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_INVALID_PARAMETER The parameter is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Insuffcient resources to complete the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync operation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS Successfully updated the route caches.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6ProcessRedirect (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP6_HEADER *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ICMP_INFORMATION_HEAD *Icmp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *Target;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS *IcmpDest;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 OptionLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ROUTE_ENTRY *RouteEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ROUTE_CACHE_ENTRY *RouteCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *NeighborCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INT32 Length;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 OptLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ETHER_ADDR_OPTION *LinkLayerOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MAC_ADDRESS Mac;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN IsRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_INVALID_PARAMETER;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Icmp = (IP6_ICMP_INFORMATION_HEAD *) NetbufGetByte (Packet, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Icmp == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Validate the incoming Redirect message
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP Hop Limit field has a value of 255, i.e. the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // could not possibly have been forwarded by a router.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP Code is 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ICMP length (derived from the IP length) is 40 or more octets.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->HopLimit != IP6_HOP_LIMIT || Icmp->Head.Code != 0 ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->PayloadLength < IP6_REDITECT_LENGTH) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP source address must be a link-local address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NetIp6IsLinkLocalAddr (&Head->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The dest of this ICMP redirect message is not us.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsOneOfSetAddress (IpSb, &Head->DestinationAddress, NULL, NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All included options have a length that is greater than zero.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptionLen = (UINT16) (Head->PayloadLength - IP6_REDITECT_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptionLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option = NetbufGetByte (Packet, IP6_REDITECT_LENGTH, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Option != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Ip6IsNDOptionValid (Option, OptionLen)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Target = (EFI_IPv6_ADDRESS *) (Icmp + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpDest = Target + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The ICMP Destination Address field in the redirect message does not contain
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IP6_IS_MULTICAST (IcmpDest)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The ICMP Target Address is either a link-local address (when redirected to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a router) or the same as the ICMP Destination Address (when redirected to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the on-link destination).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IsRouter = (BOOLEAN) !EFI_IP6_EQUAL (Target, IcmpDest);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NetIp6IsLinkLocalAddr (Target) && IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the options. The only interested option here is the target-link layer
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // address option.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Length = Packet->TotalSize - 40;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option = (UINT8 *) (IcmpDest + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Length > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (*Option) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case Ip6OptionEtherTarget:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LinkLayerOption = (IP6_ETHER_ADDR_OPTION *) Option;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptLen = LinkLayerOption->Length;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptLen != 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For ethernet, the length must be 1.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OptLen = *(Option + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (OptLen == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A length of 0 is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Length -= 8 * OptLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Option += 8 * OptLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Length != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The IP source address of the Redirect is the same as the current
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // first-hop router for the specified ICMP Destination Address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteCache = Ip6FindRouteCache (IpSb->RouteTable, IcmpDest, &Head->DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouteCache != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_IP6_EQUAL (&RouteCache->NextHop, &Head->SourceAddress)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The source of this Redirect message must match the NextHop of the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // corresponding route cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the NextHop.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_ADDRESS (&RouteCache->NextHop, Target);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteEntry = (IP6_ROUTE_ENTRY *) RouteCache->Tag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteEntry->Flag = RouteEntry->Flag | IP6_DIRECT_ROUTE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the Route Entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteEntry = Ip6FindRouteEntry (IpSb->RouteTable, IcmpDest, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouteEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteEntry = Ip6CreateRouteEntry (IcmpDest, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouteEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteEntry->Flag = IP6_DIRECT_ROUTE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a route cache for this.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteCache = Ip6CreateRouteCacheEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IcmpDest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Head->DestinationAddress,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Target,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN) RouteEntry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (RouteCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert the newly created route cache entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Index = IP6_ROUTE_CACHE_HASH (IcmpDest, &Head->DestinationAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertHeadList (&IpSb->RouteTable->Cache.CacheBucket[Index], &RouteCache->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Try to locate the neighbor cache for the Target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = Ip6FindNeighborEntry (IpSb, Target);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LinkLayerOption != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a neighbor cache for the Target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Mac, sizeof (EFI_MAC_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Mac, LinkLayerOption->EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, Target, &Mac);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Just report a success here. The neighbor cache can be created in
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // some other place.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Result = CompareMem (LinkLayerOption->EtherAddr, &NeighborCache->LinkAddress, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the link-local address is the same as that already in the cache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the cache entry's state remains unchanged. Otherwise update the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // reachability state to STALE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NeighborCache->State == EfiNeighborInComplete) || (Result != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&NeighborCache->LinkAddress, LinkLayerOption->EtherAddr, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->State == EfiNeighborInComplete) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send queued packets if exist.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->CallBack ((VOID *) NeighborCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache != NULL && IsRouter) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The Target is a router, set IsRouter to TRUE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->IsRouter = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncExit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add Neighbor cache entries. It is a work function for EfiIp6Neighbors().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetIp6Address Pointer to Target IPv6 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cache. It will be deleted after Timeout. A value of zero means that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the entry is permanent. A non-zero value means that the entry is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dynamic.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Override If TRUE, the cached link-layer address of the matching entry will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be overridden and updated; if FALSE, and if a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync corresponding cache entry already existed, EFI_ACCESS_DENIED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync will be returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The neighbor cache entry has been added.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Could not add the entry to the neighbor cache
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync due to insufficient resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND TargetLinkAddress is NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ACCESS_DENIED The to-be-added entry is already defined in the neighbor cache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and that entry is tagged as un-overridden (when DeleteFlag
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is FALSE).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6AddNeighbor (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *TargetIp6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Override
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Override) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_ACCESS_DENIED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TargetLinkAddress != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_COPY_LINK_ADDRESS (&Neighbor->LinkAddress, TargetLinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TargetLinkAddress == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, TargetIp6Address, TargetLinkAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->State = EfiNeighborReachable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Timeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = IP6_GET_TICKS (Timeout / TICKS_PER_MS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Dynamic = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delete or update Neighbor cache entries. It is a work function for EfiIp6Neighbors().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetIp6Address Pointer to Target IPv6 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TargetLinkAddress Pointer to link-layer address of the target. Ignored if NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Timeout Time in 100-ns units that this entry will remain in the neighbor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync cache. It will be deleted after Timeout. A value of zero means that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the entry is permanent. A non-zero value means that the entry is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dynamic.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Override If TRUE, the cached link-layer address of the matching entry will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be overridden and updated; if FALSE, and if a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync corresponding cache entry already existed, EFI_ACCESS_DENIED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync will be returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The neighbor cache entry has been updated or deleted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND This entry is not in the neighbor cache.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6DelNeighbor (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IPv6_ADDRESS *TargetIp6Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MAC_ADDRESS *TargetLinkAddress OPTIONAL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Timeout,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Override
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *Neighbor;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Neighbor = Ip6FindNeighborEntry (IpSb, TargetIp6Address);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Neighbor == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Neighbor->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Neighbor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The heartbeat timer of ND module in IP6_TIMER_INTERVAL_IN_MS milliseconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This time routine handles DAD module and neighbor state transition.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It is also responsible for sending out router solicitations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Event The IP6 service instance's heartbeat timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The IP6 service instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6NdFasterTimerTicking (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT Event,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_INTERFACE *IpIf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DELAY_JOIN_LIST *DelayNode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Source;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DAD_ENTRY *DupAddrDetect;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_NEIGHBOR_ENTRY *NeighborCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IPv6_ADDRESS Destination;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_SERVICE *IpSb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb = (IP6_SERVICE *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Source, sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A host SHOULD transmit up to MAX_RTR_SOLICITATIONS (3) Router
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Solicitation messages, each separated by at least
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RTR_SOLICITATION_INTERVAL (4) seconds.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((IpSb->Ip6ConfigInstance.Policy == Ip6ConfigPolicyAutomatic) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !IpSb->RouterAdvertiseReceived &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->SolicitTimer > 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((IpSb->Ticks == 0) || (--IpSb->Ticks == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendRouterSolicit (IpSb, NULL, NULL, NULL, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->SolicitTimer--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->Ticks = (UINT32) IP6_GET_TICKS (IP6_RTR_SOLICITATION_INTERVAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the delay list to join the solicited-node multicast address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DelayNode->DelayTime == 0) || (--DelayNode->DelayTime == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The timer expires, init the duplicate address detection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6InitDADProcess (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->Interface,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->AddressInfo,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->DadCallback,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DelayNode->Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the delay node
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&DelayNode->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DelayNode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the duplicate address detection list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect = NET_LIST_USER_STRUCT (Entry2, IP6_DAD_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DupAddrDetect->RetransTick == 0) || (--DupAddrDetect->RetransTick == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The timer expires, check the remaining transmit counts.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DupAddrDetect->Transmit < DupAddrDetect->MaxTransmit) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the Neighbor Solicitation message with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Source - unspecified address, destination - solicited-node multicast address
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Target - the address to be validated
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DupAddrDetect->Destination,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DupAddrDetect->AddressInfo->Address,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect->Transmit++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DupAddrDetect->RetransTick = IP6_GET_TICKS (IpSb->RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All required solicitation has been sent out, and the RetransTime after the last
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Neighbor Solicit is elapsed, finish the DAD process.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DupAddrDetect->Receive == 0) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (DupAddrDetect->Transmit == DupAddrDetect->Receive)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6OnDADFinished (Flag, IpIf, DupAddrDetect);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Polling the state of Neighbor cache
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->NeighborTable) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (NeighborCache->State) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborInComplete:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Ticks > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync --NeighborCache->Ticks;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Retransmit Neighbor Solicitation messages approximately every
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RetransTimer milliseconds while awaiting a response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Ticks == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit > 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send out multicast neighbor solicitation for address resolution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // After last neighbor solicitation message has been sent out, wait
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for RetransTimer and then remove entry if no response is received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Source,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Destination,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NeighborCache->Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->SnpMode.CurrentAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the retransmit times.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync --NeighborCache->Transmit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Timeout, send ICMP destination unreachable packet and then remove entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FreeNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_ICMP_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborReachable:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // This entry is inserted by EfiIp6Neighbors() as static entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and will not timeout.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NeighborCache->Dynamic && (NeighborCache->Ticks == IP6_INFINIT_LIFETIME)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Dynamic) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // This entry is inserted by EfiIp6Neighbors() as dynamic entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and will be deleted after timeout.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FreeNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TIMEOUT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborStale;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = (UINT32) IP6_INFINIT_LIFETIME;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborDelay:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NeighborCache->Ticks == 0) || (--NeighborCache->Ticks == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->State = EfiNeighborProbe;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Transmit = IP6_MAX_UNICAST_SOLICIT + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send out unicast neighbor solicitation for Neighbor Unreachability Detection
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Source,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NeighborCache->Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NeighborCache->Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->SnpMode.CurrentAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Transmit--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EfiNeighborProbe:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Ticks > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync --NeighborCache->Ticks;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Retransmit Neighbor Solicitation messages approximately every
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RetransTimer milliseconds while awaiting a response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Ticks == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit > 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send out unicast neighbor solicitation for Neighbor Unreachability
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Detection. After last neighbor solicitation message has been sent out,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wait for RetransTimer and then remove entry if no response is received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6SendNeighborSolicit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Source,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NeighborCache->Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &NeighborCache->Neighbor,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &IpSb->SnpMode.CurrentAddress
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the retransmit times.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync --NeighborCache->Transmit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NeighborCache->Transmit == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Delete the neighbor entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Ip6FreeNeighborEntry (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NeighborCache,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FALSE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TRUE,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_TIMEOUT,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The heartbeat timer of ND module in 1 second. This time routine handles following
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync things: 1) maitain default router list; 2) maintain prefix options;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 3) maintain route caches.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] IpSb The IP6 service binding instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIp6NdTimerTicking (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN IP6_SERVICE *IpSb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Next;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_DEFAULT_ROUTER *DefaultRouter;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_PREFIX_LIST_ENTRY *PrefixOption;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP6_ROUTE_CACHE_ENTRY *RouteCache;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Decrease the lifetime of default router, if expires remove it from default router list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->DefaultRouterList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DefaultRouter = NET_LIST_USER_STRUCT (Entry, IP6_DEFAULT_ROUTER, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DefaultRouter->Lifetime != IP6_INF_ROUTER_LIFETIME) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((DefaultRouter->Lifetime == 0) || (--DefaultRouter->Lifetime == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyDefaultRouter (IpSb, DefaultRouter);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Decrease Valid lifetime and Preferred lifetime of Prefix options and corresponding addresses.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->AutonomousPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixOption->ValidLifetime != (UINT32) IP6_INFINIT_LIFETIME) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption->ValidLifetime > 0) && (--PrefixOption->ValidLifetime > 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption->PreferredLifetime != (UINT32) IP6_INFINIT_LIFETIME) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (PrefixOption->PreferredLifetime > 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync --PrefixOption->PreferredLifetime;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyPrefixListEntry (IpSb, PrefixOption, FALSE, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH_SAFE (Entry, Next, &IpSb->OnlinkPrefix) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PrefixOption = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PrefixOption->ValidLifetime != (UINT32) IP6_INFINIT_LIFETIME) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((PrefixOption->ValidLifetime == 0) || (--PrefixOption->ValidLifetime == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6DestroyPrefixListEntry (IpSb, PrefixOption, TRUE, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Each bucket of route cache can contain at most IP6_ROUTE_CACHE_MAX entries.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the entries at the tail of the bucket. These entries
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // are likely to be used least.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reclaim frequency is set to 1 second.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < IP6_ROUTE_CACHE_HASH_SIZE; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (IpSb->RouteTable->Cache.CacheNum[Index] > IP6_ROUTE_CACHE_MAX) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = NetListRemoveTail (&IpSb->RouteTable->Cache.CacheBucket[Index]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Entry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RouteCache = NET_LIST_USER_STRUCT (Entry, IP6_ROUTE_CACHE_ENTRY, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ip6FreeRouteCacheEntry (RouteCache);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (IpSb->RouteTable->Cache.CacheNum[Index] > 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpSb->RouteTable->Cache.CacheNum[Index]--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync