chiark / gitweb /
remove unused variable
[elogind.git] / src / network / networkd-route.c
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
31 int route_new(Network *network, unsigned section, Route **ret) {
32         _cleanup_route_free_ Route *route = NULL;
33
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
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
54         if (section) {
55                 route->section = section;
56                 hashmap_put(network->routes_by_section, &route->section, route);
57         }
58
59         *ret = route;
60         route = NULL;
61
62         return 0;
63 }
64
65 void route_free(Route *route) {
66         if (!route)
67                 return;
68
69         LIST_REMOVE(routes, route->network->routes, route);
70
71         if (route->section)
72                 hashmap_remove(route->network->routes_by_section,
73                                &route->section);
74
75         free(route);
76 }
77
78 int route_configure(Route *route, Link *link,
79                     sd_rtnl_message_handler_t callback) {
80         _cleanup_sd_rtnl_message_unref_ sd_rtnl_message *req = NULL;
81         int r;
82
83         assert(link);
84         assert(link->manager);
85         assert(link->manager->rtnl);
86         assert(link->ifindex > 0);
87         assert(route->family == AF_INET || route->family == AF_INET6);
88
89         r = sd_rtnl_message_route_new(RTM_NEWROUTE, route->family, &req);
90         if (r < 0) {
91                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
92                 return r;
93         }
94
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);
99         if (r < 0) {
100                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
101                 return r;
102         }
103
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                 }
113
114                 r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
115                 if (r < 0) {
116                         log_error("Could not set destination prefix length: %s", strerror(-r));
117                         return r;
118                 }
119         }
120
121         r = sd_rtnl_message_append_u32(req, RTA_OIF, link->ifindex);
122         if (r < 0) {
123                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
124                 return r;
125         }
126
127         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
128         if (r < 0) {
129                 log_error("Could not send rtnetlink message: %s", strerror(-r));
130                 return r;
131         }
132
133         return 0;
134 }
135
136 int config_parse_gateway(const char *unit,
137                 const char *filename,
138                 unsigned line,
139                 const char *section,
140                 unsigned section_line,
141                 const char *lvalue,
142                 int ltype,
143                 const char *rvalue,
144                 void *data,
145                 void *userdata) {
146         Network *network = userdata;
147         _cleanup_route_free_ Route *n = NULL;
148         _cleanup_free_ char *route = NULL;
149         int r;
150
151         assert(filename);
152         assert(section);
153         assert(lvalue);
154         assert(rvalue);
155         assert(data);
156
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
163         r = route_new(network, section_line, &n);
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 }
178
179 int 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         /* address */
208         e = strchr(rvalue, '/');
209         if (e) {
210                 address = strndup(rvalue, e - rvalue);
211                 if (!address)
212                         return log_oom();
213         } else {
214                 address = strdup(rvalue);
215                 if (!address)
216                         return log_oom();
217         }
218
219         r = net_parse_inaddr(address, &n->family, &n->dst_addr);
220         if (r < 0) {
221                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
222                            "Destination is invalid, ignoring assignment: %s", address);
223                 return 0;
224         }
225
226         /* prefixlen */
227         if (e) {
228                 unsigned i;
229
230                 r = safe_atou(e + 1, &i);
231                 if (r < 0) {
232                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
233                                    "Route destination prefix length is invalid, "
234                                    "ignoring assignment: %s", e + 1);
235                         return 0;
236                 }
237
238                 n->dst_prefixlen = (unsigned char) i;
239         } else {
240                 switch (n->family) {
241                         case AF_INET:
242                                 n->dst_prefixlen = 32;
243                                 break;
244                         case AF_INET6:
245                                 n->dst_prefixlen = 128;
246                                 break;
247                 }
248         }
249
250         n = NULL;
251
252         return 0;
253 }