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 : }
|