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));
170 int route_configure(Route *route, Link *link,
171 sd_rtnl_message_handler_t callback) {
172 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
176 assert(link->manager);
177 assert(link->manager->rtnl);
178 assert(link->ifindex > 0);
179 assert(route->family == AF_INET || route->family == AF_INET6);
181 r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
182 RTM_NEWROUTE, route->family);
184 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
188 if (route->family == AF_INET)
189 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
190 else if (route->family == AF_INET6)
191 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
193 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
197 if (route->dst_prefixlen) {
198 if (route->family == AF_INET)
199 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
200 else if (route->family == AF_INET6)
201 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
203 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
207 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
209 log_error("Could not set destination prefix length: %s", strerror(-r));
214 r = sd_rtnl_message_route_set_scope(req, route->scope);
216 log_error("Could not set scope: %s", strerror(-r));
220 r = sd_rtnl_message_append_u32(req, RTA_PRIORITY, route->metrics);
222 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r));
226 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
228 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
232 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
234 log_error("Could not send rtnetlink message: %s", strerror(-r));
241 int config_parse_gateway(const char *unit,
242 const char *filename,
245 unsigned section_line,
251 Network *network = userdata;
252 _cleanup_route_free_ Route *n = NULL;
253 _cleanup_free_ char *route = NULL;
262 if (streq(section, "Network")) {
263 /* we are not in an Route section, so treat
264 * this as the special '0' section */
268 r = route_new_static(network, section_line, &n);
272 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
274 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
275 "Route is invalid, ignoring assignment: %s", route);
284 int config_parse_destination(const char *unit,
285 const char *filename,
288 unsigned section_line,
294 Network *network = userdata;
295 _cleanup_route_free_ Route *n = NULL;
296 _cleanup_free_ char *address = NULL;
306 r = route_new_static(network, section_line, &n);
310 /* Destination=address/prefixlen */
313 e = strchr(rvalue, '/');
315 address = strndup(rvalue, e - rvalue);
319 address = strdup(rvalue);
324 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
326 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
327 "Destination is invalid, ignoring assignment: %s", address);
335 r = safe_atou(e + 1, &i);
337 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
338 "Route destination prefix length is invalid, "
339 "ignoring assignment: %s", e + 1);
343 n->dst_prefixlen = (unsigned char) i;
347 n->dst_prefixlen = 32;
350 n->dst_prefixlen = 128;