chiark / gitweb /
networkd: use correct printf formatter
[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, route->dst_prefixlen,
90                                       0, 0, RT_TABLE_MAIN, RT_SCOPE_UNIVERSE,
91                                       RTPROT_BOOT, RTN_UNICAST, 0, &req);
92         if (r < 0) {
93                 log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r));
94                 return r;
95         }
96
97         r = sd_rtnl_message_append(req, RTA_GATEWAY, &route->in_addr);
98         if (r < 0) {
99                 log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r));
100                 return r;
101         }
102
103         r = sd_rtnl_message_append(req, RTA_DST, &route->dst_addr);
104         if (r < 0) {
105                 log_error("Could not append RTA_DST attribute: %s", strerror(-r));
106                 return r;
107         }
108
109         r = sd_rtnl_message_append(req, RTA_OIF, &link->ifindex);
110         if (r < 0) {
111                 log_error("Could not append RTA_OIF attribute: %s", strerror(-r));
112                 return r;
113         }
114
115         r = sd_rtnl_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
116         if (r < 0) {
117                 log_error("Could not send rtnetlink message: %s", strerror(-r));
118                 return r;
119         }
120
121         link->rtnl_messages ++;
122
123         return 0;
124 }
125
126 int config_parse_gateway(const char *unit,
127                 const char *filename,
128                 unsigned line,
129                 const char *section,
130                 unsigned section_line,
131                 const char *lvalue,
132                 int ltype,
133                 const char *rvalue,
134                 void *data,
135                 void *userdata) {
136         Network *network = userdata;
137         _cleanup_route_free_ Route *n = NULL;
138         _cleanup_free_ char *route = NULL;
139         int r;
140
141         assert(filename);
142         assert(section);
143         assert(lvalue);
144         assert(rvalue);
145         assert(data);
146
147         r = route_new(network, section_line, &n);
148         if (r < 0)
149                 return r;
150
151         r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
152         if (r < 0) {
153                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
154                            "Route is invalid, ignoring assignment: %s", route);
155                 return 0;
156         }
157
158         n = NULL;
159
160         return 0;
161 }
162
163 int config_parse_destination(const char *unit,
164                 const char *filename,
165                 unsigned line,
166                 const char *section,
167                 unsigned section_line,
168                 const char *lvalue,
169                 int ltype,
170                 const char *rvalue,
171                 void *data,
172                 void *userdata) {
173         Network *network = userdata;
174         _cleanup_route_free_ Route *n = NULL;
175         _cleanup_free_ char *address = NULL;
176         const char *e;
177         int r;
178
179         assert(filename);
180         assert(section);
181         assert(lvalue);
182         assert(rvalue);
183         assert(data);
184
185         r = route_new(network, section_line, &n);
186         if (r < 0)
187                 return r;
188
189         /* Destination=address/prefixlen */
190
191         /* prefixlen */
192         e = strchr(rvalue, '/');
193         if (e) {
194                 unsigned i;
195                 r = safe_atou(e + 1, &i);
196                 if (r < 0) {
197                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
198                                    "Route destination prefix length is invalid, "
199                                    "ignoring assignment: %s", e + 1);
200                         return 0;
201                 }
202
203                 n->dst_prefixlen = (unsigned char) i;
204
205                 address = strndup(rvalue, e - rvalue);
206                 if (!address)
207                         return log_oom();
208         } else {
209                 address = strdup(rvalue);
210                 if (!address)
211                         return log_oom();
212         }
213
214         r = net_parse_inaddr(address, &n->family, &n->dst_addr);
215         if (r < 0) {
216                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
217                            "Destination is invalid, ignoring assignment: %s", address);
218                 return 0;
219         }
220
221         n = NULL;
222
223         return 0;
224 }