OpenVPN
pf.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-2021 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 /* packet filter functions */
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #elif defined(_MSC_VER)
29 #include "config-msvc.h"
30 #endif
31 
32 #include "syshead.h"
33 
34 #if defined(ENABLE_PF)
35 
36 #include "init.h"
37 #include "memdbg.h"
38 #include "pf.h"
39 #include "ssl_verify.h"
40 
41 
42 static void
43 pf_destroy(struct pf_set *pfs)
44 {
45  if (pfs)
46  {
47  if (pfs->cns.hash_table)
48  {
49  hash_free(pfs->cns.hash_table);
50  }
51 
52  {
53  struct pf_cn_elem *l = pfs->cns.list;
54  while (l)
55  {
56  struct pf_cn_elem *next = l->next;
57  free(l->rule.cn);
58  free(l);
59  l = next;
60  }
61  }
62  {
63  struct pf_subnet *l = pfs->sns.list;
64  while (l)
65  {
66  struct pf_subnet *next = l->next;
67  free(l);
68  l = next;
69  }
70  }
71  free(pfs);
72  }
73 }
74 
75 static bool
76 add_client(const char *line, const char *prefix, const int line_num, struct pf_cn_elem ***next, const bool exclude)
77 {
78  struct pf_cn_elem *e;
79  ALLOC_OBJ_CLEAR(e, struct pf_cn_elem);
80  e->rule.exclude = exclude;
81  e->rule.cn = string_alloc(line, NULL);
82  **next = e;
83  *next = &e->next;
84  return true;
85 }
86 
87 static bool
88 add_subnet(const char *line, const char *prefix, const int line_num, struct pf_subnet ***next, const bool exclude)
89 {
90  struct in_addr network;
91  in_addr_t netmask = 0;
92 
93  if (strcmp(line, "unknown"))
94  {
95  int netbits = 32;
96  char *div = strchr(line, '/');
97 
98  if (div)
99  {
100  *div++ = '\0';
101  if (sscanf(div, "%d", &netbits) != 1)
102  {
103  msg(D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: '%s'", prefix, line_num, div);
104  return false;
105  }
106  if (netbits < 0 || netbits > 32)
107  {
108  msg(D_PF_INFO, "PF: %s/%d: bad '/n' subnet specifier: must be between 0 and 32: '%s'", prefix, line_num, div);
109  return false;
110  }
111  }
112 
113  if (openvpn_inet_aton(line, &network) != OIA_IP)
114  {
115  msg(D_PF_INFO, "PF: %s/%d: bad network address: '%s'", prefix, line_num, line);
116  return false;
117  }
118  netmask = netbits_to_netmask(netbits);
119  if ((network.s_addr & htonl(netmask)) != network.s_addr)
120  {
121  network.s_addr &= htonl(netmask);
122  msg(M_WARN, "WARNING: PF: %s/%d: incorrect subnet %s/%d changed to %s/%d", prefix, line_num, line, netbits, inet_ntoa(network), netbits);
123  }
124  }
125  else
126  {
127  /* match special "unknown" tag for addresses unrecognized by mroute */
128  network.s_addr = htonl(0);
129  netmask = IPV4_NETMASK_HOST;
130  }
131 
132  {
133  struct pf_subnet *e;
134  ALLOC_OBJ_CLEAR(e, struct pf_subnet);
135  e->rule.exclude = exclude;
136  e->rule.network = ntohl(network.s_addr);
137  e->rule.netmask = netmask;
138  **next = e;
139  *next = &e->next;
140  return true;
141  }
142 }
143 
144 static uint32_t
145 cn_hash_function(const void *key, uint32_t iv)
146 {
147  return hash_func((uint8_t *)key, strlen((char *)key) + 1, iv);
148 }
149 
150 static bool
151 cn_compare_function(const void *key1, const void *key2)
152 {
153  return !strcmp((const char *)key1, (const char *)key2);
154 }
155 
156 static bool
157 genhash(struct pf_cn_set *cns, const char *prefix, const int n_clients)
158 {
159  struct pf_cn_elem *e;
160  bool status = true;
161  int n_buckets = n_clients;
162 
163  if (n_buckets < 16)
164  {
165  n_buckets = 16;
166  }
167  cns->hash_table = hash_init(n_buckets, 0, cn_hash_function, cn_compare_function);
168  for (e = cns->list; e != NULL; e = e->next)
169  {
170  if (!hash_add(cns->hash_table, e->rule.cn, &e->rule, false))
171  {
172  msg(D_PF_INFO, "PF: %s: duplicate common name in [clients] section: '%s'", prefix, e->rule.cn);
173  status = false;
174  }
175  }
176 
177  return status;
178 }
179 
180 static struct pf_set *
181 pf_init(const struct buffer_list *bl, const char *prefix, const bool allow_kill)
182 {
183 #define MODE_UNDEF 0
184 #define MODE_CLIENTS 1
185 #define MODE_SUBNETS 2
186  int mode = MODE_UNDEF;
187  int line_num = 0;
188  int n_clients = 0;
189  int n_subnets = 0;
190  int n_errors = 0;
191  struct pf_set *pfs = NULL;
192  char line[PF_MAX_LINE_LEN];
193 
194  ALLOC_OBJ_CLEAR(pfs, struct pf_set);
195  if (bl)
196  {
197  struct pf_cn_elem **cl = &pfs->cns.list;
198  struct pf_subnet **sl = &pfs->sns.list;
199  struct buffer_entry *be;
200 
201  for (be = bl->head; be != NULL; be = be->next)
202  {
203  ++line_num;
204  strncpynt(line, BSTR(&be->buf), sizeof(line));
205  rm_trailing_chars(line, "\r\n\t ");
206  if (line[0] == '\0' || line[0] == '#')
207  {
208  }
209  else if (line[0] == '+' || line[0] == '-')
210  {
211  bool exclude = (line[0] == '-');
212 
213  if (line[1] =='\0')
214  {
215  msg(D_PF_INFO, "PF: %s/%d: no data after +/-: '%s'", prefix, line_num, line);
216  ++n_errors;
217  }
218  else if (mode == MODE_CLIENTS)
219  {
220  if (add_client(&line[1], prefix, line_num, &cl, exclude))
221  {
222  ++n_clients;
223  }
224  else
225  {
226  ++n_errors;
227  }
228  }
229  else if (mode == MODE_SUBNETS)
230  {
231  if (add_subnet(&line[1], prefix, line_num, &sl, exclude))
232  {
233  ++n_subnets;
234  }
235  else
236  {
237  ++n_errors;
238  }
239  }
240  else if (mode == MODE_UNDEF)
241  {
242  }
243  else
244  {
245  ASSERT(0);
246  }
247  }
248  else if (line[0] == '[')
249  {
250  if (!strcasecmp(line, "[clients accept]"))
251  {
252  mode = MODE_CLIENTS;
253  pfs->cns.default_allow = true;
254  }
255  else if (!strcasecmp(line, "[clients drop]"))
256  {
257  mode = MODE_CLIENTS;
258  pfs->cns.default_allow = false;
259  }
260  else if (!strcasecmp(line, "[subnets accept]"))
261  {
262  mode = MODE_SUBNETS;
263  pfs->sns.default_allow = true;
264  }
265  else if (!strcasecmp(line, "[subnets drop]"))
266  {
267  mode = MODE_SUBNETS;
268  pfs->sns.default_allow = false;
269  }
270  else if (!strcasecmp(line, "[end]"))
271  {
272  goto done;
273  }
274  else if (allow_kill && !strcasecmp(line, "[kill]"))
275  {
276  goto kill;
277  }
278  else
279  {
280  mode = MODE_UNDEF;
281  msg(D_PF_INFO, "PF: %s/%d unknown tag: '%s'", prefix, line_num, line);
282  ++n_errors;
283  }
284  }
285  else
286  {
287  msg(D_PF_INFO, "PF: %s/%d line must begin with '+', '-', or '[' : '%s'", prefix, line_num, line);
288  ++n_errors;
289  }
290  }
291  ++n_errors;
292  msg(D_PF_INFO, "PF: %s: missing [end]", prefix);
293  }
294  else
295  {
296  msg(D_PF_INFO, "PF: %s: cannot open", prefix);
297  ++n_errors;
298  }
299 
300 done:
301  if (bl)
302  {
303  if (!n_errors)
304  {
305  if (!genhash(&pfs->cns, prefix, n_clients))
306  {
307  ++n_errors;
308  }
309  }
310  if (n_errors)
311  {
312  msg(D_PF_INFO, "PF: %s rejected due to %d error(s)", prefix, n_errors);
313  }
314  }
315  if (n_errors)
316  {
317  pf_destroy(pfs);
318  pfs = NULL;
319  }
320  return pfs;
321 
322 kill:
323  pf_destroy(pfs);
324  ALLOC_OBJ_CLEAR(pfs, struct pf_set);
325  pfs->kill = true;
326  return pfs;
327 }
328 
329 #ifdef PLUGIN_PF
330 static struct pf_set *
331 pf_init_from_file(const char *fn)
332 {
333  struct buffer_list *bl = buffer_list_file(fn, PF_MAX_LINE_LEN);
334  if (bl)
335  {
336  struct pf_set *pfs = pf_init(bl, fn, true);
337  buffer_list_free(bl);
338  return pfs;
339  }
340  else
341  {
342  msg(D_PF_INFO|M_ERRNO, "PF: %s: cannot open", fn);
343  return NULL;
344  }
345 }
346 #endif
347 
348 #ifdef ENABLE_DEBUG
349 
350 static const char *
351 drop_accept(const bool accept)
352 {
353  return accept ? "ACCEPT" : "DROP";
354 }
355 
356 static const char *
357 pct_name(const int type)
358 {
359  switch (type)
360  {
361  case PCT_SRC:
362  return "SRC";
363 
364  case PCT_DEST:
365  return "DEST";
366 
367  default:
368  return "???";
369  }
370 }
371 
372 static void
373 pf_cn_test_print(const char *prefix,
374  const int type,
375  const char *prefix2,
376  const char *cn,
377  const bool allow,
378  const struct pf_cn *rule)
379 {
380  if (rule)
381  {
382  dmsg(D_PF_DEBUG, "PF: %s/%s/%s %s %s rule=[%s %s]",
383  prefix, prefix2, pct_name(type),
384  cn, drop_accept(allow),
385  rule->cn, drop_accept(!rule->exclude));
386  }
387  else
388  {
389  dmsg(D_PF_DEBUG, "PF: %s/%s/%s %s %s",
390  prefix, prefix2, pct_name(type),
391  cn, drop_accept(allow));
392  }
393 }
394 
395 static void
396 pf_addr_test_print(const char *prefix,
397  const char *prefix2,
398  const struct context *src,
399  const struct mroute_addr *dest,
400  const bool allow,
401  const struct ipv4_subnet *rule)
402 {
403  struct gc_arena gc = gc_new();
404  if (rule)
405  {
406  dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s rule=[%s/%s %s]",
407  prefix,
408  prefix2,
409  tls_common_name(src->c2.tls_multi, false),
411  drop_accept(allow),
412  print_in_addr_t(rule->network, 0, &gc),
413  print_in_addr_t(rule->netmask, 0, &gc),
414  drop_accept(!rule->exclude));
415  }
416  else
417  {
418  dmsg(D_PF_DEBUG, "PF: %s/%s %s %s %s",
419  prefix,
420  prefix2,
421  tls_common_name(src->c2.tls_multi, false),
423  drop_accept(allow));
424  }
425  gc_free(&gc);
426 }
427 
428 #endif /* ifdef ENABLE_DEBUG */
429 
430 static inline struct pf_cn *
431 lookup_cn_rule(struct hash *h, const char *cn, const uint32_t cn_hash)
432 {
433  struct hash_element *he = hash_lookup_fast(h, hash_bucket(h, cn_hash), cn, cn_hash);
434  if (he)
435  {
436  return (struct pf_cn *) he->value;
437  }
438  else
439  {
440  return NULL;
441  }
442 }
443 
444 bool
445 pf_cn_test(struct pf_set *pfs, const struct tls_multi *tm, const int type, const char *prefix)
446 {
447  if (pfs && !pfs->kill)
448  {
449  const char *cn;
450  uint32_t cn_hash;
451  if (tls_common_name_hash(tm, &cn, &cn_hash))
452  {
453  const struct pf_cn *rule = lookup_cn_rule(pfs->cns.hash_table, cn, cn_hash);
454  if (rule)
455  {
456 #ifdef ENABLE_DEBUG
458  {
459  pf_cn_test_print("PF_CN_MATCH", type, prefix, cn, !rule->exclude, rule);
460  }
461 #endif
462  if (!rule->exclude)
463  {
464  return true;
465  }
466  else
467  {
468  return false;
469  }
470  }
471  else
472  {
473 #ifdef ENABLE_DEBUG
475  {
476  pf_cn_test_print("PF_CN_DEFAULT", type, prefix, cn, pfs->cns.default_allow, NULL);
477  }
478 #endif
479  if (pfs->cns.default_allow)
480  {
481  return true;
482  }
483  else
484  {
485  return false;
486  }
487  }
488  }
489  }
490 #ifdef ENABLE_DEBUG
492  {
493  pf_cn_test_print("PF_CN_FAULT", type, prefix, tls_common_name(tm, false), false, NULL);
494  }
495 #endif
496  return false;
497 }
498 
499 bool
500 pf_addr_test_dowork(const struct context *src, const struct mroute_addr *dest, const char *prefix)
501 {
502  struct pf_set *pfs = src->c2.pf.pfs;
503  if (pfs && !pfs->kill)
504  {
505  const in_addr_t addr = in_addr_t_from_mroute_addr(dest);
506  const struct pf_subnet *se = pfs->sns.list;
507  while (se)
508  {
509  if ((addr & se->rule.netmask) == se->rule.network)
510  {
511 #ifdef ENABLE_DEBUG
513  {
514  pf_addr_test_print("PF_ADDR_MATCH", prefix, src, dest, !se->rule.exclude, &se->rule);
515  }
516 #endif
517  return !se->rule.exclude;
518  }
519  se = se->next;
520  }
521 #ifdef ENABLE_DEBUG
523  {
524  pf_addr_test_print("PF_ADDR_DEFAULT", prefix, src, dest, pfs->sns.default_allow, NULL);
525  }
526 #endif
527  return pfs->sns.default_allow;
528  }
529  else
530  {
531 #ifdef ENABLE_DEBUG
533  {
534  pf_addr_test_print("PF_ADDR_FAULT", prefix, src, dest, false, NULL);
535  }
536 #endif
537  return false;
538  }
539 }
540 
541 #ifdef PLUGIN_PF
542 void
543 pf_check_reload(struct context *c)
544 {
545  const int slow_wakeup = 15;
546  const int fast_wakeup = 1;
547  const int wakeup_transition = 60;
548  bool reloaded = false;
549 
550  if (c->c2.pf.filename)
551  {
552  platform_stat_t s;
553  if (!platform_stat(c->c2.pf.filename, &s))
554  {
555  if (s.st_mtime > c->c2.pf.file_last_mod)
556  {
557  struct pf_set *pfs = pf_init_from_file(c->c2.pf.filename);
558  if (pfs)
559  {
560  if (c->c2.pf.pfs)
561  {
562  pf_destroy(c->c2.pf.pfs);
563  }
564  c->c2.pf.pfs = pfs;
565  reloaded = true;
566  if (pf_kill_test(pfs))
567  {
569  c->sig->signal_text = "pf-kill";
570  }
571  }
572  c->c2.pf.file_last_mod = s.st_mtime;
573  }
574  }
575  {
576  int wakeup = slow_wakeup;
577  if (!c->c2.pf.pfs && c->c2.pf.n_check_reload < wakeup_transition)
578  {
579  wakeup = fast_wakeup;
580  }
581  event_timeout_init(&c->c2.pf.reload, wakeup, now);
583  c->c2.pf.n_check_reload++;
584  }
585  }
586 #ifdef ENABLE_DEBUG
587  if (reloaded && check_debug_level(D_PF_DEBUG))
588  {
589  pf_context_print(&c->c2.pf, "pf_check_reload", D_PF_DEBUG);
590  }
591 #endif
592 }
593 #endif /* ifdef PLUGIN_PF */
594 
595 #ifdef MANAGEMENT_PF
596 bool
597 pf_load_from_buffer_list(struct context *c, const struct buffer_list *config)
598 {
599  struct pf_set *pfs = pf_init(config, "[SERVER-PF]", false);
600  if (pfs)
601  {
602  if (c->c2.pf.pfs)
603  {
604  pf_destroy(c->c2.pf.pfs);
605  }
606  c->c2.pf.pfs = pfs;
607  return true;
608  }
609  else
610  {
611  return false;
612  }
613 }
614 #endif
615 
616 void
617 pf_init_context(struct context *c)
618 {
619 #ifdef PLUGIN_PF
621  {
622  c->c2.pf.filename = platform_create_temp_file(c->options.tmp_dir, "pf",
623  &c->c2.gc);
624  if (c->c2.pf.filename)
625  {
626  setenv_str(c->c2.es, "pf_file", c->c2.pf.filename);
627 
629  {
630  event_timeout_init(&c->c2.pf.reload, 1, now);
631  c->c2.pf.enabled = true;
632 #ifdef ENABLE_DEBUG
634  {
635  pf_context_print(&c->c2.pf, "pf_init_context#1", D_PF_DEBUG);
636  }
637 #endif
638  }
639  }
640  if (!c->c2.pf.enabled)
641  {
642  /* At some point in openvpn history, this code just printed a
643  * warning and signalled itself (SIGUSR1, "plugin-pf-init-failed")
644  * to terminate the client instance. This got broken at one of
645  * the client auth state refactorings (leading to SIGSEGV crashes)
646  * and due to "pf will be removed anyway" reasons the easiest way
647  * to prevent crashes is to REQUIRE that plugins succeed - so if
648  * the plugin fails, we cleanly abort OpenVPN
649  *
650  * see also: https://community.openvpn.net/openvpn/ticket/1377
651  */
652  msg(M_FATAL, "FATAL: failed to init PF plugin, must succeed.");
653  return;
654  }
655  }
656 #endif /* ifdef PLUGIN_PF */
657 #ifdef MANAGEMENT_PF
658  if (!c->c2.pf.enabled && management_enable_pf(management))
659  {
660  c->c2.pf.enabled = true;
661 #ifdef ENABLE_DEBUG
663  {
664  pf_context_print(&c->c2.pf, "pf_init_context#2", D_PF_DEBUG);
665  }
666 #endif
667  }
668 #endif
669 }
670 
671 void
672 pf_destroy_context(struct pf_context *pfc)
673 {
674 #ifdef PLUGIN_PF
675  if (pfc->filename)
676  {
677  platform_unlink(pfc->filename);
678  }
679 #endif
680  if (pfc->pfs)
681  {
682  pf_destroy(pfc->pfs);
683  }
684 }
685 
686 #ifdef ENABLE_DEBUG
687 
688 static void
689 pf_subnet_set_print(const struct pf_subnet_set *s, const int lev)
690 {
691  struct gc_arena gc = gc_new();
692  if (s)
693  {
694  struct pf_subnet *e;
695 
696  msg(lev, " ----- struct pf_subnet_set -----");
697  msg(lev, " default_allow=%s", drop_accept(s->default_allow));
698 
699  for (e = s->list; e != NULL; e = e->next)
700  {
701  msg(lev, " %s/%s %s",
702  print_in_addr_t(e->rule.network, 0, &gc),
703  print_in_addr_t(e->rule.netmask, 0, &gc),
704  drop_accept(!e->rule.exclude));
705  }
706  }
707  gc_free(&gc);
708 }
709 
710 static void
711 pf_cn_set_print(const struct pf_cn_set *s, const int lev)
712 {
713  if (s)
714  {
715  struct hash_iterator hi;
716  struct hash_element *he;
717 
718  msg(lev, " ----- struct pf_cn_set -----");
719  msg(lev, " default_allow=%s", drop_accept(s->default_allow));
720 
721  if (s->hash_table)
722  {
723  hash_iterator_init(s->hash_table, &hi);
724  while ((he = hash_iterator_next(&hi)))
725  {
726  struct pf_cn *e = (struct pf_cn *)he->value;
727  msg(lev, " %s %s",
728  e->cn,
729  drop_accept(!e->exclude));
730  }
731 
732  msg(lev, " ----------");
733 
734  {
735  struct pf_cn_elem *ce;
736  for (ce = s->list; ce != NULL; ce = ce->next)
737  {
738  struct pf_cn *e = lookup_cn_rule(s->hash_table, ce->rule.cn, cn_hash_function(ce->rule.cn, 0));
739  if (e)
740  {
741  msg(lev, " %s %s",
742  e->cn,
743  drop_accept(!e->exclude));
744  }
745  else
746  {
747  msg(lev, " %s LOOKUP FAILED", ce->rule.cn);
748  }
749  }
750  }
751  }
752  }
753 }
754 
755 static void
756 pf_set_print(const struct pf_set *pfs, const int lev)
757 {
758  if (pfs)
759  {
760  msg(lev, " ----- struct pf_set -----");
761  msg(lev, " kill=%d", pfs->kill);
762  pf_subnet_set_print(&pfs->sns, lev);
763  pf_cn_set_print(&pfs->cns, lev);
764  }
765 }
766 
767 void
768 pf_context_print(const struct pf_context *pfc, const char *prefix, const int lev)
769 {
770  msg(lev, "----- %s : struct pf_context -----", prefix);
771  if (pfc)
772  {
773  msg(lev, "enabled=%d", pfc->enabled);
774 #ifdef PLUGIN_PF
775  msg(lev, "filename='%s'", np(pfc->filename));
776  msg(lev, "file_last_mod=%u", (unsigned int)pfc->file_last_mod);
777  msg(lev, "n_check_reload=%u", pfc->n_check_reload);
778  msg(lev, "reload=[%d,%u,%u]", pfc->reload.defined, pfc->reload.n, (unsigned int)pfc->reload.last);
779 #endif
780  pf_set_print(pfc->pfs, lev);
781  }
782  msg(lev, "--------------------");
783 }
784 
785 #endif /* ifdef ENABLE_DEBUG */
786 
787 #endif /* if defined(ENABLE_PF) */
struct env_set * es
Definition: openvpn.h:409
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition: buffer.h:348
struct options options
Options loaded from command line or configuration file.
Definition: openvpn.h:467
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:685
struct buffer_list * buffer_list_file(const char *fn, int max_line_len)
Definition: buffer.c:1375
void hash_free(struct hash *hash)
Definition: list.c:65
Contains all state information for one tunnel.
Definition: openvpn.h:465
struct buffer_entry * head
Definition: buffer.h:1112
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
static int plugin_call(const struct plugin_list *pl, const int type, const struct argv *av, struct plugin_return *pr, struct env_set *es)
Definition: plugin.h:202
Security parameter state for a single VPN tunnel.
Definition: ssl_common.h:570
void buffer_list_free(struct buffer_list *ol)
Frees a buffer list and all the buffers in it.
Definition: buffer.c:1207
static in_addr_t netbits_to_netmask(const int netbits)
Definition: route.h:377
int openvpn_inet_aton(const char *dotted_quad, struct in_addr *addr)
Definition: socket.c:675
const char * mroute_addr_print_ex(const struct mroute_addr *ma, const unsigned int flags, struct gc_arena *gc)
Definition: mroute.c:455
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition: env_set.c:285
#define in_addr_t
Definition: config-msvc.h:103
#define dmsg(flags,...)
Definition: error.h:157
struct signal_info * sig
Internal error signaling object.
Definition: openvpn.h:492
#define SIGTERM
Definition: config-msvc.h:117
#define ASSERT(x)
Definition: error.h:204
#define OPENVPN_PLUGIN_ENABLE_PF
struct gc_arena gc
Garbage collection arena for allocations done in the level 2 scope of this context_2 structure...
Definition: openvpn.h:226
static bool check_debug_level(unsigned int level)
Definition: error.h:234
#define OPENVPN_PLUGIN_FUNC_SUCCESS
bool platform_unlink(const char *filename)
Definition: platform.c:350
#define strcasecmp
Definition: config-msvc.h:93
struct hash * hash_init(const int n_buckets, const uint32_t iv, uint32_t(*hash_function)(const void *key, uint32_t iv), bool(*compare_function)(const void *key1, const void *key2))
Definition: list.c:40
bool hash_add(struct hash *hash, const void *key, void *value, bool replace)
Definition: list.c:149
#define OIA_IP
Definition: socket.h:424
#define D_PF_DEBUG
Definition: errlevel.h:149
#define MAPF_SHOW_ARP
Definition: mroute.h:159
static const char * np(const char *str)
Definition: simple.c:128
void rm_trailing_chars(char *str, const char *what_to_delete)
Definition: buffer.c:659
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
time_t now
Definition: otime.c:36
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition: buffer.h:1050
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
Definition: socket.c:2876
#define D_PF_INFO
Definition: errlevel.h:93
void hash_iterator_init(struct hash *hash, struct hash_iterator *hi)
Definition: list.c:248
struct buffer buf
Definition: buffer.h:1106
#define M_ERRNO
Definition: error.h:103
void reset_coarse_timers(struct context *c)
Definition: init.c:1362
struct context_2 c2
Level 2 context.
Definition: openvpn.h:506
struct hash_element * hash_iterator_next(struct hash_iterator *hi)
Definition: list.c:291
int platform_stat(const char *path, platform_stat_t *buf)
Definition: platform.c:389
Container for bidirectional cipher and HMAC key material.
Definition: crypto.h:181
static struct hash_bucket * hash_bucket(struct hash *hash, uint32_t hv)
Definition: list.h:141
#define msg(flags,...)
Definition: error.h:153
struct buffer_entry * next
Definition: buffer.h:1107
uint32_t hash_func(const uint8_t *k, uint32_t length, uint32_t initval)
Definition: list.c:589
const char * tmp_dir
Definition: options.h:418
volatile int signal_received
Definition: sig.h:45
bool plugin_defined(const struct plugin_list *pl, const int type)
Definition: plugin.c:901
#define M_FATAL
Definition: error.h:98
struct hash_element * hash_lookup_fast(struct hash *hash, struct hash_bucket *bucket, const void *key, uint32_t hv)
Definition: list.c:85
struct plugin_list * plugins
List of plug-ins.
Definition: openvpn.h:494
const char * tls_common_name(const struct tls_multi *multi, const bool null)
Returns the common name field for the given tunnel.
Definition: ssl_verify.c:128
#define M_WARN
Definition: error.h:100
static in_addr_t in_addr_t_from_mroute_addr(const struct mroute_addr *addr)
Definition: mroute.h:252
#define free
Definition: cmocka.c:1850
Definition: buffer.h:1104
void * value
Definition: list.h:47
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
const char * platform_create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)
Create a temporary file in directory, returns the filename of the created file.
Definition: platform.c:403
#define BSTR(buf)
Definition: buffer.h:129
static SERVICE_STATUS status
Definition: interactive.c:56
Definition: list.h:58
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Definition: openvpn.h:320
#define IPV4_NETMASK_HOST
Definition: basic.h:35
const char * signal_text
Definition: sig.h:47
struct _stat platform_stat_t
Definition: platform.h:148
static void event_timeout_init(struct event_timeout *et, interval_t n, const time_t local_now)
Definition: interval.h:166
Container for unidirectional cipher and HMAC key material.
Definition: crypto.h:151