]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
30ae9dfd | 2 | |
dccca82b | 3 | #include <errno.h> |
634f0f98 | 4 | #include <fcntl.h> |
634f0f98 | 5 | #include <net/if.h> |
e306723e | 6 | #include <netinet/if_ether.h> |
634f0f98 ZJS |
7 | #include <sys/ioctl.h> |
8 | #include <sys/stat.h> | |
9 | #include <sys/types.h> | |
9aa5d8ba | 10 | #include <linux/if_tun.h> |
30ae9dfd | 11 | |
b5efdb8a | 12 | #include "alloc-util.h" |
3ffd4af2 | 13 | #include "fd-util.h" |
737f1405 | 14 | #include "tuntap.h" |
b1d4f8e1 | 15 | #include "user-util.h" |
30ae9dfd SS |
16 | |
17 | #define TUN_DEV "/dev/net/tun" | |
18 | ||
30ae9dfd | 19 | static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { |
aa9f1140 | 20 | TunTap *t; |
30ae9dfd SS |
21 | |
22 | assert(netdev); | |
aa9f1140 | 23 | assert(netdev->ifname); |
30ae9dfd SS |
24 | assert(ifr); |
25 | ||
aa9f1140 TG |
26 | if (netdev->kind == NETDEV_KIND_TAP) { |
27 | t = TAP(netdev); | |
30ae9dfd | 28 | ifr->ifr_flags |= IFF_TAP; |
aa9f1140 TG |
29 | } else { |
30 | t = TUN(netdev); | |
63dadd90 | 31 | ifr->ifr_flags |= IFF_TUN; |
aa9f1140 | 32 | } |
63dadd90 | 33 | |
aa9f1140 | 34 | if (!t->packet_info) |
30ae9dfd SS |
35 | ifr->ifr_flags |= IFF_NO_PI; |
36 | ||
aa9f1140 | 37 | if (t->multi_queue) |
30ae9dfd SS |
38 | ifr->ifr_flags |= IFF_MULTI_QUEUE; |
39 | ||
f5f07dbf SS |
40 | if (t->vnet_hdr) |
41 | ifr->ifr_flags |= IFF_VNET_HDR; | |
42 | ||
30ae9dfd SS |
43 | strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); |
44 | ||
45 | return 0; | |
46 | } | |
47 | ||
48 | static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { | |
49 | _cleanup_close_ int fd; | |
aa9f1140 | 50 | TunTap *t = NULL; |
30ae9dfd SS |
51 | const char *user; |
52 | const char *group; | |
53 | uid_t uid; | |
54 | gid_t gid; | |
6f44acfb | 55 | int r; |
30ae9dfd | 56 | |
aa9f1140 TG |
57 | assert(netdev); |
58 | assert(ifr); | |
59 | ||
163a035a | 60 | fd = open(TUN_DEV, O_RDWR|O_CLOEXEC); |
ce67afb0 SS |
61 | if (fd < 0) |
62 | return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m"); | |
30ae9dfd | 63 | |
ad16158c | 64 | if (ioctl(fd, TUNSETIFF, ifr) < 0) |
ce67afb0 | 65 | return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m"); |
30ae9dfd | 66 | |
aa9f1140 TG |
67 | if (netdev->kind == NETDEV_KIND_TAP) |
68 | t = TAP(netdev); | |
69 | else | |
70 | t = TUN(netdev); | |
71 | ||
72 | assert(t); | |
30ae9dfd | 73 | |
9ed794a3 | 74 | if (t->user_name) { |
aa9f1140 | 75 | user = t->user_name; |
30ae9dfd | 76 | |
fafff8f1 | 77 | r = get_user_creds(&user, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING); |
ce67afb0 SS |
78 | if (r < 0) |
79 | return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name); | |
30ae9dfd | 80 | |
ad16158c | 81 | if (ioctl(fd, TUNSETOWNER, uid) < 0) |
ce67afb0 | 82 | return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m"); |
30ae9dfd SS |
83 | } |
84 | ||
98b32556 | 85 | if (t->group_name) { |
aa9f1140 | 86 | group = t->group_name; |
30ae9dfd | 87 | |
fafff8f1 | 88 | r = get_group_creds(&group, &gid, USER_CREDS_ALLOW_MISSING); |
ce67afb0 SS |
89 | if (r < 0) |
90 | return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name); | |
30ae9dfd | 91 | |
ad16158c | 92 | if (ioctl(fd, TUNSETGROUP, gid) < 0) |
ce67afb0 | 93 | return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m"); |
30ae9dfd SS |
94 | |
95 | } | |
96 | ||
ad16158c | 97 | if (ioctl(fd, TUNSETPERSIST, 1) < 0) |
ce67afb0 | 98 | return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m"); |
30ae9dfd | 99 | |
6f44acfb | 100 | return 0; |
30ae9dfd SS |
101 | } |
102 | ||
3be1d7e0 | 103 | static int netdev_create_tuntap(NetDev *netdev) { |
aa9f1140 | 104 | struct ifreq ifr = {}; |
30ae9dfd SS |
105 | int r; |
106 | ||
30ae9dfd | 107 | r = netdev_fill_tuntap_message(netdev, &ifr); |
9ed794a3 | 108 | if (r < 0) |
30ae9dfd SS |
109 | return r; |
110 | ||
30ae9dfd SS |
111 | return netdev_tuntap_add(netdev, &ifr); |
112 | } | |
3be1d7e0 | 113 | |
aa9f1140 TG |
114 | static void tuntap_done(NetDev *netdev) { |
115 | TunTap *t = NULL; | |
116 | ||
117 | assert(netdev); | |
118 | ||
119 | if (netdev->kind == NETDEV_KIND_TUN) | |
120 | t = TUN(netdev); | |
121 | else | |
122 | t = TAP(netdev); | |
123 | ||
124 | assert(t); | |
125 | ||
a1e58e8e LP |
126 | t->user_name = mfree(t->user_name); |
127 | t->group_name = mfree(t->group_name); | |
aa9f1140 TG |
128 | } |
129 | ||
e0fbf1fc | 130 | static int tuntap_verify(NetDev *netdev, const char *filename) { |
e0fbf1fc TG |
131 | assert(netdev); |
132 | ||
4e964aa0 | 133 | if (netdev->mtu != 0) |
1df569bf YW |
134 | log_netdev_warning(netdev, |
135 | "MTUBytes= configured for %s device in %s will be ignored.\n" | |
136 | "Please set it in the corresponding .network file.", | |
137 | netdev_kind_to_string(netdev->kind), filename); | |
e0fbf1fc | 138 | |
98b32556 | 139 | if (netdev->mac) |
1df569bf YW |
140 | log_netdev_warning(netdev, |
141 | "MACAddress= configured for %s device in %s will be ignored.\n" | |
142 | "Please set it in the corresponding .network file.", | |
143 | netdev_kind_to_string(netdev->kind), filename); | |
e0fbf1fc TG |
144 | |
145 | return 0; | |
146 | } | |
147 | ||
3be1d7e0 | 148 | const NetDevVTable tun_vtable = { |
aa9f1140 | 149 | .object_size = sizeof(TunTap), |
130b812f | 150 | .sections = NETDEV_COMMON_SECTIONS "Tun\0", |
e0fbf1fc | 151 | .config_verify = tuntap_verify, |
aa9f1140 | 152 | .done = tuntap_done, |
3be1d7e0 | 153 | .create = netdev_create_tuntap, |
aa9f1140 | 154 | .create_type = NETDEV_CREATE_INDEPENDENT, |
3be1d7e0 TG |
155 | }; |
156 | ||
157 | const NetDevVTable tap_vtable = { | |
aa9f1140 | 158 | .object_size = sizeof(TunTap), |
130b812f | 159 | .sections = NETDEV_COMMON_SECTIONS "Tap\0", |
e0fbf1fc | 160 | .config_verify = tuntap_verify, |
aa9f1140 | 161 | .done = tuntap_done, |
3be1d7e0 | 162 | .create = netdev_create_tuntap, |
aa9f1140 | 163 | .create_type = NETDEV_CREATE_INDEPENDENT, |
3be1d7e0 | 164 | }; |