Skip to content

Commit 4593aef

Browse files
Stop advertising IPv4 addresses when IPv4 and IPv6 ports do not match. (#38057)
Our advertising backends only support advertising one port. In cases when the IPv4 and IPv6 ports do not match, advertising the IPv6 port along with IPv4 addresses does not make sense: that port does not correspond to the Matter stack on those addresses. The fix is to only allow advertising IPv4 addresses when the port we are using for IPv6 matches the port we are using for IPv4.
1 parent 79da246 commit 4593aef

File tree

6 files changed

+68
-30
lines changed

6 files changed

+68
-30
lines changed

src/app/server/Dnssd.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ CHIP_ERROR DnssdServer::AdvertiseOperational()
207207
.SetPort(GetSecuredPort())
208208
.SetInterfaceId(GetInterfaceId())
209209
.SetLocalMRPConfig(GetLocalMRPConfig().std_optional())
210-
.EnableIpV4(true);
210+
.EnableIpV4(SecuredIPv4PortMatchesIPv6Port());
211211

212212
#if CHIP_CONFIG_ENABLE_ICD_SERVER
213213
AddICDKeyToAdvertisement(advertiseParameters);
@@ -234,7 +234,7 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi
234234
auto advertiseParameters = chip::Dnssd::CommissionAdvertisingParameters()
235235
.SetPort(commissionableNode ? GetSecuredPort() : GetUnsecuredPort())
236236
.SetInterfaceId(GetInterfaceId())
237-
.EnableIpV4(true);
237+
.EnableIpV4(!commissionableNode || SecuredIPv4PortMatchesIPv6Port());
238238
advertiseParameters.SetCommissionAdvertiseMode(commissionableNode ? chip::Dnssd::CommssionAdvertiseMode::kCommissionableNode
239239
: chip::Dnssd::CommssionAdvertiseMode::kCommissioner);
240240

src/app/server/Dnssd.h

+25-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <app/icd/server/ICDStateObserver.h>
2525
#include <app/server/CommissioningModeProvider.h>
2626
#include <credentials/FabricTable.h>
27+
#include <inet/InetConfig.h>
2728
#include <lib/core/CHIPError.h>
2829
#include <lib/core/Optional.h>
2930
#include <lib/dnssd/Advertiser.h>
@@ -46,11 +47,16 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
4647
return instance;
4748
}
4849

49-
/// Sets the secure Matter port
50-
void SetSecuredPort(uint16_t port) { mSecuredPort = port; }
50+
/// Sets the secure Matter IPv6 port
51+
void SetSecuredIPv6Port(uint16_t port) { mSecuredIPv6Port = port; }
52+
53+
#if INET_CONFIG_ENABLE_IPV4
54+
/// Sets the secure Matter IPv4 port.
55+
void SetSecuredIPv4Port(uint16_t port) { mSecuredIPv4Port = port; }
56+
#endif // INET_CONFIG_ENABLE_IPV4
5157

5258
/// Gets the secure Matter port
53-
uint16_t GetSecuredPort() const { return mSecuredPort; }
59+
uint16_t GetSecuredPort() const { return mSecuredIPv6Port; }
5460

5561
/// Sets the unsecure Matter port
5662
void SetUnsecuredPort(uint16_t port) { mUnsecuredPort = port; }
@@ -176,6 +182,18 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
176182
//
177183
bool HaveOperationalCredentials();
178184

185+
// Check whether the secured IPv4 port matches the secured IPv6 port. If it
186+
// does not, we should not advertise our IPv4 bits, because we can only
187+
// advertise one port number.
188+
bool SecuredIPv4PortMatchesIPv6Port() const
189+
{
190+
#if INET_CONFIG_ENABLE_IPV4
191+
return mSecuredIPv4Port == mSecuredIPv6Port;
192+
#else
193+
return false;
194+
#endif // INET_CONFIG_ENABLE_IPV4
195+
}
196+
179197
FabricTable * mFabricTable = nullptr;
180198
CommissioningModeProvider * mCommissioningModeProvider = nullptr;
181199

@@ -187,7 +205,10 @@ class DLL_EXPORT DnssdServer : public ICDStateObserver
187205
bool mTCPServerEnabled = true;
188206
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
189207

190-
uint16_t mSecuredPort = CHIP_PORT;
208+
uint16_t mSecuredIPv6Port = CHIP_PORT;
209+
#if INET_CONFIG_ENABLE_IPV4
210+
uint16_t mSecuredIPv4Port = CHIP_PORT;
211+
#endif // INET_CONFIG_ENABLE_IPV4
191212
uint16_t mUnsecuredPort = CHIP_UDC_PORT;
192213
Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
193214

src/app/server/Server.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,17 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
216216
}
217217

218218
// Init transport before operations with secure session mgr.
219+
//
220+
// The logic below expects that the IPv6 transport is at index 0. Keep that logic in sync with
221+
// this code.
219222
err = mTransports.Init(UdpListenParameters(DeviceLayer::UDPEndPointManager())
220223
.SetAddressType(IPAddressType::kIPv6)
221224
.SetListenPort(mOperationalServicePort)
222225
.SetNativeParams(initParams.endpointNativeParams)
223226
#if INET_CONFIG_ENABLE_IPV4
224227
,
228+
// The logic below expects that the IPv4 transport, if enabled, is at
229+
// index 1. Keep that logic in sync with this code.
225230
UdpListenParameters(DeviceLayer::UDPEndPointManager())
226231
.SetAddressType(IPAddressType::kIPv4)
227232
.SetListenPort(mOperationalServicePort)
@@ -318,13 +323,10 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams)
318323
SuccessOrExit(err);
319324
#endif
320325

321-
//
322-
// We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
323-
// and IPv6 endpoint to pick from. Given that the listen port passed in may be set to 0 (which then has the kernel select
324-
// a valid port at bind time), that will result in two possible ports being provided back from the resultant endpoint
325-
// initializations. Since IPv6 is POR for Matter, let's go ahead and pick that port.
326-
//
327-
app::DnssdServer::Instance().SetSecuredPort(mTransports.GetTransport().GetImplAtIndex<0>().GetBoundPort());
326+
app::DnssdServer::Instance().SetSecuredIPv6Port(mTransports.GetTransport().GetImplAtIndex<0>().GetBoundPort());
327+
#if INET_CONFIG_ENABLE_IPV4
328+
app::DnssdServer::Instance().SetSecuredIPv4Port(mTransports.GetTransport().GetImplAtIndex<1>().GetBoundPort());
329+
#endif // INET_CONFIG_ENABLE_IPV4
328330

329331
app::DnssdServer::Instance().SetUnsecuredPort(mUserDirectedCommissioningPort);
330332
app::DnssdServer::Instance().SetInterfaceId(mInterfaceId);

src/controller/CHIPDeviceControllerFactory.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,18 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
169169
stateParams.transportMgr = chip::Platform::New<DeviceTransportMgr>();
170170

171171
//
172-
// The logic below expects IPv6 to be at index 0 of this tuple. Please do not alter that.
172+
// The logic below expects IPv6 to be at index 0 of this tuple. Keep that logic in sync with
173+
// this code.
173174
//
174175
ReturnErrorOnFailure(stateParams.transportMgr->Init(Transport::UdpListenParameters(stateParams.udpEndPointManager)
175176
.SetAddressType(Inet::IPAddressType::kIPv6)
176177
.SetListenPort(params.listenPort)
177178
#if INET_CONFIG_ENABLE_IPV4
178179
,
180+
//
181+
// The logic below expects IPv4 to be at index 1 of this tuple,
182+
// if it's enabled. Keep that logic in sync with this code.
183+
//
179184
Transport::UdpListenParameters(stateParams.udpEndPointManager)
180185
.SetAddressType(Inet::IPAddressType::kIPv4)
181186
.SetListenPort(params.listenPort)
@@ -272,13 +277,15 @@ CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params)
272277
stateParams.exchangeMgr, stateParams.sessionMgr, stateParams.fabricTable, sessionResumptionStorage,
273278
stateParams.certificateValidityPolicy, stateParams.groupDataProvider));
274279

275-
//
276-
// We need to advertise the port that we're listening to for unsolicited messages over UDP. However, we have both a IPv4
277-
// and IPv6 endpoint to pick from. Given that the listen port passed in may be set to 0 (which then has the kernel select
278-
// a valid port at bind time), that will result in two possible ports being provided back from the resultant endpoint
279-
// initializations. Since IPv6 is POR for Matter, let's go ahead and pick that port.
280-
//
281-
app::DnssdServer::Instance().SetSecuredPort(stateParams.transportMgr->GetTransport().GetImplAtIndex<0>().GetBoundPort());
280+
// Our IPv6 transport is at index 0.
281+
app::DnssdServer::Instance().SetSecuredIPv6Port(
282+
stateParams.transportMgr->GetTransport().GetImplAtIndex<0>().GetBoundPort());
283+
284+
#if INET_CONFIG_ENABLE_IPV4
285+
// If enabled, our IPv4 transport is at index 1.
286+
app::DnssdServer::Instance().SetSecuredIPv4Port(
287+
stateParams.transportMgr->GetTransport().GetImplAtIndex<1>().GetBoundPort());
288+
#endif // INET_CONFIG_ENABLE_IPV4
282289

283290
//
284291
// TODO: This is a hack to workaround the fact that we have a bi-polar stack that has controller and server modalities that

src/lib/dnssd/Discovery_ImplPlatform.cpp

+15-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include <app/icd/server/ICDServerConfig.h>
2424
#include <crypto/RandUtils.h>
25+
#include <inet/InetConfig.h>
2526
#include <lib/core/CHIPConfig.h>
2627
#include <lib/core/CHIPSafeCasts.h>
2728
#include <lib/dnssd/IPAddressSorter.h>
@@ -527,33 +528,39 @@ CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextE
527528
const OperationalAdvertisingParameters & params)
528529
{
529530
return PublishService(serviceType, textEntries, textEntrySize, subTypes, subTypeSize, params.GetPort(), params.GetInterfaceId(),
530-
params.GetMac(), DnssdServiceProtocol::kDnssdProtocolTcp, params.GetPeerId());
531+
params.GetMac(), DnssdServiceProtocol::kDnssdProtocolTcp, params.GetPeerId(), params.IsIPv4Enabled());
531532
}
532533

533534
CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize,
534535
const char ** subTypes, size_t subTypeSize,
535536
const CommissionAdvertisingParameters & params)
536537
{
537538
return PublishService(serviceType, textEntries, textEntrySize, subTypes, subTypeSize, params.GetPort(), params.GetInterfaceId(),
538-
params.GetMac(), DnssdServiceProtocol::kDnssdProtocolUdp, PeerId());
539+
params.GetMac(), DnssdServiceProtocol::kDnssdProtocolUdp, PeerId(), params.IsIPv4Enabled());
539540
}
540541

541542
CHIP_ERROR DiscoveryImplPlatform::PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize,
542543
const char ** subTypes, size_t subTypeSize, uint16_t port,
543544
Inet::InterfaceId interfaceId, const chip::ByteSpan & mac,
544-
DnssdServiceProtocol protocol, PeerId peerId)
545+
DnssdServiceProtocol protocol, PeerId peerId, bool ipv4Enabled)
545546
{
546547
DnssdService service;
547548
ReturnErrorOnFailure(MakeHostName(service.mHostName, sizeof(service.mHostName), mac));
548549
ReturnErrorOnFailure(protocol == DnssdServiceProtocol::kDnssdProtocolTcp
549550
? MakeInstanceName(service.mName, sizeof(service.mName), peerId)
550551
: GetCommissionableInstanceName(service.mName, sizeof(service.mName)));
551552
Platform::CopyString(service.mType, serviceType);
552-
#if INET_CONFIG_ENABLE_IPV4
553-
service.mAddressType = Inet::IPAddressType::kAny;
554-
#else
555-
service.mAddressType = Inet::IPAddressType::kIPv6;
556-
#endif
553+
#if !INET_CONFIG_ENABLE_IPV4
554+
ipv4Enabled = false;
555+
#endif // INET_CONFIG_ENABLE_IPV4
556+
if (ipv4Enabled)
557+
{
558+
service.mAddressType = Inet::IPAddressType::kAny;
559+
}
560+
else
561+
{
562+
service.mAddressType = Inet::IPAddressType::kIPv6;
563+
}
557564
service.mInterface = interfaceId;
558565
service.mProtocol = protocol;
559566
service.mPort = port;

src/lib/dnssd/Discovery_ImplPlatform.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
8585
size_t subTypeSize, const OperationalAdvertisingParameters & params);
8686
CHIP_ERROR PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize, const char ** subTypes,
8787
size_t subTypeSize, const CommissionAdvertisingParameters & params);
88+
// ipv4Enabled will be ignored if we don't actually support IPv4.
8889
CHIP_ERROR PublishService(const char * serviceType, TextEntry * textEntries, size_t textEntrySize, const char ** subTypes,
8990
size_t subTypeSize, uint16_t port, Inet::InterfaceId interfaceId, const chip::ByteSpan & mac,
90-
DnssdServiceProtocol procotol, PeerId peerId);
91+
DnssdServiceProtocol procotol, PeerId peerId, bool ipv4Enabled);
9192

9293
static void HandleNodeIdResolve(void * context, DnssdService * result, const Span<Inet::IPAddress> & addresses,
9394
CHIP_ERROR error);

0 commit comments

Comments
 (0)