OpenVPN
tun.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/*
24 * Support routines for configuring and accessing TUN/TAP
25 * virtual network adapters.
26 *
27 * This file is based on the TUN/TAP driver interface routines
28 * from VTun by Maxim Krasnyansky <max_mk@yahoo.com>.
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "syshead.h"
36
37#include "openvpn.h"
38#include "tun.h"
39#include "fdmisc.h"
40#include "common.h"
41#include "run_command.h"
42#include "socket_util.h"
43#include "manage.h"
44#include "route.h"
45#include "win32.h"
46#include "wfp_block.h"
47#include "networking.h"
48#include "dhcp.h"
49
50#include "memdbg.h"
51
52#ifdef _WIN32
53#include "openvpn-msg.h"
54#endif
55
56#include <string.h>
57
58const char *
60{
61 switch (driver)
62 {
64 return "tap-windows6";
65
67 return "tun/tap";
68
69 case DRIVER_DCO:
70 return "ovpn-dco";
71
72 case DRIVER_AFUNIX:
73 return "unix";
74
75 case DRIVER_NULL:
76 return "null";
77
78 case DRIVER_UTUN:
79 return "utun";
80
81 default:
82 return "unspecified";
83 }
84}
85
86#ifdef _WIN32
87
88static const GUID GUID_DEVCLASS_NET = {
89 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 }
90};
91static const GUID GUID_DEVINTERFACE_NET = {
92 0xcac88484, 0x7515, 0x4c03, { 0x82, 0xe6, 0x71, 0xa8, 0x7a, 0xba, 0xc3, 0x61 }
93};
94
95/* #define SIMULATE_DHCP_FAILED */ /* simulate bad DHCP negotiation */
96
97#define NI_TEST_FIRST (1 << 0)
98#define NI_IP_NETMASK (1 << 1)
99#define NI_OPTIONS (1 << 2)
100
101static void netsh_ifconfig(const struct tuntap_options *to, DWORD adapter_index, const in_addr_t ip,
102 const in_addr_t netmask, const unsigned int flags);
103
104static void windows_set_mtu(const int iface_index, const short family, const int mtu);
105
106static void netsh_set_dns6_servers(const struct in6_addr *addr_list, const int addr_len,
107 DWORD adapter_index);
108
109static void netsh_command(const struct argv *a, int n, msglvl_t msglevel);
110
111static void exec_command(const char *prefix, const struct argv *a, int n, msglvl_t msglevel);
112
113static const char *netsh_get_id(const char *dev_node, struct gc_arena *gc);
114
115static bool
116do_address_service(const bool add, const short family, const struct tuntap *tt)
117{
118 bool ret = false;
119 ack_message_t ack;
120 struct gc_arena gc = gc_new();
121 HANDLE pipe = tt->options.msg_channel;
122
124 sizeof(address_message_t), 0 },
125 .family = family,
126 .iface = { .index = tt->adapter_index, .name = "" } };
127
129 {
130 strncpy(addr.iface.name, tt->actual_name, sizeof(addr.iface.name));
131 addr.iface.name[sizeof(addr.iface.name) - 1] = '\0';
132 }
133
134 if (addr.family == AF_INET)
135 {
136 addr.address.ipv4.s_addr = htonl(tt->local);
138 msg(D_IFCONFIG, "INET address service: %s %s/%d", add ? "add" : "remove",
139 print_in_addr_t(tt->local, 0, &gc), addr.prefix_len);
140 }
141 else
142 {
143 addr.address.ipv6 = tt->local_ipv6;
144 addr.prefix_len = (tt->type == DEV_TYPE_TUN) ? 128 : tt->netbits_ipv6;
145 msg(D_IFCONFIG, "INET6 address service: %s %s/%d", add ? "add" : "remove",
146 print_in6_addr(tt->local_ipv6, 0, &gc), addr.prefix_len);
147 }
148
149 if (!send_msg_iservice(pipe, &addr, sizeof(addr), &ack, "TUN"))
150 {
151 goto out;
152 }
153
154 if (ack.error_number != NO_ERROR)
155 {
156 msg(M_WARN, "TUN: %s address failed using service: %s [status=%u if_index=%d]",
157 (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), ack.error_number,
158 addr.iface.index);
159 goto out;
160 }
161
162 ret = true;
163
164out:
165 gc_free(&gc);
166 return ret;
167}
168
169static void
170do_dns_domain_service(bool add, const struct tuntap *tt)
171{
172 ack_message_t ack;
173 struct gc_arena gc = gc_new();
174 const struct tuntap_options *o = &tt->options;
175
176 /* no domains to add or delete */
177 if (!o->domain && !o->domain_search_list[0])
178 {
179 goto out;
180 }
181
182 /* Use dns_cfg_msg with addr_len = 0 for setting only the DOMAIN */
184 .header = { (add ? msg_add_dns_cfg : msg_del_dns_cfg), sizeof(dns_cfg_message_t), 0 },
185 .iface = { .index = tt->adapter_index, .name = "" },
186 .domains = "", /* set below */
187 .family = AF_INET, /* unused */
188 .addr_len = 0 /* add/delete only the domain, not DNS servers */
189 };
190
191 /* interface name is required */
192 strncpynt(dns.iface.name, tt->actual_name, sizeof(dns.iface.name));
193
194 /* only use domain when there are no search domains */
195 if (o->domain && !o->domain_search_list[0])
196 {
197 strncpynt(dns.domains, o->domain, sizeof(dns.domains));
198 }
199
200 /* Create a comma separated list of search domains */
201 for (int i = 0; i < N_SEARCH_LIST_LEN && o->domain_search_list[i]; ++i)
202 {
203 size_t dstlen = strlen(dns.domains);
204 size_t srclen = strlen(o->domain_search_list[i]);
205 size_t extra = dstlen ? 2 : 1; /* space for comma and NUL */
206 if (dstlen + srclen + extra > sizeof(dns.domains))
207 {
208 msg(M_WARN, "DNS search domains sent to service truncated to %d", i);
209 break;
210 }
211 if (dstlen)
212 {
213 dns.domains[dstlen++] = ',';
214 }
215 strncpy(dns.domains + dstlen, o->domain_search_list[i], srclen + 1);
216 }
217
218 msg(D_LOW, "%s DNS domains on '%s' (if_index = %d) using service",
219 (add ? "Setting" : "Deleting"), dns.iface.name, dns.iface.index);
220 if (!send_msg_iservice(o->msg_channel, &dns, sizeof(dns), &ack, "TUN"))
221 {
222 goto out;
223 }
224
225 if (ack.error_number != NO_ERROR)
226 {
227 msg(M_WARN, "TUN: %s DNS domains failed using service: %s [status=%u if_name=%s]",
228 (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), ack.error_number,
229 dns.iface.name);
230 goto out;
231 }
232
233 msg(M_INFO, "DNS domains %s using service", (add ? "set" : "deleted"));
234
235out:
236 gc_free(&gc);
237}
238
239static void
240do_dns_service(bool add, const short family, const struct tuntap *tt)
241{
242 ack_message_t ack;
243 struct gc_arena gc = gc_new();
244 HANDLE pipe = tt->options.msg_channel;
245 int len = family == AF_INET6 ? tt->options.dns6_len : tt->options.dns_len;
246 int addr_len = add ? len : 0;
247 const char *ip_proto_name = family == AF_INET6 ? "IPv6" : "IPv4";
248
249 if (len == 0)
250 {
251 /* nothing to do */
252 goto out;
253 }
254
255 /* Use dns_cfg_msg with domain = "" for setting only the DNS servers */
257 sizeof(dns_cfg_message_t), 0 },
258 .iface = { .index = tt->adapter_index, .name = "" },
259 .domains = "",
260 .family = family,
261 .addr_len = addr_len };
262
263 /* interface name is required */
264 strncpy(dns.iface.name, tt->actual_name, sizeof(dns.iface.name));
265 dns.iface.name[sizeof(dns.iface.name) - 1] = '\0';
266
267 if (addr_len > _countof(dns.addr))
268 {
269 addr_len = _countof(dns.addr);
270 dns.addr_len = addr_len;
271 msg(M_WARN, "Number of %s DNS addresses sent to service truncated to %d", ip_proto_name,
272 addr_len);
273 }
274
275 for (int i = 0; i < addr_len; ++i)
276 {
277 if (family == AF_INET6)
278 {
279 dns.addr[i].ipv6 = tt->options.dns6[i];
280 }
281 else
282 {
283 dns.addr[i].ipv4.s_addr = htonl(tt->options.dns[i]);
284 }
285 }
286
287 msg(D_LOW, "%s %s dns servers on '%s' (if_index = %d) using service",
288 (add ? "Setting" : "Deleting"), ip_proto_name, dns.iface.name, dns.iface.index);
289
290 if (!send_msg_iservice(pipe, &dns, sizeof(dns), &ack, "TUN"))
291 {
292 goto out;
293 }
294
295 if (ack.error_number != NO_ERROR)
296 {
297 msg(M_WARN, "TUN: %s %s dns failed using service: %s [status=%u if_name=%s]",
298 (add ? "adding" : "deleting"), ip_proto_name, strerror_win32(ack.error_number, &gc),
299 ack.error_number, dns.iface.name);
300 goto out;
301 }
302
303 msg(M_INFO, "%s dns servers %s using service", ip_proto_name, (add ? "set" : "deleted"));
304
305out:
306 gc_free(&gc);
307}
308
309static void
310do_wins_service(bool add, const struct tuntap *tt)
311{
312 ack_message_t ack;
313 struct gc_arena gc = gc_new();
314 HANDLE pipe = tt->options.msg_channel;
315 int addr_len = add ? tt->options.wins_len : 0;
316
317 if (tt->options.wins_len == 0)
318 {
319 /* nothing to do */
320 goto out;
321 }
322
324 sizeof(wins_cfg_message_t), 0 },
325 .iface = { .index = tt->adapter_index, .name = "" },
326 .addr_len = addr_len };
327
328 /* interface name is required */
329 strncpy(wins.iface.name, tt->actual_name, sizeof(wins.iface.name));
330 wins.iface.name[sizeof(wins.iface.name) - 1] = '\0';
331
332 if (addr_len > _countof(wins.addr))
333 {
334 addr_len = _countof(wins.addr);
335 wins.addr_len = addr_len;
336 msg(M_WARN, "Number of WINS addresses sent to service truncated to %d", addr_len);
337 }
338
339 for (int i = 0; i < addr_len; ++i)
340 {
341 wins.addr[i].ipv4.s_addr = htonl(tt->options.wins[i]);
342 }
343
344 msg(D_LOW, "%s WINS servers on '%s' (if_index = %d) using service",
345 (add ? "Setting" : "Deleting"), wins.iface.name, wins.iface.index);
346
347 if (!send_msg_iservice(pipe, &wins, sizeof(wins), &ack, "TUN"))
348 {
349 goto out;
350 }
351
352 if (ack.error_number != NO_ERROR)
353 {
354 msg(M_WARN, "TUN: %s WINS failed using service: %s [status=%u if_name=%s]",
355 (add ? "adding" : "deleting"), strerror_win32(ack.error_number, &gc), ack.error_number,
356 wins.iface.name);
357 goto out;
358 }
359
360 msg(M_INFO, "WINS servers %s using service", (add ? "set" : "deleted"));
361
362out:
363 gc_free(&gc);
364}
365
366static bool
367do_set_mtu_service(const struct tuntap *tt, const short family, const int mtu)
368{
369 bool ret = false;
370 ack_message_t ack;
371 struct gc_arena gc = gc_new();
372 HANDLE pipe = tt->options.msg_channel;
373 const char *family_name = (family == AF_INET6) ? "IPv6" : "IPv4";
374 set_mtu_message_t mtu_msg = { .header = { msg_set_mtu, sizeof(set_mtu_message_t), 0 },
375 .iface = { .index = tt->adapter_index },
376 .mtu = mtu,
377 .family = family };
378 strncpynt(mtu_msg.iface.name, tt->actual_name, sizeof(mtu_msg.iface.name));
379 if (family == AF_INET6 && mtu < 1280)
380 {
381 msg(M_INFO,
382 "NOTE: IPv6 interface MTU < 1280 conflicts with IETF standards and might not work");
383 }
384
385 if (!send_msg_iservice(pipe, &mtu_msg, sizeof(mtu_msg), &ack, "Set_mtu"))
386 {
387 goto out;
388 }
389
390 if (ack.error_number != NO_ERROR)
391 {
392 msg(M_NONFATAL, "TUN: setting %s mtu using service failed: %s [status=%u if_index=%d]",
393 family_name, strerror_win32(ack.error_number, &gc), ack.error_number,
394 mtu_msg.iface.index);
395 }
396 else
397 {
398 msg(M_INFO, "%s MTU set to %d on interface %d using service", family_name, mtu,
399 mtu_msg.iface.index);
400 ret = true;
401 }
402
403out:
404 gc_free(&gc);
405 return ret;
406}
407
408static void
409do_dns_domain_pwsh(bool add, const struct tuntap *tt)
410{
411 if (!tt->options.domain)
412 {
413 return;
414 }
415
416 struct argv argv = argv_new();
418 "%s%s -NoProfile -NonInteractive -Command Set-DnsClient -InterfaceIndex %lu -ConnectionSpecificSuffix '%s'",
421 tt->adapter_index,
422 add ? tt->options.domain : "");
423 exec_command("PowerShell", &argv, 1, M_WARN);
424
425 argv_free(&argv);
426}
427
436static bool
437do_create_adapter_service(HANDLE msg_channel, enum tun_driver_type driver_type)
438{
439 bool ret = false;
440 ack_message_t ack;
441 struct gc_arena gc = gc_new();
442
444 switch (driver_type)
445 {
448 break;
449
450 case DRIVER_DCO:
452 break;
453
454 default:
455 msg(M_NONFATAL, "Invalid backend driver %s", print_tun_backend_driver(driver_type));
456 goto out;
457 }
458
460 .header = { msg_create_adapter, sizeof(create_adapter_message_t), 0 }, .adapter_type = t
461 };
462
463 if (!send_msg_iservice(msg_channel, &msg, sizeof(msg), &ack, "create_adapter"))
464 {
465 goto out;
466 }
467
468 if (ack.error_number != NO_ERROR)
469 {
470 msg(M_NONFATAL, "TUN: creating %s adapter using service failed: %s [status=%u]",
472 ack.error_number);
473 }
474 else
475 {
476 msg(M_INFO, "%s adapter created using service", print_tun_backend_driver(driver_type));
477 ret = true;
478 }
479
480out:
481 gc_free(&gc);
482 return ret;
483}
484
485#endif /* ifdef _WIN32 */
486
487#ifdef TARGET_SOLARIS
488static void solaris_error_close(struct tuntap *tt, const struct env_set *es, const char *actual,
489 bool unplumb_inet6);
490
491#include <stropts.h>
492#endif
493
494#if defined(TARGET_DARWIN)
495#include <sys/kern_control.h>
496#include <net/if_utun.h>
497#include <sys/sys_domain.h>
498#endif
499
500static void clear_tuntap(struct tuntap *tuntap);
501
502bool
503is_dev_type(const char *dev, const char *dev_type, const char *match_type)
504{
505 ASSERT(match_type);
506 if (!dev)
507 {
508 return false;
509 }
510 if (dev_type)
511 {
512 return !strcmp(dev_type, match_type);
513 }
514 else
515 {
516 return !strncmp(dev, match_type, strlen(match_type));
517 }
518}
519
520int
521dev_type_enum(const char *dev, const char *dev_type)
522{
523 /* We pretend that the null device is also a tun device but it does not
524 * really matter as it will discard everything anyway */
525 if (is_dev_type(dev, dev_type, "tun") || is_dev_type(dev, dev_type, "null"))
526 {
527 return DEV_TYPE_TUN;
528 }
529 else if (is_dev_type(dev, dev_type, "tap"))
530 {
531 return DEV_TYPE_TAP;
532 }
533 else
534 {
535 return DEV_TYPE_UNDEF;
536 }
537}
538
539const char *
540dev_type_string(const char *dev, const char *dev_type)
541{
542 switch (dev_type_enum(dev, dev_type))
543 {
544 case DEV_TYPE_TUN:
545 return "tun";
546
547 case DEV_TYPE_TAP:
548 return "tap";
549
550 default:
551 return "[unknown-dev-type]";
552 }
553}
554
555/*
556 * Try to predict the actual TUN/TAP device instance name,
557 * before the device is actually opened.
558 */
559const char *
560guess_tuntap_dev(const char *dev, const char *dev_type, const char *dev_node, struct gc_arena *gc)
561{
562#ifdef _WIN32
563 const int dt = dev_type_enum(dev, dev_type);
564 if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP)
565 {
566 return netsh_get_id(dev_node, gc);
567 }
568#endif
569
570 /* default case */
571 return dev;
572}
573
574
575/* --ifconfig-nowarn disables some options sanity checking */
576static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)";
577
578/*
579 * If !tun_p2p, make sure ifconfig_remote_netmask looks
580 * like a netmask.
581 *
582 * If tun_p2p, make sure ifconfig_remote_netmask looks
583 * like an IPv4 address.
584 */
585static void
587{
588 struct gc_arena gc = gc_new();
589 const bool looks_like_netmask = ((addr & 0xFF000000) == 0xFF000000);
590 if (tun_p2p)
591 {
592 if (looks_like_netmask)
593 {
594 msg(M_WARN,
595 "WARNING: Since you are using --dev tun with a point-to-point topology, the second argument to --ifconfig must be an IP address. You are using something (%s) that looks more like a netmask. %s",
597 }
598 }
599 else
600 {
601 if (!looks_like_netmask)
602 {
603 msg(M_WARN,
604 "WARNING: Since you are using subnet topology, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. %s",
606 }
607 }
608 gc_free(&gc);
609}
610
611/*
612 * Check that --local and --remote addresses do not
613 * clash with ifconfig addresses or subnet.
614 */
615static void
616check_addr_clash(const char *name, int type, in_addr_t public, in_addr_t local,
617 in_addr_t remote_netmask)
618{
619 struct gc_arena gc = gc_new();
620#if 0
621 msg(M_INFO, "CHECK_ADDR_CLASH type=%d public=%s local=%s, remote_netmask=%s",
622 type,
623 print_in_addr_t(public, 0, &gc),
624 print_in_addr_t(local, 0, &gc),
625 print_in_addr_t(remote_netmask, 0, &gc));
626#endif
627
628 if (public)
629 {
630 if (type == DEV_TYPE_TUN)
631 {
632 const in_addr_t test_netmask = 0xFFFFFF00;
633 const in_addr_t public_net = public & test_netmask;
634 const in_addr_t local_net = local & test_netmask;
635 const in_addr_t remote_net = remote_netmask & test_netmask;
636
637 if (public == local || public == remote_netmask)
638 {
639 msg(M_WARN,
640 "WARNING: --%s address [%s] conflicts with --ifconfig address pair [%s, %s]. %s",
641 name, print_in_addr_t(public, 0, &gc), print_in_addr_t(local, 0, &gc),
642 print_in_addr_t(remote_netmask, 0, &gc), ifconfig_warn_how_to_silence);
643 }
644
645 if (public_net == local_net || public_net == remote_net)
646 {
647 msg(M_WARN,
648 "WARNING: potential conflict between --%s address [%s] and --ifconfig address pair [%s, %s] -- this is a warning only that is triggered when local/remote addresses exist within the same /24 subnet as --ifconfig endpoints. %s",
649 name, print_in_addr_t(public, 0, &gc), print_in_addr_t(local, 0, &gc),
650 print_in_addr_t(remote_netmask, 0, &gc), ifconfig_warn_how_to_silence);
651 }
652 }
653 else if (type == DEV_TYPE_TAP)
654 {
655 const in_addr_t public_network = public & remote_netmask;
656 const in_addr_t virtual_network = local & remote_netmask;
657 if (public_network == virtual_network)
658 {
659 msg(M_WARN,
660 "WARNING: --%s address [%s] conflicts with --ifconfig subnet [%s, %s] -- local and remote addresses cannot be inside of the --ifconfig subnet. %s",
661 name, print_in_addr_t(public, 0, &gc), print_in_addr_t(local, 0, &gc),
662 print_in_addr_t(remote_netmask, 0, &gc), ifconfig_warn_how_to_silence);
663 }
664 }
665 }
666 gc_free(&gc);
667}
668
669void
671{
672 struct gc_arena gc = gc_new();
673 struct route_gateway_info rgi;
674 const unsigned int needed = (RGI_ADDR_DEFINED | RGI_NETMASK_DEFINED);
675
676 get_default_gateway(&rgi, 0, ctx);
677 if ((rgi.flags & needed) == needed)
678 {
679 const in_addr_t lan_network = rgi.gateway.addr & rgi.gateway.netmask;
680 if (lan_network == 0xC0A80000 || lan_network == 0xC0A80100)
681 {
682 msg(M_WARN,
683 "NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x. Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.");
684 }
685 }
686 gc_free(&gc);
687}
688
689/*
690 * Return a string to be used for options compatibility check
691 * between peers.
692 */
693const char *
694ifconfig_options_string(const struct tuntap *tt, bool remote, bool disable, struct gc_arena *gc)
695{
696 struct buffer out = alloc_buf_gc(256, gc);
697 if (tt->did_ifconfig_setup && !disable)
698 {
699 if (!is_tun_p2p(tt))
700 {
701 buf_printf(&out, "%s %s", print_in_addr_t(tt->local & tt->remote_netmask, 0, gc),
702 print_in_addr_t(tt->remote_netmask, 0, gc));
703 }
704 else if (tt->type == DEV_TYPE_TUN) /* tun p2p topology */
705 {
706 const char *l, *r;
707 if (remote)
708 {
709 r = print_in_addr_t(tt->local, 0, gc);
710 l = print_in_addr_t(tt->remote_netmask, 0, gc);
711 }
712 else
713 {
714 l = print_in_addr_t(tt->local, 0, gc);
715 r = print_in_addr_t(tt->remote_netmask, 0, gc);
716 }
717 buf_printf(&out, "%s %s", r, l);
718 }
719 else
720 {
721 buf_printf(&out, "[undef]");
722 }
723 }
724 return BSTR(&out);
725}
726
727/*
728 * Return a status string describing wait state.
729 */
730const char *
731tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
732{
733 struct buffer out = alloc_buf_gc(64, gc);
734 if (tt)
735 {
736 if (rwflags & EVENT_READ)
737 {
738 buf_printf(&out, "T%s", (tt->rwflags_debug & EVENT_READ) ? "R" : "r");
739#ifdef _WIN32
740 buf_printf(&out, "%s", overlapped_io_state_ascii(&tt->reads));
741#endif
742 }
743 if (rwflags & EVENT_WRITE)
744 {
745 buf_printf(&out, "T%s", (tt->rwflags_debug & EVENT_WRITE) ? "W" : "w");
746#ifdef _WIN32
747 buf_printf(&out, "%s", overlapped_io_state_ascii(&tt->writes));
748#endif
749 }
750 }
751 else
752 {
753 buf_printf(&out, "T?");
754 }
755 return BSTR(&out);
756}
757
758/*
759 * Return true for point-to-point topology, false for subnet topology
760 */
761bool
762is_tun_p2p(const struct tuntap *tt)
763{
764 bool tun_p2p = false;
765
766 if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
767 {
768 tun_p2p = false;
769 }
770 else if (tt->type == DEV_TYPE_TUN)
771 {
772 tun_p2p = true;
773 }
774 else
775 {
776 msg(M_FATAL, "Error: problem with tun vs. tap setting"); /* JYFIXME -- needs to be caught
777 earlier, in init_tun? */
778 }
779 return tun_p2p;
780}
781
782/*
783 * Set the ifconfig_* environment variables, both for IPv4 and IPv6
784 */
785void
786do_ifconfig_setenv(const struct tuntap *tt, struct env_set *es)
787{
788 struct gc_arena gc = gc_new();
789 const char *ifconfig_local = print_in_addr_t(tt->local, 0, &gc);
790 const char *ifconfig_remote_netmask = print_in_addr_t(tt->remote_netmask, 0, &gc);
791
792 /*
793 * Set environmental variables with ifconfig parameters.
794 */
795 if (tt->did_ifconfig_setup)
796 {
797 bool tun = is_tun_p2p(tt);
798
799 setenv_str(es, "ifconfig_local", ifconfig_local);
800 if (tun)
801 {
802 setenv_str(es, "ifconfig_remote", ifconfig_remote_netmask);
803 }
804 else
805 {
806 setenv_str(es, "ifconfig_netmask", ifconfig_remote_netmask);
807 }
808 }
809
811 {
812 const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
813 const char *ifconfig_ipv6_remote = print_in6_addr(tt->remote_ipv6, 0, &gc);
814
815 setenv_str(es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
816 setenv_int(es, "ifconfig_ipv6_netbits", tt->netbits_ipv6);
817 setenv_str(es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
818 }
819
820 gc_free(&gc);
821}
822
823/*
824 * Init tun/tap object.
825 *
826 * Set up tuntap structure for ifconfig,
827 * but don't execute yet.
828 */
829struct tuntap *
830init_tun(const char *dev, /* --dev option */
831 const char *dev_type, /* --dev-type option */
832 int topology, /* one of the TOP_x values */
833 const char *ifconfig_local_parm, /* --ifconfig parm 1 */
834 const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
835 const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
836 int ifconfig_ipv6_netbits_parm,
837 const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
838 struct addrinfo *local_public, struct addrinfo *remote_public, const bool strict_warn,
839 struct env_set *es, openvpn_net_ctx_t *ctx, struct tuntap *tt)
840{
841 if (!tt)
842 {
843 ALLOC_OBJ(tt, struct tuntap);
844 clear_tuntap(tt);
845 }
846
847 tt->type = dev_type_enum(dev, dev_type);
848 tt->topology = topology;
849
850 if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
851 {
852 /*
853 * We only handle TUN/TAP devices here, not --dev null devices.
854 */
855 bool tun_p2p = is_tun_p2p(tt);
856
857 /*
858 * Convert arguments to binary IPv4 addresses.
859 */
860
861 tt->local =
863 ifconfig_local_parm, 0, NULL, NULL);
864
867 ifconfig_remote_netmask_parm, 0, NULL, NULL);
868
869 /*
870 * Look for common errors in --ifconfig parms
871 */
872 if (strict_warn)
873 {
874 struct addrinfo *curele;
876
877 /*
878 * If local_public or remote_public addresses are defined,
879 * make sure they do not clash with our virtual subnet.
880 */
881
882 for (curele = local_public; curele; curele = curele->ai_next)
883 {
884 if (curele->ai_family == AF_INET)
885 {
886 const in_addr_t local =
887 ntohl(((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
888 check_addr_clash("local", tt->type, local, tt->local, tt->remote_netmask);
889 }
890 }
891
892 for (curele = remote_public; curele; curele = curele->ai_next)
893 {
894 if (curele->ai_family == AF_INET)
895 {
896 const in_addr_t remote =
897 ntohl(((struct sockaddr_in *)curele->ai_addr)->sin_addr.s_addr);
898 check_addr_clash("remote", tt->type, remote, tt->local, tt->remote_netmask);
899 }
900 }
901 }
902
903#ifdef _WIN32
904 /*
905 * Make sure that both ifconfig addresses are part of the
906 * same .252 subnet.
907 */
908 if (tun_p2p)
909 {
911 tt->adapter_netmask = ~3;
912 }
913 else
914 {
916 }
917#endif
918
919 tt->did_ifconfig_setup = true;
920 }
921
922 if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm)
923 {
924 /*
925 * Convert arguments to binary IPv6 addresses.
926 */
927
928 if (inet_pton(AF_INET6, ifconfig_ipv6_local_parm, &tt->local_ipv6) != 1
929 || inet_pton(AF_INET6, ifconfig_ipv6_remote_parm, &tt->remote_ipv6) != 1)
930 {
931 msg(M_FATAL, "init_tun: problem converting IPv6 ifconfig addresses %s and %s to binary",
932 ifconfig_ipv6_local_parm, ifconfig_ipv6_remote_parm);
933 }
934 tt->netbits_ipv6 = ifconfig_ipv6_netbits_parm;
935
936 tt->did_ifconfig_ipv6_setup = true;
937 }
938
939 /*
940 * Set environmental variables with ifconfig parameters.
941 */
942 if (es)
943 {
945 }
946
947 return tt;
948}
949
950/*
951 * Platform specific tun initializations
952 */
953void
954init_tun_post(struct tuntap *tt, const struct frame *frame, const struct tuntap_options *options)
955{
956 tt->options = *options;
957#ifdef _WIN32
958 if (tt->backend_driver == DRIVER_DCO)
959 {
960 tt->dco.tt = tt;
961 return;
962 }
963
964 overlapped_io_init(&tt->reads, frame, FALSE);
965 overlapped_io_init(&tt->writes, frame, TRUE);
967
968 tt->rw_handle.read = tt->reads.overlapped.hEvent;
969 tt->rw_handle.write = tt->writes.overlapped.hEvent;
970#endif /* ifdef _WIN32 */
971}
972
973#if defined(_WIN32)
974
975/* some of the platforms will auto-add a "network route" pointing
976 * to the interface on "ifconfig tunX 2001:db8::1/64", others need
977 * an extra call to "route add..."
978 * -> helper function to simplify code below
979 */
980static void
981add_route_connected_v6_net(struct tuntap *tt, const struct env_set *es)
982{
983 struct route_ipv6 r6;
984
985 CLEAR(r6);
986 r6.network = tt->local_ipv6;
987 r6.netbits = tt->netbits_ipv6;
988 r6.gateway = tt->local_ipv6;
989 r6.metric = 0; /* connected route */
991 add_route_ipv6(&r6, tt, 0, es, NULL);
992}
993
994void
996{
997 struct route_ipv6 r6;
998
999 CLEAR(r6);
1000 r6.network = tt->local_ipv6;
1001 r6.netbits = tt->netbits_ipv6;
1002 r6.gateway = tt->local_ipv6;
1003 r6.metric = 0; /* connected route */
1006 delete_route_ipv6(&r6, tt, NULL, NULL);
1007}
1008#endif /* if defined(_WIN32) || defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || \
1009 defined(TARGET_OPENBSD) */
1010
1011#if defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) || defined(TARGET_NETBSD) \
1012 || defined(TARGET_OPENBSD)
1013/* we can't use true subnet mode on tun on all platforms, as that
1014 * conflicts with IPv6 (wants to use ND then, which we don't do),
1015 * but the OSes want "a remote address that is different from ours"
1016 * - so we construct one, normally the first in the subnet, but if
1017 * this is the same as ours, use the second one.
1018 * The actual address does not matter at all, as the tun interface
1019 * is still point to point and no layer 2 resolution is done...
1020 */
1021
1023create_arbitrary_remote(struct tuntap *tt)
1024{
1025 in_addr_t remote;
1026
1027 remote = (tt->local & tt->remote_netmask) + 1;
1028
1029 if (remote == tt->local)
1030 {
1031 remote++;
1032 }
1033
1034 return remote;
1035}
1036#endif
1037
1047static void
1048do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es,
1049 openvpn_net_ctx_t *ctx)
1050{
1051#if !defined(TARGET_LINUX)
1052 struct argv argv = argv_new();
1053 struct gc_arena gc = gc_new();
1054 const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
1055#endif
1056
1057#if defined(TARGET_LINUX)
1058 if (net_iface_mtu_set(ctx, ifname, tun_mtu) < 0)
1059 {
1060 msg(M_FATAL, "Linux can't set mtu (%d) on %s", tun_mtu, ifname);
1061 }
1062
1063 if (net_iface_up(ctx, ifname, true) < 0)
1064 {
1065 msg(M_FATAL, "Linux can't bring %s up", ifname);
1066 }
1067
1068 if (net_addr_v6_add(ctx, ifname, &tt->local_ipv6, tt->netbits_ipv6) < 0)
1069 {
1070 msg(M_FATAL, "Linux can't add IPv6 to interface %s", ifname);
1071 }
1072#elif defined(TARGET_ANDROID)
1073 char out6[64];
1074
1075 snprintf(out6, sizeof(out6), "%s/%d %d", ifconfig_ipv6_local, tt->netbits_ipv6, tun_mtu);
1076 management_android_control(management, "IFCONFIG6", out6);
1077#elif defined(TARGET_SOLARIS)
1078 argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, ifname);
1079 argv_msg(M_INFO, &argv);
1080 openvpn_execve_check(&argv, es, 0, NULL);
1081
1082 if (tt->type == DEV_TYPE_TUN)
1083 {
1084 const char *ifconfig_ipv6_remote = print_in6_addr(tt->remote_ipv6, 0, &gc);
1085
1086 argv_printf(&argv, "%s %s inet6 plumb %s/%d %s mtu %d up", IFCONFIG_PATH, ifname,
1087 ifconfig_ipv6_local, tt->netbits_ipv6, ifconfig_ipv6_remote, tun_mtu);
1088 }
1089 else /* tap mode */
1090 {
1091 /* base IPv6 tap interface needs to be brought up first */
1092 argv_printf(&argv, "%s %s inet6 plumb up", IFCONFIG_PATH, ifname);
1093 argv_msg(M_INFO, &argv);
1094
1095 if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 (prepare) failed"))
1096 {
1097 solaris_error_close(tt, es, ifname, true);
1098 }
1099
1100 /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
1101 * after the system has noticed the interface and fired up
1102 * the DHCPv6 client - but this takes quite a while, and the
1103 * server will ignore the DHCPv6 packets anyway. So we don't.
1104 */
1105
1106 /* static IPv6 addresses need to go to a subinterface (tap0:1)
1107 * and we cannot set an mtu here (must go to the "parent")
1108 */
1109 argv_printf(&argv, "%s %s inet6 addif %s/%d up", IFCONFIG_PATH, ifname, ifconfig_ipv6_local,
1110 tt->netbits_ipv6);
1111 }
1112 argv_msg(M_INFO, &argv);
1113
1114 if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 failed"))
1115 {
1116 solaris_error_close(tt, es, ifname, true);
1117 }
1118
1119 if (tt->type != DEV_TYPE_TUN)
1120 {
1121 argv_printf(&argv, "%s %s inet6 mtu %d", IFCONFIG_PATH, ifname, tun_mtu);
1122 argv_msg(M_INFO, &argv);
1123 openvpn_execve_check(&argv, es, 0, "Solaris ifconfig IPv6 mtu failed");
1124 }
1125#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) || defined(TARGET_DARWIN) \
1126 || defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1127 argv_printf(&argv, "%s %s inet6 %s/%d mtu %d up", IFCONFIG_PATH, ifname, ifconfig_ipv6_local,
1128 tt->netbits_ipv6, tun_mtu);
1129 argv_msg(M_INFO, &argv);
1130
1131 openvpn_execve_check(&argv, es, S_FATAL, "generic BSD ifconfig inet6 failed");
1132
1133#if defined(TARGET_FREEBSD) && __FreeBSD_version >= 1200000 && __FreeBSD_version < 1300000
1134 /* On FreeBSD 12.0-12.4, there is ipv6_activate_all_interfaces="YES"
1135 * in rc.conf, which is not set by default. If it is *not* set,
1136 * "all new interfaces that are not already up" are configured by
1137 * devd -> /etc/pccard_ether -> /etc/network.subr as "inet6 ifdisabled".
1138 *
1139 * The "is this interface already up?" test is a non-zero time window
1140 * which we manage to hit with our ifconfig often enough to cause
1141 * frequent fails in the openvpn test environment.
1142 *
1143 * Thus: assume that the system might interfere, wait for things to
1144 * settle (it's a very short time window), and remove -ifdisable again.
1145 *
1146 * See: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=248172
1147 */
1148 sleep(1);
1149 argv_printf(&argv, "%s %s inet6 -ifdisabled", IFCONFIG_PATH, ifname);
1150 argv_msg(M_INFO, &argv);
1151
1152 openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD BSD 'ifconfig inet6 -ifdisabled' failed");
1153#endif
1154
1155#elif defined(TARGET_AIX)
1156 argv_printf(&argv, "%s %s inet6 %s/%d mtu %d up", IFCONFIG_PATH, ifname, ifconfig_ipv6_local,
1157 tt->netbits_ipv6, tun_mtu);
1158 argv_msg(M_INFO, &argv);
1159
1160 /* AIX ifconfig will complain if it can't find ODM path in env */
1161 es = env_set_create(NULL);
1162 env_set_add(es, "ODMDIR=/etc/objrepos");
1163
1164 openvpn_execve_check(&argv, es, S_FATAL, "generic BSD ifconfig inet6 failed");
1165
1167#elif defined(_WIN32)
1169 {
1170 msg(M_INFO,
1171 "******** NOTE: Please manually set the v6 IP of '%s' to %s (if it is not already set)",
1172 ifname, ifconfig_ipv6_local);
1173 }
1174 else if (tt->options.msg_channel)
1175 {
1176 do_address_service(true, AF_INET6, tt);
1177 if (tt->type == DEV_TYPE_TUN)
1178 {
1180 }
1181 do_dns_service(true, AF_INET6, tt);
1182 do_set_mtu_service(tt, AF_INET6, tun_mtu);
1183 /* If IPv4 is not enabled, set DNS domain here */
1184 if (!tt->did_ifconfig_setup)
1185 {
1186 do_dns_domain_service(true, tt);
1187 }
1188 }
1189 else
1190 {
1191 /* example: netsh interface ipv6 set address 42
1192 * 2001:608:8003::d/bits store=active
1193 */
1194
1195 /* in TUN mode, we only simulate a subnet, so the interface
1196 * is configured with /128 + a route to fe80::8. In TAP mode,
1197 * the correct netbits must be set, and no on-link route
1198 */
1199 int netbits = (tt->type == DEV_TYPE_TUN) ? 128 : tt->netbits_ipv6;
1200
1201 argv_printf(&argv, "%s%s interface ipv6 set address %lu %s/%d store=active",
1202 get_win_sys_path(), NETSH_PATH_SUFFIX, tt->adapter_index, ifconfig_ipv6_local,
1203 netbits);
1205 if (tt->type == DEV_TYPE_TUN)
1206 {
1208 }
1209 /* set ipv6 dns servers if any are specified */
1211 windows_set_mtu(tt->adapter_index, AF_INET6, tun_mtu);
1212
1213 if (!tt->did_ifconfig_setup)
1214 {
1215 do_dns_domain_pwsh(true, tt);
1216 }
1217 }
1218#else /* platforms we have no IPv6 code for */
1219 msg(M_FATAL,
1220 "Sorry, but I don't know how to do IPv6 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
1221#endif /* outer "if defined(TARGET_xxx)" conditional */
1222
1223#if !defined(TARGET_LINUX)
1224 gc_free(&gc);
1225 argv_free(&argv);
1226#endif
1227}
1228
1238static void
1239do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es,
1240 openvpn_net_ctx_t *ctx)
1241{
1242#if !defined(_WIN32) && !defined(TARGET_ANDROID)
1243 /*
1244 * We only handle TUN/TAP devices here, not --dev null devices.
1245 */
1246 bool tun_p2p = is_tun_p2p(tt);
1247#endif
1248
1249#if !defined(TARGET_LINUX)
1250 const char *ifconfig_local = NULL;
1251 const char *ifconfig_remote_netmask = NULL;
1252 struct argv argv = argv_new();
1253 struct gc_arena gc = gc_new();
1254
1255 /*
1256 * Set ifconfig parameters
1257 */
1258 ifconfig_local = print_in_addr_t(tt->local, 0, &gc);
1259 ifconfig_remote_netmask = print_in_addr_t(tt->remote_netmask, 0, &gc);
1260#endif
1261
1262#if defined(TARGET_LINUX)
1263 if (net_iface_mtu_set(ctx, ifname, tun_mtu) < 0)
1264 {
1265 msg(M_FATAL, "Linux can't set mtu (%d) on %s", tun_mtu, ifname);
1266 }
1267
1268 if (net_iface_up(ctx, ifname, true) < 0)
1269 {
1270 msg(M_FATAL, "Linux can't bring %s up", ifname);
1271 }
1272
1273 if (tun_p2p)
1274 {
1275 if (net_addr_ptp_v4_add(ctx, ifname, &tt->local, &tt->remote_netmask) < 0)
1276 {
1277 msg(M_FATAL, "Linux can't add IP to interface %s", ifname);
1278 }
1279 }
1280 else
1281 {
1282 if (net_addr_v4_add(ctx, ifname, &tt->local, netmask_to_netbits2(tt->remote_netmask)) < 0)
1283 {
1284 msg(M_FATAL, "Linux can't add IP to interface %s", ifname);
1285 }
1286 }
1287#elif defined(TARGET_ANDROID)
1288 char out[64];
1289
1290 snprintf(out, sizeof(out), "%s %s %d %s", ifconfig_local, ifconfig_remote_netmask, tun_mtu,
1292 management_android_control(management, "IFCONFIG", out);
1293
1294#elif defined(TARGET_SOLARIS)
1295 /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
1296 * example:
1297 * ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up
1298 * ifconfig tun2 netmask 255.255.255.255
1299 */
1300 if (tun_p2p)
1301 {
1302 argv_printf(&argv, "%s %s %s %s mtu %d up", IFCONFIG_PATH, ifname, ifconfig_local,
1303 ifconfig_remote_netmask, tun_mtu);
1304
1305 argv_msg(M_INFO, &argv);
1306 if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-1 failed"))
1307 {
1308 solaris_error_close(tt, es, ifname, false);
1309 }
1310
1311 argv_printf(&argv, "%s %s netmask 255.255.255.255", IFCONFIG_PATH, ifname);
1312 }
1313 else if (tt->type == DEV_TYPE_TUN)
1314 {
1315 argv_printf(&argv, "%s %s %s %s netmask %s mtu %d up", IFCONFIG_PATH, ifname,
1316 ifconfig_local, ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1317 }
1318 else /* tap */
1319 {
1320 argv_printf(&argv, "%s %s %s netmask %s up", IFCONFIG_PATH, ifname, ifconfig_local,
1321 ifconfig_remote_netmask);
1322 }
1323
1324 argv_msg(M_INFO, &argv);
1325 if (!openvpn_execve_check(&argv, es, 0, "Solaris ifconfig phase-2 failed"))
1326 {
1327 solaris_error_close(tt, es, ifname, false);
1328 }
1329
1330 if (!tun_p2p && tt->type == DEV_TYPE_TUN)
1331 {
1332 /* Add a network route for the local tun interface */
1333 struct route_ipv4 r;
1334 CLEAR(r);
1336 r.network = tt->local & tt->remote_netmask;
1337 r.netmask = tt->remote_netmask;
1338 r.gateway = tt->local;
1339 r.metric = 0;
1340 add_route(&r, tt, 0, NULL, es, NULL);
1341 }
1342
1343#elif defined(TARGET_OPENBSD)
1344
1345 in_addr_t remote_end; /* for "virtual" subnet topology */
1346
1347 /*
1348 * On OpenBSD, tun interfaces are persistent if created with
1349 * "ifconfig tunX create", and auto-destroyed if created by
1350 * opening "/dev/tunX" (so we just use the /dev/tunX)
1351 */
1352
1353 /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
1354 if (tun_p2p)
1355 {
1356 argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up -link0", IFCONFIG_PATH,
1357 ifname, ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1358 }
1359 else if (tt->type == DEV_TYPE_TUN)
1360 {
1361 remote_end = create_arbitrary_remote(tt);
1362 argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up -link0", IFCONFIG_PATH, ifname,
1363 ifconfig_local, print_in_addr_t(remote_end, 0, &gc), tun_mtu,
1364 ifconfig_remote_netmask);
1365 }
1366 else /* tap */
1367 {
1368 argv_printf(&argv, "%s %s %s netmask %s mtu %d link0", IFCONFIG_PATH, ifname,
1369 ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1370 }
1371 argv_msg(M_INFO, &argv);
1372 openvpn_execve_check(&argv, es, S_FATAL, "OpenBSD ifconfig failed");
1373
1374 /* Add a network route for the local tun interface */
1375 if (!tun_p2p && tt->type == DEV_TYPE_TUN)
1376 {
1377 struct route_ipv4 r;
1378 CLEAR(r);
1379 r.flags = RT_DEFINED;
1380 r.network = tt->local & tt->remote_netmask;
1381 r.netmask = tt->remote_netmask;
1382 r.gateway = remote_end;
1383 add_route(&r, tt, 0, NULL, es, NULL);
1384 }
1385
1386#elif defined(TARGET_NETBSD)
1387 in_addr_t remote_end = INADDR_ANY; /* for "virtual" subnet topology */
1388
1389 if (tun_p2p)
1390 {
1391 argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", IFCONFIG_PATH, ifname,
1392 ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1393 }
1394 else if (tt->type == DEV_TYPE_TUN)
1395 {
1396 remote_end = create_arbitrary_remote(tt);
1397 argv_printf(&argv, "%s %s %s %s mtu %d netmask %s up", IFCONFIG_PATH, ifname,
1398 ifconfig_local, print_in_addr_t(remote_end, 0, &gc), tun_mtu,
1399 ifconfig_remote_netmask);
1400 }
1401 else /* tap */
1402 {
1403 /*
1404 * NetBSD has distinct tun and tap devices
1405 * so we don't need the "link0" extra parameter to specify we want to do
1406 * tunneling at the ethernet level
1407 */
1408 argv_printf(&argv, "%s %s %s netmask %s mtu %d", IFCONFIG_PATH, ifname, ifconfig_local,
1409 ifconfig_remote_netmask, tun_mtu);
1410 }
1411 argv_msg(M_INFO, &argv);
1412 openvpn_execve_check(&argv, es, S_FATAL, "NetBSD ifconfig failed");
1413
1414 /* Add a network route for the local tun interface */
1415 if (!tun_p2p && tt->type == DEV_TYPE_TUN)
1416 {
1417 struct route_ipv4 r;
1418 CLEAR(r);
1419 r.flags = RT_DEFINED;
1420 r.network = tt->local & tt->remote_netmask;
1421 r.netmask = tt->remote_netmask;
1422 r.gateway = remote_end;
1423 add_route(&r, tt, 0, NULL, es, NULL);
1424 }
1425
1426#elif defined(TARGET_DARWIN)
1427 /*
1428 * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD...
1429 */
1430
1431 argv_printf(&argv, "%s %s delete", IFCONFIG_PATH, ifname);
1432 argv_msg(M_INFO, &argv);
1433 openvpn_execve_check(&argv, es, 0, NULL);
1434 msg(M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure");
1435
1436
1437 /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
1438 if (tun_p2p)
1439 {
1440 argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", IFCONFIG_PATH, ifname,
1441 ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1442 }
1443 else if (tt->type == DEV_TYPE_TUN)
1444 {
1445 argv_printf(&argv, "%s %s %s %s netmask %s mtu %d up", IFCONFIG_PATH, ifname,
1446 ifconfig_local, ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1447 }
1448 else /* tap */
1449 {
1450 argv_printf(&argv, "%s %s %s netmask %s mtu %d up", IFCONFIG_PATH, ifname, ifconfig_local,
1451 ifconfig_remote_netmask, tun_mtu);
1452 }
1453
1454 argv_msg(M_INFO, &argv);
1455 openvpn_execve_check(&argv, es, S_FATAL, "Mac OS X ifconfig failed");
1456
1457 /* Add a network route for the local tun interface */
1458 if (!tun_p2p && tt->type == DEV_TYPE_TUN)
1459 {
1460 struct route_ipv4 r;
1461 CLEAR(r);
1462 r.flags = RT_DEFINED;
1463 r.network = tt->local & tt->remote_netmask;
1464 r.netmask = tt->remote_netmask;
1465 r.gateway = tt->local;
1466 add_route(&r, tt, 0, NULL, es, NULL);
1467 }
1468
1469#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
1470
1471 /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
1472 if (tun_p2p) /* point-to-point tun */
1473 {
1474 argv_printf(&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", IFCONFIG_PATH, ifname,
1475 ifconfig_local, ifconfig_remote_netmask, tun_mtu);
1476 }
1477 else /* tun with topology subnet and tap mode (always subnet) */
1478 {
1479 int netbits = netmask_to_netbits2(tt->remote_netmask);
1480 argv_printf(&argv, "%s %s %s/%d mtu %d up", IFCONFIG_PATH, ifname, ifconfig_local, netbits,
1481 tun_mtu);
1482 }
1483
1484 argv_msg(M_INFO, &argv);
1485 openvpn_execve_check(&argv, es, S_FATAL, "FreeBSD ifconfig failed");
1486
1487#elif defined(TARGET_AIX)
1488 {
1489 /* AIX ifconfig will complain if it can't find ODM path in env */
1490 struct env_set *aix_es = env_set_create(NULL);
1491 env_set_add(aix_es, "ODMDIR=/etc/objrepos");
1492
1493 if (tt->type == DEV_TYPE_TUN)
1494 {
1495 msg(M_FATAL, "no tun support on AIX (canthappen)");
1496 }
1497
1498 /* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */
1499 argv_printf(&argv, "%s %s %s netmask %s mtu %d up", IFCONFIG_PATH, ifname, ifconfig_local,
1500 ifconfig_remote_netmask, tun_mtu);
1501
1502 argv_msg(M_INFO, &argv);
1503 openvpn_execve_check(&argv, aix_es, S_FATAL, "AIX ifconfig failed");
1504
1505 env_set_destroy(aix_es);
1506 }
1507#elif defined(_WIN32)
1509 {
1510 msg(M_INFO,
1511 "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)",
1512 ifname, ifconfig_local, ifconfig_remote_netmask);
1513 }
1516 {
1517 /* Let the DHCP configure the interface. */
1518 }
1519 else if (tt->options.msg_channel)
1520 {
1521 do_address_service(true, AF_INET, tt);
1522 do_dns_service(true, AF_INET, tt);
1523 do_dns_domain_service(true, tt);
1524 do_wins_service(true, tt);
1525 }
1526 else
1527 {
1529 {
1532 }
1533
1534 do_dns_domain_pwsh(true, tt);
1535 }
1536
1537
1538 if (tt->options.msg_channel)
1539 {
1540 do_set_mtu_service(tt, AF_INET, tun_mtu);
1541 }
1542 else
1543 {
1544 windows_set_mtu(tt->adapter_index, AF_INET, tun_mtu);
1545 }
1546#elif defined(TARGET_HAIKU)
1547 /* example: ifconfig tun/0 inet 1.1.1.1 255.255.255.0 mtu 1450 up */
1548 argv_printf(&argv, "%s %s inet %s %s mtu %d up", IFCONFIG_PATH, ifname, ifconfig_local,
1549 ifconfig_remote_netmask, tun_mtu);
1550
1551 argv_msg(M_INFO, &argv);
1552 openvpn_execve_check(&argv, es, S_FATAL, "Haiku ifconfig failed");
1553#else /* if defined(TARGET_LINUX) */
1554 msg(M_FATAL,
1555 "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
1556#endif /* if defined(TARGET_LINUX) */
1557
1558#if !defined(TARGET_LINUX)
1559 gc_free(&gc);
1560 argv_free(&argv);
1561#endif
1562}
1563
1564/* execute the ifconfig command through the shell */
1565void
1566do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es,
1567 openvpn_net_ctx_t *ctx)
1568{
1569 msg(D_LOW, "do_ifconfig, ipv4=%d, ipv6=%d", tt->did_ifconfig_setup,
1571
1572#ifdef ENABLE_MANAGEMENT
1573 if (management)
1574 {
1576 NULL, NULL);
1577 }
1578#endif
1579
1580 if (tt->did_ifconfig_setup)
1581 {
1582 do_ifconfig_ipv4(tt, ifname, tun_mtu, es, ctx);
1583 }
1584
1586 {
1587 do_ifconfig_ipv6(tt, ifname, tun_mtu, es, ctx);
1588 }
1589
1590 /* release resources potentially allocated during interface setup */
1591 net_ctx_free(ctx);
1592}
1593
1594static void
1596{
1597#if defined(TARGET_LINUX)
1598 int netbits = netmask_to_netbits2(tt->remote_netmask);
1599
1600 if (is_tun_p2p(tt))
1601 {
1602 if (net_addr_ptp_v4_del(ctx, tt->actual_name, &tt->local, &tt->remote_netmask) < 0)
1603 {
1604 msg(M_WARN, "Linux can't del IP from iface %s", tt->actual_name);
1605 }
1606 }
1607 else
1608 {
1609 if (net_addr_v4_del(ctx, tt->actual_name, &tt->local, netbits) < 0)
1610 {
1611 msg(M_WARN, "Linux can't del IP from iface %s", tt->actual_name);
1612 }
1613 }
1614#elif defined(TARGET_FREEBSD)
1615 struct gc_arena gc = gc_new();
1616 const char *ifconfig_local = print_in_addr_t(tt->local, 0, &gc);
1617 struct argv argv = argv_new();
1618
1619 argv_printf(&argv, "%s %s %s -alias", IFCONFIG_PATH, tt->actual_name, ifconfig_local);
1620 argv_msg(M_INFO, &argv);
1621 openvpn_execve_check(&argv, NULL, 0, "FreeBSD ip addr del failed");
1622
1623 argv_free(&argv);
1624 gc_free(&gc);
1625#endif /* if defined(TARGET_LINUX) */
1626 /* Empty for _WIN32 and all other unixoid platforms */
1627}
1628
1629static void
1631{
1632#if defined(TARGET_LINUX)
1633 if (net_addr_v6_del(ctx, tt->actual_name, &tt->local_ipv6, tt->netbits_ipv6) < 0)
1634 {
1635 msg(M_WARN, "Linux can't del IPv6 from iface %s", tt->actual_name);
1636 }
1637#elif defined(TARGET_FREEBSD)
1638 struct gc_arena gc = gc_new();
1639 const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
1640 struct argv argv = argv_new();
1641
1642 argv_printf(&argv, "%s %s inet6 %s/%d -alias", IFCONFIG_PATH, tt->actual_name,
1643 ifconfig_ipv6_local, tt->netbits_ipv6);
1644
1645 argv_msg(M_INFO, &argv);
1646 openvpn_execve_check(&argv, NULL, 0, "FreeBSD ip -6 addr del failed");
1647
1648 argv_free(&argv);
1649 gc_free(&gc);
1650#endif /* if defined(TARGET_LINUX) */
1651 /* Empty for _WIN32 and all other unixoid platforms */
1652}
1653
1654void
1656{
1658 {
1659 if (tt->did_ifconfig_setup)
1660 {
1661 undo_ifconfig_ipv4(tt, ctx);
1662 }
1663
1665 {
1666 undo_ifconfig_ipv6(tt, ctx);
1667 }
1668
1669 /* release resources potentially allocated during undo */
1670 net_ctx_reset(ctx);
1671 }
1672}
1673
1674static void
1676{
1677 CLEAR(*tuntap);
1678#ifdef _WIN32
1679 tuntap->hand = NULL;
1680#else
1681 tuntap->fd = -1;
1682#endif
1683#ifdef TARGET_SOLARIS
1684 tuntap->ip_fd = -1;
1685#endif
1686}
1687
1688#if defined(TARGET_OPENBSD) || defined(TARGET_DARWIN)
1689
1690/*
1691 * OpenBSD and Mac OS X when using utun
1692 * have a slightly incompatible TUN device from
1693 * the rest of the world, in that it prepends a
1694 * uint32 to the beginning of the IP header
1695 * to designate the protocol (why not just
1696 * look at the version field in the IP header to
1697 * determine v4 or v6?).
1698 *
1699 * We strip off this field on reads and
1700 * put it back on writes.
1701 *
1702 * I have not tested TAP devices on OpenBSD,
1703 * but I have conditionalized the special
1704 * TUN handling code described above to
1705 * go away for TAP devices.
1706 */
1707
1708#include <netinet/ip.h>
1709#include <sys/uio.h>
1710
1711static inline int
1712header_modify_read_write_return(int len)
1713{
1714 if (len > 0)
1715 {
1716 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
1717 }
1718 else
1719 {
1720 return len;
1721 }
1722}
1723
1724#if defined(__GNUC__) || defined(__clang__)
1725#pragma GCC diagnostic push
1726#pragma GCC diagnostic ignored "-Wconversion"
1727#endif
1728
1729static int
1730write_tun_header(struct tuntap *tt, uint8_t *buf, int len)
1731{
1732 if (tt->type == DEV_TYPE_TUN)
1733 {
1734 u_int32_t type;
1735 struct iovec iv[2];
1736 struct openvpn_iphdr *iph;
1737
1738 iph = (struct openvpn_iphdr *)buf;
1739
1740 if (OPENVPN_IPH_GET_VER(iph->version_len) == 6)
1741 {
1742 type = htonl(AF_INET6);
1743 }
1744 else
1745 {
1746 type = htonl(AF_INET);
1747 }
1748
1749 iv[0].iov_base = &type;
1750 iv[0].iov_len = sizeof(type);
1751 iv[1].iov_base = buf;
1752 iv[1].iov_len = len;
1753
1754 return header_modify_read_write_return(writev(tt->fd, iv, 2));
1755 }
1756 else
1757 {
1758 return write(tt->fd, buf, len);
1759 }
1760}
1761
1762static int
1763read_tun_header(struct tuntap *tt, uint8_t *buf, int len)
1764{
1765 if (tt->type == DEV_TYPE_TUN)
1766 {
1767 u_int32_t type;
1768 struct iovec iv[2];
1769
1770 iv[0].iov_base = &type;
1771 iv[0].iov_len = sizeof(type);
1772 iv[1].iov_base = buf;
1773 iv[1].iov_len = len;
1774
1775 return header_modify_read_write_return(readv(tt->fd, iv, 2));
1776 }
1777 else
1778 {
1779 return read(tt->fd, buf, len);
1780 }
1781}
1782
1783#if defined(__GNUC__) || defined(__clang__)
1784#pragma GCC diagnostic pop
1785#endif
1786
1787#endif /* if defined (TARGET_OPENBSD) || defined(TARGET_DARWIN) */
1788
1789bool
1790tun_name_is_fixed(const char *dev)
1791{
1792 return has_digit(dev);
1793}
1794
1795#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
1796static bool
1797tun_dco_enabled(struct tuntap *tt)
1798{
1799 return tt->backend_driver == DRIVER_DCO;
1800}
1801#endif
1802
1803
1804#if !(defined(_WIN32) || defined(TARGET_LINUX) || defined(TARGET_SOLARIS))
1805static void
1806open_tun_generic(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
1807{
1808 char tunname[256];
1809 char dynamic_name[256];
1810 bool dynamic_opened = false;
1811
1812 /*
1813 * --dev-node specified, so open an explicit device node
1814 */
1815 if (dev_node)
1816 {
1817 snprintf(tunname, sizeof(tunname), "%s", dev_node);
1818 }
1819 else
1820 {
1821 /*
1822 * dynamic open is indicated by --dev specified without
1823 * explicit unit number. Try opening /dev/[dev]n
1824 * where n = [0, 255].
1825 */
1826
1827 if (!tun_name_is_fixed(dev))
1828 {
1829 for (int i = 0; i < 256; ++i)
1830 {
1831 /* some platforms have a dedicated directory per driver */
1832 char *sep = "";
1833#if defined(TARGET_HAIKU)
1834 sep = "/";
1835#endif
1836 snprintf(tunname, sizeof(tunname), "/dev/%s%s%d", dev, sep, i);
1837 snprintf(dynamic_name, sizeof(dynamic_name), "%s%s%d", dev, sep, i);
1838 if ((tt->fd = open(tunname, O_RDWR)) > 0)
1839 {
1840 dynamic_opened = true;
1841 break;
1842 }
1843 msg(D_READ_WRITE | M_ERRNO, "Tried opening %s (failed)", tunname);
1844 }
1845 if (!dynamic_opened)
1846 {
1847 msg(M_FATAL, "Cannot allocate TUN/TAP dev dynamically");
1848 }
1849 }
1850 /*
1851 * explicit unit number specified
1852 */
1853 else
1854 {
1855 snprintf(tunname, sizeof(tunname), "/dev/%s", dev);
1856 }
1857 }
1858
1859 if (!dynamic_opened)
1860 {
1861 /* has named device existed before? if so, don't destroy at end */
1862 if (if_nametoindex(dev) > 0)
1863 {
1864 msg(M_INFO, "TUN/TAP device %s exists previously, keep at program end", dev);
1865 tt->persistent_if = true;
1866 }
1867
1868 if ((tt->fd = open(tunname, O_RDWR)) < 0)
1869 {
1870 msg(M_ERR, "Cannot open TUN/TAP dev %s", tunname);
1871 }
1872 }
1873
1874 set_nonblock(tt->fd);
1875 set_cloexec(tt->fd); /* don't pass fd to scripts */
1876 msg(M_INFO, "TUN/TAP device %s opened", tunname);
1877
1878 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
1879 tt->actual_name = string_alloc(dynamic_opened ? dynamic_name : dev, NULL);
1880}
1881#endif /* !_WIN32 && !TARGET_LINUX && !TARGET_FREEBSD*/
1882
1883#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
1884static void
1885open_tun_dco_generic(const char *dev, const char *dev_type, struct tuntap *tt,
1886 openvpn_net_ctx_t *ctx)
1887{
1888 char dynamic_name[256];
1889 bool dynamic_opened = false;
1890
1891 /*
1892 * unlike "open_tun_generic()", DCO on Linux and FreeBSD follows
1893 * the device naming model of "non-DCO linux", that is:
1894 * --dev tun -> try tun0, tun1, ... tun255, use first free
1895 * --dev <anything> -> (try to) create a tun device named "anything"
1896 * ("--dev tap" and "--dev null" are caught earlier and not handled here)
1897 */
1898
1899 if (strcmp(dev, "tun") == 0)
1900 {
1901 for (int i = 0; i < 256; ++i)
1902 {
1903 snprintf(dynamic_name, sizeof(dynamic_name), "%s%d", dev, i);
1904 int ret = open_tun_dco(tt, ctx, dynamic_name);
1905 if (ret == 0)
1906 {
1907 dynamic_opened = true;
1908 msg(M_INFO, "DCO device %s opened", dynamic_name);
1909 break;
1910 }
1911 /* "permission denied" won't succeed if we try 256 times */
1912 else if (ret == -EPERM)
1913 {
1914 break;
1915 }
1916 }
1917 if (!dynamic_opened)
1918 {
1919 msg(M_FATAL, "Cannot allocate DCO dev dynamically");
1920 }
1921 /* tt->actual_name is passed to up and down scripts and used as
1922 * the ifconfig dev name */
1923 tt->actual_name = string_alloc(dynamic_name, NULL);
1924 }
1925 /*
1926 * explicit unit number specified
1927 */
1928 else
1929 {
1930 int ret = open_tun_dco(tt, ctx, dev);
1931 if (ret == -EEXIST)
1932 {
1933 msg(M_INFO, "DCO device %s already exists, won't be destroyed at shutdown", dev);
1934 tt->persistent_if = true;
1935 }
1936 else if (ret < 0)
1937 {
1938 msg(M_ERR, "Cannot open DCO device %s: %s (%d)", dev, strerror(-ret), ret);
1939 }
1940 else
1941 {
1942 msg(M_INFO, "DCO device %s opened", dev);
1943 }
1944
1945 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
1946 tt->actual_name = string_alloc(dev, NULL);
1947 }
1948}
1949#endif /* TARGET_LINUX || TARGET_FREEBSD*/
1950
1951#if !(defined(_WIN32) || defined(TARGET_SOLARIS))
1952static void
1953close_tun_generic(struct tuntap *tt)
1954{
1955 if (tt->fd >= 0)
1956 {
1957 close(tt->fd);
1958 }
1959
1960 free(tt->actual_name);
1961 clear_tuntap(tt);
1962}
1963#endif /* !_WIN32 */
1964
1965#if defined(TARGET_ANDROID)
1966void
1967open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
1968 openvpn_net_ctx_t *ctx)
1969{
1970#define ANDROID_TUNNAME "vpnservice-tun"
1971 struct user_pass up;
1972 struct gc_arena gc = gc_new();
1973 bool opentun;
1974
1975 int oldtunfd = tt->fd;
1976
1977 /* Prefer IPv6 DNS servers,
1978 * Android will use the DNS server in the order we specify*/
1979 for (int i = 0; i < tt->options.dns6_len; i++)
1980 {
1981 management_android_control(management, "DNS6SERVER",
1982 print_in6_addr(tt->options.dns6[i], 0, &gc));
1983 }
1984
1985 for (int i = 0; i < tt->options.dns_len; i++)
1986 {
1987 management_android_control(management, "DNSSERVER",
1988 print_in_addr_t(tt->options.dns[i], 0, &gc));
1989 }
1990
1991 if (tt->options.domain)
1992 {
1993 management_android_control(management, "DNSDOMAIN", tt->options.domain);
1994 }
1995
1996 if (tt->options.http_proxy)
1997 {
1998 struct buffer buf = alloc_buf_gc(strlen(tt->options.http_proxy) + 20, &gc);
1999 buf_printf(&buf, "%s %d", tt->options.http_proxy, tt->options.http_proxy_port);
2000 management_android_control(management, "HTTPPROXY", BSTR(&buf));
2001 }
2002
2004
2006 {
2007 /* keep the old fd */
2008 opentun = true;
2009 }
2010 else
2011 {
2013 /* Pick up the fd from management interface after calling the
2014 * OPENTUN command */
2015 tt->fd = management->connection.lastfdreceived;
2016 management->connection.lastfdreceived = -1;
2017 }
2018
2020 {
2021 close(oldtunfd);
2022 }
2023
2024 /* Set the actual name to a dummy name */
2025 tt->actual_name = string_alloc(ANDROID_TUNNAME, NULL);
2026
2027 if ((tt->fd < 0) || !opentun)
2028 {
2029 msg(M_ERR, "ERROR: Cannot open TUN");
2030 }
2031
2032 gc_free(&gc);
2033}
2034
2035void
2036close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2037{
2038 ASSERT(tt);
2039
2041 free(tt);
2042}
2043
2044int
2045write_tun(struct tuntap *tt, uint8_t *buf, int len)
2046{
2047 return write(tt->fd, buf, len);
2048}
2049
2050int
2051read_tun(struct tuntap *tt, uint8_t *buf, int len)
2052{
2053 return read(tt->fd, buf, len);
2054}
2055
2056#elif defined(TARGET_LINUX)
2057
2058#if !PEDANTIC
2059
2060void
2061open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2062 openvpn_net_ctx_t *ctx)
2063{
2064 struct ifreq ifr;
2065
2066 if (tun_dco_enabled(tt))
2067 {
2068 open_tun_dco_generic(dev, dev_type, tt, ctx);
2069 }
2070 else
2071 {
2072 /*
2073 * Process --dev-node
2074 */
2075 const char *node = dev_node;
2076 if (!node)
2077 {
2078 node = "/dev/net/tun";
2079 }
2080
2081 /*
2082 * Open the interface
2083 */
2084 if ((tt->fd = open(node, O_RDWR)) < 0)
2085 {
2086 msg(M_ERR, "ERROR: Cannot open TUN/TAP dev %s", node);
2087 }
2088
2089 /*
2090 * Process --tun-ipv6
2091 */
2092 CLEAR(ifr);
2093 ifr.ifr_flags = IFF_NO_PI;
2094
2095#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
2096 ifr.ifr_flags |= IFF_ONE_QUEUE;
2097#endif
2098
2099 /*
2100 * Figure out if tun or tap device
2101 */
2102 if (tt->type == DEV_TYPE_TUN)
2103 {
2104 ifr.ifr_flags |= IFF_TUN;
2105 }
2106 else if (tt->type == DEV_TYPE_TAP)
2107 {
2108 ifr.ifr_flags |= IFF_TAP;
2109 }
2110 else
2111 {
2112 msg(M_FATAL, "I don't recognize device %s as a tun or tap device", dev);
2113 }
2114
2115 /*
2116 * Set an explicit name, if --dev is not tun or tap
2117 */
2118 if (strcmp(dev, "tun") && strcmp(dev, "tap"))
2119 {
2120 strncpynt(ifr.ifr_name, dev, IFNAMSIZ);
2121 }
2122
2123 /*
2124 * Use special ioctl that configures tun/tap device with the parms
2125 * we set in ifr
2126 */
2127 if (ioctl(tt->fd, TUNSETIFF, (void *)&ifr) < 0)
2128 {
2129 msg(M_ERR, "ERROR: Cannot ioctl TUNSETIFF %s", dev);
2130 }
2131
2132 msg(M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
2133
2134 /*
2135 * Try making the TX send queue bigger
2136 */
2137#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
2138 if (tt->options.txqueuelen)
2139 {
2140 struct ifreq netifr;
2141 int ctl_fd;
2142
2143 if ((ctl_fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0)
2144 {
2145 CLEAR(netifr);
2146 strncpynt(netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
2147 netifr.ifr_qlen = tt->options.txqueuelen;
2148 if (ioctl(ctl_fd, SIOCSIFTXQLEN, (void *)&netifr) >= 0)
2149 {
2150 msg(D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen);
2151 }
2152 else
2153 {
2154 msg(M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name);
2155 }
2156 close(ctl_fd);
2157 }
2158 else
2159 {
2160 msg(M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name);
2161 }
2162 }
2163#endif /* if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) */
2164
2165 set_nonblock(tt->fd);
2166 set_cloexec(tt->fd);
2167 tt->actual_name = string_alloc(ifr.ifr_name, NULL);
2168 }
2169 return;
2170}
2171
2172#else /* if !PEDANTIC */
2173
2174void
2175open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2176 openvpn_net_ctx_t *ctx)
2177{
2178 ASSERT(0);
2179}
2180
2181#endif /* !PEDANTIC */
2182
2183#ifdef ENABLE_FEATURE_TUN_PERSIST
2184
2185void
2186tuncfg(const char *dev, const char *dev_type, const char *dev_node, int persist_mode,
2187 const char *username, const char *groupname, const struct tuntap_options *options,
2188 openvpn_net_ctx_t *ctx)
2189{
2190 struct tuntap *tt;
2191
2192 ALLOC_OBJ(tt, struct tuntap);
2193 clear_tuntap(tt);
2194 tt->type = dev_type_enum(dev, dev_type);
2195 tt->options = *options;
2196
2197 open_tun(dev, dev_type, dev_node, tt, ctx);
2198 if (ioctl(tt->fd, TUNSETPERSIST, persist_mode) < 0)
2199 {
2200 msg(M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
2201 }
2202 if (username != NULL)
2203 {
2205
2206 if (!platform_user_get(username, &platform_state_user))
2207 {
2208 msg(M_ERR, "Cannot get user entry for %s", username);
2209 }
2210 else if (ioctl(tt->fd, TUNSETOWNER, platform_state_user.uid) < 0)
2211 {
2212 msg(M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
2213 }
2214 }
2215 if (groupname != NULL)
2216 {
2218
2219 if (!platform_group_get(groupname, &platform_state_group))
2220 {
2221 msg(M_ERR, "Cannot get group entry for %s", groupname);
2222 }
2223 else if (ioctl(tt->fd, TUNSETGROUP, platform_state_group.gid) < 0)
2224 {
2225 msg(M_ERR, "Cannot ioctl TUNSETGROUP(%s) %s", groupname, dev);
2226 }
2227 }
2228 close_tun(tt, ctx);
2229 msg(M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
2230}
2231
2232#endif /* ENABLE_FEATURE_TUN_PERSIST */
2233
2234void
2235close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2236{
2237 ASSERT(tt);
2238
2239#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
2240 if (tun_dco_enabled(tt))
2241 {
2242 close_tun_dco(tt, ctx);
2243 }
2244#endif
2245 close_tun_generic(tt);
2246 free(tt);
2247}
2248
2249#if defined(__GNUC__) || defined(__clang__)
2250#pragma GCC diagnostic push
2251#pragma GCC diagnostic ignored "-Wconversion"
2252#endif
2253
2254int
2255write_tun(struct tuntap *tt, uint8_t *buf, int len)
2256{
2257 return write(tt->fd, buf, len);
2258}
2259
2260int
2261read_tun(struct tuntap *tt, uint8_t *buf, int len)
2262{
2263 return read(tt->fd, buf, len);
2264}
2265
2266#if defined(__GNUC__) || defined(__clang__)
2267#pragma GCC diagnostic pop
2268#endif
2269
2270#elif defined(TARGET_SOLARIS)
2271
2272#ifndef TUNNEWPPA
2273#error I need the symbol TUNNEWPPA from net/if_tun.h
2274#endif
2275
2276void
2277open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2278 openvpn_net_ctx_t *ctx)
2279{
2280 int if_fd = -1, ip_muxid = -1, arp_muxid = -1, arp_fd = -1, ppa = -1;
2281 struct lifreq ifr;
2282 const char *ptr;
2283 const char *ip_node = NULL, *arp_node = NULL;
2284 const char *dev_tuntap_type;
2285 int link_type;
2286 struct strioctl strioc_if, strioc_ppa;
2287
2288 /* improved generic TUN/TAP driver from
2289 * https://web.archive.org/web/20250504214754/http://www.whiteboard.ne.jp/~admin2/tuntap/
2290 * has IPv6 support
2291 */
2292 CLEAR(ifr);
2293
2294 if (tt->type == DEV_TYPE_TUN)
2295 {
2296 ip_node = "/dev/udp";
2297 if (!dev_node)
2298 {
2299 dev_node = "/dev/tun";
2300 }
2301 dev_tuntap_type = "tun";
2302 link_type = I_PLINK;
2303 }
2304 else if (tt->type == DEV_TYPE_TAP)
2305 {
2306 ip_node = "/dev/udp";
2307 if (!dev_node)
2308 {
2309 dev_node = "/dev/tap";
2310 }
2311 arp_node = dev_node;
2312 dev_tuntap_type = "tap";
2313 link_type = I_PLINK; /* was: I_LINK */
2314 }
2315 else
2316 {
2317 msg(M_FATAL, "I don't recognize device %s as a tun or tap device", dev);
2318 }
2319
2320 if ((tt->ip_fd = open(ip_node, O_RDWR, 0)) < 0)
2321 {
2322 msg(M_ERR, "Can't open %s", ip_node);
2323 }
2324
2325 if ((tt->fd = open(dev_node, O_RDWR, 0)) < 0)
2326 {
2327 msg(M_ERR, "Can't open %s", dev_node);
2328 }
2329
2330 ptr = dev;
2331
2332 /* get unit number */
2333 if (*ptr)
2334 {
2335 while (*ptr && !isdigit((int)*ptr))
2336 {
2337 ptr++;
2338 }
2339 ppa = atoi(ptr);
2340 }
2341
2342 /* Assign a new PPA and get its unit number. */
2343 strioc_ppa.ic_cmd = TUNNEWPPA;
2344 strioc_ppa.ic_timout = 0;
2345 strioc_ppa.ic_len = sizeof(ppa);
2346 strioc_ppa.ic_dp = (char *)&ppa;
2347
2348 if (*ptr == '\0') /* no number given, try dynamic */
2349 {
2350 bool found_one = false;
2351 while (!found_one && ppa < 64)
2352 {
2353 int new_ppa = ioctl(tt->fd, I_STR, &strioc_ppa);
2354 if (new_ppa >= 0)
2355 {
2356 msg(M_INFO, "open_tun: got dynamic interface '%s%d'", dev_tuntap_type, new_ppa);
2357 ppa = new_ppa;
2358 found_one = true;
2359 break;
2360 }
2361 if (errno != EEXIST)
2362 {
2363 msg(M_ERR, "open_tun: unexpected error trying to find free %s interface",
2364 dev_tuntap_type);
2365 }
2366 ppa++;
2367 }
2368 if (!found_one)
2369 {
2370 msg(M_ERR, "open_tun: could not find free %s interface, give up.", dev_tuntap_type);
2371 }
2372 }
2373 else /* try this particular one */
2374 {
2375 if ((ppa = ioctl(tt->fd, I_STR, &strioc_ppa)) < 0)
2376 {
2377 msg(M_ERR, "Can't assign PPA for new interface (%s%d)", dev_tuntap_type, ppa);
2378 }
2379 }
2380
2381 if ((if_fd = open(dev_node, O_RDWR, 0)) < 0)
2382 {
2383 msg(M_ERR, "Can't open %s (2)", dev_node);
2384 }
2385
2386 if (ioctl(if_fd, I_PUSH, "ip") < 0)
2387 {
2388 msg(M_ERR, "Can't push IP module");
2389 }
2390
2391 if (tt->type == DEV_TYPE_TUN)
2392 {
2393 /* Assign ppa according to the unit number returned by tun device */
2394 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0)
2395 {
2396 msg(M_ERR, "Can't set PPA %d", ppa);
2397 }
2398 }
2399
2400 tt->actual_name = (char *)malloc(32);
2402
2403 snprintf(tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa);
2404
2405 if (tt->type == DEV_TYPE_TAP)
2406 {
2407 if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
2408 {
2409 msg(M_ERR, "Can't get flags");
2410 }
2411 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2412 ifr.lifr_ppa = ppa;
2413 /* Assign ppa according to the unit number returned by tun device */
2414 if (ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0)
2415 {
2416 msg(M_ERR, "Can't set PPA %d", ppa);
2417 }
2418 if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
2419 {
2420 msg(M_ERR, "Can't get flags");
2421 }
2422 /* Push arp module to if_fd */
2423 if (ioctl(if_fd, I_PUSH, "arp") < 0)
2424 {
2425 msg(M_ERR, "Can't push ARP module");
2426 }
2427
2428 /* Pop any modules on the stream */
2429 while (true)
2430 {
2431 if (ioctl(tt->ip_fd, I_POP, NULL) < 0)
2432 {
2433 break;
2434 }
2435 }
2436 /* Push arp module to ip_fd */
2437 if (ioctl(tt->ip_fd, I_PUSH, "arp") < 0)
2438 {
2439 msg(M_ERR, "Can't push ARP module");
2440 }
2441
2442 /* Open arp_fd */
2443 if ((arp_fd = open(arp_node, O_RDWR, 0)) < 0)
2444 {
2445 msg(M_ERR, "Can't open %s", arp_node);
2446 }
2447 /* Push arp module to arp_fd */
2448 if (ioctl(arp_fd, I_PUSH, "arp") < 0)
2449 {
2450 msg(M_ERR, "Can't push ARP module");
2451 }
2452
2453 /* Set ifname to arp */
2454 strioc_if.ic_cmd = SIOCSLIFNAME;
2455 strioc_if.ic_timout = 0;
2456 strioc_if.ic_len = sizeof(ifr);
2457 strioc_if.ic_dp = (char *)&ifr;
2458 if (ioctl(arp_fd, I_STR, &strioc_if) < 0)
2459 {
2460 msg(M_ERR, "Can't set ifname to arp");
2461 }
2462 }
2463
2464 if ((ip_muxid = ioctl(tt->ip_fd, link_type, if_fd)) < 0)
2465 {
2466 msg(M_ERR, "Can't link %s device to IP", dev_tuntap_type);
2467 }
2468
2469 if (tt->type == DEV_TYPE_TAP)
2470 {
2471 if ((arp_muxid = ioctl(tt->ip_fd, link_type, arp_fd)) < 0)
2472 {
2473 msg(M_ERR, "Can't link %s device to ARP", dev_tuntap_type);
2474 }
2475 close(arp_fd);
2476 }
2477
2478 CLEAR(ifr);
2479 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2480 ifr.lifr_ip_muxid = ip_muxid;
2481 if (tt->type == DEV_TYPE_TAP)
2482 {
2483 ifr.lifr_arp_muxid = arp_muxid;
2484 }
2485
2486 if (ioctl(tt->ip_fd, SIOCSLIFMUXID, &ifr) < 0)
2487 {
2488 if (tt->type == DEV_TYPE_TAP)
2489 {
2490 ioctl(tt->ip_fd, I_PUNLINK, arp_muxid);
2491 }
2492 ioctl(tt->ip_fd, I_PUNLINK, ip_muxid);
2493 msg(M_ERR, "Can't set multiplexor id");
2494 }
2495
2496 set_nonblock(tt->fd);
2497 set_cloexec(tt->fd);
2498 set_cloexec(tt->ip_fd);
2499
2500 msg(M_INFO, "TUN/TAP device %s opened", tt->actual_name);
2501}
2502
2503static void
2504solaris_close_tun(struct tuntap *tt)
2505{
2506 /* IPv6 interfaces need to be 'manually' de-configured */
2508 {
2509 struct argv argv = argv_new();
2510 argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, tt->actual_name);
2511 argv_msg(M_INFO, &argv);
2512 openvpn_execve_check(&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed");
2513 argv_free(&argv);
2514 }
2515
2516 if (tt->ip_fd >= 0)
2517 {
2518 struct lifreq ifr;
2519 CLEAR(ifr);
2520 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2521
2522 if (ioctl(tt->ip_fd, SIOCGLIFFLAGS, &ifr) < 0)
2523 {
2524 msg(M_WARN | M_ERRNO, "Can't get iface flags");
2525 }
2526
2527 if (ioctl(tt->ip_fd, SIOCGLIFMUXID, &ifr) < 0)
2528 {
2529 msg(M_WARN | M_ERRNO, "Can't get multiplexor id");
2530 }
2531
2532 if (tt->type == DEV_TYPE_TAP)
2533 {
2534 if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_arp_muxid) < 0)
2535 {
2536 msg(M_WARN | M_ERRNO, "Can't unlink interface(arp)");
2537 }
2538 }
2539
2540 if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0)
2541 {
2542 msg(M_WARN | M_ERRNO, "Can't unlink interface(ip)");
2543 }
2544
2545 close(tt->ip_fd);
2546 tt->ip_fd = -1;
2547 }
2548
2549 if (tt->fd >= 0)
2550 {
2551 close(tt->fd);
2552 tt->fd = -1;
2553 }
2554}
2555
2556/*
2557 * Close TUN device.
2558 */
2559void
2560close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2561{
2562 ASSERT(tt);
2563
2564 solaris_close_tun(tt);
2565
2566 free(tt->actual_name);
2567
2568 clear_tuntap(tt);
2569 free(tt);
2570}
2571
2572static void
2573solaris_error_close(struct tuntap *tt, const struct env_set *es, const char *actual,
2574 bool unplumb_inet6)
2575{
2576 struct argv argv = argv_new();
2577
2578 if (unplumb_inet6)
2579 {
2580 argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, actual);
2581 argv_msg(M_INFO, &argv);
2582 openvpn_execve_check(&argv, es, 0, "Solaris ifconfig inet6 unplumb failed");
2583 }
2584
2585 argv_printf(&argv, "%s %s unplumb", IFCONFIG_PATH, actual);
2586
2587 argv_msg(M_INFO, &argv);
2588 openvpn_execve_check(&argv, es, 0, "Solaris ifconfig unplumb failed");
2589 close_tun(tt, NULL);
2590 msg(M_FATAL, "Solaris ifconfig failed");
2591 argv_free(&argv);
2592}
2593
2594int
2595write_tun(struct tuntap *tt, uint8_t *buf, int len)
2596{
2597 struct strbuf sbuf;
2598 sbuf.len = len;
2599 sbuf.buf = (char *)buf;
2600 return putmsg(tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;
2601}
2602
2603int
2604read_tun(struct tuntap *tt, uint8_t *buf, int len)
2605{
2606 struct strbuf sbuf;
2607 int f = 0;
2608
2609 sbuf.maxlen = len;
2610 sbuf.buf = (char *)buf;
2611 return getmsg(tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
2612}
2613
2614#elif defined(TARGET_OPENBSD)
2615
2616void
2617open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2618 openvpn_net_ctx_t *ctx)
2619{
2620 open_tun_generic(dev, dev_type, dev_node, tt);
2621
2622 /* Enable multicast on the interface */
2623 if (tt->fd >= 0)
2624 {
2625 struct tuninfo info;
2626
2627 if (ioctl(tt->fd, TUNGIFINFO, &info) < 0)
2628 {
2629 msg(M_WARN | M_ERRNO, "Can't get interface info");
2630 }
2631
2632#ifdef IFF_MULTICAST /* openbsd 4.x doesn't have this */
2633 info.flags |= IFF_MULTICAST;
2634#endif
2635
2636 if (ioctl(tt->fd, TUNSIFINFO, &info) < 0)
2637 {
2638 msg(M_WARN | M_ERRNO, "Can't set interface info");
2639 }
2640 }
2641}
2642
2643/* tun(4): "If the device was created by opening /dev/tunN, it will be
2644 * automatically destroyed. Devices created via ifconfig(8) are
2645 * only marked as not running and traffic will be dropped
2646 * returning EHOSTDOWN."
2647 * --> no special handling should be needed - *but* OpenBSD is misbehaving
2648 * here: if the interface was put in tap mode ("ifconfig tunN link0"), it
2649 * *will* stay around, and needs to be cleaned up manually
2650 */
2651
2652void
2653close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2654{
2655 ASSERT(tt);
2656
2657 /* only *TAP* devices need destroying, tun devices auto-self-destruct
2658 */
2659 if (tt->type == DEV_TYPE_TUN || tt->persistent_if)
2660 {
2661 close_tun_generic(tt);
2662 free(tt);
2663 return;
2664 }
2665
2666 struct argv argv = argv_new();
2667
2668 /* setup command, close tun dev (clears tt->actual_name!), run command
2669 */
2670
2671 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2672
2673 close_tun_generic(tt);
2674
2675 argv_msg(M_INFO, &argv);
2676 openvpn_execve_check(&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)");
2677
2678 free(tt);
2679 argv_free(&argv);
2680}
2681
2682int
2683write_tun(struct tuntap *tt, uint8_t *buf, int len)
2684{
2685 return write_tun_header(tt, buf, len);
2686}
2687
2688int
2689read_tun(struct tuntap *tt, uint8_t *buf, int len)
2690{
2691 return read_tun_header(tt, buf, len);
2692}
2693
2694#elif defined(TARGET_NETBSD)
2695
2696/*
2697 * NetBSD 4.0 and up support IPv6 on tun interfaces, but we need to put
2698 * the tun interface into "multi_af" mode, which will prepend the address
2699 * family to all packets (same as OpenBSD and FreeBSD).
2700 *
2701 * If this is not enabled, the kernel silently drops all IPv6 packets on
2702 * output and gets confused on input.
2703 *
2704 * Note: --dev tap3 works *if* the interface is created externally by
2705 * "ifconfig tap3 create"
2706 * (and for devices beyond tap3, "mknod /dev/tapN c ...")
2707 * but we do not have code to do that inside OpenVPN
2708 */
2709
2710void
2711open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2712 openvpn_net_ctx_t *ctx)
2713{
2714 /* on NetBSD, tap (but not tun) devices are opened by
2715 * opening /dev/tap and then querying the system about the
2716 * actual device name (tap0, tap1, ...) assigned
2717 */
2718 if (strcmp(dev, "tap") == 0)
2719 {
2720 struct ifreq ifr;
2721 if ((tt->fd = open("/dev/tap", O_RDWR)) < 0)
2722 {
2723 msg(M_FATAL, "Cannot allocate NetBSD TAP dev dynamically");
2724 }
2725 if (ioctl(tt->fd, TAPGIFNAME, (void *)&ifr) < 0)
2726 {
2727 msg(M_FATAL, "Cannot query NetBSD TAP device name");
2728 }
2729 set_nonblock(tt->fd);
2730 set_cloexec(tt->fd); /* don't pass fd to scripts */
2731 msg(M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
2732
2733 tt->actual_name = string_alloc(ifr.ifr_name, NULL);
2734 }
2735 else
2736 {
2737 /* dynamic / named tun can be handled by the generic function
2738 * named tap ("tap3") is handled there as well, if pre-created
2739 */
2740 open_tun_generic(dev, dev_type, dev_node, tt);
2741 }
2742
2743 if (tt->fd >= 0)
2744 {
2745 int i = IFF_POINTOPOINT | IFF_MULTICAST;
2746 ioctl(tt->fd, TUNSIFMODE, &i); /* multicast on */
2747 i = 0;
2748 ioctl(tt->fd, TUNSLMODE, &i); /* link layer mode off */
2749
2750 if (tt->type == DEV_TYPE_TUN)
2751 {
2752 i = 1;
2753 if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
2754 {
2755 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
2756 }
2757 }
2758 }
2759}
2760
2761/* the current way OpenVPN handles tun devices on NetBSD leads to
2762 * lingering tunX interfaces after close -> for a full cleanup, they
2763 * need to be explicitly destroyed
2764 */
2765void
2766close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2767{
2768 ASSERT(tt);
2769
2770 /* only tun devices need destroying, tap devices auto-self-destruct
2771 */
2772 if (tt->type != DEV_TYPE_TUN || tt->persistent_if)
2773 {
2774 close_tun_generic(tt);
2775 free(tt);
2776 return;
2777 }
2778
2779 struct argv argv = argv_new();
2780
2781 /* setup command, close tun dev (clears tt->actual_name!), run command
2782 */
2783
2784 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2785
2786 close_tun_generic(tt);
2787
2788 argv_msg(M_INFO, &argv);
2789 openvpn_execve_check(&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)");
2790
2791 free(tt);
2792 argv_free(&argv);
2793}
2794
2795static inline int
2796netbsd_modify_read_write_return(int len)
2797{
2798 if (len > 0)
2799 {
2800 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
2801 }
2802 else
2803 {
2804 return len;
2805 }
2806}
2807
2808int
2809write_tun(struct tuntap *tt, uint8_t *buf, int len)
2810{
2811 if (tt->type == DEV_TYPE_TUN)
2812 {
2813 u_int32_t type;
2814 struct iovec iv[2];
2815 struct openvpn_iphdr *iph;
2816
2817 iph = (struct openvpn_iphdr *)buf;
2818
2819 if (OPENVPN_IPH_GET_VER(iph->version_len) == 6)
2820 {
2821 type = htonl(AF_INET6);
2822 }
2823 else
2824 {
2825 type = htonl(AF_INET);
2826 }
2827
2828 iv[0].iov_base = (char *)&type;
2829 iv[0].iov_len = sizeof(type);
2830 iv[1].iov_base = buf;
2831 iv[1].iov_len = len;
2832
2833 return netbsd_modify_read_write_return(writev(tt->fd, iv, 2));
2834 }
2835 else
2836 {
2837 return write(tt->fd, buf, len);
2838 }
2839}
2840
2841int
2842read_tun(struct tuntap *tt, uint8_t *buf, int len)
2843{
2844 if (tt->type == DEV_TYPE_TUN)
2845 {
2846 u_int32_t type;
2847 struct iovec iv[2];
2848
2849 iv[0].iov_base = (char *)&type;
2850 iv[0].iov_len = sizeof(type);
2851 iv[1].iov_base = buf;
2852 iv[1].iov_len = len;
2853
2854 return netbsd_modify_read_write_return(readv(tt->fd, iv, 2));
2855 }
2856 else
2857 {
2858 return read(tt->fd, buf, len);
2859 }
2860}
2861
2862#elif defined(TARGET_FREEBSD)
2863
2864static inline int
2865freebsd_modify_read_write_return(int len)
2866{
2867 if (len > 0)
2868 {
2869 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
2870 }
2871 else
2872 {
2873 return len;
2874 }
2875}
2876
2877void
2878open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2879 openvpn_net_ctx_t *ctx)
2880{
2881 if (tun_dco_enabled(tt))
2882 {
2883 open_tun_dco_generic(dev, dev_type, tt, ctx);
2884 }
2885 else
2886 {
2887 open_tun_generic(dev, dev_type, dev_node, tt);
2888
2889 if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
2890 {
2891 /* see "Interface Flags" in ifnet(9) */
2892 int i = IFF_POINTOPOINT | IFF_MULTICAST;
2893 if (tt->topology == TOP_SUBNET)
2894 {
2895 i = IFF_BROADCAST | IFF_MULTICAST;
2896 }
2897
2898 if (ioctl(tt->fd, TUNSIFMODE, &i) < 0)
2899 {
2900 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE)");
2901 }
2902
2903 /* multi_af mode for v4+v6, see "tun(4)" */
2904 i = 1;
2905 if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0)
2906 {
2907 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
2908 }
2909 }
2910 }
2911}
2912
2913/* tun(4): "These network interfaces persist until the if_tun.ko module is
2914 * unloaded, or until removed with the ifconfig(8) command."
2915 * (verified for FreeBSD 6.3, 7.4, 8.2 and 9, same for tap(4))
2916 *
2917 * so, to avoid lingering tun/tap interfaces after OpenVPN quits,
2918 * we need to call "ifconfig ... destroy" for cleanup
2919 */
2920void
2921close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2922{
2923 ASSERT(tt);
2924
2925 if (tt->persistent_if) /* keep pre-existing if around */
2926 {
2927 close_tun_generic(tt);
2928 free(tt);
2929 return;
2930 }
2931
2932 /* close and destroy */
2933 struct argv argv = argv_new();
2934
2935 /* setup command, close tun dev (clears tt->actual_name!), run command
2936 */
2937
2938 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2939
2940 close_tun_generic(tt);
2941
2942 argv_msg(M_INFO, &argv);
2943 openvpn_execve_check(&argv, NULL, 0, "FreeBSD 'destroy tun interface' failed (non-critical)");
2944
2945 free(tt);
2946 argv_free(&argv);
2947}
2948
2949#if defined(__GNUC__) || defined(__clang__)
2950#pragma GCC diagnostic push
2951#pragma GCC diagnostic ignored "-Wconversion"
2952#endif
2953
2954int
2955write_tun(struct tuntap *tt, uint8_t *buf, int len)
2956{
2957 if (tt->type == DEV_TYPE_TUN)
2958 {
2959 u_int32_t type;
2960 struct iovec iv[2];
2961 struct ip *iph;
2962
2963 iph = (struct ip *)buf;
2964
2965 if (iph->ip_v == 6)
2966 {
2967 type = htonl(AF_INET6);
2968 }
2969 else
2970 {
2971 type = htonl(AF_INET);
2972 }
2973
2974 iv[0].iov_base = (char *)&type;
2975 iv[0].iov_len = sizeof(type);
2976 iv[1].iov_base = buf;
2977 iv[1].iov_len = len;
2978
2979 return freebsd_modify_read_write_return(writev(tt->fd, iv, 2));
2980 }
2981 else
2982 {
2983 return write(tt->fd, buf, len);
2984 }
2985}
2986
2987int
2988read_tun(struct tuntap *tt, uint8_t *buf, int len)
2989{
2990 if (tt->type == DEV_TYPE_TUN)
2991 {
2992 u_int32_t type;
2993 struct iovec iv[2];
2994
2995 iv[0].iov_base = (char *)&type;
2996 iv[0].iov_len = sizeof(type);
2997 iv[1].iov_base = buf;
2998 iv[1].iov_len = len;
2999
3000 return freebsd_modify_read_write_return(readv(tt->fd, iv, 2));
3001 }
3002 else
3003 {
3004 return read(tt->fd, buf, len);
3005 }
3006}
3007
3008#if defined(__GNUC__) || defined(__clang__)
3009#pragma GCC diagnostic pop
3010#endif
3011
3012#elif defined(TARGET_DRAGONFLY)
3013
3014static inline int
3015dragonfly_modify_read_write_return(int len)
3016{
3017 if (len > 0)
3018 {
3019 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
3020 }
3021 else
3022 {
3023 return len;
3024 }
3025}
3026
3027void
3028open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3029 openvpn_net_ctx_t *ctx)
3030{
3031 open_tun_generic(dev, dev_type, dev_node, tt);
3032
3033 if (tt->fd >= 0)
3034 {
3035 int i = 0;
3036
3037 /* Disable extended modes */
3038 ioctl(tt->fd, TUNSLMODE, &i);
3039 i = 1;
3040 ioctl(tt->fd, TUNSIFHEAD, &i);
3041 }
3042}
3043
3044void
3045close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3046{
3047 ASSERT(tt);
3048
3049 close_tun_generic(tt);
3050 free(tt);
3051}
3052
3053int
3054write_tun(struct tuntap *tt, uint8_t *buf, int len)
3055{
3056 if (tt->type == DEV_TYPE_TUN)
3057 {
3058 u_int32_t type;
3059 struct iovec iv[2];
3060 struct ip *iph;
3061
3062 iph = (struct ip *)buf;
3063
3064 if (iph->ip_v == 6)
3065 {
3066 type = htonl(AF_INET6);
3067 }
3068 else
3069 {
3070 type = htonl(AF_INET);
3071 }
3072
3073 iv[0].iov_base = (char *)&type;
3074 iv[0].iov_len = sizeof(type);
3075 iv[1].iov_base = buf;
3076 iv[1].iov_len = len;
3077
3078 return dragonfly_modify_read_write_return(writev(tt->fd, iv, 2));
3079 }
3080 else
3081 {
3082 return write(tt->fd, buf, len);
3083 }
3084}
3085
3086int
3087read_tun(struct tuntap *tt, uint8_t *buf, int len)
3088{
3089 if (tt->type == DEV_TYPE_TUN)
3090 {
3091 u_int32_t type;
3092 struct iovec iv[2];
3093
3094 iv[0].iov_base = (char *)&type;
3095 iv[0].iov_len = sizeof(type);
3096 iv[1].iov_base = buf;
3097 iv[1].iov_len = len;
3098
3099 return dragonfly_modify_read_write_return(readv(tt->fd, iv, 2));
3100 }
3101 else
3102 {
3103 return read(tt->fd, buf, len);
3104 }
3105}
3106
3107#elif defined(TARGET_DARWIN)
3108
3109/* Darwin (MacOS X) is mostly "just use the generic stuff", but there
3110 * is always one caveat...:
3111 *
3112 * If IPv6 is configured, and the tun device is closed, the IPv6 address
3113 * configured to the tun interface changes to a lingering /128 route
3114 * pointing to lo0. Need to unconfigure... (observed on 10.5)
3115 */
3116
3117/*
3118 * utun is the native Darwin tun driver present since at least 10.7
3119 * Thanks goes to Jonathan Levin for providing an example how to utun
3120 * (https://www.cs.dartmouth.edu/~sergey/netreads/utun/utun-demo.c)
3121 */
3122
3123/* Helper functions that tries to open utun device
3124 * return -2 on early initialization failures (utun not supported
3125 * at all) and -1 on initlization failure of utun
3126 * device (utun works but utunX is already used)
3127 */
3128static int
3129utun_open_helper(struct ctl_info ctlInfo, int utunnum)
3130{
3131 struct sockaddr_ctl sc;
3132 int fd;
3133
3134 fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
3135
3136 if (fd < 0)
3137 {
3138 msg(M_INFO | M_ERRNO, "Opening utun%d failed (socket(SYSPROTO_CONTROL))", utunnum);
3139 return -2;
3140 }
3141
3142 if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1)
3143 {
3144 close(fd);
3145 msg(M_INFO | M_ERRNO, "Opening utun%d failed (ioctl(CTLIOCGINFO))", utunnum);
3146 return -2;
3147 }
3148
3149
3150 sc.sc_id = ctlInfo.ctl_id;
3151 sc.sc_len = sizeof(sc);
3152 sc.sc_family = AF_SYSTEM;
3153 sc.ss_sysaddr = AF_SYS_CONTROL;
3154
3155 sc.sc_unit = utunnum + 1;
3156
3157
3158 /* If the connect is successful, a utun%d device will be created, where "%d"
3159 * is (sc.sc_unit - 1) */
3160
3161 if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0)
3162 {
3163 msg(M_INFO | M_ERRNO, "Opening utun%d failed (connect(AF_SYS_CONTROL))", utunnum);
3164 close(fd);
3165 return -1;
3166 }
3167
3168 set_nonblock(fd);
3169 set_cloexec(fd); /* don't pass fd to scripts */
3170
3171 return fd;
3172}
3173
3174void
3175open_darwin_utun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
3176{
3177 struct ctl_info ctlInfo;
3178 int fd;
3179 char utunname[20];
3180 int utunnum = -1;
3181 socklen_t utunname_len = sizeof(utunname);
3182
3183 /* dev_node is simply utun, do the normal dynamic utun
3184 * otherwise try to parse the utun number */
3185 if (dev_node && (strcmp("utun", dev_node) != 0))
3186 {
3187 if (sscanf(dev_node, "utun%d", &utunnum) != 1)
3188 {
3189 msg(M_FATAL,
3190 "Cannot parse 'dev-node %s' please use 'dev-node utunX'"
3191 "to use a utun device number X",
3192 dev_node);
3193 }
3194 }
3195
3196
3197 CLEAR(ctlInfo);
3198 if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name))
3199 >= sizeof(ctlInfo.ctl_name))
3200 {
3201 msg(M_ERR, "Opening utun: UTUN_CONTROL_NAME too long");
3202 }
3203
3204 /* try to open first available utun device if no specific utun is requested */
3205 if (utunnum == -1)
3206 {
3207 for (utunnum = 0; utunnum < 255; utunnum++)
3208 {
3209 char ifname[20];
3210 /* if the interface exists silently skip it */
3211 ASSERT(snprintf(ifname, sizeof(ifname), "utun%d", utunnum) > 0);
3212 if (if_nametoindex(ifname))
3213 {
3214 continue;
3215 }
3216 fd = utun_open_helper(ctlInfo, utunnum);
3217 /* Break if the fd is valid,
3218 * or if early initialization failed (-2) */
3219 if (fd != -1)
3220 {
3221 break;
3222 }
3223 }
3224 }
3225 else
3226 {
3227 fd = utun_open_helper(ctlInfo, utunnum);
3228 }
3229
3230 /* opening an utun device failed */
3231 tt->fd = fd;
3232
3233 if (fd < 0)
3234 {
3235 return;
3236 }
3237
3238 /* Retrieve the assigned interface name. */
3239 if (getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len))
3240 {
3241 msg(M_ERR | M_ERRNO, "Error retrieving utun interface name");
3242 }
3243
3244 tt->actual_name = string_alloc(utunname, NULL);
3245
3246 msg(M_INFO, "Opened utun device %s", utunname);
3248}
3249
3250void
3251open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3252 openvpn_net_ctx_t *ctx)
3253{
3254 /* If dev_node does not start start with utun assume regular tun/tap */
3255 if ((!dev_node && tt->type == DEV_TYPE_TUN) || (dev_node && !strncmp(dev_node, "utun", 4)))
3256 {
3257 /* Check if user has specific dev_type tap and forced utun with
3258 * dev-node utun */
3259 if (tt->type != DEV_TYPE_TUN)
3260 {
3261 msg(M_FATAL, "Cannot use utun devices with --dev-type %s",
3262 dev_type_string(dev, dev_type));
3263 }
3264
3265 /* Try utun first and fall back to normal tun if utun fails
3266 * and dev_node is not specified */
3267 open_darwin_utun(dev, dev_type, dev_node, tt);
3268
3269 if (tt->backend_driver != DRIVER_UTUN)
3270 {
3271 if (!dev_node)
3272 {
3273 /* No explicit utun and utun failed, try the generic way) */
3274 msg(M_INFO, "Failed to open utun device. Falling back to /dev/tun device");
3275 open_tun_generic(dev, dev_type, NULL, tt);
3276 }
3277 else
3278 {
3279 /* Specific utun device or generic utun request with no tun
3280 * fall back failed, consider this a fatal failure */
3281 msg(M_FATAL, "Cannot open utun device");
3282 }
3283 }
3284 }
3285 else
3286 {
3287 /* Use plain dev-node tun to select /dev/tun style
3288 * Unset dev_node variable prior to passing to open_tun_generic to
3289 * let open_tun_generic pick the first available tun device */
3290
3291 if (dev_node && strcmp(dev_node, "tun") == 0)
3292 {
3293 dev_node = NULL;
3294 }
3295
3296 open_tun_generic(dev, dev_type, dev_node, tt);
3297 }
3298}
3299
3300#if defined(__GNUC__) || defined(__clang__)
3301#pragma GCC diagnostic push
3302#pragma GCC diagnostic ignored "-Wconversion"
3303#endif
3304
3305void
3306close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3307{
3308 ASSERT(tt);
3309
3310 struct gc_arena gc = gc_new();
3311 struct argv argv = argv_new();
3312
3314 {
3315 const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
3316
3317 argv_printf(&argv, "%s delete -inet6 %s", ROUTE_PATH, ifconfig_ipv6_local);
3318 argv_msg(M_INFO, &argv);
3319 openvpn_execve_check(&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)");
3320 }
3321
3322 close_tun_generic(tt);
3323 free(tt);
3324 argv_free(&argv);
3325 gc_free(&gc);
3326}
3327
3328int
3329write_tun(struct tuntap *tt, uint8_t *buf, int len)
3330{
3331 if (tt->backend_driver == DRIVER_UTUN)
3332 {
3333 return write_tun_header(tt, buf, len);
3334 }
3335 else
3336 {
3337 return write(tt->fd, buf, len);
3338 }
3339}
3340
3341int
3342read_tun(struct tuntap *tt, uint8_t *buf, int len)
3343{
3344 if (tt->backend_driver == DRIVER_UTUN)
3345 {
3346 return read_tun_header(tt, buf, len);
3347 }
3348 else
3349 {
3350 return read(tt->fd, buf, len);
3351 }
3352}
3353
3354#if defined(__GNUC__) || defined(__clang__)
3355#pragma GCC diagnostic pop
3356#endif
3357
3358#elif defined(TARGET_AIX)
3359
3360void
3361open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3362 openvpn_net_ctx_t *ctx)
3363{
3364 char tunname[256];
3365 char dynamic_name[20];
3366 const char *p;
3367
3368 if (tt->type == DEV_TYPE_TUN)
3369 {
3370 msg(M_FATAL, "no support for 'tun' devices on AIX");
3371 }
3372
3373 if (strncmp(dev, "tap", 3) != 0 || dev_node)
3374 {
3375 msg(M_FATAL,
3376 "'--dev %s' and/or '--dev-node' not supported on AIX, use '--dev tap0', 'tap1', etc.",
3377 dev);
3378 }
3379
3380 if (strcmp(dev, "tap") == 0) /* find first free tap dev */
3381 { /* (= no /dev/tapN node) */
3382 int i;
3383 for (i = 0; i < 99; i++)
3384 {
3385 snprintf(tunname, sizeof(tunname), "/dev/tap%d", i);
3386 if (access(tunname, F_OK) < 0 && errno == ENOENT)
3387 {
3388 break;
3389 }
3390 }
3391 if (i >= 99)
3392 {
3393 msg(M_FATAL, "cannot find unused tap device");
3394 }
3395
3396 snprintf(dynamic_name, sizeof(dynamic_name), "tap%d", i);
3397 dev = dynamic_name;
3398 }
3399 else /* name given, sanity check */
3400 {
3401 /* ensure that dev name is "tap+<digits>" *only* */
3402 p = &dev[3];
3403 while (isdigit(*p))
3404 {
3405 p++;
3406 }
3407 if (*p != '\0')
3408 {
3409 msg(M_FATAL, "TAP device name must be '--dev tapNNNN'");
3410 }
3411
3412 snprintf(tunname, sizeof(tunname), "/dev/%s", dev);
3413 }
3414
3415 /* pre-existing device?
3416 */
3417 if (access(tunname, F_OK) < 0 && errno == ENOENT)
3418 {
3419 /* tunnel device must be created with 'ifconfig tapN create'
3420 */
3421 struct argv argv = argv_new();
3422 struct env_set *es = env_set_create(NULL);
3423 argv_printf(&argv, "%s %s create", IFCONFIG_PATH, dev);
3424 argv_msg(M_INFO, &argv);
3425 env_set_add(es, "ODMDIR=/etc/objrepos");
3426 openvpn_execve_check(&argv, es, S_FATAL, "AIX 'create tun interface' failed");
3428 argv_free(&argv);
3429 }
3430 else
3431 {
3432 /* we didn't make it, we're not going to break it */
3433 tt->persistent_if = TRUE;
3434 }
3435
3436 if ((tt->fd = open(tunname, O_RDWR)) < 0)
3437 {
3438 msg(M_ERR, "Cannot open TAP device '%s'", tunname);
3439 }
3440
3441 set_nonblock(tt->fd);
3442 set_cloexec(tt->fd); /* don't pass fd to scripts */
3443 msg(M_INFO, "TUN/TAP device %s opened", tunname);
3444
3445 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
3446 tt->actual_name = string_alloc(dev, NULL);
3447}
3448
3449/* tap devices need to be manually destroyed on AIX
3450 */
3451void
3452close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3453{
3454 ASSERT(tt);
3455
3456 struct argv argv = argv_new();
3457 struct env_set *es = env_set_create(NULL);
3458
3459 /* persistent devices need IP address unconfig, others need destroyal
3460 */
3461 if (tt->persistent_if)
3462 {
3463 argv_printf(&argv, "%s %s 0.0.0.0 down", IFCONFIG_PATH, tt->actual_name);
3464 }
3465 else
3466 {
3467 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
3468 }
3469
3470 close_tun_generic(tt);
3471 argv_msg(M_INFO, &argv);
3472 env_set_add(es, "ODMDIR=/etc/objrepos");
3473 openvpn_execve_check(&argv, es, 0, "AIX 'destroy tap interface' failed (non-critical)");
3474
3475 free(tt);
3477 argv_free(&argv);
3478}
3479
3480int
3481write_tun(struct tuntap *tt, uint8_t *buf, int len)
3482{
3483 return write(tt->fd, buf, len);
3484}
3485
3486int
3487read_tun(struct tuntap *tt, uint8_t *buf, int len)
3488{
3489 return read(tt->fd, buf, len);
3490}
3491
3492#elif defined(_WIN32)
3493
3494int
3495tun_read_queue(struct tuntap *tt, int maxsize)
3496{
3497 if (tt->reads.iostate == IOSTATE_INITIAL)
3498 {
3499 DWORD len;
3500 BOOL status;
3501 int err;
3502
3503 /* reset buf to its initial state */
3504 tt->reads.buf = tt->reads.buf_init;
3505
3506 len = maxsize ? maxsize : BLEN(&tt->reads.buf);
3507 ASSERT(len <= BLEN(&tt->reads.buf));
3508
3509 /* the overlapped read will signal this event on I/O completion */
3510 ASSERT(ResetEvent(tt->reads.overlapped.hEvent));
3511
3512 status =
3513 ReadFile(tt->hand, BPTR(&tt->reads.buf), len, &tt->reads.size, &tt->reads.overlapped);
3514
3515 if (status) /* operation completed immediately? */
3516 {
3517 /* since we got an immediate return, we must signal the event object ourselves */
3518 ASSERT(SetEvent(tt->reads.overlapped.hEvent));
3519
3521 tt->reads.status = 0;
3522
3523 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]", (int)len,
3524 (int)tt->reads.size);
3525 }
3526 else
3527 {
3528 err = GetLastError();
3529 if (err == ERROR_IO_PENDING) /* operation queued? */
3530 {
3532 tt->reads.status = err;
3533 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]", (int)len);
3534 }
3535 else /* error occurred */
3536 {
3537 struct gc_arena gc = gc_new();
3538 ASSERT(SetEvent(tt->reads.overlapped.hEvent));
3540 tt->reads.status = err;
3541 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s", (int)len,
3543 gc_free(&gc);
3544 }
3545 }
3546 }
3547 return tt->reads.iostate;
3548}
3549
3550int
3551tun_write_queue(struct tuntap *tt, struct buffer *buf)
3552{
3553 if (tt->writes.iostate == IOSTATE_INITIAL)
3554 {
3555 BOOL status;
3556 int err;
3557
3558 /* make a private copy of buf */
3559 tt->writes.buf = tt->writes.buf_init;
3560 tt->writes.buf.len = 0;
3561 ASSERT(buf_copy(&tt->writes.buf, buf));
3562
3563 /* the overlapped write will signal this event on I/O completion */
3564 ASSERT(ResetEvent(tt->writes.overlapped.hEvent));
3565
3566 status = WriteFile(tt->hand, BPTR(&tt->writes.buf), BLEN(&tt->writes.buf), &tt->writes.size,
3567 &tt->writes.overlapped);
3568
3569 if (status) /* operation completed immediately? */
3570 {
3572
3573 /* since we got an immediate return, we must signal the event object ourselves */
3574 ASSERT(SetEvent(tt->writes.overlapped.hEvent));
3575
3576 tt->writes.status = 0;
3577
3578 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]", BLEN(&tt->writes.buf),
3579 (int)tt->writes.size);
3580 }
3581 else
3582 {
3583 err = GetLastError();
3584 if (err == ERROR_IO_PENDING) /* operation queued? */
3585 {
3587 tt->writes.status = err;
3588 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]", BLEN(&tt->writes.buf));
3589 }
3590 else /* error occurred */
3591 {
3592 struct gc_arena gc = gc_new();
3593 ASSERT(SetEvent(tt->writes.overlapped.hEvent));
3595 tt->writes.status = err;
3596 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s", BLEN(&tt->writes.buf),
3597 strerror_win32(err, &gc));
3598 gc_free(&gc);
3599 }
3600 }
3601 }
3602 return tt->writes.iostate;
3603}
3604
3605int
3606tun_write_win32(struct tuntap *tt, struct buffer *buf)
3607{
3608 int err = 0;
3609 int status = 0;
3610 if (overlapped_io_active(&tt->writes))
3611 {
3612 sockethandle_t sh = { .is_handle = true, .h = tt->hand };
3613 status = sockethandle_finalize(sh, &tt->writes, NULL, NULL);
3614 if (status < 0)
3615 {
3616 err = GetLastError();
3617 }
3618 }
3619 tun_write_queue(tt, buf);
3620 if (status < 0)
3621 {
3622 SetLastError(err);
3623 return status;
3624 }
3625 else
3626 {
3627 return BLEN(buf);
3628 }
3629}
3630
3631static const struct device_instance_id_interface *
3633{
3634 HDEVINFO dev_info_set;
3635 DWORD err;
3636 struct device_instance_id_interface *first = NULL;
3637 struct device_instance_id_interface *last = NULL;
3638
3639 dev_info_set =
3640 SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
3641 if (dev_info_set == INVALID_HANDLE_VALUE)
3642 {
3643 err = GetLastError();
3644 msg(M_FATAL, "Error [%u] opening device information set key: %s", (unsigned int)err,
3645 strerror_win32(err, gc));
3646 }
3647
3648 msg(D_TAP_WIN_DEBUG, "Enumerate device interface lists:");
3649 for (DWORD i = 0;; ++i)
3650 {
3651 SP_DEVINFO_DATA device_info_data;
3652 BOOL res;
3653 HKEY dev_key;
3654 char net_cfg_instance_id_string[] = "NetCfgInstanceId";
3655 BYTE net_cfg_instance_id[256];
3656 char device_instance_id[256];
3657 DWORD len;
3658 DWORD data_type;
3659 LONG status;
3660 ULONG dev_interface_list_size;
3661 CONFIGRET cr;
3662
3663 ZeroMemory(&device_info_data, sizeof(SP_DEVINFO_DATA));
3664 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
3665 res = SetupDiEnumDeviceInfo(dev_info_set, i, &device_info_data);
3666 if (!res)
3667 {
3668 if (GetLastError() == ERROR_NO_MORE_ITEMS)
3669 {
3670 break;
3671 }
3672 else
3673 {
3674 continue;
3675 }
3676 }
3677
3678 dev_key = SetupDiOpenDevRegKey(dev_info_set, &device_info_data, DICS_FLAG_GLOBAL, 0,
3679 DIREG_DRV, KEY_QUERY_VALUE);
3680 if (dev_key == INVALID_HANDLE_VALUE)
3681 {
3682 continue;
3683 }
3684
3685 len = sizeof(net_cfg_instance_id);
3686 data_type = REG_SZ;
3687 status = RegQueryValueEx(dev_key, net_cfg_instance_id_string, NULL, &data_type,
3688 net_cfg_instance_id, &len);
3689 if (status != ERROR_SUCCESS)
3690 {
3691 goto next;
3692 }
3693
3694 len = sizeof(device_instance_id);
3695 res = SetupDiGetDeviceInstanceId(dev_info_set, &device_info_data, device_instance_id, len,
3696 &len);
3697 if (!res)
3698 {
3699 goto next;
3700 }
3701
3702 cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size,
3703 (LPGUID)&GUID_DEVINTERFACE_NET, device_instance_id,
3704 CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
3705
3706 if (cr != CR_SUCCESS)
3707 {
3708 goto next;
3709 }
3710
3711 char *dev_interface_list = gc_malloc(dev_interface_list_size, false, gc);
3712 cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_NET, device_instance_id,
3713 dev_interface_list, dev_interface_list_size,
3714 CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
3715 if (cr != CR_SUCCESS)
3716 {
3717 goto next;
3718 }
3719
3720 char *dev_if = dev_interface_list;
3721
3722 /* device interface list ends with empty string */
3723 while (strlen(dev_if) > 0)
3724 {
3725 struct device_instance_id_interface *dev_iif;
3727 dev_iif->net_cfg_instance_id =
3728 (unsigned char *)string_alloc((char *)net_cfg_instance_id, gc);
3729 dev_iif->device_interface = string_alloc(dev_if, gc);
3730
3731 msg(D_TAP_WIN_DEBUG, "NetCfgInstanceId: %s, Device Interface: %s",
3732 dev_iif->net_cfg_instance_id, dev_iif->device_interface);
3733
3734 /* link into return list */
3735 if (!first)
3736 {
3737 first = dev_iif;
3738 }
3739 if (last)
3740 {
3741 last->next = dev_iif;
3742 }
3743 last = dev_iif;
3744
3745 dev_if += strlen(dev_if) + 1;
3746 }
3747
3748next:
3749 RegCloseKey(dev_key);
3750 }
3751
3752 SetupDiDestroyDeviceInfoList(dev_info_set);
3753
3754 return first;
3755}
3756
3757static const struct tap_reg *
3759{
3760 HKEY adapter_key;
3761 LONG status;
3762 DWORD len;
3763 struct tap_reg *first = NULL;
3764 struct tap_reg *last = NULL;
3765 int i = 0;
3766
3767 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &adapter_key);
3768
3769 if (status != ERROR_SUCCESS)
3770 {
3771 msg(M_FATAL, "Error opening registry key: %s", ADAPTER_KEY);
3772 }
3773
3774 msg(D_TAP_WIN_DEBUG, "Enumerate drivers in registy: ");
3775 while (true)
3776 {
3777 char enum_name[256];
3778 char unit_string[256];
3779 HKEY unit_key;
3780 char component_id_string[] = "ComponentId";
3781 char component_id[256];
3782 char net_cfg_instance_id_string[] = "NetCfgInstanceId";
3783 BYTE net_cfg_instance_id[256];
3784 DWORD data_type;
3785
3786 len = sizeof(enum_name);
3787 status = RegEnumKeyEx(adapter_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
3788 if (status == ERROR_NO_MORE_ITEMS)
3789 {
3790 break;
3791 }
3792 else if (status != ERROR_SUCCESS)
3793 {
3794 msg(M_FATAL, "Error enumerating registry subkeys of key: %s", ADAPTER_KEY);
3795 }
3796
3797 snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name);
3798
3799 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key);
3800
3801 if (status != ERROR_SUCCESS)
3802 {
3803 dmsg(D_REGISTRY, "Error opening registry key: %s", unit_string);
3804 }
3805 else
3806 {
3807 len = sizeof(component_id);
3808 status = RegQueryValueEx(unit_key, component_id_string, NULL, &data_type,
3809 (LPBYTE)component_id, &len);
3810
3811 if (status != ERROR_SUCCESS || data_type != REG_SZ)
3812 {
3813 dmsg(D_REGISTRY, "Error opening registry key: %s\\%s", unit_string,
3814 component_id_string);
3815 }
3816 else
3817 {
3818 len = sizeof(net_cfg_instance_id);
3819 status = RegQueryValueEx(unit_key, net_cfg_instance_id_string, NULL, &data_type,
3820 net_cfg_instance_id, &len);
3821
3822 if (status == ERROR_SUCCESS && data_type == REG_SZ)
3823 {
3824 /* Is this adapter supported? */
3826 if (strcasecmp(component_id, TAP_WIN_COMPONENT_ID) == 0
3827 || strcasecmp(component_id, "root\\" TAP_WIN_COMPONENT_ID) == 0)
3828 {
3830 }
3831 else if (strcasecmp(component_id, "ovpn-dco") == 0)
3832 {
3834 }
3835
3837 {
3838 struct tap_reg *reg;
3839 ALLOC_OBJ_CLEAR_GC(reg, struct tap_reg, gc);
3840 reg->guid = string_alloc((char *)net_cfg_instance_id, gc);
3842
3843 /* link into return list */
3844 if (!first)
3845 {
3846 first = reg;
3847 }
3848 if (last)
3849 {
3850 last->next = reg;
3851 }
3852 last = reg;
3853
3854 msg(D_TAP_WIN_DEBUG, "NetCfgInstanceId: %s, Driver: %s", reg->guid,
3856 }
3857 }
3858 }
3859 RegCloseKey(unit_key);
3860 }
3861 ++i;
3862 }
3863
3864 RegCloseKey(adapter_key);
3865 return first;
3866}
3867
3868static const struct panel_reg *
3870{
3871 LONG status;
3872 HKEY network_connections_key;
3873 DWORD len;
3874 struct panel_reg *first = NULL;
3875 struct panel_reg *last = NULL;
3876 int i = 0;
3877
3878 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ,
3879 &network_connections_key);
3880
3881 if (status != ERROR_SUCCESS)
3882 {
3883 msg(M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);
3884 }
3885
3886 while (true)
3887 {
3888 char enum_name[256];
3889 char connection_string[256];
3890 HKEY connection_key;
3891 WCHAR name_data[256];
3892 DWORD name_type;
3893 const WCHAR name_string[] = L"Name";
3894
3895 len = sizeof(enum_name);
3896 status = RegEnumKeyEx(network_connections_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
3897 if (status == ERROR_NO_MORE_ITEMS)
3898 {
3899 break;
3900 }
3901 else if (status != ERROR_SUCCESS)
3902 {
3903 msg(M_FATAL, "Error enumerating registry subkeys of key: %s", NETWORK_CONNECTIONS_KEY);
3904 }
3905
3906 snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection",
3907 NETWORK_CONNECTIONS_KEY, enum_name);
3908
3909 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key);
3910
3911 if (status != ERROR_SUCCESS)
3912 {
3913 dmsg(D_REGISTRY, "Error opening registry key: %s", connection_string);
3914 }
3915 else
3916 {
3917 len = sizeof(name_data);
3918 status = RegQueryValueExW(connection_key, name_string, NULL, &name_type,
3919 (LPBYTE)name_data, &len);
3920
3921 if (status != ERROR_SUCCESS || name_type != REG_SZ)
3922 {
3923 dmsg(D_REGISTRY, "Error opening registry key: %s\\%s\\%ls", NETWORK_CONNECTIONS_KEY,
3924 connection_string, name_string);
3925 }
3926 else
3927 {
3928 int n;
3929 LPSTR name;
3930 struct panel_reg *reg;
3931
3932 ALLOC_OBJ_CLEAR_GC(reg, struct panel_reg, gc);
3933 n = WideCharToMultiByte(CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL);
3934 name = gc_malloc(n, false, gc);
3935 WideCharToMultiByte(CP_UTF8, 0, name_data, -1, name, n, NULL, NULL);
3936 reg->name = name;
3937 reg->guid = string_alloc(enum_name, gc);
3938
3939 /* link into return list */
3940 if (!first)
3941 {
3942 first = reg;
3943 }
3944 if (last)
3945 {
3946 last->next = reg;
3947 }
3948 last = reg;
3949 }
3950 RegCloseKey(connection_key);
3951 }
3952 ++i;
3953 }
3954
3955 RegCloseKey(network_connections_key);
3956
3957 return first;
3958}
3959
3960/*
3961 * Check that two addresses are part of the same 255.255.255.252 subnet.
3962 */
3963void
3965{
3966 struct gc_arena gc = gc_new();
3967 const unsigned int mask = 3;
3968 const char *err = NULL;
3969
3970 if (local == remote)
3971 {
3972 err = "must be different";
3973 goto error;
3974 }
3975 if ((local & (~mask)) != (remote & (~mask)))
3976 {
3977 err =
3978 "must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
3979 goto error;
3980 }
3981 if ((local & mask) == 0 || (local & mask) == 3 || (remote & mask) == 0 || (remote & mask) == 3)
3982 {
3983 err =
3984 "cannot use the first or last address within a given 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
3985 goto error;
3986 }
3987
3988 gc_free(&gc);
3989 return;
3990
3991error:
3992 msg(M_FATAL,
3993 "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s]. The local and remote VPN endpoints %s. Try '" PACKAGE
3994 " --show-valid-subnets' option for more info.",
3995 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), err);
3996 gc_free(&gc);
3997}
3998
3999void
4001{
4002 int i;
4003 int col = 0;
4004
4005 printf("On Windows, point-to-point IP support (i.e. --dev tun)\n");
4006 printf("is emulated by the TAP-Windows driver. The major limitation\n");
4007 printf("imposed by this approach is that the --ifconfig local and\n");
4008 printf("remote endpoints must be part of the same 255.255.255.252\n");
4009 printf("subnet. The following list shows examples of endpoint\n");
4010 printf("pairs which satisfy this requirement. Only the final\n");
4011 printf("component of the IP address pairs is at issue.\n\n");
4012 printf("As an example, the following option would be correct:\n");
4013 printf(" --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n");
4014 printf(" --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n");
4015 printf("because [5,6] is part of the below list.\n\n");
4016
4017 for (i = 0; i < 256; i += 4)
4018 {
4019 printf("[%3d,%3d] ", i + 1, i + 2);
4020 if (++col > 4)
4021 {
4022 col = 0;
4023 printf("\n");
4024 }
4025 }
4026 if (col)
4027 {
4028 printf("\n");
4029 }
4030}
4031
4032void
4034{
4035 struct gc_arena gc = gc_new();
4036
4037 bool warn_panel_null = false;
4038 bool warn_panel_dup = false;
4039 bool warn_tap_dup = false;
4040
4041 int links;
4042
4043 const struct tap_reg *tr;
4044 const struct tap_reg *tr1;
4045 const struct panel_reg *pr;
4046
4047 const struct tap_reg *tap_reg = get_tap_reg(&gc);
4048 const struct panel_reg *panel_reg = get_panel_reg(&gc);
4049
4050 msg(msglevel, "Available adapters [name, GUID, driver]:");
4051
4052 /* loop through each TAP-Windows adapter registry entry */
4053 for (tr = tap_reg; tr != NULL; tr = tr->next)
4054 {
4055 links = 0;
4056
4057 /* loop through each network connections entry in the control panel */
4058 for (pr = panel_reg; pr != NULL; pr = pr->next)
4059 {
4060 if (!strcmp(tr->guid, pr->guid))
4061 {
4062 msg(msglevel, "'%s' %s %s", pr->name, tr->guid,
4064 ++links;
4065 }
4066 }
4067
4068 if (links > 1)
4069 {
4070 warn_panel_dup = true;
4071 }
4072 else if (links == 0)
4073 {
4074 /* a TAP adapter exists without a link from the network
4075 * connections control panel */
4076 warn_panel_null = true;
4077 msg(msglevel, "[NULL] %s", tr->guid);
4078 }
4079 }
4080
4081 /* check for TAP-Windows adapter duplicated GUIDs */
4082 for (tr = tap_reg; tr != NULL; tr = tr->next)
4083 {
4084 for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
4085 {
4086 if (tr != tr1 && !strcmp(tr->guid, tr1->guid))
4087 {
4088 warn_tap_dup = true;
4089 }
4090 }
4091 }
4092
4093 /* warn on registry inconsistencies */
4094 if (warn_tap_dup)
4095 {
4096 msg(warnlevel, "WARNING: Some TAP-Windows adapters have duplicate GUIDs");
4097 }
4098
4099 if (warn_panel_dup)
4100 {
4101 msg(warnlevel,
4102 "WARNING: Some TAP-Windows adapters have duplicate links from the Network Connections control panel");
4103 }
4104
4105 if (warn_panel_null)
4106 {
4107 msg(warnlevel,
4108 "WARNING: Some TAP-Windows adapters have no link from the Network Connections control panel");
4109 }
4110
4111 gc_free(&gc);
4112}
4113
4114/*
4115 * Lookup an adapter by GUID.
4116 */
4117static const struct tap_reg *
4118get_adapter_by_guid(const char *guid, const struct tap_reg *tap_reg)
4119{
4120 const struct tap_reg *tr;
4121
4122 for (tr = tap_reg; tr != NULL; tr = tr->next)
4123 {
4124 if (guid && !strcmp(tr->guid, guid))
4125 {
4126 return tr;
4127 }
4128 }
4129
4130 return NULL;
4131}
4132
4133static const char *
4134guid_to_name(const char *guid, const struct panel_reg *panel_reg)
4135{
4136 const struct panel_reg *pr;
4137
4138 for (pr = panel_reg; pr != NULL; pr = pr->next)
4139 {
4140 if (guid && !strcmp(pr->guid, guid))
4141 {
4142 return pr->name;
4143 }
4144 }
4145
4146 return NULL;
4147}
4148
4149static const struct tap_reg *
4150get_adapter_by_name(const char *name, const struct tap_reg *tap_reg,
4151 const struct panel_reg *panel_reg)
4152{
4153 const struct panel_reg *pr;
4154
4155 for (pr = panel_reg; pr != NULL; pr = pr->next)
4156 {
4157 if (name && !strcmp(pr->name, name))
4158 {
4159 return get_adapter_by_guid(pr->guid, tap_reg);
4160 }
4161 }
4162
4163 return NULL;
4164}
4165
4166static void
4168{
4169 if (!tap_reg)
4170 {
4171 msg(M_FATAL, "There are no TAP-Windows or ovpn-dco adapters "
4172 "on this system. You should be able to create an adapter "
4173 "by using tapctl.exe utility.");
4174 }
4175}
4176
4177/*
4178 * Get an adapter GUID and optional actual_name from the
4179 * registry for the TAP device # = device_number.
4180 */
4181static const char *
4182get_unspecified_device_guid(const int device_number, uint8_t *actual_name, int actual_name_size,
4183 const struct tap_reg *tap_reg_src,
4184 const struct panel_reg *panel_reg_src,
4185 enum tun_driver_type *windows_driver, struct gc_arena *gc)
4186{
4187 const struct tap_reg *tap_reg = tap_reg_src;
4188 struct buffer actual = clear_buf();
4189 int i;
4190
4191 ASSERT(device_number >= 0);
4192
4193 /* Make sure we have at least one TAP adapter */
4194 if (!tap_reg)
4195 {
4196 return NULL;
4197 }
4198
4199 /* The actual_name output buffer may be NULL */
4200 if (actual_name)
4201 {
4203 buf_set_write(&actual, actual_name, actual_name_size);
4204 }
4205
4206 /* Move on to specified device number */
4207 for (i = 0; i < device_number; i++)
4208 {
4209 tap_reg = tap_reg->next;
4210 if (!tap_reg)
4211 {
4212 return NULL;
4213 }
4214 }
4215
4216 /* Save Network Panel name (if exists) in actual_name */
4217 if (actual_name)
4218 {
4219 const char *act = guid_to_name(tap_reg->guid, panel_reg_src);
4220 if (act)
4221 {
4222 buf_printf(&actual, "%s", act);
4223 }
4224 else
4225 {
4226 buf_printf(&actual, "%s", tap_reg->guid);
4227 }
4228 }
4229
4230 /* Save GUID for return value */
4231 struct buffer ret = alloc_buf_gc(256, gc);
4232 buf_printf(&ret, "%s", tap_reg->guid);
4233 if (windows_driver != NULL)
4234 {
4235 *windows_driver = tap_reg->windows_driver;
4236 }
4237 return BSTR(&ret);
4238}
4239
4240/*
4241 * Lookup a --dev-node adapter name in the registry
4242 * returning the GUID and optional actual_name and device type
4243 */
4244static const char *
4245get_device_guid(const char *name, uint8_t *actual_name, int actual_name_size,
4246 enum tun_driver_type *windows_driver, const struct tap_reg *tap_reg,
4247 const struct panel_reg *panel_reg, struct gc_arena *gc)
4248{
4249 struct buffer ret = alloc_buf_gc(256, gc);
4250 struct buffer actual = clear_buf();
4251 const struct tap_reg *tr;
4252
4253 /* Make sure we have at least one TAP adapter */
4254 if (!tap_reg)
4255 {
4256 return NULL;
4257 }
4258
4259 /* The actual_name output buffer may be NULL */
4260 if (actual_name)
4261 {
4262 ASSERT(actual_name_size > 0);
4263 buf_set_write(&actual, actual_name, actual_name_size);
4264 }
4265
4266 /* Check if GUID was explicitly specified as --dev-node parameter */
4267 tr = get_adapter_by_guid(name, tap_reg);
4268 if (tr)
4269 {
4270 const char *act = guid_to_name(name, panel_reg);
4271 buf_printf(&ret, "%s", name);
4272 if (act)
4273 {
4274 buf_printf(&actual, "%s", act);
4275 }
4276 else
4277 {
4278 buf_printf(&actual, "%s", name);
4279 }
4280 if (windows_driver)
4281 {
4283 }
4284 return BSTR(&ret);
4285 }
4286
4287 /* Lookup TAP adapter in network connections list */
4288 {
4290 if (tr)
4291 {
4292 buf_printf(&actual, "%s", name);
4293 if (windows_driver)
4294 {
4296 }
4297 buf_printf(&ret, "%s", tr->guid);
4298 return BSTR(&ret);
4299 }
4300 }
4301
4302 return NULL;
4303}
4304
4305/*
4306 * Get adapter info list
4307 */
4308const IP_ADAPTER_INFO *
4310{
4311 ULONG size = 0;
4312 IP_ADAPTER_INFO *pi = NULL;
4313 DWORD status;
4314
4315 if ((status = GetAdaptersInfo(NULL, &size)) != ERROR_BUFFER_OVERFLOW)
4316 {
4317 msg(M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s", (unsigned int)status,
4319 }
4320 else
4321 {
4322 pi = (PIP_ADAPTER_INFO)gc_malloc(size, false, gc);
4323 if ((status = GetAdaptersInfo(pi, &size)) != NO_ERROR)
4324 {
4325 msg(M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s", (unsigned int)status,
4327 pi = NULL;
4328 }
4329 }
4330 return pi;
4331}
4332
4333const IP_PER_ADAPTER_INFO *
4334get_per_adapter_info(const DWORD index, struct gc_arena *gc)
4335{
4336 ULONG size = 0;
4337 IP_PER_ADAPTER_INFO *pi = NULL;
4338 DWORD status;
4339
4340 if (index != TUN_ADAPTER_INDEX_INVALID)
4341 {
4342 if ((status = GetPerAdapterInfo(index, NULL, &size)) != ERROR_BUFFER_OVERFLOW)
4343 {
4344 msg(M_INFO, "GetPerAdapterInfo #1 failed (status=%u) : %s", (unsigned int)status,
4346 }
4347 else
4348 {
4349 pi = (PIP_PER_ADAPTER_INFO)gc_malloc(size, false, gc);
4350 if ((status = GetPerAdapterInfo((ULONG)index, pi, &size)) == ERROR_SUCCESS)
4351 {
4352 return pi;
4353 }
4354 else
4355 {
4356 msg(M_INFO, "GetPerAdapterInfo #2 failed (status=%u) : %s", (unsigned int)status,
4358 }
4359 }
4360 }
4361 return pi;
4362}
4363
4364static const IP_INTERFACE_INFO *
4366{
4367 ULONG size = 0;
4368 IP_INTERFACE_INFO *ii = NULL;
4369 DWORD status;
4370
4371 if ((status = GetInterfaceInfo(NULL, &size)) != ERROR_INSUFFICIENT_BUFFER)
4372 {
4373 msg(M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s", (unsigned int)status,
4375 }
4376 else
4377 {
4378 ii = (PIP_INTERFACE_INFO)gc_malloc(size, false, gc);
4379 if ((status = GetInterfaceInfo(ii, &size)) == NO_ERROR)
4380 {
4381 return ii;
4382 }
4383 else
4384 {
4385 msg(M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s", (unsigned int)status,
4387 }
4388 }
4389 return ii;
4390}
4391
4392static const IP_ADAPTER_INDEX_MAP *
4393get_interface_info(DWORD index, struct gc_arena *gc)
4394{
4395 const IP_INTERFACE_INFO *list = get_interface_info_list(gc);
4396 if (list)
4397 {
4398 int i;
4399 for (i = 0; i < list->NumAdapters; ++i)
4400 {
4401 const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i];
4402 if (index == inter->Index)
4403 {
4404 return inter;
4405 }
4406 }
4407 }
4408 return NULL;
4409}
4410
4411/*
4412 * Given an adapter index, return a pointer to the
4413 * IP_ADAPTER_INFO structure for that adapter.
4414 */
4415
4416const IP_ADAPTER_INFO *
4417get_adapter(const IP_ADAPTER_INFO *ai, DWORD index)
4418{
4419 if (ai && index != TUN_ADAPTER_INDEX_INVALID)
4420 {
4421 const IP_ADAPTER_INFO *a;
4422
4423 /* find index in the linked list */
4424 for (a = ai; a != NULL; a = a->Next)
4425 {
4426 if (a->Index == index)
4427 {
4428 return a;
4429 }
4430 }
4431 }
4432 return NULL;
4433}
4434
4435const IP_ADAPTER_INFO *
4436get_adapter_info(DWORD index, struct gc_arena *gc)
4437{
4438 return get_adapter(get_adapter_info_list(gc), index);
4439}
4440
4441static int
4442get_adapter_n_ip_netmask(const IP_ADAPTER_INFO *ai)
4443{
4444 if (ai)
4445 {
4446 int n = 0;
4447 const IP_ADDR_STRING *ip = &ai->IpAddressList;
4448
4449 while (ip)
4450 {
4451 ++n;
4452 ip = ip->Next;
4453 }
4454 return n;
4455 }
4456 else
4457 {
4458 return 0;
4459 }
4460}
4461
4462static bool
4463get_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask)
4464{
4465 bool ret = false;
4466 *ip = 0;
4467 *netmask = 0;
4468
4469 if (ai)
4470 {
4471 const IP_ADDR_STRING *iplist = &ai->IpAddressList;
4472 int i = 0;
4473
4474 while (iplist)
4475 {
4476 if (i == n)
4477 {
4478 break;
4479 }
4480 ++i;
4481 iplist = iplist->Next;
4482 }
4483
4484 if (iplist)
4485 {
4486 const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
4487 const char *ip_str = iplist->IpAddress.String;
4488 const char *netmask_str = iplist->IpMask.String;
4489 bool succeed1 = false;
4490 bool succeed2 = false;
4491
4492 if (ip_str && netmask_str && strlen(ip_str) && strlen(netmask_str))
4493 {
4494 *ip = getaddr(getaddr_flags, ip_str, 0, &succeed1, NULL);
4495 *netmask = getaddr(getaddr_flags, netmask_str, 0, &succeed2, NULL);
4496 ret = (succeed1 == true && succeed2 == true);
4497 }
4498 }
4499 }
4500
4501 return ret;
4502}
4503
4504static bool
4505test_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
4506{
4507 if (ai)
4508 {
4509 in_addr_t ip_adapter = 0;
4510 in_addr_t netmask_adapter = 0;
4511 const bool status = get_adapter_ip_netmask(ai, 0, &ip_adapter, &netmask_adapter);
4512 return (status && ip_adapter == ip && netmask_adapter == netmask);
4513 }
4514 else
4515 {
4516 return false;
4517 }
4518}
4519
4520const IP_ADAPTER_INFO *
4521get_tun_adapter(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
4522{
4523 if (list && tt)
4524 {
4525 return get_adapter(list, tt->adapter_index);
4526 }
4527 else
4528 {
4529 return NULL;
4530 }
4531}
4532
4533bool
4534is_adapter_up(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
4535{
4536 int i;
4537 bool ret = false;
4538
4539 const IP_ADAPTER_INFO *ai = get_tun_adapter(tt, list);
4540
4541 if (ai)
4542 {
4543 const int n = get_adapter_n_ip_netmask(ai);
4544
4545 /* loop once for every IP/netmask assigned to adapter */
4546 for (i = 0; i < n; ++i)
4547 {
4548 in_addr_t ip, netmask;
4549 if (get_adapter_ip_netmask(ai, i, &ip, &netmask))
4550 {
4551 if (tt->local && tt->adapter_netmask)
4552 {
4553 /* wait for our --ifconfig parms to match the actual adapter parms */
4554 if (tt->local == ip && tt->adapter_netmask == netmask)
4555 {
4556 ret = true;
4557 }
4558 }
4559 else
4560 {
4561 /* --ifconfig was not defined, maybe using a real DHCP server */
4562 if (ip && netmask)
4563 {
4564 ret = true;
4565 }
4566 }
4567 }
4568 }
4569 }
4570 else
4571 {
4572 ret = true; /* this can occur when TAP adapter is bridged */
4573 }
4574 return ret;
4575}
4576
4577bool
4578is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
4579{
4580 int i;
4581 bool ret = false;
4582
4583 if (highest_netmask)
4584 {
4585 *highest_netmask = 0;
4586 }
4587
4588 if (ai)
4589 {
4590 const int n = get_adapter_n_ip_netmask(ai);
4591 for (i = 0; i < n; ++i)
4592 {
4593 in_addr_t adapter_ip, adapter_netmask;
4594 if (get_adapter_ip_netmask(ai, i, &adapter_ip, &adapter_netmask))
4595 {
4596 if (adapter_ip && adapter_netmask
4597 && (ip & adapter_netmask) == (adapter_ip & adapter_netmask))
4598 {
4599 if (highest_netmask && adapter_netmask > *highest_netmask)
4600 {
4601 *highest_netmask = adapter_netmask;
4602 }
4603 ret = true;
4604 }
4605 }
4606 }
4607 }
4608 return ret;
4609}
4610
4611DWORD
4612adapter_index_of_ip(const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count, in_addr_t *netmask)
4613{
4614 struct gc_arena gc = gc_new();
4615 DWORD ret = TUN_ADAPTER_INDEX_INVALID;
4616 in_addr_t highest_netmask = 0;
4617 int lowest_metric = INT_MAX;
4618 bool first = true;
4619
4620 if (count)
4621 {
4622 *count = 0;
4623 }
4624
4625 while (list)
4626 {
4627 in_addr_t hn;
4628
4629 if (is_ip_in_adapter_subnet(list, ip, &hn))
4630 {
4631 int metric = get_interface_metric(list->Index, AF_INET, NULL);
4632 if (first || hn > highest_netmask)
4633 {
4634 highest_netmask = hn;
4635 if (metric >= 0)
4636 {
4637 lowest_metric = metric;
4638 }
4639 if (count)
4640 {
4641 *count = 1;
4642 }
4643 ret = list->Index;
4644 first = false;
4645 }
4646 else if (hn == highest_netmask)
4647 {
4648 if (count)
4649 {
4650 ++*count;
4651 }
4652 if (metric >= 0 && metric < lowest_metric)
4653 {
4654 ret = list->Index;
4655 lowest_metric = metric;
4656 }
4657 }
4658 }
4659 list = list->Next;
4660 }
4661
4662 dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d metric=%d",
4663 print_in_addr_t(ip, 0, &gc), print_in_addr_t(highest_netmask, 0, &gc), (int)ret,
4664 count ? *count : -1, lowest_metric);
4665
4666 if (ret == TUN_ADAPTER_INDEX_INVALID && count)
4667 {
4668 *count = 0;
4669 }
4670
4671 if (netmask)
4672 {
4673 *netmask = highest_netmask;
4674 }
4675
4676 gc_free(&gc);
4677 return ret;
4678}
4679
4680/*
4681 * Given an adapter index, return true if the adapter
4682 * is DHCP disabled.
4683 */
4684
4685#define DHCP_STATUS_UNDEF 0
4686#define DHCP_STATUS_ENABLED 1
4687#define DHCP_STATUS_DISABLED 2
4688
4689static int
4690dhcp_status(DWORD index)
4691{
4692 struct gc_arena gc = gc_new();
4693 int ret = DHCP_STATUS_UNDEF;
4694 if (index != TUN_ADAPTER_INDEX_INVALID)
4695 {
4696 const IP_ADAPTER_INFO *ai = get_adapter_info(index, &gc);
4697
4698 if (ai)
4699 {
4700 if (ai->DhcpEnabled)
4701 {
4702 ret = DHCP_STATUS_ENABLED;
4703 }
4704 else
4705 {
4707 }
4708 }
4709 }
4710 gc_free(&gc);
4711 return ret;
4712}
4713
4714/*
4715 * Delete all temporary address/netmask pairs which were added
4716 * to adapter (given by index) by previous calls to AddIPAddress.
4717 */
4718static void
4720{
4721 struct gc_arena gc = gc_new();
4722 const IP_ADAPTER_INFO *a = get_adapter_info(index, &gc);
4723
4724 if (a)
4725 {
4726 const IP_ADDR_STRING *ip = &a->IpAddressList;
4727 while (ip)
4728 {
4729 DWORD status;
4730 const DWORD context = ip->Context;
4731
4732 if ((status = DeleteIPAddress((ULONG)context)) == NO_ERROR)
4733 {
4734 msg(M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s",
4735 ip->IpAddress.String, ip->IpMask.String);
4736 }
4737 else
4738 {
4739 const char *empty = "0.0.0.0";
4740 if (strcmp(ip->IpAddress.String, empty) || strcmp(ip->IpMask.String, empty))
4741 {
4742 msg(M_INFO,
4743 "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)",
4744 ip->IpAddress.String, ip->IpMask.String, (unsigned int)status);
4745 }
4746 }
4747 ip = ip->Next;
4748 }
4749 }
4750 gc_free(&gc);
4751}
4752
4753/*
4754 * Get interface index for use with IP Helper API functions.
4755 */
4756static DWORD
4758{
4759 DWORD index;
4760 ULONG aindex;
4761 wchar_t wbuf[256];
4762 swprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%hs", guid);
4763 if (GetAdapterIndex(wbuf, &aindex) != NO_ERROR)
4764 {
4766 }
4767 else
4768 {
4769 index = (DWORD)aindex;
4770 }
4771 return index;
4772}
4773
4774static DWORD
4776{
4777 struct gc_arena gc = gc_new();
4778 DWORD index = TUN_ADAPTER_INDEX_INVALID;
4779
4780 const IP_ADAPTER_INFO *list = get_adapter_info_list(&gc);
4781
4782 while (list)
4783 {
4784 if (!strcmp(guid, list->AdapterName))
4785 {
4786 index = list->Index;
4787 break;
4788 }
4789 list = list->Next;
4790 }
4791
4792 gc_free(&gc);
4793 return index;
4794}
4795
4796static DWORD
4797get_adapter_index(const char *guid)
4798{
4799 DWORD index;
4800 index = get_adapter_index_method_1(guid);
4801 if (index == TUN_ADAPTER_INDEX_INVALID)
4802 {
4803 index = get_adapter_index_method_2(guid);
4804 }
4805 if (index == TUN_ADAPTER_INDEX_INVALID)
4806 {
4807 msg(M_INFO, "NOTE: could not get adapter index for %s", guid);
4808 }
4809 return index;
4810}
4811
4812/*
4813 * Return a string representing a PIP_ADDR_STRING
4814 */
4815static const char *
4816format_ip_addr_string(const IP_ADDR_STRING *ip, struct gc_arena *gc)
4817{
4818 struct buffer out = alloc_buf_gc(256, gc);
4819 while (ip)
4820 {
4821 buf_printf(&out, "%s", ip->IpAddress.String);
4822 if (strlen(ip->IpMask.String))
4823 {
4824 buf_printf(&out, "/");
4825 buf_printf(&out, "%s", ip->IpMask.String);
4826 }
4827 buf_printf(&out, " ");
4828 ip = ip->Next;
4829 }
4830 return BSTR(&out);
4831}
4832
4833/*
4834 * Show info for a single adapter
4835 */
4836static void
4838{
4839 msg(msglevel, "%s", a->Description);
4840 msg(msglevel, " Index = %d", (int)a->Index);
4841 msg(msglevel, " GUID = %s", a->AdapterName);
4842 msg(msglevel, " IP = %s", format_ip_addr_string(&a->IpAddressList, gc));
4843 msg(msglevel, " MAC = %s", format_hex_ex(a->Address, a->AddressLength, 0, 1, ":", gc));
4844 msg(msglevel, " GATEWAY = %s", format_ip_addr_string(&a->GatewayList, gc));
4845 if (a->DhcpEnabled)
4846 {
4847 msg(msglevel, " DHCP SERV = %s", format_ip_addr_string(&a->DhcpServer, gc));
4848 msg(msglevel, " DHCP LEASE OBTAINED = %s", time_string(a->LeaseObtained, 0, false, gc));
4849 msg(msglevel, " DHCP LEASE EXPIRES = %s", time_string(a->LeaseExpires, 0, false, gc));
4850 }
4851 if (a->HaveWins)
4852 {
4853 msg(msglevel, " PRI WINS = %s", format_ip_addr_string(&a->PrimaryWinsServer, gc));
4854 msg(msglevel, " SEC WINS = %s", format_ip_addr_string(&a->SecondaryWinsServer, gc));
4855 }
4856
4857 {
4859 if (pai)
4860 {
4861 msg(msglevel, " DNS SERV = %s", format_ip_addr_string(&pai->DnsServerList, gc));
4862 }
4863 }
4864}
4865
4866/*
4867 * Show current adapter list
4868 */
4869void
4871{
4872 struct gc_arena gc = gc_new();
4873 const IP_ADAPTER_INFO *ai = get_adapter_info_list(&gc);
4874
4875 msg(msglevel, "SYSTEM ADAPTER LIST");
4876 if (ai)
4877 {
4878 const IP_ADAPTER_INFO *a;
4879
4880 /* find index in the linked list */
4881 for (a = ai; a != NULL; a = a->Next)
4882 {
4883 show_adapter(msglevel, a, &gc);
4884 }
4885 }
4886 gc_free(&gc);
4887}
4888
4889/*
4890 * Set a particular TAP-Windows adapter (or all of them if
4891 * adapter_name == NULL) to allow it to be opened from
4892 * a non-admin account. This setting will only persist
4893 * for the lifetime of the device object.
4894 */
4895
4896static void
4897tap_allow_nonadmin_access_handle(const char *device_path, HANDLE hand)
4898{
4899 struct security_attributes sa;
4900 BOOL status;
4901
4903 {
4904 msg(M_ERR, "Error: init SA failed");
4905 }
4906
4907 status = SetKernelObjectSecurity(hand, DACL_SECURITY_INFORMATION, &sa.sd);
4908 if (!status)
4909 {
4910 msg(M_ERRNO, "Error: SetKernelObjectSecurity failed on %s", device_path);
4911 }
4912 else
4913 {
4914 msg(M_INFO | M_NOPREFIX, "TAP-Windows device: %s [Non-admin access allowed]", device_path);
4915 }
4916}
4917
4918void
4919tap_allow_nonadmin_access(const char *dev_node)
4920{
4921 struct gc_arena gc = gc_new();
4922 const struct tap_reg *tap_reg = get_tap_reg(&gc);
4923 const struct panel_reg *panel_reg = get_panel_reg(&gc);
4924 const char *device_guid = NULL;
4925 HANDLE hand;
4926 uint8_t actual_buffer[256];
4927 char device_path[256];
4928
4930
4931 if (dev_node)
4932 {
4933 /* Get the device GUID for the device specified with --dev-node. */
4934 device_guid = get_device_guid(dev_node, actual_buffer, sizeof(actual_buffer), NULL, tap_reg,
4935 panel_reg, &gc);
4936
4937 if (!device_guid)
4938 {
4939 msg(M_FATAL, "TAP-Windows adapter '%s' not found", dev_node);
4940 }
4941
4942 /* Open Windows TAP-Windows adapter */
4943 snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid,
4944 TAP_WIN_SUFFIX);
4945
4946 hand = CreateFile(device_path, MAXIMUM_ALLOWED, 0, /* was: FILE_SHARE_READ */
4947 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
4948
4949 if (hand == INVALID_HANDLE_VALUE)
4950 {
4951 msg(M_ERR, "CreateFile failed on TAP device: %s", device_path);
4952 }
4953
4954 tap_allow_nonadmin_access_handle(device_path, hand);
4955 CloseHandle(hand);
4956 }
4957 else
4958 {
4959 int device_number = 0;
4960
4961 /* Try opening all TAP devices */
4962 while (true)
4963 {
4964 device_guid = get_unspecified_device_guid(
4965 device_number, actual_buffer, sizeof(actual_buffer), tap_reg, panel_reg, NULL, &gc);
4966
4967 if (!device_guid)
4968 {
4969 break;
4970 }
4971
4972 /* Open Windows TAP-Windows adapter */
4973 snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid,
4974 TAP_WIN_SUFFIX);
4975
4976 hand = CreateFile(device_path, MAXIMUM_ALLOWED, 0, /* was: FILE_SHARE_READ */
4977 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
4978
4979 if (hand == INVALID_HANDLE_VALUE)
4980 {
4981 msg(M_WARN, "CreateFile failed on TAP device: %s", device_path);
4982 }
4983 else
4984 {
4985 tap_allow_nonadmin_access_handle(device_path, hand);
4986 CloseHandle(hand);
4987 }
4988
4989 device_number++;
4990 }
4991 }
4992 gc_free(&gc);
4993}
4994
4995/*
4996 * DHCP release/renewal
4997 */
4998bool
4999dhcp_release_by_adapter_index(const DWORD adapter_index)
5000{
5001 struct gc_arena gc = gc_new();
5002 bool ret = false;
5003 const IP_ADAPTER_INDEX_MAP *inter = get_interface_info(adapter_index, &gc);
5004
5005 if (inter)
5006 {
5007 DWORD status = IpReleaseAddress((IP_ADAPTER_INDEX_MAP *)inter);
5008 if (status == NO_ERROR)
5009 {
5010 msg(D_TUNTAP_INFO, "TAP: DHCP address released");
5011 ret = true;
5012 }
5013 else
5014 {
5015 msg(M_WARN,
5016 "NOTE: Release of DHCP-assigned IP address lease on TAP-Windows adapter failed: %s (code=%u)",
5017 strerror_win32(status, &gc), (unsigned int)status);
5018 }
5019 }
5020
5021 gc_free(&gc);
5022 return ret;
5023}
5024
5025static bool
5026dhcp_release(const struct tuntap *tt)
5027{
5030 {
5032 }
5033 else
5034 {
5035 return false;
5036 }
5037}
5038
5039bool
5040dhcp_renew_by_adapter_index(const DWORD adapter_index)
5041{
5042 struct gc_arena gc = gc_new();
5043 bool ret = false;
5044 const IP_ADAPTER_INDEX_MAP *inter = get_interface_info(adapter_index, &gc);
5045
5046 if (inter)
5047 {
5048 DWORD status = IpRenewAddress((IP_ADAPTER_INDEX_MAP *)inter);
5049 if (status == NO_ERROR)
5050 {
5051 msg(D_TUNTAP_INFO, "TAP: DHCP address renewal succeeded");
5052 ret = true;
5053 }
5054 else
5055 {
5056 msg(M_WARN,
5057 "WARNING: Failed to renew DHCP IP address lease on TAP-Windows adapter: %s (code=%u)",
5058 strerror_win32(status, &gc), (unsigned int)status);
5059 }
5060 }
5061 gc_free(&gc);
5062 return ret;
5063}
5064
5065static bool
5066dhcp_renew(const struct tuntap *tt)
5067{
5070 {
5072 }
5073 else
5074 {
5075 return false;
5076 }
5077}
5078
5079static void
5080exec_command(const char *prefix, const struct argv *a, int n, msglvl_t msglevel)
5081{
5082 int i;
5083 for (i = 0; i < n; ++i)
5084 {
5085 bool status;
5088 argv_msg_prefix(M_INFO, a, prefix);
5089 status = openvpn_execve_check(a, NULL, 0, "ERROR: command failed");
5091 if (status)
5092 {
5093 return;
5094 }
5096 }
5097 msg(msglevel, "%s: command failed", prefix);
5098}
5099
5100static void
5101netsh_command(const struct argv *a, int n, msglvl_t msglevel)
5102{
5103 exec_command("NETSH", a, n, msglevel);
5104}
5105
5106void
5108{
5109 struct argv argv = argv_new();
5110 const char err[] = "ERROR: Windows ipconfig command failed";
5111
5112 msg(D_TUNTAP_INFO, "Start ipconfig commands for register-dns...");
5114
5117 openvpn_execve_check(&argv, es, 0, err);
5118
5119 argv_printf(&argv, "%s%s /registerdns", get_win_sys_path(), WIN_IPCONFIG_PATH_SUFFIX);
5121 openvpn_execve_check(&argv, es, 0, err);
5122 argv_free(&argv);
5123
5125 msg(D_TUNTAP_INFO, "End ipconfig commands for register-dns...");
5126}
5127
5128void
5129ip_addr_string_to_array(in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
5130{
5131 int i = 0;
5132 while (src)
5133 {
5134 const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
5135 const char *ip_str = src->IpAddress.String;
5136 in_addr_t ip = 0;
5137 bool succeed = false;
5138
5139 if (i >= *dest_len)
5140 {
5141 break;
5142 }
5143 if (!ip_str || !strlen(ip_str))
5144 {
5145 break;
5146 }
5147
5148 ip = getaddr(getaddr_flags, ip_str, 0, &succeed, NULL);
5149 if (!succeed)
5150 {
5151 break;
5152 }
5153 dest[i++] = ip;
5154
5155 src = src->Next;
5156 }
5157 *dest_len = i;
5158
5159#if 0
5160 {
5161 struct gc_arena gc = gc_new();
5162 msg(M_INFO, "ip_addr_string_to_array [%d]", *dest_len);
5163 for (i = 0; i < *dest_len; ++i)
5164 {
5165 msg(M_INFO, "%s", print_in_addr_t(dest[i], 0, &gc));
5166 }
5167 gc_free(&gc);
5168 }
5169#endif
5170}
5171
5172static bool
5173ip_addr_one_to_one(const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
5174{
5175 in_addr_t a2[8];
5176 int a2len = SIZE(a2);
5177 int i;
5178
5179 ip_addr_string_to_array(a2, &a2len, ias);
5180 /*msg (M_INFO, "a1len=%d a2len=%d", a1len, a2len);*/
5181 if (a1len != a2len)
5182 {
5183 return false;
5184 }
5185
5186 for (i = 0; i < a1len; ++i)
5187 {
5188 if (a1[i] != a2[i])
5189 {
5190 return false;
5191 }
5192 }
5193 return true;
5194}
5195
5196static bool
5197ip_addr_member_of(const in_addr_t addr, const IP_ADDR_STRING *ias)
5198{
5199 in_addr_t aa[8];
5200 int len = SIZE(aa);
5201 int i;
5202
5203 ip_addr_string_to_array(aa, &len, ias);
5204 for (i = 0; i < len; ++i)
5205 {
5206 if (addr == aa[i])
5207 {
5208 return true;
5209 }
5210 }
5211 return false;
5212}
5213
5219static void
5220netsh_set_dns6_servers(const struct in6_addr *addr_list, const int addr_len, DWORD adapter_index)
5221{
5222 struct gc_arena gc = gc_new();
5223 struct argv argv = argv_new();
5224
5225 /* delete existing DNS settings from TAP interface */
5226 argv_printf(&argv, "%s%s interface ipv6 delete dns %lu all", get_win_sys_path(),
5227 NETSH_PATH_SUFFIX, adapter_index);
5229
5230 for (int i = 0; i < addr_len; ++i)
5231 {
5232 const char *fmt = (i == 0) ? "%s%s interface ipv6 set dns %lu static %s"
5233 : "%s%s interface ipv6 add dns %lu %s";
5234 argv_printf(&argv, fmt, get_win_sys_path(), NETSH_PATH_SUFFIX, adapter_index,
5235 print_in6_addr(addr_list[i], 0, &gc));
5236
5237 /* disable slow address validation */
5238 argv_printf_cat(&argv, "%s", "validate=no");
5239
5240 /* Treat errors while adding as non-fatal as we do not check for duplicates */
5241 netsh_command(&argv, 1, (i == 0) ? M_FATAL : M_NONFATAL);
5242 }
5243
5244 argv_free(&argv);
5245 gc_free(&gc);
5246}
5247
5248static void
5249netsh_ifconfig_options(const char *type, const in_addr_t *addr_list, const int addr_len,
5250 const IP_ADDR_STRING *current, DWORD adapter_index, const bool test_first)
5251{
5252 struct gc_arena gc = gc_new();
5253 struct argv argv = argv_new();
5254 bool delete_first = false;
5255 bool is_dns = !strcmp(type, "dns");
5256
5257 /* first check if we should delete existing DNS/WINS settings from TAP interface */
5258 if (test_first)
5259 {
5260 if (!ip_addr_one_to_one(addr_list, addr_len, current))
5261 {
5262 delete_first = true;
5263 }
5264 }
5265 else
5266 {
5267 delete_first = true;
5268 }
5269
5270 /* delete existing DNS/WINS settings from TAP interface */
5271 if (delete_first)
5272 {
5273 argv_printf(&argv, "%s%s interface ip delete %s %lu all", get_win_sys_path(),
5274 NETSH_PATH_SUFFIX, type, adapter_index);
5276 }
5277
5278 /* add new DNS/WINS settings to TAP interface */
5279 {
5280 int count = 0;
5281 int i;
5282 for (i = 0; i < addr_len; ++i)
5283 {
5284 if (delete_first || !test_first || !ip_addr_member_of(addr_list[i], current))
5285 {
5286 const char *fmt = count ? "%s%s interface ip add %s %lu %s"
5287 : "%s%s interface ip set %s %lu static %s";
5288
5289 argv_printf(&argv, fmt, get_win_sys_path(), NETSH_PATH_SUFFIX, type, adapter_index,
5290 print_in_addr_t(addr_list[i], 0, &gc));
5291
5292 /* disable slow address validation for DNS */
5293 if (is_dns)
5294 {
5295 argv_printf_cat(&argv, "%s", "validate=no");
5296 }
5297
5299
5300 ++count;
5301 }
5302 else
5303 {
5304 msg(M_INFO, "NETSH: %lu %s %s [already set]", adapter_index, type,
5305 print_in_addr_t(addr_list[i], 0, &gc));
5306 }
5307 }
5308 }
5309
5310 argv_free(&argv);
5311 gc_free(&gc);
5312}
5313
5314static void
5315init_ip_addr_string2(IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
5316{
5317 CLEAR(dest[0]);
5318 CLEAR(dest[1]);
5319 if (src1)
5320 {
5321 dest[0] = *src1;
5322 dest[0].Next = NULL;
5323 }
5324 if (src2)
5325 {
5326 dest[1] = *src2;
5327 dest[0].Next = &dest[1];
5328 dest[1].Next = NULL;
5329 }
5330}
5331
5332static void
5333netsh_ifconfig(const struct tuntap_options *to, DWORD adapter_index, const in_addr_t ip,
5334 const in_addr_t netmask, const unsigned int flags)
5335{
5336 struct gc_arena gc = gc_new();
5337 struct argv argv = argv_new();
5338 const IP_ADAPTER_INFO *ai = NULL;
5339 const IP_PER_ADAPTER_INFO *pai = NULL;
5340
5341 if (flags & NI_TEST_FIRST)
5342 {
5343 const IP_ADAPTER_INFO *list = get_adapter_info_list(&gc);
5344 ai = get_adapter(list, adapter_index);
5345 pai = get_per_adapter_info(adapter_index, &gc);
5346 }
5347
5348 if (flags & NI_IP_NETMASK)
5349 {
5350 if (test_adapter_ip_netmask(ai, ip, netmask))
5351 {
5352 msg(M_INFO, "NETSH: %lu %s/%s [already set]", adapter_index,
5353 print_in_addr_t(ip, 0, &gc), print_in_addr_t(netmask, 0, &gc));
5354 }
5355 else
5356 {
5357 /* example: netsh interface ip set address 42 static 10.3.0.1 255.255.255.0 */
5358 argv_printf(&argv, "%s%s interface ip set address %lu static %s %s", get_win_sys_path(),
5359 NETSH_PATH_SUFFIX, adapter_index, print_in_addr_t(ip, 0, &gc),
5360 print_in_addr_t(netmask, 0, &gc));
5361
5363 }
5364 }
5365
5366 /* set WINS/DNS options */
5367 if (flags & NI_OPTIONS)
5368 {
5369 IP_ADDR_STRING wins[2];
5370 CLEAR(wins[0]);
5371 CLEAR(wins[1]);
5372
5373 netsh_ifconfig_options("dns", to->dns, to->dns_len, pai ? &pai->DnsServerList : NULL,
5374 adapter_index, BOOL_CAST(flags & NI_TEST_FIRST));
5375 if (ai && ai->HaveWins)
5376 {
5377 init_ip_addr_string2(wins, &ai->PrimaryWinsServer, &ai->SecondaryWinsServer);
5378 }
5379
5380 netsh_ifconfig_options("wins", to->wins, to->wins_len, ai ? wins : NULL, adapter_index,
5381 BOOL_CAST(flags & NI_TEST_FIRST));
5382 }
5383
5384 argv_free(&argv);
5385 gc_free(&gc);
5386}
5387
5388static void
5389netsh_enable_dhcp(DWORD adapter_index)
5390{
5391 struct argv argv = argv_new();
5392
5393 /* example: netsh interface ip set address 42 dhcp */
5394 argv_printf(&argv, "%s%s interface ip set address %lu dhcp", get_win_sys_path(),
5395 NETSH_PATH_SUFFIX, adapter_index);
5396
5398
5399 argv_free(&argv);
5400}
5401
5402/* Enable dhcp on tap adapter using iservice */
5403static bool
5405{
5406 bool ret = false;
5407 ack_message_t ack;
5408 struct gc_arena gc = gc_new();
5409 HANDLE pipe = tt->options.msg_channel;
5410
5412 .iface = { .index = tt->adapter_index, .name = "" } };
5413
5414 if (!send_msg_iservice(pipe, &dhcp, sizeof(dhcp), &ack, "Enable_dhcp"))
5415 {
5416 goto out;
5417 }
5418
5419 if (ack.error_number != NO_ERROR)
5420 {
5421 msg(M_NONFATAL, "TUN: enabling dhcp using service failed: %s [status=%u if_index=%d]",
5422 strerror_win32(ack.error_number, &gc), ack.error_number, dhcp.iface.index);
5423 }
5424 else
5425 {
5426 msg(M_INFO, "DHCP enabled on interface %d using service", dhcp.iface.index);
5427 ret = true;
5428 }
5429
5430out:
5431 gc_free(&gc);
5432 return ret;
5433}
5434
5435static void
5436windows_set_mtu(const int iface_index, const short family, const int mtu)
5437{
5438 DWORD err = 0;
5439 struct gc_arena gc = gc_new();
5440 MIB_IPINTERFACE_ROW ipiface;
5441 InitializeIpInterfaceEntry(&ipiface);
5442 const char *family_name = (family == AF_INET6) ? "IPv6" : "IPv4";
5443 ipiface.Family = family;
5444 ipiface.InterfaceIndex = iface_index;
5445 if (family == AF_INET6 && mtu < 1280)
5446 {
5447 msg(M_INFO,
5448 "NOTE: IPv6 interface MTU < 1280 conflicts with IETF standards and might not work");
5449 }
5450
5451 err = GetIpInterfaceEntry(&ipiface);
5452 if (err == NO_ERROR)
5453 {
5454 if (family == AF_INET)
5455 {
5456 ipiface.SitePrefixLength = 0;
5457 }
5458 ipiface.NlMtu = mtu;
5459 err = SetIpInterfaceEntry(&ipiface);
5460 }
5461
5462 if (err != NO_ERROR)
5463 {
5464 msg(M_WARN, "TUN: Setting %s mtu failed: %s [status=%lu if_index=%d]", family_name,
5465 strerror_win32(err, &gc), err, iface_index);
5466 }
5467 else
5468 {
5469 msg(M_INFO, "%s MTU set to %d on interface %d using SetIpInterfaceEntry()", family_name,
5470 mtu, iface_index);
5471 }
5472}
5473
5474
5475/*
5476 * Return a TAP name for netsh commands.
5477 */
5478static const char *
5479netsh_get_id(const char *dev_node, struct gc_arena *gc)
5480{
5481 const struct tap_reg *tap_reg = get_tap_reg(gc);
5482 const struct panel_reg *panel_reg = get_panel_reg(gc);
5483 struct buffer actual = alloc_buf_gc(256, gc);
5484 const char *guid;
5485
5487
5488 if (dev_node)
5489 {
5490 guid =
5491 get_device_guid(dev_node, BPTR(&actual), BCAP(&actual), NULL, tap_reg, panel_reg, gc);
5492 }
5493 else
5494 {
5495 guid = get_unspecified_device_guid(0, BPTR(&actual), BCAP(&actual), tap_reg, panel_reg,
5496 NULL, gc);
5497
5499 gc)) /* ambiguous if more than one TAP-Windows adapter */
5500 {
5501 guid = NULL;
5502 }
5503 }
5504
5505 if (!guid)
5506 {
5507 return "NULL"; /* not found */
5508 }
5509 else if (strcmp(BSTR(&actual), "NULL"))
5510 {
5511 return BSTR(&actual); /* control panel name */
5512 }
5513 else
5514 {
5515 return guid; /* no control panel name, return GUID instead */
5516 }
5517}
5518
5519/*
5520 * Called iteratively on TAP-Windows wait-for-initialization polling loop
5521 */
5522void
5524{
5525 tt->standby_iter = 0;
5526}
5527
5528bool
5530{
5531 bool ret = true;
5532 ++tt->standby_iter;
5533 if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
5534 {
5535 if (tt->standby_iter == IPW32_SET_ADAPTIVE_TRY_NETSH)
5536 {
5537 msg(M_INFO, "NOTE: now trying netsh (this may take some time)");
5538 netsh_ifconfig(&tt->options, tt->adapter_index, tt->local, tt->adapter_netmask,
5540 }
5541 else if (tt->standby_iter >= IPW32_SET_ADAPTIVE_TRY_NETSH * 2)
5542 {
5543 ret = false;
5544 }
5545 }
5546 return ret;
5547}
5548
5549static void
5551{
5552 if (tt->options.dhcp_pre_release || tt->options.dhcp_renew)
5553 {
5554 struct gc_arena gc = gc_new();
5555 struct buffer cmd = alloc_buf_gc(256, &gc);
5556 const int verb = 3;
5557 const int pre_sleep = 1;
5558
5559 buf_printf(&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep);
5560 if (tt->options.dhcp_pre_release)
5561 {
5562 buf_printf(&cmd, " --dhcp-pre-release");
5563 }
5564 if (tt->options.dhcp_renew)
5565 {
5566 buf_printf(&cmd, " --dhcp-renew");
5567 }
5568 buf_printf(&cmd, " --dhcp-internal %lu", tt->adapter_index);
5569
5571 gc_free(&gc);
5572 }
5573}
5574
5575static void
5577{
5578 HANDLE msg_channel = tt->options.msg_channel;
5580 struct gc_arena gc = gc_new();
5581
5582 message_header_t rdns = { msg_register_dns, sizeof(message_header_t), 0 };
5583
5584 if (!send_msg_iservice(msg_channel, &rdns, sizeof(rdns), &ack, "Register_dns"))
5585 {
5586 gc_free(&gc);
5587 return;
5588 }
5589
5590 else if (ack.error_number != NO_ERROR)
5591 {
5592 msg(M_WARN, "Register_dns failed using service: %s [status=0x%x]",
5594 }
5595
5596 else
5597 {
5598 msg(M_INFO, "Register_dns request sent to the service");
5599 }
5600
5601 gc_free(&gc);
5602}
5603
5604void
5606{
5607 if (tt && tt->options.register_dns && tt->options.msg_channel)
5608 {
5610 }
5611 else if (tt && tt->options.register_dns)
5612 {
5613 struct gc_arena gc = gc_new();
5614 struct buffer cmd = alloc_buf_gc(256, &gc);
5615 const int verb = 3;
5616
5617 buf_printf(&cmd, "openvpn --verb %d --register-dns --rdns-internal", verb);
5619 gc_free(&gc);
5620 }
5621}
5622
5623static uint32_t
5624dhcp_masq_addr(const in_addr_t local, const in_addr_t netmask, const int offset)
5625{
5626 struct gc_arena gc = gc_new();
5627 in_addr_t dsa; /* DHCP server addr */
5628
5629 if (offset < 0)
5630 {
5631 dsa = (local | (~netmask)) + offset;
5632 }
5633 else
5634 {
5635 dsa = (local & netmask) + offset;
5636 }
5637
5638 if (dsa == local)
5639 {
5640 msg(M_FATAL,
5641 "ERROR: There is a clash between the --ifconfig local address and the internal DHCP server address -- both are set to %s -- please use the --ip-win32 dynamic option to choose a different free address from the --ifconfig subnet for the internal DHCP server",
5642 print_in_addr_t(dsa, 0, &gc));
5643 }
5644
5645 if ((local & netmask) != (dsa & netmask))
5646 {
5647 msg(M_FATAL, "ERROR: --ip-win32 dynamic [offset] : offset is outside of --ifconfig subnet");
5648 }
5649
5650 gc_free(&gc);
5651 return htonl(dsa);
5652}
5653
5654static void
5656{
5657 ULONG info[3];
5658 DWORD len;
5659 CLEAR(info);
5660 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_VERSION, &info, sizeof(info), &info,
5661 sizeof(info), &len, NULL))
5662 {
5663 msg(D_TUNTAP_INFO, "TAP-Windows Driver Version %d.%d %s", (int)info[0], (int)info[1],
5664 (info[2] ? "(DEBUG)" : ""));
5665 }
5666 if (!(info[0] == TAP_WIN_MIN_MAJOR && info[1] >= TAP_WIN_MIN_MINOR))
5667 {
5668 msg(M_FATAL,
5669 "ERROR: This version of " PACKAGE_NAME
5670 " requires a TAP-Windows driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME
5671 " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
5672 TAP_WIN_MIN_MAJOR, TAP_WIN_MIN_MINOR);
5673 }
5674
5675 /* usage of numeric constants is ugly, but this is really tied to
5676 * *this* version of the driver
5677 */
5678 if (tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] < 8)
5679 {
5680 msg(M_INFO,
5681 "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will not work. Upgrade your Tap-Win32 driver.",
5682 (int)info[0], (int)info[1]);
5683 }
5684
5685 /* tap driver 9.8 (2.2.0 and 2.2.1 release) is buggy
5686 */
5687 if (tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] == 8)
5688 {
5689 msg(M_FATAL,
5690 "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade your Tap-Win32 driver.",
5691 (int)info[0], (int)info[1]);
5692 }
5693}
5694
5695static void
5697{
5698 ULONG mtu = 0;
5699 DWORD len;
5700 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu, sizeof(mtu), &len,
5701 NULL))
5702 {
5703 msg(D_MTU_INFO, "TAP-Windows MTU=%d", (int)mtu);
5704 }
5705}
5706
5707static void
5708tuntap_set_ip_addr(struct tuntap *tt, const char *device_guid, bool dhcp_masq_post)
5709{
5710 struct gc_arena gc = gc_new();
5711 const DWORD index = tt->adapter_index;
5712
5713 /* flush arp cache */
5715 {
5716 DWORD status = -1;
5717
5718 if (tt->options.msg_channel)
5719 {
5720 ack_message_t ack;
5722 sizeof(flush_neighbors_message_t), 0 },
5723 .family = AF_INET,
5724 .iface = { .index = index, .name = "" } };
5725
5726 if (send_msg_iservice(tt->options.msg_channel, &msg, sizeof(msg), &ack, "TUN"))
5727 {
5728 status = ack.error_number;
5729 }
5730 }
5731 else
5732 {
5733 status = FlushIpNetTable(index);
5734 }
5735
5736 if (status == NO_ERROR)
5737 {
5738 msg(M_INFO, "Successful ARP Flush on interface [%lu] %s", index, device_guid);
5739 }
5740 else if (status != -1)
5741 {
5743 "NOTE: FlushIpNetTable failed on interface [%lu] %s (status=%lu) : %s", index,
5744 device_guid, status, strerror_win32(status, &gc));
5745 }
5746
5747 /*
5748 * If the TAP-Windows driver is masquerading as a DHCP server
5749 * make sure the TCP/IP properties for the adapter are
5750 * set correctly.
5751 */
5752 if (dhcp_masq_post)
5753 {
5754 /* check dhcp enable status */
5755 if (dhcp_status(index) == DHCP_STATUS_DISABLED)
5756 {
5757 msg(M_WARN,
5758 "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Windows TCP/IP properties are set to 'Obtain an IP address automatically'");
5759 }
5760
5761 /* force an explicit DHCP lease renewal on TAP adapter? */
5762 if (tt->options.dhcp_pre_release)
5763 {
5764 dhcp_release(tt);
5765 }
5766 if (tt->options.dhcp_renew)
5767 {
5768 dhcp_renew(tt);
5769 }
5770 }
5771 else
5772 {
5773 fork_dhcp_action(tt);
5774 }
5775 }
5776
5778 {
5779 DWORD status;
5780 const char *error_suffix =
5781 "I am having trouble using the Windows 'IP helper API' to automatically set the IP address -- consider using other --ip-win32 methods (not 'ipapi')";
5782
5783 /* couldn't get adapter index */
5784 if (index == TUN_ADAPTER_INDEX_INVALID)
5785 {
5786 msg(M_FATAL, "ERROR: unable to get adapter index for interface %s -- %s", device_guid,
5787 error_suffix);
5788 }
5789
5790 /* check dhcp enable status */
5791 if (dhcp_status(index) == DHCP_STATUS_DISABLED)
5792 {
5793 msg(M_WARN,
5794 "NOTE: You have selected (explicitly or by default) '--ip-win32 ipapi', which has a better chance of working correctly if the TAP-Windows TCP/IP properties are set to 'Obtain an IP address automatically'");
5795 }
5796
5797 /* delete previously added IP addresses which were not
5798 * correctly deleted */
5799 delete_temp_addresses(index);
5800
5801 /* add a new IP address */
5802 if ((status = AddIPAddress(htonl(tt->local), htonl(tt->adapter_netmask), index,
5803 &tt->ipapi_context, &tt->ipapi_instance))
5804 == NO_ERROR)
5805 {
5806 msg(M_INFO,
5807 "Succeeded in adding a temporary IP/netmask of %s/%s to interface %s using the Win32 IP Helper API",
5809 device_guid);
5810 }
5811 else
5812 {
5813 msg(M_FATAL,
5814 "ERROR: AddIPAddress %s/%s failed on interface %s, index=%lu, status=%lu (windows error: '%s') -- %s",
5816 device_guid, index, status, strerror_win32(status, &gc), error_suffix);
5817 }
5818 tt->ipapi_context_defined = true;
5819 }
5820
5821 gc_free(&gc);
5822}
5823
5824static void
5826{
5827 ULONG status = TRUE;
5828 DWORD len;
5829 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status,
5830 sizeof(status), &len, NULL))
5831 {
5832 msg(M_WARN,
5833 "WARNING: The TAP-Windows driver rejected a TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
5834 }
5835
5836 int s = tt->options.tap_sleep;
5837 if (s > 0)
5838 {
5839 msg(M_INFO, "Sleeping for %d seconds...", s);
5841 }
5842}
5843
5844static void
5845tuntap_set_ptp(const struct tuntap *tt)
5846{
5847 DWORD len;
5848 struct gc_arena gc = gc_new();
5849
5851 {
5852 msg(M_FATAL, "ERROR: --dev tun also requires --ifconfig");
5853 }
5854
5855 /* send 0/0/0 to the TAP driver even if we have no IPv4 configured to
5856 * ensure it is somehow initialized.
5857 */
5858 if (!tt->did_ifconfig_setup || tt->topology == TOP_SUBNET)
5859 {
5860 in_addr_t ep[3];
5861 BOOL status;
5862
5863 ep[0] = htonl(tt->local);
5864 ep[1] = htonl(tt->local & tt->remote_netmask);
5865 ep[2] = htonl(tt->remote_netmask);
5866
5867 status = DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_TUN, ep, sizeof(ep), ep, sizeof(ep),
5868 &len, NULL);
5869
5870 if (tt->did_ifconfig_setup)
5871 {
5873 "Set TAP-Windows TUN subnet mode network/local/netmask = %s/%s/%s [%s]",
5876 print_in_addr_t(ep[2], IA_NET_ORDER, &gc), status ? "SUCCEEDED" : "FAILED");
5877 }
5878 else
5879 {
5880 msg(status ? M_INFO : M_FATAL, "Set TAP-Windows TUN with fake IPv4 [%s]",
5881 status ? "SUCCEEDED" : "FAILED");
5882 }
5883 }
5884 else
5885 {
5886 in_addr_t ep[2];
5887 ep[0] = htonl(tt->local);
5888 ep[1] = htonl(tt->remote_netmask);
5889
5890 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT, ep, sizeof(ep), ep,
5891 sizeof(ep), &len, NULL))
5892 {
5893 msg(M_FATAL,
5894 "ERROR: The TAP-Windows driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun");
5895 }
5896 }
5897
5898 gc_free(&gc);
5899}
5900
5901static void
5902tuntap_dhcp_mask(const struct tuntap *tt, const char *device_guid)
5903{
5904 struct gc_arena gc = gc_new();
5905 DWORD len;
5906 uint32_t ep[4];
5907
5908 /* We will answer DHCP requests with a reply to set IP/subnet to these values */
5909 ep[0] = htonl(tt->local);
5910 ep[1] = htonl(tt->adapter_netmask);
5911
5912 /* At what IP address should the DHCP server masquerade at? */
5913 if (tt->type == DEV_TYPE_TUN)
5914 {
5915 if (tt->topology == TOP_SUBNET)
5916 {
5917 ep[2] = dhcp_masq_addr(
5918 tt->local, tt->remote_netmask,
5920 }
5921 else
5922 {
5923 ep[2] = htonl(tt->remote_netmask);
5924 }
5925 }
5926 else
5927 {
5928 ASSERT(tt->type == DEV_TYPE_TAP);
5929 ep[2] =
5932 }
5933
5934 /* lease time in seconds */
5935 ep[3] = (uint32_t)tt->options.dhcp_lease_time;
5936
5937 ASSERT(ep[3] > 0);
5938
5939#ifndef SIMULATE_DHCP_FAILED /* this code is disabled to simulate bad DHCP negotiation */
5940 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_DHCP_MASQ, ep, sizeof(ep), ep, sizeof(ep),
5941 &len, NULL))
5942 {
5943 msg(M_FATAL,
5944 "ERROR: The TAP-Windows driver rejected a DeviceIoControl call to set TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode");
5945 }
5946
5947 msg(M_INFO,
5948 "Notified TAP-Windows driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]",
5950 device_guid, print_in_addr_t(ep[2], IA_NET_ORDER, &gc), ep[3]);
5951
5952 /* user-supplied DHCP options capability */
5953 if (tt->options.dhcp_options)
5954 {
5955 struct buffer buf = alloc_buf(256);
5956 if (build_dhcp_options_string(&buf, &tt->options))
5957 {
5958 msg(D_DHCP_OPT, "DHCP option string: %s", format_hex(BPTR(&buf), BLEN(&buf), 0, &gc));
5960 BLEN(&buf), BPTR(&buf), BLEN(&buf), &len, NULL))
5961 {
5962 msg(M_FATAL,
5963 "ERROR: The TAP-Windows driver rejected a TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");
5964 }
5965 }
5966 else
5967 {
5968 msg(M_WARN, "DHCP option string not set due to error");
5969 }
5970 free_buf(&buf);
5971 }
5972#endif /* ifndef SIMULATE_DHCP_FAILED */
5973
5974 gc_free(&gc);
5975}
5976
5977static bool
5980{
5981 const char *path = NULL;
5982 char tuntap_device_path[256];
5983
5984 if (tt->backend_driver == DRIVER_DCO)
5985 {
5986 const struct device_instance_id_interface *dev_if;
5987
5988 for (dev_if = device_instance_id_interface; dev_if != NULL; dev_if = dev_if->next)
5989 {
5990 if (strcmp((const char *)dev_if->net_cfg_instance_id, device_guid) != 0)
5991 {
5992 continue;
5993 }
5994
5995 if (tt->backend_driver == DRIVER_DCO)
5996 {
5997 char *last_sep = strrchr(dev_if->device_interface, '\\');
5998 if (!last_sep || strcmp(last_sep + 1, DCO_WIN_REFERENCE_STRING) != 0)
5999 {
6000 continue;
6001 }
6002 }
6003
6004 path = dev_if->device_interface;
6005 break;
6006 }
6007 if (path == NULL)
6008 {
6009 return false;
6010 }
6011 }
6012 else
6013 {
6014 /* Open TAP-Windows */
6015 snprintf(tuntap_device_path, sizeof(tuntap_device_path), "%s%s%s", USERMODEDEVICEDIR,
6016 device_guid, TAP_WIN_SUFFIX);
6017 path = tuntap_device_path;
6018 }
6019
6020 msg(D_TAP_WIN_DEBUG, "Using device interface: %s", path);
6021
6022 tt->hand = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, /* was: FILE_SHARE_READ */
6023 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
6024 if (tt->hand == INVALID_HANDLE_VALUE)
6025 {
6026 msg(D_TUNTAP_INFO | M_ERRNO, "CreateFile failed on %s device: %s",
6028 return false;
6029 }
6030
6031 return true;
6032}
6033
6034void
6035tun_open_device(struct tuntap *tt, const char *dev_node, const char **device_guid,
6036 struct gc_arena *gc)
6037{
6038 const struct tap_reg *tap_reg = get_tap_reg(gc);
6039 const struct panel_reg *panel_reg = get_panel_reg(gc);
6042
6043 uint8_t actual_buffer[256];
6044
6045 /*
6046 * Lookup the device name in the registry, using the --dev-node high level name.
6047 */
6048 if (dev_node)
6049 {
6050 enum tun_driver_type windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
6051
6052 /* Get the device GUID for the device specified with --dev-node. */
6053 *device_guid = get_device_guid(dev_node, actual_buffer, sizeof(actual_buffer),
6054 &windows_driver, tap_reg, panel_reg, gc);
6055
6056 if (!*device_guid)
6057 {
6058 msg(M_FATAL, "Adapter '%s' not found", dev_node);
6059 }
6060
6061 if (tt->backend_driver != windows_driver)
6062 {
6063 msg(M_FATAL,
6064 "Adapter '%s' is using %s driver, %s expected. If you want to use this device, adjust --windows-driver.",
6065 dev_node, print_tun_backend_driver(windows_driver),
6067 }
6068
6069 if (!tun_try_open_device(tt, *device_guid, device_instance_id_interface))
6070 {
6071 msg(M_FATAL, "Failed to open %s adapter: %s",
6073 }
6074 }
6075 else
6076 {
6077 int device_number = 0;
6078 int adapters_created = 0;
6079
6080 /* Try opening all TAP devices until we find one available */
6081 while (true)
6082 {
6083 enum tun_driver_type windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
6084 *device_guid =
6085 get_unspecified_device_guid(device_number, actual_buffer, sizeof(actual_buffer),
6086 tap_reg, panel_reg, &windows_driver, gc);
6087
6088 if (!*device_guid)
6089 {
6090 /* try to create an adapter a few times if we have a service pipe handle */
6091 if ((++adapters_created > 10)
6093 {
6094 msg(M_FATAL, "All %s adapters on this system are currently in use or disabled.",
6096 }
6097 else
6098 {
6099 /* we have created a new adapter so we must reinitialize adapters structs */
6103
6104 device_number = 0;
6105
6106 continue;
6107 }
6108 }
6109
6110 if (tt->backend_driver != windows_driver)
6111 {
6112 goto next;
6113 }
6114
6116 {
6117 break;
6118 }
6119
6120next:
6121 device_number++;
6122 }
6123 }
6124
6125 /* translate high-level device name into a device instance
6126 * GUID using the registry */
6127 tt->actual_name = string_alloc((const char *)actual_buffer, NULL);
6128
6129 tt->adapter_index = get_adapter_index(*device_guid);
6130}
6131
6132static void
6133tuntap_set_ip_props(const struct tuntap *tt, bool *dhcp_masq, bool *dhcp_masq_post)
6134{
6136 {
6137 /*
6138 * If adapter is set to non-DHCP, set to DHCP mode.
6139 */
6141 {
6142 /* try using the service if available, else directly execute netsh */
6143 if (tt->options.msg_channel)
6144 {
6146 }
6147 else
6148 {
6150 }
6151 }
6152 *dhcp_masq = true;
6153 *dhcp_masq_post = true;
6154 }
6156 {
6157 /*
6158 * If adapter is set to non-DHCP, use netsh right away.
6159 */
6161 {
6164 }
6165 else
6166 {
6167 *dhcp_masq = true;
6168 }
6169 }
6170}
6171
6172static void
6173tuntap_post_open(struct tuntap *tt, const char *device_guid)
6174{
6175 bool dhcp_masq = false;
6176 bool dhcp_masq_post = false;
6177
6179 {
6180 /* get driver version info */
6182
6183 /* get driver MTU */
6184 tuntap_get_mtu(tt);
6185
6186 /*
6187 * Preliminaries for setting TAP-Windows adapter TCP/IP
6188 * properties via --ip-win32 dynamic or --ip-win32 adaptive.
6189 */
6190 if (tt->did_ifconfig_setup)
6191 {
6192 tuntap_set_ip_props(tt, &dhcp_masq, &dhcp_masq_post);
6193 }
6194
6195 /* set point-to-point mode if TUN device */
6196 if (tt->type == DEV_TYPE_TUN)
6197 {
6198 tuntap_set_ptp(tt);
6199 }
6200
6201 /* should we tell the TAP-Windows driver to masquerade as a DHCP server as a means
6202 * of setting the adapter address? */
6203 if (dhcp_masq)
6204 {
6205 tuntap_dhcp_mask(tt, device_guid);
6206 }
6207
6208 /* set driver media status to 'connected' */
6210 }
6211
6212 /* possibly use IP Helper API to set IP address on adapter */
6213 tuntap_set_ip_addr(tt, device_guid, dhcp_masq_post);
6214}
6215
6216void
6217open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
6218 openvpn_net_ctx_t *ctx)
6219{
6222 {
6223 msg(M_WARN,
6224 "Some --dhcp-option or --dns options require DHCP server,"
6225 " which is not supported by the selected %s driver. They will be"
6226 " ignored.",
6228 }
6229
6230 /* dco-win already opened the device, which handle we treat as socket */
6231 if (tuntap_is_dco_win(tt))
6232 {
6233 return;
6234 }
6235
6236 const char *device_guid = NULL;
6237
6238 /*netcmd_semaphore_lock ();*/
6239
6240 msg(M_INFO, "open_tun");
6241
6242 if (tt->type != DEV_TYPE_TAP && tt->type != DEV_TYPE_TUN)
6243 {
6244 msg(M_FATAL | M_NOPREFIX, "Unknown virtual device type: '%s'", dev);
6245 }
6246
6247 struct gc_arena gc = gc_new(); /* used also for device_guid allocation */
6248 tun_open_device(tt, dev_node, &device_guid, &gc);
6249
6250 tuntap_post_open(tt, device_guid);
6251
6252 gc_free(&gc);
6253
6254 /*netcmd_semaphore_release ();*/
6255}
6256
6257const char *
6258tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc)
6259{
6261 {
6262 struct buffer out = alloc_buf_gc(256, gc);
6263 DWORD len;
6264 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_INFO, BSTR(&out), BCAP(&out), BSTR(&out),
6265 BCAP(&out), &len, NULL))
6266 {
6267 return BSTR(&out);
6268 }
6269 }
6270 return NULL;
6271}
6272
6273void
6275{
6276 if (tt->backend_driver == WINDOWS_DRIVER_TAP_WINDOWS6)
6277 {
6278 struct buffer out = alloc_buf(1024);
6279 DWORD len;
6280 while (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_LOG_LINE, BSTR(&out), BCAP(&out),
6281 BSTR(&out), BCAP(&out), &len, NULL))
6282 {
6283 msg(D_TAP_WIN_DEBUG, "TAP-Windows: %s", BSTR(&out));
6284 }
6285 free_buf(&out);
6286 }
6287}
6288
6289static void
6290netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc)
6291{
6292 const char *ifconfig_ip_local;
6293 struct argv argv = argv_new();
6294
6295 /* delete ipvX dns servers if any were set */
6296 int len = ipv6 ? tt->options.dns6_len : tt->options.dns_len;
6297 if (len > 0)
6298 {
6299 argv_printf(&argv, "%s%s interface %s delete dns %lu all", get_win_sys_path(),
6300 NETSH_PATH_SUFFIX, ipv6 ? "ipv6" : "ipv4", tt->adapter_index);
6302 }
6303
6304 if (!ipv6 && tt->options.wins_len > 0)
6305 {
6306 argv_printf(&argv, "%s%s interface ipv4 delete winsservers %lu all", get_win_sys_path(),
6309 }
6310
6311 if (ipv6 && tt->type == DEV_TYPE_TUN)
6312 {
6314 }
6315
6316 /* "store=active" is needed in Windows 8(.1) to delete the
6317 * address we added (pointed out by Cedric Tabary).
6318 */
6319
6320 /* netsh interface ipvX delete address %lu %s */
6321 if (ipv6)
6322 {
6323 ifconfig_ip_local = print_in6_addr(tt->local_ipv6, 0, gc);
6324 }
6325 else
6326 {
6327 ifconfig_ip_local = print_in_addr_t(tt->local, 0, gc);
6328 }
6329 argv_printf(&argv, "%s%s interface %s delete address %lu %s store=active", get_win_sys_path(),
6330 NETSH_PATH_SUFFIX, ipv6 ? "ipv6" : "ipv4", tt->adapter_index, ifconfig_ip_local);
6332
6333 argv_free(&argv);
6334}
6335
6336void
6338{
6339 const char *adaptertype = print_tun_backend_driver(tt->backend_driver);
6340
6341 if (tt->hand)
6342 {
6343 dmsg(D_WIN32_IO_LOW, "Attempting CancelIO on %s adapter", adaptertype);
6344 if (!CancelIo(tt->hand))
6345 {
6346 msg(M_WARN | M_ERRNO, "Warning: CancelIO failed on %s adapter", adaptertype);
6347 }
6348 }
6349
6350 dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped read event on %s adapter", adaptertype);
6352
6353 dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped write event on %s adapter", adaptertype);
6355
6356 if (tt->hand)
6357 {
6358 dmsg(D_WIN32_IO_LOW, "Attempting CloseHandle on %s adapter", adaptertype);
6359 if (!CloseHandle(tt->hand))
6360 {
6361 msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on %s adapter", adaptertype);
6362 }
6363 tt->hand = NULL;
6364 }
6365}
6366
6367void
6369{
6370 ASSERT(tt);
6371
6372 struct gc_arena gc = gc_new();
6373
6375 {
6377 {
6378 /* We didn't do ifconfig. */
6379 }
6380 else if (tt->options.msg_channel)
6381 {
6382 /* If IPv4 is not enabled, delete DNS domain here */
6383 if (!tt->did_ifconfig_setup)
6384 {
6385 do_dns_domain_service(false, tt);
6386 }
6387 do_dns_service(false, AF_INET6, tt);
6389 do_address_service(false, AF_INET6, tt);
6390 }
6391 else
6392 {
6393 if (!tt->did_ifconfig_setup)
6394 {
6395 do_dns_domain_pwsh(false, tt);
6396 }
6397
6398 netsh_delete_address_dns(tt, true, &gc);
6399 }
6400 }
6401
6402 if (tt->did_ifconfig_setup)
6403 {
6405 {
6406 /* We didn't do ifconfig. */
6407 }
6410 {
6411 /* We don't have to clean the configuration with DHCP. */
6412 }
6413 else if (tt->options.msg_channel)
6414 {
6415 do_wins_service(false, tt);
6416 do_dns_domain_service(false, tt);
6417 do_dns_service(false, AF_INET, tt);
6418 do_address_service(false, AF_INET, tt);
6419 }
6420 else
6421 {
6422 do_dns_domain_pwsh(false, tt);
6423
6425 {
6426 netsh_delete_address_dns(tt, false, &gc);
6427 }
6428 }
6429 }
6430
6431 if (tt->ipapi_context_defined)
6432 {
6433 DWORD status;
6434 if ((status = DeleteIPAddress(tt->ipapi_context)) != NO_ERROR)
6435 {
6436 msg(M_WARN,
6437 "Warning: DeleteIPAddress[%u] failed on TAP-Windows adapter, status=%u : %s",
6438 (unsigned int)tt->ipapi_context, (unsigned int)status, strerror_win32(status, &gc));
6439 }
6440 }
6441
6442 dhcp_release(tt);
6443
6444 close_tun_handle(tt);
6445
6446 free(tt->actual_name);
6447
6448 clear_tuntap(tt);
6449 free(tt);
6450 gc_free(&gc);
6451}
6452
6453/*
6454 * Convert --ip-win32 constants between index and ascii form.
6455 */
6456
6458{
6459 const char *short_form;
6460};
6461
6462/* Indexed by IPW32_SET_x */
6463static const struct ipset_names ipset_names[] = {
6464 { "manual" }, { "netsh" }, { "ipapi" }, { "dynamic" }, { "adaptive" }
6465};
6466
6467int
6468ascii2ipset(const char *name)
6469{
6470 int i;
6472 for (i = 0; i < IPW32_SET_N; ++i)
6473 {
6474 if (!strcmp(name, ipset_names[i].short_form))
6475 {
6476 return i;
6477 }
6478 }
6479 return -1;
6480}
6481
6482const char *
6483ipset2ascii(int index)
6484{
6486 if (index < 0 || index >= IPW32_SET_N)
6487 {
6488 return "[unknown --ip-win32 type]";
6489 }
6490 else
6491 {
6492 return ipset_names[index].short_form;
6493 }
6494}
6495
6496const char *
6498{
6499 struct buffer out = alloc_buf_gc(256, gc);
6500 int i;
6501
6503 for (i = 0; i < IPW32_SET_N; ++i)
6504 {
6505 if (i)
6506 {
6507 buf_printf(&out, " ");
6508 }
6509 buf_printf(&out, "[%s]", ipset2ascii(i));
6510 }
6511 return BSTR(&out);
6512}
6513
6514#else /* generic */
6515
6516void
6517open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
6518 openvpn_net_ctx_t *ctx)
6519{
6520 open_tun_generic(dev, dev_type, dev_node, tt);
6521}
6522
6523void
6524close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
6525{
6526 ASSERT(tt);
6527
6529 free(tt);
6530}
6531
6532int
6533write_tun(struct tuntap *tt, uint8_t *buf, int len)
6534{
6535 return write(tt->fd, buf, len);
6536}
6537
6538int
6539read_tun(struct tuntap *tt, uint8_t *buf, int len)
6540{
6541 return read(tt->fd, buf, len);
6542}
6543
6544#endif /* if defined (TARGET_ANDROID) */
void argv_msg(const msglvl_t msglevel, const struct argv *a)
Write the arguments stored in a struct argv via the msg() command.
Definition argv.c:242
void argv_free(struct argv *a)
Frees all memory allocations allocated by the struct argv related functions.
Definition argv.c:101
void argv_msg_prefix(const msglvl_t msglevel, const struct argv *a, const char *prefix)
Similar to argv_msg() but prefixes the messages being written with a given string.
Definition argv.c:259
bool argv_printf(struct argv *argres, const char *format,...)
printf() variant which populates a struct argv.
Definition argv.c:438
bool argv_printf_cat(struct argv *argres, const char *format,...)
printf() inspired argv concatenation.
Definition argv.c:462
struct argv argv_new(void)
Allocates a new struct argv and ensures it is initialised.
Definition argv.c:87
void free_buf(struct buffer *buf)
Definition buffer.c:184
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
char * format_hex_ex(const uint8_t *data, size_t size, size_t maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition buffer.c:483
struct buffer alloc_buf(size_t size)
Definition buffer.c:63
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:648
static bool has_digit(const char *src)
Definition buffer.h:372
#define ALLOC_OBJ(dptr, type)
Definition buffer.h:1047
#define BSTR(buf)
Definition buffer.h:128
static struct buffer clear_buf(void)
Return an empty struct buffer.
Definition buffer.h:222
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Definition buffer.h:704
#define BPTR(buf)
Definition buffer.h:123
static void buf_set_write(struct buffer *buf, uint8_t *data, int size)
Definition buffer.h:331
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1089
#define BLEN(buf)
Definition buffer.h:126
static char * format_hex(const uint8_t *data, size_t size, size_t maxoutput, struct gc_arena *gc)
Definition buffer.h:503
#define BCAP(buf)
Definition buffer.h:129
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:361
static void check_malloc_return(void *p)
Definition buffer.h:1095
static void gc_free(struct gc_arena *a)
Definition buffer.h:1025
static struct gc_arena gc_new(void)
Definition buffer.h:1017
static int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
Definition dco.h:298
static void close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition dco.h:304
bool build_dhcp_options_string(struct buffer *buf, const struct tuntap_options *o)
Definition dhcp.c:330
void env_set_destroy(struct env_set *es)
Definition env_set.c:166
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_add(struct env_set *es, const char *str)
Definition env_set.c:193
struct env_set * env_set_create(struct gc_arena *gc)
Definition env_set.c:156
#define D_TAP_WIN_DEBUG
Definition errlevel.h:114
#define D_REGISTRY
Definition errlevel.h:177
#define D_IFCONFIG
Definition errlevel.h:92
#define D_ROUTE_DEBUG
Definition errlevel.h:132
#define D_WIN32_IO_LOW
Definition errlevel.h:124
#define D_WIN32_IO
Definition errlevel.h:172
#define D_TUNTAP_INFO
Definition errlevel.h:80
#define D_MTU_INFO
Definition errlevel.h:104
#define D_READ_WRITE
Definition errlevel.h:166
#define D_OSBUF
Definition errlevel.h:90
#define D_LOW
Definition errlevel.h:96
#define M_INFO
Definition errlevel.h:54
#define D_DHCP_OPT
Definition errlevel.h:97
#define EVENT_WRITE
Definition event.h:38
#define EVENT_READ
Definition event.h:37
void set_nonblock(socket_descriptor_t fd)
Definition fdmisc.c:68
void set_cloexec(socket_descriptor_t fd)
Definition fdmisc.c:78
static SERVICE_STATUS status
Definition interactive.c:51
@ write
@ read
void management_set_state(struct management *man, const int state, const char *detail, const in_addr_t *tun_local_ip, const struct in6_addr *tun_local_ip6, const struct openvpn_sockaddr *local, const struct openvpn_sockaddr *remote)
Definition manage.c:2789
void management_sleep(const int n)
A sleep function that services the management layer for n seconds rather than doing nothing.
Definition manage.c:4140
#define OPENVPN_STATE_ASSIGN_IP
Definition manage.h:450
static void net_ctx_reset(openvpn_net_ctx_t *ctx)
Definition networking.h:56
static void net_ctx_free(openvpn_net_ctx_t *ctx)
Definition networking.h:62
void * openvpn_net_ctx_t
Definition networking.h:38
@ msg_del_address
Definition openvpn-msg.h:33
@ msg_add_wins_cfg
Definition openvpn-msg.h:49
@ msg_add_address
Definition openvpn-msg.h:32
@ msg_enable_dhcp
Definition openvpn-msg.h:46
@ msg_create_adapter
Definition openvpn-msg.h:51
@ msg_del_wins_cfg
Definition openvpn-msg.h:50
@ msg_add_dns_cfg
Definition openvpn-msg.h:36
@ msg_register_dns
Definition openvpn-msg.h:45
@ msg_set_mtu
Definition openvpn-msg.h:48
@ msg_flush_neighbors
Definition openvpn-msg.h:42
@ msg_del_dns_cfg
Definition openvpn-msg.h:37
adapter_type_t
@ ADAPTER_TYPE_DCO
@ ADAPTER_TYPE_TAP
#define BOOL_CAST(x)
Definition basic.h:26
#define CLEAR(x)
Definition basic.h:32
#define SIZE(x)
Definition basic.h:29
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition error.c:768
#define M_NOPREFIX
Definition error.h:98
#define M_FATAL
Definition error.h:90
#define M_NONFATAL
Definition error.h:91
#define dmsg(flags,...)
Definition error.h:172
#define M_ERR
Definition error.h:106
#define msg(flags,...)
Definition error.h:152
unsigned int msglvl_t
Definition error.h:77
#define ASSERT(x)
Definition error.h:219
#define M_WARN
Definition error.h:92
#define M_ERRNO
Definition error.h:95
const char * print_topology(const int topology)
Definition options.c:4781
const char * time_string(time_t t, tv_usec_t usec, bool show_usec, struct gc_arena *gc)
Definition otime.c:104
bool platform_user_get(const char *username, struct platform_state_user *state)
Definition platform.c:80
bool platform_group_get(const char *groupname, struct platform_state_group *state)
Definition platform.c:124
#define DEV_TYPE_TAP
Definition proto.h:36
#define DEV_TYPE_UNDEF
Definition proto.h:34
#define DEV_TYPE_TUN
Definition proto.h:35
#define OPENVPN_IPH_GET_VER(v)
Definition proto.h:91
#define TOP_SUBNET
Definition proto.h:43
int netmask_to_netbits2(in_addr_t netmask)
Definition route.c:3909
bool add_route(struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es, openvpn_net_ctx_t *ctx)
Definition route.c:1480
bool add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx)
Definition route.c:1794
void get_default_gateway(struct route_gateway_info *rgi, in_addr_t dest, openvpn_net_ctx_t *ctx)
Retrieves the best gateway for a given destination based on the routing table.
Definition route.c:2570
void delete_route_ipv6(const struct route_ipv6 *r6, const struct tuntap *tt, const struct env_set *es, openvpn_net_ctx_t *ctx)
Definition route.c:2202
void route_ipv6_clear_host_bits(struct route_ipv6 *r6)
Definition route.c:1769
#define RGI_ADDR_DEFINED
Definition route.h:159
#define RT_ADDED
Definition route.h:121
#define RT_METRIC_DEFINED
Definition route.h:122
#define RT_DEFINED
Definition route.h:120
#define RGI_NETMASK_DEFINED
Definition route.h:160
int openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message)
#define S_FATAL
Definition run_command.h:50
int sockethandle_finalize(sockethandle_t sh, struct overlapped_io *io, struct buffer *buf, struct link_socket_actual *from)
Definition socket.c:2871
in_addr_t getaddr(unsigned int flags, const char *hostname, int resolve_retry_seconds, bool *succeeded, struct signal_info *sig_info)
Translate an IPv4 addr or hostname from string form to in_addr_t.
Definition socket.c:199
const char * print_in6_addr(struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
const char * print_in_addr_t(in_addr_t addr, unsigned int flags, struct gc_arena *gc)
#define GETADDR_FATAL
#define GETADDR_HOST_ORDER
#define GETADDR_FATAL_ON_SIGNAL
#define GETADDR_RESOLVE
#define IA_NET_ORDER
Definition socket_util.h:90
inet_address_t address
Definition openvpn-msg.h:83
message_header_t header
Definition openvpn-msg.h:81
interface_t iface
Definition openvpn-msg.h:85
Definition argv.h:35
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
int offset
Offset in bytes of the actual content within the allocated memory.
Definition buffer.h:63
Contains all state information for one tunnel.
Definition openvpn.h:474
message_header_t header
const char * device_interface
Definition tun.h:419
struct device_instance_id_interface * next
Definition tun.h:420
Definition dhcp.h:62
message_header_t header
inet_address_t addr[4]
interface_t iface
message_header_t header
Packet geometry parameters.
Definition mtu.h:103
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
struct gc_entry * list
First element of the linked list of gc_entry structures.
Definition buffer.h:117
char name[256]
Definition openvpn-msg.h:70
const char * short_form
Definition tun.c:6459
struct man_connection connection
Definition manage.h:335
uint8_t version_len
Definition proto.h:93
struct buffer buf
Definition win32.h:221
DWORD size
Definition win32.h:210
OVERLAPPED overlapped
Definition win32.h:209
struct buffer buf_init
Definition win32.h:220
int iostate
Definition win32.h:208
struct panel_reg * next
Definition tun.h:413
const char * name
Definition tun.h:411
const char * guid
Definition tun.h:412
in_addr_t netmask
Definition route.h:154
unsigned int flags
Definition route.h:165
struct route_gateway_address gateway
Definition route.h:180
int metric
Definition route.h:130
in_addr_t network
Definition route.h:126
in_addr_t netmask
Definition route.h:127
in_addr_t gateway
Definition route.h:128
unsigned int flags
Definition route.h:124
HANDLE write
Definition win32.h:82
HANDLE read
Definition win32.h:81
SECURITY_ATTRIBUTES sa
Definition win32.h:64
message_header_t header
interface_t iface
bool is_handle
Definition socket.h:262
Definition tun.h:403
struct tap_reg * next
Definition tun.h:406
enum tun_driver_type windows_driver
Definition tun.h:405
const char * guid
Definition tun.h:404
int wins_len
Definition tun.h:118
struct in6_addr dns6[N_DHCP_ADDR]
Definition tun.h:142
int dns_len
Definition tun.h:114
int dns6_len
Definition tun.h:143
in_addr_t wins[N_DHCP_ADDR]
Definition tun.h:117
int tap_sleep
Definition tun.h:97
int dhcp_lease_time
Definition tun.h:94
in_addr_t dns[N_DHCP_ADDR]
Definition tun.h:113
bool dhcp_masq_custom_offset
Definition tun.h:92
const char * domain
Definition tun.h:103
bool dhcp_renew
Definition tun.h:137
const char * domain_search_list[N_SEARCH_LIST_LEN]
Definition tun.h:131
HANDLE msg_channel
Definition tun.h:88
int dhcp_masq_offset
Definition tun.h:93
int ip_win32_type
Definition tun.h:85
bool dhcp_pre_release
Definition tun.h:138
bool register_dns
Definition tun.h:140
int dhcp_options
Definition tun.h:101
Definition tun.h:183
in_addr_t local
Definition tun.h:210
int type
Definition tun.h:185
ULONG ipapi_instance
Definition tun.h:229
int netbits_ipv6
Definition tun.h:215
DWORD adapter_index
Definition tun.h:234
struct rw_handle rw_handle
Definition tun.h:223
enum tun_driver_type backend_driver
The backend driver that used for this tun/tap device.
Definition tun.h:193
bool did_ifconfig_ipv6_setup
if the internal variables related to ifconfig-ipv6 of this struct have been set up.
Definition tun.h:201
struct tuntap_options options
Definition tun.h:205
struct in6_addr remote_ipv6
Definition tun.h:214
bool did_ifconfig_setup
if the internal variables related to ifconfig of this struct have been set up.
Definition tun.h:197
int topology
Definition tun.h:188
struct overlapped_io writes
Definition tun.h:222
in_addr_t adapter_netmask
Definition tun.h:230
HANDLE hand
Definition tun.h:218
struct overlapped_io reads
Definition tun.h:221
struct in6_addr local_ipv6
Definition tun.h:213
ULONG ipapi_context
Definition tun.h:228
dco_context_t dco
Definition tun.h:249
char * actual_name
Definition tun.h:207
in_addr_t remote_netmask
Definition tun.h:211
bool ipapi_context_defined
Definition tun.h:227
bool persistent_if
Definition tun.h:203
interface_t iface
inet_address_t addr[4]
message_header_t header
#define sleep(x)
Definition syshead.h:42
uint32_t in_addr_t
Definition syshead.h:52
struct env_set * es
char * r6[]
struct gc_arena gc
Definition test_ssl.c:131
static const char * get_unspecified_device_guid(const int device_number, uint8_t *actual_name, int actual_name_size, const struct tap_reg *tap_reg_src, const struct panel_reg *panel_reg_src, enum tun_driver_type *windows_driver, struct gc_arena *gc)
Definition tun.c:4182
void ipconfig_register_dns(const struct env_set *es)
Definition tun.c:5107
void tun_show_debug(struct tuntap *tt)
Definition tun.c:6274
static const struct tap_reg * get_tap_reg(struct gc_arena *gc)
Definition tun.c:3758
static DWORD get_adapter_index_method_1(const char *guid)
Definition tun.c:4757
static void tuntap_post_open(struct tuntap *tt, const char *device_guid)
Definition tun.c:6173
static bool do_address_service(const bool add, const short family, const struct tuntap *tt)
Definition tun.c:116
static void clear_tuntap(struct tuntap *tuntap)
Definition tun.c:1675
static const char * netsh_get_id(const char *dev_node, struct gc_arena *gc)
Definition tun.c:5479
void open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition tun.c:6217
int dev_type_enum(const char *dev, const char *dev_type)
Definition tun.c:521
static const struct panel_reg * get_panel_reg(struct gc_arena *gc)
Definition tun.c:3869
void close_tun_handle(struct tuntap *tt)
Definition tun.c:6337
void fork_register_dns_action(struct tuntap *tt)
Definition tun.c:5605
static bool test_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
Definition tun.c:4505
static void do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es, openvpn_net_ctx_t *ctx)
do_ifconfig_ipv6 - perform platform specific ifconfig6 commands
Definition tun.c:1048
static void netsh_enable_dhcp(DWORD adapter_index)
Definition tun.c:5389
static const GUID GUID_DEVINTERFACE_NET
Definition tun.c:91
static bool do_create_adapter_service(HANDLE msg_channel, enum tun_driver_type driver_type)
Requests the interactive service to create a VPN adapter of the specified type.
Definition tun.c:437
#define NI_TEST_FIRST
Definition tun.c:97
void show_tap_win_adapters(msglvl_t msglevel, msglvl_t warnlevel)
Definition tun.c:4033
bool dhcp_renew_by_adapter_index(const DWORD adapter_index)
Definition tun.c:5040
static void tuntap_get_version_info(const struct tuntap *tt)
Definition tun.c:5655
static bool service_enable_dhcp(const struct tuntap *tt)
Definition tun.c:5404
static void netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc)
Definition tun.c:6290
static void exec_command(const char *prefix, const struct argv *a, int n, msglvl_t msglevel)
Definition tun.c:5080
int ascii2ipset(const char *name)
Definition tun.c:6468
const IP_ADAPTER_INFO * get_tun_adapter(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
Definition tun.c:4521
static void check_addr_clash(const char *name, int type, in_addr_t public, in_addr_t local, in_addr_t remote_netmask)
Definition tun.c:616
bool is_adapter_up(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
Definition tun.c:4534
static void tuntap_set_ptp(const struct tuntap *tt)
Definition tun.c:5845
static void undo_ifconfig_ipv4(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition tun.c:1595
static bool tun_try_open_device(struct tuntap *tt, const char *device_guid, const struct device_instance_id_interface *device_instance_id_interface)
Definition tun.c:5978
static DWORD get_adapter_index(const char *guid)
Definition tun.c:4797
static void netsh_ifconfig(const struct tuntap_options *to, DWORD adapter_index, const in_addr_t ip, const in_addr_t netmask, const unsigned int flags)
Definition tun.c:5333
const IP_ADAPTER_INFO * get_adapter_info(DWORD index, struct gc_arena *gc)
Definition tun.c:4436
static bool dhcp_release(const struct tuntap *tt)
Definition tun.c:5026
struct tuntap * init_tun(const char *dev, const char *dev_type, int topology, const char *ifconfig_local_parm, const char *ifconfig_remote_netmask_parm, const char *ifconfig_ipv6_local_parm, int ifconfig_ipv6_netbits_parm, const char *ifconfig_ipv6_remote_parm, struct addrinfo *local_public, struct addrinfo *remote_public, const bool strict_warn, struct env_set *es, openvpn_net_ctx_t *ctx, struct tuntap *tt)
Definition tun.c:830
static void fork_dhcp_action(struct tuntap *tt)
Definition tun.c:5550
static void show_adapter(msglvl_t msglevel, const IP_ADAPTER_INFO *a, struct gc_arena *gc)
Definition tun.c:4837
const char * tun_stat(const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
Definition tun.c:731
static bool get_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask)
Definition tun.c:4463
const IP_PER_ADAPTER_INFO * get_per_adapter_info(const DWORD index, struct gc_arena *gc)
Definition tun.c:4334
static void ifconfig_sanity_check(bool tun_p2p, in_addr_t addr)
Definition tun.c:586
int tun_write_win32(struct tuntap *tt, struct buffer *buf)
Definition tun.c:3606
#define DHCP_STATUS_DISABLED
Definition tun.c:4687
static const char * get_device_guid(const char *name, uint8_t *actual_name, int actual_name_size, enum tun_driver_type *windows_driver, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg, struct gc_arena *gc)
Definition tun.c:4245
bool is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
Definition tun.c:4578
static void delete_temp_addresses(DWORD index)
Definition tun.c:4719
static void tuntap_set_ip_addr(struct tuntap *tt, const char *device_guid, bool dhcp_masq_post)
Definition tun.c:5708
const char * tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc)
Definition tun.c:6258
static const struct tap_reg * get_adapter_by_name(const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg)
Definition tun.c:4150
static const IP_ADAPTER_INDEX_MAP * get_interface_info(DWORD index, struct gc_arena *gc)
Definition tun.c:4393
static const IP_INTERFACE_INFO * get_interface_info_list(struct gc_arena *gc)
Definition tun.c:4365
#define NI_OPTIONS
Definition tun.c:99
bool is_dev_type(const char *dev, const char *dev_type, const char *match_type)
Definition tun.c:503
static uint32_t dhcp_masq_addr(const in_addr_t local, const in_addr_t netmask, const int offset)
Definition tun.c:5624
#define DHCP_STATUS_UNDEF
Definition tun.c:4685
#define DHCP_STATUS_ENABLED
Definition tun.c:4686
static void netsh_ifconfig_options(const char *type, const in_addr_t *addr_list, const int addr_len, const IP_ADDR_STRING *current, DWORD adapter_index, const bool test_first)
Definition tun.c:5249
static void tuntap_set_ip_props(const struct tuntap *tt, bool *dhcp_masq, bool *dhcp_masq_post)
Definition tun.c:6133
static void register_dns_service(const struct tuntap *tt)
Definition tun.c:5576
static void do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es, openvpn_net_ctx_t *ctx)
do_ifconfig_ipv4 - perform platform specific ifconfig commands
Definition tun.c:1239
int tun_write_queue(struct tuntap *tt, struct buffer *buf)
Definition tun.c:3551
bool dhcp_release_by_adapter_index(const DWORD adapter_index)
Definition tun.c:4999
void delete_route_connected_v6_net(const struct tuntap *tt)
Definition tun.c:995
bool tun_standby(struct tuntap *tt)
Definition tun.c:5529
static void tuntap_dhcp_mask(const struct tuntap *tt, const char *device_guid)
Definition tun.c:5902
static void init_ip_addr_string2(IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
Definition tun.c:5315
void do_ifconfig(struct tuntap *tt, const char *ifname, int tun_mtu, const struct env_set *es, openvpn_net_ctx_t *ctx)
do_ifconfig - configure the tunnel interface
Definition tun.c:1566
const char * dev_type_string(const char *dev, const char *dev_type)
Definition tun.c:540
static const char ifconfig_warn_how_to_silence[]
Definition tun.c:576
static const struct device_instance_id_interface * get_device_instance_id_interface(struct gc_arena *gc)
Definition tun.c:3632
void close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition tun.c:6368
static const char * guid_to_name(const char *guid, const struct panel_reg *panel_reg)
Definition tun.c:4134
static DWORD get_adapter_index_method_2(const char *guid)
Definition tun.c:4775
static int dhcp_status(DWORD index)
Definition tun.c:4690
const IP_ADAPTER_INFO * get_adapter_info_list(struct gc_arena *gc)
Definition tun.c:4309
void tap_allow_nonadmin_access(const char *dev_node)
Definition tun.c:4919
bool tun_name_is_fixed(const char *dev)
Definition tun.c:1790
static bool ip_addr_member_of(const in_addr_t addr, const IP_ADDR_STRING *ias)
Definition tun.c:5197
static const char * format_ip_addr_string(const IP_ADDR_STRING *ip, struct gc_arena *gc)
Definition tun.c:4816
const IP_ADAPTER_INFO * get_adapter(const IP_ADAPTER_INFO *ai, DWORD index)
Definition tun.c:4417
static void at_least_one_tap_win(const struct tap_reg *tap_reg)
Definition tun.c:4167
void show_adapters(msglvl_t msglevel)
Definition tun.c:4870
static void add_route_connected_v6_net(struct tuntap *tt, const struct env_set *es)
Definition tun.c:981
void warn_on_use_of_common_subnets(openvpn_net_ctx_t *ctx)
Definition tun.c:670
static bool dhcp_renew(const struct tuntap *tt)
Definition tun.c:5066
static void undo_ifconfig_ipv6(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition tun.c:1630
int tun_read_queue(struct tuntap *tt, int maxsize)
Definition tun.c:3495
static void do_dns_domain_pwsh(bool add, const struct tuntap *tt)
Definition tun.c:409
void init_tun_post(struct tuntap *tt, const struct frame *frame, const struct tuntap_options *options)
Definition tun.c:954
static void tuntap_set_connected(const struct tuntap *tt)
Definition tun.c:5825
static const struct tap_reg * get_adapter_by_guid(const char *guid, const struct tap_reg *tap_reg)
Definition tun.c:4118
static void do_dns_domain_service(bool add, const struct tuntap *tt)
Definition tun.c:170
static void tuntap_get_mtu(struct tuntap *tt)
Definition tun.c:5696
const char * ifconfig_options_string(const struct tuntap *tt, bool remote, bool disable, struct gc_arena *gc)
Definition tun.c:694
const char * guess_tuntap_dev(const char *dev, const char *dev_type, const char *dev_node, struct gc_arena *gc)
Definition tun.c:560
const char * ipset2ascii(int index)
Definition tun.c:6483
void do_ifconfig_setenv(const struct tuntap *tt, struct env_set *es)
Definition tun.c:786
static bool do_set_mtu_service(const struct tuntap *tt, const short family, const int mtu)
Definition tun.c:367
void undo_ifconfig(struct tuntap *tt, openvpn_net_ctx_t *ctx)
undo_ifconfig - undo configuration of the tunnel interface
Definition tun.c:1655
bool is_tun_p2p(const struct tuntap *tt)
Definition tun.c:762
static void windows_set_mtu(const int iface_index, const short family, const int mtu)
Definition tun.c:5436
const char * ipset2ascii_all(struct gc_arena *gc)
Definition tun.c:6497
static int get_adapter_n_ip_netmask(const IP_ADAPTER_INFO *ai)
Definition tun.c:4442
void tun_standby_init(struct tuntap *tt)
Definition tun.c:5523
#define NI_IP_NETMASK
Definition tun.c:98
void show_valid_win32_tun_subnets(void)
Definition tun.c:4000
static void tap_allow_nonadmin_access_handle(const char *device_path, HANDLE hand)
Definition tun.c:4897
void ip_addr_string_to_array(in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
Definition tun.c:5129
static void netsh_set_dns6_servers(const struct in6_addr *addr_list, const int addr_len, DWORD adapter_index)
Set the ipv6 dns servers on the specified interface.
Definition tun.c:5220
static const GUID GUID_DEVCLASS_NET
Definition tun.c:88
const char * print_tun_backend_driver(enum tun_driver_type driver)
Return a string representation of the tun backed driver type.
Definition tun.c:59
static void do_wins_service(bool add, const struct tuntap *tt)
Definition tun.c:310
static void netsh_command(const struct argv *a, int n, msglvl_t msglevel)
Definition tun.c:5101
DWORD adapter_index_of_ip(const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count, in_addr_t *netmask)
Definition tun.c:4612
static void do_dns_service(bool add, const short family, const struct tuntap *tt)
Definition tun.c:240
void tun_open_device(struct tuntap *tt, const char *dev_node, const char **device_guid, struct gc_arena *gc)
Definition tun.c:6035
void verify_255_255_255_252(in_addr_t local, in_addr_t remote)
Definition tun.c:3964
static bool ip_addr_one_to_one(const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
Definition tun.c:5173
#define IPW32_SET_NETSH
Definition tun.h:80
#define IPW32_SET_ADAPTIVE
Definition tun.h:83
#define DHCP_OPTIONS_DHCP_REQUIRED
Definition tun.h:72
#define N_SEARCH_LIST_LEN
Definition tun.h:128
#define IPW32_SET_IPAPI
Definition tun.h:81
#define TUN_ADAPTER_INDEX_INVALID
Definition tun.h:64
#define IPW32_SET_DHCP_MASQ
Definition tun.h:82
static bool tuntap_is_dco_win(struct tuntap *tt)
Definition tun.h:534
#define DCO_WIN_REFERENCE_STRING
Definition tun.h:59
#define IPW32_SET_ADAPTIVE_TRY_NETSH
Definition tun.h:68
#define IPW32_SET_N
Definition tun.h:84
#define IPW32_SET_MANUAL
Definition tun.h:79
tun_driver_type
Definition tun.h:44
@ DRIVER_NULL
Definition tun.h:52
@ WINDOWS_DRIVER_UNSPECIFIED
Definition tun.h:45
@ DRIVER_UTUN
macOS internal tun driver
Definition tun.h:55
@ DRIVER_GENERIC_TUNTAP
Definition tun.h:47
@ DRIVER_AFUNIX
using an AF_UNIX socket to pass packets from/to an external program.
Definition tun.h:51
@ WINDOWS_DRIVER_TAP_WINDOWS6
Definition tun.h:46
@ DRIVER_DCO
Definition tun.h:53
int read_tun(struct tuntap *tt, uint8_t *buf, int len)
int write_tun(struct tuntap *tt, uint8_t *buf, int len)
struct in6_addr ipv6
Definition openvpn-msg.h:64
struct in_addr ipv4
Definition openvpn-msg.h:63
int get_interface_metric(const NET_IFINDEX index, const ADDRESS_FAMILY family, int *is_auto)
Return interface metric value for the specified interface index.
Definition wfp_block.c:369
void overlapped_io_init(struct overlapped_io *o, const struct frame *frame, BOOL event_state)
Definition win32.c:169
void fork_to_self(const char *cmdline)
Definition win32.c:1068
char * overlapped_io_state_ascii(const struct overlapped_io *o)
Definition win32.c:198
void overlapped_io_close(struct overlapped_io *o)
Definition win32.c:185
void netcmd_semaphore_release(void)
Definition win32.c:867
char * get_win_sys_path(void)
Definition win32.c:1109
void netcmd_semaphore_lock(void)
Definition win32.c:851
bool send_msg_iservice(HANDLE pipe, const void *data, DWORD size, ack_message_t *ack, const char *context)
Send the size bytes in buffer data to the interactive service pipe and read the result in ack.
Definition win32.c:1423
bool init_security_attributes_allow_all(struct security_attributes *obj)
Definition win32.c:150
#define IOSTATE_IMMEDIATE_RETURN
Definition win32.h:207
#define POWERSHELL_PATH_SUFFIX
Definition win32.h:43
#define WIN_IPCONFIG_PATH_SUFFIX
Definition win32.h:41
static bool overlapped_io_active(struct overlapped_io *o)
Definition win32.h:229
#define IOSTATE_INITIAL
Definition win32.h:205
#define IOSTATE_QUEUED
Definition win32.h:206
#define NETSH_PATH_SUFFIX
Definition win32.h:39