From 3d33a42935a1cf8415ca388ac00e3796978599f7 Mon Sep 17 00:00:00 2001 From: ZhangLe2016 <156590889+ZhangLe2016@users.noreply.github.com> Date: Tue, 30 Apr 2024 00:15:38 +0800 Subject: [PATCH] [cli] update `borderagent discover` to allow network interface selection for mDNS binding (#259) Within the OTBR practice application, the BR host will have several interfaces. When users want to discover the border agent using mDNS, they'll need to choose the specific interface the border agent is bound to. This change introduces a new option for the CLI command `borderagent dicover`. Users can now specify a network interface using the syntax `borderagent discover `. The chosen interface will be used for mDNS binding through socket options. --- src/app/border_agent_functions_mock.cpp | 4 ++-- src/app/border_agent_functions_mock.hpp | 2 +- src/app/br_discover.cpp | 19 ++++++++++++++++++- src/app/br_discover.hpp | 4 +++- src/app/cli/README.md | 2 +- src/app/cli/interpreter.cpp | 10 ++++++++-- src/app/cli/interpreter_test.cpp | 2 +- 7 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/app/border_agent_functions_mock.cpp b/src/app/border_agent_functions_mock.cpp index 30c217c70..8aaa9a136 100644 --- a/src/app/border_agent_functions_mock.cpp +++ b/src/app/border_agent_functions_mock.cpp @@ -43,9 +43,9 @@ void ClearBorderAgentFunctionsMock() gBorderAgentFunctionsMock = nullptr; } -Error DiscoverBorderAgent(BorderAgentHandler aBorderAgentHandler, size_t aTimeout) +Error DiscoverBorderAgent(BorderAgentHandler aBorderAgentHandler, size_t aTimeout, const std::string &aNetIf) { - return gBorderAgentFunctionsMock->DiscoverBorderAgent(aBorderAgentHandler, aTimeout); + return gBorderAgentFunctionsMock->DiscoverBorderAgent(aBorderAgentHandler, aTimeout, aNetIf); } } // namespace commissioner diff --git a/src/app/border_agent_functions_mock.hpp b/src/app/border_agent_functions_mock.hpp index 6d4880124..e775af79b 100644 --- a/src/app/border_agent_functions_mock.hpp +++ b/src/app/border_agent_functions_mock.hpp @@ -45,7 +45,7 @@ class BorderAgentFunctionsMock public: virtual ~BorderAgentFunctionsMock() = default; - MOCK_METHOD(Error, DiscoverBorderAgent, (BorderAgentHandler, size_t)); + MOCK_METHOD(Error, DiscoverBorderAgent, (BorderAgentHandler, size_t, const std::string &)); }; void SetBorderAgentFunctionsMock(ot::commissioner::BorderAgentFunctionsMock *ptr); diff --git a/src/app/br_discover.cpp b/src/app/br_discover.cpp index f0928756a..0d6128d78 100644 --- a/src/app/br_discover.cpp +++ b/src/app/br_discover.cpp @@ -29,6 +29,11 @@ #include "br_discover.hpp" #include +#ifdef __linux__ +#include +#else // __NetBSD__ || __FreeBSD__ || __APPLE__ +#include +#endif #include #include "common/error_macros.hpp" @@ -38,7 +43,7 @@ namespace ot { namespace commissioner { -Error DiscoverBorderAgent(BorderAgentHandler aBorderAgentHandler, size_t aTimeout) +Error DiscoverBorderAgent(BorderAgentHandler aBorderAgentHandler, size_t aTimeout, const std::string &aNetIf) { static constexpr size_t kDefaultBufferSize = 1024 * 16; static constexpr mdns_record_type_t kMdnsQueryType = MDNS_RECORDTYPE_PTR; @@ -46,12 +51,24 @@ Error DiscoverBorderAgent(BorderAgentHandler aBorderAgentHandler, size_t aTimeou Error error; uint8_t buf[kDefaultBufferSize]; + int rval = 0; auto begin = std::chrono::system_clock::now(); int socket = mdns_socket_open_ipv4(); VerifyOrExit(socket >= 0, error = ERROR_IO_ERROR("failed to open mDNS IPv4 socket")); + if (!aNetIf.empty()) + { +#ifdef __linux__ + rval = setsockopt(socket, SOL_SOCKET, SO_BINDTODEVICE, aNetIf.c_str(), aNetIf.size()); +#else // __NetBSD__ || __FreeBSD__ || __APPLE__ + rval = setsockopt(socket, IPPROTO_IPV6, IP_BOUND_IF, aNetIf.c_str(), aNetIf.size()); +#endif // __linux__ + VerifyOrExit(rval == 0, + error = ERROR_INVALID_ARGS("failed to bind network interface {}: {}", aNetIf, strerror(errno))); + } + if (mdns_query_send(socket, kMdnsQueryType, kServiceName, strlen(kServiceName), buf, sizeof(buf)) != 0) { ExitNow(error = ERROR_IO_ERROR("failed to send mDNS query")); diff --git a/src/app/br_discover.hpp b/src/app/br_discover.hpp index 91273b95f..7304d0eee 100644 --- a/src/app/br_discover.hpp +++ b/src/app/br_discover.hpp @@ -56,9 +56,11 @@ using BorderAgentHandler = std::function help borderagent usage: -borderagent discover [] +borderagent discover [] [] borderagent get locator [done] > diff --git a/src/app/cli/interpreter.cpp b/src/app/cli/interpreter.cpp index e38b1071c..41efc825b 100644 --- a/src/app/cli/interpreter.cpp +++ b/src/app/cli/interpreter.cpp @@ -1813,14 +1813,20 @@ Interpreter::Value Interpreter::ProcessBorderAgent(const Expression &aExpr) if (CaseInsensitiveEqual(aExpr[1], "discover")) { - uint64_t timeout = 4000; + uint64_t timeout = 4000; + std::string netIf = ""; if (aExpr.size() >= 3) { SuccessOrExit(value = ParseInteger(timeout, aExpr[2])); } - SuccessOrExit(value = DiscoverBorderAgent(BorderAgentHandler, static_cast(timeout))); + if (aExpr.size() == 4) + { + netIf = aExpr[3]; + } + + SuccessOrExit(value = DiscoverBorderAgent(BorderAgentHandler, static_cast(timeout), netIf)); } else if (CaseInsensitiveEqual(aExpr[1], "get")) { diff --git a/src/app/cli/interpreter_test.cpp b/src/app/cli/interpreter_test.cpp index 7cf36b602..4ebefba7b 100644 --- a/src/app/cli/interpreter_test.cpp +++ b/src/app/cli/interpreter_test.cpp @@ -1629,7 +1629,7 @@ TEST_F(InterpreterTestSuite, PC_BorderagentDiscover) BorderAgentFunctionsMock bafm; SetBorderAgentFunctionsMock(&bafm); - EXPECT_CALL(bafm, DiscoverBorderAgent(_, _)).WillOnce(Return(Error{})); + EXPECT_CALL(bafm, DiscoverBorderAgent(_, _, _)).WillOnce(Return(Error{})); Interpreter::Expression expr; Interpreter::Value value;