X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FHttpBootDxe%2FHttpBootDhcp6.c;h=b22cef4ff58743898c3ff863ab2a52f995b2dd2b;hb=HEAD;hp=2538bd116ca42ddb47c2081c4fab3e03c0399766;hpb=ce22514e4800dca7854a4778a66e8f08d2b18345;p=mirror_edk2.git diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c index 2538bd116c..b22cef4ff5 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c +++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c @@ -1,14 +1,8 @@ /** @file Functions implementation related with DHCPv6 for HTTP boot driver. -Copyright (c) 2016, 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 that 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. +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -26,70 +20,70 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ UINT32 HttpBootBuildDhcp6Options ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - OUT EFI_DHCP6_PACKET_OPTION **OptList, - IN UINT8 *Buffer + IN HTTP_BOOT_PRIVATE_DATA *Private, + OUT EFI_DHCP6_PACKET_OPTION **OptList, + IN UINT8 *Buffer ) { - HTTP_BOOT_DHCP6_OPTION_ENTRY OptEnt; - UINT16 Value; - UINT32 Index; + HTTP_BOOT_DHCP6_OPTION_ENTRY OptEnt; + UINT16 Value; + UINT32 Index; Index = 0; - OptList[0] = (EFI_DHCP6_PACKET_OPTION *) Buffer; + OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer; // // Append client option request option // - OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_ORO); - OptList[Index]->OpLen = HTONS (8); - OptEnt.Oro = (HTTP_BOOT_DHCP6_OPTION_ORO *) OptList[Index]->Data; - OptEnt.Oro->OpCode[0] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL); - OptEnt.Oro->OpCode[1] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM); - OptEnt.Oro->OpCode[2] = HTONS(HTTP_BOOT_DHCP6_OPT_DNS_SERVERS); - OptEnt.Oro->OpCode[3] = HTONS(HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS); + OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO); + OptList[Index]->OpLen = HTONS (8); + OptEnt.Oro = (HTTP_BOOT_DHCP6_OPTION_ORO *)OptList[Index]->Data; + OptEnt.Oro->OpCode[0] = HTONS (DHCP6_OPT_BOOT_FILE_URL); + OptEnt.Oro->OpCode[1] = HTONS (DHCP6_OPT_BOOT_FILE_PARAM); + OptEnt.Oro->OpCode[2] = HTONS (DHCP6_OPT_DNS_SERVERS); + OptEnt.Oro->OpCode[3] = HTONS (DHCP6_OPT_VENDOR_CLASS); Index++; - OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); // // Append client network device interface option // - OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_UNDI); - OptList[Index]->OpLen = HTONS ((UINT16)3); - OptEnt.Undi = (HTTP_BOOT_DHCP6_OPTION_UNDI *) OptList[Index]->Data; + OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI); + OptList[Index]->OpLen = HTONS ((UINT16)3); + OptEnt.Undi = (HTTP_BOOT_DHCP6_OPTION_UNDI *)OptList[Index]->Data; if (Private->Nii != NULL) { - OptEnt.Undi->Type = Private->Nii->Type; - OptEnt.Undi->MajorVer = Private->Nii->MajorVer; - OptEnt.Undi->MinorVer = Private->Nii->MinorVer; + OptEnt.Undi->Type = Private->Nii->Type; + OptEnt.Undi->MajorVer = Private->Nii->MajorVer; + OptEnt.Undi->MinorVer = Private->Nii->MinorVer; } else { - OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; - OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; - OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; + OptEnt.Undi->Type = DEFAULT_UNDI_TYPE; + OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR; + OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR; } Index++; - OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); // // Append client system architecture option // - OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_ARCH); - OptList[Index]->OpLen = HTONS ((UINT16) sizeof (HTTP_BOOT_DHCP6_OPTION_ARCH)); - OptEnt.Arch = (HTTP_BOOT_DHCP6_OPTION_ARCH *) OptList[Index]->Data; - Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE); + OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH); + OptList[Index]->OpLen = HTONS ((UINT16)sizeof (HTTP_BOOT_DHCP6_OPTION_ARCH)); + OptEnt.Arch = (HTTP_BOOT_DHCP6_OPTION_ARCH *)OptList[Index]->Data; + Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE); CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16)); Index++; - OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]); // // Append vendor class identify option. // - OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS); - OptList[Index]->OpLen = HTONS ((UINT16) sizeof (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS)); - OptEnt.VendorClass = (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data; + OptList[Index]->OpCode = HTONS (DHCP6_OPT_VENDOR_CLASS); + OptList[Index]->OpLen = HTONS ((UINT16)sizeof (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS)); + OptEnt.VendorClass = (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data; OptEnt.VendorClass->Vendor = HTONL (HTTP_BOOT_DHCP6_ENTERPRISE_NUM); - OptEnt.VendorClass->ClassLen = HTONS ((UINT16) sizeof (HTTP_BOOT_CLASS_ID)); + OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (HTTP_BOOT_CLASS_ID)); CopyMem ( &OptEnt.VendorClass->ClassId, DEFAULT_CLASS_ID_DATA, @@ -132,38 +126,35 @@ HttpBootBuildDhcp6Options ( @param[in] OptTag The required option tag. @retval NULL Failed to parse the required option. - @retval Others The postion of the required option in buffer. + @retval Others The position of the required option in buffer. **/ EFI_DHCP6_PACKET_OPTION * HttpBootParseDhcp6Options ( - IN UINT8 *Buffer, - IN UINT32 Length, - IN UINT16 OptTag + IN UINT8 *Buffer, + IN UINT32 Length, + IN UINT16 OptTag ) { - EFI_DHCP6_PACKET_OPTION *Option; - UINT32 Offset; + EFI_DHCP6_PACKET_OPTION *Option; + UINT32 Offset; - Option = (EFI_DHCP6_PACKET_OPTION *) Buffer; - Offset = 0; + Option = (EFI_DHCP6_PACKET_OPTION *)Buffer; + Offset = 0; // // OpLen and OpCode here are both stored in network order. // while (Offset < Length) { - if (NTOHS (Option->OpCode) == OptTag) { - return Option; } - Offset += (NTOHS(Option->OpLen) + 4); - Option = (EFI_DHCP6_PACKET_OPTION *) (Buffer + Offset); + Offset += (NTOHS (Option->OpLen) + 4); + Option = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset); } return NULL; - } /** @@ -177,70 +168,70 @@ HttpBootParseDhcp6Options ( **/ EFI_STATUS HttpBootParseDhcp6Packet ( - IN HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6 + IN HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6 ) { - EFI_DHCP6_PACKET *Offer; - EFI_DHCP6_PACKET_OPTION **Options; - EFI_DHCP6_PACKET_OPTION *Option; - HTTP_BOOT_OFFER_TYPE OfferType; - EFI_IPv6_ADDRESS IpAddr; - BOOLEAN IsProxyOffer; - BOOLEAN IsHttpOffer; - BOOLEAN IsDnsOffer; - BOOLEAN IpExpressedUri; - EFI_STATUS Status; - UINT32 Offset; - UINT32 Length; - + EFI_DHCP6_PACKET *Offer; + EFI_DHCP6_PACKET_OPTION **Options; + EFI_DHCP6_PACKET_OPTION *Option; + HTTP_BOOT_OFFER_TYPE OfferType; + EFI_IPv6_ADDRESS IpAddr; + BOOLEAN IsProxyOffer; + BOOLEAN IsHttpOffer; + BOOLEAN IsDnsOffer; + BOOLEAN IpExpressedUri; + EFI_STATUS Status; + UINT32 Offset; + UINT32 Length; + IsDnsOffer = FALSE; IpExpressedUri = FALSE; IsProxyOffer = TRUE; IsHttpOffer = FALSE; - Offer = &Cache6->Packet.Offer; - Options = Cache6->OptList; - + Offer = &Cache6->Packet.Offer; + Options = Cache6->OptList; + ZeroMem (Cache6->OptList, sizeof (Cache6->OptList)); - Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option); - Offset = 0; - Length = GET_DHCP6_OPTION_SIZE (Offer); + Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option); + Offset = 0; + Length = GET_DHCP6_OPTION_SIZE (Offer); // // OpLen and OpCode here are both stored in network order, since they are from original packet. // while (Offset < Length) { - - if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_IA_NA) { + if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) { Options[HTTP_BOOT_DHCP6_IDX_IA_NA] = Option; - } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL) { + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) { // // The server sends this option to inform the client about an URL to a boot file. // Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] = Option; - } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM) { + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_PARAM) { Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_PARAM] = Option; - } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS) { + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_VENDOR_CLASS) { Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS] = Option; - } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_DNS_SERVERS) { + } else if (NTOHS (Option->OpCode) == DHCP6_OPT_DNS_SERVERS) { Options[HTTP_BOOT_DHCP6_IDX_DNS_SERVER] = Option; } Offset += (NTOHS (Option->OpLen) + 4); - Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option + Offset); + Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset); } + // // The offer with assigned client address is NOT a proxy offer. - // An ia_na option, embeded with valid ia_addr option and a status_code of success. + // An ia_na option, embedded with valid ia_addr option and a status_code of success. // Option = Options[HTTP_BOOT_DHCP6_IDX_IA_NA]; if (Option != NULL) { Option = HttpBootParseDhcp6Options ( Option->Data + 12, NTOHS (Option->OpLen), - HTTP_BOOT_DHCP6_OPT_STATUS_CODE + DHCP6_OPT_STATUS_CODE ); - if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) { + if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) { IsProxyOffer = FALSE; } } @@ -250,10 +241,11 @@ HttpBootParseDhcp6Packet ( // Option = Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS]; - if (Option != NULL && - NTOHS(Option->OpLen) >= 10 && - CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 10) == 0) { - IsHttpOffer = TRUE; + if ((Option != NULL) && + (NTOHS (Option->OpLen) >= 16) && + (CompareMem ((Option->Data + 6), DEFAULT_CLASS_ID_DATA, 10) == 0)) + { + IsHttpOffer = TRUE; } // @@ -267,17 +259,17 @@ HttpBootParseDhcp6Packet ( // // Http offer must have a boot URI. // - if (IsHttpOffer && Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] == NULL) { + if (IsHttpOffer && (Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] == NULL)) { return EFI_DEVICE_ERROR; } - + // - // Try to retrieve the IP of HTTP server from URI. + // Try to retrieve the IP of HTTP server from URI. // if (IsHttpOffer) { Status = HttpParseUrl ( - (CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data, - (UINT32) AsciiStrLen ((CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data), + (CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data, + (UINT32)AsciiStrLen ((CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data), FALSE, &Cache6->UriParser ); @@ -286,7 +278,7 @@ HttpBootParseDhcp6Packet ( } Status = HttpUrlGetIp6 ( - (CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data, + (CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data, Cache6->UriParser, &IpAddr ); @@ -298,7 +290,11 @@ HttpBootParseDhcp6Packet ( // if (IsHttpOffer) { if (IpExpressedUri) { - OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri : HttpOfferTypeDhcpIpUri; + if (IsProxyOffer) { + OfferType = HttpOfferTypeProxyIpUri; + } else { + OfferType = IsDnsOffer ? HttpOfferTypeDhcpIpUriDns : HttpOfferTypeDhcpIpUri; + } } else { if (!IsProxyOffer) { OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : HttpOfferTypeDhcpNameUri; @@ -306,7 +302,6 @@ HttpBootParseDhcp6Packet ( OfferType = HttpOfferTypeProxyNameUri; } } - } else { if (!IsProxyOffer) { OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly; @@ -314,7 +309,7 @@ HttpBootParseDhcp6Packet ( return EFI_DEVICE_ERROR; } } - + Cache6->OfferType = OfferType; return EFI_SUCCESS; } @@ -325,17 +320,24 @@ HttpBootParseDhcp6Packet ( @param[in] Dst The pointer to the cache buffer for DHCPv6 packet. @param[in] Src The pointer to the DHCPv6 packet to be cached. + @retval EFI_SUCCESS Packet is copied. + @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet. + **/ -VOID +EFI_STATUS HttpBootCacheDhcp6Packet ( - IN EFI_DHCP6_PACKET *Dst, - IN EFI_DHCP6_PACKET *Src + IN EFI_DHCP6_PACKET *Dst, + IN EFI_DHCP6_PACKET *Src ) { - ASSERT (Dst->Size >= Src->Length); + if (Dst->Size < Src->Length) { + return EFI_BUFFER_TOO_SMALL; + } CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length); Dst->Length = Src->Length; + + return EFI_SUCCESS; } /** @@ -344,16 +346,20 @@ HttpBootCacheDhcp6Packet ( @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. @param[in] RcvdOffer The pointer to the received offer packet. + @retval EFI_SUCCESS Cache and parse the packet successfully. + @retval Others Operation failed. + **/ -VOID +EFI_STATUS HttpBootCacheDhcp6Offer ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN EFI_DHCP6_PACKET *RcvdOffer ) { - HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6; - EFI_DHCP6_PACKET *Offer; - HTTP_BOOT_OFFER_TYPE OfferType; + HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6; + EFI_DHCP6_PACKET *Offer; + HTTP_BOOT_OFFER_TYPE OfferType; + EFI_STATUS Status; Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6; Offer = &Cache6->Packet.Offer; @@ -361,13 +367,16 @@ HttpBootCacheDhcp6Offer ( // // Cache the content of DHCPv6 packet firstly. // - HttpBootCacheDhcp6Packet(Offer, RcvdOffer); + Status = HttpBootCacheDhcp6Packet (Offer, RcvdOffer); + if (EFI_ERROR (Status)) { + return Status; + } // // Validate the DHCPv6 packet, and parse the options and offer type. // if (EFI_ERROR (HttpBootParseDhcp6Packet (Cache6))) { - return ; + return EFI_ABORTED; } // @@ -378,7 +387,9 @@ HttpBootCacheDhcp6Offer ( ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM); Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum; Private->OfferCount[OfferType]++; - Private->OfferNum++; + Private->OfferNum++; + + return EFI_SUCCESS; } /** @@ -397,71 +408,105 @@ HttpBootCacheDhcp6Offer ( @retval EFI_NOT_READY Only used in the Dhcp6Selecting state. The EFI DHCPv6 Protocol driver will continue to wait for more packets. @retval EFI_ABORTED Told the EFI DHCPv6 Protocol driver to abort the current process. + @retval EFI_OUT_OF_RESOURCES There are not enough resources. **/ EFI_STATUS EFIAPI HttpBootDhcp6CallBack ( - IN EFI_DHCP6_PROTOCOL *This, - IN VOID *Context, - IN EFI_DHCP6_STATE CurrentState, - IN EFI_DHCP6_EVENT Dhcp6Event, - IN EFI_DHCP6_PACKET *Packet, - OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL + IN EFI_DHCP6_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP6_STATE CurrentState, + IN EFI_DHCP6_EVENT Dhcp6Event, + IN EFI_DHCP6_PACKET *Packet, + OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL ) { - HTTP_BOOT_PRIVATE_DATA *Private; - EFI_DHCP6_PACKET *SelectAd; - EFI_STATUS Status; - if ((Dhcp6Event != Dhcp6RcvdAdvertise) && (Dhcp6Event != Dhcp6SelectAdvertise)) { - return EFI_SUCCESS; - } - - ASSERT (Packet != NULL); - - Private = (HTTP_BOOT_PRIVATE_DATA *) Context; - Status = EFI_SUCCESS; - switch (Dhcp6Event) { - - case Dhcp6RcvdAdvertise: - Status = EFI_NOT_READY; - if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { - // - // Cache the dhcp offers to OfferBuffer[] for select later, and record - // the OfferIndex and OfferCount. - // - HttpBootCacheDhcp6Offer (Private, Packet); - } - break; - - case Dhcp6SelectAdvertise: - // - // Select offer by the default policy or by order, and record the SelectIndex - // and SelectProxyType. - // - HttpBootSelectDhcpOffer (Private); - - if (Private->SelectIndex == 0) { - Status = EFI_ABORTED; - } else { - ASSERT (NewPacket != NULL); - SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; - *NewPacket = AllocateZeroPool (SelectAd->Size); - ASSERT (*NewPacket != NULL); - CopyMem (*NewPacket, SelectAd, SelectAd->Size); - } - break; - - default: - break; - } - - return Status; + HTTP_BOOT_PRIVATE_DATA *Private; + EFI_DHCP6_PACKET *SelectAd; + EFI_STATUS Status; + BOOLEAN Received; + + if ((Dhcp6Event != Dhcp6SendSolicit) && + (Dhcp6Event != Dhcp6RcvdAdvertise) && + (Dhcp6Event != Dhcp6SendRequest) && + (Dhcp6Event != Dhcp6RcvdReply) && + (Dhcp6Event != Dhcp6SelectAdvertise)) + { + return EFI_SUCCESS; + } + + ASSERT (Packet != NULL); + + Private = (HTTP_BOOT_PRIVATE_DATA *)Context; + Status = EFI_SUCCESS; + if ((Private->HttpBootCallback != NULL) && (Dhcp6Event != Dhcp6SelectAdvertise)) { + Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply); + Status = Private->HttpBootCallback->Callback ( + Private->HttpBootCallback, + HttpBootDhcp6, + Received, + Packet->Length, + &Packet->Dhcp6 + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + } + + switch (Dhcp6Event) { + case Dhcp6RcvdAdvertise: + Status = EFI_NOT_READY; + if (Packet->Length > HTTP_BOOT_DHCP6_PACKET_MAX_SIZE) { + // + // Ignore the incoming packets which exceed the maximum length. + // + break; + } + + if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) { + // + // Cache the dhcp offers to OfferBuffer[] for select later, and record + // the OfferIndex and OfferCount. + // If error happens, just ignore this packet and continue to wait more offer. + // + HttpBootCacheDhcp6Offer (Private, Packet); + } + + break; + + case Dhcp6SelectAdvertise: + // + // Select offer by the default policy or by order, and record the SelectIndex + // and SelectProxyType. + // + HttpBootSelectDhcpOffer (Private); + + if (Private->SelectIndex == 0) { + Status = EFI_ABORTED; + } else { + ASSERT (NewPacket != NULL); + SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer; + *NewPacket = AllocateZeroPool (SelectAd->Size); + if (*NewPacket == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (*NewPacket, SelectAd, SelectAd->Size); + } + + break; + + default: + break; + } + + return Status; } /** Check whether IP driver could route the message which will be sent to ServerIp address. - + This function will check the IP6 route table every 1 seconds until specified timeout is expired, if a valid route is found in IP6 route table, the address will be filed in GatewayAddr and return. @@ -471,23 +516,23 @@ HttpBootDhcp6CallBack ( @retval EFI_SUCCESS Found a valid gateway address successfully. @retval EFI_TIMEOUT The operation is time out. - @retval Other Unexpect error happened. - + @retval Other Unexpected error happened. + **/ EFI_STATUS HttpBootCheckRouteTable ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN UINTN TimeOutInSecond, - OUT EFI_IPv6_ADDRESS *GatewayAddr + IN HTTP_BOOT_PRIVATE_DATA *Private, + IN UINTN TimeOutInSecond, + OUT EFI_IPv6_ADDRESS *GatewayAddr ) { - EFI_STATUS Status; - EFI_IP6_PROTOCOL *Ip6; - EFI_IP6_MODE_DATA Ip6ModeData; - UINTN Index; - EFI_EVENT TimeOutEvt; - UINTN RetryCount; - BOOLEAN GatewayIsFound; + EFI_STATUS Status; + EFI_IP6_PROTOCOL *Ip6; + EFI_IP6_MODE_DATA Ip6ModeData; + UINTN Index; + EFI_EVENT TimeOutEvt; + UINTN RetryCount; + BOOLEAN GatewayIsFound; ASSERT (GatewayAddr != NULL); ASSERT (Private != NULL); @@ -504,7 +549,7 @@ HttpBootCheckRouteTable ( if (EFI_ERROR (Status)) { goto ON_EXIT; } - + // // Find out the gateway address which can route the message which send to ServerIp. // @@ -519,28 +564,33 @@ HttpBootCheckRouteTable ( if (Ip6ModeData.AddressList != NULL) { FreePool (Ip6ModeData.AddressList); } + if (Ip6ModeData.GroupTable != NULL) { FreePool (Ip6ModeData.GroupTable); } + if (Ip6ModeData.RouteTable != NULL) { FreePool (Ip6ModeData.RouteTable); } + if (Ip6ModeData.NeighborCache != NULL) { FreePool (Ip6ModeData.NeighborCache); } + if (Ip6ModeData.PrefixTable != NULL) { FreePool (Ip6ModeData.PrefixTable); } + if (Ip6ModeData.IcmpTypeList != NULL) { FreePool (Ip6ModeData.IcmpTypeList); } - - if (GatewayIsFound || RetryCount == TimeOutInSecond) { + + if (GatewayIsFound || (RetryCount == TimeOutInSecond)) { break; } - + RetryCount++; - + // // Delay 1 second then recheck it again. // @@ -561,23 +611,24 @@ HttpBootCheckRouteTable ( if (EFI_ERROR (Status)) { goto ON_EXIT; } + while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) { Ip6->Poll (Ip6); } } - + ON_EXIT: if (TimeOutEvt != NULL) { gBS->CloseEvent (TimeOutEvt); } - + if (GatewayIsFound) { Status = EFI_SUCCESS; } else if (RetryCount == TimeOutInSecond) { Status = EFI_TIMEOUT; } - return Status; + return Status; } /** @@ -585,23 +636,23 @@ ON_EXIT: @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. - @retval EFI_SUCCESS Switch the IP policy succesfully. - @retval Others Unexpect error happened. + @retval EFI_SUCCESS Switch the IP policy successfully. + @retval Others Unexpected error happened. **/ EFI_STATUS HttpBootSetIp6Policy ( - IN HTTP_BOOT_PRIVATE_DATA *Private + IN HTTP_BOOT_PRIVATE_DATA *Private ) { - EFI_IP6_CONFIG_POLICY Policy; - EFI_IP6_CONFIG_PROTOCOL *Ip6Config; - EFI_STATUS Status; - UINTN DataSize; + EFI_IP6_CONFIG_POLICY Policy; + EFI_IP6_CONFIG_PROTOCOL *Ip6Config; + EFI_STATUS Status; + UINTN DataSize; + + Ip6Config = Private->Ip6Config; + DataSize = sizeof (EFI_IP6_CONFIG_POLICY); - Ip6Config = Private->Ip6Config; - DataSize = sizeof (EFI_IP6_CONFIG_POLICY); - // // Get and store the current policy of IP6 driver. // @@ -620,19 +671,20 @@ HttpBootSetIp6Policy ( Status = Ip6Config->SetData ( Ip6Config, Ip6ConfigDataTypePolicy, - sizeof(EFI_IP6_CONFIG_POLICY), + sizeof (EFI_IP6_CONFIG_POLICY), &Policy ); if (EFI_ERROR (Status)) { return Status; } } + return EFI_SUCCESS; } /** This function will register the default DNS addresses to the network device. - + @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes. @param[in] DnsServerData Point a list of DNS server address in an array @@ -644,17 +696,17 @@ HttpBootSetIp6Policy ( **/ EFI_STATUS HttpBootSetIp6Dns ( - IN HTTP_BOOT_PRIVATE_DATA *Private, - IN UINTN DataLength, - IN VOID *DnsServerData + IN HTTP_BOOT_PRIVATE_DATA *Private, + IN UINTN DataLength, + IN VOID *DnsServerData ) { - EFI_IP6_CONFIG_PROTOCOL *Ip6Config; - + EFI_IP6_CONFIG_PROTOCOL *Ip6Config; + ASSERT (Private->UsingIpv6); Ip6Config = Private->Ip6Config; - + return Ip6Config->SetData ( Ip6Config, Ip6ConfigDataTypeDnsServer, @@ -665,7 +717,7 @@ HttpBootSetIp6Dns ( /** This function will register the IPv6 gateway address to the network device. - + @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. @retval EFI_SUCCESS The new IP configuration has been configured successfully. @@ -674,17 +726,17 @@ HttpBootSetIp6Dns ( **/ EFI_STATUS HttpBootSetIp6Gateway ( - IN HTTP_BOOT_PRIVATE_DATA *Private + IN HTTP_BOOT_PRIVATE_DATA *Private ) { - EFI_IP6_CONFIG_PROTOCOL *Ip6Config; - EFI_STATUS Status; + EFI_IP6_CONFIG_PROTOCOL *Ip6Config; + EFI_STATUS Status; ASSERT (Private->UsingIpv6); Ip6Config = Private->Ip6Config; - + // - // Set the default gateway address. + // Set the default gateway address. // if (!Private->NoGateway && !NetIp6IsUnspecifiedAddr (&Private->GatewayIp.v6)) { Status = Ip6Config->SetData ( @@ -693,7 +745,7 @@ HttpBootSetIp6Gateway ( sizeof (EFI_IPv6_ADDRESS), &Private->GatewayIp.v6 ); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { return Status; } } @@ -703,7 +755,7 @@ HttpBootSetIp6Gateway ( /** This function will register the station IP address. - + @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA. @retval EFI_SUCCESS The new IP address has been configured successfully. @@ -712,40 +764,40 @@ HttpBootSetIp6Gateway ( **/ EFI_STATUS HttpBootSetIp6Address ( - IN HTTP_BOOT_PRIVATE_DATA *Private -) + IN HTTP_BOOT_PRIVATE_DATA *Private + ) { - EFI_STATUS Status; - EFI_IP6_PROTOCOL *Ip6; - EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; - EFI_IP6_CONFIG_POLICY Policy; - EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; - EFI_IPv6_ADDRESS *Ip6Addr; - EFI_IPv6_ADDRESS GatewayAddr; - EFI_IP6_CONFIG_DATA Ip6CfgData; - EFI_EVENT MappedEvt; - UINTN DataSize; - BOOLEAN IsAddressOk; - UINTN Index; + EFI_STATUS Status; + EFI_IP6_PROTOCOL *Ip6; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; + EFI_IP6_CONFIG_POLICY Policy; + EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr; + EFI_IPv6_ADDRESS *Ip6Addr; + EFI_IPv6_ADDRESS GatewayAddr; + EFI_IP6_CONFIG_DATA Ip6CfgData; + EFI_EVENT MappedEvt; + UINTN DataSize; + BOOLEAN IsAddressOk; + UINTN Index; ASSERT (Private->UsingIpv6); - + MappedEvt = NULL; IsAddressOk = FALSE; Ip6Addr = NULL; Ip6Cfg = Private->Ip6Config; Ip6 = Private->Ip6; - + ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); CopyMem (&CfgAddr, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS)); ZeroMem (&Ip6CfgData, sizeof (EFI_IP6_CONFIG_DATA)); - - Ip6CfgData.AcceptIcmpErrors = TRUE; - Ip6CfgData.DefaultProtocol = IP6_ICMP; - Ip6CfgData.HopLimit = HTTP_BOOT_DEFAULT_HOPLIMIT; - Ip6CfgData.ReceiveTimeout = HTTP_BOOT_DEFAULT_LIFETIME; - Ip6CfgData.TransmitTimeout = HTTP_BOOT_DEFAULT_LIFETIME; - + + Ip6CfgData.AcceptIcmpErrors = TRUE; + Ip6CfgData.DefaultProtocol = IP6_ICMP; + Ip6CfgData.HopLimit = HTTP_BOOT_DEFAULT_HOPLIMIT; + Ip6CfgData.ReceiveTimeout = HTTP_BOOT_DEFAULT_LIFETIME; + Ip6CfgData.TransmitTimeout = HTTP_BOOT_DEFAULT_LIFETIME; + Status = Ip6->Configure (Ip6, &Ip6CfgData); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -768,13 +820,13 @@ HttpBootSetIp6Address ( Status = Ip6Cfg->SetData ( Ip6Cfg, Ip6ConfigDataTypePolicy, - sizeof(EFI_IP6_CONFIG_POLICY), + sizeof (EFI_IP6_CONFIG_POLICY), &Policy ); if (EFI_ERROR (Status)) { goto ON_EXIT; } - + // // Create a notify event to set address flag when DAD if IP6 driver succeeded. // @@ -788,7 +840,7 @@ HttpBootSetIp6Address ( if (EFI_ERROR (Status)) { goto ON_EXIT; } - + // // Set static host ip6 address. This is a asynchronous process. // @@ -797,7 +849,7 @@ HttpBootSetIp6Address ( Ip6ConfigDataTypeManualAddress, MappedEvt ); - if (EFI_ERROR(Status)) { + if (EFI_ERROR (Status)) { goto ON_EXIT; } @@ -806,8 +858,8 @@ HttpBootSetIp6Address ( Ip6ConfigDataTypeManualAddress, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS), &CfgAddr - ); - if (EFI_ERROR (Status) && Status != EFI_NOT_READY) { + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { goto ON_EXIT; } else if (Status == EFI_NOT_READY) { // @@ -816,47 +868,50 @@ HttpBootSetIp6Address ( while (!IsAddressOk) { Ip6->Poll (Ip6); } + // // Check whether the Ip6 Address setting is successed. // DataSize = 0; - Status = Ip6Cfg->GetData ( - Ip6Cfg, - Ip6ConfigDataTypeManualAddress, - &DataSize, - NULL - ); - if (Status != EFI_BUFFER_TOO_SMALL || DataSize == 0) { + Status = Ip6Cfg->GetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, + &DataSize, + NULL + ); + if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) { Status = EFI_DEVICE_ERROR; goto ON_EXIT; } - + Ip6Addr = AllocatePool (DataSize); if (Ip6Addr == NULL) { return EFI_OUT_OF_RESOURCES; } + Status = Ip6Cfg->GetData ( Ip6Cfg, Ip6ConfigDataTypeManualAddress, &DataSize, - (VOID *) Ip6Addr + (VOID *)Ip6Addr ); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto ON_EXIT; } - for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index ++) { + for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index++) { if (CompareMem (Ip6Addr + Index, &CfgAddr, sizeof (EFI_IPv6_ADDRESS)) == 0) { break; } } + if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) { Status = EFI_ABORTED; goto ON_EXIT; - } + } } - + ON_EXIT: if (MappedEvt != NULL) { Ip6Cfg->UnregisterDataNotify ( @@ -870,8 +925,8 @@ ON_EXIT: if (Ip6Addr != NULL) { FreePool (Ip6Addr); } - - return Status; + + return Status; } /** @@ -885,17 +940,17 @@ ON_EXIT: **/ EFI_STATUS HttpBootDhcp6Sarr ( - IN HTTP_BOOT_PRIVATE_DATA *Private + IN HTTP_BOOT_PRIVATE_DATA *Private ) { - EFI_DHCP6_PROTOCOL *Dhcp6; - EFI_DHCP6_CONFIG_DATA Config; - EFI_DHCP6_MODE_DATA Mode; - EFI_DHCP6_RETRANSMISSION *Retransmit; - EFI_DHCP6_PACKET_OPTION *OptList[HTTP_BOOT_DHCP6_OPTION_MAX_NUM]; - UINT32 OptCount; - UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE]; - EFI_STATUS Status; + EFI_DHCP6_PROTOCOL *Dhcp6; + EFI_DHCP6_CONFIG_DATA Config; + EFI_DHCP6_MODE_DATA Mode; + EFI_DHCP6_RETRANSMISSION *Retransmit; + EFI_DHCP6_PACKET_OPTION *OptList[HTTP_BOOT_DHCP6_OPTION_MAX_NUM]; + UINT32 OptCount; + UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE]; + EFI_STATUS Status; Dhcp6 = Private->Dhcp6; ASSERT (Dhcp6 != NULL); @@ -904,16 +959,16 @@ HttpBootDhcp6Sarr ( // Build options list for the request packet. // OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer); - ASSERT (OptCount >0); - + ASSERT (OptCount > 0); + Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION)); if (Retransmit == NULL) { return EFI_OUT_OF_RESOURCES; } - + ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA)); ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA)); - + Config.OptionCount = OptCount; Config.OptionList = OptList; Config.Dhcp6Callback = HttpBootDhcp6CallBack; @@ -928,7 +983,7 @@ HttpBootDhcp6Sarr ( Retransmit->Mrc = 4; Retransmit->Mrt = 32; Retransmit->Mrd = 60; - + // // Configure the DHCPv6 instance for HTTP boot. // @@ -937,14 +992,15 @@ HttpBootDhcp6Sarr ( if (EFI_ERROR (Status)) { goto ON_EXIT; } + // // Initialize the record fields for DHCPv6 offer in private data. // - Private->OfferNum = 0; - Private->SelectIndex = 0; + Private->OfferNum = 0; + Private->SelectIndex = 0; ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); - + // // Start DHCPv6 S.A.R.R. process to acquire IPv6 address. // @@ -952,7 +1008,7 @@ HttpBootDhcp6Sarr ( if (EFI_ERROR (Status)) { goto ON_EXIT; } - + // // Get the acquired IPv6 address and store them. // @@ -960,14 +1016,14 @@ HttpBootDhcp6Sarr ( if (EFI_ERROR (Status)) { goto ON_EXIT; } - + ASSERT (Mode.Ia->State == Dhcp6Bound); CopyMem (&Private->StationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS)); - + AsciiPrint ("\n Station IPv6 address is "); HttpBootShowIp6Addr (&Private->StationIp.v6); AsciiPrint ("\n"); - + ON_EXIT: if (EFI_ERROR (Status)) { Dhcp6->Stop (Dhcp6); @@ -978,12 +1034,11 @@ ON_EXIT: if (Mode.ClientId != NULL) { FreePool (Mode.ClientId); } + if (Mode.Ia != NULL) { FreePool (Mode.Ia); } } - return Status; - + return Status; } -