1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
28 #include "conf-parser.h"
29 #include "network-internal.h"
31 int route_new_static(Network *network, unsigned section, Route **ret) {
32 _cleanup_route_free_ Route *route = NULL;
35 uint64_t key = section;
37 route = hashmap_get(network->routes_by_section, &key);
46 route = new0(Route, 1);
50 route->family = AF_UNSPEC;
51 route->scope = RT_SCOPE_UNIVERSE;
53 route->network = network;
55 LIST_PREPEND(routes, network->static_routes, route);
58 route->section = section;
59 hashmap_put(network->routes_by_section, &route->section, route);
68 int route_new_dynamic(Route **ret) {
69 _cleanup_route_free_ Route *route = NULL;
71 route = new0(Route, 1);
75 route->family = AF_UNSPEC;
76 route->scope = RT_SCOPE_UNIVERSE;
84 void route_free(Route *route) {
89 LIST_REMOVE(routes, route->network->static_routes, route);
92 hashmap_remove(route->network->routes_by_section,
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;
105 assert(link->manager);
106 assert(link->manager->rtnl);
107 assert(link->ifindex > 0);
108 assert(route->family == AF_INET || route->family == AF_INET6);
110 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
111 RTM_DELROUTE, route->family);
113 log_error("Could not create RTM_DELROUTE message: %s", strerror(-r));
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);
122 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
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);
132 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
136 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
138 log_error("Could not set destination prefix length: %s", strerror(-r));
143 r = sd_rtnl_message_route_set_scope(req, route->scope);
145 log_error("Could not set scope: %s", strerror(-r));
149 r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
151 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
155 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
157 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
161 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
163 log_error("Could not send rtnetlink message: %s", strerror(-r));
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;
178 assert(link->manager);
179 assert(link->manager->rtnl);
180 assert(link->ifindex > 0);
181 assert(route->family == AF_INET || route->family == AF_INET6);
183 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
184 RTM_NEWROUTE, route->family);
186 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
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);
195 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
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);
205 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
209 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
211 log_error("Could not set destination prefix length: %s", strerror(-r));
216 r = sd_rtnl_message_route_set_scope(req, route->scope);
218 log_error("Could not set scope: %s", strerror(-r));
222 r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
224 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
228 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
230 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
234 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
236 log_error("Could not send rtnetlink message: %s", strerror(-r));
245 int config_parse_gateway(const char *unit,
246 const char *filename,
249 unsigned section_line,
255 Network *network = userdata;
256 _cleanup_route_free_ Route *n = NULL;
257 _cleanup_free_ char *route = NULL;
266 if (streq(section, "Network")) {
267 /* we are not in an Route section, so treat
268 * this as the special '0' section */
272 r = route_new_static(network, section_line, &n);
276 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
278 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
279 "Route is invalid, ignoring assignment: %s", route);
288 int config_parse_destination(const char *unit,
289 const char *filename,
292 unsigned section_line,
298 Network *network = userdata;
299 _cleanup_route_free_ Route *n = NULL;
300 _cleanup_free_ char *address = NULL;
310 r = route_new_static(network, section_line, &n);
314 /* Destination=address/prefixlen */
317 e = strchr(rvalue, '/');
319 address = strndup(rvalue, e - rvalue);
323 address = strdup(rvalue);
328 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
330 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
331 "Destination is invalid, ignoring assignment: %s", address);
339 r = safe_atou(e + 1, &i);
341 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
342 "Route destination prefix length is invalid, "
343 "ignoring assignment: %s", e + 1);
347 n->dst_prefixlen = (unsigned char) i;
351 n->dst_prefixlen = 32;
354 n->dst_prefixlen = 128;