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