Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Silabs] MDNS and matter packet filter on WiFi Devices #34335

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/platform/silabs/ConnectivityManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <platform/internal/GenericConnectivityManagerImpl_NoThread.h>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
#include "EndpointQueueFilter.h"
#include <platform/internal/GenericConnectivityManagerImpl_WiFi.ipp>
#else
#include <platform/internal/GenericConnectivityManagerImpl_NoWiFi.h>
Expand Down Expand Up @@ -131,6 +132,9 @@ class ConnectivityManagerImpl final : public ConnectivityManager,
static void DriveStationState(::chip::System::Layer * aLayer, void * aAppState);

void UpdateInternetConnectivityState(void);
#if CHIP_CONFIG_ENABLE_ICD_SERVER
Inet::SilabsEndpointQueueFilter::EndpointQueueFilter mEndpointQueueFilter;
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER
#endif
};

Expand Down
27 changes: 27 additions & 0 deletions src/platform/silabs/ConnectivityManagerImpl_WIFI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#endif

#include "CHIPDevicePlatformConfig.h"
#include "EndpointQueueFilter.h"
#include <platform/silabs/wifi/WifiInterfaceAbstraction.h>

using namespace ::chip;
Expand Down Expand Up @@ -426,6 +427,32 @@ void ConnectivityManagerImpl::UpdateInternetConnectivityState(void)
event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn);
event.InternetConnectivityChange.ipAddress = addr;

#if CHIP_CONFIG_ENABLE_ICD_SERVER
{
sl_wfx_mac_address_t macaddr;
wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr);
char macaddrString[13]; // 12 characters + null terminator
sprintf(macaddrString, "%02X%02X%02X%02X%02X%02X", macaddr.octet[0], macaddr.octet[1], macaddr.octet[2],
macaddr.octet[3], macaddr.octet[4], macaddr.octet[5]);
EndpointQueueFilterConfig config;
config.allowedQueuedPackets = 20; // Set the desired value

mEndpointQueueFilter.SetConfig(config);

// Convert macaddrString to Span<const unsigned char>
Span<const unsigned char> macaddrSpan(reinterpret_cast<const unsigned char *>(macaddrString), sizeof(macaddrString));

if (mEndpointQueueFilter.SetHostName(macaddrSpan) == CHIP_NO_ERROR)
{
UDPEndPointImpl::SetQueueFilter(&mEndpointQueueFilter);
}
else
{
ChipLogError(DeviceLayer, "Failed to set host name filter");
}
}
#endif // CHIP_CONFIG_ENABLE_ICD_SERVER

if (haveIPv4Conn != hadIPv4Conn)
{
ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST");
Expand Down
121 changes: 121 additions & 0 deletions src/platform/silabs/EndpointQueueFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#include "EndpointQueueFilter.h"
#include <algorithm>
#include <cctype>
#include <lib/core/CHIPSafeCasts.h>
#include <string.h>
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>

using namespace ::chip;

namespace chip {
namespace Inet {

using FilterOutcome = EndpointQueueFilter::FilterOutcome;

namespace {

bool IsValidMdnsHostName(const Span<const unsigned char> & hostName)
{
for (size_t i = 0; i < hostName.size(); ++i)
{
char ch_data = *(hostName.data());
Comment on lines +20 to +22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason not to do:

Suggested change
for (size_t i = 0; i < hostName.size(); ++i)
{
char ch_data = *(hostName.data());
for (char ch_data : hostName)
{

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notice the span interation is not working, will have a check once

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment...

if (!((ch_data >= '0' && ch_data <= '9') || (ch_data >= 'A' && ch_data <= 'F') || (ch_data >= 'a' && ch_data <= 'f')))
{
return false;
}
}
return true;
}

bool IsMdnsBroadcastPacket(const IPPacketInfo & pktInfo, const System::PacketBufferHandle & pktPayload)
{
// if the packet is not a broadcast packet to mDNS port, drop it.
VerifyOrReturnValue(pktInfo.DestPort == 5353, false);
#if INET_CONFIG_ENABLE_IPV4
ip_addr_t mdnsIPv4BroadcastAddr = IPADDR4_INIT_BYTES(224, 0, 0, 251);
if (pktInfo.DestAddress == Inet::IPAddress(mdnsIPv4BroadcastAddr))
{
return true;
}
#endif
ip_addr_t mdnsIPv6BroadcastAddr = IPADDR6_INIT_HOST(0xFF020000, 0, 0, 0xFB);
if (pktInfo.DestAddress == Inet::IPAddress(mdnsIPv6BroadcastAddr))
{
return true;
}
return false;
}

bool PayloadContainsCaseInsensitive(const System::PacketBufferHandle & payload, const Span<const unsigned char> & pattern)
{
if (payload->TotalLength() == 0 || pattern.size() == 0)
{
return false;
}

if (payload->HasChainedBuffer() || payload->TotalLength() < pattern.size())
{
return false;
}

Span<const unsigned char> payloadView(payload->Start(), payload->TotalLength());

auto toLower = [](unsigned char c) { return std::tolower(c); };

auto it = std::search(payloadView.begin(), payloadView.end(), pattern.begin(), pattern.end(),
[&](unsigned char a, unsigned char b) { return toLower(a) == toLower(b); });

return (it != payloadView.end());
}

} // namespace

FilterOutcome HostNameFilter::Filter(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload)
{
// Drop the mDNS packets which don't contain 'matter' or '<device-hostname>'.
const unsigned char matterBytes[] = { 'm', 'a', 't', 't', 'e', 'r' };
if (PayloadContainsCaseInsensitive(pktPayload, Span<const unsigned char>(matterBytes)) ||
PayloadContainsCaseInsensitive(pktPayload, Span<const unsigned char>(mHostName)))
{
return FilterOutcome::kAllowPacket;
}
return FilterOutcome::kDropPacket;
}

CHIP_ERROR HostNameFilter::SetHostName(Span<const unsigned char> & hostName)
{
VerifyOrReturnError(IsValidMdnsHostName(hostName), CHIP_ERROR_INVALID_ARGUMENT);
memcpy(mHostName, hostName.data(), hostName.size());
return CHIP_NO_ERROR;
}

namespace SilabsEndpointQueueFilter {

EndpointQueueFilter::EndpointQueueFilter() : mTooManyFilter(mConfig.allowedQueuedPackets) {}

EndpointQueueFilter::EndpointQueueFilter(size_t maxAllowedQueuedPackets) : mTooManyFilter(maxAllowedQueuedPackets) {}

FilterOutcome EndpointQueueFilter::FilterBeforeEnqueue(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload)
{
VerifyOrReturnError(FilterOutcome::kAllowPacket == mTooManyFilter.FilterBeforeEnqueue(endpoint, pktInfo, pktPayload),
FilterOutcome::kDropPacket);

if (!IsMdnsBroadcastPacket(pktInfo, pktPayload))
{
return FilterOutcome::kAllowPacket;
}
return mHostNameFilter.Filter(endpoint, pktInfo, pktPayload);
}

FilterOutcome EndpointQueueFilter::FilterAfterDequeue(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload)
{
return mTooManyFilter.FilterAfterDequeue(endpoint, pktInfo, pktPayload);
}

} // namespace SilabsEndpointQueueFilter
} // namespace Inet
} // namespace chip
78 changes: 78 additions & 0 deletions src/platform/silabs/EndpointQueueFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <inet/BasicPacketFilters.h>

namespace chip {
namespace Inet {

struct EndpointFilter
{
virtual ~EndpointFilter() = default;
virtual EndpointQueueFilter::FilterOutcome Filter(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload) = 0;
};

struct EndpointQueueFilterConfig
{
size_t allowedQueuedPackets = 10; // Default value
};

struct HostNameFilter : EndpointFilter
{
static constexpr size_t kHostNameLengthMax = 13; // 6 bytes in hex and null terminator.

EndpointQueueFilter::FilterOutcome Filter(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload) override;

CHIP_ERROR SetHostName(Span<const unsigned char> & name);

private:
uint8_t mHostName[kHostNameLengthMax] = { 0 };
static constexpr size_t kMdnsPort = 5353;
};

namespace SilabsEndpointQueueFilter {

class EndpointQueueFilter : public Inet::EndpointQueueFilter
{
public:
EndpointQueueFilterConfig mConfig;
EndpointQueueFilter();
EndpointQueueFilter(size_t maxAllowedQueuedPackets);

FilterOutcome FilterBeforeEnqueue(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload) override;

FilterOutcome FilterAfterDequeue(const void * endpoint, const IPPacketInfo & pktInfo,
const System::PacketBufferHandle & pktPayload);

CHIP_ERROR SetHostName(Span<const unsigned char> & addr) { return mHostNameFilter.SetHostName(addr); }

// Method to set the configuration
void SetConfig(const EndpointQueueFilterConfig & config) { mConfig = config; }

private:
DropIfTooManyQueuedPacketsFilter mTooManyFilter;
HostNameFilter mHostNameFilter;
};

} // namespace SilabsEndpointQueueFilter
} // namespace Inet
} // namespace chip
2 changes: 2 additions & 0 deletions src/platform/silabs/SiWx917/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ static_library("SiWx917") {
"${silabs_platform_dir}/ConnectivityManagerImpl_WIFI.cpp",
"${silabs_platform_dir}/DiagnosticDataProviderImpl.cpp",
"${silabs_platform_dir}/DiagnosticDataProviderImpl.h",
"${silabs_platform_dir}/EndpointQueueFilter.cpp",
"${silabs_platform_dir}/EndpointQueueFilter.h",
"${silabs_platform_dir}/InetPlatformConfig.h",
"${silabs_platform_dir}/KeyValueStoreManagerImpl.cpp",
"${silabs_platform_dir}/KeyValueStoreManagerImpl.h",
Expand Down
2 changes: 2 additions & 0 deletions src/platform/silabs/efr32/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ static_library("efr32") {
if (chip_enable_wifi) {
sources += [
"${silabs_platform_dir}/ConnectivityManagerImpl_WIFI.cpp",
"${silabs_platform_dir}/EndpointQueueFilter.cpp",
"${silabs_platform_dir}/EndpointQueueFilter.h",
"${silabs_platform_dir}/NetworkCommissioningWiFiDriver.cpp",
"${silabs_platform_dir}/NetworkCommissioningWiFiDriver.h",
]
Expand Down
Loading