]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-lldp-rx.c
network/lldp: do not save LLDP neighbors under /run/systemd
[thirdparty/systemd.git] / src / network / networkd-lldp-rx.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if.h>
4 #include <net/if_arp.h>
5 #include <unistd.h>
6
7 #include "fd-util.h"
8 #include "fileio.h"
9 #include "fs-util.h"
10 #include "networkd-link.h"
11 #include "networkd-lldp-rx.h"
12 #include "networkd-lldp-tx.h"
13 #include "networkd-manager.h"
14 #include "networkd-network.h"
15 #include "string-table.h"
16 #include "string-util.h"
17 #include "strv.h"
18 #include "tmpfile-util.h"
19
20 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
21
22 static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
23 [LLDP_MODE_NO] = "no",
24 [LLDP_MODE_YES] = "yes",
25 [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
26 };
27
28 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
29
30 static bool link_lldp_rx_enabled(Link *link) {
31 assert(link);
32
33 if (link->flags & IFF_LOOPBACK)
34 return false;
35
36 if (link->iftype != ARPHRD_ETHER)
37 return false;
38
39 if (!link->network)
40 return false;
41
42 /* LLDP should be handled on bridge and bond slaves as those have a direct connection to their peers,
43 * not on the bridge/bond master. Linux doesn't even (by default) forward lldp packets to the bridge
44 * master. */
45 if (link->kind && STR_IN_SET(link->kind, "bridge", "bond"))
46 return false;
47
48 return link->network->lldp_mode != LLDP_MODE_NO;
49 }
50
51 static void lldp_rx_handler(sd_lldp_rx *lldp_rx, sd_lldp_rx_event_t event, sd_lldp_neighbor *n, void *userdata) {
52 Link *link = ASSERT_PTR(userdata);
53 int r;
54
55 if (link->lldp_tx && event == SD_LLDP_RX_EVENT_ADDED) {
56 /* If we received information about a new neighbor, restart the LLDP "fast" logic */
57
58 log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
59
60 (void) sd_lldp_tx_stop(link->lldp_tx);
61 r = sd_lldp_tx_start(link->lldp_tx);
62 if (r < 0)
63 log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
64 }
65 }
66
67 int link_lldp_rx_configure(Link *link) {
68 int r;
69
70 if (!link_lldp_rx_enabled(link))
71 return 0;
72
73 if (link->lldp_rx)
74 return -EBUSY;
75
76 r = sd_lldp_rx_new(&link->lldp_rx);
77 if (r < 0)
78 return r;
79
80 r = sd_lldp_rx_attach_event(link->lldp_rx, link->manager->event, 0);
81 if (r < 0)
82 return r;
83
84 r = sd_lldp_rx_set_ifindex(link->lldp_rx, link->ifindex);
85 if (r < 0)
86 return r;
87
88 r = sd_lldp_rx_match_capabilities(link->lldp_rx,
89 link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
90 SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
91 SD_LLDP_SYSTEM_CAPABILITIES_ALL);
92 if (r < 0)
93 return r;
94
95 r = sd_lldp_rx_set_filter_address(link->lldp_rx, &link->hw_addr.ether);
96 if (r < 0)
97 return r;
98
99 r = sd_lldp_rx_set_callback(link->lldp_rx, lldp_rx_handler, link);
100 if (r < 0)
101 return r;
102
103 return 0;
104 }