X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FDhcp6Dxe%2FDhcp6Utility.c;h=a65ed6d5892b59c861ab6181e632b67a37a6413d;hb=03f9cc20b851ce60f5a629381c288f502eb9432c;hp=ac0e577f5e333eaae1661d606c58520cc4dc4e1b;hpb=33c09637c6017fb6882d4a54f40a347adf4a05b8;p=mirror_edk2.git diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c index ac0e577f5e..a65ed6d589 100644 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c @@ -1,7 +1,8 @@ /** @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 - 2017, 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 @@ -41,7 +42,7 @@ Dhcp6GenerateClientId ( // 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,7 +64,7 @@ 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: @@ -143,10 +144,10 @@ Dhcp6GenerateClientId ( // // 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); } @@ -157,7 +158,10 @@ Dhcp6GenerateClientId ( Duid->Length + 2, (VOID *) Duid ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + FreePool (Duid); + return NULL; + } return Duid; } @@ -383,7 +387,6 @@ Dhcp6CalculateLeaseTime ( IN DHCP6_IA_CB *IaCb ) { - EFI_DHCP6_IA_ADDRESS *IaAddr; UINT32 MinLt; UINT32 MaxLt; UINTN Index; @@ -398,9 +401,8 @@ Dhcp6CalculateLeaseTime ( // 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); } // @@ -647,6 +649,75 @@ Dhcp6AppendOption ( 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,6 +726,7 @@ 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. @@ -664,13 +736,13 @@ Dhcp6AppendIaOption ( IN OUT UINT8 *Buf, IN EFI_DHCP6_IA *Ia, IN UINT32 T1, - IN UINT32 T2 + IN UINT32 T2, + IN UINT32 MessageType ) { UINT8 *AddrOpt; UINT16 *Len; UINTN Index; - UINT16 Length; // // The format of IA_NA and IA_TA option: @@ -713,9 +785,9 @@ Dhcp6AppendIaOption ( // 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)); + WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff)); Buf += 4; - WriteUnaligned32 ((UINT32 *) Buf, ((T2 != 0) ? T2 : 0xffffffff)); + WriteUnaligned32 ((UINT32 *) Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff)); Buf += 4; } @@ -723,15 +795,8 @@ Dhcp6AppendIaOption ( // 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); } // @@ -827,7 +892,7 @@ SetElapsedTime ( // // 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) { @@ -934,10 +999,39 @@ Dhcp6SeekIaOption ( return Option; } +/** + Check whether the incoming IPv6 address in IaAddr is one of the maintained + addresses in the IA control blcok. + + @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. + @param[in] CurrentIa The pointer to the Ia Address in control blcok. @param[in] IaInnerOpt The pointer to the buffer. @param[in] IaInnerLen The length to parse. @param[out] AddrNum The number of addresses. @@ -946,6 +1040,7 @@ Dhcp6SeekIaOption ( **/ VOID Dhcp6ParseAddrOption ( + IN EFI_DHCP6_IA *CurrentIa, IN UINT8 *IaInnerOpt, IN UINT16 IaInnerLen, OUT UINT32 *AddrNum, @@ -956,6 +1051,8 @@ Dhcp6ParseAddrOption ( UINT16 DataLen; UINT16 OpCode; UINT32 ValidLt; + UINT32 PreferredLt; + EFI_DHCP6_IA_ADDRESS *IaAddr; // // The format of the IA Address option: @@ -992,19 +1089,21 @@ 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) { - + 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); + 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))); @@ -1025,6 +1124,7 @@ 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 @@ -1041,14 +1141,14 @@ Dhcp6GenerateIaCb ( 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; @@ -1070,7 +1170,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. @@ -1189,3 +1289,42 @@ Dhcp6AppendCacheIa ( Instance->IaCb.Ia = NewIa; } } + +/** + Calculate the Dhcp6 get mapping timeout by adding additinal 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; +}