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