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