chiark / gitweb /
sd-network: avoid false positive compiler warning caused by LTO
[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 static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) {
133         NetDev *netdev;
134         int r;
135
136         assert(link);
137         assert(link->network);
138         assert(link->network->tunnel);
139         assert(m);
140
141         netdev = link->network->tunnel;
142
143         r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
144         if (r < 0) {
145                 log_error_netdev(netdev,
146                                  "Could not append IFLA_IFNAME, attribute: %s",
147                                  strerror(-r));
148                 return r;
149         }
150
151         if(netdev->mtu) {
152                 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
153                 if (r < 0) {
154                         log_error_netdev(netdev,
155                                          "Could not append IFLA_MTU attribute: %s",
156                                          strerror(-r));
157                         return r;
158                 }
159         }
160
161         r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
162         if (r < 0) {
163                 log_error_netdev(netdev,
164                                  "Could not append IFLA_LINKINFO attribute: %s",
165                                  strerror(-r));
166                 return r;
167         }
168
169         r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
170                                                  netdev_kind_to_string(netdev->kind));
171         if (r < 0) {
172                 log_error_netdev(netdev,
173                                  "Could not append IFLA_INFO_DATA attribute: %s",
174                                  strerror(-r));
175                 return r;
176         }
177
178         r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
179         if (r < 0) {
180                 log_error_netdev(netdev,
181                                  "Could not append IFLA_IPTUN_LINK attribute: %s",
182                                  strerror(-r));
183                 return r;
184         }
185
186         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->tunnel_local);
187         if (r < 0) {
188                 log_error_netdev(netdev,
189                                  "Could not append IFLA_IPTUN_LOCAL attribute: %s",
190                                  strerror(-r));
191                 return r;
192         }
193
194         r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->tunnel_remote);
195         if (r < 0) {
196                 log_error_netdev(netdev,
197                                  "Could not append IFLA_IPTUN_REMOTE attribute: %s",
198                                  strerror(-r));
199                 return r;
200         }
201
202         r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TOS, netdev->tunnel_tos);
203         if (r < 0) {
204                 log_error_netdev(netdev,
205                                  "Could not append IFLA_IPTUN_TOS attribute: %s",
206                                  strerror(-r));
207                 return r;
208         }
209
210         r = sd_rtnl_message_close_container(m);
211         if (r < 0) {
212                 log_error_netdev(netdev,
213                                  "Could not append IFLA_INFO_DATA attribute: %s",
214                                  strerror(-r));
215                 return r;
216         }
217
218         r = sd_rtnl_message_close_container(m);
219         if (r < 0) {
220                 log_error_netdev(netdev,
221                                  "Could not append IFLA_LINKINFO attribute: %s",
222                                  strerror(-r));
223                 return r;
224         }
225
226         return r;
227 }
228
229 int netdev_create_tunnel(Link *link, sd_rtnl_message_handler_t callback) {
230         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
231         NetDev *netdev;
232         int r;
233
234         assert(link);
235         assert(link->network);
236         assert(link->network->tunnel);
237
238         netdev = link->network->tunnel;
239
240         assert(netdev);
241         assert(netdev->ifname);
242         assert(netdev->manager);
243         assert(netdev->manager->rtnl);
244         assert(netdev->manager->kmod_ctx);
245
246         /* Load kernel module first */
247         switch(netdev->kind) {
248         case NETDEV_KIND_IPIP:
249         case NETDEV_KIND_GRE:
250         case NETDEV_KIND_SIT:
251                 r = load_module(netdev->manager->kmod_ctx,
252                                 netdev_kind_to_string(netdev->kind));
253                 if (r < 0) {
254                         log_error_netdev(netdev,
255                                          "Could not load Kernel module: %s . Ignoring",
256                                          netdev_kind_to_string(netdev->kind));
257                         return r;
258                 }
259                 break;
260         default:
261                 return -ENOTSUP;
262         }
263
264         r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
265         if (r < 0) {
266                 log_error_netdev(netdev,
267                                  "Could not allocate RTM_NEWLINK message: %s",
268                                  strerror(-r));
269                 return r;
270         }
271
272         switch(netdev->kind) {
273         case NETDEV_KIND_IPIP:
274                 r = netdev_fill_ipip_rtnl_message(link, m);
275                 if(r < 0)
276                         return r;
277                 break;
278         case NETDEV_KIND_SIT:
279                 r = netdev_fill_sit_rtnl_message(link, m);
280                 if(r < 0)
281                         return r;
282                 break;
283         case NETDEV_KIND_GRE:
284         default:
285                 return -ENOTSUP;
286         }
287
288         r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
289         if (r < 0) {
290                 log_error_netdev(netdev,
291                                  "Could not send rtnetlink message: %s", strerror(-r));
292                 return r;
293         }
294
295         log_debug_netdev(netdev, "Creating tunnel netdev: %s",
296                          netdev_kind_to_string(netdev->kind));
297
298         netdev->state = NETDEV_STATE_CREATING;
299
300         return 0;
301 }