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