OpenVPN
sample-client-connect.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-2024 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, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 /*
25  * This file implements a simple OpenVPN plugin module which
26  * will log the calls made, and send back some config statements
27  * when called on the CLIENT_CONNECT and CLIENT_CONNECT_V2 hooks.
28  *
29  * it can be asked to fail or go to async/deferred mode by setting
30  * environment variables (UV_WANT_CC_FAIL, UV_WANT_CC_ASYNC,
31  * UV_WANT_CC2_ASYNC) - mostly used as a testing vehicle for the
32  * server side code to handle these cases
33  *
34  * See the README file for build instructions and env control variables.
35  */
36 
37 /* strdup() might need special defines to be visible in <string.h> */
38 #include "config.h"
39 
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <stdbool.h>
44 #include <unistd.h>
45 #include <fcntl.h>
46 #include <sys/wait.h>
47 
48 #include "openvpn-plugin.h"
49 
50 /* Pointers to functions exported from openvpn */
51 static plugin_log_t plugin_log = NULL;
54 
55 /* module name for plugin_log() */
56 static char *MODULE = "sample-cc";
57 
58 /*
59  * Our context, where we keep our state.
60  */
61 
63  int verb; /* logging verbosity */
64 };
65 
66 /* this is used for the CLIENT_CONNECT_V2 async/deferred handler
67  *
68  * the "CLIENT_CONNECT_V2" handler puts per-client information into
69  * this, and the "CLIENT_CONNECT_DEFER_V2" handler looks at it to see
70  * if it's time yet to succeed/fail
71  */
73  time_t sleep_until; /* wakeup time (time() + sleep) */
74  bool want_fail;
76  const char *client_config;
77 };
78 
79 /*
80  * Given an environmental variable name, search
81  * the envp array for its value, returning it
82  * if found or NULL otherwise.
83  */
84 static const char *
85 get_env(const char *name, const char *envp[])
86 {
87  if (envp)
88  {
89  int i;
90  const int namelen = strlen(name);
91  for (i = 0; envp[i]; ++i)
92  {
93  if (!strncmp(envp[i], name, namelen))
94  {
95  const char *cp = envp[i] + namelen;
96  if (*cp == '=')
97  {
98  return cp + 1;
99  }
100  }
101  }
102  }
103  return NULL;
104 }
105 
106 
107 static int
108 atoi_null0(const char *str)
109 {
110  if (str)
111  {
112  return atoi(str);
113  }
114  else
115  {
116  return 0;
117  }
118 }
119 
120 /* use v3 functions so we can use openvpn's logging and base64 etc. */
121 OPENVPN_EXPORT int
122 openvpn_plugin_open_v3(const int v3structver,
123  struct openvpn_plugin_args_open_in const *args,
125 {
126  /* const char **argv = args->argv; */ /* command line arguments (unused) */
127  const char **envp = args->envp; /* environment variables */
128 
129  /* Check API compatibility -- struct version 5 or higher needed */
130  if (v3structver < 5)
131  {
132  fprintf(stderr, "sample-client-connect: this plugin is incompatible with the running version of OpenVPN\n");
134  }
135 
136  /*
137  * Allocate our context
138  */
139  struct plugin_context *context = calloc(1, sizeof(struct plugin_context));
140  if (!context)
141  {
142  goto error;
143  }
144 
145  /*
146  * Intercept just about everything...
147  */
148  ret->type_mask =
160 
161  /* Save global pointers to functions exported from openvpn */
165 
166  /*
167  * Get verbosity level from environment
168  */
169  context->verb = atoi_null0(get_env("verb", envp));
170 
172  plugin_log(PLOG_NOTE, MODULE, "initialization succeeded");
174 
175 error:
176  free(context);
178 }
179 
180 
181 /* there are two possible interfaces for an openvpn plugin how
182  * to be called on "client connect", which primarily differ in the
183  * way config options are handed back to the client instance
184  * (see openvpn/multi.c, multi_client_connect_call_plugin_{v1,v2}())
185  *
186  * OPENVPN_PLUGIN_CLIENT_CONNECT
187  * openvpn creates a temp file and passes the name to the plugin
188  * (via argv[1] variable, argv[0] is the name of the plugin)
189  * the plugin can write config statements to that file, and openvpn
190  * reads it in like a "ccd/$cn" per-client config file
191  *
192  * OPENVPN_PLUGIN_CLIENT_CONNECT_V2
193  * the caller passes in a pointer to an "openvpn_plugin_string_list"
194  * (openvpn-plugin.h), which is a linked list of (name,value) pairs
195  *
196  * we fill in one node with name="config" and value="our config"
197  *
198  * both "l" and "l->name" and "l->value" are malloc()ed by the plugin
199  * and free()ed by the caller (openvpn_plugin_string_list_free())
200  */
201 
202 /* helper function to write actual "here are your options" file,
203  * called from sync and sync handler
204  */
205 int
206 write_cc_options_file(const char *name, const char **envp)
207 {
208  if (!name)
209  {
211  }
212 
213  FILE *fp = fopen(name, "w");
214  if (!fp)
215  {
216  plugin_log(PLOG_ERR, MODULE, "fopen('%s') failed", name);
218  }
219 
220  /* config to-be-sent can come from "setenv plugin_cc_config" in openvpn */
221  const char *p = get_env("plugin_cc_config", envp);
222  if (p)
223  {
224  fprintf(fp, "%s\n", p);
225  }
226 
227  /* some generic config snippets so we know it worked */
228  fprintf(fp, "push \"echo sample-cc plugin 1 called\"\n");
229 
230  /* if the caller wants, reject client by means of "disable" option */
231  if (get_env("UV_WANT_CC_DISABLE", envp))
232  {
233  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC_DISABLE, reject");
234  fprintf(fp, "disable\n");
235  }
236  fclose(fp);
237 
239 }
240 
241 int
242 cc_handle_deferred_v1(int seconds, const char *name, const char **envp)
243 {
244  const char *ccd_file = get_env("client_connect_deferred_file", envp);
245  if (!ccd_file)
246  {
247  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC_ASYNC=%d, but "
248  "'client_connect_deferred_file' not set -> fail", seconds);
250  }
251 
252  /* the CLIENT_CONNECT (v1) API is a bit tricky to work with, because
253  * completition can be signalled both by the "deferred_file" and by
254  * the new ...CLIENT_CONNECT_DEFER API - which is optional.
255  *
256  * For OpenVPN to be able to differenciate, we must create the file
257  * right away if we want to use that for signalling.
258  */
259  int fd = open(ccd_file, O_WRONLY);
260  if (fd < 0)
261  {
262  plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "open('%s') failed", ccd_file);
264  }
265 
266  if (write(fd, "2", 1) != 1)
267  {
268  plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "write to '%s' failed", ccd_file );
269  close(fd);
271  }
272  close(fd);
273 
274  /* we do not want to complicate our lives with having to wait()
275  * for child processes (so they are not zombiefied) *and* we MUST NOT
276  * fiddle with signal handlers (= shared with openvpn main), so
277  * we use double-fork() trick.
278  */
279 
280  /* fork, sleep, succeed/fail according to env vars */
281  pid_t p1 = fork();
282  if (p1 < 0) /* Fork failed */
283  {
285  }
286  if (p1 > 0) /* parent process */
287  {
288  waitpid(p1, NULL, 0);
290  }
291 
292  /* first gen child process, fork() again and exit() right away */
293  pid_t p2 = fork();
294  if (p2 < 0)
295  {
296  plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "BACKGROUND: fork(2) failed");
297  exit(1);
298  }
299  if (p2 > 0) /* new parent: exit right away */
300  {
301  exit(0);
302  }
303 
304  /* (grand-)child process
305  * - never call "return" now (would mess up openvpn)
306  * - return status is communicated by file
307  * - then exit()
308  */
309 
310  /* do mighty complicated work that will really take time here... */
311  plugin_log(PLOG_NOTE, MODULE, "in async/deferred handler, sleep(%d)", seconds);
312  sleep(seconds);
313 
314  /* write config options to openvpn */
315  int ret = write_cc_options_file(name, envp);
316 
317  /* by setting "UV_WANT_CC_FAIL" we can be triggered to fail */
318  const char *p = get_env("UV_WANT_CC_FAIL", envp);
319  if (p)
320  {
321  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC_FAIL=%s -> fail", p);
323  }
324 
325  /* now signal success/failure state to openvpn */
326  fd = open(ccd_file, O_WRONLY);
327  if (fd < 0)
328  {
329  plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "open('%s') failed", ccd_file);
330  exit(1);
331  }
332 
333  plugin_log(PLOG_NOTE, MODULE, "cc_handle_deferred_v1: done, signalling %s",
334  (ret == OPENVPN_PLUGIN_FUNC_SUCCESS) ? "success" : "fail" );
335 
336  if (write(fd, (ret == OPENVPN_PLUGIN_FUNC_SUCCESS) ? "1" : "0", 1) != 1)
337  {
338  plugin_log(PLOG_ERR|PLOG_ERRNO, MODULE, "write to '%s' failed", ccd_file );
339  }
340  close(fd);
341 
342  exit(0);
343 }
344 
345 int
347  const char **argv,
348  const char **envp)
349 {
350  /* log environment variables handed to us by OpenVPN, but
351  * only if "setenv verb" is 3 or higher (arbitrary number)
352  */
353  if (context->verb>=3)
354  {
355  for (int i = 0; argv[i]; i++)
356  {
357  plugin_log(PLOG_NOTE, MODULE, "per-client argv: %s", argv[i]);
358  }
359  for (int i = 0; envp[i]; i++)
360  {
361  plugin_log(PLOG_NOTE, MODULE, "per-client env: %s", envp[i]);
362  }
363  }
364 
365  /* by setting "UV_WANT_CC_ASYNC" we go to async/deferred mode */
366  const char *p = get_env("UV_WANT_CC_ASYNC", envp);
367  if (p)
368  {
369  /* the return value will usually be OPENVPN_PLUGIN_FUNC_DEFERRED
370  * ("I will do my job in the background, check the status file!")
371  * but depending on env setup it might be "..._ERRROR"
372  */
373  return cc_handle_deferred_v1(atoi(p), argv[1], envp);
374  }
375 
376  /* -- this is synchronous mode (openvpn waits for us) -- */
377 
378  /* by setting "UV_WANT_CC_FAIL" we can be triggered to fail */
379  p = get_env("UV_WANT_CC_FAIL", envp);
380  if (p)
381  {
382  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC_FAIL=%s -> fail", p);
384  }
385 
386  /* does the caller want options? give them some */
387  int ret = write_cc_options_file(argv[1], envp);
388 
389  return ret;
390 }
391 
392 int
394  struct plugin_per_client_context *pcc,
395  const char **envp,
396  struct openvpn_plugin_string_list **return_list)
397 {
398  /* by setting "UV_WANT_CC2_ASYNC" we go to async/deferred mode */
399  const char *want_async = get_env("UV_WANT_CC2_ASYNC", envp);
400  const char *want_fail = get_env("UV_WANT_CC2_FAIL", envp);
401  const char *want_disable = get_env("UV_WANT_CC2_DISABLE", envp);
402 
403  /* config to push towards client - can be controlled by OpenVPN
404  * config ("setenv plugin_cc2_config ...") - mostly useful in a
405  * regression test environment to push stuff like routes which are
406  * then verified by t_client ping tests
407  */
408  const char *client_config = get_env("plugin_cc2_config", envp);
409  if (!client_config)
410  {
411  /* pick something meaningless which can be verified in client log */
412  client_config = "push \"setenv CC2 MOOH\"\n";
413  }
414 
415  if (want_async)
416  {
417  /* we do no really useful work here, so we just tell the
418  * "CLIENT_CONNECT_DEFER_V2" handler that it should sleep
419  * and then "do things" via the per-client-context
420  */
421  pcc->sleep_until = time(NULL) + atoi(want_async);
422  pcc->want_fail = (want_fail != NULL);
423  pcc->want_disable = (want_disable != NULL);
424  pcc->client_config = client_config;
425  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC2_ASYNC=%s -> set up deferred handler", want_async);
427  }
428 
429  /* by setting "UV_WANT_CC2_FAIL" we can be triggered to fail here */
430  if (want_fail)
431  {
432  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC2_FAIL=%s -> fail", want_fail);
434  }
435 
436  struct openvpn_plugin_string_list *rl =
437  calloc(1, sizeof(struct openvpn_plugin_string_list));
438  if (!rl)
439  {
440  plugin_log(PLOG_ERR, MODULE, "malloc(return_list) failed");
442  }
443  rl->name = strdup("config");
444  if (want_disable)
445  {
446  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC2_DISABLE, reject");
447  rl->value = strdup("disable\n");
448  }
449  else
450  {
451  rl->value = strdup(client_config);
452  }
453 
454  if (!rl->name || !rl->value)
455  {
456  plugin_log(PLOG_ERR, MODULE, "malloc(return_list->xx) failed");
457  free(rl->name);
458  free(rl->value);
459  free(rl);
461  }
462 
463  *return_list = rl;
464 
466 }
467 
468 int
470  struct plugin_per_client_context *pcc,
472  **return_list)
473 {
474  time_t time_left = pcc->sleep_until - time(NULL);
475  plugin_log(PLOG_NOTE, MODULE, "defer_v2: seconds left=%d",
476  (int) time_left);
477 
478  /* not yet due? */
479  if (time_left > 0)
480  {
482  }
483 
484  /* client wants fail? */
485  if (pcc->want_fail)
486  {
487  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC2_FAIL -> fail" );
489  }
490 
491  /* fill in RL according to with-disable / without-disable */
492 
493  /* TODO: unify this with non-deferred case */
494  struct openvpn_plugin_string_list *rl =
495  calloc(1, sizeof(struct openvpn_plugin_string_list));
496  if (!rl)
497  {
498  plugin_log(PLOG_ERR, MODULE, "malloc(return_list) failed");
500  }
501  rl->name = strdup("config");
502  if (pcc->want_disable)
503  {
504  plugin_log(PLOG_NOTE, MODULE, "env has UV_WANT_CC2_DISABLE, reject");
505  rl->value = strdup("disable\n");
506  }
507  else
508  {
509  rl->value = strdup(pcc->client_config);
510  }
511 
512  if (!rl->name || !rl->value)
513  {
514  plugin_log(PLOG_ERR, MODULE, "malloc(return_list->xx) failed");
515  free(rl->name);
516  free(rl->value);
517  free(rl);
519  }
520 
521  *return_list = rl;
522 
524 }
525 
526 OPENVPN_EXPORT int
528  const int type,
529  const char *argv[],
530  const char *envp[],
531  void *per_client_context,
532  struct openvpn_plugin_string_list **return_list)
533 {
534  struct plugin_context *context = (struct plugin_context *) handle;
535  struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
536 
537  /* for most functions, we just "don't do anything" but log the
538  * event received (so one can follow it in the log and understand
539  * the sequence of events). CONNECT and CONNECT_V2 are handled
540  */
541  switch (type)
542  {
543  case OPENVPN_PLUGIN_UP:
544  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_UP");
545  break;
546 
547  case OPENVPN_PLUGIN_DOWN:
548  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_DOWN");
549  break;
550 
552  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_ROUTE_UP");
553  break;
554 
556  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_IPCHANGE");
557  break;
558 
560  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_TLS_VERIFY");
561  break;
562 
564  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_CONNECT");
566 
568  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_CONNECT_V2");
569  return openvpn_plugin_client_connect_v2(context, pcc, envp,
570  return_list);
571 
573  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2");
575  return_list);
576 
578  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_CLIENT_DISCONNECT");
579  break;
580 
582  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_LEARN_ADDRESS");
583  break;
584 
586  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_TLS_FINAL");
587  break;
588 
589  default:
590  plugin_log(PLOG_NOTE, MODULE, "OPENVPN_PLUGIN_? type=%d\n", type);
591  }
593 }
594 
595 OPENVPN_EXPORT void *
597 {
598  printf("FUNC: openvpn_plugin_client_constructor_v1\n");
599  return calloc(1, sizeof(struct plugin_per_client_context));
600 }
601 
602 OPENVPN_EXPORT void
604 {
605  printf("FUNC: openvpn_plugin_client_destructor_v1\n");
606  free(per_client_context);
607 }
608 
609 OPENVPN_EXPORT void
611 {
612  struct plugin_context *context = (struct plugin_context *) handle;
613  printf("FUNC: openvpn_plugin_close_v1\n");
614  free(context);
615 }
openvpn_plugin_client_constructor_v1
OPENVPN_EXPORT void * openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
Definition: sample-client-connect.c:596
openvpn_plugin_callbacks::plugin_base64_decode
plugin_base64_decode_t plugin_base64_decode
Definition: openvpn-plugin.h:323
OPENVPN_PLUGIN_CLIENT_CONNECT_V2
#define OPENVPN_PLUGIN_CLIENT_CONNECT_V2
Definition: openvpn-plugin.h:126
PLOG_NOTE
@ PLOG_NOTE
Definition: openvpn-plugin.h:235
openvpn_plugin_client_connect
int openvpn_plugin_client_connect(struct plugin_context *context, const char **argv, const char **envp)
Definition: sample-client-connect.c:346
openvpn_plugin_func_v2
OPENVPN_EXPORT int openvpn_plugin_func_v2(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[], void *per_client_context, struct openvpn_plugin_string_list **return_list)
Definition: sample-client-connect.c:527
OPENVPN_PLUGIN_LEARN_ADDRESS
#define OPENVPN_PLUGIN_LEARN_ADDRESS
Definition: openvpn-plugin.h:125
OPENVPN_PLUGIN_UP
#define OPENVPN_PLUGIN_UP
Definition: openvpn-plugin.h:117
OPENVPN_PLUGIN_DOWN
#define OPENVPN_PLUGIN_DOWN
Definition: openvpn-plugin.h:118
openvpn_plugin_callbacks::plugin_secure_memzero
plugin_secure_memzero_t plugin_secure_memzero
Definition: openvpn-plugin.h:321
argv
Definition: argv.h:35
get_env
static const char * get_env(const char *name, const char *envp[])
Definition: sample-client-connect.c:85
openvpn_plugin_args_open_in
Arguments used to transport variables to the plug-in.
Definition: openvpn-plugin.h:359
context
Contains all state information for one tunnel.
Definition: openvpn.h:476
plugin_context
Definition: sample-client-connect.c:62
openvpn_plugin_args_open_return::type_mask
int type_mask
Definition: openvpn-plugin.h:396
openvpn_plugin_string_list::name
char * name
Definition: openvpn-plugin.h:193
plugin_per_client_context::want_fail
bool want_fail
Definition: sample-client-connect.c:74
plugin_base64_decode
static plugin_base64_decode_t plugin_base64_decode
Definition: sample-client-connect.c:53
plugin_log_t
void(* plugin_log_t)(openvpn_plugin_log_flags_t flags, const char *plugin_name, const char *format,...) _ovpn_chk_fmt(3
Definition: openvpn-plugin.h:254
write_cc_options_file
int write_cc_options_file(const char *name, const char **envp)
Definition: sample-client-connect.c:206
OPENVPN_PLUGIN_MASK
#define OPENVPN_PLUGIN_MASK(x)
Definition: openvpn-plugin.h:137
openvpn_plugin_client_connect_v2
int openvpn_plugin_client_connect_v2(struct plugin_context *context, struct plugin_per_client_context *pcc, const char **envp, struct openvpn_plugin_string_list **return_list)
Definition: sample-client-connect.c:393
openvpn_plugin_close_v1
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
Definition: sample-client-connect.c:610
openvpn_plugin_client_connect_defer_v2
int openvpn_plugin_client_connect_defer_v2(struct plugin_context *context, struct plugin_per_client_context *pcc, struct openvpn_plugin_string_list **return_list)
Definition: sample-client-connect.c:469
sleep
#define sleep(x)
Definition: syshead.h:43
plugin_log
static plugin_log_t plugin_log
Definition: sample-client-connect.c:51
openvpn_plugin_open_v3
OPENVPN_EXPORT int openvpn_plugin_open_v3(const int v3structver, struct openvpn_plugin_args_open_in const *args, struct openvpn_plugin_args_open_return *ret)
Definition: sample-client-connect.c:122
plugin_per_client_context::want_disable
bool want_disable
Definition: sample-client-connect.c:75
OPENVPN_PLUGIN_FUNC_ERROR
#define OPENVPN_PLUGIN_FUNC_ERROR
Definition: openvpn-plugin.h:149
PLOG_ERRNO
@ PLOG_ERRNO
Definition: openvpn-plugin.h:238
write
@ write
Definition: interactive.c:219
plugin_secure_memzero
static plugin_secure_memzero_t plugin_secure_memzero
Definition: sample-client-connect.c:52
plugin_base64_decode_t
int(* plugin_base64_decode_t)(const char *str, void *data, int size)
Export of openvpn_base64_decode() to be used inside plug-ins.
Definition: openvpn-plugin.h:298
plugin_per_client_context
Definition: sample-client-connect.c:72
OPENVPN_PLUGIN_IPCHANGE
#define OPENVPN_PLUGIN_IPCHANGE
Definition: openvpn-plugin.h:120
OPENVPN_EXPORT
#define OPENVPN_EXPORT
Definition: openvpn-plugin.h:156
OPENVPN_PLUGIN_FUNC_DEFERRED
#define OPENVPN_PLUGIN_FUNC_DEFERRED
Definition: openvpn-plugin.h:150
OPENVPN_PLUGIN_ROUTE_UP
#define OPENVPN_PLUGIN_ROUTE_UP
Definition: openvpn-plugin.h:119
openvpn_plugin_client_destructor_v1
OPENVPN_EXPORT void openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *per_client_context)
Definition: sample-client-connect.c:603
atoi_null0
static int atoi_null0(const char *str)
Definition: sample-client-connect.c:108
OPENVPN_PLUGIN_TLS_VERIFY
#define OPENVPN_PLUGIN_TLS_VERIFY
Definition: openvpn-plugin.h:121
openvpn_plugin_string_list::value
char * value
Definition: openvpn-plugin.h:194
PLOG_ERR
@ PLOG_ERR
Definition: openvpn-plugin.h:233
openvpn_plugin_args_open_in::envp
const char **const envp
Definition: openvpn-plugin.h:363
plugin_secure_memzero_t
void(*) typedef void(*) typedef void(* plugin_secure_memzero_t)(void *data, size_t len)
Export of secure_memzero() to be used inside plug-ins.
Definition: openvpn-plugin.h:271
plugin_per_client_context::sleep_until
time_t sleep_until
Definition: sample-client-connect.c:73
OPENVPN_PLUGIN_CLIENT_DISCONNECT
#define OPENVPN_PLUGIN_CLIENT_DISCONNECT
Definition: openvpn-plugin.h:124
MODULE
static char * MODULE
Definition: sample-client-connect.c:56
openvpn_plugin_args_open_return
Arguments used to transport variables from the plug-in back to the OpenVPN process.
Definition: openvpn-plugin.h:394
openvpn_plugin_args_open_return::handle
openvpn_plugin_handle_t handle
Definition: openvpn-plugin.h:397
openvpn_plugin_string_list
Definition: openvpn-plugin.h:190
OPENVPN_PLUGIN_FUNC_SUCCESS
#define OPENVPN_PLUGIN_FUNC_SUCCESS
Definition: openvpn-plugin.h:148
config.h
OPENVPN_PLUGIN_TLS_FINAL
#define OPENVPN_PLUGIN_TLS_FINAL
Definition: openvpn-plugin.h:127
plugin_context::verb
int verb
Definition: sample-client-connect.c:63
plugin_per_client_context::client_config
const char * client_config
Definition: sample-client-connect.c:76
openvpn-plugin.h
openvpn_plugin_handle_t
void * openvpn_plugin_handle_t
Definition: openvpn-plugin.h:143
cc_handle_deferred_v1
int cc_handle_deferred_v1(int seconds, const char *name, const char **envp)
Definition: sample-client-connect.c:242
OPENVPN_PLUGIN_CLIENT_CONNECT
#define OPENVPN_PLUGIN_CLIENT_CONNECT
Definition: openvpn-plugin.h:123
openvpn_plugin_args_open_in::callbacks
struct openvpn_plugin_callbacks * callbacks
Definition: openvpn-plugin.h:364
openvpn_plugin_callbacks::plugin_log
plugin_log_t plugin_log
Definition: openvpn-plugin.h:319
OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2
#define OPENVPN_PLUGIN_CLIENT_CONNECT_DEFER_V2
Definition: openvpn-plugin.h:131