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_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_new_route(link->manager->rtnl, RTM_NEWROUTE,
109 route->family, &req);
111 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
115 if (route->family == AF_INET)
116 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
117 else if (route->family == AF_INET6)
118 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
120 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
124 if (route->dst_prefixlen) {
125 if (route->family == AF_INET)
126 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
127 else if (route->family == AF_INET6)
128 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
130 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
134 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
136 log_error("Could not set destination prefix length: %s", strerror(-r));
141 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
143 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
147 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
149 log_error("Could not send rtnetlink message: %s", strerror(-r));
156 int config_parse_gateway(const char *unit,
157 const char *filename,
160 unsigned section_line,
166 Network *network = userdata;
167 _cleanup_route_free_ Route *n = NULL;
168 _cleanup_free_ char *route = NULL;
177 if (streq(section, "Network")) {
178 /* we are not in an Route section, so treat
179 * this as the special '0' section */
183 r = route_new_static(network, section_line, &n);
187 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
189 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
190 "Route is invalid, ignoring assignment: %s", route);
199 int config_parse_destination(const char *unit,
200 const char *filename,
203 unsigned section_line,
209 Network *network = userdata;
210 _cleanup_route_free_ Route *n = NULL;
211 _cleanup_free_ char *address = NULL;
221 r = route_new_static(network, section_line, &n);
225 /* Destination=address/prefixlen */
228 e = strchr(rvalue, '/');
230 address = strndup(rvalue, e - rvalue);
234 address = strdup(rvalue);
239 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
241 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
242 "Destination is invalid, ignoring assignment: %s", address);
250 r = safe_atou(e + 1, &i);
252 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
253 "Route destination prefix length is invalid, "
254 "ignoring assignment: %s", e + 1);
258 n->dst_prefixlen = (unsigned char) i;
262 n->dst_prefixlen = 32;
265 n->dst_prefixlen = 128;