diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 26a5dbbd1e1..066793c6e64 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -171,7 +171,10 @@
WireGuard Secure Network Tunnel.
netdevsim
- A simulator. This simulated networking device is used for testing various networking APIs and at this time is particularly focused on testing hardware offloading related interfaces.
+ A simulator. This simulated networking device is used for testing various networking APIs and at this time is particularly focused on testing hardware offloading related interfaces.
+
+ nlmon
+ A Netlink monitor device. Use an nlmon device when you want to monitor system Netlink messages.
fou
Foo-over-UDP tunneling.
diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c
index 7fd3efbd357..35ca843569d 100644
--- a/src/libsystemd/sd-netlink/netlink-types.c
+++ b/src/libsystemd/sd-netlink/netlink-types.c
@@ -357,6 +357,7 @@ static const char* const nl_union_link_info_data_table[] = {
[NL_UNION_LINK_INFO_DATA_NETDEVSIM] = "netdevsim",
[NL_UNION_LINK_INFO_DATA_CAN] = "can",
[NL_UNION_LINK_INFO_DATA_MACSEC] = "macsec",
+ [NL_UNION_LINK_INFO_DATA_NLMON] = "nlmon",
};
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
diff --git a/src/libsystemd/sd-netlink/netlink-types.h b/src/libsystemd/sd-netlink/netlink-types.h
index 8585280463a..fed43ae43c0 100644
--- a/src/libsystemd/sd-netlink/netlink-types.h
+++ b/src/libsystemd/sd-netlink/netlink-types.h
@@ -82,6 +82,7 @@ typedef enum NLUnionLinkInfoData {
NL_UNION_LINK_INFO_DATA_NETDEVSIM,
NL_UNION_LINK_INFO_DATA_CAN,
NL_UNION_LINK_INFO_DATA_MACSEC,
+ NL_UNION_LINK_INFO_DATA_NLMON,
_NL_UNION_LINK_INFO_DATA_MAX,
_NL_UNION_LINK_INFO_DATA_INVALID = -1
} NLUnionLinkInfoData;
diff --git a/src/network/meson.build b/src/network/meson.build
index 0bcf7f4a815..feeb98cb074 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -13,6 +13,8 @@ sources = files('''
netdev/macvlan.h
netdev/netdev.c
netdev/netdev.h
+ netdev/nlmon.c
+ netdev/nlmon.h
netdev/tunnel.c
netdev/tunnel.h
netdev/tuntap.c
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 1c307a3125d..54292376035 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -19,6 +19,7 @@
#include "netdev/macvlan.h"
#include "netdev/netdev.h"
#include "netdev/netdevsim.h"
+#include "netdev/nlmon.h"
#include "netdev/tunnel.h"
#include "netdev/tuntap.h"
#include "netdev/vcan.h"
@@ -70,6 +71,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_ERSPAN] = &erspan_vtable,
[NETDEV_KIND_L2TP] = &l2tptnl_vtable,
[NETDEV_KIND_MACSEC] = &macsec_vtable,
+ [NETDEV_KIND_NLMON] = &nlmon_vtable,
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -104,6 +106,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_ERSPAN] = "erspan",
[NETDEV_KIND_L2TP] = "l2tp",
[NETDEV_KIND_MACSEC] = "macsec",
+ [NETDEV_KIND_NLMON] = "nlmon",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 8295ba1966d..57fabbef40d 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -49,6 +49,7 @@ typedef enum NetDevKind {
NETDEV_KIND_ERSPAN,
NETDEV_KIND_L2TP,
NETDEV_KIND_MACSEC,
+ NETDEV_KIND_NLMON,
_NETDEV_KIND_MAX,
_NETDEV_KIND_TUNNEL, /* Used by config_parse_stacked_netdev() */
_NETDEV_KIND_INVALID = -1
diff --git a/src/network/netdev/nlmon.c b/src/network/netdev/nlmon.c
new file mode 100644
index 00000000000..c58a6b51ca8
--- /dev/null
+++ b/src/network/netdev/nlmon.c
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "netdev/nlmon.h"
+
+static int netdev_nlmon_verify(NetDev *netdev, const char *filename) {
+ assert(netdev);
+ assert(filename);
+
+ if (netdev->mac) {
+ log_netdev_warning(netdev, "%s: MACAddress= is not supported. Ignoring", filename);
+ netdev->mac = mfree(netdev->mac);
+ }
+
+ return 0;
+}
+
+const NetDevVTable nlmon_vtable = {
+ .object_size = sizeof(NLMon),
+ .sections = "Match\0NetDev\0",
+ .create_type = NETDEV_CREATE_INDEPENDENT,
+ .config_verify = netdev_nlmon_verify,
+};
diff --git a/src/network/netdev/nlmon.h b/src/network/netdev/nlmon.h
new file mode 100644
index 00000000000..590b62d8631
--- /dev/null
+++ b/src/network/netdev/nlmon.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+typedef struct NLMon NLMon;
+
+#include "netdev/netdev.h"
+
+struct NLMon {
+ NetDev meta;
+};
+
+DEFINE_NETDEV_CAST(NLMON, NLMon);
+
+extern const NetDevVTable nlmon_vtable;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 924cc8ce6af..9486329b9a9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -132,7 +132,7 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
if (!link->network)
return false;
- if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan"))
+ if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6", "can", "vcan", "vxcan", "nlmon"))
return false;
/* L3 or L3S mode do not support ARP. */
@@ -142,6 +142,9 @@ bool link_ipv4ll_enabled(Link *link, AddressFamilyBoolean mask) {
if (link->network->bond)
return false;
+ if (link->network->bond)
+ return false;
+
return link->network->link_local & mask;
}
@@ -157,7 +160,7 @@ static bool link_ipv6ll_enabled(Link *link) {
if (!link->network)
return false;
- if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan"))
+ if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti", "can", "vcan", "vxcan", "nlmon"))
return false;
if (link->network->bond)