/** @file\r
Dhcp6 internal functions implementation.\r
\r
- Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+ Copyright (c) 2009 - 2018, 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
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
}\r
}\r
\r
+/**\r
+ Check whether the TxCb is still a valid control block in the instance's retry list.\r
+\r
+ @param[in] Instance The pointer to DHCP6_INSTANCE.\r
+ @param[in] TxCb The control block for a transmitted message.\r
+\r
+ @retval TRUE The control block is in Instance's retry list.\r
+ @retval FALSE The control block is NOT in Instance's retry list.\r
+\r
+**/\r
+BOOLEAN\r
+Dhcp6IsValidTxCb (\r
+ IN DHCP6_INSTANCE *Instance,\r
+ IN DHCP6_TX_CB *TxCb\r
+ )\r
+{\r
+ LIST_ENTRY *Entry;\r
+\r
+ NET_LIST_FOR_EACH (Entry, &Instance->TxList) {\r
+ if (TxCb == NET_LIST_USER_STRUCT (Entry, DHCP6_TX_CB, Link)) {\r
+ return TRUE;\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
\r
/**\r
Clean up the session of the instance stateful exchange.\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_DHCP6_STATE State;\r
UINT8 *Option;\r
UINT8 *IaInnerOpt;\r
UINT16 IaInnerLen;\r
//\r
// See details in the section-18.1.8 of rfc-3315.\r
//\r
- State = Dhcp6Init;\r
Option = Dhcp6SeekIaOption (\r
Packet->Dhcp6.Option,\r
Packet->Length - sizeof (EFI_DHCP6_HEADER),\r
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
goto ON_ERROR;\r
}\r
- \r
+\r
gBS->RestoreTPL (OldTpl);\r
return EFI_SUCCESS;\r
- \r
+\r
ON_ERROR:\r
- gBS->RestoreTPL (OldTpl); \r
+ gBS->RestoreTPL (OldTpl);\r
RemoveEntryList (&InfCb->Link);\r
FreePool (InfCb);\r
\r
//\r
Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option);\r
ASSERT (Packet->Size > Packet->Length + 8);\r
- \r
+\r
//\r
// Clear initial time for current transaction.\r
//\r
}\r
} else if (Status == EFI_NOT_FOUND) {\r
//\r
- // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, \r
+ // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message,\r
// the client sends a Renew or Rebind if the IA is not in the Reply message.\r
// Return EFI_SUCCESS so we can continue to restart the Renew/Rebind process.\r
//\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
goto ON_EXIT;\r
- \r
+\r
} else if (Option != NULL) {\r
//\r
// Any error status code option is found.\r
case Dhcp6StsNoBinding:\r
if (Instance->IaCb.Ia->State == Dhcp6Renewing || Instance->IaCb.Ia->State == Dhcp6Rebinding) {\r
//\r
- // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client \r
+ // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client\r
// sends a Request message if the IA contained a Status Code option with the NoBinding status.\r
//\r
Status = Dhcp6SendRequestMsg(Instance);\r
}\r
\r
return EFI_SUCCESS;\r
- \r
+\r
ON_EXIT:\r
\r
if (!EFI_ERROR(Status)) {\r
FALSE\r
);\r
}\r
- \r
+\r
return Status;\r
}\r
\r
{\r
EFI_STATUS Status;\r
UINT8 *Option;\r
- UINT16 StsCode;\r
BOOLEAN Timeout;\r
\r
ASSERT(Instance->Config);\r
ASSERT(Instance->IaCb.Ia);\r
\r
Timeout = FALSE;\r
- StsCode = Dhcp6StsSuccess;\r
\r
//\r
// If the client does receives a valid reply message that includes a rapid\r
LIST_ENTRY *Next1;\r
LIST_ENTRY *Entry2;\r
LIST_ENTRY *Next2;\r
+ EFI_STATUS Status;\r
\r
ASSERT (Udp6Wrap != NULL);\r
ASSERT (Context != NULL);\r
return ;\r
}\r
\r
+ if (Udp6Wrap->TotalSize < sizeof (EFI_DHCP6_HEADER)) {\r
+ goto ON_CONTINUE;\r
+ }\r
+\r
//\r
// Copy the net buffer received from upd6 to a Dhcp6 packet.\r
//\r
\r
ON_CONTINUE:\r
\r
+ if (!IsDispatched) {\r
+ Status = UdpIoRecvDatagram (\r
+ Service->UdpIo,\r
+ Dhcp6ReceivePacket,\r
+ Service,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ NET_LIST_FOR_EACH_SAFE (Entry1, Next1, &Service->Child) {\r
+ Instance = NET_LIST_USER_STRUCT (Entry1, DHCP6_INSTANCE, Link);\r
+ Dhcp6CleanupRetry (Instance, DHCP6_PACKET_ALL);\r
+ }\r
+ }\r
+ }\r
+\r
NetbufFree (Udp6Wrap);\r
\r
if (Packet != NULL) {\r
// Select the advertisement received before.\r
//\r
Status = Dhcp6SelectAdvertiseMsg (Instance, Instance->AdSelect);\r
- if (EFI_ERROR (Status)) {\r
+ if (Status == EFI_ABORTED) {\r
+ goto ON_CLOSE;\r
+ } else if (EFI_ERROR (Status)) {\r
TxCb->RetryCnt++;\r
}\r
return;\r
// Check whether overflow the max retry count limit for this packet\r
//\r
if (TxCb->RetryCtl.Mrc != 0 && TxCb->RetryCtl.Mrc < TxCb->RetryCnt) {\r
+ Status = EFI_NO_RESPONSE;\r
goto ON_CLOSE;\r
}\r
\r
// Check whether overflow the max retry duration for this packet\r
//\r
if (TxCb->RetryCtl.Mrd != 0 && TxCb->RetryCtl.Mrd <= TxCb->RetryLos) {\r
+ Status = EFI_NO_RESPONSE;\r
goto ON_CLOSE;\r
}\r
\r
\r
ON_CLOSE:\r
\r
- if (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest ||\r
+ if (Dhcp6IsValidTxCb (Instance, TxCb) &&\r
+ TxCb->TxPacket != NULL &&\r
+ (TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgInfoRequest ||\r
TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgRenew ||\r
- TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm\r
+ TxCb->TxPacket->Dhcp6.Header.MessageType == Dhcp6MsgConfirm)\r
) {\r
//\r
// The failure of renew/Confirm will still switch to the bound state.\r
//\r
// The failure of the others will terminate current state machine if timeout.\r
//\r
- Dhcp6CleanupSession (Instance, EFI_NO_RESPONSE);\r
+ Dhcp6CleanupSession (Instance, Status);\r
}\r
}\r