1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2014 Susant Sahani <susant@redhat.com>
8 #include <linux/if_tun.h>
10 #include <netinet/if_ether.h>
11 #include <sys/ioctl.h>
13 #include <sys/types.h>
15 #include "alloc-util.h"
17 #include "netdev/tuntap.h"
18 #include "user-util.h"
20 #define TUN_DEV "/dev/net/tun"
22 static int netdev_fill_tuntap_message(NetDev
*netdev
, struct ifreq
*ifr
) {
26 assert(netdev
->ifname
);
29 if (netdev
->kind
== NETDEV_KIND_TAP
) {
31 ifr
->ifr_flags
|= IFF_TAP
;
34 ifr
->ifr_flags
|= IFF_TUN
;
38 ifr
->ifr_flags
|= IFF_NO_PI
;
41 ifr
->ifr_flags
|= IFF_ONE_QUEUE
;
44 ifr
->ifr_flags
|= IFF_MULTI_QUEUE
;
47 ifr
->ifr_flags
|= IFF_VNET_HDR
;
49 strncpy(ifr
->ifr_name
, netdev
->ifname
, IFNAMSIZ
-1);
54 static int netdev_tuntap_add(NetDev
*netdev
, struct ifreq
*ifr
) {
55 _cleanup_close_
int fd
;
66 fd
= open(TUN_DEV
, O_RDWR
);
68 return log_netdev_error_errno(netdev
, -errno
, "Failed to open tun dev: %m");
70 r
= ioctl(fd
, TUNSETIFF
, ifr
);
72 return log_netdev_error_errno(netdev
, -errno
, "TUNSETIFF failed on tun dev: %m");
74 if (netdev
->kind
== NETDEV_KIND_TAP
)
85 r
= get_user_creds(&user
, &uid
, NULL
, NULL
, NULL
);
87 return log_netdev_error_errno(netdev
, r
, "Cannot resolve user name %s: %m", t
->user_name
);
89 r
= ioctl(fd
, TUNSETOWNER
, uid
);
91 return log_netdev_error_errno(netdev
, -errno
, "TUNSETOWNER failed on tun dev: %m");
96 group
= t
->group_name
;
98 r
= get_group_creds(&group
, &gid
);
100 return log_netdev_error_errno(netdev
, r
, "Cannot resolve group name %s: %m", t
->group_name
);
102 r
= ioctl(fd
, TUNSETGROUP
, gid
);
104 return log_netdev_error_errno(netdev
, -errno
, "TUNSETGROUP failed on tun dev: %m");
108 r
= ioctl(fd
, TUNSETPERSIST
, 1);
110 return log_netdev_error_errno(netdev
, -errno
, "TUNSETPERSIST failed on tun dev: %m");
115 static int netdev_create_tuntap(NetDev
*netdev
) {
116 struct ifreq ifr
= {};
119 r
= netdev_fill_tuntap_message(netdev
, &ifr
);
123 return netdev_tuntap_add(netdev
, &ifr
);
126 static void tuntap_done(NetDev
*netdev
) {
131 if (netdev
->kind
== NETDEV_KIND_TUN
)
138 t
->user_name
= mfree(t
->user_name
);
139 t
->group_name
= mfree(t
->group_name
);
142 static int tuntap_verify(NetDev
*netdev
, const char *filename
) {
145 if (netdev
->mtu
!= 0)
146 log_netdev_warning(netdev
, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
149 log_netdev_warning(netdev
, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
154 const NetDevVTable tun_vtable
= {
155 .object_size
= sizeof(TunTap
),
156 .sections
= "Match\0NetDev\0Tun\0",
157 .config_verify
= tuntap_verify
,
159 .create
= netdev_create_tuntap
,
160 .create_type
= NETDEV_CREATE_INDEPENDENT
,
163 const NetDevVTable tap_vtable
= {
164 .object_size
= sizeof(TunTap
),
165 .sections
= "Match\0NetDev\0Tap\0",
166 .config_verify
= tuntap_verify
,
168 .create
= netdev_create_tuntap
,
169 .create_type
= NETDEV_CREATE_INDEPENDENT
,