]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-netdev-tuntap.c
Merge pull request #1190 from poettering/rework-virt
[thirdparty/systemd.git] / src / network / networkd-netdev-tuntap.c
CommitLineData
30ae9dfd
SS
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
3be1d7e0 26#include "networkd-netdev-tuntap.h"
30ae9dfd
SS
27
28#define TUN_DEV "/dev/net/tun"
29
30ae9dfd 30static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
aa9f1140 31 TunTap *t;
30ae9dfd
SS
32
33 assert(netdev);
aa9f1140 34 assert(netdev->ifname);
30ae9dfd
SS
35 assert(ifr);
36
aa9f1140
TG
37 if (netdev->kind == NETDEV_KIND_TAP) {
38 t = TAP(netdev);
30ae9dfd 39 ifr->ifr_flags |= IFF_TAP;
aa9f1140
TG
40 } else {
41 t = TUN(netdev);
63dadd90 42 ifr->ifr_flags |= IFF_TUN;
aa9f1140 43 }
63dadd90 44
aa9f1140 45 if (!t->packet_info)
30ae9dfd
SS
46 ifr->ifr_flags |= IFF_NO_PI;
47
aa9f1140 48 if (t->one_queue)
30ae9dfd
SS
49 ifr->ifr_flags |= IFF_ONE_QUEUE;
50
aa9f1140 51 if (t->multi_queue)
30ae9dfd
SS
52 ifr->ifr_flags |= IFF_MULTI_QUEUE;
53
f5f07dbf
SS
54 if (t->vnet_hdr)
55 ifr->ifr_flags |= IFF_VNET_HDR;
56
30ae9dfd
SS
57 strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
58
59 return 0;
60}
61
62static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
63 _cleanup_close_ int fd;
aa9f1140 64 TunTap *t = NULL;
30ae9dfd
SS
65 const char *user;
66 const char *group;
67 uid_t uid;
68 gid_t gid;
6f44acfb 69 int r;
30ae9dfd 70
aa9f1140
TG
71 assert(netdev);
72 assert(ifr);
73
30ae9dfd 74 fd = open(TUN_DEV, O_RDWR);
ce67afb0
SS
75 if (fd < 0)
76 return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m");
30ae9dfd
SS
77
78 r = ioctl(fd, TUNSETIFF, ifr);
ce67afb0
SS
79 if (r < 0)
80 return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m");
30ae9dfd 81
aa9f1140
TG
82 if (netdev->kind == NETDEV_KIND_TAP)
83 t = TAP(netdev);
84 else
85 t = TUN(netdev);
86
87 assert(t);
30ae9dfd 88
aa9f1140
TG
89 if(t->user_name) {
90
91 user = t->user_name;
30ae9dfd
SS
92
93 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
ce67afb0
SS
94 if (r < 0)
95 return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name);
30ae9dfd
SS
96
97 r = ioctl(fd, TUNSETOWNER, uid);
ce67afb0
SS
98 if (r < 0)
99 return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m");
30ae9dfd
SS
100 }
101
98b32556 102 if (t->group_name) {
30ae9dfd 103
aa9f1140 104 group = t->group_name;
30ae9dfd
SS
105
106 r = get_group_creds(&group, &gid);
ce67afb0
SS
107 if (r < 0)
108 return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name);
30ae9dfd
SS
109
110 r = ioctl(fd, TUNSETGROUP, gid);
ce67afb0
SS
111 if (r < 0)
112 return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m");
30ae9dfd
SS
113
114 }
115
116 r = ioctl(fd, TUNSETPERSIST, 1);
ce67afb0
SS
117 if (r < 0)
118 return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m");
30ae9dfd 119
6f44acfb 120 return 0;
30ae9dfd
SS
121}
122
3be1d7e0 123static int netdev_create_tuntap(NetDev *netdev) {
aa9f1140 124 struct ifreq ifr = {};
30ae9dfd
SS
125 int r;
126
30ae9dfd
SS
127 r = netdev_fill_tuntap_message(netdev, &ifr);
128 if(r < 0)
129 return r;
130
30ae9dfd
SS
131 return netdev_tuntap_add(netdev, &ifr);
132}
3be1d7e0 133
aa9f1140
TG
134static void tuntap_done(NetDev *netdev) {
135 TunTap *t = NULL;
136
137 assert(netdev);
138
139 if (netdev->kind == NETDEV_KIND_TUN)
140 t = TUN(netdev);
141 else
142 t = TAP(netdev);
143
144 assert(t);
145
146 free(t->user_name);
147 t->user_name = NULL;
148
149 free(t->group_name);
150 t->group_name = NULL;
151}
152
e0fbf1fc 153static int tuntap_verify(NetDev *netdev, const char *filename) {
e0fbf1fc
TG
154 assert(netdev);
155
98b32556
LP
156 if (netdev->mtu)
157 log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
e0fbf1fc 158
98b32556
LP
159 if (netdev->mac)
160 log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
e0fbf1fc
TG
161
162 return 0;
163}
164
3be1d7e0 165const NetDevVTable tun_vtable = {
aa9f1140
TG
166 .object_size = sizeof(TunTap),
167 .sections = "Match\0NetDev\0Tun\0",
e0fbf1fc 168 .config_verify = tuntap_verify,
aa9f1140 169 .done = tuntap_done,
3be1d7e0 170 .create = netdev_create_tuntap,
aa9f1140 171 .create_type = NETDEV_CREATE_INDEPENDENT,
3be1d7e0
TG
172};
173
174const NetDevVTable tap_vtable = {
aa9f1140
TG
175 .object_size = sizeof(TunTap),
176 .sections = "Match\0NetDev\0Tap\0",
e0fbf1fc 177 .config_verify = tuntap_verify,
aa9f1140 178 .done = tuntap_done,
3be1d7e0 179 .create = netdev_create_tuntap,
aa9f1140 180 .create_type = NETDEV_CREATE_INDEPENDENT,
3be1d7e0 181};