chiark / gitweb /
core: make sure we properly parse ProtectHome= and ProtectSystem=
[elogind.git] / src / network / networkd-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.h"
30 #include "network-internal.h"
31 #include "util.h"
32
33
34 static int netdev_fill_ipip_rtnl_message(Link *link, sd_rtnl_message *m) {
35         NetDev *netdev;
36         int r;
37
38         assert(link);
39         assert(link->network);
40         assert(link->network->tunnel);
41         assert(m);
42
43         netdev = link->network->tunnel;
44
45         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
46         if (r < 0) {
47                 log_error_netdev(netdev,
48                                  "Could not append IFLA_IFNAME, attribute: %s",
49                                  strerror(-r));
50                 return r;
51         }
52
53         if(netdev->mtu) {
54                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
55                 if (r < 0) {
56                         log_error_netdev(netdev,
57                                          "Could not append IFLA_MTU attribute: %s",
58                                          strerror(-r));
59                         return r;
60                 }
61         }
62
63         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
64         if (r < 0) {
65                 log_error_netdev(netdev,
66                                  "Could not append IFLA_LINKINFO attribute: %s",
67                                  strerror(-r));
68                 return r;
69         }
70
71         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
72                                                  netdev_kind_to_string(netdev->kind));
73         if (r < 0) {
74                 log_error_netdev(netdev,
75                                  "Could not append IFLA_INFO_DATA attribute: %s",
76                                  strerror(-r));
77                 return r;
78         }
79
80         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
81         if (r < 0) {
82                 log_error_netdev(netdev,
83                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
84                                  strerror(-r));
85                 return r;
86         }
87
88         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->tunnel_local);
89         if (r < 0) {
90                 log_error_netdev(netdev,
91                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
92                                  strerror(-r));
93                 return r;
94         }
95
96         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->tunnel_remote);
97         if (r < 0) {
98                 log_error_netdev(netdev,
99                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
100                                  strerror(-r));
101                 return r;
102         }
103
104         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->tunnel_ttl);
105         if (r < 0) {
106                 log_error_netdev(netdev,
107                                  "Could not append IFLA_IPTUN_TTL  attribute: %s",
108                                  strerror(-r));
109                 return r;
110         }
111
112         r = sd_rtnl_message_close_container(m);
113         if (r < 0) {
114                 log_error_netdev(netdev,
115                                  "Could not append IFLA_INFO_DATA attribute: %s",
116                                  strerror(-r));
117                 return r;
118         }
119
120         r = sd_rtnl_message_close_container(m);
121         if (r < 0) {
122                 log_error_netdev(netdev,
123                                  "Could not append IFLA_LINKINFO attribute: %s",
124                                  strerror(-r));
125                 return r;
126         }
127
128         return r;
129 }
130
131 static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) {
132         NetDev *netdev;
133         int r;
134
135         assert(link);
136         assert(link->network);
137         assert(link->network->tunnel);
138         assert(m);
139
140         netdev = link->network->tunnel;
141
142         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
143         if (r < 0) {
144                 log_error_netdev(netdev,
145                                  "Could not append IFLA_IFNAME, attribute: %s",
146                                  strerror(-r));
147                 return r;
148         }
149
150         if(netdev->mtu) {
151                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
152                 if (r < 0) {
153                         log_error_netdev(netdev,
154                                          "Could not append IFLA_MTU attribute: %s",
155                                          strerror(-r));
156                         return r;
157                 }
158         }
159
160         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
161         if (r < 0) {
162                 log_error_netdev(netdev,
163                                  "Could not append IFLA_LINKINFO attribute: %s",
164                                  strerror(-r));
165                 return r;
166         }
167
168         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
169                                                  netdev_kind_to_string(netdev->kind));
170         if (r < 0) {
171                 log_error_netdev(netdev,
172                                  "Could not append IFLA_INFO_DATA attribute: %s",
173                                  strerror(-r));
174                 return r;
175         }
176
177         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
178         if (r < 0) {
179                 log_error_netdev(netdev,
180                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
181                                  strerror(-r));
182                 return r;
183         }
184
185         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->tunnel_local);
186         if (r < 0) {
187                 log_error_netdev(netdev,
188                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
189                                  strerror(-r));
190                 return r;
191         }
192
193         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->tunnel_remote);
194         if (r < 0) {
195                 log_error_netdev(netdev,
196                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
197                                  strerror(-r));
198                 return r;
199         }
200
201         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TOS, netdev->tunnel_tos);
202         if (r < 0) {
203                 log_error_netdev(netdev,
204                                  "Could not append IFLA_IPTUN_TOS attribute: %s",
205                                  strerror(-r));
206                 return r;
207         }
208
209         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, netdev->tunnel_pmtudisc);
210         if (r < 0) {
211                 log_error_netdev(netdev,
212                                  "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
213                                  strerror(-r));
214                 return r;
215         }
216
217         r = sd_rtnl_message_close_container(m);
218         if (r < 0) {
219                 log_error_netdev(netdev,
220                                  "Could not append IFLA_INFO_DATA attribute: %s",
221                                  strerror(-r));
222                 return r;
223         }
224
225         r = sd_rtnl_message_close_container(m);
226         if (r < 0) {
227                 log_error_netdev(netdev,
228                                  "Could not append IFLA_LINKINFO attribute: %s",
229                                  strerror(-r));
230                 return r;
231         }
232
233         return r;
234 }
235
236 static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) {
237         NetDev *netdev;
238         int r;
239
240         assert(link);
241         assert(link->network);
242         assert(link->network->tunnel);
243         assert(m);
244
245         netdev = link->network->tunnel;
246
247         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
248         if (r < 0) {
249                 log_error_netdev(netdev,
250                                  "Could not append IFLA_IFNAME, attribute: %s",
251                                  strerror(-r));
252                 return r;
253         }
254
255         if(netdev->mtu) {
256                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
257                 if (r < 0) {
258                         log_error_netdev(netdev,
259                                          "Could not append IFLA_MTU attribute: %s",
260                                          strerror(-r));
261                         return r;
262                 }
263         }
264
265         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
266         if (r < 0) {
267                 log_error_netdev(netdev,
268                                  "Could not append IFLA_LINKINFO attribute: %s",
269                                  strerror(-r));
270                 return r;
271         }
272
273         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
274                                                  netdev_kind_to_string(netdev->kind));
275         if (r < 0) {
276                 log_error_netdev(netdev,
277                                  "Could not append IFLA_INFO_DATA attribute: %s",
278                                  strerror(-r));
279                 return r;
280         }
281
282         r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
283         if (r < 0) {
284                 log_error_netdev(netdev,
285                                  "Could not append IFLA_GRE_LINK attribute: %s",
286                                  strerror(-r));
287                 return r;
288         }
289
290         r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->tunnel_local);
291         if (r < 0) {
292                 log_error_netdev(netdev,
293                                  "Could not append IFLA_GRE_LOCAL attribute: %s",
294                                  strerror(-r));
295                 return r;
296         }
297
298         r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->tunnel_remote);
299         if (r < 0) {
300                 log_error_netdev(netdev,
301                                  "Could not append IFLA_GRE_REMOTE attribute: %s",
302                                  strerror(-r));
303                 return r;
304         }
305
306         r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->tunnel_ttl);
307         if (r < 0) {
308                 log_error_netdev(netdev,
309                                  "Could not append IFLA_GRE_TTL attribute: %s",
310                                  strerror(-r));
311                 return r;
312         }
313
314         r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tunnel_tos);
315         if (r < 0) {
316                 log_error_netdev(netdev,
317                                  "Could not append IFLA_GRE_TOS attribute: %s",
318                                  strerror(-r));
319                 return r;
320         }
321
322         r = sd_rtnl_message_close_container(m);
323         if (r < 0) {
324                 log_error_netdev(netdev,
325                                  "Could not append IFLA_INFO_DATA attribute: %s",
326                                  strerror(-r));
327                 return r;
328         }
329
330         r = sd_rtnl_message_close_container(m);
331         if (r < 0) {
332                 log_error_netdev(netdev,
333                                  "Could not append IFLA_LINKINFO attribute: %s",
334                                  strerror(-r));
335                 return r;
336         }
337
338         return r;
339 }
340
341 static int netdev_fill_vti_rtnl_message(Link *link, sd_rtnl_message *m) {
342         NetDev *netdev;
343         int r;
344
345         assert(link);
346         assert(link->network);
347         assert(link->network->tunnel);
348         assert(m);
349
350         netdev = link->network->tunnel;
351
352         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
353         if (r < 0) {
354                 log_error_netdev(netdev,
355                                  "Could not append IFLA_IFNAME, attribute: %s",
356                                  strerror(-r));
357                 return r;
358         }
359
360         if(netdev->mtu) {
361                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
362                 if (r < 0) {
363                         log_error_netdev(netdev,
364                                          "Could not append IFLA_MTU attribute: %s",
365                                          strerror(-r));
366                         return r;
367                 }
368         }
369
370         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
371         if (r < 0) {
372                 log_error_netdev(netdev,
373                                  "Could not append IFLA_LINKINFO attribute: %s",
374                                  strerror(-r));
375                 return r;
376         }
377
378         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
379                                                  netdev_kind_to_string(netdev->kind));
380         if (r < 0) {
381                 log_error_netdev(netdev,
382                                  "Could not append IFLA_INFO_DATA attribute: %s",
383                                  strerror(-r));
384                 return r;
385         }
386
387         r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
388         if (r < 0) {
389                 log_error_netdev(netdev,
390                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
391                                  strerror(-r));
392                 return r;
393         }
394
395         r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &netdev->tunnel_local);
396         if (r < 0) {
397                 log_error_netdev(netdev,
398                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
399                                  strerror(-r));
400                 return r;
401         }
402
403         r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &netdev->tunnel_remote);
404         if (r < 0) {
405                 log_error_netdev(netdev,
406                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
407                                  strerror(-r));
408                 return r;
409         }
410
411         r = sd_rtnl_message_close_container(m);
412         if (r < 0) {
413                 log_error_netdev(netdev,
414                                  "Could not append IFLA_INFO_DATA attribute: %s",
415                                  strerror(-r));
416                 return r;
417         }
418
419         r = sd_rtnl_message_close_container(m);
420         if (r < 0) {
421                 log_error_netdev(netdev,
422                                  "Could not append IFLA_LINKINFO attribute: %s",
423                                  strerror(-r));
424                 return r;
425         }
426
427         return r;
428 }
429
430 int netdev_create_tunnel(Link *link, sd_rtnl_message_handler_t callback) {
431         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
432         NetDev *netdev;
433         int r;
434
435         assert(link);
436         assert(link->network);
437         assert(link->network->tunnel);
438
439         netdev = link->network->tunnel;
440
441         assert(netdev);
442         assert(netdev->ifname);
443         assert(netdev->manager);
444         assert(netdev->manager->rtnl);
445
446         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
447         if (r < 0) {
448                 log_error_netdev(netdev,
449                                  "Could not allocate RTM_NEWLINK message: %s",
450                                  strerror(-r));
451                 return r;
452         }
453
454         switch(netdev->kind) {
455         case NETDEV_KIND_IPIP:
456                 r = netdev_fill_ipip_rtnl_message(link, m);
457                 if(r < 0)
458                         return r;
459                 break;
460         case NETDEV_KIND_SIT:
461                 r = netdev_fill_sit_rtnl_message(link, m);
462                 if(r < 0)
463                         return r;
464                 break;
465         case NETDEV_KIND_VTI:
466                 netdev_fill_vti_rtnl_message(link, m);
467                 if(r < 0)
468                         return r;
469                 break;
470         case NETDEV_KIND_GRE:
471                 r = netdev_fill_ipgre_rtnl_message(link, m);
472                 if(r < 0)
473                         return r;
474                 break;
475         default:
476                 return -ENOTSUP;
477         }
478
479         r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
480         if (r < 0) {
481                 log_error_netdev(netdev,
482                                  "Could not send rtnetlink message: %s", strerror(-r));
483                 return r;
484         }
485
486         log_debug_netdev(netdev, "Creating tunnel netdev: %s",
487                          netdev_kind_to_string(netdev->kind));
488
489         netdev->state = NETDEV_STATE_CREATING;
490
491         return 0;
492 }