]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-netdev-tuntap.c
util-lib: split out user/group/uid/gid calls into user-util.[ch]
[thirdparty/systemd.git] / src / network / networkd-netdev-tuntap.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Susant Sahani <susant@redhat.com>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/ioctl.h>
23 #include <net/if.h>
24 #include <linux/if_tun.h>
25
26 #include "fd-util.h"
27 #include "networkd-netdev-tuntap.h"
28 #include "user-util.h"
29
30 #define TUN_DEV "/dev/net/tun"
31
32 static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
33 TunTap *t;
34
35 assert(netdev);
36 assert(netdev->ifname);
37 assert(ifr);
38
39 if (netdev->kind == NETDEV_KIND_TAP) {
40 t = TAP(netdev);
41 ifr->ifr_flags |= IFF_TAP;
42 } else {
43 t = TUN(netdev);
44 ifr->ifr_flags |= IFF_TUN;
45 }
46
47 if (!t->packet_info)
48 ifr->ifr_flags |= IFF_NO_PI;
49
50 if (t->one_queue)
51 ifr->ifr_flags |= IFF_ONE_QUEUE;
52
53 if (t->multi_queue)
54 ifr->ifr_flags |= IFF_MULTI_QUEUE;
55
56 if (t->vnet_hdr)
57 ifr->ifr_flags |= IFF_VNET_HDR;
58
59 strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
60
61 return 0;
62 }
63
64 static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
65 _cleanup_close_ int fd;
66 TunTap *t = NULL;
67 const char *user;
68 const char *group;
69 uid_t uid;
70 gid_t gid;
71 int r;
72
73 assert(netdev);
74 assert(ifr);
75
76 fd = open(TUN_DEV, O_RDWR);
77 if (fd < 0)
78 return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m");
79
80 r = ioctl(fd, TUNSETIFF, ifr);
81 if (r < 0)
82 return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m");
83
84 if (netdev->kind == NETDEV_KIND_TAP)
85 t = TAP(netdev);
86 else
87 t = TUN(netdev);
88
89 assert(t);
90
91 if(t->user_name) {
92
93 user = t->user_name;
94
95 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
96 if (r < 0)
97 return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name);
98
99 r = ioctl(fd, TUNSETOWNER, uid);
100 if (r < 0)
101 return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m");
102 }
103
104 if (t->group_name) {
105
106 group = t->group_name;
107
108 r = get_group_creds(&group, &gid);
109 if (r < 0)
110 return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name);
111
112 r = ioctl(fd, TUNSETGROUP, gid);
113 if (r < 0)
114 return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m");
115
116 }
117
118 r = ioctl(fd, TUNSETPERSIST, 1);
119 if (r < 0)
120 return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m");
121
122 return 0;
123 }
124
125 static int netdev_create_tuntap(NetDev *netdev) {
126 struct ifreq ifr = {};
127 int r;
128
129 r = netdev_fill_tuntap_message(netdev, &ifr);
130 if(r < 0)
131 return r;
132
133 return netdev_tuntap_add(netdev, &ifr);
134 }
135
136 static void tuntap_done(NetDev *netdev) {
137 TunTap *t = NULL;
138
139 assert(netdev);
140
141 if (netdev->kind == NETDEV_KIND_TUN)
142 t = TUN(netdev);
143 else
144 t = TAP(netdev);
145
146 assert(t);
147
148 t->user_name = mfree(t->user_name);
149 t->group_name = mfree(t->group_name);
150 }
151
152 static int tuntap_verify(NetDev *netdev, const char *filename) {
153 assert(netdev);
154
155 if (netdev->mtu)
156 log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
157
158 if (netdev->mac)
159 log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
160
161 return 0;
162 }
163
164 const NetDevVTable tun_vtable = {
165 .object_size = sizeof(TunTap),
166 .sections = "Match\0NetDev\0Tun\0",
167 .config_verify = tuntap_verify,
168 .done = tuntap_done,
169 .create = netdev_create_tuntap,
170 .create_type = NETDEV_CREATE_INDEPENDENT,
171 };
172
173 const NetDevVTable tap_vtable = {
174 .object_size = sizeof(TunTap),
175 .sections = "Match\0NetDev\0Tap\0",
176 .config_verify = tuntap_verify,
177 .done = tuntap_done,
178 .create = netdev_create_tuntap,
179 .create_type = NETDEV_CREATE_INDEPENDENT,
180 };