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-2025 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
65 if (!openvpn_waitpid_check(tt->afunix.childprocess, msgprefix, M_WARN))
66 {
67 tt->afunix.childprocess = 0;
68 }
70}
71
72void
73open_tun_afunix(struct options *o, int mtu, struct tuntap *tt, struct env_set *orig_env)
74{
75 struct gc_arena gc = gc_new();
76
77 int fds[2];
78 if (!(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0))
79 {
80 msg(M_ERR, "Cannot create socket pair for AF_UNIX socket to external "
81 "program");
82 return;
83 }
84
85
86 /* Ensure that the buffer sizes are decently sized. Otherwise macOS will
87 * just have 2048 */
88 struct socket_buffer_size newsizes = { 65536, 65536 };
89 socket_set_buffers(fds[0], &newsizes, false);
90 socket_set_buffers(fds[1], &newsizes, false);
91
92 /* Use the first file descriptor for our side and avoid passing it
93 * to the child */
94 tt->fd = fds[1];
95 set_cloexec(tt->fd);
96
97 /* Make a copy of the env, so we do not need to delete our custom
98 * environment variables later */
99 struct env_set *env = env_set_create(&gc);
100 env_set_inherit(env, orig_env);
101
102 setenv_int(env, "TUNTAP_SOCKET_FD", fds[0]);
103 setenv_str(env, "TUNTAP_DEV_TYPE", dev_type_string(o->dev, o->dev_type));
104 setenv_int(env, "TUNTAP_MTU", mtu);
106 {
107 setenv_str(env, "ifconfig_gateway", o->route_default_gateway);
108 }
109 if (o->lladdr)
110 {
111 setenv_str(env, "TUNTAP_LLADDR", o->lladdr);
112 }
113
114 tun_afunix_exec_child(o->dev_node, tt, env);
115
116 close(fds[0]);
117
118 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
119 tt->actual_name = string_alloc("internal:af_unix", NULL);
120
121 gc_free(&gc);
122}
123
124void
126{
127 ASSERT(tt);
128 if (tt->fd >= 0)
129 {
130 close(tt->fd);
131 tt->fd = 0;
132 }
133 /* only kill the child process if the PID is not 0 to avoid killing
134 * ourselves by accident */
135 if (tt->afunix.childprocess)
136 {
137 kill(tt->afunix.childprocess, SIGINT);
138 }
139
140 free(tt->actual_name);
141 free(tt);
142}
143
144ssize_t
145write_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
146{
147 const char *msg = "ERROR: failure during write to AF_UNIX socket: ";
149 {
150 tt->afunix.childprocess = 0;
151 return -ENXIO;
152 }
153
154 return write(tt->fd, buf, len);
155}
156
157ssize_t
158read_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
159{
160 const char *msg = "ERROR: failure during read from AF_UNIX socket: ";
162 {
163 tt->afunix.childprocess = 0;
164 }
165 /* do an actual read on the file descriptor even in the error case since
166 * we otherwise loop on this on this from select and spam the console
167 * with error messages */
168 return read(tt->fd, buf, len);
169}
170#else /* ifndef WIN32 */
171void
172open_tun_afunix(const char *dev, const char *dev_type, int mtu, struct tuntap *tt,
173 struct env_set env)
174{
175 msg(M_ERR, "AF_UNIX socket support not available on this platform");
176}
177
178void
179close_tun_afunix(struct tuntap *tt)
180{
181 /* should never be called as open_tun_afunix always fails */
182 ASSERT(0);
183}
184
185ssize_t
186write_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
187{
188 /* should never be called as open_tun_afunix always fails */
189 ASSERT(0);
190}
191
192ssize_t
193read_tun_afunix(struct tuntap *tt, uint8_t *buf, int len)
194{
195 /* should never be called as open_tun_afunix always fails */
196 ASSERT(0);
197}
198
199#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:649
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_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:471
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:428
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
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:73
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:158
void close_tun_afunix(struct tuntap *tt)
Closes the socket used for the AF_UNIX based device.
Definition tun_afunix.c:125
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:145