]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
MdeModulePkg: Ignore BootFileName if it is overloaded.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcDhcp.c
index 8be753151ccbd578ed1022e54a495130ea80f3dd..38f630301b1b6e7f0f2950636f8d683edbb2a7c0 100644 (file)
@@ -2,7 +2,7 @@
   Support for PxeBc dhcp functions.\r
 \r
 Copyright (c) 2013, Red Hat, Inc.\r
-Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -147,13 +147,43 @@ PxeBcParseCachedDhcpPacket (
 \r
   //\r
   // Parse interested dhcp options and store their pointers in CachedPacket->Dhcp4Option.\r
+  // First, try to parse DHCPv4 options from the DHCP optional parameters field.\r
   //\r
   for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
     Options[Index] = PxeBcParseExtendOptions (\r
-                      Offer->Dhcp4.Option,\r
-                      GET_OPTION_BUFFER_LEN (Offer),\r
-                      mInterestedDhcp4Tags[Index]\r
-                      );\r
+                       Offer->Dhcp4.Option,\r
+                       GET_OPTION_BUFFER_LEN (Offer),\r
+                       mInterestedDhcp4Tags[Index]\r
+                       );\r
+  }\r
+  //\r
+  // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. \r
+  // If yes, try to parse options from the BootFileName field, then ServerName field.\r
+  //\r
+  Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
+  if (Option != NULL) {\r
+    if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0) {\r
+      for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+        if (Options[Index] == NULL) {\r
+          Options[Index] = PxeBcParseExtendOptions (\r
+                             (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
+                             sizeof (Offer->Dhcp4.Header.BootFileName),\r
+                             mInterestedDhcp4Tags[Index]\r
+                             );\r
+        }\r
+      }\r
+    }\r
+    if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_SERVER_NAME) != 0) {\r
+      for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+        if (Options[Index] == NULL) {\r
+          Options[Index] = PxeBcParseExtendOptions (\r
+                             (UINT8 *) Offer->Dhcp4.Header.ServerName,\r
+                             sizeof (Offer->Dhcp4.Header.ServerName),\r
+                             mInterestedDhcp4Tags[Index]\r
+                             );\r
+        }\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -177,38 +207,34 @@ PxeBcParseCachedDhcpPacket (
     }\r
   }\r
 \r
+\r
   //\r
-  // Check whether bootfilename/serverhostname overloaded (See details in dhcp spec).\r
-  // If overloaded, parse this buffer as nested dhcp options, or just parse bootfilename/\r
-  // serverhostname option.\r
+  // Parse PXE boot file name:\r
+  // According to PXE spec, boot file name should be read from DHCP option 67 (bootfile name) if present.\r
+  // Otherwise, read from boot file field in DHCP header.\r
   //\r
-  Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
-  if ((Option != NULL) && ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0)) {\r
-\r
-    Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = PxeBcParseExtendOptions (\r
-                                                (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
-                                                sizeof (Offer->Dhcp4.Header.BootFileName),\r
-                                                PXEBC_DHCP4_TAG_BOOTFILE\r
-                                                );\r
+  if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
     //\r
     // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null \r
     // terminated string. So force to append null terminated character at the end of string.\r
     //\r
-    if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
-      Ptr8 =  (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
-      Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
-      *Ptr8 =  '\0';\r
+    Ptr8 =  (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
+    Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
+    if (*(Ptr8 - 1) != '\0') {\r
+      *Ptr8 = '\0';\r
     }\r
-\r
-  } else if ((Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) &&\r
-            (Offer->Dhcp4.Header.BootFileName[0] != 0)) {\r
+  } else if (Offer->Dhcp4.Header.BootFileName[0] != 0) {\r
     //\r
     // If the bootfile is not present and bootfilename is present in dhcp packet, just parse it.\r
     // And do not count dhcp option header, or else will destroy the serverhostname.\r
     //\r
-    Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *) (&Offer->Dhcp4.Header.BootFileName[0] -\r
+    // Make sure "BootFileName" is not overloaded.\r
+    //\r
+    if (Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD] == NULL ||\r
+        (Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD]->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) == 0) {\r
+      Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *) (&Offer->Dhcp4.Header.BootFileName[0] -\r
                                             OFFSET_OF (EFI_DHCP4_PACKET_OPTION, Data[0]));\r
-\r
+    }\r
   }\r
 \r
   //\r
@@ -455,6 +481,7 @@ PxeBcCheckSelectedOffer (
         //\r
         Status = EFI_NO_RESPONSE;\r
 \r
+        ASSERT (Private->NumOffers < PXEBC_MAX_OFFER_NUM);\r
         for (Index = 0; Index < Private->NumOffers; Index++) {\r
 \r
           Offer = &Private->Dhcp4Offers[Index].Packet.Offer;\r
@@ -624,6 +651,53 @@ PxeBcCacheDhcpOffer (
   Private->NumOffers++;\r
 }\r
 \r
+/**\r
+  Switch the Ip4 policy to static.\r
+\r
+  @param[in]  Private             The pointer to PXEBC_PRIVATE_DATA.\r
+\r
+  @retval     EFI_SUCCESS         The policy is already configured to static.\r
+  @retval     Others              Other error as indicated..\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcSetIp4Policy (   \r
+  IN PXEBC_PRIVATE_DATA            *Private\r
+  )\r
+{\r
+  EFI_STATUS                   Status;\r
+  EFI_IP4_CONFIG2_PROTOCOL     *Ip4Config2;\r
+  EFI_IP4_CONFIG2_POLICY       Policy;\r
+  UINTN                        DataSize;\r
+\r
+  Ip4Config2 = Private->Ip4Config2;\r
+  DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
+  Status = Ip4Config2->GetData (\r
+                       Ip4Config2,\r
+                       Ip4Config2DataTypePolicy,\r
+                       &DataSize,\r
+                       &Policy\r
+                       );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  if (Policy != Ip4Config2PolicyStatic) {\r
+    Policy = Ip4Config2PolicyStatic;\r
+    Status= Ip4Config2->SetData (\r
+                          Ip4Config2,\r
+                          Ip4Config2DataTypePolicy,\r
+                          sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                          &Policy\r
+                          );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    } \r
+  }\r
+\r
+  return  EFI_SUCCESS;\r
+}\r
+\r
 \r
 /**\r
   Select the specified proxy offer, such as BINL, DHCP_ONLY and so on.\r