2 This file is part of systemd.
4 Copyright 2014 Susant Sahani <susant@redhat.com>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/ioctl.h>
22 #include <linux/if_tun.h>
23 #include <netinet/if_ether.h>
25 #include "alloc-util.h"
27 #include "networkd-netdev-tuntap.h"
28 #include "user-util.h"
30 #define TUN_DEV "/dev/net/tun"
32 static int netdev_fill_tuntap_message(NetDev
*netdev
, struct ifreq
*ifr
) {
36 assert(netdev
->ifname
);
39 if (netdev
->kind
== NETDEV_KIND_TAP
) {
41 ifr
->ifr_flags
|= IFF_TAP
;
44 ifr
->ifr_flags
|= IFF_TUN
;
48 ifr
->ifr_flags
|= IFF_NO_PI
;
51 ifr
->ifr_flags
|= IFF_ONE_QUEUE
;
54 ifr
->ifr_flags
|= IFF_MULTI_QUEUE
;
57 ifr
->ifr_flags
|= IFF_VNET_HDR
;
59 strncpy(ifr
->ifr_name
, netdev
->ifname
, IFNAMSIZ
-1);
64 static int netdev_tuntap_add(NetDev
*netdev
, struct ifreq
*ifr
) {
65 _cleanup_close_
int fd
;
76 fd
= open(TUN_DEV
, O_RDWR
);
78 return log_netdev_error_errno(netdev
, -errno
, "Failed to open tun dev: %m");
80 r
= ioctl(fd
, TUNSETIFF
, ifr
);
82 return log_netdev_error_errno(netdev
, -errno
, "TUNSETIFF failed on tun dev: %m");
84 if (netdev
->kind
== NETDEV_KIND_TAP
)
95 r
= get_user_creds(&user
, &uid
, NULL
, NULL
, NULL
);
97 return log_netdev_error_errno(netdev
, r
, "Cannot resolve user name %s: %m", t
->user_name
);
99 r
= ioctl(fd
, TUNSETOWNER
, uid
);
101 return log_netdev_error_errno(netdev
, -errno
, "TUNSETOWNER failed on tun dev: %m");
106 group
= t
->group_name
;
108 r
= get_group_creds(&group
, &gid
);
110 return log_netdev_error_errno(netdev
, r
, "Cannot resolve group name %s: %m", t
->group_name
);
112 r
= ioctl(fd
, TUNSETGROUP
, gid
);
114 return log_netdev_error_errno(netdev
, -errno
, "TUNSETGROUP failed on tun dev: %m");
118 r
= ioctl(fd
, TUNSETPERSIST
, 1);
120 return log_netdev_error_errno(netdev
, -errno
, "TUNSETPERSIST failed on tun dev: %m");
125 static int netdev_create_tuntap(NetDev
*netdev
) {
126 struct ifreq ifr
= {};
129 r
= netdev_fill_tuntap_message(netdev
, &ifr
);
133 return netdev_tuntap_add(netdev
, &ifr
);
136 static void tuntap_done(NetDev
*netdev
) {
141 if (netdev
->kind
== NETDEV_KIND_TUN
)
148 t
->user_name
= mfree(t
->user_name
);
149 t
->group_name
= mfree(t
->group_name
);
152 static int tuntap_verify(NetDev
*netdev
, const char *filename
) {
156 log_netdev_warning(netdev
, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
159 log_netdev_warning(netdev
, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
164 const NetDevVTable tun_vtable
= {
165 .object_size
= sizeof(TunTap
),
166 .sections
= "Match\0NetDev\0Tun\0",
167 .config_verify
= tuntap_verify
,
169 .create
= netdev_create_tuntap
,
170 .create_type
= NETDEV_CREATE_INDEPENDENT
,
173 const NetDevVTable tap_vtable
= {
174 .object_size
= sizeof(TunTap
),
175 .sections
= "Match\0NetDev\0Tap\0",
176 .config_verify
= tuntap_verify
,
178 .create
= netdev_create_tuntap
,
179 .create_type
= NETDEV_CREATE_INDEPENDENT
,