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>
24 #include "alloc-util.h"
26 #include "networkd-netdev-tuntap.h"
27 #include "user-util.h"
29 #define TUN_DEV "/dev/net/tun"
31 static int netdev_fill_tuntap_message(NetDev
*netdev
, struct ifreq
*ifr
) {
35 assert(netdev
->ifname
);
38 if (netdev
->kind
== NETDEV_KIND_TAP
) {
40 ifr
->ifr_flags
|= IFF_TAP
;
43 ifr
->ifr_flags
|= IFF_TUN
;
47 ifr
->ifr_flags
|= IFF_NO_PI
;
50 ifr
->ifr_flags
|= IFF_ONE_QUEUE
;
53 ifr
->ifr_flags
|= IFF_MULTI_QUEUE
;
56 ifr
->ifr_flags
|= IFF_VNET_HDR
;
58 strncpy(ifr
->ifr_name
, netdev
->ifname
, IFNAMSIZ
-1);
63 static int netdev_tuntap_add(NetDev
*netdev
, struct ifreq
*ifr
) {
64 _cleanup_close_
int fd
;
75 fd
= open(TUN_DEV
, O_RDWR
);
77 return log_netdev_error_errno(netdev
, -errno
, "Failed to open tun dev: %m");
79 r
= ioctl(fd
, TUNSETIFF
, ifr
);
81 return log_netdev_error_errno(netdev
, -errno
, "TUNSETIFF failed on tun dev: %m");
83 if (netdev
->kind
== NETDEV_KIND_TAP
)
94 r
= get_user_creds(&user
, &uid
, NULL
, NULL
, NULL
);
96 return log_netdev_error_errno(netdev
, r
, "Cannot resolve user name %s: %m", t
->user_name
);
98 r
= ioctl(fd
, TUNSETOWNER
, uid
);
100 return log_netdev_error_errno(netdev
, -errno
, "TUNSETOWNER failed on tun dev: %m");
105 group
= t
->group_name
;
107 r
= get_group_creds(&group
, &gid
);
109 return log_netdev_error_errno(netdev
, r
, "Cannot resolve group name %s: %m", t
->group_name
);
111 r
= ioctl(fd
, TUNSETGROUP
, gid
);
113 return log_netdev_error_errno(netdev
, -errno
, "TUNSETGROUP failed on tun dev: %m");
117 r
= ioctl(fd
, TUNSETPERSIST
, 1);
119 return log_netdev_error_errno(netdev
, -errno
, "TUNSETPERSIST failed on tun dev: %m");
124 static int netdev_create_tuntap(NetDev
*netdev
) {
125 struct ifreq ifr
= {};
128 r
= netdev_fill_tuntap_message(netdev
, &ifr
);
132 return netdev_tuntap_add(netdev
, &ifr
);
135 static void tuntap_done(NetDev
*netdev
) {
140 if (netdev
->kind
== NETDEV_KIND_TUN
)
147 t
->user_name
= mfree(t
->user_name
);
148 t
->group_name
= mfree(t
->group_name
);
151 static int tuntap_verify(NetDev
*netdev
, const char *filename
) {
155 log_netdev_warning(netdev
, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
158 log_netdev_warning(netdev
, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
163 const NetDevVTable tun_vtable
= {
164 .object_size
= sizeof(TunTap
),
165 .sections
= "Match\0NetDev\0Tun\0",
166 .config_verify
= tuntap_verify
,
168 .create
= netdev_create_tuntap
,
169 .create_type
= NETDEV_CREATE_INDEPENDENT
,
172 const NetDevVTable tap_vtable
= {
173 .object_size
= sizeof(TunTap
),
174 .sections
= "Match\0NetDev\0Tap\0",
175 .config_verify
= tuntap_verify
,
177 .create
= netdev_create_tuntap
,
178 .create_type
= NETDEV_CREATE_INDEPENDENT
,