]>
Commit | Line | Data |
---|---|---|
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 | ||
19 | int 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 | ||
31 | void 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 | ||
49 | static 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 | ||
88 | int 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 | ||
129 | int 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 | ||
165 | int 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 | } |