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