1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 #include <net/if_arp.h>
9 #include "networkd-link.h"
10 #include "networkd-lldp-rx.h"
11 #include "networkd-lldp-tx.h"
12 #include "networkd-manager.h"
13 #include "networkd-network.h"
14 #include "string-table.h"
15 #include "string-util.h"
17 #include "tmpfile-util.h"
19 DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode
, lldp_mode
, LLDPMode
, "Failed to parse LLDP= setting.");
21 static const char* const lldp_mode_table
[_LLDP_MODE_MAX
] = {
22 [LLDP_MODE_NO
] = "no",
23 [LLDP_MODE_YES
] = "yes",
24 [LLDP_MODE_ROUTERS_ONLY
] = "routers-only",
27 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode
, LLDPMode
, LLDP_MODE_YES
);
29 static bool link_lldp_rx_enabled(Link
*link
) {
32 if (link
->flags
& IFF_LOOPBACK
)
35 if (link
->iftype
!= ARPHRD_ETHER
)
41 /* LLDP should be handled on bridge and bond slaves as those have a direct connection to their peers,
42 * not on the bridge/bond master. Linux doesn't even (by default) forward lldp packets to the bridge
44 if (link
->kind
&& STR_IN_SET(link
->kind
, "bridge", "bond"))
47 return link
->network
->lldp_mode
!= LLDP_MODE_NO
;
50 static void lldp_handler(sd_lldp
*lldp
, sd_lldp_event event
, sd_lldp_neighbor
*n
, void *userdata
) {
51 Link
*link
= userdata
;
56 (void) link_lldp_save(link
);
58 if (link_lldp_emit_enabled(link
) && event
== SD_LLDP_EVENT_ADDED
) {
59 /* If we received information about a new neighbor, restart the LLDP "fast" logic */
61 log_link_debug(link
, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
63 r
= link_lldp_emit_start(link
);
65 log_link_warning_errno(link
, r
, "Failed to restart LLDP transmission: %m");
69 int link_lldp_rx_configure(Link
*link
) {
72 if (!link_lldp_rx_enabled(link
))
76 r
= sd_lldp_new(&link
->lldp
);
80 r
= sd_lldp_attach_event(link
->lldp
, link
->manager
->event
, 0);
85 r
= sd_lldp_set_ifindex(link
->lldp
, link
->ifindex
);
89 r
= sd_lldp_match_capabilities(link
->lldp
,
90 link
->network
->lldp_mode
== LLDP_MODE_ROUTERS_ONLY
?
91 SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS
:
92 SD_LLDP_SYSTEM_CAPABILITIES_ALL
);
96 r
= sd_lldp_set_filter_address(link
->lldp
, &link
->hw_addr
.addr
.ether
);
100 r
= sd_lldp_set_callback(link
->lldp
, lldp_handler
, link
);
104 r
= link_update_lldp(link
);
111 int link_update_lldp(Link
*link
) {
119 if (link
->flags
& IFF_UP
) {
120 r
= sd_lldp_start(link
->lldp
);
122 return log_link_warning_errno(link
, r
, "Failed to start LLDP: %m");
124 log_link_debug(link
, "Started LLDP.");
126 r
= sd_lldp_stop(link
->lldp
);
128 return log_link_warning_errno(link
, r
, "Failed to stop LLDP: %m");
130 log_link_debug(link
, "Stopped LLDP.");
136 int link_lldp_save(Link
*link
) {
137 _cleanup_free_
char *temp_path
= NULL
;
138 _cleanup_fclose_
FILE *f
= NULL
;
139 sd_lldp_neighbor
**l
= NULL
;
143 assert(link
->lldp_file
);
146 (void) unlink(link
->lldp_file
);
150 r
= sd_lldp_get_neighbors(link
->lldp
, &l
);
154 (void) unlink(link
->lldp_file
);
160 r
= fopen_temporary(link
->lldp_file
, &f
, &temp_path
);
164 fchmod(fileno(f
), 0644);
166 for (i
= 0; i
< n
; i
++) {
171 r
= sd_lldp_neighbor_get_raw(l
[i
], &p
, &sz
);
176 (void) fwrite(&u
, 1, sizeof(u
), f
);
177 (void) fwrite(p
, 1, sz
, f
);
180 r
= fflush_and_check(f
);
184 if (rename(temp_path
, link
->lldp_file
) < 0) {
191 (void) unlink(link
->lldp_file
);
193 (void) unlink(temp_path
);
195 log_link_error_errno(link
, r
, "Failed to save LLDP data to %s: %m", link
->lldp_file
);
199 for (i
= 0; i
< n
; i
++)
200 sd_lldp_neighbor_unref(l
[i
]);