1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Susant Sahani <susant@redhat.com>
10 #include <linux/if_tun.h>
12 #include <netinet/if_ether.h>
13 #include <sys/ioctl.h>
15 #include <sys/types.h>
17 #include "alloc-util.h"
19 #include "netdev/tuntap.h"
20 #include "user-util.h"
22 #define TUN_DEV "/dev/net/tun"
24 static int netdev_fill_tuntap_message(NetDev
*netdev
, struct ifreq
*ifr
) {
28 assert(netdev
->ifname
);
31 if (netdev
->kind
== NETDEV_KIND_TAP
) {
33 ifr
->ifr_flags
|= IFF_TAP
;
36 ifr
->ifr_flags
|= IFF_TUN
;
40 ifr
->ifr_flags
|= IFF_NO_PI
;
43 ifr
->ifr_flags
|= IFF_ONE_QUEUE
;
46 ifr
->ifr_flags
|= IFF_MULTI_QUEUE
;
49 ifr
->ifr_flags
|= IFF_VNET_HDR
;
51 strncpy(ifr
->ifr_name
, netdev
->ifname
, IFNAMSIZ
-1);
56 static int netdev_tuntap_add(NetDev
*netdev
, struct ifreq
*ifr
) {
57 _cleanup_close_
int fd
;
68 fd
= open(TUN_DEV
, O_RDWR
);
70 return log_netdev_error_errno(netdev
, -errno
, "Failed to open tun dev: %m");
72 r
= ioctl(fd
, TUNSETIFF
, ifr
);
74 return log_netdev_error_errno(netdev
, -errno
, "TUNSETIFF failed on tun dev: %m");
76 if (netdev
->kind
== NETDEV_KIND_TAP
)
87 r
= get_user_creds(&user
, &uid
, NULL
, NULL
, NULL
);
89 return log_netdev_error_errno(netdev
, r
, "Cannot resolve user name %s: %m", t
->user_name
);
91 r
= ioctl(fd
, TUNSETOWNER
, uid
);
93 return log_netdev_error_errno(netdev
, -errno
, "TUNSETOWNER failed on tun dev: %m");
98 group
= t
->group_name
;
100 r
= get_group_creds(&group
, &gid
);
102 return log_netdev_error_errno(netdev
, r
, "Cannot resolve group name %s: %m", t
->group_name
);
104 r
= ioctl(fd
, TUNSETGROUP
, gid
);
106 return log_netdev_error_errno(netdev
, -errno
, "TUNSETGROUP failed on tun dev: %m");
110 r
= ioctl(fd
, TUNSETPERSIST
, 1);
112 return log_netdev_error_errno(netdev
, -errno
, "TUNSETPERSIST failed on tun dev: %m");
117 static int netdev_create_tuntap(NetDev
*netdev
) {
118 struct ifreq ifr
= {};
121 r
= netdev_fill_tuntap_message(netdev
, &ifr
);
125 return netdev_tuntap_add(netdev
, &ifr
);
128 static void tuntap_done(NetDev
*netdev
) {
133 if (netdev
->kind
== NETDEV_KIND_TUN
)
140 t
->user_name
= mfree(t
->user_name
);
141 t
->group_name
= mfree(t
->group_name
);
144 static int tuntap_verify(NetDev
*netdev
, const char *filename
) {
148 log_netdev_warning(netdev
, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
151 log_netdev_warning(netdev
, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev
->kind
));
156 const NetDevVTable tun_vtable
= {
157 .object_size
= sizeof(TunTap
),
158 .sections
= "Match\0NetDev\0Tun\0",
159 .config_verify
= tuntap_verify
,
161 .create
= netdev_create_tuntap
,
162 .create_type
= NETDEV_CREATE_INDEPENDENT
,
165 const NetDevVTable tap_vtable
= {
166 .object_size
= sizeof(TunTap
),
167 .sections
= "Match\0NetDev\0Tap\0",
168 .config_verify
= tuntap_verify
,
170 .create
= netdev_create_tuntap
,
171 .create_type
= NETDEV_CREATE_INDEPENDENT
,