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