]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-address-label.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / network / networkd-address-label.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2017 Susant Sahani
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <net/if.h>
22 #include <linux/if_addrlabel.h>
23
24 #include "alloc-util.h"
25 #include "conf-parser.h"
26 #include "networkd-address-label.h"
27 #include "netlink-util.h"
28 #include "networkd-manager.h"
29 #include "parse-util.h"
30 #include "socket-util.h"
31
32 int address_label_new(AddressLabel **ret) {
33 _cleanup_address_label_free_ AddressLabel *addrlabel = NULL;
34
35 addrlabel = new0(AddressLabel, 1);
36 if (!addrlabel)
37 return -ENOMEM;
38
39 *ret = addrlabel;
40 addrlabel = NULL;
41
42 return 0;
43 }
44
45 void address_label_free(AddressLabel *label) {
46 if (!label)
47 return;
48
49 if (label->network) {
50 LIST_REMOVE(labels, label->network->address_labels, label);
51 assert(label->network->n_address_labels > 0);
52 label->network->n_address_labels--;
53
54 if (label->section) {
55 hashmap_remove(label->network->address_labels_by_section, label->section);
56 network_config_section_free(label->section);
57 }
58 }
59
60 free(label);
61 }
62
63 static int address_label_new_static(Network *network, const char *filename, unsigned section_line, AddressLabel **ret) {
64 _cleanup_network_config_section_free_ NetworkConfigSection *n = NULL;
65 _cleanup_address_label_free_ AddressLabel *label = NULL;
66 int r;
67
68 assert(network);
69 assert(ret);
70 assert(!!filename == (section_line > 0));
71
72 r = network_config_section_new(filename, section_line, &n);
73 if (r < 0)
74 return r;
75
76 label = hashmap_get(network->address_labels_by_section, n);
77 if (label) {
78 *ret = label;
79 label = NULL;
80
81 return 0;
82 }
83
84 r = address_label_new(&label);
85 if (r < 0)
86 return r;
87
88 label->section = n;
89 n = NULL;
90
91 r = hashmap_put(network->address_labels_by_section, label->section, label);
92 if (r < 0)
93 return r;
94
95 label->network = network;
96 LIST_APPEND(labels, network->address_labels, label);
97 network->n_address_labels++;
98
99 *ret = label;
100 label = NULL;
101
102 return 0;
103 }
104
105 int address_label_configure(
106 AddressLabel *label,
107 Link *link,
108 sd_netlink_message_handler_t callback,
109 bool update) {
110
111 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
112 int r;
113
114 assert(label);
115 assert(link);
116 assert(link->ifindex > 0);
117 assert(link->manager);
118 assert(link->manager->rtnl);
119
120 r = sd_rtnl_message_new_addrlabel(link->manager->rtnl, &req, RTM_NEWADDRLABEL,
121 link->ifindex, AF_INET6);
122 if (r < 0)
123 return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m");
124
125 r = sd_rtnl_message_addrlabel_set_prefixlen(req, label->prefixlen);
126 if (r < 0)
127 return log_error_errno(r, "Could not set prefixlen: %m");
128
129 r = sd_netlink_message_append_u32(req, IFAL_LABEL, label->label);
130 if (r < 0)
131 return log_error_errno(r, "Could not append IFAL_LABEL attribute: %m");
132
133 r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &label->in_addr.in6);
134 if (r < 0)
135 return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m");
136
137 r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
138 if (r < 0)
139 return log_error_errno(r, "Could not send rtnetlink message: %m");
140
141 link_ref(link);
142
143 return 0;
144 }
145
146 int config_parse_address_label_prefix(const char *unit,
147 const char *filename,
148 unsigned line,
149 const char *section,
150 unsigned section_line,
151 const char *lvalue,
152 int ltype,
153 const char *rvalue,
154 void *data,
155 void *userdata) {
156
157 _cleanup_address_label_free_ AddressLabel *n = NULL;
158 Network *network = userdata;
159 int r;
160
161 assert(filename);
162 assert(section);
163 assert(lvalue);
164 assert(rvalue);
165 assert(data);
166
167 r = address_label_new_static(network, filename, section_line, &n);
168 if (r < 0)
169 return r;
170
171 r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen);
172 if (r < 0) {
173 log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue);
174 return 0;
175 }
176
177 n = NULL;
178
179 return 0;
180 }
181
182 int config_parse_address_label(
183 const char *unit,
184 const char *filename,
185 unsigned line,
186 const char *section,
187 unsigned section_line,
188 const char *lvalue,
189 int ltype,
190 const char *rvalue,
191 void *data,
192 void *userdata) {
193
194 _cleanup_address_label_free_ AddressLabel *n = NULL;
195 Network *network = userdata;
196 uint32_t k;
197 int r;
198
199 assert(filename);
200 assert(section);
201 assert(lvalue);
202 assert(rvalue);
203 assert(data);
204
205 r = address_label_new_static(network, filename, section_line, &n);
206 if (r < 0)
207 return r;
208
209 r = safe_atou32(rvalue, &k);
210 if (r < 0) {
211 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address label, ignoring: %s", rvalue);
212 return 0;
213 }
214
215 if (k == 0xffffffffUL) {
216 log_syntax(unit, LOG_ERR, filename, line, r, "Adress label is invalid, ignoring: %s", rvalue);
217 return 0;
218 }
219
220 n->label = k;
221 n = NULL;
222
223 return 0;
224 }