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"
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;
52 route->network = network;
54 LIST_PREPEND(static_routes, network->static_routes, route);
57 route->section = section;
58 hashmap_put(network->routes_by_section, &route->section, route);
67 int route_new_dynamic(Route **ret) {
68 _cleanup_route_free_ Route *route = NULL;
70 route = new0(Route, 1);
74 route->family = AF_UNSPEC;
82 void route_free(Route *route) {
87 LIST_REMOVE(static_routes, route->network->static_routes, route);
90 hashmap_remove(route->network->routes_by_section,
97 int route_configure(Route *route, Link *link,
98 sd_rtnl_message_handler_t callback) {
99 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
103 assert(link->manager);
104 assert(link->manager->rtnl);
105 assert(link->ifindex > 0);
106 assert(route->family == AF_INET || route->family == AF_INET6);
108 r = sd_rtnl_message_route_new(RTM_NEWROUTE, route->family, &req);
110 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
114 if (route->family == AF_INET)
115 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
116 else if (route->family == AF_INET6)
117 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
119 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
123 if (route->dst_prefixlen) {
124 if (route->family == AF_INET)
125 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
126 else if (route->family == AF_INET6)
127 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
129 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
133 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
135 log_error("Could not set destination prefix length: %s", strerror(-r));
140 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
142 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
146 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
148 log_error("Could not send rtnetlink message: %s", strerror(-r));
155 int config_parse_gateway(const char *unit,
156 const char *filename,
159 unsigned section_line,
165 Network *network = userdata;
166 _cleanup_route_free_ Route *n = NULL;
167 _cleanup_free_ char *route = NULL;
176 if (streq(section, "Network")) {
177 /* we are not in an Route section, so treat
178 * this as the special '0' section */
182 r = route_new_static(network, section_line, &n);
186 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
188 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
189 "Route is invalid, ignoring assignment: %s", route);
198 int config_parse_destination(const char *unit,
199 const char *filename,
202 unsigned section_line,
208 Network *network = userdata;
209 _cleanup_route_free_ Route *n = NULL;
210 _cleanup_free_ char *address = NULL;
220 r = route_new_static(network, section_line, &n);
224 /* Destination=address/prefixlen */
227 e = strchr(rvalue, '/');
229 address = strndup(rvalue, e - rvalue);
233 address = strdup(rvalue);
238 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
240 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
241 "Destination is invalid, ignoring assignment: %s", address);
249 r = safe_atou(e + 1, &i);
251 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
252 "Route destination prefix length is invalid, "
253 "ignoring assignment: %s", e + 1);
257 n->dst_prefixlen = (unsigned char) i;
261 n->dst_prefixlen = 32;
264 n->dst_prefixlen = 128;