OpenVPN
helper.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-2023 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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "syshead.h"
29 
30 #include "forward.h"
31 #include "helper.h"
32 #include "pool.h"
33 #include "push.h"
34 
35 #include "memdbg.h"
36 
37 
38 static const char *
39 print_netmask(int netbits, struct gc_arena *gc)
40 {
41  struct buffer out = alloc_buf_gc(128, gc);
42  const in_addr_t netmask = netbits_to_netmask(netbits);
43 
44  buf_printf(&out, "%s (/%d)", print_in_addr_t(netmask, 0, gc), netbits);
45 
46  return BSTR(&out);
47 }
48 
49 static const char *
50 print_opt_route_gateway(const in_addr_t route_gateway, struct gc_arena *gc)
51 {
52  struct buffer out = alloc_buf_gc(128, gc);
53  ASSERT(route_gateway);
54  buf_printf(&out, "route-gateway %s", print_in_addr_t(route_gateway, 0, gc));
55  return BSTR(&out);
56 }
57 
58 static const char *
60 {
61  struct buffer out = alloc_buf_gc(32, gc);
62  buf_printf(&out, "route-gateway dhcp");
63  return BSTR(&out);
64 }
65 
66 static const char *
67 print_opt_route(const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc)
68 {
69  struct buffer out = alloc_buf_gc(128, gc);
70  ASSERT(network);
71 
72  if (netmask)
73  {
74  buf_printf(&out, "route %s %s",
75  print_in_addr_t(network, 0, gc),
76  print_in_addr_t(netmask, 0, gc));
77  }
78  else
79  {
80  buf_printf(&out, "route %s",
81  print_in_addr_t(network, 0, gc));
82  }
83 
84  return BSTR(&out);
85 }
86 
87 static const char *
88 print_opt_topology(const int topology, struct gc_arena *gc)
89 {
90  struct buffer out = alloc_buf_gc(128, gc);
91 
92  buf_printf(&out, "topology %s", print_topology(topology));
93 
94  return BSTR(&out);
95 }
96 
97 static const char *
98 print_str_int(const char *str, const int i, struct gc_arena *gc)
99 {
100  struct buffer out = alloc_buf_gc(128, gc);
101  buf_printf(&out, "%s %d", str, i);
102  return BSTR(&out);
103 }
104 
105 static const char *
106 print_str(const char *str, struct gc_arena *gc)
107 {
108  struct buffer out = alloc_buf_gc(128, gc);
109  buf_printf(&out, "%s", str);
110  return BSTR(&out);
111 }
112 
113 static void
114 helper_add_route(const in_addr_t network, const in_addr_t netmask, struct options *o)
115 {
116  rol_check_alloc(o);
118  print_in_addr_t(network, 0, &o->gc),
119  print_in_addr_t(netmask, 0, &o->gc),
120  NULL,
121  NULL);
122 }
123 
124 static void
125 verify_common_subnet(const char *opt, const in_addr_t a, const in_addr_t b, const in_addr_t subnet)
126 {
127  struct gc_arena gc = gc_new();
128  if ((a & subnet) != (b & subnet))
129  {
130  msg(M_USAGE, "%s IP addresses %s and %s are not in the same %s subnet",
131  opt,
132  print_in_addr_t(a, 0, &gc),
133  print_in_addr_t(b, 0, &gc),
134  print_in_addr_t(subnet, 0, &gc));
135  }
136  gc_free(&gc);
137 }
138 
139 
140 /*
141  * Process server, server-bridge, and client helper
142  * directives after the parameters themselves have been
143  * parsed and placed in struct options.
144  */
145 void
147 {
148  struct gc_arena gc = gc_new();
149 
150  /*
151  * Get tun/tap/null device type
152  */
153  const int dev = dev_type_enum(o->dev, o->dev_type);
154  const int topology = o->topology;
155 
156  /*
157  *
158  * HELPER DIRECTIVE for IPv6
159  *
160  * server-ipv6 2001:db8::/64
161  *
162  * EXPANDS TO:
163  *
164  * tun-ipv6
165  * push "tun-ipv6"
166  * ifconfig-ipv6 2001:db8::1 2001:db8::2
167  * if !nopool:
168  * ifconfig-ipv6-pool 2001:db8::1000/64
169  *
170  */
171  if (o->server_ipv6_defined)
172  {
173  if (o->client)
174  {
175  msg(M_USAGE, "--server-ipv6 and --client cannot be used together");
176  }
177 
178  if (o->server_flags & SF_NOPOOL)
179  {
180  msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
181  }
183  {
184  msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
185  }
186 
187  o->mode = MODE_SERVER;
188  o->tls_server = true;
189 
190  /* local ifconfig is "base address + 1" and "+2" */
196 
197  /* basic sanity check */
198  ASSERT(o->server_netbits_ipv6 >= 64 && o->server_netbits_ipv6 <= 124);
199 
200  o->ifconfig_ipv6_pool_defined = true;
201  /* For large enough pools we keep the original behaviour of adding
202  * 0x1000 when computing the base.
203  *
204  * Smaller pools can't get that far, therefore we just increase by 2
205  */
207  o->server_netbits_ipv6 < 112 ? 0x1000 : 2);
209 
210  push_option( o, "tun-ipv6", M_USAGE );
211  }
212 
213  /*
214  *
215  * HELPER DIRECTIVE:
216  *
217  * server 10.8.0.0 255.255.255.0
218  *
219  * EXPANDS TO:
220  *
221  * mode server
222  * tls-server
223  * push "topology [topology]"
224  *
225  * if tun AND (topology == net30 OR topology == p2p):
226  * ifconfig 10.8.0.1 10.8.0.2
227  * if !nopool:
228  * ifconfig-pool 10.8.0.4 10.8.0.251
229  * route 10.8.0.0 255.255.255.0
230  * if client-to-client:
231  * push "route 10.8.0.0 255.255.255.0"
232  * else if topology == net30:
233  * push "route 10.8.0.1"
234  *
235  * if tap OR (tun AND topology == subnet):
236  * ifconfig 10.8.0.1 255.255.255.0
237  * if !nopool:
238  * ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0
239  * push "route-gateway 10.8.0.1"
240  * if route-gateway unset:
241  * route-gateway 10.8.0.2
242  */
243 
244  if (o->server_defined)
245  {
246  int netbits = -2;
247  bool status = false;
248 
249  if (o->client)
250  {
251  msg(M_USAGE, "--server and --client cannot be used together");
252  }
253 
255  {
256  msg(M_USAGE, "--server and --server-bridge cannot be used together");
257  }
258 
259  if (o->shared_secret_file)
260  {
261  msg(M_USAGE, "--server and --secret cannot be used together (you must use SSL/TLS keys)");
262  }
263 
264  if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
265  {
266  msg(M_USAGE, "--server already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
267  }
268 
269  if (!(dev == DEV_TYPE_TAP || dev == DEV_TYPE_TUN))
270  {
271  msg(M_USAGE, "--server directive only makes sense with --dev tun or --dev tap");
272  }
273 
275  if (!status)
276  {
277  msg(M_USAGE, "--server directive network/netmask combination is invalid");
278  }
279 
280  if (netbits < 0)
281  {
282  msg(M_USAGE, "--server directive netmask is invalid");
283  }
284 
285  if (netbits < IFCONFIG_POOL_MIN_NETBITS)
286  {
287  msg(M_USAGE, "--server directive netmask allows for too many host addresses (subnet must be %s or higher)",
289  }
290 
291  if (dev == DEV_TYPE_TUN)
292  {
293  int pool_end_reserve = 4;
294 
295  if (netbits > 29)
296  {
297  msg(M_USAGE, "--server directive when used with --dev tun must define a subnet of %s or lower",
298  print_netmask(29, &gc));
299  }
300 
301  if (netbits == 29)
302  {
303  pool_end_reserve = 0;
304  }
305 
306  o->mode = MODE_SERVER;
307  o->tls_server = true;
308 
309  if (topology == TOP_NET30 || topology == TOP_P2P)
310  {
311  o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
313 
314  if (!(o->server_flags & SF_NOPOOL))
315  {
316  o->ifconfig_pool_defined = true;
318  o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - pool_end_reserve;
320  }
321 
323  if (o->enable_c2c)
324  {
326  }
327  else if (topology == TOP_NET30)
328  {
329  push_option(o, print_opt_route(o->server_network + 1, 0, &o->gc), M_USAGE);
330  }
331  }
332  else if (topology == TOP_SUBNET)
333  {
334  o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
336 
337  if (!(o->server_flags & SF_NOPOOL))
338  {
339  o->ifconfig_pool_defined = true;
341  o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 1;
343  }
345 
347  if (!o->route_default_gateway)
348  {
350  }
351  }
352  else
353  {
354  ASSERT(0);
355  }
356 
357  push_option(o, print_opt_topology(topology, &o->gc), M_USAGE);
358 
359  if (topology == TOP_NET30 && !(o->server_flags & SF_NOPOOL))
360  {
361  msg(M_WARN, "WARNING: --topology net30 support for server "
362  "configs with IPv4 pools will be removed in a future "
363  "release. Please migrate to --topology subnet as soon "
364  "as possible.");
365  }
366  }
367  else if (dev == DEV_TYPE_TAP)
368  {
369  if (netbits > 30)
370  {
371  msg(M_USAGE, "--server directive when used with --dev tap must define a subnet of %s or lower",
372  print_netmask(30, &gc));
373  }
374 
375  o->mode = MODE_SERVER;
376  o->tls_server = true;
377  o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
379 
380  if (!(o->server_flags & SF_NOPOOL))
381  {
382  o->ifconfig_pool_defined = true;
384  o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 1;
386  }
388 
390  }
391  else
392  {
393  ASSERT(0);
394  }
395 
396  /* set push-ifconfig-constraint directive */
397  if ((dev == DEV_TYPE_TAP || topology == TOP_SUBNET))
398  {
402  }
403  }
404 
405  /*
406  * HELPER DIRECTIVE:
407  *
408  * server-bridge 10.8.0.4 255.255.255.0 10.8.0.128 10.8.0.254
409  *
410  * EXPANDS TO:
411  *
412  * mode server
413  * tls-server
414  *
415  * ifconfig-pool 10.8.0.128 10.8.0.254 255.255.255.0
416  * push "route-gateway 10.8.0.4"
417  *
418  * OR
419  *
420  * server-bridge
421  *
422  * EXPANDS TO:
423  *
424  * mode server
425  * tls-server
426  *
427  * if !nogw:
428  * push "route-gateway dhcp"
429  */
431  {
432  if (o->client)
433  {
434  msg(M_USAGE, "--server-bridge and --client cannot be used together");
435  }
436 
437  if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
438  {
439  msg(M_USAGE, "--server-bridge already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
440  }
441 
442  if (o->shared_secret_file)
443  {
444  msg(M_USAGE, "--server-bridge and --secret cannot be used together (you must use SSL/TLS keys)");
445  }
446 
447  if (dev != DEV_TYPE_TAP)
448  {
449  msg(M_USAGE, "--server-bridge directive only makes sense with --dev tap");
450  }
451 
452  if (o->server_bridge_defined)
453  {
457  }
458 
459  o->mode = MODE_SERVER;
460  o->tls_server = true;
461 
462  if (o->server_bridge_defined)
463  {
464  o->ifconfig_pool_defined = true;
470  }
472  {
474  }
475  }
476  else
477  /*
478  * HELPER DIRECTIVE:
479  *
480  * client
481  *
482  * EXPANDS TO:
483  *
484  * pull
485  * tls-client
486  */
487  if (o->client)
488  {
489  o->pull = true;
490  o->tls_client = true;
491  }
492 
493  gc_free(&gc);
494 }
495 
496 /*
497  *
498  * HELPER DIRECTIVE:
499  *
500  * keepalive 10 60
501  *
502  * EXPANDS TO:
503  *
504  * if mode server:
505  * ping 10
506  * ping-restart 120
507  * push "ping 10"
508  * push "ping-restart 60"
509  * else
510  * ping 10
511  * ping-restart 60
512  */
513 void
515 {
516  if (o->keepalive_ping || o->keepalive_timeout)
517  {
518  /*
519  * Sanity checks.
520  */
521  if (o->keepalive_ping <= 0 || o->keepalive_timeout <= 0)
522  {
523  msg(M_USAGE, "--keepalive parameters must be > 0");
524  }
525  if (o->keepalive_ping * 2 > o->keepalive_timeout)
526  {
527  msg(M_USAGE, "the second parameter to --keepalive (restart timeout=%d) must be at least twice the value of the first parameter (ping interval=%d). A ratio of 1:5 or 1:6 would be even better. Recommended setting is --keepalive 10 60.",
529  o->keepalive_ping);
530  }
531  if (o->ping_send_timeout || o->ping_rec_timeout)
532  {
533  msg(M_USAGE, "--keepalive conflicts with --ping, --ping-exit, or --ping-restart. If you use --keepalive, you don't need any of the other --ping directives.");
534  }
535 
536  /*
537  * Expand.
538  */
539  if (o->mode == MODE_POINT_TO_POINT)
540  {
544  }
545  else if (o->mode == MODE_SERVER)
546  {
550  push_option(o, print_str_int("ping", o->keepalive_ping, &o->gc), M_USAGE);
551  push_option(o, print_str_int("ping-restart", o->keepalive_timeout, &o->gc), M_USAGE);
552  }
553  else
554  {
555  ASSERT(0);
556  }
557  }
558 }
559 
560 /*
561  *
562  * HELPER DIRECTIVE:
563  *
564  * tcp-nodelay
565  *
566  * EXPANDS TO:
567  *
568  * if mode server:
569  * socket-flags TCP_NODELAY
570  * push "socket-flags TCP_NODELAY"
571  */
572 void
574 {
576  {
577  if (o->mode == MODE_SERVER)
578  {
580  push_option(o, print_str("socket-flags TCP_NODELAY", &o->gc), M_USAGE);
581  }
582  else
583  {
585  }
586  }
587 }
options::keepalive_timeout
int keepalive_timeout
Definition: options.h:328
options::server_network_ipv6
struct in6_addr server_network_ipv6
Definition: options.h:456
netmask_to_netbits
bool netmask_to_netbits(const in_addr_t network, const in_addr_t netmask, int *netbits)
Definition: route.c:3922
helper_client_server
void helper_client_server(struct options *o)
Definition: helper.c:146
SF_NO_PUSH_ROUTE_GATEWAY
#define SF_NO_PUSH_ROUTE_GATEWAY
Definition: options.h:461
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1031
SF_TCP_NODELAY_HELPER
#define SF_TCP_NODELAY_HELPER
Definition: options.h:460
DEV_TYPE_TUN
#define DEV_TYPE_TUN
Definition: proto.h:37
forward.h
options::keepalive_ping
int keepalive_ping
Definition: options.h:327
options::server_flags
unsigned int server_flags
Definition: options.h:462
options::enable_c2c
bool enable_c2c
Definition: options.h:510
options::server_network
in_addr_t server_network
Definition: options.h:453
print_netmask
static const char * print_netmask(int netbits, struct gc_arena *gc)
Definition: helper.c:39
options::server_bridge_ip
in_addr_t server_bridge_ip
Definition: options.h:467
options::topology
int topology
Definition: options.h:307
BSTR
#define BSTR(buf)
Definition: buffer.h:129
options::dev_type
const char * dev_type
Definition: options.h:304
options::tls_client
bool tls_client
Definition: options.h:575
options::shared_secret_file
const char * shared_secret_file
Definition: options.h:553
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
verify_common_subnet
static void verify_common_subnet(const char *opt, const in_addr_t a, const in_addr_t b, const in_addr_t subnet)
Definition: helper.c:125
options::server_defined
bool server_defined
Definition: options.h:452
options::mode
int mode
Definition: options.h:247
print_opt_route
static const char * print_opt_route(const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc)
Definition: helper.c:67
options::ifconfig_ipv6_pool_defined
bool ifconfig_ipv6_pool_defined
Definition: options.h:480
SF_TCP_NODELAY
#define SF_TCP_NODELAY
Definition: socket.h:205
TOP_SUBNET
#define TOP_SUBNET
Definition: proto.h:45
MODE_SERVER
#define MODE_SERVER
Definition: options.h:246
options::tls_server
bool tls_server
Definition: options.h:574
add_route_to_option_list
void add_route_to_option_list(struct route_option_list *l, const char *network, const char *netmask, const char *gateway, const char *metric)
Definition: route.c:507
PING_RESTART
#define PING_RESTART
Definition: options.h:341
SF_NOPOOL
#define SF_NOPOOL
Definition: options.h:459
push_option
void push_option(struct options *o, const char *opt, int msglevel)
Definition: push.c:867
options::dev
const char * dev
Definition: options.h:303
ASSERT
#define ASSERT(x)
Definition: error.h:201
helper_tcp_nodelay
void helper_tcp_nodelay(struct options *o)
Definition: helper.c:573
print_in6_addr
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
Definition: socket.c:2921
print_topology
const char * print_topology(const int topology)
Definition: options.c:4733
options::server_netmask
in_addr_t server_netmask
Definition: options.h:454
options::ping_send_timeout
int ping_send_timeout
Definition: options.h:335
options::client
bool client
Definition: options.h:539
options::ifconfig_ipv6_netbits
int ifconfig_ipv6_netbits
Definition: options.h:311
IFCONFIG_POOL_MIN_NETBITS
#define IFCONFIG_POOL_MIN_NETBITS
Definition: pool.h:33
push.h
M_WARN
#define M_WARN
Definition: error.h:97
options::push_ifconfig_constraint_defined
bool push_ifconfig_constraint_defined
Definition: options.h:501
options::server_netbits_ipv6
unsigned int server_netbits_ipv6
Definition: options.h:457
options
Definition: options.h:236
pool.h
options::gc
struct gc_arena gc
Definition: options.h:238
print_str
static const char * print_str(const char *str, struct gc_arena *gc)
Definition: helper.c:106
helper_keepalive
void helper_keepalive(struct options *o)
Definition: helper.c:514
options::ifconfig_pool_netmask
in_addr_t ifconfig_pool_netmask
Definition: options.h:476
options::server_ipv6_defined
bool server_ipv6_defined
Definition: options.h:455
DEV_TYPE_TAP
#define DEV_TYPE_TAP
Definition: proto.h:38
options::ping_rec_timeout
int ping_rec_timeout
Definition: options.h:336
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
print_in_addr_t
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
Definition: socket.c:2901
print_opt_topology
static const char * print_opt_topology(const int topology, struct gc_arena *gc)
Definition: helper.c:88
options::server_bridge_proxy_dhcp
bool server_bridge_proxy_dhcp
Definition: options.h:464
syshead.h
options::server_bridge_pool_start
in_addr_t server_bridge_pool_start
Definition: options.h:469
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
MODE_POINT_TO_POINT
#define MODE_POINT_TO_POINT
Definition: options.h:245
options::server_bridge_netmask
in_addr_t server_bridge_netmask
Definition: options.h:468
TOP_P2P
#define TOP_P2P
Definition: proto.h:44
rol_check_alloc
void rol_check_alloc(struct options *options)
Definition: options.c:1683
options::ifconfig_pool_end
in_addr_t ifconfig_pool_end
Definition: options.h:475
print_str_int
static const char * print_str_int(const char *str, const int i, struct gc_arena *gc)
Definition: helper.c:98
options::ifconfig_pool_defined
bool ifconfig_pool_defined
Definition: options.h:473
netbits_to_netmask
static in_addr_t netbits_to_netmask(const int netbits)
Definition: route.h:367
status
static SERVICE_STATUS status
Definition: interactive.c:52
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1039
print_opt_route_gateway
static const char * print_opt_route_gateway(const in_addr_t route_gateway, struct gc_arena *gc)
Definition: helper.c:50
options::ifconfig_remote_netmask
const char * ifconfig_remote_netmask
Definition: options.h:309
options::routes
struct route_option_list * routes
Definition: options.h:419
options::ifconfig_ipv6_pool_netbits
int ifconfig_ipv6_pool_netbits
Definition: options.h:482
helper_add_route
static void helper_add_route(const in_addr_t network, const in_addr_t netmask, struct options *o)
Definition: helper.c:114
options::server_bridge_pool_end
in_addr_t server_bridge_pool_end
Definition: options.h:470
options::sockflags
unsigned int sockflags
Definition: options.h:407
TOP_NET30
#define TOP_NET30
Definition: proto.h:43
config.h
options::ifconfig_pool_start
in_addr_t ifconfig_pool_start
Definition: options.h:474
options::ifconfig_ipv6_pool_base
struct in6_addr ifconfig_ipv6_pool_base
Definition: options.h:481
options::ifconfig_ipv6_local
const char * ifconfig_ipv6_local
Definition: options.h:310
print_opt_route_gateway_dhcp
static const char * print_opt_route_gateway_dhcp(struct gc_arena *gc)
Definition: helper.c:59
helper.h
options::push_ifconfig_constraint_network
in_addr_t push_ifconfig_constraint_network
Definition: options.h:502
ifconfig_pool_verify_range
bool ifconfig_pool_verify_range(const int msglevel, const in_addr_t start, const in_addr_t end)
Definition: pool.c:121
add_in6_addr
struct in6_addr add_in6_addr(struct in6_addr base, uint32_t add)
Definition: socket.c:2952
options::ifconfig_local
const char * ifconfig_local
Definition: options.h:308
memdbg.h
options::ping_rec_timeout_action
int ping_rec_timeout_action
Definition: options.h:342
M_USAGE
#define M_USAGE
Definition: error.h:112
msg
#define msg(flags,...)
Definition: error.h:150
options::ifconfig_ipv6_remote
const char * ifconfig_ipv6_remote
Definition: options.h:312
buf_printf
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:240
options::server_bridge_defined
bool server_bridge_defined
Definition: options.h:466
options::push_ifconfig_constraint_netmask
in_addr_t push_ifconfig_constraint_netmask
Definition: options.h:503
options::pull
bool pull
Definition: options.h:540
dev_type_enum
int dev_type_enum(const char *dev, const char *dev_type)
Definition: tun.c:436
options::route_default_gateway
const char * route_default_gateway
Definition: options.h:412