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