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; }