Go to the documentation of this file.
37 #include <sys/types.h>
38 #include <sys/socket.h>
48 #define DEBUG(verb) ((verb) >= 7)
51 #define COMMAND_RUN_SCRIPT 1
52 #define COMMAND_EXIT 2
55 #define RESPONSE_INIT_SUCCEEDED 10
56 #define RESPONSE_INIT_FAILED 11
57 #define RESPONSE_SCRIPT_SUCCEEDED 12
58 #define RESPONSE_SCRIPT_FAILED 13
61 static void down_root_server(
const int fd,
char *
const *
argv,
char *
const *envp,
const int verb);
87 get_env(
const char *name,
const char *envp[])
92 const int namelen = strlen(name);
93 for (i = 0; envp[i]; ++i)
95 if (!strncmp(envp[i], name, namelen))
97 const char *cp = envp[i] + namelen;
133 const ssize_t size =
read(fd, &c,
sizeof(c));
134 if (size ==
sizeof(c))
147 unsigned char c = (
unsigned char) code;
148 const ssize_t size =
write(fd, &c,
sizeof(c));
149 if (size ==
sizeof(c))
167 const char *daemon_string =
get_env(
"daemon", envp);
168 if (daemon_string && daemon_string[0] ==
'1')
170 const char *log_redirect =
get_env(
"daemon_log_redirect", envp);
172 if (log_redirect && log_redirect[0] ==
'1')
176 #if defined(__APPLE__) && defined(__clang__)
177 #pragma clang diagnostic push
178 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
182 warn(
"DOWN-ROOT: daemonization failed");
184 #if defined(__APPLE__) && defined(__clang__)
185 #pragma clang diagnostic pop
210 for (i = 3; i <= 100; ++i)
226 signal(SIGTERM, SIG_DFL);
228 signal(SIGINT, SIG_IGN);
229 signal(SIGHUP, SIG_IGN);
230 signal(SIGUSR1, SIG_IGN);
231 signal(SIGUSR2, SIG_IGN);
232 signal(SIGPIPE, SIG_IGN);
261 err(127,
"DOWN-ROOT: Failed execute: %s",
argv[0]);
263 else if (pid < (pid_t)0)
265 warn(
"DOWN-ROOT: Failed to fork child to run %s",
argv[0]);
270 if (waitpid(pid, &ret, 0) != pid)
273 fprintf(stderr,
"DOWN-ROOT: waitpid() failed, don't know exit code of child (%s)\n",
argv[0]);
292 warn(
"DOWN-ROOT: Could not allocate memory for plug-in context");
308 fprintf(stderr,
"DOWN-ROOT: need down script command\n");
318 warn(
"DOWN-ROOT: Could not allocate memory for command array");
332 const char *verb_string =
get_env(
"verb", envp);
335 context->verb = atoi(verb_string);
360 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
362 warn(
"DOWN-ROOT: socketpair call failed");
386 if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0)
388 warn(
"DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
395 context->foreground_fd = fd[0];
426 warn(
"DOWN-ROOT: Error sending script execution signal to background process");
437 warn(
"DOWN-ROOT: Error receiving script execution confirmation from background process");
451 fprintf(stderr,
"DOWN-ROOT: close\n");
454 if (
context->foreground_fd >= 0)
459 warn(
"DOWN-ROOT: Error signalling background process to exit");
463 if (
context->background_pid > 0)
465 waitpid(
context->background_pid, NULL, 0);
500 fprintf(stderr,
"DOWN-ROOT: BACKGROUND: INIT command='%s'\n",
argv[0]);
508 warn(
"DOWN-ROOT: BACKGROUND: write error on response socket [1]");
525 fprintf(stderr,
"DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
528 switch (command_code)
535 warn(
"DOWN-ROOT: BACKGROUND: write error on response socket [2]");
541 fprintf(stderr,
"DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n",
argv[0], exit_code);
544 warn(
"DOWN-ROOT: BACKGROUND: write error on response socket [3]");
554 warn(
"DOWN-ROOT: BACKGROUND: read error on command channel");
558 fprintf(stderr,
"DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
567 fprintf(stderr,
"DOWN-ROOT: BACKGROUND: EXIT\n");
#define OPENVPN_PLUGIN_UP
static void down_root_server(const int fd, char *const *argv, char *const *envp, const int verb)
#define OPENVPN_PLUGIN_DOWN
Contains all state information for one tunnel.
static void daemonize(const char *envp[])
#define RESPONSE_SCRIPT_FAILED
#define COMMAND_RUN_SCRIPT
static void free_context(struct down_root_context *context)
#define OPENVPN_PLUGIN_MASK(x)
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
This cleans up the last part of the plug-in, allows it to shut down cleanly and release the plug-in g...
#define OPENVPN_PLUGIN_FUNC_ERROR
OPENVPN_EXPORT int openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
This function is called by OpenVPN each time the OpenVPN reaches a point where plug-in calls should h...
static void set_signals(void)
#define RESPONSE_INIT_SUCCEEDED
static int send_control(int fd, int code)
OPENVPN_EXPORT void openvpn_plugin_abort_v1(openvpn_plugin_handle_t handle)
int daemon(int nochdir, int noclose)
static int recv_control(int fd)
static SERVICE_STATUS status
#define OPENVPN_PLUGIN_FUNC_SUCCESS
static const char * get_env(const char *name, const char *envp[])
static int string_array_len(const char *array[])
static void close_fds_except(int keep)
OPENVPN_EXPORT openvpn_plugin_handle_t openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
void * openvpn_plugin_handle_t
#define RESPONSE_SCRIPT_SUCCEEDED
static int run_script(char *const *argv, char *const *envp)