]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
MdeModulePkg: Replace ASSERT with error return code in PXE driver.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDhcp6.c
index 6ad5f5f1ac9fd5eb318a3fcd55e597d13e92dbd7..6a08e9a2de68a56cebf1c71174ec6364af4119bc 100644 (file)
@@ -2,7 +2,7 @@
   Functions implementation related with DHCPv6 for UefiPxeBc Driver.\r
 \r
   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -92,18 +92,19 @@ PxeBcBuildDhcp6Options (
   //\r
   // Append client option request option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ORO);\r
-  OptList[Index]->OpLen      = HTONS (4);\r
+  OptList[Index]->OpCode     = HTONS (DHCP6_OPT_ORO);\r
+  OptList[Index]->OpLen      = HTONS (6);\r
   OptEnt.Oro                 = (PXEBC_DHCP6_OPTION_ORO *) OptList[Index]->Data;\r
-  OptEnt.Oro->OpCode[0]      = HTONS(PXEBC_DHCP6_OPT_BOOT_FILE_URL);\r
-  OptEnt.Oro->OpCode[1]      = HTONS(PXEBC_DHCP6_OPT_BOOT_FILE_PARAM);\r
+  OptEnt.Oro->OpCode[0]      = HTONS(DHCP6_OPT_BOOT_FILE_URL);\r
+  OptEnt.Oro->OpCode[1]      = HTONS(DHCP6_OPT_BOOT_FILE_PARAM);\r
+  OptEnt.Oro->OpCode[2]      = HTONS(DHCP6_OPT_DNS_SERVERS);\r
   Index++;\r
   OptList[Index]             = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
 \r
   //\r
   // Append client network device interface option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_UNDI);\r
+  OptList[Index]->OpCode     = HTONS (DHCP6_OPT_UNDI);\r
   OptList[Index]->OpLen      = HTONS ((UINT16)3);\r
   OptEnt.Undi                = (PXEBC_DHCP6_OPTION_UNDI *) OptList[Index]->Data;\r
 \r
@@ -123,7 +124,7 @@ PxeBcBuildDhcp6Options (
   //\r
   // Append client system architecture option\r
   //\r
-  OptList[Index]->OpCode     = HTONS (PXEBC_DHCP6_OPT_ARCH);\r
+  OptList[Index]->OpCode     = HTONS (DHCP6_OPT_ARCH);\r
   OptList[Index]->OpLen      = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_ARCH));\r
   OptEnt.Arch                = (PXEBC_DHCP6_OPTION_ARCH *) OptList[Index]->Data;\r
   Value                      = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);\r
@@ -134,7 +135,7 @@ PxeBcBuildDhcp6Options (
   //\r
   // Append vendor class option to store the PXE class identifier.\r
   //\r
-  OptList[Index]->OpCode       = HTONS (PXEBC_DHCP6_OPT_VENDOR_CLASS);\r
+  OptList[Index]->OpCode       = HTONS (DHCP6_OPT_VENDOR_CLASS);\r
   OptList[Index]->OpLen        = HTONS ((UINT16) sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS));\r
   OptEnt.VendorClass           = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data;\r
   OptEnt.VendorClass->Vendor   = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM);\r
@@ -216,10 +217,173 @@ PxeBcFreeBootFileOption (
   }\r
 }\r
 \r
+/**\r
+  Retrieve the boot server address using the EFI_DNS6_PROTOCOL.\r
+\r
+  @param[in]  Private             Pointer to PxeBc private data.\r
+  @param[in]  HostName            Pointer to buffer containing hostname.\r
+  @param[out] IpAddress           On output, pointer to buffer containing IPv6 address.\r
+\r
+  @retval EFI_SUCCESS             Operation succeeded.\r
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate needed resources.\r
+  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.\r
+  @retval Others                  Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+PxeBcDns6 (\r
+  IN PXEBC_PRIVATE_DATA           *Private,\r
+  IN     CHAR16                   *HostName,\r
+     OUT EFI_IPv6_ADDRESS         *IpAddress                \r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_DNS6_PROTOCOL               *Dns6;\r
+  EFI_DNS6_CONFIG_DATA            Dns6ConfigData;\r
+  EFI_DNS6_COMPLETION_TOKEN       Token;\r
+  EFI_HANDLE                      Dns6Handle;\r
+  EFI_IPv6_ADDRESS                *DnsServerList;\r
+  BOOLEAN                         IsDone;\r
+  \r
+  Dns6                = NULL;\r
+  Dns6Handle          = NULL;\r
+  DnsServerList       = Private->DnsServer;\r
+  ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
+\r
+  //\r
+  // Create a DNSv6 child instance and get the protocol.\r
+  //\r
+  Status = NetLibCreateServiceChild (\r
+             Private->Controller,\r
+             Private->Image,\r
+             &gEfiDns6ServiceBindingProtocolGuid,\r
+             &Dns6Handle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  } \r
+  \r
+  Status = gBS->OpenProtocol (\r
+                  Dns6Handle,\r
+                  &gEfiDns6ProtocolGuid,\r
+                  (VOID **) &Dns6,\r
+                  Private->Image,\r
+                  Private->Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Configure DNS6 instance for the DNS server address and protocol.\r
+  //\r
+  ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+  Dns6ConfigData.DnsServerCount = 1;\r
+  Dns6ConfigData.DnsServerList  = DnsServerList;\r
+  Dns6ConfigData.EnableDnsCache = TRUE;\r
+  Dns6ConfigData.Protocol       = EFI_IP_PROTO_UDP;\r
+  IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &Private->TmpStationIp.v6);\r
+  Status = Dns6->Configure (\r
+                   Dns6,\r
+                   &Dns6ConfigData\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  Token.Status = EFI_NOT_READY;\r
+  IsDone       = FALSE;\r
+  //\r
+  // Create event to set the  IsDone flag when name resolution is finished.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  PxeBcCommonNotify,\r
+                  &IsDone,\r
+                  &Token.Event\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Start asynchronous name resolution.\r
+  //\r
+  Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  while (!IsDone) {\r
+    Dns6->Poll (Dns6);\r
+  }\r
+\r
+  //\r
+  // Name resolution is done, check result.\r
+  //\r
+  Status = Token.Status;  \r
+  if (!EFI_ERROR (Status)) {\r
+    if (Token.RspData.H2AData == NULL) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+    if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Exit;\r
+    }\r
+    //\r
+    // We just return the first IPv6 address from DNS protocol.\r
+    //\r
+    IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+  \r
+Exit:\r
+  FreePool (HostName);\r
+\r
+  if (Token.Event != NULL) {\r
+    gBS->CloseEvent (Token.Event);\r
+  }\r
+  if (Token.RspData.H2AData != NULL) {\r
+    if (Token.RspData.H2AData->IpList != NULL) {\r
+      FreePool (Token.RspData.H2AData->IpList);\r
+    }\r
+    FreePool (Token.RspData.H2AData);\r
+  }\r
+\r
+  if (Dns6 != NULL) {\r
+    Dns6->Configure (Dns6, NULL);\r
+    \r
+    gBS->CloseProtocol (\r
+           Dns6Handle,\r
+           &gEfiDns6ProtocolGuid,\r
+           Private->Image,\r
+           Private->Controller\r
+           );\r
+  }\r
+\r
+  if (Dns6Handle != NULL) {\r
+    NetLibDestroyServiceChild (\r
+      Private->Controller,\r
+      Private->Image,\r
+      &gEfiDns6ServiceBindingProtocolGuid,\r
+      Dns6Handle\r
+      );\r
+  }\r
+\r
+  if (DnsServerList != NULL) {\r
+    FreePool (DnsServerList);\r
+  }\r
+  \r
+  return Status;  \r
+}\r
 \r
 /**\r
   Parse the Boot File URL option.\r
 \r
+  @param[in]      Private      Pointer to PxeBc private data.\r
   @param[out]     FileName     The pointer to the boot file name.\r
   @param[in, out] SrvAddr      The pointer to the boot server address.\r
   @param[in]      BootFile     The pointer to the boot file URL option data.\r
@@ -232,6 +396,7 @@ PxeBcFreeBootFileOption (
 **/\r
 EFI_STATUS\r
 PxeBcExtractBootFileUrl (\r
+  IN PXEBC_PRIVATE_DATA      *Private,\r
      OUT UINT8               **FileName,\r
   IN OUT EFI_IPv6_ADDRESS    *SrvAddr,\r
   IN     CHAR8               *BootFile,\r
@@ -247,8 +412,12 @@ PxeBcExtractBootFileUrl (
   CHAR8                      *ServerAddressOption;\r
   CHAR8                      *ServerAddress;\r
   CHAR8                      *ModeStr;\r
+  CHAR16                     *HostName;\r
+  BOOLEAN                    IpExpressedUrl;\r
+  UINTN                      Len;\r
   EFI_STATUS                 Status;\r
 \r
+  IpExpressedUrl = TRUE;\r
   //\r
   // The format of the Boot File URL option is:\r
   //\r
@@ -264,8 +433,8 @@ PxeBcExtractBootFileUrl (
   //\r
 \r
   //\r
-  // Based upon RFC 5970 and UEFI 2.3 Errata D specification, bootfile-url format\r
-  // is tftp://[SERVER_ADDRESS]/BOOTFILE_NAME\r
+  // Based upon RFC 5970 and UEFI 2.6, bootfile-url format can be\r
+  // tftp://[SERVER_ADDRESS]/BOOTFILE_NAME or tftp://domain_name/BOOTFILE_NAME\r
   // As an example where the BOOTFILE_NAME is the EFI loader and\r
   // SERVER_ADDRESS is the ASCII encoding of an IPV6 address.\r
   //\r
@@ -291,43 +460,76 @@ PxeBcExtractBootFileUrl (
   // Get the part of SERVER_ADDRESS string.\r
   //\r
   ServerAddressOption = TmpStr;\r
-  if (*ServerAddressOption != PXEBC_ADDR_START_DELIMITER) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  if (*ServerAddressOption == PXEBC_ADDR_START_DELIMITER) {\r
+    ServerAddressOption ++;\r
+    ServerAddress = ServerAddressOption;\r
+    while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
+      ServerAddress++;\r
+    }\r
+    \r
+    if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    \r
+    *ServerAddress = '\0';\r
+    \r
+    //\r
+    // Convert the string of server address to Ipv6 address format and store it.\r
+    //\r
+    Status = NetLibAsciiStrToIp6 (ServerAddressOption, SrvAddr);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (TmpStr);\r
+      return Status;\r
+    }\r
 \r
-  ServerAddressOption ++;\r
-  ServerAddress = ServerAddressOption;\r
-  while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    ServerAddress++;\r
-  }\r
+  } else {\r
+    IpExpressedUrl = FALSE;\r
+    ServerAddress = ServerAddressOption;\r
+    while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      ServerAddress++;\r
+    }\r
 \r
-  if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+    if (*ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    *ServerAddress = '\0';\r
 \r
-  *ServerAddress = '\0';\r
+    Len = AsciiStrSize (ServerAddressOption);\r
+    HostName = AllocateZeroPool (Len * sizeof (CHAR16));\r
+    if (HostName == NULL) {\r
+      FreePool (TmpStr);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    AsciiStrToUnicodeStrS (\r
+      ServerAddressOption,\r
+      HostName,\r
+      Len\r
+      );\r
 \r
-  //\r
-  // Convert the string of server address to Ipv6 address format and store it.\r
-  //\r
-  Status = NetLibAsciiStrToIp6 (ServerAddressOption, SrvAddr);\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (TmpStr);\r
-    return Status;\r
+    //\r
+    // Perform DNS resolution.\r
+    //\r
+    Status = PxeBcDns6 (Private,HostName, SrvAddr);\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (TmpStr);\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
   // Get the part of BOOTFILE_NAME string.\r
   //\r
   BootFileNamePtr = (CHAR8*)((UINTN)ServerAddress + 1);\r
-  if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {\r
-    FreePool (TmpStr);\r
-    return EFI_INVALID_PARAMETER;\r
+  if (IpExpressedUrl) {\r
+    if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {\r
+      FreePool (TmpStr);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    ++BootFileNamePtr;\r
   }\r
 \r
-  ++BootFileNamePtr;\r
   BootFileNameLen = (UINT16)(Length - (UINT16) ((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);\r
   if (BootFileNameLen != 0 || FileName != NULL) {\r
     //\r
@@ -471,17 +673,19 @@ PxeBcParseDhcp6Packet (
   //\r
   while (Offset < Length) {\r
 \r
-    if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_IA_NA) {\r
+    if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) {\r
       Options[PXEBC_DHCP6_IDX_IA_NA] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_BOOT_FILE_URL) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) {\r
       //\r
       // The server sends this option to inform the client about an URL to a boot file.\r
       //\r
       Options[PXEBC_DHCP6_IDX_BOOT_FILE_URL] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_BOOT_FILE_PARAM) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_PARAM) {\r
       Options[PXEBC_DHCP6_IDX_BOOT_FILE_PARAM] = Option;\r
-    } else if (NTOHS (Option->OpCode) == PXEBC_DHCP6_OPT_VENDOR_CLASS) {\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_VENDOR_CLASS) {\r
       Options[PXEBC_DHCP6_IDX_VENDOR_CLASS] = Option;\r
+    } else if (NTOHS (Option->OpCode) == DHCP6_OPT_DNS_SERVERS) {\r
+      Options[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;\r
     }\r
 \r
     Offset += (NTOHS (Option->OpLen) + 4);\r
@@ -497,7 +701,7 @@ PxeBcParseDhcp6Packet (
     Option = PxeBcParseDhcp6Options (\r
                Option->Data + 12,\r
                NTOHS (Option->OpLen),\r
-               PXEBC_DHCP6_OPT_STATUS_CODE\r
+               DHCP6_OPT_STATUS_CODE\r
                );\r
     if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) {\r
       IsProxyOffer = FALSE;\r
@@ -713,7 +917,7 @@ PxeBcRequestBootService (
   Option = PxeBcDhcp6SeekOption (\r
              ProxyOffer->Dhcp6.Option,\r
              ProxyOffer->Length - 4,\r
-             PXEBC_DHCP6_OPT_SERVER_ID\r
+             DHCP6_OPT_SERVER_ID\r
              );\r
   if (Option == NULL) {\r
     return EFI_NOT_FOUND;\r
@@ -732,7 +936,7 @@ PxeBcRequestBootService (
     OpLen  = NTOHS (((EFI_DHCP6_PACKET_OPTION *) RequestOpt)->OpLen);\r
     if (OpCode != EFI_DHCP6_IA_TYPE_NA &&\r
         OpCode != EFI_DHCP6_IA_TYPE_TA &&\r
-        OpCode != PXEBC_DHCP6_OPT_SERVER_ID\r
+        OpCode != DHCP6_OPT_SERVER_ID\r
         ) {\r
       //\r
       // Copy all the options except IA option and Server ID\r
@@ -751,7 +955,7 @@ PxeBcRequestBootService (
   Option = PxeBcDhcp6SeekOption (\r
              Discover->DhcpOptions,\r
              (UINT32)(RequestLen - 4),\r
-             PXEBC_DHCP6_OPT_ELAPSED_TIME\r
+             DHCP6_OPT_ELAPSED_TIME\r
              );\r
   if (Option != NULL) {\r
     CalcElapsedTime (Private);\r
@@ -864,6 +1068,7 @@ PxeBcRetryDhcp6Binl (
     // Parse out the next server address from the last offer, and store it\r
     //\r
     Status = PxeBcExtractBootFileUrl (\r
+               Private,\r
                &Private->BootFileName,\r
                &Private->ServerIp.v6,\r
                (CHAR8 *) (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
@@ -1093,8 +1298,9 @@ PxeBcSelectDhcp6Offer (
 \r
   @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
 \r
-  @retval     EFI_SUCCESS         Handled the DHCPv6 offer packet successfully.\r
-  @retval     EFI_NO_RESPONSE     No response to the following request packet.\r
+  @retval     EFI_SUCCESS           Handled the DHCPv6 offer packet successfully.\r
+  @retval     EFI_NO_RESPONSE       No response to the following request packet.\r
+  @retval     EFI_OUT_OF_RESOURCES  Failed to allocate resources.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1115,6 +1321,17 @@ PxeBcHandleDhcp6Offer (
   Cache6      = &Private->OfferBuffer[SelectIndex].Dhcp6;\r
   Status      = EFI_SUCCESS;\r
 \r
+  //\r
+  // First try to cache DNS server address if DHCP6 offer provides.\r
+  //\r
+  if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {\r
+    Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));\r
+    if (Private->DnsServer == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));\r
+  }\r
+\r
   if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {\r
     //\r
     // DhcpBinl offer is selected, so need try to request bootfilename by this offer.\r
@@ -1702,6 +1919,14 @@ PxeBcDhcp6CallBack (
   switch (Dhcp6Event) {\r
 \r
   case Dhcp6SendSolicit:\r
+    if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+      //\r
+      // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+      //\r
+      Status = EFI_ABORTED;\r
+      break;\r
+    }\r
+    \r
     //\r
     // Record the first Solicate msg time\r
     //\r
@@ -1717,6 +1942,12 @@ PxeBcDhcp6CallBack (
 \r
   case Dhcp6RcvdAdvertise:\r
     Status = EFI_NOT_READY;\r
+    if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+      //\r
+      // Ignore the incoming packets which exceed the maximum length.\r
+      //\r
+      break;\r
+    }\r
     if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {\r
       //\r
       // Cache the dhcp offers to OfferBuffer[] for select later, and record\r
@@ -1727,6 +1958,14 @@ PxeBcDhcp6CallBack (
     break;\r
 \r
   case Dhcp6SendRequest:\r
+    if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+      //\r
+      // If the to be sent packet exceeds the maximum length, abort the DHCP process.\r
+      //\r
+      Status = EFI_ABORTED;\r
+      break;\r
+    }\r
+    \r
     //\r
     // Store the request packet as seed packet for discover.\r
     //\r
@@ -1758,6 +1997,13 @@ PxeBcDhcp6CallBack (
     break;\r
 \r
   case Dhcp6RcvdReply:\r
+    if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {\r
+      //\r
+      // Abort the DHCP if the Peply packet exceeds the maximum length.\r
+      //\r
+         Status = EFI_ABORTED;\r
+      break;\r
+    }\r
     //\r
     // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data\r
     // without verification.\r
@@ -2073,7 +2319,7 @@ PxeBcDhcp6Sarr (
     return Status;\r
   }\r
 \r
-  ASSERT (Mode.Ia->State == Dhcp6Bound);\r
+  ASSERT ((Mode.Ia != NULL) && (Mode.Ia->State == Dhcp6Bound));\r
   //\r
   // DHCP6 doesn't have an option to specify the router address on the subnet, the only way to get the\r
   // router address in IP6 is the router discovery mechanism (the RS and RA, which only be handled when\r
@@ -2082,7 +2328,12 @@ PxeBcDhcp6Sarr (
   // to find a valid router address.\r
   //\r
   CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
-\r
+  if (Mode.ClientId != NULL) {\r
+    FreePool (Mode.ClientId);\r
+  }\r
+  if (Mode.Ia != NULL) {\r
+    FreePool (Mode.Ia);\r
+  }\r
   //\r
   // Check the selected offer whether BINL retry is needed.\r
   //\r