]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-route.c
networkd: remove unused variable
[thirdparty/systemd.git] / src / network / networkd-route.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <net/if.h>
23
24 #include "networkd.h"
25
26 #include "utf8.h"
27 #include "util.h"
28 #include "conf-parser.h"
29 #include "network-internal.h"
30
31 int route_new_static(Network *network, unsigned section, Route **ret) {
32 _cleanup_route_free_ Route *route = NULL;
33
34 if (section) {
35 uint64_t key = section;
36
37 route = hashmap_get(network->routes_by_section, &key);
38 if (route) {
39 *ret = route;
40 route = NULL;
41
42 return 0;
43 }
44 }
45
46 route = new0(Route, 1);
47 if (!route)
48 return -ENOMEM;
49
50 route->family = AF_UNSPEC;
51 route->scope = RT_SCOPE_UNIVERSE;
52
53 route->network = network;
54
55 LIST_PREPEND(routes, network->static_routes, route);
56
57 if (section) {
58 route->section = section;
59 hashmap_put(network->routes_by_section, &route->section, route);
60 }
61
62 *ret = route;
63 route = NULL;
64
65 return 0;
66 }
67
68 int route_new_dynamic(Route **ret) {
69 _cleanup_route_free_ Route *route = NULL;
70
71 route = new0(Route, 1);
72 if (!route)
73 return -ENOMEM;
74
75 route->family = AF_UNSPEC;
76 route->scope = RT_SCOPE_UNIVERSE;
77
78 *ret = route;
79 route = NULL;
80
81 return 0;
82 }
83
84 void route_free(Route *route) {
85 if (!route)
86 return;
87
88 if (route->network) {
89 LIST_REMOVE(routes, route->network->static_routes, route);
90
91 if (route->section)
92 hashmap_remove(route->network->routes_by_section,
93 &route->section);
94 }
95
96 free(route);
97 }
98
99 int route_drop(Route *route, Link *link,
100 sd_rtnl_message_handler_t callback) {
101 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
102 int r;
103
104 assert(link);
105 assert(link->manager);
106 assert(link->manager->rtnl);
107 assert(link->ifindex > 0);
108 assert(route->family == AF_INET || route->family == AF_INET6);
109
110 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
111 RTM_DELROUTE, route->family);
112 if (r < 0) {
113 log_error("Could not create RTM_DELROUTE message: %s", strerror(-r));
114 return r;
115 }
116
117 if (route->family == AF_INET)
118 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
119 else if (route->family == AF_INET6)
120 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
121 if (r < 0) {
122 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
123 return r;
124 }
125
126 if (route->dst_prefixlen) {
127 if (route->family == AF_INET)
128 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
129 else if (route->family == AF_INET6)
130 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
131 if (r < 0) {
132 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
133 return r;
134 }
135
136 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
137 if (r < 0) {
138 log_error("Could not set destination prefix length: %s", strerror(-r));
139 return r;
140 }
141 }
142
143 r = sd_rtnl_message_route_set_scope(req, route->scope);
144 if (r < 0) {
145 log_error("Could not set scope: %s", strerror(-r));
146 return r;
147 }
148
149 r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
150 if (r < 0) {
151 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
152 return r;
153 }
154
155 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
156 if (r < 0) {
157 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
158 return r;
159 }
160
161 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
162 if (r < 0) {
163 log_error("Could not send rtnetlink message: %s", strerror(-r));
164 return r;
165 }
166
167 link_ref(link);
168
169 return 0;
170 }
171
172 int route_configure(Route *route, Link *link,
173 sd_rtnl_message_handler_t callback) {
174 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
175 int r;
176
177 assert(link);
178 assert(link->manager);
179 assert(link->manager->rtnl);
180 assert(link->ifindex > 0);
181 assert(route->family == AF_INET || route->family == AF_INET6);
182
183 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
184 RTM_NEWROUTE, route->family);
185 if (r < 0) {
186 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
187 return r;
188 }
189
190 if (route->family == AF_INET)
191 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
192 else if (route->family == AF_INET6)
193 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
194 if (r < 0) {
195 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
196 return r;
197 }
198
199 if (route->dst_prefixlen) {
200 if (route->family == AF_INET)
201 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
202 else if (route->family == AF_INET6)
203 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
204 if (r < 0) {
205 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
206 return r;
207 }
208
209 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
210 if (r < 0) {
211 log_error("Could not set destination prefix length: %s", strerror(-r));
212 return r;
213 }
214 }
215
216 r = sd_rtnl_message_route_set_scope(req, route->scope);
217 if (r < 0) {
218 log_error("Could not set scope: %s", strerror(-r));
219 return r;
220 }
221
222 r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
223 if (r < 0) {
224 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
225 return r;
226 }
227
228 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
229 if (r < 0) {
230 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
231 return r;
232 }
233
234 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
235 if (r < 0) {
236 log_error("Could not send rtnetlink message: %s", strerror(-r));
237 return r;
238 }
239
240 link_ref(link);
241
242 return 0;
243 }
244
245 int config_parse_gateway(const char *unit,
246 const char *filename,
247 unsigned line,
248 const char *section,
249 unsigned section_line,
250 const char *lvalue,
251 int ltype,
252 const char *rvalue,
253 void *data,
254 void *userdata) {
255 Network *network = userdata;
256 _cleanup_route_free_ Route *n = NULL;
257 _cleanup_free_ char *route = NULL;
258 int r;
259
260 assert(filename);
261 assert(section);
262 assert(lvalue);
263 assert(rvalue);
264 assert(data);
265
266 if (streq(section, "Network")) {
267 /* we are not in an Route section, so treat
268 * this as the special '0' section */
269 section_line = 0;
270 }
271
272 r = route_new_static(network, section_line, &n);
273 if (r < 0)
274 return r;
275
276 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
277 if (r < 0) {
278 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
279 "Route is invalid, ignoring assignment: %s", route);
280 return 0;
281 }
282
283 n = NULL;
284
285 return 0;
286 }
287
288 int config_parse_destination(const char *unit,
289 const char *filename,
290 unsigned line,
291 const char *section,
292 unsigned section_line,
293 const char *lvalue,
294 int ltype,
295 const char *rvalue,
296 void *data,
297 void *userdata) {
298 Network *network = userdata;
299 _cleanup_route_free_ Route *n = NULL;
300 _cleanup_free_ char *address = NULL;
301 const char *e;
302 int r;
303
304 assert(filename);
305 assert(section);
306 assert(lvalue);
307 assert(rvalue);
308 assert(data);
309
310 r = route_new_static(network, section_line, &n);
311 if (r < 0)
312 return r;
313
314 /* Destination=address/prefixlen */
315
316 /* address */
317 e = strchr(rvalue, '/');
318 if (e) {
319 address = strndup(rvalue, e - rvalue);
320 if (!address)
321 return log_oom();
322 } else {
323 address = strdup(rvalue);
324 if (!address)
325 return log_oom();
326 }
327
328 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
329 if (r < 0) {
330 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
331 "Destination is invalid, ignoring assignment: %s", address);
332 return 0;
333 }
334
335 /* prefixlen */
336 if (e) {
337 unsigned i;
338
339 r = safe_atou(e + 1, &i);
340 if (r < 0) {
341 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
342 "Route destination prefix length is invalid, "
343 "ignoring assignment: %s", e + 1);
344 return 0;
345 }
346
347 n->dst_prefixlen = (unsigned char) i;
348 } else {
349 switch (n->family) {
350 case AF_INET:
351 n->dst_prefixlen = 32;
352 break;
353 case AF_INET6:
354 n->dst_prefixlen = 128;
355 break;
356 }
357 }
358
359 n = NULL;
360
361 return 0;
362 }
363
364 int config_parse_route_priority(const char *unit,
365 const char *filename,
366 unsigned line,
367 const char *section,
368 unsigned section_line,
369 const char *lvalue,
370 int ltype,
371 const char *rvalue,
372 void *data,
373 void *userdata) {
374 Network *network = userdata;
375 _cleanup_route_free_ Route *n = NULL;
376 int r;
377
378 assert(filename);
379 assert(section);
380 assert(lvalue);
381 assert(rvalue);
382 assert(data);
383
384 r = route_new_static(network, section_line, &n);
385 if (r < 0)
386 return r;
387
388 r = config_parse_unsigned(unit, filename, line, section,
389 section_line, lvalue, ltype,
390 rvalue, &n->metrics, userdata);
391 if (r < 0)
392 return r;
393
394 n = NULL;
395
396 return 0;
397 }