Skip to content

Commit

Permalink
[cli] update br scan to allow network interface selection for mDNS …
Browse files Browse the repository at this point in the history
…binding (#260)

Within the OTBR practice application, the BR host will have several
interfaces. When users want to discover the border router using mDNS,
they will need to choose the specific interface.

This change introduces a new option for the CLI command `br
scan`. User can now specify a network interface using the syntax `br
scan --netif <network interface>`. The chosen interface will be used
for mDNS binding through socket options.
  • Loading branch information
ZhangLe2016 authored Apr 22, 2024
1 parent 744d599 commit 4543bd1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/app/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ Each advanced command always sends associative `MGMT_*_(GET|SET).req` requests.
```shell
> help br
usage:
br scan [--nwk <network-alias-list> | --dom <domain-name>] [--export <json-file-path>] [--timeout <ms>]
br scan [--nwk <network-alias-list> | --dom <domain-name>] [--export <json-file-path>] [--timeout <ms>] [--netif <network-interface>]
br add <json-file-path>
br list [--nwk <network-alias-list> | --dom <domain-name>]
br delete (<br-record-id> | --nwk <network-alias-list> | --dom <domain-name>)
Expand Down
38 changes: 32 additions & 6 deletions src/app/cli/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <vector>

#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

Expand Down Expand Up @@ -111,6 +112,8 @@
#define WARN_NETWORK_SELECTION_DROPPED "Network selection was dropped by the command"
#define WARN_NETWORK_SELECTION_CHANGED "Network selection was changed by the command"

#define SO_BINDTODEVICE 25

#define COLOR_ALIAS_FAILED Console::Color::kYellow

namespace ot {
Expand Down Expand Up @@ -213,7 +216,8 @@ const std::map<std::string, std::string> &Interpreter::mUsageMap = *new std::map
{"br", "br list [--nwk <network-alias-list> | --dom <domain-name>]\n"
"br add <json-file-path>\n"
"br delete (<br-record-id> | --nwk <network-alias-list> | --dom <domain-name>)\n"
"br scan [--nwk <network-alias-list> | --dom <domain-name>] [--export <json-file-path>] [--timeout <ms>]\n"},
"br scan [--nwk <network-alias-list> | --dom <domain-name>] [--export <json-file-path>] [--timeout <ms>] "
"[--netif <network-interface>]\n"},
{"domain", "domain list [--dom <domain-name>]"},
{"network", "network save <network-data-file>\n"
"network sync\n"
Expand Down Expand Up @@ -1421,6 +1425,7 @@ Interpreter::Value Interpreter::ProcessBr(const Expression &aExpr)
const std::string kServiceName = "_meshcop._udp.local";

uint32_t scanTimeout = 10000;
std::string netIf = "";
int mdnsSocket = -1;
FDGuard fdgMdnsSocket;
std::thread selectThread;
Expand All @@ -1432,20 +1437,41 @@ Interpreter::Value Interpreter::ProcessBr(const Expression &aExpr)
nlohmann::json baJson;
char mdnsSendBuffer[kMdnsBufferSize];

if (mContext.mCommandKeys.size() == 2 && mContext.mCommandKeys[0] == "--timeout")
auto it = std::find(mContext.mCommandKeys.begin(), mContext.mCommandKeys.end(), "--timeout");
if (it != mContext.mCommandKeys.end())
{
try
if (++it != mContext.mCommandKeys.end())
{
scanTimeout = stol(mContext.mCommandKeys[1]);
} catch (...)
SuccessOrExit(value = ParseInteger(scanTimeout, it[0]));
}
else
{
ExitNow(value = ERROR_INVALID_ARGS("Imparsable timeout value '{}'", aExpr[3]));
ExitNow(value = ERROR_INVALID_ARGS("Missing --timeout value"));
}
}

it = std::find(mContext.mCommandKeys.begin(), mContext.mCommandKeys.end(), "--netif");
if (it != mContext.mCommandKeys.end())
{
if (++it != mContext.mCommandKeys.end())
{
netIf = it[0];
}
else
{
ExitNow(value = ERROR_INVALID_ARGS("Missing --netif value"));
}
}

// Open IPv4 mDNS socket
mdnsSocket = mdns_socket_open_ipv4();
VerifyOrExit(mdnsSocket >= 0, value = ERROR_IO_ERROR("failed to open mDNS IPv4 socket"));

if (!netIf.empty() && setsockopt(mdnsSocket, SOL_SOCKET, SO_BINDTODEVICE, netIf.c_str(), netIf.size()) < 0)
{
ExitNow(value = ERROR_INVALID_ARGS("failed to bind network interface {}: {}", netIf, strerror(errno)));
}

fdgMdnsSocket.mFD = mdnsSocket;

// Initialize event library
Expand Down

0 comments on commit 4543bd1

Please sign in to comment.