]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-tunnel.c
networkd: sit-tunnel add support for pmtudisc
[thirdparty/systemd.git] / src / network / networkd-tunnel.c
CommitLineData
7951dea2
SS
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
35static 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
af4e9e2c 46 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
7951dea2
SS
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
9ae70211
SS
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
7951dea2
SS
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
abf446af
SS
132static 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
a9f434cf
SS
210 r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, netdev->tunnel_pmtudisc);
211 if (r < 0) {
212 log_error_netdev(netdev,
213 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
214 strerror(-r));
215 return r;
216 }
217
abf446af
SS
218 r = sd_rtnl_message_close_container(m);
219 if (r < 0) {
220 log_error_netdev(netdev,
221 "Could not append IFLA_INFO_DATA attribute: %s",
222 strerror(-r));
223 return r;
224 }
225
226 r = sd_rtnl_message_close_container(m);
227 if (r < 0) {
228 log_error_netdev(netdev,
229 "Could not append IFLA_LINKINFO attribute: %s",
230 strerror(-r));
231 return r;
232 }
233
234 return r;
235}
236
8bb088c5
SS
237static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) {
238 NetDev *netdev;
239 int r;
240
241 assert(link);
242 assert(link->network);
243 assert(link->network->tunnel);
244 assert(m);
245
246 netdev = link->network->tunnel;
247
248 r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
249 if (r < 0) {
250 log_error_netdev(netdev,
251 "Could not append IFLA_IFNAME, attribute: %s",
252 strerror(-r));
253 return r;
254 }
255
256 if(netdev->mtu) {
257 r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
258 if (r < 0) {
259 log_error_netdev(netdev,
260 "Could not append IFLA_MTU attribute: %s",
261 strerror(-r));
262 return r;
263 }
264 }
265
266 r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
267 if (r < 0) {
268 log_error_netdev(netdev,
269 "Could not append IFLA_LINKINFO attribute: %s",
270 strerror(-r));
271 return r;
272 }
273
274 r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
275 netdev_kind_to_string(netdev->kind));
276 if (r < 0) {
277 log_error_netdev(netdev,
278 "Could not append IFLA_INFO_DATA attribute: %s",
279 strerror(-r));
280 return r;
281 }
282
283 r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
284 if (r < 0) {
285 log_error_netdev(netdev,
286 "Could not append IFLA_GRE_LINK attribute: %s",
287 strerror(-r));
288 return r;
289 }
290
291 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->tunnel_local);
292 if (r < 0) {
293 log_error_netdev(netdev,
294 "Could not append IFLA_GRE_LOCAL attribute: %s",
295 strerror(-r));
296 return r;
297 }
298
299 r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->tunnel_remote);
300 if (r < 0) {
301 log_error_netdev(netdev,
302 "Could not append IFLA_GRE_REMOTE attribute: %s",
303 strerror(-r));
304 return r;
305 }
306
307 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->tunnel_ttl);
308 if (r < 0) {
309 log_error_netdev(netdev,
310 "Could not append IFLA_GRE_TTL attribute: %s",
311 strerror(-r));
312 return r;
313 }
314
315 r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tunnel_tos);
316 if (r < 0) {
317 log_error_netdev(netdev,
318 "Could not append IFLA_GRE_TOS attribute: %s",
319 strerror(-r));
320 return r;
321 }
322
323 r = sd_rtnl_message_close_container(m);
324 if (r < 0) {
325 log_error_netdev(netdev,
326 "Could not append IFLA_INFO_DATA attribute: %s",
327 strerror(-r));
328 return r;
329 }
330
331 r = sd_rtnl_message_close_container(m);
332 if (r < 0) {
333 log_error_netdev(netdev,
334 "Could not append IFLA_LINKINFO attribute: %s",
335 strerror(-r));
336 return r;
337 }
338
339 return r;
340}
341
342
7951dea2
SS
343int netdev_create_tunnel(Link *link, sd_rtnl_message_handler_t callback) {
344 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
345 NetDev *netdev;
346 int r;
347
348 assert(link);
349 assert(link->network);
350 assert(link->network->tunnel);
351
352 netdev = link->network->tunnel;
353
354 assert(netdev);
af4e9e2c 355 assert(netdev->ifname);
7951dea2
SS
356 assert(netdev->manager);
357 assert(netdev->manager->rtnl);
358 assert(netdev->manager->kmod_ctx);
359
360 /* Load kernel module first */
361 switch(netdev->kind) {
362 case NETDEV_KIND_IPIP:
363 case NETDEV_KIND_GRE:
364 case NETDEV_KIND_SIT:
365 r = load_module(netdev->manager->kmod_ctx,
366 netdev_kind_to_string(netdev->kind));
367 if (r < 0) {
368 log_error_netdev(netdev,
369 "Could not load Kernel module: %s . Ignoring",
370 netdev_kind_to_string(netdev->kind));
371 return r;
372 }
373 break;
374 default:
375 return -ENOTSUP;
376 }
377
378 r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
379 if (r < 0) {
380 log_error_netdev(netdev,
381 "Could not allocate RTM_NEWLINK message: %s",
382 strerror(-r));
383 return r;
384 }
385
386 switch(netdev->kind) {
387 case NETDEV_KIND_IPIP:
388 r = netdev_fill_ipip_rtnl_message(link, m);
389 if(r < 0)
390 return r;
391 break;
7951dea2 392 case NETDEV_KIND_SIT:
abf446af
SS
393 r = netdev_fill_sit_rtnl_message(link, m);
394 if(r < 0)
395 return r;
396 break;
397 case NETDEV_KIND_GRE:
8bb088c5
SS
398 r = netdev_fill_ipgre_rtnl_message(link, m);
399 if(r < 0)
400 return r;
401 break;
7951dea2
SS
402 default:
403 return -ENOTSUP;
404 }
405
406 r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
407 if (r < 0) {
408 log_error_netdev(netdev,
409 "Could not send rtnetlink message: %s", strerror(-r));
410 return r;
411 }
412
413 log_debug_netdev(netdev, "Creating tunnel netdev: %s",
414 netdev_kind_to_string(netdev->kind));
415
416 netdev->state = NETDEV_STATE_CREATING;
417
418 return 0;
419}