]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-route.c
rtnl: replace message_append by typesafe versions
[thirdparty/systemd.git] / src / network / networkd-route.c
CommitLineData
f579559b
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20***/
21
22#include <net/if.h>
23
24#include "networkd.h"
25
26#include "utf8.h"
27#include "util.h"
28#include "conf-parser.h"
29#include "net-util.h"
30
6ae115c1 31int route_new(Network *network, unsigned section, Route **ret) {
f579559b
TG
32 _cleanup_route_free_ Route *route = NULL;
33
6ae115c1
TG
34 if (section) {
35 uint64_t key = section;
36
37 route = hashmap_get(network->routes_by_section, &key);
38 if (route) {
39 *ret = route;
40 route = NULL;
41
42 return 0;
43 }
44 }
45
f579559b
TG
46 route = new0(Route, 1);
47 if (!route)
48 return -ENOMEM;
49
50 route->network = network;
51
52 LIST_PREPEND(routes, network->routes, route);
53
6ae115c1
TG
54 if (section) {
55 route->section = section;
56 hashmap_put(network->routes_by_section, &route->section, route);
57 }
58
f579559b
TG
59 *ret = route;
60 route = NULL;
61
62 return 0;
63}
64
65void route_free(Route *route) {
66 if (!route)
67 return;
68
69 LIST_REMOVE(routes, route->network->routes, route);
70
6ae115c1
TG
71 if (route->section)
72 hashmap_remove(route->network->routes_by_section,
73 &route->section);
74
f579559b
TG
75 free(route);
76}
77
f882c247
TG
78int route_configure(Route *route, Link *link,
79 sd_rtnl_message_handler_t callback) {
f579559b
TG
80 _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
81 int r;
82
f579559b 83 assert(link);
f882c247
TG
84 assert(link->manager);
85 assert(link->manager->rtnl);
f579559b
TG
86 assert(link->ifindex > 0);
87 assert(route->family == AF_INET || route->family == AF_INET6);
88
1f01fb4f 89 r = sd_rtnl_message_route_new(RTM_NEWROUTE, route->family, &req);
f579559b
TG
90 if (r < 0) {
91 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
92 return r;
93 }
94
0a0dc69b
TG
95 if (route->family == AF_INET)
96 r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &route->in_addr.in);
97 else if (route->family == AF_INET6)
98 r = sd_rtnl_message_append_in6_addr(req, RTA_GATEWAY, &route->in_addr.in6);
f579559b
TG
99 if (r < 0) {
100 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
101 return r;
102 }
103
0a0dc69b
TG
104 if (route->dst_prefixlen) {
105 if (route->family == AF_INET)
106 r = sd_rtnl_message_append_in_addr(req, RTA_DST, &route->dst_addr.in);
107 else if (route->family == AF_INET6)
108 r = sd_rtnl_message_append_in6_addr(req, RTA_DST, &route->dst_addr.in6);
109 if (r < 0) {
110 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
111 return r;
112 }
6ae115c1
TG
113 }
114
1f01fb4f
TG
115 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
116 if (r < 0) {
117 log_error("Could not set destination prefix length: %s", strerror(-r));
118 return r;
119 }
120
0a0dc69b 121 r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
f579559b
TG
122 if (r < 0) {
123 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
124 return r;
125 }
126
f882c247 127 r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
f579559b 128 if (r < 0) {
f882c247 129 log_error("Could not send rtnetlink message: %s", strerror(-r));
f579559b
TG
130 return r;
131 }
132
f579559b
TG
133 return 0;
134}
135
136int config_parse_gateway(const char *unit,
137 const char *filename,
138 unsigned line,
139 const char *section,
71a61510 140 unsigned section_line,
f579559b
TG
141 const char *lvalue,
142 int ltype,
143 const char *rvalue,
144 void *data,
145 void *userdata) {
6ae115c1 146 Network *network = userdata;
f579559b
TG
147 _cleanup_route_free_ Route *n = NULL;
148 _cleanup_free_ char *route = NULL;
149 int r;
150
151 assert(filename);
6ae115c1 152 assert(section);
f579559b
TG
153 assert(lvalue);
154 assert(rvalue);
155 assert(data);
156
92fe133a
TG
157 if (streq(section, "Network")) {
158 /* we are not in an Route section, so treat
159 * this as the special '0' section */
160 section_line = 0;
161 }
162
6ae115c1 163 r = route_new(network, section_line, &n);
f579559b
TG
164 if (r < 0)
165 return r;
166
167 r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
168 if (r < 0) {
169 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
170 "Route is invalid, ignoring assignment: %s", route);
171 return 0;
172 }
173
174 n = NULL;
175
176 return 0;
177}
6ae115c1
TG
178
179int config_parse_destination(const char *unit,
180 const char *filename,
181 unsigned line,
182 const char *section,
183 unsigned section_line,
184 const char *lvalue,
185 int ltype,
186 const char *rvalue,
187 void *data,
188 void *userdata) {
189 Network *network = userdata;
190 _cleanup_route_free_ Route *n = NULL;
191 _cleanup_free_ char *address = NULL;
192 const char *e;
193 int r;
194
195 assert(filename);
196 assert(section);
197 assert(lvalue);
198 assert(rvalue);
199 assert(data);
200
201 r = route_new(network, section_line, &n);
202 if (r < 0)
203 return r;
204
205 /* Destination=address/prefixlen */
206
207 /* prefixlen */
208 e = strchr(rvalue, '/');
209 if (e) {
210 unsigned i;
211 r = safe_atou(e + 1, &i);
212 if (r < 0) {
213 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
214 "Route destination prefix length is invalid, "
215 "ignoring assignment: %s", e + 1);
216 return 0;
217 }
218
219 n->dst_prefixlen = (unsigned char) i;
220
221 address = strndup(rvalue, e - rvalue);
222 if (!address)
223 return log_oom();
224 } else {
225 address = strdup(rvalue);
226 if (!address)
227 return log_oom();
228 }
229
230 r = net_parse_inaddr(address, &n->family, &n->dst_addr);
231 if (r < 0) {
232 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
233 "Destination is invalid, ignoring assignment: %s", address);
234 return 0;
235 }
236
237 n = NULL;
238
239 return 0;
240}