chiark / gitweb /
resolved: add daemon to manage resolv.conf
[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 #include <libkmod.h>
28
29 #include "sd-rtnl.h"
30 #include "networkd.h"
31 #include "network-internal.h"
32 #include "util.h"
33
34
35 static int netdev_fill_ipip_rtnl_message(Link *link, sd_rtnl_message *m) {
36         NetDev *netdev;
37         int r;
38
39         assert(link);
40         assert(link->network);
41         assert(link->network->tunnel);
42         assert(m);
43
44         netdev = link->network->tunnel;
45
46         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
47         if (r < 0) {
48                 log_error_netdev(netdev,
49                                  "Could not append IFLA_IFNAME, attribute: %s",
50                                  strerror(-r));
51                 return r;
52         }
53
54         if(netdev->mtu) {
55                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
56                 if (r < 0) {
57                         log_error_netdev(netdev,
58                                          "Could not append IFLA_MTU attribute: %s",
59                                          strerror(-r));
60                         return r;
61                 }
62         }
63
64         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
65         if (r < 0) {
66                 log_error_netdev(netdev,
67                                  "Could not append IFLA_LINKINFO attribute: %s",
68                                  strerror(-r));
69                 return r;
70         }
71
72         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
73                                                  netdev_kind_to_string(netdev->kind));
74         if (r < 0) {
75                 log_error_netdev(netdev,
76                                  "Could not append IFLA_INFO_DATA attribute: %s",
77                                  strerror(-r));
78                 return r;
79         }
80
81         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
82         if (r < 0) {
83                 log_error_netdev(netdev,
84                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
85                                  strerror(-r));
86                 return r;
87         }
88
89         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->tunnel_local);
90         if (r < 0) {
91                 log_error_netdev(netdev,
92                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
93                                  strerror(-r));
94                 return r;
95         }
96
97         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->tunnel_remote);
98         if (r < 0) {
99                 log_error_netdev(netdev,
100                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
101                                  strerror(-r));
102                 return r;
103         }
104
105         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->tunnel_ttl);
106         if (r < 0) {
107                 log_error_netdev(netdev,
108                                  "Could not append IFLA_IPTUN_TTL  attribute: %s",
109                                  strerror(-r));
110                 return r;
111         }
112
113         r = sd_rtnl_message_close_container(m);
114         if (r < 0) {
115                 log_error_netdev(netdev,
116                                  "Could not append IFLA_INFO_DATA attribute: %s",
117                                  strerror(-r));
118                 return r;
119         }
120
121         r = sd_rtnl_message_close_container(m);
122         if (r < 0) {
123                 log_error_netdev(netdev,
124                                  "Could not append IFLA_LINKINFO attribute: %s",
125                                  strerror(-r));
126                 return r;
127         }
128
129         return r;
130 }
131
132 int netdev_create_tunnel(Link *link, sd_rtnl_message_handler_t callback) {
133         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
134         NetDev *netdev;
135         int r;
136
137         assert(link);
138         assert(link->network);
139         assert(link->network->tunnel);
140
141         netdev = link->network->tunnel;
142
143         assert(netdev);
144         assert(netdev->ifname);
145         assert(netdev->manager);
146         assert(netdev->manager->rtnl);
147         assert(netdev->manager->kmod_ctx);
148
149         /* Load kernel module first */
150         switch(netdev->kind) {
151         case NETDEV_KIND_IPIP:
152         case NETDEV_KIND_GRE:
153         case NETDEV_KIND_SIT:
154                 r = load_module(netdev->manager->kmod_ctx,
155                                 netdev_kind_to_string(netdev->kind));
156                 if (r < 0) {
157                         log_error_netdev(netdev,
158                                          "Could not load Kernel module: %s . Ignoring",
159                                          netdev_kind_to_string(netdev->kind));
160                         return r;
161                 }
162                 break;
163         default:
164                 return -ENOTSUP;
165         }
166
167         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
168         if (r < 0) {
169                 log_error_netdev(netdev,
170                                  "Could not allocate RTM_NEWLINK message: %s",
171                                  strerror(-r));
172                 return r;
173         }
174
175         switch(netdev->kind) {
176         case NETDEV_KIND_IPIP:
177                 r = netdev_fill_ipip_rtnl_message(link, m);
178                 if(r < 0)
179                         return r;
180                 break;
181         case NETDEV_KIND_GRE:
182         case NETDEV_KIND_SIT:
183         default:
184                 return -ENOTSUP;
185         }
186
187         r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
188         if (r < 0) {
189                 log_error_netdev(netdev,
190                                  "Could not send rtnetlink message: %s", strerror(-r));
191                 return r;
192         }
193
194         log_debug_netdev(netdev, "Creating tunnel netdev: %s",
195                          netdev_kind_to_string(netdev->kind));
196
197         netdev->state = NETDEV_STATE_CREATING;
198
199         return 0;
200 }