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/>.
25 #include "networkd-link.h"
29 #include "conf-parser.h"
30 #include "network-internal.h"
32 int route_new_static(Network
*network
, unsigned section
, Route
**ret
) {
33 _cleanup_route_free_ Route
*route
= NULL
;
36 route
= hashmap_get(network
->routes_by_section
,
37 UINT_TO_PTR(section
));
46 route
= new0(Route
, 1);
50 route
->family
= AF_UNSPEC
;
51 route
->scope
= RT_SCOPE_UNIVERSE
;
52 route
->protocol
= RTPROT_STATIC
;
54 route
->network
= network
;
56 LIST_PREPEND(routes
, network
->static_routes
, route
);
59 route
->section
= section
;
60 hashmap_put(network
->routes_by_section
,
61 UINT_TO_PTR(route
->section
), route
);
70 int route_new_dynamic(Route
**ret
, unsigned char rtm_protocol
) {
71 _cleanup_route_free_ Route
*route
= NULL
;
73 route
= new0(Route
, 1);
77 route
->family
= AF_UNSPEC
;
78 route
->scope
= RT_SCOPE_UNIVERSE
;
79 route
->protocol
= rtm_protocol
;
87 void route_free(Route
*route
) {
92 LIST_REMOVE(routes
, route
->network
->static_routes
, route
);
95 hashmap_remove(route
->network
->routes_by_section
,
96 UINT_TO_PTR(route
->section
));
102 int route_drop(Route
*route
, Link
*link
,
103 sd_rtnl_message_handler_t callback
) {
104 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
= NULL
;
108 assert(link
->manager
);
109 assert(link
->manager
->rtnl
);
110 assert(link
->ifindex
> 0);
111 assert(route
->family
== AF_INET
|| route
->family
== AF_INET6
);
113 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &req
,
114 RTM_DELROUTE
, route
->family
,
117 log_error("Could not create RTM_DELROUTE message: %s", strerror(-r
));
121 if (!in_addr_is_null(route
->family
, &route
->in_addr
)) {
122 if (route
->family
== AF_INET
)
123 r
= sd_rtnl_message_append_in_addr(req
, RTA_GATEWAY
, &route
->in_addr
.in
);
124 else if (route
->family
== AF_INET6
)
125 r
= sd_rtnl_message_append_in6_addr(req
, RTA_GATEWAY
, &route
->in_addr
.in6
);
127 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r
));
132 if (route
->dst_prefixlen
) {
133 if (route
->family
== AF_INET
)
134 r
= sd_rtnl_message_append_in_addr(req
, RTA_DST
, &route
->dst_addr
.in
);
135 else if (route
->family
== AF_INET6
)
136 r
= sd_rtnl_message_append_in6_addr(req
, RTA_DST
, &route
->dst_addr
.in6
);
138 log_error("Could not append RTA_DST attribute: %s", strerror(-r
));
142 r
= sd_rtnl_message_route_set_dst_prefixlen(req
, route
->dst_prefixlen
);
144 log_error("Could not set destination prefix length: %s", strerror(-r
));
149 if (!in_addr_is_null(route
->family
, &route
->prefsrc_addr
)) {
150 if (route
->family
== AF_INET
)
151 r
= sd_rtnl_message_append_in_addr(req
, RTA_PREFSRC
, &route
->prefsrc_addr
.in
);
152 else if (route
->family
== AF_INET6
)
153 r
= sd_rtnl_message_append_in6_addr(req
, RTA_PREFSRC
, &route
->prefsrc_addr
.in6
);
155 log_error("Could not append RTA_PREFSRC attribute: %s", strerror(-r
));
160 r
= sd_rtnl_message_route_set_scope(req
, route
->scope
);
162 log_error("Could not set scope: %s", strerror(-r
));
166 r
= sd_rtnl_message_append_u32(req
, RTA_PRIORITY
, route
->metrics
);
168 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r
));
172 r
= sd_rtnl_message_append_u32(req
, RTA_OIF
, link
->ifindex
);
174 log_error("Could not append RTA_OIF attribute: %s", strerror(-r
));
178 r
= sd_rtnl_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
180 log_error("Could not send rtnetlink message: %s", strerror(-r
));
189 int route_configure(Route
*route
, Link
*link
,
190 sd_rtnl_message_handler_t callback
) {
191 _cleanup_rtnl_message_unref_ sd_rtnl_message
*req
= NULL
;
195 assert(link
->manager
);
196 assert(link
->manager
->rtnl
);
197 assert(link
->ifindex
> 0);
198 assert(route
->family
== AF_INET
|| route
->family
== AF_INET6
);
200 r
= sd_rtnl_message_new_route(link
->manager
->rtnl
, &req
,
201 RTM_NEWROUTE
, route
->family
,
204 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r
));
208 if (!in_addr_is_null(route
->family
, &route
->in_addr
)) {
209 if (route
->family
== AF_INET
)
210 r
= sd_rtnl_message_append_in_addr(req
, RTA_GATEWAY
, &route
->in_addr
.in
);
211 else if (route
->family
== AF_INET6
)
212 r
= sd_rtnl_message_append_in6_addr(req
, RTA_GATEWAY
, &route
->in_addr
.in6
);
214 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r
));
219 if (route
->dst_prefixlen
) {
220 if (route
->family
== AF_INET
)
221 r
= sd_rtnl_message_append_in_addr(req
, RTA_DST
, &route
->dst_addr
.in
);
222 else if (route
->family
== AF_INET6
)
223 r
= sd_rtnl_message_append_in6_addr(req
, RTA_DST
, &route
->dst_addr
.in6
);
225 log_error("Could not append RTA_DST attribute: %s", strerror(-r
));
229 r
= sd_rtnl_message_route_set_dst_prefixlen(req
, route
->dst_prefixlen
);
231 log_error("Could not set destination prefix length: %s", strerror(-r
));
236 if (!in_addr_is_null(route
->family
, &route
->prefsrc_addr
)) {
237 if (route
->family
== AF_INET
)
238 r
= sd_rtnl_message_append_in_addr(req
, RTA_PREFSRC
, &route
->prefsrc_addr
.in
);
239 else if (route
->family
== AF_INET6
)
240 r
= sd_rtnl_message_append_in6_addr(req
, RTA_PREFSRC
, &route
->prefsrc_addr
.in6
);
242 log_error("Could not append RTA_PREFSRC attribute: %s", strerror(-r
));
247 r
= sd_rtnl_message_route_set_scope(req
, route
->scope
);
249 log_error("Could not set scope: %s", strerror(-r
));
253 r
= sd_rtnl_message_append_u32(req
, RTA_PRIORITY
, route
->metrics
);
255 log_error("Could not append RTA_PRIORITY attribute: %s", strerror(-r
));
259 r
= sd_rtnl_message_append_u32(req
, RTA_OIF
, link
->ifindex
);
261 log_error("Could not append RTA_OIF attribute: %s", strerror(-r
));
265 r
= sd_rtnl_call_async(link
->manager
->rtnl
, req
, callback
, link
, 0, NULL
);
267 log_error("Could not send rtnetlink message: %s", strerror(-r
));
276 int config_parse_gateway(const char *unit
,
277 const char *filename
,
280 unsigned section_line
,
287 Network
*network
= userdata
;
288 _cleanup_route_free_ Route
*n
= NULL
;
289 union in_addr_union buffer
;
298 if (streq(section
, "Network")) {
299 /* we are not in an Route section, so treat
300 * this as the special '0' section */
304 r
= route_new_static(network
, section_line
, &n
);
308 r
= in_addr_from_string_auto(rvalue
, &f
, &buffer
);
310 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
311 "Route is invalid, ignoring assignment: %s", rvalue
);
322 int config_parse_destination(const char *unit
,
323 const char *filename
,
326 unsigned section_line
,
333 Network
*network
= userdata
;
334 _cleanup_route_free_ Route
*n
= NULL
;
335 const char *address
, *e
;
336 union in_addr_union buffer
;
345 r
= route_new_static(network
, section_line
, &n
);
349 /* Destination=address/prefixlen */
352 e
= strchr(rvalue
, '/');
354 address
= strndupa(rvalue
, e
- rvalue
);
358 r
= in_addr_from_string_auto(address
, &f
, &buffer
);
360 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
361 "Destination is invalid, ignoring assignment: %s", address
);
369 r
= safe_atou(e
+ 1, &i
);
371 log_syntax(unit
, LOG_ERR
, filename
, line
, EINVAL
,
372 "Route destination prefix length is invalid, ignoring assignment: %s", e
+ 1);
376 n
->dst_prefixlen
= (unsigned char) i
;
380 n
->dst_prefixlen
= 32;
383 n
->dst_prefixlen
= 128;
389 n
->dst_addr
= buffer
;
395 int config_parse_route_priority(const char *unit
,
396 const char *filename
,
399 unsigned section_line
,
405 Network
*network
= userdata
;
406 _cleanup_route_free_ Route
*n
= NULL
;
415 r
= route_new_static(network
, section_line
, &n
);
419 r
= config_parse_unsigned(unit
, filename
, line
, section
,
420 section_line
, lvalue
, ltype
,
421 rvalue
, &n
->metrics
, userdata
);