X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FDhcp6Dxe%2FDhcp6Utility.c;h=e6368b5b1c6c65f8f2387ef4a202d96286ae4a47;hb=d1050b9dff1cace252aff86630bfdb59dff5f507;hp=ac0e577f5e333eaae1661d606c58520cc4dc4e1b;hpb=33c09637c6017fb6882d4a54f40a347adf4a05b8;p=mirror_edk2.git
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
index ac0e577f5e..e6368b5b1c 100644
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
@@ -1,21 +1,15 @@
/** @file
Dhcp6 support functions implementation.
- Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Dhcp6Impl.h"
-
/**
Generate client Duid in the format of Duid-llt.
@@ -27,21 +21,20 @@
**/
EFI_DHCP6_DUID *
Dhcp6GenerateClientId (
- IN EFI_SIMPLE_NETWORK_MODE *Mode
+ IN EFI_SIMPLE_NETWORK_MODE *Mode
)
{
- EFI_STATUS Status;
- EFI_DHCP6_DUID *Duid;
- EFI_TIME Time;
- UINT32 Stamp;
- EFI_GUID Uuid;
-
+ EFI_STATUS Status;
+ EFI_DHCP6_DUID *Duid;
+ EFI_TIME Time;
+ UINT32 Stamp;
+ EFI_GUID Uuid;
//
// Attempt to get client Id from variable to keep it constant.
// See details in section-9 of rfc-3315.
//
- Duid = GetVariable (L"ClientId", &gEfiDhcp6ServiceBindingProtocolGuid);
+ GetVariable2 (L"ClientId", &gEfiDhcp6ServiceBindingProtocolGuid, (VOID **)&Duid, NULL);
if (Duid != NULL) {
return Duid;
}
@@ -63,11 +56,11 @@ Dhcp6GenerateClientId (
//
// If System UUID is found from SMBIOS Table, use DUID-UUID type.
//
- if (!EFI_ERROR (NetLibGetSystemGuid (&Uuid))) {
+ if ((PcdGet8 (PcdDhcp6UidType) == Dhcp6DuidTypeUuid) && !EFI_ERROR (NetLibGetSystemGuid (&Uuid)) && !CompareGuid (&Uuid, &gZeroGuid)) {
//
//
// The format of DUID-UUID:
- //
+ //
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | DUID-Type (4) | UUID (128 bits) |
@@ -89,17 +82,15 @@ Dhcp6GenerateClientId (
//
// sizeof (Duid-type + UUID-size) = 18 bytes
//
- Duid->Length = (UINT16) (18);
-
+ Duid->Length = (UINT16)(18);
+
//
// Set the Duid-type and copy UUID.
//
- WriteUnaligned16 ((UINT16 *) (Duid->Duid), HTONS (Dhcp6DuidTypeUuid));
-
- CopyMem (Duid->Duid + 2, &Uuid, sizeof(EFI_GUID));
+ WriteUnaligned16 ((UINT16 *)(Duid->Duid), HTONS (Dhcp6DuidTypeUuid));
+ CopyMem (Duid->Duid + 2, &Uuid, sizeof (EFI_GUID));
} else {
-
//
//
// The format of DUID-LLT:
@@ -121,11 +112,11 @@ Dhcp6GenerateClientId (
//
gRT->GetTime (&Time, NULL);
Stamp = (UINT32)
- (
- (((((Time.Year - 2000) * 360 + (Time.Month - 1)) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) *
- 60 +
- Time.Second
- );
+ (
+ ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) *
+ 60 +
+ Time.Second
+ );
//
// sizeof (option-len + Duid-type + hardware-type + time) = 10 bytes
@@ -134,19 +125,19 @@ Dhcp6GenerateClientId (
if (Duid == NULL) {
return NULL;
}
-
+
//
// sizeof (Duid-type + hardware-type + time) = 8 bytes
//
- Duid->Length = (UINT16) (Mode->HwAddressSize + 8);
-
+ Duid->Length = (UINT16)(Mode->HwAddressSize + 8);
+
//
// Set the Duid-type, hardware-type, time and copy the hardware address.
//
- WriteUnaligned16 ((UINT16 *) (Duid->Duid), HTONS (Dhcp6DuidTypeLlt));
- WriteUnaligned16 ((UINT16 *) (Duid->Duid + 2), HTONS (NET_IFTYPE_ETHERNET));
- WriteUnaligned32 ((UINT32 *) (Duid->Duid + 4), HTONL (Stamp));
-
+ WriteUnaligned16 ((UINT16 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid)), HTONS (Dhcp6DuidTypeLlt));
+ WriteUnaligned16 ((UINT16 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 2), HTONS (NET_IFTYPE_ETHERNET));
+ WriteUnaligned32 ((UINT32 *)((UINT8 *)Duid + OFFSET_OF (EFI_DHCP6_DUID, Duid) + 4), HTONL (Stamp));
+
CopyMem (Duid->Duid + 8, &Mode->CurrentAddress, Mode->HwAddressSize);
}
@@ -155,14 +146,16 @@ Dhcp6GenerateClientId (
&gEfiDhcp6ServiceBindingProtocolGuid,
(EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
Duid->Length + 2,
- (VOID *) Duid
+ (VOID *)Duid
);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ FreePool (Duid);
+ return NULL;
+ }
return Duid;
}
-
/**
Copy the Dhcp6 configure data.
@@ -175,13 +168,13 @@ Dhcp6GenerateClientId (
**/
EFI_STATUS
Dhcp6CopyConfigData (
- IN EFI_DHCP6_CONFIG_DATA *DstCfg,
- IN EFI_DHCP6_CONFIG_DATA *SorCfg
+ IN EFI_DHCP6_CONFIG_DATA *DstCfg,
+ IN EFI_DHCP6_CONFIG_DATA *SorCfg
)
{
- UINTN Index;
- UINTN OptionListSize;
- UINTN OptionSize;
+ UINTN Index;
+ UINTN OptionListSize;
+ UINTN OptionSize;
CopyMem (DstCfg, SorCfg, sizeof (EFI_DHCP6_CONFIG_DATA));
@@ -189,7 +182,6 @@ Dhcp6CopyConfigData (
// Allocate another buffer for solicitretransmission, and copy it.
//
if (SorCfg->SolicitRetransmission != NULL) {
-
DstCfg->SolicitRetransmission = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
if (DstCfg->SolicitRetransmission == NULL) {
@@ -206,8 +198,7 @@ Dhcp6CopyConfigData (
);
}
- if (SorCfg->OptionList != NULL && SorCfg->OptionCount != 0) {
-
+ if ((SorCfg->OptionList != NULL) && (SorCfg->OptionCount != 0)) {
OptionListSize = SorCfg->OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *);
DstCfg->OptionList = AllocateZeroPool (OptionListSize);
@@ -219,7 +210,6 @@ Dhcp6CopyConfigData (
}
for (Index = 0; Index < SorCfg->OptionCount; Index++) {
-
OptionSize = NTOHS (SorCfg->OptionList[Index]->OpLen) + 4;
DstCfg->OptionList[Index] = AllocateZeroPool (OptionSize);
@@ -241,7 +231,6 @@ Dhcp6CopyConfigData (
return EFI_SUCCESS;
}
-
/**
Clean up the configure data.
@@ -250,10 +239,10 @@ Dhcp6CopyConfigData (
**/
VOID
Dhcp6CleanupConfigData (
- IN OUT EFI_DHCP6_CONFIG_DATA *CfgData
+ IN OUT EFI_DHCP6_CONFIG_DATA *CfgData
)
{
- UINTN Index;
+ UINTN Index;
ASSERT (CfgData != NULL);
//
@@ -266,6 +255,7 @@ Dhcp6CleanupConfigData (
FreePool (CfgData->OptionList[Index]);
}
}
+
FreePool (CfgData->OptionList);
}
@@ -276,7 +266,6 @@ Dhcp6CleanupConfigData (
ZeroMem (CfgData, sizeof (EFI_DHCP6_CONFIG_DATA));
}
-
/**
Clean up the mode data.
@@ -285,7 +274,7 @@ Dhcp6CleanupConfigData (
**/
VOID
Dhcp6CleanupModeData (
- IN OUT EFI_DHCP6_MODE_DATA *ModeData
+ IN OUT EFI_DHCP6_MODE_DATA *ModeData
)
{
ASSERT (ModeData != NULL);
@@ -298,38 +287,37 @@ Dhcp6CleanupModeData (
}
if (ModeData->Ia != NULL) {
-
if (ModeData->Ia->ReplyPacket != NULL) {
FreePool (ModeData->Ia->ReplyPacket);
}
+
FreePool (ModeData->Ia);
}
ZeroMem (ModeData, sizeof (EFI_DHCP6_MODE_DATA));
}
-
/**
Calculate the expire time by the algorithm defined in rfc.
@param[in] Base The base value of the time.
@param[in] IsFirstRt If TRUE, it is the first time to calculate expire time.
- @param[in] NeedSigned If TRUE, the the signed factor is needed.
+ @param[in] NeedSigned If TRUE, the signed factor is needed.
@return Expire The calculated result for the new expire time.
**/
UINT32
Dhcp6CalculateExpireTime (
- IN UINT32 Base,
- IN BOOLEAN IsFirstRt,
- IN BOOLEAN NeedSigned
+ IN UINT32 Base,
+ IN BOOLEAN IsFirstRt,
+ IN BOOLEAN NeedSigned
)
{
- EFI_TIME Time;
- BOOLEAN Signed;
- UINT32 Seed;
- UINT32 Expire;
+ EFI_TIME Time;
+ BOOLEAN Signed;
+ UINT32 Seed;
+ UINT32 Expire;
//
// Take the 10bits of microsecond in system time as a uniform distribution.
@@ -337,8 +325,8 @@ Dhcp6CalculateExpireTime (
//
gRT->GetTime (&Time, NULL);
Seed = ((Time.Nanosecond >> 10) & DHCP6_10_BIT_MASK);
- Signed = (BOOLEAN) ((((Time.Nanosecond >> 9) & 0x01) != 0) ? TRUE : FALSE);
- Signed = (BOOLEAN) (NeedSigned ? Signed : FALSE);
+ Signed = (BOOLEAN)((((Time.Nanosecond >> 9) & 0x01) != 0) ? TRUE : FALSE);
+ Signed = (BOOLEAN)(NeedSigned ? Signed : FALSE);
//
// Calculate expire by the following algo:
@@ -350,20 +338,13 @@ Dhcp6CalculateExpireTime (
// The (Seed / 0x3ff / 10) is used to a random range (0, 0.1).
//
if (IsFirstRt && Signed) {
-
- Expire = Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
-
+ Expire = Base - (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);
} else if (IsFirstRt && !Signed) {
-
- Expire = Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
-
+ Expire = Base + (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);
} else if (!IsFirstRt && Signed) {
-
- Expire = 2 * Base - (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
-
+ Expire = 2 * Base - (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);
} else {
-
- Expire = 2 * Base + (UINT32) (Base * Seed / DHCP6_10_BIT_MASK / 10);
+ Expire = 2 * Base + (UINT32)(Base * Seed / DHCP6_10_BIT_MASK / 10);
}
Expire = (Expire != 0) ? Expire : 1;
@@ -371,7 +352,6 @@ Dhcp6CalculateExpireTime (
return Expire;
}
-
/**
Calculate the lease time by the algorithm defined in rfc.
@@ -380,27 +360,25 @@ Dhcp6CalculateExpireTime (
**/
VOID
Dhcp6CalculateLeaseTime (
- IN DHCP6_IA_CB *IaCb
+ IN DHCP6_IA_CB *IaCb
)
{
- EFI_DHCP6_IA_ADDRESS *IaAddr;
- UINT32 MinLt;
- UINT32 MaxLt;
- UINTN Index;
+ UINT32 MinLt;
+ UINT32 MaxLt;
+ UINTN Index;
ASSERT (IaCb->Ia->IaAddressCount > 0);
- MinLt = (UINT32) (-1);
- MaxLt = 0;
+ MinLt = (UINT32)(-1);
+ MaxLt = 0;
//
// Calculate minlt as min of all valid life time, and maxlt as max of all
// valid life time.
//
for (Index = 0; Index < IaCb->Ia->IaAddressCount; Index++) {
- IaAddr = IaCb->Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
- MinLt = MIN (MinLt, IaAddr->ValidLifetime);
- MaxLt = MAX (MinLt, IaAddr->ValidLifetime);
+ MinLt = MIN (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);
+ MaxLt = MAX (MinLt, IaCb->Ia->IaAddress[Index].ValidLifetime);
}
//
@@ -413,7 +391,6 @@ Dhcp6CalculateLeaseTime (
IaCb->LeaseTime = 0;
}
-
/**
Check whether the addresses are all included by the configured Ia.
@@ -427,31 +404,29 @@ Dhcp6CalculateLeaseTime (
**/
EFI_STATUS
Dhcp6CheckAddress (
- IN EFI_DHCP6_IA *Ia,
- IN UINT32 AddressCount,
- IN EFI_IPv6_ADDRESS *Addresses
+ IN EFI_DHCP6_IA *Ia,
+ IN UINT32 AddressCount,
+ IN EFI_IPv6_ADDRESS *Addresses
)
{
- UINTN Index1;
- UINTN Index2;
- BOOLEAN Found;
+ UINTN Index1;
+ UINTN Index2;
+ BOOLEAN Found;
//
// Check whether the addresses are all included by the configured IA. And it
// will return success if address count is zero, which means all addresses.
//
for (Index1 = 0; Index1 < AddressCount; Index1++) {
-
Found = FALSE;
for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
-
if (CompareMem (
&Addresses[Index1],
&Ia->IaAddress[Index2],
sizeof (EFI_IPv6_ADDRESS)
- ) == 0) {
-
+ ) == 0)
+ {
Found = TRUE;
break;
}
@@ -465,7 +440,6 @@ Dhcp6CheckAddress (
return EFI_SUCCESS;
}
-
/**
Deprive the addresses from current Ia, and generate another eliminated Ia.
@@ -479,16 +453,16 @@ Dhcp6CheckAddress (
**/
EFI_DHCP6_IA *
Dhcp6DepriveAddress (
- IN EFI_DHCP6_IA *Ia,
- IN UINT32 AddressCount,
- IN EFI_IPv6_ADDRESS *Addresses
+ IN EFI_DHCP6_IA *Ia,
+ IN UINT32 AddressCount,
+ IN EFI_IPv6_ADDRESS *Addresses
)
{
- EFI_DHCP6_IA *IaCopy;
- UINTN IaCopySize;
- UINTN Index1;
- UINTN Index2;
- BOOLEAN Found;
+ EFI_DHCP6_IA *IaCopy;
+ UINTN IaCopySize;
+ UINTN Index1;
+ UINTN Index2;
+ BOOLEAN Found;
if (AddressCount == 0) {
//
@@ -510,7 +484,7 @@ Dhcp6DepriveAddress (
//
// If release all Ia addresses, just copy the configured Ia and then set
// its address count as zero.
- // We may decline/release part of addresses at the begining. So it's a
+ // We may decline/release part of addresses at the beginning. So it's a
// forwarding step to update address infor for decline/release, while the
// other infor such as Ia state will be updated when receiving reply.
//
@@ -525,16 +499,15 @@ Dhcp6DepriveAddress (
// Move the addresses from the Ia of instance to the deprived Ia.
//
for (Index1 = 0; Index1 < AddressCount; Index1++) {
-
Found = FALSE;
for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
-
if (CompareMem (
&Addresses[Index1],
&Ia->IaAddress[Index2],
sizeof (EFI_IPv6_ADDRESS)
- ) == 0) {
+ ) == 0)
+ {
//
// Copy the deprived address to the copy of Ia
//
@@ -553,10 +526,12 @@ Dhcp6DepriveAddress (
(Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
);
}
+
Found = TRUE;
break;
}
}
+
ASSERT (Found == TRUE);
}
@@ -566,7 +541,6 @@ Dhcp6DepriveAddress (
return IaCopy;
}
-
/**
The dummy ext buffer free callback routine.
@@ -576,12 +550,11 @@ Dhcp6DepriveAddress (
VOID
EFIAPI
Dhcp6DummyExtFree (
- IN VOID *Arg
+ IN VOID *Arg
)
{
}
-
/**
The callback routine once message transmitted.
@@ -594,16 +567,15 @@ Dhcp6DummyExtFree (
VOID
EFIAPI
Dhcp6OnTransmitted (
- IN NET_BUF *Wrap,
- IN UDP_END_POINT *EndPoint,
- IN EFI_STATUS IoStatus,
- IN VOID *Context
+ IN NET_BUF *Wrap,
+ IN UDP_END_POINT *EndPoint,
+ IN EFI_STATUS IoStatus,
+ IN VOID *Context
)
{
NetbufFree (Wrap);
}
-
/**
Append the option to Buf, and move Buf to the end.
@@ -617,10 +589,10 @@ Dhcp6OnTransmitted (
**/
UINT8 *
Dhcp6AppendOption (
- IN OUT UINT8 *Buf,
- IN UINT16 OptType,
- IN UINT16 OptLen,
- IN UINT8 *Data
+ IN OUT UINT8 *Buf,
+ IN UINT16 OptType,
+ IN UINT16 OptLen,
+ IN UINT8 *Data
)
{
//
@@ -637,16 +609,85 @@ Dhcp6AppendOption (
ASSERT (OptLen != 0);
- WriteUnaligned16 ((UINT16 *) Buf, OptType);
- Buf += 2;
- WriteUnaligned16 ((UINT16 *) Buf, OptLen);
- Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, OptType);
+ Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, OptLen);
+ Buf += 2;
CopyMem (Buf, Data, NTOHS (OptLen));
- Buf += NTOHS (OptLen);
+ Buf += NTOHS (OptLen);
return Buf;
}
+/**
+ Append the appointed IA Address option to Buf, and move Buf to the end.
+
+ @param[in, out] Buf The pointer to the position to append.
+ @param[in] IaAddr The pointer to the IA Address.
+ @param[in] MessageType Message type of DHCP6 package.
+
+ @return Buf The position to append the next option.
+
+**/
+UINT8 *
+Dhcp6AppendIaAddrOption (
+ IN OUT UINT8 *Buf,
+ IN EFI_DHCP6_IA_ADDRESS *IaAddr,
+ IN UINT32 MessageType
+ )
+{
+ // The format of the IA Address option is:
+ //
+ // 0 1 2 3
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | OPTION_IAADDR | option-len |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | |
+ // | IPv6 address |
+ // | |
+ // | |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | preferred-lifetime |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | valid-lifetime |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // . .
+ // . IAaddr-options .
+ // . .
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ //
+ // Fill the value of Ia Address option type
+ //
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));
+ Buf += 2;
+
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
+ Buf += 2;
+
+ CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
+ Buf += sizeof (EFI_IPv6_ADDRESS);
+
+ //
+ // Fill the value of preferred-lifetime and valid-lifetime.
+ // According to RFC3315 Chapter 18.1.2, the preferred-lifetime and valid-lifetime fields
+ // should set to 0 when initiate a Confirm message.
+ //
+ if (MessageType != Dhcp6MsgConfirm) {
+ WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));
+ }
+
+ Buf += 4;
+
+ if (MessageType != Dhcp6MsgConfirm) {
+ WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));
+ }
+
+ Buf += 4;
+
+ return Buf;
+}
/**
Append the appointed Ia option to Buf, and move Buf to the end.
@@ -655,22 +696,23 @@ Dhcp6AppendOption (
@param[in] Ia The pointer to the Ia.
@param[in] T1 The time of T1.
@param[in] T2 The time of T2.
+ @param[in] MessageType Message type of DHCP6 package.
@return Buf The position to append the next Ia option.
**/
UINT8 *
Dhcp6AppendIaOption (
- IN OUT UINT8 *Buf,
- IN EFI_DHCP6_IA *Ia,
- IN UINT32 T1,
- IN UINT32 T2
+ IN OUT UINT8 *Buf,
+ IN EFI_DHCP6_IA *Ia,
+ IN UINT32 T1,
+ IN UINT32 T2,
+ IN UINT32 MessageType
)
{
- UINT8 *AddrOpt;
- UINT16 *Len;
- UINTN Index;
- UINT16 Length;
+ UINT8 *AddrOpt;
+ UINT16 *Len;
+ UINTN Index;
//
// The format of IA_NA and IA_TA option:
@@ -694,50 +736,43 @@ Dhcp6AppendIaOption (
//
// Fill the value of Ia option type
//
- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Ia->Descriptor.Type));
- Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));
+ Buf += 2;
//
// Fill the len of Ia option later, keep the pointer first
//
- Len = (UINT16 *) Buf;
- Buf += 2;
+ Len = (UINT16 *)Buf;
+ Buf += 2;
//
// Fill the value of iaid
//
- WriteUnaligned32 ((UINT32 *) Buf, HTONL (Ia->Descriptor.IaId));
- Buf += 4;
+ WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));
+ Buf += 4;
//
// Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
//
if (Ia->Descriptor.Type == Dhcp6OptIana) {
- WriteUnaligned32 ((UINT32 *) Buf, ((T1 != 0) ? T1 : 0xffffffff));
- Buf += 4;
- WriteUnaligned32 ((UINT32 *) Buf, ((T2 != 0) ? T2 : 0xffffffff));
- Buf += 4;
+ WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
+ Buf += 4;
+ WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
+ Buf += 4;
}
//
// Fill all the addresses belong to the Ia
//
for (Index = 0; Index < Ia->IaAddressCount; Index++) {
-
- AddrOpt = (UINT8 *) Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
- Length = HTONS ((UINT16) sizeof (EFI_DHCP6_IA_ADDRESS));
- Buf = Dhcp6AppendOption (
- Buf,
- HTONS (Dhcp6OptIaAddr),
- Length,
- AddrOpt
- );
+ AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
+ Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
}
//
// Fill the value of Ia option length
//
- *Len = HTONS ((UINT16) (Buf - (UINT8 *) Len - 2));
+ *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));
return Buf;
}
@@ -755,9 +790,9 @@ Dhcp6AppendIaOption (
**/
UINT8 *
Dhcp6AppendETOption (
- IN OUT UINT8 *Buf,
- IN DHCP6_INSTANCE *Instance,
- OUT UINT16 **Elapsed
+ IN OUT UINT8 *Buf,
+ IN DHCP6_INSTANCE *Instance,
+ OUT UINT16 **Elapsed
)
{
//
@@ -774,22 +809,22 @@ Dhcp6AppendETOption (
//
// Fill the value of elapsed-time option type.
//
- WriteUnaligned16 ((UINT16 *) Buf, HTONS (Dhcp6OptElapsedTime));
- Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));
+ Buf += 2;
//
// Fill the len of elapsed-time option, which is fixed.
//
- WriteUnaligned16 ((UINT16 *) Buf, HTONS(2));
- Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));
+ Buf += 2;
//
// Fill in elapsed time value with 0 value for now. The actual value is
// filled in later just before the packet is transmitted.
//
- WriteUnaligned16 ((UINT16 *) Buf, HTONS(0));
- *Elapsed = (UINT16 *) Buf;
- Buf += 2;
+ WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));
+ *Elapsed = (UINT16 *)Buf;
+ Buf += 2;
return Buf;
}
@@ -804,34 +839,34 @@ Dhcp6AppendETOption (
**/
VOID
SetElapsedTime (
- IN UINT16 *Elapsed,
- IN DHCP6_INSTANCE *Instance
+ IN UINT16 *Elapsed,
+ IN DHCP6_INSTANCE *Instance
)
{
- EFI_TIME Time;
- UINT64 CurrentStamp;
- UINT64 ElapsedTimeValue;
+ EFI_TIME Time;
+ UINT64 CurrentStamp;
+ UINT64 ElapsedTimeValue;
//
// Generate a time stamp of the centiseconds from 2000/1/1, assume 30day/month.
//
gRT->GetTime (&Time, NULL);
- CurrentStamp = (UINT64)
- (
- ((((((Time.Year - 2000) * 360 +
- (Time.Month - 1)) * 30 +
- (Time.Day - 1)) * 24 + Time.Hour) * 60 +
- Time.Minute) * 60 + Time.Second) * 100
- + DivU64x32(Time.Nanosecond, 10000000)
- );
+ CurrentStamp = MultU64x32 (
+ ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
+ 100
+ ) +
+ DivU64x32 (
+ Time.Nanosecond,
+ 10000000
+ );
//
// Sentinel value of 0 means that this is the first DHCP packet that we are
- // sending and that we need to initialize the value. First DHCP Solicit
+ // sending and that we need to initialize the value. First DHCP message
// gets 0 elapsed-time. Otherwise, calculate based on StartTime.
//
if (Instance->StartTime == 0) {
- ElapsedTimeValue = 0;
+ ElapsedTimeValue = 0;
Instance->StartTime = CurrentStamp;
} else {
ElapsedTimeValue = CurrentStamp - Instance->StartTime;
@@ -843,9 +878,9 @@ SetElapsedTime (
ElapsedTimeValue = 0xffff;
}
}
- WriteUnaligned16 (Elapsed, HTONS((UINT16) ElapsedTimeValue));
-}
+ WriteUnaligned16 (Elapsed, HTONS ((UINT16)ElapsedTimeValue));
+}
/**
Seek the address of the first byte of the option header.
@@ -860,15 +895,15 @@ SetElapsedTime (
**/
UINT8 *
Dhcp6SeekOption (
- IN UINT8 *Buf,
- IN UINT32 SeekLen,
- IN UINT16 OptType
+ IN UINT8 *Buf,
+ IN UINT32 SeekLen,
+ IN UINT16 OptType
)
{
- UINT8 *Cursor;
- UINT8 *Option;
- UINT16 DataLen;
- UINT16 OpCode;
+ UINT8 *Cursor;
+ UINT8 *Option;
+ UINT16 DataLen;
+ UINT16 OpCode;
Option = NULL;
Cursor = Buf;
@@ -877,19 +912,19 @@ Dhcp6SeekOption (
// The format of Dhcp6 option refers to Dhcp6AppendOption().
//
while (Cursor < Buf + SeekLen) {
- OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
+ OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
if (OpCode == HTONS (OptType)) {
Option = Cursor;
break;
}
- DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
+
+ DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
Cursor += (DataLen + 4);
}
return Option;
}
-
/**
Seek the address of the first byte of the Ia option header.
@@ -908,11 +943,11 @@ Dhcp6SeekIaOption (
IN EFI_DHCP6_IA_DESCRIPTOR *IaDesc
)
{
- UINT8 *Cursor;
- UINT8 *Option;
- UINT16 DataLen;
- UINT16 OpCode;
- UINT32 IaId;
+ UINT8 *Cursor;
+ UINT8 *Option;
+ UINT16 DataLen;
+ UINT16 OpCode;
+ UINT32 IaId;
//
// The format of IA_NA and IA_TA option refers to Dhcp6AppendIaOption().
@@ -921,23 +956,54 @@ Dhcp6SeekIaOption (
Cursor = Buf;
while (Cursor < Buf + SeekLen) {
- OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
- IaId = ReadUnaligned32 ((UINT32 *) (Cursor + 4));
- if (OpCode == HTONS (IaDesc->Type) && IaId == HTONL (IaDesc->IaId)) {
+ OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
+ IaId = ReadUnaligned32 ((UINT32 *)(Cursor + 4));
+ if ((OpCode == HTONS (IaDesc->Type)) && (IaId == HTONL (IaDesc->IaId))) {
Option = Cursor;
break;
}
- DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
+
+ DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
Cursor += (DataLen + 4);
}
return Option;
}
+/**
+ Check whether the incoming IPv6 address in IaAddr is one of the maintained
+ addresses in the IA control block.
+
+ @param[in] IaAddr The pointer to the IA Address to be checked.
+ @param[in] CurrentIa The pointer to the IA in IA control block.
+
+ @retval TRUE Yes, this Address is already in IA control block.
+ @retval FALSE No, this Address is NOT in IA control block.
+
+**/
+BOOLEAN
+Dhcp6AddrIsInCurrentIa (
+ IN EFI_DHCP6_IA_ADDRESS *IaAddr,
+ IN EFI_DHCP6_IA *CurrentIa
+ )
+{
+ UINT32 Index;
+
+ ASSERT (IaAddr != NULL && CurrentIa != NULL);
+
+ for (Index = 0; Index < CurrentIa->IaAddressCount; Index++) {
+ if (EFI_IP6_EQUAL (&IaAddr->IpAddress, &CurrentIa->IaAddress[Index].IpAddress)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
/**
- Parse the address option and update the address infomation.
+ Parse the address option and update the address information.
+ @param[in] CurrentIa The pointer to the Ia Address in control block.
@param[in] IaInnerOpt The pointer to the buffer.
@param[in] IaInnerLen The length to parse.
@param[out] AddrNum The number of addresses.
@@ -946,16 +1012,19 @@ Dhcp6SeekIaOption (
**/
VOID
Dhcp6ParseAddrOption (
- IN UINT8 *IaInnerOpt,
- IN UINT16 IaInnerLen,
- OUT UINT32 *AddrNum,
- IN OUT EFI_DHCP6_IA_ADDRESS *AddrBuf
+ IN EFI_DHCP6_IA *CurrentIa,
+ IN UINT8 *IaInnerOpt,
+ IN UINT16 IaInnerLen,
+ OUT UINT32 *AddrNum,
+ IN OUT EFI_DHCP6_IA_ADDRESS *AddrBuf
)
{
- UINT8 *Cursor;
- UINT16 DataLen;
- UINT16 OpCode;
- UINT32 ValidLt;
+ UINT8 *Cursor;
+ UINT16 DataLen;
+ UINT16 OpCode;
+ UINT32 ValidLt;
+ UINT32 PreferredLt;
+ EFI_DHCP6_IA_ADDRESS *IaAddr;
//
// The format of the IA Address option:
@@ -992,29 +1061,33 @@ Dhcp6ParseAddrOption (
while (Cursor < IaInnerOpt + IaInnerLen) {
//
- // Count the Ia address option with non-0 valid time.
+ // Refer to RFC3315 Chapter 18.1.8, we need to update lifetimes for any addresses in the IA option
+ // that the client already has recorded in the IA, and discard the Ia address option with 0 valid time.
//
- OpCode = ReadUnaligned16 ((UINT16 *) Cursor);
- ValidLt = ReadUnaligned32 ((UINT32 *) (Cursor + 24));
- if (OpCode == HTONS (Dhcp6OptIaAddr) && ValidLt != 0) {
-
+ OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
+ PreferredLt = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 20)));
+ ValidLt = NTOHL (ReadUnaligned32 ((UINT32 *)(Cursor + 24)));
+ IaAddr = (EFI_DHCP6_IA_ADDRESS *)(Cursor + 4);
+ if ((OpCode == HTONS (Dhcp6OptIaAddr)) && (ValidLt >= PreferredLt) &&
+ (Dhcp6AddrIsInCurrentIa (IaAddr, CurrentIa) || (ValidLt != 0)))
+ {
if (AddrBuf != NULL) {
- CopyMem (AddrBuf, Cursor + 4, sizeof (EFI_DHCP6_IA_ADDRESS));
- AddrBuf->PreferredLifetime = NTOHL (AddrBuf->PreferredLifetime);
- AddrBuf->ValidLifetime = NTOHL (AddrBuf->ValidLifetime);
- AddrBuf = (EFI_DHCP6_IA_ADDRESS *) ((UINT8 *) AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));
+ CopyMem (AddrBuf, IaAddr, sizeof (EFI_DHCP6_IA_ADDRESS));
+ AddrBuf->PreferredLifetime = PreferredLt;
+ AddrBuf->ValidLifetime = ValidLt;
+ AddrBuf = (EFI_DHCP6_IA_ADDRESS *)((UINT8 *)AddrBuf + sizeof (EFI_DHCP6_IA_ADDRESS));
}
(*AddrNum)++;
}
- DataLen = NTOHS (ReadUnaligned16 ((UINT16 *) (Cursor + 2)));
+
+ DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
Cursor += (DataLen + 4);
}
}
-
/**
- Create a control blcok for the Ia according to the corresponding options.
+ Create a control block for the Ia according to the corresponding options.
@param[in] Instance The pointer to DHCP6 Instance.
@param[in] IaInnerOpt The pointer to the inner options in the Ia option.
@@ -1025,30 +1098,31 @@ Dhcp6ParseAddrOption (
@retval EFI_NOT_FOUND No valid IA option is found.
@retval EFI_SUCCESS Create an IA control block successfully.
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected error.
**/
EFI_STATUS
Dhcp6GenerateIaCb (
- IN DHCP6_INSTANCE *Instance,
- IN UINT8 *IaInnerOpt,
- IN UINT16 IaInnerLen,
- IN UINT32 T1,
- IN UINT32 T2
+ IN DHCP6_INSTANCE *Instance,
+ IN UINT8 *IaInnerOpt,
+ IN UINT16 IaInnerLen,
+ IN UINT32 T1,
+ IN UINT32 T2
)
{
- UINT32 AddrNum;
- UINT32 IaSize;
- EFI_DHCP6_IA *Ia;
+ UINT32 AddrNum;
+ UINT32 IaSize;
+ EFI_DHCP6_IA *Ia;
if (Instance->IaCb.Ia == NULL) {
- return EFI_NOT_FOUND;
+ return EFI_DEVICE_ERROR;
}
//
// Calculate the number of addresses for this Ia, excluding the addresses with
// the value 0 of valid lifetime.
//
- Dhcp6ParseAddrOption (IaInnerOpt, IaInnerLen, &AddrNum, NULL);
+ Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, NULL);
if (AddrNum == 0) {
return EFI_NOT_FOUND;
@@ -1058,7 +1132,7 @@ Dhcp6GenerateIaCb (
// Allocate for new IA.
//
IaSize = sizeof (EFI_DHCP6_IA) + (AddrNum - 1) * sizeof (EFI_DHCP6_IA_ADDRESS);
- Ia = AllocateZeroPool (IaSize);
+ Ia = AllocateZeroPool (IaSize);
if (Ia == NULL) {
return EFI_OUT_OF_RESOURCES;
@@ -1070,7 +1144,7 @@ Dhcp6GenerateIaCb (
Ia->State = Instance->IaCb.Ia->State;
Ia->IaAddressCount = AddrNum;
CopyMem (&Ia->Descriptor, &Instance->Config->IaDescriptor, sizeof (EFI_DHCP6_IA_DESCRIPTOR));
- Dhcp6ParseAddrOption (IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);
+ Dhcp6ParseAddrOption (Instance->IaCb.Ia, IaInnerOpt, IaInnerLen, &AddrNum, Ia->IaAddress);
//
// Free original IA resource.
@@ -1078,19 +1152,19 @@ Dhcp6GenerateIaCb (
if (Instance->IaCb.Ia->ReplyPacket != NULL) {
FreePool (Instance->IaCb.Ia->ReplyPacket);
}
- FreePool (Instance->IaCb.Ia);
+ FreePool (Instance->IaCb.Ia);
ZeroMem (&Instance->IaCb, sizeof (DHCP6_IA_CB));
//
// Update IaCb to use new IA.
//
- Instance->IaCb.Ia = Ia;
+ Instance->IaCb.Ia = Ia;
//
- // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.
+ // Fill in IaCb fields. Such as T1, T2, AllExpireTime and LeaseTime.
//
Instance->IaCb.T1 = T1;
Instance->IaCb.T2 = T2;
@@ -1099,7 +1173,6 @@ Dhcp6GenerateIaCb (
return EFI_SUCCESS;
}
-
/**
Cache the current IA configuration information.
@@ -1111,11 +1184,11 @@ Dhcp6GenerateIaCb (
**/
EFI_STATUS
Dhcp6CacheIa (
- IN DHCP6_INSTANCE *Instance
+ IN DHCP6_INSTANCE *Instance
)
{
- UINTN IaSize;
- EFI_DHCP6_IA *Ia;
+ UINTN IaSize;
+ EFI_DHCP6_IA *Ia;
Ia = Instance->IaCb.Ia;
@@ -1129,29 +1202,31 @@ Dhcp6CacheIa (
if (Instance->CacheIa == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+
CopyMem (Instance->CacheIa, Ia, IaSize);
}
+
return EFI_SUCCESS;
}
/**
- Append CacheIa to the currrent IA. Meanwhile, clear CacheIa.ValidLifetime to 0.
+ Append CacheIa to the current IA. Meanwhile, clear CacheIa.ValidLifetime to 0.
@param[in] Instance The pointer to DHCP6 instance.
**/
VOID
Dhcp6AppendCacheIa (
- IN DHCP6_INSTANCE *Instance
+ IN DHCP6_INSTANCE *Instance
)
{
- UINT8 *Ptr;
- UINTN Index;
- UINTN IaSize;
- UINTN NewIaSize;
- EFI_DHCP6_IA *Ia;
- EFI_DHCP6_IA *NewIa;
- EFI_DHCP6_IA *CacheIa;
+ UINT8 *Ptr;
+ UINTN Index;
+ UINTN IaSize;
+ UINTN NewIaSize;
+ EFI_DHCP6_IA *Ia;
+ EFI_DHCP6_IA *NewIa;
+ EFI_DHCP6_IA *CacheIa;
Ia = Instance->IaCb.Ia;
CacheIa = Instance->CacheIa;
@@ -1173,11 +1248,11 @@ Dhcp6AppendCacheIa (
// Clear old address.ValidLifetime
//
for (Index = 0; Index < CacheIa->IaAddressCount; Index++) {
- CacheIa->IaAddress[Index].ValidLifetime = 0;
+ CacheIa->IaAddress[Index].ValidLifetime = 0;
}
NewIa->IaAddressCount += CacheIa->IaAddressCount;
- Ptr = (UINT8*)&NewIa->IaAddress[Ia->IaAddressCount];
+ Ptr = (UINT8 *)&NewIa->IaAddress[Ia->IaAddressCount];
CopyMem (Ptr, CacheIa->IaAddress, CacheIa->IaAddressCount * sizeof (EFI_DHCP6_IA_ADDRESS));
//
@@ -1185,7 +1260,46 @@ Dhcp6AppendCacheIa (
//
FreePool (Instance->CacheIa);
FreePool (Instance->IaCb.Ia);
- Instance->CacheIa = NULL;
- Instance->IaCb.Ia = NewIa;
+ Instance->CacheIa = NULL;
+ Instance->IaCb.Ia = NewIa;
+ }
+}
+
+/**
+ Calculate the Dhcp6 get mapping timeout by adding additional delay to the IP6 DAD transmits count.
+
+ @param[in] Ip6Cfg The pointer to Ip6 config protocol.
+ @param[out] TimeOut The time out value in 100ns units.
+
+ @retval EFI_INVALID_PARAMETER Input parameters are invalid.
+ @retval EFI_SUCCESS Calculate the time out value successfully.
+**/
+EFI_STATUS
+Dhcp6GetMappingTimeOut (
+ IN EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg,
+ OUT UINTN *TimeOut
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
+
+ if ((Ip6Cfg == NULL) || (TimeOut == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeDupAddrDetectTransmits,
+ &DataSize,
+ &DadXmits
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+
+ *TimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + DHCP6_DAD_ADDITIONAL_DELAY;
+
+ return EFI_SUCCESS;
}