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