OpenVPN
tun_afunix.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "tun.h"
30#include "fdmisc.h"
31#include "run_command.h"
32#include "manage.h"
33#include "win32.h"
34#include "wfp_block.h"
35#include "argv.h"
36#include "options.h"
37#include "socket.h"
38
39#ifndef WIN32
40/* Windows does implement some AF_UNIX functionality but key features
41 * like socketpair() and SOCK_DGRAM are missing */
42
43#include <string.h>
44#include <unistd.h>
45#include <sys/wait.h>
46#include <signal.h>
47#include <stdlib.h>
48
49
50static void
51tun_afunix_exec_child(const char *dev_node, struct tuntap *tt, struct env_set *env)
52{
53 const char *msgprefix = "ERROR: failure executing process for tun:";
54 struct argv argv = argv_new();
55
56 /* we should always called with a proper unix: dev node string */
57 ASSERT(dev_node && strncmp(dev_node, "unix:", strlen("unix:")) == 0);
58 /* since we know that dev-node starts with unix: we can just skip that
59 * to get the program name */
60 const char *program = dev_node + strlen("unix:");
61
62 argv_printf(&argv, "%s", program);
63
64 /* exit when executing fails to easier spot errors here and treat this
65 * command like an external script */
66 int flags = S_NOWAITPID | S_SCRIPT | S_FATAL;
67 tt->afunix.childprocess = openvpn_execve_check(&argv, env, flags, msgprefix);
68 if (!openvpn_waitpid_check(tt->afunix.childprocess, msgprefix, M_WARN))
69 {
70 tt->afunix.childprocess = 0;
71 }
73}
74
75void
76open_tun_afunix(struct options *o, int mtu, struct tuntap *tt, struct env_set *orig_env)
77{
78 struct gc_arena gc = gc_new();
79
80 int fds[2];
81 if (!(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0))
82 {
83 msg(M_ERR, "Cannot create socket pair for AF_UNIX socket to external "
84 "program");
85 return;
86 }
87
88
89 /* Ensure that the buffer sizes are decently sized. Otherwise macOS will
90 * just have 2048 */
91 struct socket_buffer_size newsizes = { 65536, 65536 };
92 socket_set_buffers(fds[0], &newsizes, false);
93 socket_set_buffers(fds[1], &newsizes, false);
94
95 /* Use the first file descriptor for our side and avoid passing it
96 * to the child */
97 tt->fd = fds[1];
98 set_cloexec(tt->fd);
99
100 /* Make a copy of the env, so we do not need to delete our custom
101 * environment variables later */
102 struct env_set *env = env_set_create(&gc);
103 env_set_inherit(env, orig_env);
104
105 setenv_int(env, "TUNTAP_SOCKET_FD", fds[0]);
106 setenv_str(env, "TUNTAP_DEV_TYPE", dev_type_string(o->dev, o->dev_type));
107 setenv_int(env, "TUNTAP_MTU", mtu);
109 {
110 setenv_str(env, "ifconfig_gateway", o->route_default_gateway);
111 }
112 if (o->lladdr)
113 {
114 setenv_str(env, "TUNTAP_LLADDR", o->lladdr);
115 }
116
117 tun_afunix_exec_child(o->dev_node, tt, env);
118
119 close(fds[0]);
120
121 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
122 tt->actual_name = string_alloc("internal:af_unix", NULL);
123
124 gc_free(&gc);
125}
126
127void
129{
130 ASSERT(tt);
131 if (tt->fd >= 0)
132 {
133 close(tt->fd);
134 tt->fd = 0;
135 }
136 /* only kill the child process if the PID is not 0 to avoid killing
137 * ourselves by accident */
138 if (tt->afunix.childprocess)
139 {
140 kill(tt->afunix.childprocess, SIGINT);
141 }
142
143 free(tt->actual_name);
144 free(tt);
145}
146
147ssize_t
148write_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
149{
150 const char *msg = "ERROR: failure during write to AF_UNIX socket: ";
152 {
153 tt->afunix.childprocess = 0;
154 return -ENXIO;
155 }
156
157 return write(tt->fd, buf, len);
158}
159
160ssize_t
161read_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
162{
163 const char *msg = "ERROR: failure during read from AF_UNIX socket: ";
165 {
166 tt->afunix.childprocess = 0;
167 }
168 /* do an actual read on the file descriptor even in the error case since
169 * we otherwise loop on this on this from select and spam the console
170 * with error messages */
171 return read(tt->fd, buf, len);
172}
173#else /* ifndef WIN32 */
174void
175open_tun_afunix(const char *dev, const char *dev_type, int mtu, struct tuntap *tt,
176 struct env_set env)
177{
178 msg(M_ERR, "AF_UNIX socket support not available on this platform");
179}
180
181void
182close_tun_afunix(struct tuntap *tt)
183{
184 /* should never be called as open_tun_afunix always fails */
185 ASSERT(0);
186}
187
188ssize_t
189write_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
190{
191 /* should never be called as open_tun_afunix always fails */
192 ASSERT(0);
193}
194
195ssize_t
196read_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
197{
198 /* should never be called as open_tun_afunix always fails */
199 ASSERT(0);
200}
201
202#endif /* ifndef WIN32 */
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
Definition argv.c:101
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
Definition argv.c:438
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
Definition argv.c:87
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:648
static void gc_free(struct gc_arena *a)
Definition buffer.h:1025
static struct gc_arena gc_new(void)
Definition buffer.h:1017
void setenv_int(struct env_set *es, const char *name, int value)
Definition env_set.c:291
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:307
void env_set_inherit(struct env_set *es, const struct env_set *src)
Definition env_set.c:262
struct env_set * env_set_create(struct gc_arena *gc)
Definition env_set.c:156
void set_cloexec(socket_descriptor_t fd)
Definition fdmisc.c:78
@ write
@ read
#define M_ERR
Definition error.h:106
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
#define M_WARN
Definition error.h:92
int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
bool openvpn_waitpid_check(pid_t pid, const char *msg_prefix, msglvl_t msglevel)
Checks if a running process is still running.
#define S_FATAL
Definition run_command.h:50
#define S_SCRIPT
Definition run_command.h:49
#define S_NOWAITPID
instead of waiting for child process to exit and report the status, return the pid of the child proce...
Definition run_command.h:56
void socket_set_buffers(socket_descriptor_t fd, const struct socket_buffer_size *sbs, bool reduce_size)
Sets the receive and send buffer sizes of a socket descriptor.
Definition socket.c:476
pid_t childprocess
Definition tun.h:172
Definition argv.h:35
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
const char * dev_type
Definition options.h:322
const char * route_default_gateway
Definition options.h:425
const char * dev_node
Definition options.h:323
const char * lladdr
Definition options.h:324
const char * dev
Definition options.h:321
Definition tun.h:183
char * actual_name
Definition tun.h:207
afunix_context_t afunix
Definition tun.h:250
#define SIGINT
Definition syshead.h:56
struct gc_arena gc
Definition test_ssl.c:131
const char * dev_type_string(const char *dev, const char *dev_type)
Definition tun.c:540
void open_tun_afunix(struct options *o, int mtu, struct tuntap *tt, struct env_set *orig_env)
Opens an AF_UNIX based tun device.
Definition tun_afunix.c:76
static void tun_afunix_exec_child(const char *dev_node, struct tuntap *tt, struct env_set *env)
Definition tun_afunix.c:51
ssize_t read_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
Reads a packet from a AF_UNIX based tun device.
Definition tun_afunix.c:161
void close_tun_afunix(struct tuntap *tt)
Closes the socket used for the AF_UNIX based device.
Definition tun_afunix.c:128
ssize_t write_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
Writes a packet to a AF_UNIX based tun device.
Definition tun_afunix.c:148