Skip to content

Commit cda9454

Browse files
authored
Merge pull request #85 from microsoft/apdiscoveryagentlinux
Implement access point discovery operations for Linux using netlink
2 parents d44ddb1 + 12b8c72 commit cda9454

File tree

24 files changed

+1269
-10
lines changed

24 files changed

+1269
-10
lines changed

.docker/netremote-dev/Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ LABEL org.label-schema.schema-version = "1.0"
2222
# sudo apt-get update
2323
#
2424
# 2. Install core build tools and dependencies:
25-
# sudo apt-get install -y --no-install-recommends build-essential ca-certificates cmake curl dotnet7 git gnupg linux-libc-dev ninja-build pkg-config tar unzip zip libnl-3-dev libssl-dev libnl-genl-3-dev libdbus-c++-dev libnl-route-3-dev
25+
# sudo apt-get install -y --no-install-recommends build-essential ca-certificates cmake curl dotnet7 git gnupg linux-libc-dev ninja-build pkg-config tar unzip zip libnl-3-200-dbg libnl-3-dev libssl-dev libnl-genl-3-dev libdbus-c++-dev libnl-route-3-dev
2626
#
2727
# 3. Remove llvm 16 toolchain packages to avoid conflicts with llvm 17 toolchain.
2828
# sudo apt-get remove -y --purge clang-16* lldb-16* llvm-16*
@@ -57,7 +57,8 @@ RUN apt-get update && \
5757
unzip \
5858
zip \
5959
# hostapd build dependencies.
60-
# libnl-3-dev libssl-dev libnl-genl-3-dev
60+
# libnl-3-200-dbg libnl-3-dev libssl-dev libnl-genl-3-dev
61+
libnl-3-200-dbg \
6162
libnl-3-dev \
6263
libnl-genl-3-dev \
6364
libssl-dev \

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ include(GNUInstallDirs)
5555
include(grpc)
5656
include(protoc)
5757

58-
# Enable verbose output until project is bootstrapped.
59-
set(CMAKE_VERBOSE_MAKEFILE ON)
58+
# Enable to debug CMake issues.
59+
set(CMAKE_VERBOSE_MAKEFILE OFF CACHE BOOL "Verbose Makefile Generation")
6060

6161
# Pull in external dependencies.
6262
# Look for protobuf-config.cmake.

CMakePresets.json

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"cacheVariables": {
4646
"CMAKE_CXX_COMPILER": "/usr/bin/clang++-17",
4747
"CMAKE_C_COMPILER": "/usr/bin/clang-17",
48-
"CMAKE_GENERATOR": "Ninja"
48+
"CMAKE_GENERATOR": "Ninja Multi-Config"
4949
}
5050
},
5151
{
@@ -106,10 +106,7 @@
106106
"os-linux",
107107
"linux-base",
108108
"release-base"
109-
],
110-
"cacheVariables": {
111-
"CMAKE_GENERATOR": "Ninja Multi-Config"
112-
}
109+
]
113110
},
114111
{
115112
"name": "release-windows",
@@ -123,7 +120,8 @@
123120
"buildPresets": [
124121
{
125122
"name": "dev-linux",
126-
"configurePreset": "dev-linux"
123+
"configurePreset": "dev-linux",
124+
"configuration": "Debug"
127125
},
128126
{
129127
"name": "dev-windows",

src/common/shared/notstd/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ target_sources(notstd
1212
FILES
1313
${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Exceptions.hxx
1414
${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Memory.hxx
15+
${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Scope.hxx
1516
${NOTSTD_PUBLIC_INCLUDE_PREFIX}/Utility.hxx
1617
)
1718

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#ifndef NOT_STD_SCOPE_HXX
2+
#define NOT_STD_SCOPE_HXX
3+
4+
#include <type_traits>
5+
#include <utility>
6+
7+
namespace notstd
8+
{
9+
namespace details
10+
{
11+
/**
12+
* @brief Executes a given lambda when destroyed.
13+
*
14+
* @tparam TLambda
15+
*/
16+
template <typename TLambda>
17+
class lambda_call
18+
{
19+
public:
20+
lambda_call(const lambda_call&) = delete;
21+
lambda_call&
22+
operator=(const lambda_call&) = delete;
23+
lambda_call&
24+
operator=(lambda_call&& other) = delete;
25+
26+
/**
27+
* @brief Construct a new lambda call object.
28+
*
29+
* @param lambda
30+
*/
31+
explicit lambda_call(TLambda&& lambda) noexcept :
32+
m_lambda(std::move(lambda))
33+
{
34+
static_assert(std::is_same<decltype(lambda()), void>::value, "scope_exit lambdas must not have a return value");
35+
static_assert(!std::is_lvalue_reference<TLambda>::value && !std::is_rvalue_reference<TLambda>::value,
36+
"scope_exit should only be directly used with a lambda");
37+
}
38+
39+
/**
40+
* @brief Construct a new lambda call object.
41+
*
42+
* @param other
43+
*/
44+
lambda_call(lambda_call&& other) noexcept :
45+
m_lambda(std::move(other.m_lambda)),
46+
m_call(other.m_call)
47+
{
48+
other.m_call = false;
49+
}
50+
51+
/**
52+
* @brief Destroy the lambda call object.
53+
*/
54+
~lambda_call() noexcept
55+
{
56+
reset();
57+
}
58+
59+
/**
60+
* @brief Ensures the scope_exit lambda will not be called.
61+
*/
62+
void
63+
release() noexcept
64+
{
65+
m_call = false;
66+
}
67+
68+
/**
69+
* @brief Executes the scope_exit lambda immediately if not yet run; ensures
70+
* it will not run again.
71+
*/
72+
void
73+
reset() noexcept
74+
{
75+
if (m_call) {
76+
m_call = false;
77+
m_lambda();
78+
}
79+
}
80+
81+
/**
82+
* @brief Returns true if the scope_exit lambda is still going to be
83+
* executed.
84+
*
85+
* @return true
86+
* @return false
87+
*/
88+
explicit operator bool() const noexcept
89+
{
90+
return m_call;
91+
}
92+
93+
private:
94+
TLambda m_lambda;
95+
bool m_call = true;
96+
};
97+
} // namespace details
98+
99+
/**
100+
* @brief Returns an object that executes the given lambda when destroyed.
101+
*
102+
* @tparam TLambda
103+
* @param lambda
104+
* @return auto
105+
*/
106+
template <typename TLambda>
107+
[[nodiscard]] inline auto
108+
scope_exit(TLambda&& lambda) noexcept
109+
{
110+
return details::lambda_call<TLambda>(std::forward<TLambda>(lambda));
111+
}
112+
113+
/**
114+
* @brief Name alias for scope_exit.
115+
*
116+
* @tparam TLambda
117+
* @param lambda
118+
* @return auto
119+
*/
120+
template <typename TLambda>
121+
[[nodiscard]] inline auto
122+
ScopeExit(TLambda&& lambda) noexcept
123+
{
124+
return scope_exit(std::forward<TLambda>(lambda));
125+
}
126+
127+
} // namespace notstd
128+
129+
#endif // NOT_STD_SCOPE_HXX

src/linux/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
add_subdirectory(external)
3+
add_subdirectory(libnl-helpers)
34
add_subdirectory(server)
5+
add_subdirectory(tools)
46
add_subdirectory(wifi)
57
add_subdirectory(wpa-controller)

src/linux/external/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11

22
add_subdirectory(hostap)
3+
add_subdirectory(libnl)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
# Requires that libnl development package is installed (libnl-3-dev on ubuntu).
3+
find_path(LIBNL_INCLUDE_DIR netlink/netlink.h
4+
PATHS
5+
/usr/include/libnl3
6+
/usr/local/include/libnl3
7+
REQUIRED
8+
)
9+
10+
# libnl core
11+
find_library(LIBNL_STATIC NAMES libnl-3.a REQUIRED)
12+
add_library(nl STATIC IMPORTED GLOBAL)
13+
set_target_properties(nl PROPERTIES IMPORTED_LOCATION ${LIBNL_STATIC})
14+
set_target_properties(nl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR})
15+
target_include_directories(nl INTERFACE ${LIBNL_INCLUDE_DIR})
16+
17+
# libnl-genl
18+
find_library(LIBNL_GENL_STATIC NAMES libnl-genl-3.a REQUIRED)
19+
add_library(nl-genl STATIC IMPORTED GLOBAL)
20+
set_target_properties(nl-genl PROPERTIES IMPORTED_LOCATION ${LIBNL_GENL_STATIC})
21+
set_target_properties(nl-genl PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR})
22+
target_include_directories(nl-genl INTERFACE ${LIBNL_INCLUDE_DIR})
23+
24+
# libnl-route
25+
find_library(LIBNL_ROUTE_STATIC NAMES libnl-route-3.a REQUIRED)
26+
add_library(nl-route STATIC IMPORTED GLOBAL)
27+
set_target_properties(nl-route PROPERTIES IMPORTED_LOCATION ${LIBNL_ROUTE_STATIC})
28+
set_target_properties(nl-route PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${LIBNL_INCLUDE_DIR})
29+
target_include_directories(nl-route INTERFACE ${LIBNL_INCLUDE_DIR})
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
add_library(libnl-helpers STATIC "")
3+
4+
set(LIBNL_HELPERS_PUBLIC_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/include)
5+
set(LIBNL_HELPERS_PUBLIC_INCLUDE_SUFFIX microsoft/net/netlink)
6+
set(LIBNL_HELPERS_PUBLIC_INCLUDE_PREFIX ${LIBNL_HELPERS_PUBLIC_INCLUDE}/${LIBNL_HELPERS_PUBLIC_INCLUDE_SUFFIX})
7+
8+
target_sources(libnl-helpers
9+
PRIVATE
10+
NetlinkSocket.cxx
11+
NetlinkMessage.cxx
12+
PUBLIC
13+
FILE_SET HEADERS
14+
BASE_DIRS ${LIBNL_HELPERS_PUBLIC_INCLUDE}
15+
FILES
16+
${LIBNL_HELPERS_PUBLIC_INCLUDE_PREFIX}/NetlinkMessage.hxx
17+
${LIBNL_HELPERS_PUBLIC_INCLUDE_PREFIX}/NetlinkSocket.hxx
18+
)
19+
20+
target_link_libraries(libnl-helpers
21+
PUBLIC
22+
nl
23+
)
24+
25+
install(
26+
TARGETS libnl-helpers
27+
EXPORT ${PROJECT_NAME}
28+
FILE_SET HEADERS
29+
PUBLIC_HEADER DESTINATION "${NETREMOTE_DIR_INSTALL_PUBLIC_HEADER_BASE}/${LIBNL_HELPERS_PUBLIC_INCLUDE_SUFFIX}"
30+
)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
2+
#include <microsoft/net/netlink/NetlinkMessage.hxx>
3+
4+
using namespace Microsoft::Net::Netlink;
5+
6+
NetlinkMessage::NetlinkMessage(struct nl_msg* message) :
7+
Message(message)
8+
{
9+
}
10+
11+
NetlinkMessage::NetlinkMessage(NetlinkMessage&& other) :
12+
Message(other.Message)
13+
{
14+
other.Message = nullptr;
15+
}
16+
17+
NetlinkMessage&
18+
NetlinkMessage::operator=(NetlinkMessage&& other)
19+
{
20+
if (this != &other) {
21+
Reset();
22+
Message = other.Message;
23+
other.Message = nullptr;
24+
}
25+
26+
return *this;
27+
}
28+
29+
NetlinkMessage::~NetlinkMessage()
30+
{
31+
Reset();
32+
}
33+
34+
void
35+
NetlinkMessage::Reset()
36+
{
37+
if (Message != nullptr) {
38+
nlmsg_free(Message);
39+
Message = nullptr;
40+
}
41+
}
42+
43+
struct nl_msg*
44+
NetlinkMessage::Release() noexcept
45+
{
46+
auto message = Message;
47+
Message = nullptr;
48+
return message;
49+
}
50+
51+
NetlinkMessage::operator struct nl_msg *() const noexcept
52+
{
53+
return Message;
54+
}
55+
56+
struct nlmsghdr*
57+
NetlinkMessage::Header() const noexcept
58+
{
59+
return nlmsg_hdr(Message);
60+
}

0 commit comments

Comments
 (0)