]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/netdev/tuntap.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / network / netdev / tuntap.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 Copyright 2014 Susant Sahani <susant@redhat.com>
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/if_tun.h>
9 #include <net/if.h>
10 #include <netinet/if_ether.h>
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14
15 #include "alloc-util.h"
16 #include "fd-util.h"
17 #include "netdev/tuntap.h"
18 #include "user-util.h"
19
20 #define TUN_DEV "/dev/net/tun"
21
22 static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
23 TunTap *t;
24
25 assert(netdev);
26 assert(netdev->ifname);
27 assert(ifr);
28
29 if (netdev->kind == NETDEV_KIND_TAP) {
30 t = TAP(netdev);
31 ifr->ifr_flags |= IFF_TAP;
32 } else {
33 t = TUN(netdev);
34 ifr->ifr_flags |= IFF_TUN;
35 }
36
37 if (!t->packet_info)
38 ifr->ifr_flags |= IFF_NO_PI;
39
40 if (t->one_queue)
41 ifr->ifr_flags |= IFF_ONE_QUEUE;
42
43 if (t->multi_queue)
44 ifr->ifr_flags |= IFF_MULTI_QUEUE;
45
46 if (t->vnet_hdr)
47 ifr->ifr_flags |= IFF_VNET_HDR;
48
49 strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
50
51 return 0;
52 }
53
54 static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
55 _cleanup_close_ int fd;
56 TunTap *t = NULL;
57 const char *user;
58 const char *group;
59 uid_t uid;
60 gid_t gid;
61 int r;
62
63 assert(netdev);
64 assert(ifr);
65
66 fd = open(TUN_DEV, O_RDWR);
67 if (fd < 0)
68 return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m");
69
70 r = ioctl(fd, TUNSETIFF, ifr);
71 if (r < 0)
72 return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m");
73
74 if (netdev->kind == NETDEV_KIND_TAP)
75 t = TAP(netdev);
76 else
77 t = TUN(netdev);
78
79 assert(t);
80
81 if (t->user_name) {
82
83 user = t->user_name;
84
85 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
86 if (r < 0)
87 return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name);
88
89 r = ioctl(fd, TUNSETOWNER, uid);
90 if (r < 0)
91 return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m");
92 }
93
94 if (t->group_name) {
95
96 group = t->group_name;
97
98 r = get_group_creds(&group, &gid);
99 if (r < 0)
100 return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name);
101
102 r = ioctl(fd, TUNSETGROUP, gid);
103 if (r < 0)
104 return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m");
105
106 }
107
108 r = ioctl(fd, TUNSETPERSIST, 1);
109 if (r < 0)
110 return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m");
111
112 return 0;
113 }
114
115 static int netdev_create_tuntap(NetDev *netdev) {
116 struct ifreq ifr = {};
117 int r;
118
119 r = netdev_fill_tuntap_message(netdev, &ifr);
120 if (r < 0)
121 return r;
122
123 return netdev_tuntap_add(netdev, &ifr);
124 }
125
126 static void tuntap_done(NetDev *netdev) {
127 TunTap *t = NULL;
128
129 assert(netdev);
130
131 if (netdev->kind == NETDEV_KIND_TUN)
132 t = TUN(netdev);
133 else
134 t = TAP(netdev);
135
136 assert(t);
137
138 t->user_name = mfree(t->user_name);
139 t->group_name = mfree(t->group_name);
140 }
141
142 static int tuntap_verify(NetDev *netdev, const char *filename) {
143 assert(netdev);
144
145 if (netdev->mtu != 0)
146 log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
147
148 if (netdev->mac)
149 log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
150
151 return 0;
152 }
153
154 const NetDevVTable tun_vtable = {
155 .object_size = sizeof(TunTap),
156 .sections = "Match\0NetDev\0Tun\0",
157 .config_verify = tuntap_verify,
158 .done = tuntap_done,
159 .create = netdev_create_tuntap,
160 .create_type = NETDEV_CREATE_INDEPENDENT,
161 };
162
163 const NetDevVTable tap_vtable = {
164 .object_size = sizeof(TunTap),
165 .sections = "Match\0NetDev\0Tap\0",
166 .config_verify = tuntap_verify,
167 .done = tuntap_done,
168 .create = netdev_create_tuntap,
169 .create_type = NETDEV_CREATE_INDEPENDENT,
170 };