]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-address-label.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[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 int address_label_configure(
83 AddressLabel *label,
84 Link *link,
85 sd_netlink_message_handler_t callback,
86 bool update) {
87
88 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
89 int r;
90
91 assert(label);
92 assert(link);
93 assert(link->ifindex > 0);
94 assert(link->manager);
95 assert(link->manager->rtnl);
96
97 r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL,
98 link->ifindex, AF_INET6);
99 if (r < 0)
100 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
101
102 r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen);
103 if (r < 0)
104 return log_error_errno(r, "Could not set prefixlen: %m");
105
106 r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label);
107 if (r < 0)
108 return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m");
109
110 r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6);
111 if (r < 0)
112 return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
113
114 r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback,
115 link_netlink_destroy_callback, link, 0, __func__);
116 if (r < 0)
117 return log_error_errno(r, "Could not send rtnetlink message: %m");
118
119 link_ref(link);
120
121 return 0;
122 }
123
124 int config_parse_address_label_prefix(const char *unit,
125 const char *filename,
126 unsigned line,
127 const char *section,
128 unsigned section_line,
129 const char *lvalue,
130 int ltype,
131 const char *rvalue,
132 void *data,
133 void *userdata) {
134
135 _cleanup_(address_label_freep) AddressLabel *n = NULL;
136 Network *network = userdata;
137 int r;
138
139 assert(filename);
140 assert(section);
141 assert(lvalue);
142 assert(rvalue);
143 assert(data);
144
145 r = address_label_new_static(network, filename, section_line, &n);
146 if (r < 0)
147 return r;
148
149 r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen);
150 if (r < 0) {
151 log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue);
152 return 0;
153 }
154
155 n = NULL;
156
157 return 0;
158 }
159
160 int config_parse_address_label(
161 const char *unit,
162 const char *filename,
163 unsigned line,
164 const char *section,
165 unsigned section_line,
166 const char *lvalue,
167 int ltype,
168 const char *rvalue,
169 void *data,
170 void *userdata) {
171
172 _cleanup_(address_label_freep) AddressLabel *n = NULL;
173 Network *network = userdata;
174 uint32_t k;
175 int r;
176
177 assert(filename);
178 assert(section);
179 assert(lvalue);
180 assert(rvalue);
181 assert(data);
182
183 r = address_label_new_static(network, filename, section_line, &n);
184 if (r < 0)
185 return r;
186
187 r = safe_atou32(rvalue, &k);
188 if (r < 0) {
189 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue);
190 return 0;
191 }
192
193 if (k == 0xffffffffUL) {
194 log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring: %s", rvalue);
195 return 0;
196 }
197
198 n->label = k;
199 n = NULL;
200
201 return 0;
202 }