]>
Commit | Line | Data |
---|---|---|
95b74ef6 SS |
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, | |
f7bf1abe | 120 | link->ifindex, AF_INET6); |
95b74ef6 SS |
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; | |
f7bf1abe | 158 | int r; |
95b74ef6 SS |
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 | ||
f7bf1abe | 170 | r = in_addr_prefix_from_string(rvalue, AF_INET6, &n->in_addr, &n->prefixlen); |
95b74ef6 | 171 | if (r < 0) { |
f7bf1abe | 172 | log_syntax(unit, LOG_ERR, filename, line, r, "Address label is invalid, ignoring assignment: %s", rvalue); |
95b74ef6 SS |
173 | return 0; |
174 | } | |
175 | ||
95b74ef6 SS |
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 | } |