Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <net/if.h>
4 : : #include <linux/if_addrlabel.h>
5 : :
6 : : #include "alloc-util.h"
7 : : #include "conf-parser.h"
8 : : #include "networkd-address-label.h"
9 : : #include "netlink-util.h"
10 : : #include "networkd-manager.h"
11 : : #include "parse-util.h"
12 : : #include "socket-util.h"
13 : :
14 : 0 : void address_label_free(AddressLabel *label) {
15 [ # # ]: 0 : if (!label)
16 : 0 : return;
17 : :
18 [ # # ]: 0 : if (label->network) {
19 [ # # # # : 0 : LIST_REMOVE(labels, label->network->address_labels, label);
# # # # ]
20 [ # # ]: 0 : assert(label->network->n_address_labels > 0);
21 : 0 : label->network->n_address_labels--;
22 : :
23 [ # # ]: 0 : if (label->section) {
24 : 0 : hashmap_remove(label->network->address_labels_by_section, label->section);
25 : 0 : network_config_section_free(label->section);
26 : : }
27 : : }
28 : :
29 : 0 : free(label);
30 : : }
31 : :
32 : 0 : static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
33 : 0 : _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
34 : 0 : _cleanup_(address_label_freep) AddressLabel *label = NULL;
35 : : int r;
36 : :
37 [ # # ]: 0 : assert(network);
38 [ # # ]: 0 : assert(ret);
39 [ # # ]: 0 : assert(!!filename == (section_line > 0));
40 : :
41 [ # # ]: 0 : if (filename) {
42 : 0 : r = network_config_section_new(filename, section_line, &n);
43 [ # # ]: 0 : if (r < 0)
44 : 0 : return r;
45 : :
46 : 0 : label = hashmap_get(network->address_labels_by_section, n);
47 [ # # ]: 0 : if (label) {
48 : 0 : *ret = TAKE_PTR(label);
49 : :
50 : 0 : return 0;
51 : : }
52 : : }
53 : :
54 : 0 : label = new(AddressLabel, 1);
55 [ # # ]: 0 : if (!label)
56 : 0 : return -ENOMEM;
57 : :
58 : 0 : *label = (AddressLabel) {
59 : : .network = network,
60 : : };
61 : :
62 [ # # # # : 0 : LIST_APPEND(labels, network->address_labels, label);
# # # # #
# # # ]
63 : 0 : network->n_address_labels++;
64 : :
65 [ # # ]: 0 : if (filename) {
66 : 0 : label->section = TAKE_PTR(n);
67 : :
68 : 0 : r = hashmap_ensure_allocated(&network->address_labels_by_section, &network_config_hash_ops);
69 [ # # ]: 0 : if (r < 0)
70 : 0 : return r;
71 : :
72 : 0 : r = hashmap_put(network->address_labels_by_section, label->section, label);
73 [ # # ]: 0 : if (r < 0)
74 : 0 : return r;
75 : : }
76 : :
77 : 0 : *ret = TAKE_PTR(label);
78 : :
79 : 0 : return 0;
80 : : }
81 : :
82 : 0 : static int address_label_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
83 : : int r;
84 : :
85 [ # # ]: 0 : assert(rtnl);
86 [ # # ]: 0 : assert(m);
87 [ # # ]: 0 : assert(link);
88 [ # # ]: 0 : assert(link->ifname);
89 [ # # ]: 0 : assert(link->address_label_messages > 0);
90 : :
91 : 0 : link->address_label_messages--;
92 : :
93 [ # # # # ]: 0 : if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
94 : 0 : return 1;
95 : :
96 : 0 : r = sd_netlink_message_get_errno(m);
97 [ # # # # ]: 0 : if (r < 0 && r != -EEXIST) {
98 [ # # # # ]: 0 : log_link_warning_errno(link, r, "could not set address label: %m");
99 : 0 : link_enter_failed(link);
100 : 0 : return 1;
101 [ # # ]: 0 : } else if (r >= 0)
102 : 0 : (void) manager_rtnl_process_address(rtnl, m, link->manager);
103 : :
104 [ # # ]: 0 : if (link->address_label_messages == 0)
105 [ # # # # ]: 0 : log_link_debug(link, "Addresses label set");
106 : :
107 : 0 : return 1;
108 : : }
109 : :
110 : 0 : int address_label_configure(
111 : : AddressLabel *label,
112 : : Link *link,
113 : : link_netlink_message_handler_t callback,
114 : : bool update) {
115 : :
116 : 0 : _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
117 : : int r;
118 : :
119 [ # # ]: 0 : assert(label);
120 [ # # ]: 0 : assert(link);
121 [ # # ]: 0 : assert(link->ifindex > 0);
122 [ # # ]: 0 : assert(link->manager);
123 [ # # ]: 0 : assert(link->manager->rtnl);
124 : :
125 : 0 : r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL,
126 : : link->ifindex, AF_INET6);
127 [ # # ]: 0 : if (r < 0)
128 [ # # ]: 0 : return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
129 : :
130 : 0 : r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen);
131 [ # # ]: 0 : if (r < 0)
132 [ # # ]: 0 : return log_error_errno(r, "Could not set prefixlen: %m");
133 : :
134 : 0 : r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label);
135 [ # # ]: 0 : if (r < 0)
136 [ # # ]: 0 : return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m");
137 : :
138 : 0 : r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6);
139 [ # # ]: 0 : if (r < 0)
140 [ # # ]: 0 : return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
141 : :
142 [ # # ]: 0 : r = netlink_call_async(link->manager->rtnl, NULL, req,
143 : : callback ?: address_label_handler,
144 : : link_netlink_destroy_callback, link);
145 [ # # ]: 0 : if (r < 0)
146 [ # # ]: 0 : return log_error_errno(r, "Could not send rtnetlink message: %m");
147 : :
148 : 0 : link_ref(link);
149 : :
150 : 0 : return 0;
151 : : }
152 : :
153 : 0 : int config_parse_address_label_prefix(const char *unit,
154 : : const char *filename,
155 : : unsigned line,
156 : : const char *section,
157 : : unsigned section_line,
158 : : const char *lvalue,
159 : : int ltype,
160 : : const char *rvalue,
161 : : void *data,
162 : : void *userdata) {
163 : :
164 : 0 : _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL;
165 : 0 : Network *network = userdata;
166 : : int r;
167 : :
168 [ # # ]: 0 : assert(filename);
169 [ # # ]: 0 : assert(section);
170 [ # # ]: 0 : assert(lvalue);
171 [ # # ]: 0 : assert(rvalue);
172 [ # # ]: 0 : assert(data);
173 : :
174 : 0 : r = address_label_new_static(network, filename, section_line, &n);
175 [ # # ]: 0 : if (r < 0)
176 : 0 : return r;
177 : :
178 : 0 : r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen);
179 [ # # ]: 0 : if (r < 0) {
180 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue);
181 : 0 : return 0;
182 : : }
183 : :
184 : 0 : n = NULL;
185 : :
186 : 0 : return 0;
187 : : }
188 : :
189 : 0 : int config_parse_address_label(
190 : : const char *unit,
191 : : const char *filename,
192 : : unsigned line,
193 : : const char *section,
194 : : unsigned section_line,
195 : : const char *lvalue,
196 : : int ltype,
197 : : const char *rvalue,
198 : : void *data,
199 : : void *userdata) {
200 : :
201 : 0 : _cleanup_(address_label_free_or_set_invalidp) AddressLabel *n = NULL;
202 : 0 : Network *network = userdata;
203 : : uint32_t k;
204 : : int r;
205 : :
206 [ # # ]: 0 : assert(filename);
207 [ # # ]: 0 : assert(section);
208 [ # # ]: 0 : assert(lvalue);
209 [ # # ]: 0 : assert(rvalue);
210 [ # # ]: 0 : assert(data);
211 : :
212 : 0 : r = address_label_new_static(network, filename, section_line, &n);
213 [ # # ]: 0 : if (r < 0)
214 : 0 : return r;
215 : :
216 : 0 : r = safe_atou32(rvalue, &k);
217 [ # # ]: 0 : if (r < 0) {
218 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue);
219 : 0 : return 0;
220 : : }
221 : :
222 [ # # ]: 0 : if (k == 0xffffffffUL) {
223 [ # # ]: 0 : log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring: %s", rvalue);
224 : 0 : return 0;
225 : : }
226 : :
227 : 0 : n->label = k;
228 : 0 : n = NULL;
229 : :
230 : 0 : return 0;
231 : : }
|