NetworkPkg: Dhcp6Dxe: SECURITY PATCH CVE-2023-45230 Patch

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4535

Bug Details:
PixieFail Bug #2
CVE-2023-45230
CVSS 8.3 : CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:H
CWE-119 Improper Restriction of Operations within the Bounds
 of a Memory Buffer

Changes Overview:
> -UINT8 *
> +EFI_STATUS
>  Dhcp6AppendOption (
> -  IN OUT UINT8   *Buf,
> -  IN     UINT16  OptType,
> -  IN     UINT16  OptLen,
> -  IN     UINT8   *Data
> +  IN OUT EFI_DHCP6_PACKET  *Packet,
> +  IN OUT UINT8             **PacketCursor,
> +  IN     UINT16            OptType,
> +  IN     UINT16            OptLen,
> +  IN     UINT8             *Data
>    );

Dhcp6AppendOption() and variants can return errors now.  All callsites
are adapted accordingly.

It gets passed in EFI_DHCP6_PACKET as additional parameter ...

> +  //
> +  // Verify the PacketCursor is within the packet
> +  //
> +  if (  (*PacketCursor < Packet->Dhcp6.Option)
> +     || (*PacketCursor >= Packet->Dhcp6.Option +
 (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
> +  {
> +    return EFI_INVALID_PARAMETER;
> +  }

... so it can look at Packet->Size when checking buffer space.
Also to allow Packet->Length updates.

Lots of checks added.

Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>
Cc: Zachary Clark-williams <zachary.clark-williams@intel.com>

Signed-off-by: Doug Flick [MSFT] <doug.edk2@gmail.com>
Reviewed-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
This commit is contained in:
Doug Flick via groups.io 2024-01-26 05:54:43 +08:00 committed by mergify[bot]
parent 959f71c801
commit f31453e8d6
4 changed files with 666 additions and 237 deletions

View File

@ -45,6 +45,49 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
#define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S') #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
#define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I') #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
//
// For more information on DHCP options see RFC 8415, Section 21.1
//
// The format of DHCP options is:
//
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | option-code | option-len |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | option-data |
// | (option-len octets) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
//
// Combined size of Code and Length
//
#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \
DHCP6_SIZE_OF_OPT_LEN)
STATIC_ASSERT (
DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4,
"Combined size of Code and Length must be 4 per RFC 8415"
);
//
// Offset to the length is just past the code
//
#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
STATIC_ASSERT (
DHCP6_OPT_LEN_OFFSET (0) == 2,
"Offset of length is + 2 past start of option"
);
#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
STATIC_ASSERT (
DHCP6_OPT_DATA_OFFSET (0) == 4,
"Offset to option data should be +4 from start of option"
);
#define DHCP6_PACKET_ALL 0 #define DHCP6_PACKET_ALL 0
#define DHCP6_PACKET_STATEFUL 1 #define DHCP6_PACKET_STATEFUL 1
#define DHCP6_PACKET_STATELESS 2 #define DHCP6_PACKET_STATELESS 2

View File

@ -3,9 +3,9 @@
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR> (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
#include "Dhcp6Impl.h" #include "Dhcp6Impl.h"
@ -930,7 +930,8 @@ Dhcp6SendSolicitMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
@ -944,54 +945,64 @@ Dhcp6SendSolicitMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption ( Status = Dhcp6AppendIaOption (
Cursor, Packet,
&Cursor,
Instance->IaCb.Ia, Instance->IaCb.Ia,
Instance->IaCb.T1, Instance->IaCb.T1,
Instance->IaCb.T2, Instance->IaCb.T2,
Packet->Dhcp6.Header.MessageType Packet->Dhcp6.Header.MessageType
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// Append user-defined when configurate Dhcp6 service. // Append user-defined when configurate Dhcp6 service.
// //
for (Index = 0; Index < Instance->Config->OptionCount; Index++) { for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
UserOpt = Instance->Config->OptionList[Index]; UserOpt = Instance->Config->OptionList[Index];
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
UserOpt->OpCode, UserOpt->OpCode,
UserOpt->OpLen, UserOpt->OpLen,
UserOpt->Data UserOpt->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
// Callback to user with the packet to be sent and check the user's feedback. // Callback to user with the packet to be sent and check the user's feedback.
// //
Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet); Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg (
Instance->StartTime = 0; Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg (
Elapsed, Elapsed,
Instance->Config->SolicitRetransmission Instance->Config->SolicitRetransmission
); );
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1110,7 +1127,8 @@ Dhcp6SendRequestMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
@ -1124,51 +1142,67 @@ Dhcp6SendRequestMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptServerId), HTONS (Dhcp6OptServerId),
ServerId->Length, ServerId->Length,
ServerId->Duid ServerId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption ( Status = Dhcp6AppendIaOption (
Cursor, Packet,
&Cursor,
Instance->IaCb.Ia, Instance->IaCb.Ia,
Instance->IaCb.T1, Instance->IaCb.T1,
Instance->IaCb.T2, Instance->IaCb.T2,
Packet->Dhcp6.Header.MessageType Packet->Dhcp6.Header.MessageType
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// Append user-defined when configurate Dhcp6 service. // Append user-defined when configurate Dhcp6 service.
// //
for (Index = 0; Index < Instance->Config->OptionCount; Index++) { for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
UserOpt = Instance->Config->OptionList[Index]; UserOpt = Instance->Config->OptionList[Index];
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
UserOpt->OpCode, UserOpt->OpCode,
UserOpt->OpLen, UserOpt->OpLen,
UserOpt->Data UserOpt->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg (
Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet); Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1194,14 +1227,21 @@ Dhcp6SendRequestMsg (
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1266,7 +1306,8 @@ Dhcp6SendDeclineMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE; Packet->Size = DHCP6_BASE_PACKET_SIZE;
@ -1280,42 +1321,58 @@ Dhcp6SendDeclineMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptServerId), HTONS (Dhcp6OptServerId),
ServerId->Length, ServerId->Length,
ServerId->Duid ServerId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType); Status = Dhcp6AppendIaOption (
Packet,
&Cursor,
DecIa,
0,
0,
Packet->Dhcp6.Header.MessageType
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
// Callback to user with the packet to be sent and check the user's feedback. // Callback to user with the packet to be sent and check the user's feedback.
// //
Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet); Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1329,16 +1386,22 @@ Dhcp6SendDeclineMsg (
Instance->StartTime = 0; Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1399,7 +1462,8 @@ Dhcp6SendReleaseMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE; Packet->Size = DHCP6_BASE_PACKET_SIZE;
@ -1413,45 +1477,61 @@ Dhcp6SendReleaseMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// ServerId is extracted from packet, it's network order. // ServerId is extracted from packet, it's network order.
// //
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptServerId), HTONS (Dhcp6OptServerId),
ServerId->Length, ServerId->Length,
ServerId->Duid ServerId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType); Status = Dhcp6AppendIaOption (
Packet,
&Cursor,
RelIa,
0,
0,
Packet->Dhcp6.Header.MessageType
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Determine the size/length of packet
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
// Callback to user with the packet to be sent and check the user's feedback. // Callback to user with the packet to be sent and check the user's feedback.
// //
Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet); Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1461,16 +1541,22 @@ Dhcp6SendReleaseMsg (
Instance->IaCb.Ia->State = Dhcp6Releasing; Instance->IaCb.Ia->State = Dhcp6Releasing;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1529,7 +1615,8 @@ Dhcp6SendRenewRebindMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
@ -1543,26 +1630,38 @@ Dhcp6SendRenewRebindMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption ( Status = Dhcp6AppendIaOption (
Cursor, Packet,
&Cursor,
Instance->IaCb.Ia, Instance->IaCb.Ia,
Instance->IaCb.T1, Instance->IaCb.T1,
Instance->IaCb.T2, Instance->IaCb.T2,
Packet->Dhcp6.Header.MessageType Packet->Dhcp6.Header.MessageType
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
if (!RebindRequest) { if (!RebindRequest) {
// //
@ -1578,18 +1677,22 @@ Dhcp6SendRenewRebindMsg (
Dhcp6OptServerId Dhcp6OptServerId
); );
if (Option == NULL) { if (Option == NULL) {
FreePool (Packet); Status = EFI_DEVICE_ERROR;
return EFI_DEVICE_ERROR; goto ON_ERROR;
} }
ServerId = (EFI_DHCP6_DUID *)(Option + 2); ServerId = (EFI_DHCP6_DUID *)(Option + 2);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptServerId), HTONS (Dhcp6OptServerId),
ServerId->Length, ServerId->Length,
ServerId->Duid ServerId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
// //
@ -1597,18 +1700,18 @@ Dhcp6SendRenewRebindMsg (
// //
for (Index = 0; Index < Instance->Config->OptionCount; Index++) { for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
UserOpt = Instance->Config->OptionList[Index]; UserOpt = Instance->Config->OptionList[Index];
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
UserOpt->OpCode, UserOpt->OpCode,
UserOpt->OpLen, UserOpt->OpLen,
UserOpt->Data UserOpt->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
@ -1618,10 +1721,8 @@ Dhcp6SendRenewRebindMsg (
Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing; Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;
Status = Dhcp6CallbackUser (Instance, Event, &Packet); Status = Dhcp6CallbackUser (Instance, Event, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -1638,16 +1739,22 @@ Dhcp6SendRenewRebindMsg (
Instance->StartTime = 0; Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1811,7 +1918,8 @@ Dhcp6SendInfoRequestMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
@ -1828,44 +1936,56 @@ Dhcp6SendInfoRequestMsg (
if (SendClientId) { if (SendClientId) {
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
OptionRequest->OpCode, OptionRequest->OpCode,
OptionRequest->OpLen, OptionRequest->OpLen,
OptionRequest->Data OptionRequest->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// Append user-defined when configurate Dhcp6 service. // Append user-defined when configurate Dhcp6 service.
// //
for (Index = 0; Index < OptionCount; Index++) { for (Index = 0; Index < OptionCount; Index++) {
UserOpt = OptionList[Index]; UserOpt = OptionList[Index];
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
UserOpt->OpCode, UserOpt->OpCode,
UserOpt->OpLen, UserOpt->OpLen,
UserOpt->Data UserOpt->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
@ -1877,16 +1997,22 @@ Dhcp6SendInfoRequestMsg (
// Send info-request packet with no state. // Send info-request packet with no state.
// //
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**
@ -1937,7 +2063,8 @@ Dhcp6SendConfirmMsg (
// //
Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen); Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
if (Packet == NULL) { if (Packet == NULL) {
return EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen; Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
@ -1951,54 +2078,64 @@ Dhcp6SendConfirmMsg (
Cursor = Packet->Dhcp6.Option; Cursor = Packet->Dhcp6.Option;
Length = HTONS (ClientId->Length); Length = HTONS (ClientId->Length);
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
HTONS (Dhcp6OptClientId), HTONS (Dhcp6OptClientId),
Length, Length,
ClientId->Duid ClientId->Duid
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendETOption ( Status = Dhcp6AppendETOption (
Cursor, Packet,
&Cursor,
Instance, Instance,
&Elapsed &Elapsed
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Cursor = Dhcp6AppendIaOption ( Status = Dhcp6AppendIaOption (
Cursor, Packet,
&Cursor,
Instance->IaCb.Ia, Instance->IaCb.Ia,
Instance->IaCb.T1, Instance->IaCb.T1,
Instance->IaCb.T2, Instance->IaCb.T2,
Packet->Dhcp6.Header.MessageType Packet->Dhcp6.Header.MessageType
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// Append user-defined when configurate Dhcp6 service. // Append user-defined when configurate Dhcp6 service.
// //
for (Index = 0; Index < Instance->Config->OptionCount; Index++) { for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
UserOpt = Instance->Config->OptionList[Index]; UserOpt = Instance->Config->OptionList[Index];
Cursor = Dhcp6AppendOption ( Status = Dhcp6AppendOption (
Cursor, Packet,
&Cursor,
UserOpt->OpCode, UserOpt->OpCode,
UserOpt->OpLen, UserOpt->OpLen,
UserOpt->Data UserOpt->Data
); );
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
} }
//
// Determine the size/length of packet.
//
Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
ASSERT (Packet->Size > Packet->Length + 8); ASSERT (Packet->Size > Packet->Length + 8);
// //
// Callback to user with the packet to be sent and check the user's feedback. // Callback to user with the packet to be sent and check the user's feedback.
// //
Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet); Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
@ -2012,16 +2149,22 @@ Dhcp6SendConfirmMsg (
Instance->StartTime = 0; Instance->StartTime = 0;
Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed); Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (Packet); goto ON_ERROR;
return Status;
} }
// //
// Enqueue the sent packet for the retransmission in case reply timeout. // Enqueue the sent packet for the retransmission in case reply timeout.
// //
return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL); return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
ON_ERROR:
if (Packet) {
FreePool (Packet);
}
return Status;
} }
/** /**

View File

@ -577,24 +577,33 @@ Dhcp6OnTransmitted (
} }
/** /**
Append the option to Buf, and move Buf to the end. Append the option to Buf, update the length of packet, and move Buf to the end.
@param[in, out] Buf The pointer to the buffer. @param[in, out] Packet A pointer to the packet, on success Packet->Length
@param[in] OptType The option type. will be updated.
@param[in] OptLen The length of option contents. @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
@param[in] Data The pointer to the option content. will be moved to the end of the option.
@param[in] OptType The option type.
@param[in] OptLen The length of option contents.
@param[in] Data The pointer to the option content.
@return Buf The position to append the next option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendOption ( Dhcp6AppendOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN UINT16 OptType, IN OUT UINT8 **PacketCursor,
IN UINT16 OptLen, IN UINT16 OptType,
IN UINT8 *Data IN UINT16 OptLen,
IN UINT8 *Data
) )
{ {
UINT32 Length;
UINT32 BytesNeeded;
// //
// The format of Dhcp6 option: // The format of Dhcp6 option:
// //
@ -607,35 +616,95 @@ Dhcp6AppendOption (
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// //
ASSERT (OptLen != 0); //
// Verify the arguments are valid
//
if (Packet == NULL) {
return EFI_INVALID_PARAMETER;
}
WriteUnaligned16 ((UINT16 *)Buf, OptType); if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
Buf += 2; return EFI_INVALID_PARAMETER;
WriteUnaligned16 ((UINT16 *)Buf, OptLen); }
Buf += 2;
CopyMem (Buf, Data, NTOHS (OptLen));
Buf += NTOHS (OptLen);
return Buf; if (Data == NULL) {
return EFI_INVALID_PARAMETER;
}
if (OptLen == 0) {
return EFI_INVALID_PARAMETER;
}
//
// Verify the PacketCursor is within the packet
//
if ( (*PacketCursor < Packet->Dhcp6.Option)
|| (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
{
return EFI_INVALID_PARAMETER;
}
//
// Calculate the bytes needed for the option
//
BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS (OptLen);
//
// Space remaining in the packet
//
Length = Packet->Size - Packet->Length;
if (Length < BytesNeeded) {
return EFI_BUFFER_TOO_SMALL;
}
//
// Verify the PacketCursor is within the packet
//
if ( (*PacketCursor < Packet->Dhcp6.Option)
|| (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
{
return EFI_INVALID_PARAMETER;
}
WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType);
*PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen);
*PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
CopyMem (*PacketCursor, Data, NTOHS (OptLen));
*PacketCursor += NTOHS (OptLen);
// Update the packet length by the length of the option + 4 bytes
Packet->Length += BytesNeeded;
return EFI_SUCCESS;
} }
/** /**
Append the appointed IA Address option to Buf, and move Buf to the end. Append the appointed IA Address option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append. @param[in, out] Packet A pointer to the packet, on success Packet->Length
will be updated.
@param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
will be moved to the end of the option.
@param[in] IaAddr The pointer to the IA Address. @param[in] IaAddr The pointer to the IA Address.
@param[in] MessageType Message type of DHCP6 package. @param[in] MessageType Message type of DHCP6 package.
@return Buf The position to append the next option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendIaAddrOption ( Dhcp6AppendIaAddrOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN OUT UINT8 **PacketCursor,
IN EFI_DHCP6_IA_ADDRESS *IaAddr, IN EFI_DHCP6_IA_ADDRESS *IaAddr,
IN UINT32 MessageType IN UINT32 MessageType
) )
{ {
UINT32 BytesNeeded;
UINT32 Length;
// The format of the IA Address option is: // The format of the IA Address option is:
// //
// 0 1 2 3 // 0 1 2 3
@ -657,17 +726,60 @@ Dhcp6AppendIaAddrOption (
// . . // . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Verify the arguments are valid
//
if (Packet == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (IaAddr == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Verify the PacketCursor is within the packet
//
if ( (*PacketCursor < Packet->Dhcp6.Option)
|| (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
{
return EFI_INVALID_PARAMETER;
}
BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
BytesNeeded += sizeof (EFI_IPv6_ADDRESS);
//
// Even if the preferred-lifetime is 0, it still needs to store it.
//
BytesNeeded += sizeof (IaAddr->PreferredLifetime);
//
// Even if the valid-lifetime is 0, it still needs to store it.
//
BytesNeeded += sizeof (IaAddr->ValidLifetime);
//
// Space remaining in the packet
//
Length = Packet->Size - Packet->Length;
if (Length < BytesNeeded) {
return EFI_BUFFER_TOO_SMALL;
}
// //
// Fill the value of Ia Address option type // Fill the value of Ia Address option type
// //
WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr)); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr));
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS))); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS)); CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
Buf += sizeof (EFI_IPv6_ADDRESS); *PacketCursor += sizeof (EFI_IPv6_ADDRESS);
// //
// Fill the value of preferred-lifetime and valid-lifetime. // Fill the value of preferred-lifetime and valid-lifetime.
@ -675,44 +787,58 @@ Dhcp6AppendIaAddrOption (
// should set to 0 when initiate a Confirm message. // should set to 0 when initiate a Confirm message.
// //
if (MessageType != Dhcp6MsgConfirm) { if (MessageType != Dhcp6MsgConfirm) {
WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime)); WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime));
} }
Buf += 4; *PacketCursor += sizeof (IaAddr->PreferredLifetime);
if (MessageType != Dhcp6MsgConfirm) { if (MessageType != Dhcp6MsgConfirm) {
WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime)); WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime));
} }
Buf += 4; *PacketCursor += sizeof (IaAddr->ValidLifetime);
return Buf; //
// Update the packet length
//
Packet->Length += BytesNeeded;
return EFI_SUCCESS;
} }
/** /**
Append the appointed Ia option to Buf, and move Buf to the end. Append the appointed Ia option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append. @param[in, out] Packet A pointer to the packet, on success Packet->Length
will be updated.
@param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
will be moved to the end of the option.
@param[in] Ia The pointer to the Ia. @param[in] Ia The pointer to the Ia.
@param[in] T1 The time of T1. @param[in] T1 The time of T1.
@param[in] T2 The time of T2. @param[in] T2 The time of T2.
@param[in] MessageType Message type of DHCP6 package. @param[in] MessageType Message type of DHCP6 package.
@return Buf The position to append the next Ia option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendIaOption ( Dhcp6AppendIaOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN EFI_DHCP6_IA *Ia, IN OUT UINT8 **PacketCursor,
IN UINT32 T1, IN EFI_DHCP6_IA *Ia,
IN UINT32 T2, IN UINT32 T1,
IN UINT32 MessageType IN UINT32 T2,
IN UINT32 MessageType
) )
{ {
UINT8 *AddrOpt; UINT8 *AddrOpt;
UINT16 *Len; UINT16 *Len;
UINTN Index; UINTN Index;
UINT32 BytesNeeded;
UINT32 Length;
EFI_STATUS Status;
// //
// The format of IA_NA and IA_TA option: // The format of IA_NA and IA_TA option:
@ -733,32 +859,74 @@ Dhcp6AppendIaOption (
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// //
//
// Verify the arguments are valid
//
if (Packet == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Ia == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Verify the PacketCursor is within the packet
//
if ( (*PacketCursor < Packet->Dhcp6.Option)
|| (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
{
return EFI_INVALID_PARAMETER;
}
BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
BytesNeeded += sizeof (Ia->Descriptor.IaId);
//
// + N for the IA_NA-options/IA_TA-options
// Dhcp6AppendIaAddrOption will need to check the length for each address
//
if (Ia->Descriptor.Type == Dhcp6OptIana) {
BytesNeeded += sizeof (T1) + sizeof (T2);
}
//
// Space remaining in the packet
//
Length = (UINT16)(Packet->Size - Packet->Length);
if (Length < BytesNeeded) {
return EFI_BUFFER_TOO_SMALL;
}
// //
// Fill the value of Ia option type // Fill the value of Ia option type
// //
WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type)); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type));
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
// //
// Fill the len of Ia option later, keep the pointer first // Fill the len of Ia option later, keep the pointer first
// //
Len = (UINT16 *)Buf; Len = (UINT16 *)*PacketCursor;
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
// //
// Fill the value of iaid // Fill the value of iaid
// //
WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId)); WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId));
Buf += 4; *PacketCursor += sizeof (Ia->Descriptor.IaId);
// //
// Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified. // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
// //
if (Ia->Descriptor.Type == Dhcp6OptIana) { if (Ia->Descriptor.Type == Dhcp6OptIana) {
WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff)); WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff));
Buf += 4; *PacketCursor += sizeof (T1);
WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff)); WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff));
Buf += 4; *PacketCursor += sizeof (T2);
} }
// //
@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
// //
for (Index = 0; Index < Ia->IaAddressCount; Index++) { for (Index = 0; Index < Ia->IaAddressCount; Index++) {
AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS); AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType); Status = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
if (EFI_ERROR (Status)) {
return Status;
}
} }
// //
// Fill the value of Ia option length // Fill the value of Ia option length
// //
*Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2)); *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
return Buf; //
// Update the packet length
//
Packet->Length += BytesNeeded;
return EFI_SUCCESS;
} }
/** /**
Append the appointed Elapsed time option to Buf, and move Buf to the end. Append the appointed Elapsed time option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append. @param[in, out] Packet A pointer to the packet, on success Packet->Length
@param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
will be moved to the end of the option.
@param[in] Instance The pointer to the Dhcp6 instance. @param[in] Instance The pointer to the Dhcp6 instance.
@param[out] Elapsed The pointer to the elapsed time value in @param[out] Elapsed The pointer to the elapsed time value in
the generated packet. the generated packet.
@return Buf The position to append the next Ia option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendETOption ( Dhcp6AppendETOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN DHCP6_INSTANCE *Instance, IN OUT UINT8 **PacketCursor,
OUT UINT16 **Elapsed IN DHCP6_INSTANCE *Instance,
OUT UINT16 **Elapsed
) )
{ {
UINT32 BytesNeeded;
UINT32 Length;
// //
// The format of elapsed time option: // The format of elapsed time option:
// //
@ -806,27 +990,70 @@ Dhcp6AppendETOption (
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// //
//
// Verify the arguments are valid
//
if (Packet == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Instance == NULL) {
return EFI_INVALID_PARAMETER;
}
if ((Elapsed == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Verify the PacketCursor is within the packet
//
if ( (*PacketCursor < Packet->Dhcp6.Option)
|| (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
{
return EFI_INVALID_PARAMETER;
}
BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
//
// + 2 for elapsed-time
//
BytesNeeded += sizeof (UINT16);
//
// Space remaining in the packet
//
Length = Packet->Size - Packet->Length;
if (Length < BytesNeeded) {
return EFI_BUFFER_TOO_SMALL;
}
// //
// Fill the value of elapsed-time option type. // Fill the value of elapsed-time option type.
// //
WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime)); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime));
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
// //
// Fill the len of elapsed-time option, which is fixed. // Fill the len of elapsed-time option, which is fixed.
// //
WriteUnaligned16 ((UINT16 *)Buf, HTONS (2)); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2));
Buf += 2; *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
// //
// Fill in elapsed time value with 0 value for now. The actual value is // Fill in elapsed time value with 0 value for now. The actual value is
// filled in later just before the packet is transmitted. // filled in later just before the packet is transmitted.
// //
WriteUnaligned16 ((UINT16 *)Buf, HTONS (0)); WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0));
*Elapsed = (UINT16 *)Buf; *Elapsed = (UINT16 *)*PacketCursor;
Buf += 2; *PacketCursor += sizeof (UINT16);
return Buf; Packet->Length += BytesNeeded;
return EFI_SUCCESS;
} }
/** /**

View File

@ -160,69 +160,85 @@ Dhcp6OnTransmitted (
); );
/** /**
Append the appointed option to the buf, and move the buf to the end. Append the option to Buf, update the length of packet, and move Buf to the end.
@param[in, out] Buf The pointer to buffer. @param[in, out] Packet A pointer to the packet, on success Packet->Length
@param[in] OptType The option type. will be updated.
@param[in] OptLen The length of option content.s @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
@param[in] Data The pointer to the option content. will be moved to the end of the option.
@param[in] OptType The option type.
@return Buf The position to append the next option. @param[in] OptLen The length of option contents.
@param[in] Data The pointer to the option content.
@retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendOption ( Dhcp6AppendOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN UINT16 OptType, IN OUT UINT8 **PacketCursor,
IN UINT16 OptLen, IN UINT16 OptType,
IN UINT8 *Data IN UINT16 OptLen,
IN UINT8 *Data
); );
/** /**
Append the Ia option to Buf, and move Buf to the end. Append the appointed Ia option to Buf, update the Ia option length, and move Buf
to the end of the option.
@param[in, out] Buf The pointer to the position to append. @param[in, out] Packet A pointer to the packet, on success Packet->Length
will be updated.
@param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
will be moved to the end of the option.
@param[in] Ia The pointer to the Ia. @param[in] Ia The pointer to the Ia.
@param[in] T1 The time of T1. @param[in] T1 The time of T1.
@param[in] T2 The time of T2. @param[in] T2 The time of T2.
@param[in] MessageType Message type of DHCP6 package. @param[in] MessageType Message type of DHCP6 package.
@return Buf The position to append the next Ia option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendIaOption ( Dhcp6AppendIaOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN EFI_DHCP6_IA *Ia, IN OUT UINT8 **PacketCursor,
IN UINT32 T1, IN EFI_DHCP6_IA *Ia,
IN UINT32 T2, IN UINT32 T1,
IN UINT32 MessageType IN UINT32 T2,
IN UINT32 MessageType
); );
/** /**
Append the appointed Elapsed time option to Buf, and move Buf to the end. Append the appointed Elapsed time option to Buf, and move Buf to the end.
@param[in, out] Buf The pointer to the position to append. @param[in, out] Packet A pointer to the packet, on success Packet->Length
@param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
will be moved to the end of the option.
@param[in] Instance The pointer to the Dhcp6 instance. @param[in] Instance The pointer to the Dhcp6 instance.
@param[out] Elapsed The pointer to the elapsed time value in @param[out] Elapsed The pointer to the elapsed time value in
the generated packet. the generated packet.
@return Buf The position to append the next Ia option. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
UINT8 * EFI_STATUS
Dhcp6AppendETOption ( Dhcp6AppendETOption (
IN OUT UINT8 *Buf, IN OUT EFI_DHCP6_PACKET *Packet,
IN DHCP6_INSTANCE *Instance, IN OUT UINT8 **PacketCursor,
OUT UINT16 **Elapsed IN DHCP6_INSTANCE *Instance,
OUT UINT16 **Elapsed
); );
/** /**
Set the elapsed time based on the given instance and the pointer to the Set the elapsed time based on the given instance and the pointer to the
elapsed time option. elapsed time option.
@param[in] Elapsed The pointer to the position to append. @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
@param[in] Instance The pointer to the Dhcp6 instance. @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
@retval EFI_SUCCESS The option is appended successfully.
**/ **/
VOID VOID
SetElapsedTime ( SetElapsedTime (