chiark / gitweb /
5d5913186df61ee77e975aeaacd8925173c713b0
[elogind.git] / src / network / networkd-netdev-tunnel.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4     This file is part of systemd.
5
6     Copyright 2014 Susant Sahani <susant@redhat.com>
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 <netinet/ether.h>
23 #include <arpa/inet.h>
24 #include <net/if.h>
25 #include <linux/ip.h>
26 #include <linux/if_tunnel.h>
27
28 #include "sd-rtnl.h"
29 #include "networkd-netdev-tunnel.h"
30 #include "network-internal.h"
31 #include "util.h"
32 #include "missing.h"
33 #include "conf-parser.h"
34
35 static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
36         Tunnel *t = IPIP(netdev);
37         int r;
38
39         assert(netdev);
40         assert(link);
41         assert(m);
42         assert(t);
43         assert(t->family == AF_INET);
44
45         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
46         if (r < 0) {
47                 log_error_netdev(netdev,
48                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
49                                  strerror(-r));
50                 return r;
51         }
52
53         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
54         if (r < 0) {
55                 log_error_netdev(netdev,
56                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
57                                  strerror(-r));
58                 return r;
59         }
60
61         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
62         if (r < 0) {
63                 log_error_netdev(netdev,
64                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
65                                  strerror(-r));
66                 return r;
67         }
68
69         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
70         if (r < 0) {
71                 log_error_netdev(netdev,
72                                  "Could not append IFLA_IPTUN_TTL  attribute: %s",
73                                  strerror(-r));
74                 return r;
75         }
76
77         return r;
78 }
79
80 static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
81         Tunnel *t = SIT(netdev);
82         int r;
83
84         assert(netdev);
85         assert(link);
86         assert(m);
87         assert(t);
88         assert(t->family == AF_INET);
89
90         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
91         if (r < 0) {
92                 log_error_netdev(netdev,
93                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
94                                  strerror(-r));
95                 return r;
96         }
97
98         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in);
99         if (r < 0) {
100                 log_error_netdev(netdev,
101                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
102                                  strerror(-r));
103                 return r;
104         }
105
106         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in);
107         if (r < 0) {
108                 log_error_netdev(netdev,
109                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
110                                  strerror(-r));
111                 return r;
112         }
113
114         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
115         if (r < 0) {
116                 log_error_netdev(netdev,
117                                  "Could not append IFLA_IPTUN_TTL attribute: %s",
118                                  strerror(-r));
119                 return r;
120         }
121
122         return r;
123 }
124
125 static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
126         Tunnel *t = GRE(netdev);
127         int r;
128
129         assert(netdev);
130         assert(link);
131         assert(m);
132         assert(t);
133         assert(t->family == AF_INET);
134
135         r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
136         if (r < 0) {
137                 log_error_netdev(netdev,
138                                  "Could not append IFLA_GRE_LINK attribute: %s",
139                                  strerror(-r));
140                 return r;
141         }
142
143         r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in);
144         if (r < 0) {
145                 log_error_netdev(netdev,
146                                  "Could not append IFLA_GRE_LOCAL attribute: %s",
147                                  strerror(-r));
148                 return r;
149         }
150
151         r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in);
152         if (r < 0) {
153                 log_error_netdev(netdev,
154                                  "Could not append IFLA_GRE_REMOTE attribute: %s",
155                                  strerror(-r));
156                 return r;
157         }
158
159         r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
160         if (r < 0) {
161                 log_error_netdev(netdev,
162                                  "Could not append IFLA_GRE_TTL attribute: %s",
163                                  strerror(-r));
164                 return r;
165         }
166
167         r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos);
168         if (r < 0) {
169                 log_error_netdev(netdev,
170                                  "Could not append IFLA_GRE_TOS attribute: %s",
171                                  strerror(-r));
172                 return r;
173         }
174
175         return r;
176 }
177
178 static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
179         Tunnel *t = VTI(netdev);
180         int r;
181
182         assert(netdev);
183         assert(link);
184         assert(m);
185         assert(t);
186         assert(t->family == AF_INET);
187
188         r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
189         if (r < 0) {
190                 log_error_netdev(netdev,
191                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
192                                  strerror(-r));
193                 return r;
194         }
195
196         r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
197         if (r < 0) {
198                 log_error_netdev(netdev,
199                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
200                                  strerror(-r));
201                 return r;
202         }
203
204         r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in);
205         if (r < 0) {
206                 log_error_netdev(netdev,
207                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
208                                  strerror(-r));
209                 return r;
210         }
211
212         return r;
213 }
214
215 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
216         Tunnel *t = NULL;
217
218         assert(netdev);
219         assert(filename);
220
221         switch (netdev->kind) {
222         case NETDEV_KIND_IPIP:
223                 t = IPIP(netdev);
224                 break;
225         case NETDEV_KIND_SIT:
226                 t = SIT(netdev);
227                 break;
228         case NETDEV_KIND_GRE:
229                 t = GRE(netdev);
230                 break;
231         case NETDEV_KIND_VTI:
232                 t = VTI(netdev);
233                 break;
234         default:
235                 assert_not_reached("Invalid tunnel kind");
236         }
237
238         assert(t);
239
240         if (t->local.in.s_addr == INADDR_ANY) {
241                log_warning("Tunnel without local address configured in %s. Ignoring", filename);
242                return -EINVAL;
243         }
244
245         if (t->remote.in.s_addr == INADDR_ANY) {
246                log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
247                return -EINVAL;
248         }
249
250         if (t->family != AF_INET) {
251               log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
252               return -EINVAL;
253         }
254
255         return 0;
256 }
257
258 int config_parse_tunnel_address(const char *unit,
259                                 const char *filename,
260                                 unsigned line,
261                                 const char *section,
262                                 unsigned section_line,
263                                 const char *lvalue,
264                                 int ltype,
265                                 const char *rvalue,
266                                 void *data,
267                                 void *userdata) {
268         Tunnel *t = userdata;
269         union in_addr_union *addr = data, buffer;
270         int r, f;
271
272         assert(filename);
273         assert(lvalue);
274         assert(rvalue);
275         assert(data);
276
277         r = in_addr_from_string_auto(rvalue, &f, &buffer);
278         if (r < 0) {
279                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
280                 return 0;
281         }
282
283         if (t->family != AF_UNSPEC && t->family != f) {
284                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
285                 return 0;
286         }
287
288         t->family = f;
289         *addr = buffer;
290
291         return 0;
292 }
293
294 static void ipip_init(NetDev *n) {
295         Tunnel *t = IPIP(n);
296
297         assert(n);
298         assert(t);
299
300         t->pmtudisc = true;
301 }
302
303 static void sit_init(NetDev *n) {
304         Tunnel *t = SIT(n);
305
306         assert(n);
307         assert(t);
308
309         t->pmtudisc = true;
310 }
311
312 static void vti_init(NetDev *n) {
313         Tunnel *t = VTI(n);
314
315         assert(n);
316         assert(t);
317
318         t->pmtudisc = true;
319 }
320
321 static void gre_init(NetDev *n) {
322         Tunnel *t = GRE(n);
323
324         assert(n);
325         assert(t);
326
327         t->pmtudisc = true;
328 }
329
330 const NetDevVTable ipip_vtable = {
331         .object_size = sizeof(Tunnel),
332         .init = ipip_init,
333         .sections = "Match\0NetDev\0Tunnel\0",
334         .fill_message_create = netdev_ipip_fill_message_create,
335         .create_type = NETDEV_CREATE_STACKED,
336         .config_verify = netdev_tunnel_verify,
337 };
338
339 const NetDevVTable sit_vtable = {
340         .object_size = sizeof(Tunnel),
341         .init = sit_init,
342         .sections = "Match\0NetDev\0Tunnel\0",
343         .fill_message_create = netdev_sit_fill_message_create,
344         .create_type = NETDEV_CREATE_STACKED,
345         .config_verify = netdev_tunnel_verify,
346 };
347
348 const NetDevVTable vti_vtable = {
349         .object_size = sizeof(Tunnel),
350         .init = vti_init,
351         .sections = "Match\0NetDev\0Tunnel\0",
352         .fill_message_create = netdev_vti_fill_message_create,
353         .create_type = NETDEV_CREATE_STACKED,
354         .config_verify = netdev_tunnel_verify,
355 };
356
357 const NetDevVTable gre_vtable = {
358         .object_size = sizeof(Tunnel),
359         .init = gre_init,
360         .sections = "Match\0NetDev\0Tunnel\0",
361         .fill_message_create = netdev_gre_fill_message_create,
362         .create_type = NETDEV_CREATE_STACKED,
363         .config_verify = netdev_tunnel_verify,
364 };