[ip6] no anycast as source address (#5632)

- Check source address of packets from users
- Determine anycast address by MLE API for accuracy
- Replace anycast address with a valid unicast address when sending
  with platform UDP in UDP layer
- Replace anycast address with a valid unicast address in IP layer
This commit is contained in:
Yakun Xu
2020-10-13 08:10:29 -07:00
committed by GitHub
parent 831406ce90
commit d0d2b71af3
6 changed files with 85 additions and 14 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (32)
#define OPENTHREAD_API_VERSION (33)
/**
* @addtogroup api-instance
+7 -5
View File
@@ -486,11 +486,13 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled);
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMessage A pointer to the message buffer containing 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_PARSE Encountered a malformed header when processing the message.
* @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 addresss is invalid, e.g. an anycast address or a multicast address.
* @retval OT_ERROR_PARSE Encountered a malformed header when processing the message.
*
*/
otError otIp6Send(otInstance *aInstance, otMessage *aMessage);
+11 -7
View File
@@ -457,7 +457,8 @@ otError Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t
header.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
}
if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast() ||
Get<Mle::Mle>().IsAnycastLocator(aMessageInfo.GetSockAddr()))
{
const NetifUnicastAddress *source = SelectSourceAddress(aMessageInfo);
@@ -1071,6 +1072,8 @@ otError Ip6::SendRaw(Message &aMessage)
bool freed = false;
SuccessOrExit(error = header.Init(aMessage));
VerifyOrExit(!header.GetSource().IsMulticast() && !Get<Mle::Mle>().IsAnycastLocator(header.GetSource()),
error = OT_ERROR_INVALID_SOURCE_ADDRESS);
messageInfo.SetPeerAddr(header.GetSource());
messageInfo.SetSockAddr(header.GetDestination());
@@ -1301,10 +1304,11 @@ exit:
const NetifUnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
{
Address * destination = &aMessageInfo.GetPeerAddr();
uint8_t destinationScope = destination->GetScope();
const NetifUnicastAddress *rvalAddr = nullptr;
uint8_t rvalPrefixMatched = 0;
Address * destination = &aMessageInfo.GetPeerAddr();
uint8_t destinationScope = destination->GetScope();
const bool destinationIsRoutingLocator = Get<Mle::Mle>().IsRoutingLocator(*destination);
const NetifUnicastAddress *rvalAddr = nullptr;
uint8_t rvalPrefixMatched = 0;
for (const NetifUnicastAddress *addr = Get<ThreadNetif>().GetUnicastAddresses(); addr; addr = addr->GetNext())
{
@@ -1312,7 +1316,7 @@ const NetifUnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
uint8_t candidatePrefixMatched;
uint8_t overrideScope;
if (candidateAddr->GetIid().IsAnycastLocator())
if (Get<Mle::Mle>().IsAnycastLocator(*candidateAddr))
{
// Don't use anycast address as source address.
continue;
@@ -1382,7 +1386,7 @@ const NetifUnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
rvalPrefixMatched = candidatePrefixMatched;
}
else if ((candidatePrefixMatched == rvalPrefixMatched) &&
(destination->GetIid().IsRoutingLocator() == candidateAddr->GetIid().IsRoutingLocator()))
(destinationIsRoutingLocator == Get<Mle::Mle>().IsRoutingLocator(*candidateAddr)))
{
// Additional rule: Prefer RLOC source for RLOC destination, EID source for anything else
rvalAddr = addr;
+9
View File
@@ -327,6 +327,15 @@ otError Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo
if (!IsMlePort(aSocket.mSockName.mPort) &&
!(aSocket.mSockName.mPort == Tmf::kUdpPort && aMessage.GetSubType() == Message::kSubTypeJoinerEntrust))
{
// Replace anycast address with a valid unicast address since response messages typically copy the peer address
if (Get<Mle::Mle>().IsAnycastLocator(messageInfoLocal.GetSockAddr()))
{
const NetifUnicastAddress *netifAddr = Get<Ip6>().SelectSourceAddress(messageInfoLocal);
VerifyOrExit(netifAddr != nullptr, error = OT_ERROR_INVALID_ARGS);
messageInfoLocal.SetSockAddr(netifAddr->GetAddress());
}
SuccessOrExit(error = otPlatUdpSend(&aSocket, &aMessage, &messageInfoLocal));
}
else
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2020, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
source "tests/scripts/expect/_common.exp"
set spawn_id [spawn_node 1]
send "panid 0xface\n"
expect "Done"
send "ifconfig up\n"
expect "Done"
send "thread start\n"
expect "Done"
wait_for "state" "leader"
expect "Done"
send "ping fdde:ad00:beef:0:0:ff:fe00:fc00\n"
expect "Done"
expect "16 bytes from "
expect {
"fdde:ad00:beef:0:0:ff:fe00:fc00" abort
-re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})} {}
timeout abort
}
dispose
+1 -1
View File
@@ -40,7 +40,7 @@ expect "Done"
wait_for "state" "leader"
expect "Done"
send "ipaddr\n"
send "ipaddr mleid\n"
expect -re {(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4})}
set addr $expect_out(1,string)
expect "Done"