1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <net/if.h>
4 #include <net/if_arp.h>
5 
6 #include "sd-lldp-tx.h"
7 
8 #include "networkd-link.h"
9 #include "networkd-lldp-tx.h"
10 #include "networkd-manager.h"
11 #include "parse-util.h"
12 #include "string-table.h"
13 #include "string-util.h"
14 #include "strv.h"
15 
link_lldp_tx_enabled(Link * link)16 static bool link_lldp_tx_enabled(Link *link) {
17         assert(link);
18 
19         if (link->flags & IFF_LOOPBACK)
20                 return false;
21 
22         if (link->iftype != ARPHRD_ETHER)
23                 return false;
24 
25         if (!link->network)
26                 return false;
27 
28         if (link->kind && STR_IN_SET(link->kind, "bridge", "bond"))
29                 return false;
30 
31         return link->network->lldp_multicast_mode >= 0 &&
32                 link->network->lldp_multicast_mode < _SD_LLDP_MULTICAST_MODE_MAX;
33 }
34 
link_lldp_tx_configure(Link * link)35 int link_lldp_tx_configure(Link *link) {
36         int r;
37 
38         assert(link);
39 
40         if (!link_lldp_tx_enabled(link))
41                 return 0;
42 
43         if (link->lldp_tx)
44                 return -EBUSY;
45 
46         r = sd_lldp_tx_new(&link->lldp_tx);
47         if (r < 0)
48                 return r;
49 
50         r = sd_lldp_tx_attach_event(link->lldp_tx, link->manager->event, 0);
51         if (r < 0)
52                 return r;
53 
54         r = sd_lldp_tx_set_ifindex(link->lldp_tx, link->ifindex);
55         if (r < 0)
56                 return r;
57 
58         r = sd_lldp_tx_set_hwaddr(link->lldp_tx, &link->hw_addr.ether);
59         if (r < 0)
60                 return r;
61 
62         assert(link->network);
63 
64         r = sd_lldp_tx_set_multicast_mode(link->lldp_tx, link->network->lldp_multicast_mode);
65         if (r < 0)
66                 return r;
67 
68         r = sd_lldp_tx_set_capabilities(link->lldp_tx,
69                                         SD_LLDP_SYSTEM_CAPABILITIES_STATION |
70                                         SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE |
71                                         SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
72                                         (link->network->ip_forward != ADDRESS_FAMILY_NO) ?
73                                         SD_LLDP_SYSTEM_CAPABILITIES_ROUTER :
74                                         SD_LLDP_SYSTEM_CAPABILITIES_STATION);
75         if (r < 0)
76                 return r;
77 
78         r = sd_lldp_tx_set_port_description(link->lldp_tx, link->network->description);
79         if (r < 0)
80                 return r;
81 
82         r = sd_lldp_tx_set_mud_url(link->lldp_tx, link->network->lldp_mudurl);
83         if (r < 0)
84                 return r;
85 
86         return 0;
87 }
88 
89 static const char * const lldp_multicast_mode_table[_SD_LLDP_MULTICAST_MODE_MAX] = {
90         [SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE]  = "nearest-bridge",
91         [SD_LLDP_MULTICAST_MODE_NON_TPMR_BRIDGE] = "non-tpmr-bridge",
92         [SD_LLDP_MULTICAST_MODE_CUSTOMER_BRIDGE] = "customer-bridge",
93 };
94 
95 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(lldp_multicast_mode, sd_lldp_multicast_mode_t);
96 
config_parse_lldp_multicast_mode(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)97 int config_parse_lldp_multicast_mode(
98                 const char *unit,
99                 const char *filename,
100                 unsigned line,
101                 const char *section,
102                 unsigned section_line,
103                 const char *lvalue,
104                 int ltype,
105                 const char *rvalue,
106                 void *data,
107                 void *userdata) {
108 
109         sd_lldp_multicast_mode_t m, *mode = data;
110         int r;
111 
112         assert(filename);
113         assert(section);
114         assert(lvalue);
115         assert(rvalue);
116         assert(mode);
117 
118         if (isempty(rvalue)) {
119                 *mode = _SD_LLDP_MULTICAST_MODE_INVALID;
120                 return 0;
121         }
122 
123         r = parse_boolean(rvalue);
124         if (r >= 0) {
125                 *mode = r == 0 ? _SD_LLDP_MULTICAST_MODE_INVALID : SD_LLDP_MULTICAST_MODE_NEAREST_BRIDGE;
126                 return 0;
127         }
128 
129         m = lldp_multicast_mode_from_string(rvalue);
130         if (m < 0) {
131                 log_syntax(unit, LOG_WARNING, filename, line, m,
132                            "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
133                 return 0;
134         }
135 
136         *mode = m;
137         return 0;
138 }
139