summaryrefslogtreecommitdiffstats
path: root/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
diff options
context:
space:
mode:
Diffstat (limited to 'NetworkPkg/Dhcp6Dxe/Dhcp6Io.c')
-rw-r--r--NetworkPkg/Dhcp6Dxe/Dhcp6Io.c194
1 files changed, 125 insertions, 69 deletions
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
index 0e83d07853..962d9387ca 100644
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
@@ -593,6 +593,14 @@ Dhcp6UpdateIaInfo (
if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
T1 = NTOHL (ReadUnaligned32 ((UINT32 *) (Option + 8)));
T2 = NTOHL (ReadUnaligned32 ((UINT32 *) (Option + 12)));
+ //
+ // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,
+ // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes
+ // the remainder of the message as though the server had not included the invalid IA_NA option.
+ //
+ if (T1 > T2 && T2 > 0) {
+ return EFI_DEVICE_ERROR;
+ }
IaInnerOpt = Option + 16;
IaInnerLen = (UINT16) (NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 2))) - 12);
} else {
@@ -697,7 +705,7 @@ Dhcp6SeekStsOption (
&Instance->Config->IaDescriptor
);
if (*Option == NULL) {
- return EFI_DEVICE_ERROR;
+ return EFI_SUCCESS;
}
//
@@ -949,7 +957,8 @@ Dhcp6SendSolicitMsg (
Cursor,
Instance->IaCb.Ia,
Instance->IaCb.T1,
- Instance->IaCb.T2
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
);
//
@@ -987,6 +996,10 @@ Dhcp6SendSolicitMsg (
// Dhcp6selecting.
//
Instance->IaCb.Ia->State = Dhcp6Selecting;
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
@@ -1133,7 +1146,8 @@ Dhcp6SendRequestMsg (
Cursor,
Instance->IaCb.Ia,
Instance->IaCb.T1,
- Instance->IaCb.T2
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
);
//
@@ -1171,6 +1185,10 @@ Dhcp6SendRequestMsg (
// Dhcp6requesting.
//
Instance->IaCb.Ia->State = Dhcp6Requesting;
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
@@ -1282,7 +1300,7 @@ Dhcp6SendDeclineMsg (
ServerId->Duid
);
- Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0);
+ Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);
//
// Determine the size/length of packet.
@@ -1305,6 +1323,10 @@ Dhcp6SendDeclineMsg (
// Dhcp6declining.
//
Instance->IaCb.Ia->State = Dhcp6Declining;
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
@@ -1415,7 +1437,7 @@ Dhcp6SendReleaseMsg (
&Elapsed
);
- Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0);
+ Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);
//
// Determine the size/length of packet
@@ -1540,7 +1562,8 @@ Dhcp6SendRenewRebindMsg (
Cursor,
Instance->IaCb.Ia,
Instance->IaCb.T1,
- Instance->IaCb.T2
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
);
if (!RebindRequest) {
@@ -1612,6 +1635,10 @@ Dhcp6SendRenewRebindMsg (
//
Instance->IaCb.Ia->State = State;
Instance->IaCb.LeaseTime = (RebindRequest) ? Instance->IaCb.T2 : Instance->IaCb.T1;
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
@@ -1844,6 +1871,11 @@ Dhcp6SendInfoRequestMsg (
//
Packet->Length += (UINT32) (Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8);
+
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
//
// Send info-request packet with no state.
@@ -1941,7 +1973,8 @@ Dhcp6SendConfirmMsg (
Cursor,
Instance->IaCb.Ia,
Instance->IaCb.T1,
- Instance->IaCb.T2
+ Instance->IaCb.T2,
+ Packet->Dhcp6.Header.MessageType
);
//
@@ -1978,6 +2011,10 @@ Dhcp6SendConfirmMsg (
// Dhcp6Confirming.
//
Instance->IaCb.Ia->State = Dhcp6Confirming;
+ //
+ // Clear initial time for current transaction.
+ //
+ Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
@@ -2020,6 +2057,8 @@ Dhcp6HandleReplyMsg (
ASSERT (Instance->IaCb.Ia != NULL);
ASSERT (Packet != NULL);
+ Status = EFI_SUCCESS;
+
if (Packet->Dhcp6.Header.MessageType != Dhcp6MsgReply) {
return EFI_DEVICE_ERROR;
}
@@ -2056,7 +2095,7 @@ Dhcp6HandleReplyMsg (
&Instance->Config->IaDescriptor
);
if (Option == NULL) {
- return EFI_DEVICE_ERROR;
+ return EFI_SUCCESS;
}
}
@@ -2070,19 +2109,6 @@ Dhcp6HandleReplyMsg (
}
//
- // Dequeue the sent packet from retransmit list since reply received.
- //
- Status = Dhcp6DequeueRetry (
- Instance,
- Packet->Dhcp6.Header.TransactionId,
- FALSE
- );
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
// When receive a valid reply packet in response to a decline/release packet,
// the client considers the decline/release event completed regardless of the
// status code.
@@ -2115,7 +2141,8 @@ Dhcp6HandleReplyMsg (
//
Instance->StartTime = 0;
- return EFI_SUCCESS;
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
}
//
@@ -2132,55 +2159,63 @@ Dhcp6HandleReplyMsg (
if (!EFI_ERROR (Status)) {
//
- // Reset start time for next exchange.
- //
- Instance->StartTime = 0;
-
- //
// No status code or no error status code means succeed to reply.
//
Status = Dhcp6UpdateIaInfo (Instance, Packet);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Reset start time for next exchange.
+ //
+ Instance->StartTime = 0;
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Set bound state and store the reply packet.
- //
- if (Instance->IaCb.Ia->ReplyPacket != NULL) {
- FreePool (Instance->IaCb.Ia->ReplyPacket);
- }
+ //
+ // Set bound state and store the reply packet.
+ //
+ if (Instance->IaCb.Ia->ReplyPacket != NULL) {
+ FreePool (Instance->IaCb.Ia->ReplyPacket);
+ }
- Instance->IaCb.Ia->ReplyPacket = AllocateZeroPool (Packet->Size);
+ Instance->IaCb.Ia->ReplyPacket = AllocateZeroPool (Packet->Size);
- if (Instance->IaCb.Ia->ReplyPacket == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
+ if (Instance->IaCb.Ia->ReplyPacket == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
- CopyMem (Instance->IaCb.Ia->ReplyPacket, Packet, Packet->Size);
+ CopyMem (Instance->IaCb.Ia->ReplyPacket, Packet, Packet->Size);
- Instance->IaCb.Ia->State = Dhcp6Bound;
+ Instance->IaCb.Ia->State = Dhcp6Bound;
- //
- // For sync, set the success flag out of polling in start/renewrebind.
- //
- Instance->UdpSts = EFI_SUCCESS;
+ //
+ // For sync, set the success flag out of polling in start/renewrebind.
+ //
+ Instance->UdpSts = EFI_SUCCESS;
- //
- // Maybe this is a new round DHCP process due to some reason, such as NotOnLink
- // ReplyMsg for ConfirmMsg should triger new round to acquire new address. In that
- // case, clear old address.ValidLifetime and append to new address. Therefore, DHCP
- // consumers can be notified to flush old address.
- //
- Dhcp6AppendCacheIa (Instance);
+ //
+ // Maybe this is a new round DHCP process due to some reason, such as NotOnLink
+ // ReplyMsg for ConfirmMsg should triger new round to acquire new address. In that
+ // case, clear old address.ValidLifetime and append to new address. Therefore, DHCP
+ // consumers can be notified to flush old address.
+ //
+ Dhcp6AppendCacheIa (Instance);
- //
- // For async, signal the Ia event to inform Ia infomation update.
- //
- if (Instance->Config->IaInfoEvent != NULL) {
- gBS->SignalEvent (Instance->Config->IaInfoEvent);
+ //
+ // For async, signal the Ia event to inform Ia infomation update.
+ //
+ if (Instance->Config->IaInfoEvent != NULL) {
+ gBS->SignalEvent (Instance->Config->IaInfoEvent);
+ }
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message,
+ // the client sends a Renew or Rebind if the IA is not in the Reply message.
+ // Return EFI_SUCCESS so we can continue to restart the Renew/Rebind process.
+ //
+ return EFI_SUCCESS;
}
+
+ goto ON_EXIT;
+
} else if (Option != NULL) {
//
// Any error status code option is found.
@@ -2226,6 +2261,19 @@ Dhcp6HandleReplyMsg (
}
break;
+ case Dhcp6StsNoBinding:
+ if (Instance->IaCb.Ia->State == Dhcp6Renewing || Instance->IaCb.Ia->State == Dhcp6Rebinding) {
+ //
+ // Refer to RFC3315 Chapter 18.1.8, for each IA in the original Renew or Rebind message, the client
+ // sends a Request message if the IA contained a Status Code option with the NoBinding status.
+ //
+ Status = Dhcp6SendRequestMsg(Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ break;
+
default:
//
// The other status code, just restart solicitation.
@@ -2235,6 +2283,18 @@ Dhcp6HandleReplyMsg (
}
return EFI_SUCCESS;
+
+ON_EXIT:
+
+ if (!EFI_ERROR(Status)) {
+ Status = Dhcp6DequeueRetry (
+ Instance,
+ Packet->Dhcp6.Header.TransactionId,
+ FALSE
+ );
+ }
+
+ return Status;
}
@@ -2378,17 +2438,13 @@ Dhcp6HandleAdvertiseMsg (
// display the associated status message to the user.
// See the details in the section-17.1.3 of rfc-3315.
//
- Option = Dhcp6SeekOption(
- Packet->Dhcp6.Option,
- Packet->Length - 4,
- Dhcp6OptStatusCode
+ Status = Dhcp6SeekStsOption (
+ Instance,
+ Packet,
+ &Option
);
-
- if (Option != NULL) {
- StsCode = NTOHS (ReadUnaligned16 ((UINT16 *) (Option + 4)));
- if (StsCode != Dhcp6StsSuccess) {
- return EFI_DEVICE_ERROR;
- }
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
}
//