]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-address-label.c
Merge pull request #10407 from yuwata/netlink-slot
[thirdparty/systemd.git] / src / network / networkd-address-label.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
95b74ef6
SS
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
14int address_label_new(AddressLabel **ret) {
8e766630 15 _cleanup_(address_label_freep) AddressLabel *addrlabel = NULL;
95b74ef6
SS
16
17 addrlabel = new0(AddressLabel, 1);
18 if (!addrlabel)
19 return -ENOMEM;
20
1cc6c93a 21 *ret = TAKE_PTR(addrlabel);
95b74ef6
SS
22
23 return 0;
24}
25
26void 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
44static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
8e766630
LP
45 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
46 _cleanup_(address_label_freep) AddressLabel *label = NULL;
95b74ef6
SS
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) {
1cc6c93a 59 *ret = TAKE_PTR(label);
95b74ef6
SS
60
61 return 0;
62 }
63
64 r = address_label_new(&label);
65 if (r < 0)
66 return r;
67
1cc6c93a 68 label->section = TAKE_PTR(n);
95b74ef6
SS
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
1cc6c93a 78 *ret = TAKE_PTR(label);
95b74ef6
SS
79
80 return 0;
81}
82
83int 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,
f7bf1abe 99 link->ifindex, AF_INET6);
95b74ef6
SS
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
ee38400b 115 r = sd_netlink_call_async(link->manager->rtnl, NULL, req, callback,
8190a388 116 link_netlink_destroy_callback, link, 0, __func__);
95b74ef6
SS
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
125int 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
8e766630 136 _cleanup_(address_label_freep) AddressLabel *n = NULL;
95b74ef6 137 Network *network = userdata;
f7bf1abe 138 int r;
95b74ef6
SS
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
f7bf1abe 150 r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen);
95b74ef6 151 if (r < 0) {
f7bf1abe 152 log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue);
95b74ef6
SS
153 return 0;
154 }
155
95b74ef6
SS
156 n = NULL;
157
158 return 0;
159}
160
161int 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
8e766630 173 _cleanup_(address_label_freep) AddressLabel *n = NULL;
95b74ef6
SS
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) {
3fe91079 195 log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring: %s", rvalue);
95b74ef6
SS
196 return 0;
197 }
198
199 n->label = k;
200 n = NULL;
201
202 return 0;
203}