mirror of
https://github.com/espressif/openthread.git
synced 2026-08-14 06:37:46 +00:00
[icmp6] allow config of echo handling for unicast/multicast separately (#2609)
Previously, ICMPv6 Echo Request handling was either enabled or disabled. This commit allows enabling/disabling the handler for ICMPv6 Echo Requests sent to unicast and multicast destinations separately. This commit also adds an associated spinel property and NCP implementation.
This commit is contained in:
@@ -47,3 +47,23 @@ Default value is `false`.
|
||||
Array of structures containing:
|
||||
|
||||
* `6`: Multicast IPv6 Address
|
||||
|
||||
### PROP 103: PROP_IPv6_ICMP_PING_OFFLOAD_MODE
|
||||
* Type: Read-Write
|
||||
* Packed-Encoding: `C`
|
||||
* Unit: Enumeration
|
||||
|
||||
Allow the NCP to directly respond to ICMP ping requests. If this is
|
||||
turned on, ping request ICMP packets will not be passed to the host.
|
||||
|
||||
This property allows enabling responses sent to unicast only, multicast
|
||||
only, or both.
|
||||
|
||||
Values:
|
||||
|
||||
* 0: `IPV6_ICMP_PING_OFFLOAD_DISABLED`
|
||||
* 1: `IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY`
|
||||
* 2: `IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY`
|
||||
* 3: `IPV6_ICMP_PING_OFFLOAD_ALL`
|
||||
|
||||
Default value is `IPV6_ICMP_PING_OFFLOAD_DISABLED`.
|
||||
|
||||
@@ -786,7 +786,7 @@ otLwfEventWorkerThread(
|
||||
NT_ASSERT(otCtxToFilter(pFilter->otCtx) == pFilter);
|
||||
|
||||
// Disable Icmp (ping) handling
|
||||
otIcmp6SetEchoEnabled(pFilter->otCtx, FALSE);
|
||||
otIcmp6SetEchoMode(pFilter->otCtx, OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
|
||||
// Register callbacks with OpenThread
|
||||
otSetStateChangedCallback(pFilter->otCtx, otLwfStateChangedCallback, pFilter);
|
||||
|
||||
@@ -82,7 +82,7 @@ otPlatReset(
|
||||
NT_ASSERT(otCtxToFilter(pFilter->otCtx) == pFilter);
|
||||
|
||||
// Disable Icmp (ping) handling
|
||||
otIcmp6SetEchoEnabled(pFilter->otCtx, FALSE);
|
||||
otIcmp6SetEchoMode(pFilter->otCtx, OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
|
||||
// Register callbacks with OpenThread
|
||||
otSetStateChangedCallback(pFilter->otCtx, otLwfStateChangedCallback, pFilter);
|
||||
|
||||
@@ -123,25 +123,38 @@ typedef struct otIcmp6Handler
|
||||
struct otIcmp6Handler *mNext; ///< A pointer to the next handler in the list.
|
||||
} otIcmp6Handler;
|
||||
|
||||
/**
|
||||
* ICMPv6 Echo Reply Modes
|
||||
*
|
||||
*/
|
||||
typedef enum otIcmp6EchoMode {
|
||||
OT_ICMP6_ECHO_HANDLER_DISABLED = 0, ///< ICMPv6 Echo processing disabled
|
||||
OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY = 1, ///< ICMPv6 Echo processing enabled only for unicast requests only
|
||||
OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY = 2, ///< ICMPv6 Echo processing enabled only for multicast requests only
|
||||
OT_ICMP6_ECHO_HANDLER_ALL = 3, ///< ICMPv6 Echo processing enabled for unicast and multicast requests
|
||||
} otIcmp6EchoMode;
|
||||
|
||||
/**
|
||||
* This function indicates whether or not ICMPv6 Echo processing is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval TRUE ICMPv6 Echo processing is enabled.
|
||||
* @retval FALSE ICMPv6 Echo processing is disabled.
|
||||
* @retval OT_ICMP6_ECHO_HANDLER_DISABLED ICMPv6 Echo processing is disabled.
|
||||
* @retval OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY ICMPv6 Echo processing enabled for unicast requests only
|
||||
* @retval OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY ICMPv6 Echo processing enabled for multicast requests only
|
||||
* @retval OT_ICMP6_ECHO_HANDLER_ALL ICMPv6 Echo processing enabled for unicast and multicast requests
|
||||
*
|
||||
*/
|
||||
bool otIcmp6IsEchoEnabled(otInstance *aInstance);
|
||||
otIcmp6EchoMode otIcmp6GetEchoMode(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* This function sets whether or not ICMPv6 Echo processing is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
|
||||
* @param[in] aMode The ICMPv6 Echo processing mode.
|
||||
*
|
||||
*/
|
||||
void otIcmp6SetEchoEnabled(otInstance *aInstance, bool aEnabled);
|
||||
void otIcmp6SetEchoMode(otInstance *aInstance, otIcmp6EchoMode aMode);
|
||||
|
||||
/**
|
||||
* This function registers a handler to provide received ICMPv6 messages.
|
||||
@@ -150,7 +163,7 @@ void otIcmp6SetEchoEnabled(otInstance *aInstance, bool aEnabled);
|
||||
* OpenThread does not make a copy of handler structure.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aHandler A pointer to a handler conitaining callback that is called when
|
||||
* @param[in] aHandler A pointer to a handler containing callback that is called when
|
||||
* an ICMPv6 message is received.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -39,18 +39,18 @@
|
||||
|
||||
using namespace ot;
|
||||
|
||||
bool otIcmp6IsEchoEnabled(otInstance *aInstance)
|
||||
otIcmp6EchoMode otIcmp6GetEchoMode(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetIp6().GetIcmp().IsEchoEnabled();
|
||||
return instance.GetIp6().GetIcmp().GetEchoMode();
|
||||
}
|
||||
|
||||
void otIcmp6SetEchoEnabled(otInstance *aInstance, bool aEnabled)
|
||||
void otIcmp6SetEchoMode(otInstance *aInstance, otIcmp6EchoMode aMode)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
instance.GetIp6().GetIcmp().SetEchoEnabled(aEnabled);
|
||||
instance.GetIp6().GetIcmp().SetEchoMode(aMode);
|
||||
}
|
||||
|
||||
otError otIcmp6RegisterHandler(otInstance *aInstance, otIcmp6Handler *aHandler)
|
||||
|
||||
+27
-2
@@ -53,7 +53,7 @@ Icmp::Icmp(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mHandlers(NULL)
|
||||
, mEchoSequence(1)
|
||||
, mIsEchoEnabled(true)
|
||||
, mEchoMode(OT_ICMP6_ECHO_HANDLER_ALL)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ otError Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
checksum = aMessage.UpdateChecksum(checksum, aMessage.GetOffset(), payloadLength);
|
||||
VerifyOrExit(checksum == 0xffff, error = OT_ERROR_PARSE);
|
||||
|
||||
if (mIsEchoEnabled && (icmp6Header.GetType() == IcmpHeader::kTypeEchoRequest))
|
||||
if (icmp6Header.GetType() == IcmpHeader::kTypeEchoRequest)
|
||||
{
|
||||
HandleEchoRequest(aMessage, aMessageInfo);
|
||||
}
|
||||
@@ -173,6 +173,29 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Icmp::ShouldHandleEchoRequest(const MessageInfo &aMessageInfo)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
switch (mEchoMode)
|
||||
{
|
||||
case OT_ICMP6_ECHO_HANDLER_DISABLED:
|
||||
rval = false;
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY:
|
||||
rval = !aMessageInfo.GetSockAddr().IsMulticast();
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY:
|
||||
rval = aMessageInfo.GetSockAddr().IsMulticast();
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_ALL:
|
||||
rval = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
otError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
@@ -181,6 +204,8 @@ otError Icmp::HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMe
|
||||
MessageInfo replyMessageInfo;
|
||||
uint16_t payloadLength;
|
||||
|
||||
VerifyOrExit(ShouldHandleEchoRequest(aMessageInfo));
|
||||
|
||||
otLogInfoIcmp(GetInstance(), "Received Echo Request");
|
||||
|
||||
icmp6Header.Init();
|
||||
|
||||
+13
-4
@@ -325,7 +325,7 @@ public:
|
||||
* @retval FALSE ICMPv6 Echo processing is disabled.
|
||||
*
|
||||
*/
|
||||
bool IsEchoEnabled(void) { return mIsEchoEnabled; }
|
||||
otIcmp6EchoMode GetEchoMode(void) const { return mEchoMode; }
|
||||
|
||||
/**
|
||||
* This method sets whether or not ICMPv6 Echo processing is enabled.
|
||||
@@ -333,15 +333,24 @@ public:
|
||||
* @param[in] aEnabled TRUE to enable ICMPv6 Echo processing, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetEchoEnabled(bool aEnabled) { mIsEchoEnabled = aEnabled; }
|
||||
void SetEchoMode(otIcmp6EchoMode aMode) { mEchoMode = aMode; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the ICMPv6 Echo Request should be handled.
|
||||
*
|
||||
* @retval TRUE if OpenThread should respond with an ICMPv6 Echo Reply.
|
||||
* @retval FALSE if OpenThread should not respond with an ICMPv6 Echo Reply.
|
||||
*
|
||||
*/
|
||||
bool ShouldHandleEchoRequest(const MessageInfo &aMessageInfo);
|
||||
|
||||
private:
|
||||
otError HandleEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo);
|
||||
|
||||
IcmpHandler *mHandlers;
|
||||
|
||||
uint16_t mEchoSequence;
|
||||
bool mIsEchoEnabled;
|
||||
uint16_t mEchoSequence;
|
||||
otIcmp6EchoMode mEchoMode;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -616,7 +616,7 @@ otError Ip6::ProcessReceiveCallback(const Message & aMessage,
|
||||
switch (aIpProto)
|
||||
{
|
||||
case kProtoIcmp6:
|
||||
if (mIcmp.IsEchoEnabled())
|
||||
if (mIcmp.ShouldHandleEchoRequest(aMessageInfo))
|
||||
{
|
||||
IcmpHeader icmp;
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(icmp), &icmp);
|
||||
|
||||
@@ -145,6 +145,7 @@ const NcpBase::PropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] =
|
||||
NCP_GET_PROP_HANDLER_ENTRY(THREAD_PENDING_DATASET),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ADDRESS_TABLE),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ICMP_PING_OFFLOAD),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ICMP_PING_OFFLOAD_MODE),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_LL_ADDR),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ML_PREFIX),
|
||||
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ML_ADDR),
|
||||
@@ -292,6 +293,7 @@ const NcpBase::PropertyHandlerEntry NcpBase::mSetPropertyHandlerTable[] =
|
||||
NCP_SET_PROP_HANDLER_ENTRY(STREAM_NET),
|
||||
NCP_SET_PROP_HANDLER_ENTRY(IPV6_ML_PREFIX),
|
||||
NCP_SET_PROP_HANDLER_ENTRY(IPV6_ICMP_PING_OFFLOAD),
|
||||
NCP_SET_PROP_HANDLER_ENTRY(IPV6_ICMP_PING_OFFLOAD_MODE),
|
||||
NCP_SET_PROP_HANDLER_ENTRY(THREAD_RLOC16_DEBUG_PASSTHRU),
|
||||
#if OPENTHREAD_ENABLE_MAC_FILTER
|
||||
NCP_SET_PROP_HANDLER_ENTRY(MAC_WHITELIST),
|
||||
@@ -604,7 +606,7 @@ NcpBase::NcpBase(Instance *aInstance):
|
||||
otIp6SetReceiveCallback(mInstance, &NcpBase::HandleDatagramFromStack, this);
|
||||
otIp6SetReceiveFilterEnabled(mInstance, true);
|
||||
otLinkSetPcapCallback(mInstance, &NcpBase::HandleRawFrame, static_cast<void *>(this));
|
||||
otIcmp6SetEchoEnabled(mInstance, false);
|
||||
otIcmp6SetEchoMode(mInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
#if OPENTHREAD_FTD
|
||||
otThreadSetChildTableCallback(mInstance, &NcpBase::HandleChildTableChanged);
|
||||
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
|
||||
|
||||
@@ -481,6 +481,8 @@ protected:
|
||||
NCP_GET_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
|
||||
NCP_INSERT_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
|
||||
NCP_REMOVE_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
|
||||
NCP_GET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD_MODE);
|
||||
NCP_SET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD_MODE);
|
||||
|
||||
NCP_GET_PROP_HANDLER(THREAD_LEADER);
|
||||
NCP_GET_PROP_HANDLER(THREAD_RLOC16_DEBUG_PASSTHRU);
|
||||
|
||||
@@ -1136,7 +1136,7 @@ otError NcpBase::GetPropertyHandler_IPV6_ROUTE_TABLE(void)
|
||||
|
||||
otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
|
||||
{
|
||||
return mEncoder.WriteBool(otIcmp6IsEchoEnabled(mInstance));
|
||||
return mEncoder.WriteBool(otIcmp6GetEchoMode(mInstance) != OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
|
||||
@@ -1146,7 +1146,7 @@ otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(void)
|
||||
|
||||
SuccessOrExit(error = mDecoder.ReadBool(enabled));
|
||||
|
||||
otIcmp6SetEchoEnabled(mInstance, enabled);
|
||||
otIcmp6SetEchoMode(mInstance, enabled ? OT_ICMP6_ECHO_HANDLER_ALL : OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -1206,6 +1206,59 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD_MODE(void)
|
||||
{
|
||||
spinel_ipv6_icmp_ping_offload_mode_t mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
|
||||
|
||||
switch (otIcmp6GetEchoMode(mInstance))
|
||||
{
|
||||
case OT_ICMP6_ECHO_HANDLER_DISABLED:
|
||||
mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED;
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY:
|
||||
mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY;
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY:
|
||||
mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY;
|
||||
break;
|
||||
case OT_ICMP6_ECHO_HANDLER_ALL:
|
||||
mode = SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL;
|
||||
break;
|
||||
};
|
||||
|
||||
return mEncoder.WriteUint8(mode);
|
||||
}
|
||||
|
||||
otError NcpBase::SetPropertyHandler_IPV6_ICMP_PING_OFFLOAD_MODE(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otIcmp6EchoMode mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
|
||||
uint8_t spinelMode;
|
||||
|
||||
SuccessOrExit(error = mDecoder.ReadUint8(spinelMode));
|
||||
|
||||
switch (spinelMode)
|
||||
{
|
||||
case SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED:
|
||||
mode = OT_ICMP6_ECHO_HANDLER_DISABLED;
|
||||
break;
|
||||
case SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY:
|
||||
mode = OT_ICMP6_ECHO_HANDLER_UNICAST_ONLY;
|
||||
break;
|
||||
case SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY:
|
||||
mode = OT_ICMP6_ECHO_HANDLER_MULTICAST_ONLY;
|
||||
break;
|
||||
case SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL:
|
||||
mode = OT_ICMP6_ECHO_HANDLER_ALL;
|
||||
break;
|
||||
};
|
||||
|
||||
otIcmp6SetEchoMode(mInstance, mode);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError NcpBase::GetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(void)
|
||||
{
|
||||
// Note reverse logic: passthru enabled = filter disabled
|
||||
|
||||
@@ -1569,6 +1569,10 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PROP_IPV6_MULTICAST_ADDRESS_TABLE";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE:
|
||||
ret = "PROP_IPV6_ICMP_PING_OFFLOAD_MODE";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_STREAM_DEBUG:
|
||||
ret = "PROP_STREAM_DEBUG";
|
||||
break;
|
||||
|
||||
@@ -200,6 +200,14 @@ typedef enum
|
||||
SPINEL_NET_ROLE_LEADER = 3,
|
||||
} spinel_net_role_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPINEL_IPV6_ICMP_PING_OFFLOAD_DISABLED = 0,
|
||||
SPINEL_IPV6_ICMP_PING_OFFLOAD_UNICAST_ONLY = 1,
|
||||
SPINEL_IPV6_ICMP_PING_OFFLOAD_MULTICAST_ONLY = 2,
|
||||
SPINEL_IPV6_ICMP_PING_OFFLOAD_ALL = 3,
|
||||
} spinel_ipv6_icmp_ping_offload_mode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPINEL_SCAN_STATE_IDLE = 0,
|
||||
@@ -1412,6 +1420,20 @@ typedef enum
|
||||
SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE
|
||||
= SPINEL_PROP_IPV6__BEGIN + 6, ///< [A(t(6))]
|
||||
|
||||
/// IPv6 ICMP Ping Offload
|
||||
/** Format: `C`
|
||||
*
|
||||
* Allow the NCP to directly respond to ICMP ping requests. If this is
|
||||
* turned on, ping request ICMP packets will not be passed to the host.
|
||||
*
|
||||
* This property allows enabling responses sent to unicast only, multicast
|
||||
* only, or both.
|
||||
*
|
||||
* Default value is `NET_IPV6_ICMP_PING_OFFLOAD_DISABLED`.
|
||||
*/
|
||||
SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD_MODE
|
||||
= SPINEL_PROP_IPV6__BEGIN + 7, ///< [b]
|
||||
|
||||
SPINEL_PROP_IPV6__END = 0x70,
|
||||
|
||||
SPINEL_PROP_STREAM__BEGIN = 0x70,
|
||||
|
||||
Reference in New Issue
Block a user