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