Skip to content

Commit

Permalink
save
Browse files Browse the repository at this point in the history
  • Loading branch information
superwhd committed Sep 21, 2023
1 parent 93e72bc commit dc46b24
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 73 deletions.
2 changes: 1 addition & 1 deletion include/openthread/instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (359)
#define OPENTHREAD_API_VERSION (360)

/**
* @addtogroup api-instance
Expand Down
23 changes: 23 additions & 0 deletions include/openthread/ip6.h
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,29 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled);
*/
otError otIp6Send(otInstance *aInstance, otMessage *aMessage);

/**
* Sends an untrusted IPv6 datagram via Thread interface.
*
* The caller transfers ownership of @p aMessage when making this call. OpenThread will free @p aMessage when
* processing is complete, including when a value other than `OT_ERROR_NONE` is returned.
*
* This function is identical to `otIp6Send` except the this one allows you to specify the datagram's origin.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMessage A pointer to the message buffer containing the IPv6 datagram.
* @param[in] aOrigin An enum representing the origin of the IPv6 datagram.
*
* @retval OT_ERROR_NONE Successfully processed the message.
* @retval OT_ERROR_DROP Message was well-formed but not fully processed due to packet processing
* rules.
* @retval OT_ERROR_NO_BUFS Could not allocate necessary message buffers when processing the datagram.
* @retval OT_ERROR_NO_ROUTE No route to host.
* @retval OT_ERROR_INVALID_SOURCE_ADDRESS Source address is invalid, e.g. an anycast address or a multicast address.
* @retval OT_ERROR_PARSE Encountered a malformed header when processing the message.
*
*/
otError otIp6SendFromOrigin(otInstance *aInstance, otMessage *aMessage, otMessageOrigin aOrigin);

/**
* Adds a port to the allowed unsecured port list.
*
Expand Down
13 changes: 13 additions & 0 deletions include/openthread/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ typedef enum otMessagePriority
OT_MESSAGE_PRIORITY_HIGH = 2, ///< High priority level.
} otMessagePriority;

/**
* Defines the OpenThread message origins.
*
*/
typedef enum otMessageOrigin
{
OT_MESSAGE_ORIGIN_FROM_THREAD_NETIF = 0, ///< Message originates from Thread Netif.
OT_MESSAGE_ORIGIN_FROM_HOST_DISALLOW_LOOPBACK = 1, ///< Message originates from host and should not be passed back
///< to host.
OT_MESSAGE_ORIGIN_FROM_HOST_ALLOW_LOOPBACK = 2, ///< Message originates from host and can be passed back to host.
OT_MESSAGE_ORIGIN_FROM_HOST_UNTRUSTED = 3, ///< Message originates from an untrusted source on host.
} otMessageOrigin;

/**
* Represents a message settings.
*
Expand Down
12 changes: 10 additions & 2 deletions src/core/api/ip6_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,16 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled)

otError otIp6Send(otInstance *aInstance, otMessage *aMessage)
{
return AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage),
OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS);
AsCoreType(aMessage).SetOrigin(OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS
? Message::Origin::kFromHostAllowLoopBack
: Message::Origin::kFromHostDisallowLoopBack);
return AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage));
}

otError otIp6SendFromOrigin(otInstance *aInstance, otMessage *aMessage, otMessageOrigin aOrigin)
{
AsCoreType(aMessage).SetOrigin(static_cast<Message::Origin>(aOrigin));
return AsCoreType(aInstance).Get<Ip6::Ip6>().SendRaw(AsCoreType(aMessage));
}

otMessage *otIp6NewMessage(otInstance *aInstance, const otMessageSettings *aSettings)
Expand Down
1 change: 1 addition & 0 deletions src/core/common/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ Message *Message::Clone(uint16_t aLength) const
messageCopy->SetOffset(offset);

messageCopy->SetSubType(GetSubType());
messageCopy->SetOrigin(GetOrigin());
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
messageCopy->SetTimeSync(IsTimeSync());
#endif
Expand Down
36 changes: 36 additions & 0 deletions src/core/common/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer>
bool mDoNotEvict : 1; // Whether this message may be evicted.
bool mMulticastLoop : 1; // Whether this multicast message may be looped back.
bool mResolvingAddress : 1; // Whether the message is pending an address query resolution.
uint8_t mOrigin : 2; // The origin of the message.
#if OPENTHREAD_CONFIG_MULTI_RADIO
uint8_t mRadioType : 2; // The radio link type the message was received on, or should be sent on.
bool mIsRadioTypeSet : 1; // Whether the radio type is set.
Expand Down Expand Up @@ -349,6 +350,25 @@ class Message : public otMessage, public Buffer, public GetProvider<Message>
kCopyToUse,
};

/**
* Represents an IPv6 message origin.
*
* In case the message is originating from host, it may also indicate whether or not it is allowed to passed back
* the message to the host.
*
*/
enum Origin : uint8_t
{
// Message originates from Thread Netif.
kFromThreadNetif = OT_MESSAGE_ORIGIN_FROM_THREAD_NETIF,
// Message originates from host and should not be passed back to host.
kFromHostDisallowLoopBack = OT_MESSAGE_ORIGIN_FROM_HOST_DISALLOW_LOOPBACK,
// Message originates from host and can be passed back to host.
kFromHostAllowLoopBack = OT_MESSAGE_ORIGIN_FROM_HOST_ALLOW_LOOPBACK,
// Message originates from an untrusted source on host.
kFromHostUntrusted = OT_MESSAGE_ORIGIN_FROM_HOST_UNTRUSTED,
};

/**
* Represents settings used for creating a new message.
*
Expand Down Expand Up @@ -1135,6 +1155,22 @@ class Message : public otMessage, public Buffer, public GetProvider<Message>
*/
void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }

/**
* Returns the origin of the message.
*
* @returns An enum representing the origin of the message.
*
*/
Origin GetOrigin(void) const { return static_cast<Origin>(GetMetadata().mOrigin); }

/**
* Sets the origin of the message.
*
* @param aOrigin An enum representing the origin of the message.
*
*/
void SetOrigin(Origin aOrigin) { GetMetadata().mOrigin = aOrigin; }

/**
* Indicates whether or not link security is enabled for the message.
*
Expand Down
91 changes: 54 additions & 37 deletions src/core/net/ip6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader)

if ((messageCopy = aMessage.Clone()) != nullptr)
{
IgnoreError(HandleDatagram(*messageCopy, kFromHostDisallowLoopBack));
messageCopy->SetOrigin(Message::Origin::kFromHostDisallowLoopBack);
IgnoreError(HandleDatagram(*messageCopy));
LogInfo("Message copy for indirect transmission to sleepy children");
}
else
Expand Down Expand Up @@ -512,7 +513,11 @@ void Ip6::HandleSendQueue(void)
while ((message = mSendQueue.GetHead()) != nullptr)
{
mSendQueue.Dequeue(*message);
IgnoreError(HandleDatagram(*message, kFromHostAllowLoopBack));
if (message->GetOrigin() != Message::Origin::kFromHostUntrusted)
{
message->SetOrigin(Message::Origin::kFromHostAllowLoopBack);
}
IgnoreError(HandleDatagram(*message));
}
}

Expand Down Expand Up @@ -634,7 +639,7 @@ Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
return error;
}

Error Ip6::HandleFragment(Message &aMessage, MessageOrigin aOrigin, MessageInfo &aMessageInfo)
Error Ip6::HandleFragment(Message &aMessage, MessageInfo &aMessageInfo)
{
Error error = kErrorNone;
Header header, headerBuffer;
Expand Down Expand Up @@ -721,7 +726,7 @@ Error Ip6::HandleFragment(Message &aMessage, MessageOrigin aOrigin, MessageInfo

mReassemblyList.Dequeue(*message);

IgnoreError(HandleDatagram(*message, aOrigin, aMessageInfo.mLinkInfo, /* aIsReassembled */ true));
IgnoreError(HandleDatagram(*message, aMessageInfo.mLinkInfo, /* aIsReassembled */ true));
}

exit:
Expand Down Expand Up @@ -805,9 +810,8 @@ Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto)
return kErrorNone;
}

Error Ip6::HandleFragment(Message &aMessage, MessageOrigin aOrigin, MessageInfo &aMessageInfo)
Error Ip6::HandleFragment(Message &aMessage, MessageInfo &aMessageInfo)
{
OT_UNUSED_VARIABLE(aOrigin);
OT_UNUSED_VARIABLE(aMessageInfo);

Error error = kErrorNone;
Expand All @@ -824,15 +828,15 @@ Error Ip6::HandleFragment(Message &aMessage, MessageOrigin aOrigin, MessageInfo
}
#endif // OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE

Error Ip6::HandleExtensionHeaders(Message &aMessage,
MessageOrigin aOrigin,
MessageInfo &aMessageInfo,
Header &aHeader,
uint8_t &aNextHeader,
bool &aReceive)
Error Ip6::HandleExtensionHeaders(Message &aMessage,
MessageInfo &aMessageInfo,
Header &aHeader,
uint8_t &aNextHeader,
bool &aReceive)
{
Error error = kErrorNone;
bool isOutbound = (aOrigin != kFromThreadNetif);
Message::Origin origin = aMessage.GetOrigin();
bool isOutbound = (origin != Message::Origin::kFromThreadNetif);
ExtensionHeader extHeader;

while (aReceive || aNextHeader == kProtoHopOpts)
Expand All @@ -846,9 +850,9 @@ Error Ip6::HandleExtensionHeaders(Message &aMessage,
break;

case kProtoFragment:
IgnoreError(PassToHost(aMessage, aOrigin, aMessageInfo, aNextHeader,
IgnoreError(PassToHost(aMessage, aMessageInfo, aNextHeader,
/* aApplyFilter */ false, aReceive, Message::kCopyToUse));
SuccessOrExit(error = HandleFragment(aMessage, aOrigin, aMessageInfo));
SuccessOrExit(error = HandleFragment(aMessage, aMessageInfo));
break;

case kProtoDstOpts:
Expand Down Expand Up @@ -904,6 +908,8 @@ Error Ip6::HandlePayload(Header &aIp6Header,
VerifyOrExit((message = aMessage.Clone()) != nullptr, error = kErrorNoBufs);
}

VerifyOrExit(message != nullptr);

switch (aIpProto)
{
#if OPENTHREAD_CONFIG_TCP_ENABLE
Expand Down Expand Up @@ -943,7 +949,6 @@ Error Ip6::HandlePayload(Header &aIp6Header,
}

Error Ip6::PassToHost(Message &aMessage,
MessageOrigin aOrigin,
const MessageInfo &aMessageInfo,
uint8_t aIpProto,
bool aApplyFilter,
Expand Down Expand Up @@ -971,7 +976,7 @@ Error Ip6::PassToHost(Message &aMessage,
message = &aMessage;
}

VerifyOrExit(aOrigin != kFromHostDisallowLoopBack, error = kErrorNoRoute);
VerifyOrExit(aMessage.GetOrigin() != Message::Origin::kFromHostDisallowLoopBack, error = kErrorNoRoute);

VerifyOrExit(mReceiveIp6DatagramCallback.IsSet(), error = kErrorNoRoute);

Expand Down Expand Up @@ -1090,7 +1095,7 @@ Error Ip6::PassToHost(Message &aMessage,
return error;
}

Error Ip6::SendRaw(Message &aMessage, bool aAllowLoopBackToHost)
Error Ip6::SendRaw(Message &aMessage)
{
Error error = kErrorNone;
Header header;
Expand Down Expand Up @@ -1118,7 +1123,7 @@ Error Ip6::SendRaw(Message &aMessage, bool aAllowLoopBackToHost)
SuccessOrExit(error = InsertMplOption(aMessage, header));
}

error = HandleDatagram(aMessage, aAllowLoopBackToHost ? kFromHostAllowLoopBack : kFromHostDisallowLoopBack);
error = HandleDatagram(aMessage);
freed = true;

#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
Expand All @@ -1135,16 +1140,17 @@ Error Ip6::SendRaw(Message &aMessage, bool aAllowLoopBackToHost)
return error;
}

Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *aLinkMessageInfo, bool aIsReassembled)
Error Ip6::HandleDatagram(Message &aMessage, const void *aLinkMessageInfo, bool aIsReassembled)
{
Error error;
MessageInfo messageInfo;
Header header;
bool receive;
bool forwardThread;
bool forwardHost;
bool shouldFreeMessage;
uint8_t nextHeader;
Error error;
MessageInfo messageInfo;
Header header;
bool receive;
bool forwardThread;
bool forwardHost;
bool shouldFreeMessage;
uint8_t nextHeader;
Message::Origin origin = aMessage.GetOrigin();

start:
receive = false;
Expand All @@ -1168,10 +1174,11 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *
{
// Destination is multicast

forwardThread = (aOrigin != kFromThreadNetif);
forwardThread = (origin != Message::Origin::kFromThreadNetif);

#if OPENTHREAD_FTD
if ((aOrigin == kFromThreadNetif) && header.GetDestination().IsMulticastLargerThanRealmLocal() &&
if ((origin == Message::Origin::kFromThreadNetif) &&
header.GetDestination().IsMulticastLargerThanRealmLocal() &&
Get<ChildTable>().HasSleepyChildWithAddress(header.GetDestination()))
{
forwardThread = true;
Expand All @@ -1180,7 +1187,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *

forwardHost = header.GetDestination().IsMulticastLargerThanRealmLocal();

if (((aOrigin == kFromThreadNetif) || aMessage.GetMulticastLoop()) &&
if (((origin == Message::Origin::kFromThreadNetif) || aMessage.GetMulticastLoop()) &&
Get<ThreadNetif>().IsMulticastSubscribed(header.GetDestination()))
{
receive = true;
Expand All @@ -1198,7 +1205,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *
{
receive = true;
}
else if ((aOrigin != kFromThreadNetif) || !header.GetDestination().IsLinkLocal())
else if ((origin != Message::Origin::kFromThreadNetif) || !header.GetDestination().IsLinkLocal())
{
if (header.GetDestination().IsLinkLocal())
{
Expand All @@ -1207,7 +1214,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *
else if (IsOnLink(header.GetDestination()))
{
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
forwardThread = ((aOrigin == kFromHostDisallowLoopBack) ||
forwardThread = ((origin == Message::Origin::kFromHostDisallowLoopBack) ||
!Get<BackboneRouter::Manager>().ShouldForwardDuaToBackbone(header.GetDestination()));
#else
forwardThread = true;
Expand All @@ -1226,7 +1233,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *

// Process IPv6 Extension Headers
nextHeader = static_cast<uint8_t>(header.GetNextHeader());
SuccessOrExit(error = HandleExtensionHeaders(aMessage, aOrigin, messageInfo, header, nextHeader, receive));
SuccessOrExit(error = HandleExtensionHeaders(aMessage, messageInfo, header, nextHeader, receive));

if (receive && (nextHeader == kProtoIp6))
{
Expand All @@ -1238,7 +1245,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *

if ((forwardHost || receive) && !aIsReassembled)
{
error = PassToHost(aMessage, aOrigin, messageInfo, nextHeader,
error = PassToHost(aMessage, messageInfo, nextHeader,
/* aApplyFilter */ !forwardHost, receive,
(receive || forwardThread) ? Message::kCopyToUse : Message::kTakeCustody);

Expand All @@ -1261,7 +1268,7 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *
{
uint8_t hopLimit;

if (aOrigin == kFromThreadNetif)
if (origin == Message::Origin::kFromThreadNetif)
{
VerifyOrExit(Get<Mle::Mle>().IsRouterOrLeader());
header.SetHopLimit(header.GetHopLimit() - 1);
Expand Down Expand Up @@ -1289,8 +1296,18 @@ Error Ip6::HandleDatagram(Message &aMessage, MessageOrigin aOrigin, const void *
VerifyOrExit(isAllowedType, error = kErrorDrop);
}

if (aMessage.GetOrigin() == Message::Origin::kFromHostUntrusted && nextHeader == kProtoUdp)
{
uint16_t destPort;

SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + Udp::Header::kDestPortFieldOffset, destPort));
destPort = HostSwap16(destPort);

VerifyOrExit(destPort != Tmf::kUdpPort);
}

#if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
if ((aOrigin == kFromHostDisallowLoopBack) && (nextHeader == kProtoUdp))
if ((origin == Message::Origin::kFromHostDisallowLoopBack) && (nextHeader == kProtoUdp))
{
uint16_t destPort;

Expand Down
Loading

0 comments on commit dc46b24

Please sign in to comment.