Skip to content

Commit

Permalink
[posix] set addr gen mode to none on linux (#2419)
Browse files Browse the repository at this point in the history
  • Loading branch information
Irving-cl authored Aug 13, 2024
1 parent d89373f commit f93a3b8
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 2 deletions.
11 changes: 11 additions & 0 deletions src/ncp/posix/netif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ namespace otbr {
Netif::Netif(void)
: mTunFd(-1)
, mIpFd(-1)
, mNetlinkFd(-1)
, mNetlinkSequence(0)
, mNetifIndex(0)
{
}
Expand All @@ -63,10 +65,13 @@ otbrError Netif::Init(const std::string &aInterfaceName)
VerifyOrExit(mIpFd >= 0, error = OTBR_ERROR_ERRNO);

SuccessOrExit(error = CreateTunDevice(aInterfaceName));
SuccessOrExit(error = InitNetlink());

mNetifIndex = if_nametoindex(mNetifName.c_str());
VerifyOrExit(mNetifIndex > 0, error = OTBR_ERROR_INVALID_STATE);

PlatformSpecificInit();

exit:
if (error != OTBR_ERROR_NONE)
{
Expand Down Expand Up @@ -94,6 +99,12 @@ void Netif::Clear(void)
mIpFd = -1;
}

if (mNetlinkFd != -1)
{
close(mNetlinkFd);
mNetlinkFd = -1;
}

mNetifIndex = 0;
}

Expand Down
10 changes: 8 additions & 2 deletions src/ncp/posix/netif.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,15 @@ class Netif
void Clear(void);

otbrError CreateTunDevice(const std::string &aInterfaceName);
otbrError InitNetlink(void);

int mTunFd; ///< Used to exchange IPv6 packets.
int mIpFd; ///< Used to manage IPv6 stack on the network interface.
void PlatformSpecificInit(void);
void SetAddrGenModeToNone(void);

int mTunFd; ///< Used to exchange IPv6 packets.
int mIpFd; ///< Used to manage IPv6 stack on the network interface.
int mNetlinkFd; ///< Used to receive netlink events.
uint32_t mNetlinkSequence; ///< Netlink message sequence.

unsigned int mNetifIndex;
std::string mNetifName;
Expand Down
107 changes: 107 additions & 0 deletions src/ncp/posix/netif_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,34 @@
#include "common/code_utils.hpp"
#include "common/logging.hpp"
#include "common/types.hpp"
#include "utils/socket_utils.hpp"

#ifndef OTBR_POSIX_TUN_DEVICE
#define OTBR_POSIX_TUN_DEVICE "/dev/net/tun"
#endif

namespace otbr {

static struct rtattr *AddRtAttr(nlmsghdr *aHeader, uint32_t aMaxLen, uint8_t aType, const void *aData, uint8_t aLen)
{
uint8_t len = RTA_LENGTH(aLen);
rtattr *rta;

assert(NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len) <= aMaxLen);
OTBR_UNUSED_VARIABLE(aMaxLen);

rta = reinterpret_cast<rtattr *>(reinterpret_cast<char *>(aHeader) + NLMSG_ALIGN((aHeader)->nlmsg_len));
rta->rta_type = aType;
rta->rta_len = len;
if (aLen)
{
memcpy(RTA_DATA(rta), aData, aLen);
}
aHeader->nlmsg_len = NLMSG_ALIGN(aHeader->nlmsg_len) + RTA_ALIGN(len);

return rta;
}

otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
{
ifreq ifr;
Expand Down Expand Up @@ -88,6 +109,92 @@ otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
return error;
}

otbrError Netif::InitNetlink(void)
{
otbrError error = OTBR_ERROR_NONE;

mNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketNonBlock);
VerifyOrExit(mNetlinkFd >= 0, error = OTBR_ERROR_ERRNO);

#if defined(SOL_NETLINK)
{
int enable = 1;

#if defined(NETLINK_EXT_ACK)
if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_EXT_ACK, &enable, sizeof(enable)) != 0)
{
otbrLogWarning("Failed to enable NETLINK_EXT_ACK: %s", strerror(errno));
}
#endif
#if defined(NETLINK_CAP_ACK)
if (setsockopt(mNetlinkFd, SOL_NETLINK, NETLINK_CAP_ACK, &enable, sizeof(enable)) != 0)
{
otbrLogWarning("Failed to enable NETLINK_CAP_ACK: %s", strerror(errno));
}
#endif
}
#endif

{
sockaddr_nl sa;

memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
VerifyOrExit(bind(mNetlinkFd, reinterpret_cast<sockaddr *>(&sa), sizeof(sa)) == 0, error = OTBR_ERROR_ERRNO);
}

exit:
return error;
}

void Netif::PlatformSpecificInit(void)
{
SetAddrGenModeToNone();
}

void Netif::SetAddrGenModeToNone(void)
{
struct
{
nlmsghdr nh;
ifinfomsg ifi;
char buf[512];
} req;

const uint8_t mode = IN6_ADDR_GEN_MODE_NONE;

memset(&req, 0, sizeof(req));

req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req.nh.nlmsg_type = RTM_NEWLINK;
req.nh.nlmsg_pid = 0;
req.nh.nlmsg_seq = ++mNetlinkSequence;

req.ifi.ifi_index = static_cast<int>(mNetifIndex);
req.ifi.ifi_change = 0xffffffff;
req.ifi.ifi_flags = IFF_MULTICAST | IFF_NOARP;

{
rtattr *afSpec = AddRtAttr(&req.nh, sizeof(req), IFLA_AF_SPEC, 0, 0);
rtattr *afInet6 = AddRtAttr(&req.nh, sizeof(req), AF_INET6, 0, 0);
rtattr *inet6AddrGenMode = AddRtAttr(&req.nh, sizeof(req), IFLA_INET6_ADDR_GEN_MODE, &mode, sizeof(mode));

afInet6->rta_len += inet6AddrGenMode->rta_len;
afSpec->rta_len += afInet6->rta_len;
}

if (send(mNetlinkFd, &req, req.nh.nlmsg_len, 0) != -1)
{
otbrLogInfo("Sent request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
}
else
{
otbrLogWarning("Failed to send request#%u to set addr_gen_mode to %d", mNetlinkSequence, mode);
}
}

} // namespace otbr

#endif // __linux__
5 changes: 5 additions & 0 deletions src/ncp/posix/netif_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ otbrError Netif::CreateTunDevice(const std::string &aInterfaceName)
return OTBR_ERROR_NONE;
}

void Netif::PlatformSpecificInit(void)
{
/* Empty */
}

} // namespace otbr

#endif // __APPLE__ || __NetBSD__ || __OpenBSD__
22 changes: 22 additions & 0 deletions tests/gtest/test_netif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <gtest/gtest.h>

#include <cstring>
#include <fstream>
#include <ifaddrs.h>
#include <iostream>
#include <net/if.h>
Expand All @@ -43,6 +44,10 @@
#include <sys/types.h>
#include <vector>

#ifdef __linux__
#include <linux/if_link.h>
#endif

#include <openthread/ip6.h>

#include "common/types.hpp"
Expand Down Expand Up @@ -177,4 +182,21 @@ TEST(Netif, WpanDeinit)
EXPECT_LT(ioctl(sockfd, SIOCGIFFLAGS, &ifr), 0) << "'" << wpan << "' isn't shutdown";
}

TEST(Netif, WpanAddrGenMode)
{
otbr::Netif netif;
EXPECT_EQ(netif.Init("wpan0"), OT_ERROR_NONE);

std::fstream file("/proc/sys/net/ipv6/conf/wpan0/addr_gen_mode", std::ios::in);
if (!file.is_open())
{
FAIL() << "wpan0 interface doesn't exist!";
}
std::string fileContents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());

EXPECT_EQ(std::stoi(fileContents), IN6_ADDR_GEN_MODE_NONE);

netif.Deinit();
}

#endif // __linux__

0 comments on commit f93a3b8

Please sign in to comment.