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