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
586ifconfig_sanity_check(bool tun_p2p, in_addr_t addr)
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
1022in_addr_t
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#ifndef HAVE_LINUX_SOCKIOS_H
2059#error header file linux/sockios.h required
2060#endif
2061
2062#if !PEDANTIC
2063
2064void
2065open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2066 openvpn_net_ctx_t *ctx)
2067{
2068 struct ifreq ifr;
2069
2070 if (tun_dco_enabled(tt))
2071 {
2072 open_tun_dco_generic(dev, dev_type, tt, ctx);
2073 }
2074 else
2075 {
2076 /*
2077 * Process --dev-node
2078 */
2079 const char *node = dev_node;
2080 if (!node)
2081 {
2082 node = "/dev/net/tun";
2083 }
2084
2085 /*
2086 * Open the interface
2087 */
2088 if ((tt->fd = open(node, O_RDWR)) < 0)
2089 {
2090 msg(M_ERR, "ERROR: Cannot open TUN/TAP dev %s", node);
2091 }
2092
2093 /*
2094 * Process --tun-ipv6
2095 */
2096 CLEAR(ifr);
2097 ifr.ifr_flags = IFF_NO_PI;
2098
2099#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
2100 ifr.ifr_flags |= IFF_ONE_QUEUE;
2101#endif
2102
2103 /*
2104 * Figure out if tun or tap device
2105 */
2106 if (tt->type == DEV_TYPE_TUN)
2107 {
2108 ifr.ifr_flags |= IFF_TUN;
2109 }
2110 else if (tt->type == DEV_TYPE_TAP)
2111 {
2112 ifr.ifr_flags |= IFF_TAP;
2113 }
2114 else
2115 {
2116 msg(M_FATAL, "I don't recognize device %s as a tun or tap device", dev);
2117 }
2118
2119 /*
2120 * Set an explicit name, if --dev is not tun or tap
2121 */
2122 if (strcmp(dev, "tun") && strcmp(dev, "tap"))
2123 {
2124 strncpynt(ifr.ifr_name, dev, IFNAMSIZ);
2125 }
2126
2127 /*
2128 * Use special ioctl that configures tun/tap device with the parms
2129 * we set in ifr
2130 */
2131 if (ioctl(tt->fd, TUNSETIFF, (void *)&ifr) < 0)
2132 {
2133 msg(M_ERR, "ERROR: Cannot ioctl TUNSETIFF %s", dev);
2134 }
2135
2136 msg(M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
2137
2138 /*
2139 * Try making the TX send queue bigger
2140 */
2141#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
2142 if (tt->options.txqueuelen)
2143 {
2144 struct ifreq netifr;
2145 int ctl_fd;
2146
2147 if ((ctl_fd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0)
2148 {
2149 CLEAR(netifr);
2150 strncpynt(netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
2151 netifr.ifr_qlen = tt->options.txqueuelen;
2152 if (ioctl(ctl_fd, SIOCSIFTXQLEN, (void *)&netifr) >= 0)
2153 {
2154 msg(D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen);
2155 }
2156 else
2157 {
2158 msg(M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name);
2159 }
2160 close(ctl_fd);
2161 }
2162 else
2163 {
2164 msg(M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name);
2165 }
2166 }
2167#endif /* if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) */
2168
2169 set_nonblock(tt->fd);
2170 set_cloexec(tt->fd);
2171 tt->actual_name = string_alloc(ifr.ifr_name, NULL);
2172 }
2173 return;
2174}
2175
2176#else /* if !PEDANTIC */
2177
2178void
2179open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2180 openvpn_net_ctx_t *ctx)
2181{
2182 ASSERT(0);
2183}
2184
2185#endif /* !PEDANTIC */
2186
2187#ifdef ENABLE_FEATURE_TUN_PERSIST
2188
2189/* TUNSETGROUP appeared in 2.6.23 */
2190#ifndef TUNSETGROUP
2191#define TUNSETGROUP _IOW('T', 206, int)
2192#endif
2193
2194void
2195tuncfg(const char *dev, const char *dev_type, const char *dev_node, int persist_mode,
2196 const char *username, const char *groupname, const struct tuntap_options *options,
2197 openvpn_net_ctx_t *ctx)
2198{
2199 struct tuntap *tt;
2200
2201 ALLOC_OBJ(tt, struct tuntap);
2202 clear_tuntap(tt);
2203 tt->type = dev_type_enum(dev, dev_type);
2204 tt->options = *options;
2205
2206 open_tun(dev, dev_type, dev_node, tt, ctx);
2207 if (ioctl(tt->fd, TUNSETPERSIST, persist_mode) < 0)
2208 {
2209 msg(M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
2210 }
2211 if (username != NULL)
2212 {
2214
2215 if (!platform_user_get(username, &platform_state_user))
2216 {
2217 msg(M_ERR, "Cannot get user entry for %s", username);
2218 }
2219 else if (ioctl(tt->fd, TUNSETOWNER, platform_state_user.uid) < 0)
2220 {
2221 msg(M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
2222 }
2223 }
2224 if (groupname != NULL)
2225 {
2227
2228 if (!platform_group_get(groupname, &platform_state_group))
2229 {
2230 msg(M_ERR, "Cannot get group entry for %s", groupname);
2231 }
2232 else if (ioctl(tt->fd, TUNSETGROUP, platform_state_group.gid) < 0)
2233 {
2234 msg(M_ERR, "Cannot ioctl TUNSETGROUP(%s) %s", groupname, dev);
2235 }
2236 }
2237 close_tun(tt, ctx);
2238 msg(M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
2239}
2240
2241#endif /* ENABLE_FEATURE_TUN_PERSIST */
2242
2243void
2244close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2245{
2246 ASSERT(tt);
2247
2248#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
2249 if (tun_dco_enabled(tt))
2250 {
2251 close_tun_dco(tt, ctx);
2252 }
2253#endif
2254 close_tun_generic(tt);
2255 free(tt);
2256}
2257
2258#if defined(__GNUC__) || defined(__clang__)
2259#pragma GCC diagnostic push
2260#pragma GCC diagnostic ignored "-Wconversion"
2261#endif
2262
2263int
2264write_tun(struct tuntap *tt, uint8_t *buf, int len)
2265{
2266 return write(tt->fd, buf, len);
2267}
2268
2269int
2270read_tun(struct tuntap *tt, uint8_t *buf, int len)
2271{
2272 return read(tt->fd, buf, len);
2273}
2274
2275#if defined(__GNUC__) || defined(__clang__)
2276#pragma GCC diagnostic pop
2277#endif
2278
2279#elif defined(TARGET_SOLARIS)
2280
2281#ifndef TUNNEWPPA
2282#error I need the symbol TUNNEWPPA from net/if_tun.h
2283#endif
2284
2285void
2286open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2287 openvpn_net_ctx_t *ctx)
2288{
2289 int if_fd = -1, ip_muxid = -1, arp_muxid = -1, arp_fd = -1, ppa = -1;
2290 struct lifreq ifr;
2291 const char *ptr;
2292 const char *ip_node = NULL, *arp_node = NULL;
2293 const char *dev_tuntap_type;
2294 int link_type;
2295 struct strioctl strioc_if, strioc_ppa;
2296
2297 /* improved generic TUN/TAP driver from
2298 * https://web.archive.org/web/20250504214754/http://www.whiteboard.ne.jp/~admin2/tuntap/
2299 * has IPv6 support
2300 */
2301 CLEAR(ifr);
2302
2303 if (tt->type == DEV_TYPE_TUN)
2304 {
2305 ip_node = "/dev/udp";
2306 if (!dev_node)
2307 {
2308 dev_node = "/dev/tun";
2309 }
2310 dev_tuntap_type = "tun";
2311 link_type = I_PLINK;
2312 }
2313 else if (tt->type == DEV_TYPE_TAP)
2314 {
2315 ip_node = "/dev/udp";
2316 if (!dev_node)
2317 {
2318 dev_node = "/dev/tap";
2319 }
2320 arp_node = dev_node;
2321 dev_tuntap_type = "tap";
2322 link_type = I_PLINK; /* was: I_LINK */
2323 }
2324 else
2325 {
2326 msg(M_FATAL, "I don't recognize device %s as a tun or tap device", dev);
2327 }
2328
2329 if ((tt->ip_fd = open(ip_node, O_RDWR, 0)) < 0)
2330 {
2331 msg(M_ERR, "Can't open %s", ip_node);
2332 }
2333
2334 if ((tt->fd = open(dev_node, O_RDWR, 0)) < 0)
2335 {
2336 msg(M_ERR, "Can't open %s", dev_node);
2337 }
2338
2339 ptr = dev;
2340
2341 /* get unit number */
2342 if (*ptr)
2343 {
2344 while (*ptr && !isdigit((int)*ptr))
2345 {
2346 ptr++;
2347 }
2348 ppa = atoi(ptr);
2349 }
2350
2351 /* Assign a new PPA and get its unit number. */
2352 strioc_ppa.ic_cmd = TUNNEWPPA;
2353 strioc_ppa.ic_timout = 0;
2354 strioc_ppa.ic_len = sizeof(ppa);
2355 strioc_ppa.ic_dp = (char *)&ppa;
2356
2357 if (*ptr == '\0') /* no number given, try dynamic */
2358 {
2359 bool found_one = false;
2360 while (!found_one && ppa < 64)
2361 {
2362 int new_ppa = ioctl(tt->fd, I_STR, &strioc_ppa);
2363 if (new_ppa >= 0)
2364 {
2365 msg(M_INFO, "open_tun: got dynamic interface '%s%d'", dev_tuntap_type, new_ppa);
2366 ppa = new_ppa;
2367 found_one = true;
2368 break;
2369 }
2370 if (errno != EEXIST)
2371 {
2372 msg(M_ERR, "open_tun: unexpected error trying to find free %s interface",
2373 dev_tuntap_type);
2374 }
2375 ppa++;
2376 }
2377 if (!found_one)
2378 {
2379 msg(M_ERR, "open_tun: could not find free %s interface, give up.", dev_tuntap_type);
2380 }
2381 }
2382 else /* try this particular one */
2383 {
2384 if ((ppa = ioctl(tt->fd, I_STR, &strioc_ppa)) < 0)
2385 {
2386 msg(M_ERR, "Can't assign PPA for new interface (%s%d)", dev_tuntap_type, ppa);
2387 }
2388 }
2389
2390 if ((if_fd = open(dev_node, O_RDWR, 0)) < 0)
2391 {
2392 msg(M_ERR, "Can't open %s (2)", dev_node);
2393 }
2394
2395 if (ioctl(if_fd, I_PUSH, "ip") < 0)
2396 {
2397 msg(M_ERR, "Can't push IP module");
2398 }
2399
2400 if (tt->type == DEV_TYPE_TUN)
2401 {
2402 /* Assign ppa according to the unit number returned by tun device */
2403 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0)
2404 {
2405 msg(M_ERR, "Can't set PPA %d", ppa);
2406 }
2407 }
2408
2409 tt->actual_name = (char *)malloc(32);
2411
2412 snprintf(tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa);
2413
2414 if (tt->type == DEV_TYPE_TAP)
2415 {
2416 if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
2417 {
2418 msg(M_ERR, "Can't get flags");
2419 }
2420 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2421 ifr.lifr_ppa = ppa;
2422 /* Assign ppa according to the unit number returned by tun device */
2423 if (ioctl(if_fd, SIOCSLIFNAME, &ifr) < 0)
2424 {
2425 msg(M_ERR, "Can't set PPA %d", ppa);
2426 }
2427 if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
2428 {
2429 msg(M_ERR, "Can't get flags");
2430 }
2431 /* Push arp module to if_fd */
2432 if (ioctl(if_fd, I_PUSH, "arp") < 0)
2433 {
2434 msg(M_ERR, "Can't push ARP module");
2435 }
2436
2437 /* Pop any modules on the stream */
2438 while (true)
2439 {
2440 if (ioctl(tt->ip_fd, I_POP, NULL) < 0)
2441 {
2442 break;
2443 }
2444 }
2445 /* Push arp module to ip_fd */
2446 if (ioctl(tt->ip_fd, I_PUSH, "arp") < 0)
2447 {
2448 msg(M_ERR, "Can't push ARP module");
2449 }
2450
2451 /* Open arp_fd */
2452 if ((arp_fd = open(arp_node, O_RDWR, 0)) < 0)
2453 {
2454 msg(M_ERR, "Can't open %s", arp_node);
2455 }
2456 /* Push arp module to arp_fd */
2457 if (ioctl(arp_fd, I_PUSH, "arp") < 0)
2458 {
2459 msg(M_ERR, "Can't push ARP module");
2460 }
2461
2462 /* Set ifname to arp */
2463 strioc_if.ic_cmd = SIOCSLIFNAME;
2464 strioc_if.ic_timout = 0;
2465 strioc_if.ic_len = sizeof(ifr);
2466 strioc_if.ic_dp = (char *)&ifr;
2467 if (ioctl(arp_fd, I_STR, &strioc_if) < 0)
2468 {
2469 msg(M_ERR, "Can't set ifname to arp");
2470 }
2471 }
2472
2473 if ((ip_muxid = ioctl(tt->ip_fd, link_type, if_fd)) < 0)
2474 {
2475 msg(M_ERR, "Can't link %s device to IP", dev_tuntap_type);
2476 }
2477
2478 if (tt->type == DEV_TYPE_TAP)
2479 {
2480 if ((arp_muxid = ioctl(tt->ip_fd, link_type, arp_fd)) < 0)
2481 {
2482 msg(M_ERR, "Can't link %s device to ARP", dev_tuntap_type);
2483 }
2484 close(arp_fd);
2485 }
2486
2487 CLEAR(ifr);
2488 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2489 ifr.lifr_ip_muxid = ip_muxid;
2490 if (tt->type == DEV_TYPE_TAP)
2491 {
2492 ifr.lifr_arp_muxid = arp_muxid;
2493 }
2494
2495 if (ioctl(tt->ip_fd, SIOCSLIFMUXID, &ifr) < 0)
2496 {
2497 if (tt->type == DEV_TYPE_TAP)
2498 {
2499 ioctl(tt->ip_fd, I_PUNLINK, arp_muxid);
2500 }
2501 ioctl(tt->ip_fd, I_PUNLINK, ip_muxid);
2502 msg(M_ERR, "Can't set multiplexor id");
2503 }
2504
2505 set_nonblock(tt->fd);
2506 set_cloexec(tt->fd);
2507 set_cloexec(tt->ip_fd);
2508
2509 msg(M_INFO, "TUN/TAP device %s opened", tt->actual_name);
2510}
2511
2512static void
2513solaris_close_tun(struct tuntap *tt)
2514{
2515 /* IPv6 interfaces need to be 'manually' de-configured */
2517 {
2518 struct argv argv = argv_new();
2519 argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, tt->actual_name);
2520 argv_msg(M_INFO, &argv);
2521 openvpn_execve_check(&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed");
2522 argv_free(&argv);
2523 }
2524
2525 if (tt->ip_fd >= 0)
2526 {
2527 struct lifreq ifr;
2528 CLEAR(ifr);
2529 strncpynt(ifr.lifr_name, tt->actual_name, sizeof(ifr.lifr_name));
2530
2531 if (ioctl(tt->ip_fd, SIOCGLIFFLAGS, &ifr) < 0)
2532 {
2533 msg(M_WARN | M_ERRNO, "Can't get iface flags");
2534 }
2535
2536 if (ioctl(tt->ip_fd, SIOCGLIFMUXID, &ifr) < 0)
2537 {
2538 msg(M_WARN | M_ERRNO, "Can't get multiplexor id");
2539 }
2540
2541 if (tt->type == DEV_TYPE_TAP)
2542 {
2543 if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_arp_muxid) < 0)
2544 {
2545 msg(M_WARN | M_ERRNO, "Can't unlink interface(arp)");
2546 }
2547 }
2548
2549 if (ioctl(tt->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0)
2550 {
2551 msg(M_WARN | M_ERRNO, "Can't unlink interface(ip)");
2552 }
2553
2554 close(tt->ip_fd);
2555 tt->ip_fd = -1;
2556 }
2557
2558 if (tt->fd >= 0)
2559 {
2560 close(tt->fd);
2561 tt->fd = -1;
2562 }
2563}
2564
2565/*
2566 * Close TUN device.
2567 */
2568void
2569close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2570{
2571 ASSERT(tt);
2572
2573 solaris_close_tun(tt);
2574
2575 free(tt->actual_name);
2576
2577 clear_tuntap(tt);
2578 free(tt);
2579}
2580
2581static void
2582solaris_error_close(struct tuntap *tt, const struct env_set *es, const char *actual,
2583 bool unplumb_inet6)
2584{
2585 struct argv argv = argv_new();
2586
2587 if (unplumb_inet6)
2588 {
2589 argv_printf(&argv, "%s %s inet6 unplumb", IFCONFIG_PATH, actual);
2590 argv_msg(M_INFO, &argv);
2591 openvpn_execve_check(&argv, es, 0, "Solaris ifconfig inet6 unplumb failed");
2592 }
2593
2594 argv_printf(&argv, "%s %s unplumb", IFCONFIG_PATH, actual);
2595
2596 argv_msg(M_INFO, &argv);
2597 openvpn_execve_check(&argv, es, 0, "Solaris ifconfig unplumb failed");
2598 close_tun(tt, NULL);
2599 msg(M_FATAL, "Solaris ifconfig failed");
2600 argv_free(&argv);
2601}
2602
2603int
2604write_tun(struct tuntap *tt, uint8_t *buf, int len)
2605{
2606 struct strbuf sbuf;
2607 sbuf.len = len;
2608 sbuf.buf = (char *)buf;
2609 return putmsg(tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;
2610}
2611
2612int
2613read_tun(struct tuntap *tt, uint8_t *buf, int len)
2614{
2615 struct strbuf sbuf;
2616 int f = 0;
2617
2618 sbuf.maxlen = len;
2619 sbuf.buf = (char *)buf;
2620 return getmsg(tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
2621}
2622
2623#elif defined(TARGET_OPENBSD)
2624
2625void
2626open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2627 openvpn_net_ctx_t *ctx)
2628{
2629 open_tun_generic(dev, dev_type, dev_node, tt);
2630
2631 /* Enable multicast on the interface */
2632 if (tt->fd >= 0)
2633 {
2634 struct tuninfo info;
2635
2636 if (ioctl(tt->fd, TUNGIFINFO, &info) < 0)
2637 {
2638 msg(M_WARN | M_ERRNO, "Can't get interface info");
2639 }
2640
2641#ifdef IFF_MULTICAST /* openbsd 4.x doesn't have this */
2642 info.flags |= IFF_MULTICAST;
2643#endif
2644
2645 if (ioctl(tt->fd, TUNSIFINFO, &info) < 0)
2646 {
2647 msg(M_WARN | M_ERRNO, "Can't set interface info");
2648 }
2649 }
2650}
2651
2652/* tun(4): "If the device was created by opening /dev/tunN, it will be
2653 * automatically destroyed. Devices created via ifconfig(8) are
2654 * only marked as not running and traffic will be dropped
2655 * returning EHOSTDOWN."
2656 * --> no special handling should be needed - *but* OpenBSD is misbehaving
2657 * here: if the interface was put in tap mode ("ifconfig tunN link0"), it
2658 * *will* stay around, and needs to be cleaned up manually
2659 */
2660
2661void
2662close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2663{
2664 ASSERT(tt);
2665
2666 /* only *TAP* devices need destroying, tun devices auto-self-destruct
2667 */
2668 if (tt->type == DEV_TYPE_TUN || tt->persistent_if)
2669 {
2670 close_tun_generic(tt);
2671 free(tt);
2672 return;
2673 }
2674
2675 struct argv argv = argv_new();
2676
2677 /* setup command, close tun dev (clears tt->actual_name!), run command
2678 */
2679
2680 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2681
2682 close_tun_generic(tt);
2683
2684 argv_msg(M_INFO, &argv);
2685 openvpn_execve_check(&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)");
2686
2687 free(tt);
2688 argv_free(&argv);
2689}
2690
2691int
2692write_tun(struct tuntap *tt, uint8_t *buf, int len)
2693{
2694 return write_tun_header(tt, buf, len);
2695}
2696
2697int
2698read_tun(struct tuntap *tt, uint8_t *buf, int len)
2699{
2700 return read_tun_header(tt, buf, len);
2701}
2702
2703#elif defined(TARGET_NETBSD)
2704
2705/*
2706 * NetBSD 4.0 and up support IPv6 on tun interfaces, but we need to put
2707 * the tun interface into "multi_af" mode, which will prepend the address
2708 * family to all packets (same as OpenBSD and FreeBSD).
2709 *
2710 * If this is not enabled, the kernel silently drops all IPv6 packets on
2711 * output and gets confused on input.
2712 *
2713 * Note: --dev tap3 works *if* the interface is created externally by
2714 * "ifconfig tap3 create"
2715 * (and for devices beyond tap3, "mknod /dev/tapN c ...")
2716 * but we do not have code to do that inside OpenVPN
2717 */
2718
2719void
2720open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2721 openvpn_net_ctx_t *ctx)
2722{
2723 /* on NetBSD, tap (but not tun) devices are opened by
2724 * opening /dev/tap and then querying the system about the
2725 * actual device name (tap0, tap1, ...) assigned
2726 */
2727 if (strcmp(dev, "tap") == 0)
2728 {
2729 struct ifreq ifr;
2730 if ((tt->fd = open("/dev/tap", O_RDWR)) < 0)
2731 {
2732 msg(M_FATAL, "Cannot allocate NetBSD TAP dev dynamically");
2733 }
2734 if (ioctl(tt->fd, TAPGIFNAME, (void *)&ifr) < 0)
2735 {
2736 msg(M_FATAL, "Cannot query NetBSD TAP device name");
2737 }
2738 set_nonblock(tt->fd);
2739 set_cloexec(tt->fd); /* don't pass fd to scripts */
2740 msg(M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
2741
2742 tt->actual_name = string_alloc(ifr.ifr_name, NULL);
2743 }
2744 else
2745 {
2746 /* dynamic / named tun can be handled by the generic function
2747 * named tap ("tap3") is handled there as well, if pre-created
2748 */
2749 open_tun_generic(dev, dev_type, dev_node, tt);
2750 }
2751
2752 if (tt->fd >= 0)
2753 {
2754 int i = IFF_POINTOPOINT | IFF_MULTICAST;
2755 ioctl(tt->fd, TUNSIFMODE, &i); /* multicast on */
2756 i = 0;
2757 ioctl(tt->fd, TUNSLMODE, &i); /* link layer mode off */
2758
2759 if (tt->type == DEV_TYPE_TUN)
2760 {
2761 i = 1;
2762 if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
2763 {
2764 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
2765 }
2766 }
2767 }
2768}
2769
2770/* the current way OpenVPN handles tun devices on NetBSD leads to
2771 * lingering tunX interfaces after close -> for a full cleanup, they
2772 * need to be explicitly destroyed
2773 */
2774void
2775close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2776{
2777 ASSERT(tt);
2778
2779 /* only tun devices need destroying, tap devices auto-self-destruct
2780 */
2781 if (tt->type != DEV_TYPE_TUN || tt->persistent_if)
2782 {
2783 close_tun_generic(tt);
2784 free(tt);
2785 return;
2786 }
2787
2788 struct argv argv = argv_new();
2789
2790 /* setup command, close tun dev (clears tt->actual_name!), run command
2791 */
2792
2793 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2794
2795 close_tun_generic(tt);
2796
2797 argv_msg(M_INFO, &argv);
2798 openvpn_execve_check(&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)");
2799
2800 free(tt);
2801 argv_free(&argv);
2802}
2803
2804static inline int
2805netbsd_modify_read_write_return(int len)
2806{
2807 if (len > 0)
2808 {
2809 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
2810 }
2811 else
2812 {
2813 return len;
2814 }
2815}
2816
2817int
2818write_tun(struct tuntap *tt, uint8_t *buf, int len)
2819{
2820 if (tt->type == DEV_TYPE_TUN)
2821 {
2822 u_int32_t type;
2823 struct iovec iv[2];
2824 struct openvpn_iphdr *iph;
2825
2826 iph = (struct openvpn_iphdr *)buf;
2827
2828 if (OPENVPN_IPH_GET_VER(iph->version_len) == 6)
2829 {
2830 type = htonl(AF_INET6);
2831 }
2832 else
2833 {
2834 type = htonl(AF_INET);
2835 }
2836
2837 iv[0].iov_base = (char *)&type;
2838 iv[0].iov_len = sizeof(type);
2839 iv[1].iov_base = buf;
2840 iv[1].iov_len = len;
2841
2842 return netbsd_modify_read_write_return(writev(tt->fd, iv, 2));
2843 }
2844 else
2845 {
2846 return write(tt->fd, buf, len);
2847 }
2848}
2849
2850int
2851read_tun(struct tuntap *tt, uint8_t *buf, int len)
2852{
2853 if (tt->type == DEV_TYPE_TUN)
2854 {
2855 u_int32_t type;
2856 struct iovec iv[2];
2857
2858 iv[0].iov_base = (char *)&type;
2859 iv[0].iov_len = sizeof(type);
2860 iv[1].iov_base = buf;
2861 iv[1].iov_len = len;
2862
2863 return netbsd_modify_read_write_return(readv(tt->fd, iv, 2));
2864 }
2865 else
2866 {
2867 return read(tt->fd, buf, len);
2868 }
2869}
2870
2871#elif defined(TARGET_FREEBSD)
2872
2873static inline int
2874freebsd_modify_read_write_return(int len)
2875{
2876 if (len > 0)
2877 {
2878 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
2879 }
2880 else
2881 {
2882 return len;
2883 }
2884}
2885
2886void
2887open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
2888 openvpn_net_ctx_t *ctx)
2889{
2890 if (tun_dco_enabled(tt))
2891 {
2892 open_tun_dco_generic(dev, dev_type, tt, ctx);
2893 }
2894 else
2895 {
2896 open_tun_generic(dev, dev_type, dev_node, tt);
2897
2898 if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
2899 {
2900 /* see "Interface Flags" in ifnet(9) */
2901 int i = IFF_POINTOPOINT | IFF_MULTICAST;
2902 if (tt->topology == TOP_SUBNET)
2903 {
2904 i = IFF_BROADCAST | IFF_MULTICAST;
2905 }
2906
2907 if (ioctl(tt->fd, TUNSIFMODE, &i) < 0)
2908 {
2909 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFMODE)");
2910 }
2911
2912 /* multi_af mode for v4+v6, see "tun(4)" */
2913 i = 1;
2914 if (ioctl(tt->fd, TUNSIFHEAD, &i) < 0)
2915 {
2916 msg(M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD)");
2917 }
2918 }
2919 }
2920}
2921
2922/* tun(4): "These network interfaces persist until the if_tun.ko module is
2923 * unloaded, or until removed with the ifconfig(8) command."
2924 * (verified for FreeBSD 6.3, 7.4, 8.2 and 9, same for tap(4))
2925 *
2926 * so, to avoid lingering tun/tap interfaces after OpenVPN quits,
2927 * we need to call "ifconfig ... destroy" for cleanup
2928 */
2929void
2930close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
2931{
2932 ASSERT(tt);
2933
2934 if (tt->persistent_if) /* keep pre-existing if around */
2935 {
2936 close_tun_generic(tt);
2937 free(tt);
2938 return;
2939 }
2940
2941 /* close and destroy */
2942 struct argv argv = argv_new();
2943
2944 /* setup command, close tun dev (clears tt->actual_name!), run command
2945 */
2946
2947 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
2948
2949 close_tun_generic(tt);
2950
2951 argv_msg(M_INFO, &argv);
2952 openvpn_execve_check(&argv, NULL, 0, "FreeBSD 'destroy tun interface' failed (non-critical)");
2953
2954 free(tt);
2955 argv_free(&argv);
2956}
2957
2958#if defined(__GNUC__) || defined(__clang__)
2959#pragma GCC diagnostic push
2960#pragma GCC diagnostic ignored "-Wconversion"
2961#endif
2962
2963int
2964write_tun(struct tuntap *tt, uint8_t *buf, int len)
2965{
2966 if (tt->type == DEV_TYPE_TUN)
2967 {
2968 u_int32_t type;
2969 struct iovec iv[2];
2970 struct ip *iph;
2971
2972 iph = (struct ip *)buf;
2973
2974 if (iph->ip_v == 6)
2975 {
2976 type = htonl(AF_INET6);
2977 }
2978 else
2979 {
2980 type = htonl(AF_INET);
2981 }
2982
2983 iv[0].iov_base = (char *)&type;
2984 iv[0].iov_len = sizeof(type);
2985 iv[1].iov_base = buf;
2986 iv[1].iov_len = len;
2987
2988 return freebsd_modify_read_write_return(writev(tt->fd, iv, 2));
2989 }
2990 else
2991 {
2992 return write(tt->fd, buf, len);
2993 }
2994}
2995
2996int
2997read_tun(struct tuntap *tt, uint8_t *buf, int len)
2998{
2999 if (tt->type == DEV_TYPE_TUN)
3000 {
3001 u_int32_t type;
3002 struct iovec iv[2];
3003
3004 iv[0].iov_base = (char *)&type;
3005 iv[0].iov_len = sizeof(type);
3006 iv[1].iov_base = buf;
3007 iv[1].iov_len = len;
3008
3009 return freebsd_modify_read_write_return(readv(tt->fd, iv, 2));
3010 }
3011 else
3012 {
3013 return read(tt->fd, buf, len);
3014 }
3015}
3016
3017#if defined(__GNUC__) || defined(__clang__)
3018#pragma GCC diagnostic pop
3019#endif
3020
3021#elif defined(TARGET_DRAGONFLY)
3022
3023static inline int
3024dragonfly_modify_read_write_return(int len)
3025{
3026 if (len > 0)
3027 {
3028 return len > sizeof(u_int32_t) ? len - sizeof(u_int32_t) : 0;
3029 }
3030 else
3031 {
3032 return len;
3033 }
3034}
3035
3036void
3037open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3038 openvpn_net_ctx_t *ctx)
3039{
3040 open_tun_generic(dev, dev_type, dev_node, tt);
3041
3042 if (tt->fd >= 0)
3043 {
3044 int i = 0;
3045
3046 /* Disable extended modes */
3047 ioctl(tt->fd, TUNSLMODE, &i);
3048 i = 1;
3049 ioctl(tt->fd, TUNSIFHEAD, &i);
3050 }
3051}
3052
3053void
3054close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3055{
3056 ASSERT(tt);
3057
3058 close_tun_generic(tt);
3059 free(tt);
3060}
3061
3062int
3063write_tun(struct tuntap *tt, uint8_t *buf, int len)
3064{
3065 if (tt->type == DEV_TYPE_TUN)
3066 {
3067 u_int32_t type;
3068 struct iovec iv[2];
3069 struct ip *iph;
3070
3071 iph = (struct ip *)buf;
3072
3073 if (iph->ip_v == 6)
3074 {
3075 type = htonl(AF_INET6);
3076 }
3077 else
3078 {
3079 type = htonl(AF_INET);
3080 }
3081
3082 iv[0].iov_base = (char *)&type;
3083 iv[0].iov_len = sizeof(type);
3084 iv[1].iov_base = buf;
3085 iv[1].iov_len = len;
3086
3087 return dragonfly_modify_read_write_return(writev(tt->fd, iv, 2));
3088 }
3089 else
3090 {
3091 return write(tt->fd, buf, len);
3092 }
3093}
3094
3095int
3096read_tun(struct tuntap *tt, uint8_t *buf, int len)
3097{
3098 if (tt->type == DEV_TYPE_TUN)
3099 {
3100 u_int32_t type;
3101 struct iovec iv[2];
3102
3103 iv[0].iov_base = (char *)&type;
3104 iv[0].iov_len = sizeof(type);
3105 iv[1].iov_base = buf;
3106 iv[1].iov_len = len;
3107
3108 return dragonfly_modify_read_write_return(readv(tt->fd, iv, 2));
3109 }
3110 else
3111 {
3112 return read(tt->fd, buf, len);
3113 }
3114}
3115
3116#elif defined(TARGET_DARWIN)
3117
3118/* Darwin (MacOS X) is mostly "just use the generic stuff", but there
3119 * is always one caveat...:
3120 *
3121 * If IPv6 is configured, and the tun device is closed, the IPv6 address
3122 * configured to the tun interface changes to a lingering /128 route
3123 * pointing to lo0. Need to unconfigure... (observed on 10.5)
3124 */
3125
3126/*
3127 * utun is the native Darwin tun driver present since at least 10.7
3128 * Thanks goes to Jonathan Levin for providing an example how to utun
3129 * (https://www.cs.dartmouth.edu/~sergey/netreads/utun/utun-demo.c)
3130 */
3131
3132/* Helper functions that tries to open utun device
3133 * return -2 on early initialization failures (utun not supported
3134 * at all) and -1 on initlization failure of utun
3135 * device (utun works but utunX is already used)
3136 */
3137static int
3138utun_open_helper(struct ctl_info ctlInfo, int utunnum)
3139{
3140 struct sockaddr_ctl sc;
3141 int fd;
3142
3143 fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
3144
3145 if (fd < 0)
3146 {
3147 msg(M_INFO | M_ERRNO, "Opening utun%d failed (socket(SYSPROTO_CONTROL))", utunnum);
3148 return -2;
3149 }
3150
3151 if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1)
3152 {
3153 close(fd);
3154 msg(M_INFO | M_ERRNO, "Opening utun%d failed (ioctl(CTLIOCGINFO))", utunnum);
3155 return -2;
3156 }
3157
3158
3159 sc.sc_id = ctlInfo.ctl_id;
3160 sc.sc_len = sizeof(sc);
3161 sc.sc_family = AF_SYSTEM;
3162 sc.ss_sysaddr = AF_SYS_CONTROL;
3163
3164 sc.sc_unit = utunnum + 1;
3165
3166
3167 /* If the connect is successful, a utun%d device will be created, where "%d"
3168 * is (sc.sc_unit - 1) */
3169
3170 if (connect(fd, (struct sockaddr *)&sc, sizeof(sc)) < 0)
3171 {
3172 msg(M_INFO | M_ERRNO, "Opening utun%d failed (connect(AF_SYS_CONTROL))", utunnum);
3173 close(fd);
3174 return -1;
3175 }
3176
3177 set_nonblock(fd);
3178 set_cloexec(fd); /* don't pass fd to scripts */
3179
3180 return fd;
3181}
3182
3183void
3184open_darwin_utun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
3185{
3186 struct ctl_info ctlInfo;
3187 int fd;
3188 char utunname[20];
3189 int utunnum = -1;
3190 socklen_t utunname_len = sizeof(utunname);
3191
3192 /* dev_node is simply utun, do the normal dynamic utun
3193 * otherwise try to parse the utun number */
3194 if (dev_node && (strcmp("utun", dev_node) != 0))
3195 {
3196 if (sscanf(dev_node, "utun%d", &utunnum) != 1)
3197 {
3198 msg(M_FATAL,
3199 "Cannot parse 'dev-node %s' please use 'dev-node utunX'"
3200 "to use a utun device number X",
3201 dev_node);
3202 }
3203 }
3204
3205
3206 CLEAR(ctlInfo);
3207 if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name))
3208 >= sizeof(ctlInfo.ctl_name))
3209 {
3210 msg(M_ERR, "Opening utun: UTUN_CONTROL_NAME too long");
3211 }
3212
3213 /* try to open first available utun device if no specific utun is requested */
3214 if (utunnum == -1)
3215 {
3216 for (utunnum = 0; utunnum < 255; utunnum++)
3217 {
3218 char ifname[20];
3219 /* if the interface exists silently skip it */
3220 ASSERT(snprintf(ifname, sizeof(ifname), "utun%d", utunnum) > 0);
3221 if (if_nametoindex(ifname))
3222 {
3223 continue;
3224 }
3225 fd = utun_open_helper(ctlInfo, utunnum);
3226 /* Break if the fd is valid,
3227 * or if early initialization failed (-2) */
3228 if (fd != -1)
3229 {
3230 break;
3231 }
3232 }
3233 }
3234 else
3235 {
3236 fd = utun_open_helper(ctlInfo, utunnum);
3237 }
3238
3239 /* opening an utun device failed */
3240 tt->fd = fd;
3241
3242 if (fd < 0)
3243 {
3244 return;
3245 }
3246
3247 /* Retrieve the assigned interface name. */
3248 if (getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len))
3249 {
3250 msg(M_ERR | M_ERRNO, "Error retrieving utun interface name");
3251 }
3252
3253 tt->actual_name = string_alloc(utunname, NULL);
3254
3255 msg(M_INFO, "Opened utun device %s", utunname);
3257}
3258
3259void
3260open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3261 openvpn_net_ctx_t *ctx)
3262{
3263 /* If dev_node does not start start with utun assume regular tun/tap */
3264 if ((!dev_node && tt->type == DEV_TYPE_TUN) || (dev_node && !strncmp(dev_node, "utun", 4)))
3265 {
3266 /* Check if user has specific dev_type tap and forced utun with
3267 * dev-node utun */
3268 if (tt->type != DEV_TYPE_TUN)
3269 {
3270 msg(M_FATAL, "Cannot use utun devices with --dev-type %s",
3271 dev_type_string(dev, dev_type));
3272 }
3273
3274 /* Try utun first and fall back to normal tun if utun fails
3275 * and dev_node is not specified */
3276 open_darwin_utun(dev, dev_type, dev_node, tt);
3277
3278 if (tt->backend_driver != DRIVER_UTUN)
3279 {
3280 if (!dev_node)
3281 {
3282 /* No explicit utun and utun failed, try the generic way) */
3283 msg(M_INFO, "Failed to open utun device. Falling back to /dev/tun device");
3284 open_tun_generic(dev, dev_type, NULL, tt);
3285 }
3286 else
3287 {
3288 /* Specific utun device or generic utun request with no tun
3289 * fall back failed, consider this a fatal failure */
3290 msg(M_FATAL, "Cannot open utun device");
3291 }
3292 }
3293 }
3294 else
3295 {
3296 /* Use plain dev-node tun to select /dev/tun style
3297 * Unset dev_node variable prior to passing to open_tun_generic to
3298 * let open_tun_generic pick the first available tun device */
3299
3300 if (dev_node && strcmp(dev_node, "tun") == 0)
3301 {
3302 dev_node = NULL;
3303 }
3304
3305 open_tun_generic(dev, dev_type, dev_node, tt);
3306 }
3307}
3308
3309#if defined(__GNUC__) || defined(__clang__)
3310#pragma GCC diagnostic push
3311#pragma GCC diagnostic ignored "-Wconversion"
3312#endif
3313
3314void
3315close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3316{
3317 ASSERT(tt);
3318
3319 struct gc_arena gc = gc_new();
3320 struct argv argv = argv_new();
3321
3323 {
3324 const char *ifconfig_ipv6_local = print_in6_addr(tt->local_ipv6, 0, &gc);
3325
3326 argv_printf(&argv, "%s delete -inet6 %s", ROUTE_PATH, ifconfig_ipv6_local);
3327 argv_msg(M_INFO, &argv);
3328 openvpn_execve_check(&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)");
3329 }
3330
3331 close_tun_generic(tt);
3332 free(tt);
3333 argv_free(&argv);
3334 gc_free(&gc);
3335}
3336
3337int
3338write_tun(struct tuntap *tt, uint8_t *buf, int len)
3339{
3340 if (tt->backend_driver == DRIVER_UTUN)
3341 {
3342 return write_tun_header(tt, buf, len);
3343 }
3344 else
3345 {
3346 return write(tt->fd, buf, len);
3347 }
3348}
3349
3350int
3351read_tun(struct tuntap *tt, uint8_t *buf, int len)
3352{
3353 if (tt->backend_driver == DRIVER_UTUN)
3354 {
3355 return read_tun_header(tt, buf, len);
3356 }
3357 else
3358 {
3359 return read(tt->fd, buf, len);
3360 }
3361}
3362
3363#if defined(__GNUC__) || defined(__clang__)
3364#pragma GCC diagnostic pop
3365#endif
3366
3367#elif defined(TARGET_AIX)
3368
3369void
3370open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
3371 openvpn_net_ctx_t *ctx)
3372{
3373 char tunname[256];
3374 char dynamic_name[20];
3375 const char *p;
3376
3377 if (tt->type == DEV_TYPE_TUN)
3378 {
3379 msg(M_FATAL, "no support for 'tun' devices on AIX");
3380 }
3381
3382 if (strncmp(dev, "tap", 3) != 0 || dev_node)
3383 {
3384 msg(M_FATAL,
3385 "'--dev %s' and/or '--dev-node' not supported on AIX, use '--dev tap0', 'tap1', etc.",
3386 dev);
3387 }
3388
3389 if (strcmp(dev, "tap") == 0) /* find first free tap dev */
3390 { /* (= no /dev/tapN node) */
3391 int i;
3392 for (i = 0; i < 99; i++)
3393 {
3394 snprintf(tunname, sizeof(tunname), "/dev/tap%d", i);
3395 if (access(tunname, F_OK) < 0 && errno == ENOENT)
3396 {
3397 break;
3398 }
3399 }
3400 if (i >= 99)
3401 {
3402 msg(M_FATAL, "cannot find unused tap device");
3403 }
3404
3405 snprintf(dynamic_name, sizeof(dynamic_name), "tap%d", i);
3406 dev = dynamic_name;
3407 }
3408 else /* name given, sanity check */
3409 {
3410 /* ensure that dev name is "tap+<digits>" *only* */
3411 p = &dev[3];
3412 while (isdigit(*p))
3413 {
3414 p++;
3415 }
3416 if (*p != '\0')
3417 {
3418 msg(M_FATAL, "TAP device name must be '--dev tapNNNN'");
3419 }
3420
3421 snprintf(tunname, sizeof(tunname), "/dev/%s", dev);
3422 }
3423
3424 /* pre-existing device?
3425 */
3426 if (access(tunname, F_OK) < 0 && errno == ENOENT)
3427 {
3428 /* tunnel device must be created with 'ifconfig tapN create'
3429 */
3430 struct argv argv = argv_new();
3431 struct env_set *es = env_set_create(NULL);
3432 argv_printf(&argv, "%s %s create", IFCONFIG_PATH, dev);
3433 argv_msg(M_INFO, &argv);
3434 env_set_add(es, "ODMDIR=/etc/objrepos");
3435 openvpn_execve_check(&argv, es, S_FATAL, "AIX 'create tun interface' failed");
3437 argv_free(&argv);
3438 }
3439 else
3440 {
3441 /* we didn't make it, we're not going to break it */
3442 tt->persistent_if = TRUE;
3443 }
3444
3445 if ((tt->fd = open(tunname, O_RDWR)) < 0)
3446 {
3447 msg(M_ERR, "Cannot open TAP device '%s'", tunname);
3448 }
3449
3450 set_nonblock(tt->fd);
3451 set_cloexec(tt->fd); /* don't pass fd to scripts */
3452 msg(M_INFO, "TUN/TAP device %s opened", tunname);
3453
3454 /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
3455 tt->actual_name = string_alloc(dev, NULL);
3456}
3457
3458/* tap devices need to be manually destroyed on AIX
3459 */
3460void
3461close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
3462{
3463 ASSERT(tt);
3464
3465 struct argv argv = argv_new();
3466 struct env_set *es = env_set_create(NULL);
3467
3468 /* persistent devices need IP address unconfig, others need destroyal
3469 */
3470 if (tt->persistent_if)
3471 {
3472 argv_printf(&argv, "%s %s 0.0.0.0 down", IFCONFIG_PATH, tt->actual_name);
3473 }
3474 else
3475 {
3476 argv_printf(&argv, "%s %s destroy", IFCONFIG_PATH, tt->actual_name);
3477 }
3478
3479 close_tun_generic(tt);
3480 argv_msg(M_INFO, &argv);
3481 env_set_add(es, "ODMDIR=/etc/objrepos");
3482 openvpn_execve_check(&argv, es, 0, "AIX 'destroy tap interface' failed (non-critical)");
3483
3484 free(tt);
3486 argv_free(&argv);
3487}
3488
3489int
3490write_tun(struct tuntap *tt, uint8_t *buf, int len)
3491{
3492 return write(tt->fd, buf, len);
3493}
3494
3495int
3496read_tun(struct tuntap *tt, uint8_t *buf, int len)
3497{
3498 return read(tt->fd, buf, len);
3499}
3500
3501#elif defined(_WIN32)
3502
3503int
3504tun_read_queue(struct tuntap *tt, int maxsize)
3505{
3506 if (tt->reads.iostate == IOSTATE_INITIAL)
3507 {
3508 DWORD len;
3509 BOOL status;
3510 int err;
3511
3512 /* reset buf to its initial state */
3513 tt->reads.buf = tt->reads.buf_init;
3514
3515 len = maxsize ? maxsize : BLEN(&tt->reads.buf);
3516 ASSERT(len <= BLEN(&tt->reads.buf));
3517
3518 /* the overlapped read will signal this event on I/O completion */
3519 ASSERT(ResetEvent(tt->reads.overlapped.hEvent));
3520
3521 status =
3522 ReadFile(tt->hand, BPTR(&tt->reads.buf), len, &tt->reads.size, &tt->reads.overlapped);
3523
3524 if (status) /* operation completed immediately? */
3525 {
3526 /* since we got an immediate return, we must signal the event object ourselves */
3527 ASSERT(SetEvent(tt->reads.overlapped.hEvent));
3528
3530 tt->reads.status = 0;
3531
3532 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]", (int)len,
3533 (int)tt->reads.size);
3534 }
3535 else
3536 {
3537 err = GetLastError();
3538 if (err == ERROR_IO_PENDING) /* operation queued? */
3539 {
3541 tt->reads.status = err;
3542 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]", (int)len);
3543 }
3544 else /* error occurred */
3545 {
3546 struct gc_arena gc = gc_new();
3547 ASSERT(SetEvent(tt->reads.overlapped.hEvent));
3549 tt->reads.status = err;
3550 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s", (int)len,
3552 gc_free(&gc);
3553 }
3554 }
3555 }
3556 return tt->reads.iostate;
3557}
3558
3559int
3560tun_write_queue(struct tuntap *tt, struct buffer *buf)
3561{
3562 if (tt->writes.iostate == IOSTATE_INITIAL)
3563 {
3564 BOOL status;
3565 int err;
3566
3567 /* make a private copy of buf */
3568 tt->writes.buf = tt->writes.buf_init;
3569 tt->writes.buf.len = 0;
3570 ASSERT(buf_copy(&tt->writes.buf, buf));
3571
3572 /* the overlapped write will signal this event on I/O completion */
3573 ASSERT(ResetEvent(tt->writes.overlapped.hEvent));
3574
3575 status = WriteFile(tt->hand, BPTR(&tt->writes.buf), BLEN(&tt->writes.buf), &tt->writes.size,
3576 &tt->writes.overlapped);
3577
3578 if (status) /* operation completed immediately? */
3579 {
3581
3582 /* since we got an immediate return, we must signal the event object ourselves */
3583 ASSERT(SetEvent(tt->writes.overlapped.hEvent));
3584
3585 tt->writes.status = 0;
3586
3587 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]", BLEN(&tt->writes.buf),
3588 (int)tt->writes.size);
3589 }
3590 else
3591 {
3592 err = GetLastError();
3593 if (err == ERROR_IO_PENDING) /* operation queued? */
3594 {
3596 tt->writes.status = err;
3597 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]", BLEN(&tt->writes.buf));
3598 }
3599 else /* error occurred */
3600 {
3601 struct gc_arena gc = gc_new();
3602 ASSERT(SetEvent(tt->writes.overlapped.hEvent));
3604 tt->writes.status = err;
3605 dmsg(D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s", BLEN(&tt->writes.buf),
3606 strerror_win32(err, &gc));
3607 gc_free(&gc);
3608 }
3609 }
3610 }
3611 return tt->writes.iostate;
3612}
3613
3614int
3615tun_write_win32(struct tuntap *tt, struct buffer *buf)
3616{
3617 int err = 0;
3618 int status = 0;
3619 if (overlapped_io_active(&tt->writes))
3620 {
3621 sockethandle_t sh = { .is_handle = true, .h = tt->hand };
3622 status = sockethandle_finalize(sh, &tt->writes, NULL, NULL);
3623 if (status < 0)
3624 {
3625 err = GetLastError();
3626 }
3627 }
3628 tun_write_queue(tt, buf);
3629 if (status < 0)
3630 {
3631 SetLastError(err);
3632 return status;
3633 }
3634 else
3635 {
3636 return BLEN(buf);
3637 }
3638}
3639
3640static const struct device_instance_id_interface *
3642{
3643 HDEVINFO dev_info_set;
3644 DWORD err;
3645 struct device_instance_id_interface *first = NULL;
3646 struct device_instance_id_interface *last = NULL;
3647
3648 dev_info_set =
3649 SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
3650 if (dev_info_set == INVALID_HANDLE_VALUE)
3651 {
3652 err = GetLastError();
3653 msg(M_FATAL, "Error [%u] opening device information set key: %s", (unsigned int)err,
3654 strerror_win32(err, gc));
3655 }
3656
3657 msg(D_TAP_WIN_DEBUG, "Enumerate device interface lists:");
3658 for (DWORD i = 0;; ++i)
3659 {
3660 SP_DEVINFO_DATA device_info_data;
3661 BOOL res;
3662 HKEY dev_key;
3663 char net_cfg_instance_id_string[] = "NetCfgInstanceId";
3664 BYTE net_cfg_instance_id[256];
3665 char device_instance_id[256];
3666 DWORD len;
3667 DWORD data_type;
3668 LONG status;
3669 ULONG dev_interface_list_size;
3670 CONFIGRET cr;
3671
3672 ZeroMemory(&device_info_data, sizeof(SP_DEVINFO_DATA));
3673 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
3674 res = SetupDiEnumDeviceInfo(dev_info_set, i, &device_info_data);
3675 if (!res)
3676 {
3677 if (GetLastError() == ERROR_NO_MORE_ITEMS)
3678 {
3679 break;
3680 }
3681 else
3682 {
3683 continue;
3684 }
3685 }
3686
3687 dev_key = SetupDiOpenDevRegKey(dev_info_set, &device_info_data, DICS_FLAG_GLOBAL, 0,
3688 DIREG_DRV, KEY_QUERY_VALUE);
3689 if (dev_key == INVALID_HANDLE_VALUE)
3690 {
3691 continue;
3692 }
3693
3694 len = sizeof(net_cfg_instance_id);
3695 data_type = REG_SZ;
3696 status = RegQueryValueEx(dev_key, net_cfg_instance_id_string, NULL, &data_type,
3697 net_cfg_instance_id, &len);
3698 if (status != ERROR_SUCCESS)
3699 {
3700 goto next;
3701 }
3702
3703 len = sizeof(device_instance_id);
3704 res = SetupDiGetDeviceInstanceId(dev_info_set, &device_info_data, device_instance_id, len,
3705 &len);
3706 if (!res)
3707 {
3708 goto next;
3709 }
3710
3711 cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size,
3712 (LPGUID)&GUID_DEVINTERFACE_NET, device_instance_id,
3713 CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
3714
3715 if (cr != CR_SUCCESS)
3716 {
3717 goto next;
3718 }
3719
3720 char *dev_interface_list = gc_malloc(dev_interface_list_size, false, gc);
3721 cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_NET, device_instance_id,
3722 dev_interface_list, dev_interface_list_size,
3723 CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
3724 if (cr != CR_SUCCESS)
3725 {
3726 goto next;
3727 }
3728
3729 char *dev_if = dev_interface_list;
3730
3731 /* device interface list ends with empty string */
3732 while (strlen(dev_if) > 0)
3733 {
3734 struct device_instance_id_interface *dev_iif;
3736 dev_iif->net_cfg_instance_id =
3737 (unsigned char *)string_alloc((char *)net_cfg_instance_id, gc);
3738 dev_iif->device_interface = string_alloc(dev_if, gc);
3739
3740 msg(D_TAP_WIN_DEBUG, "NetCfgInstanceId: %s, Device Interface: %s",
3741 dev_iif->net_cfg_instance_id, dev_iif->device_interface);
3742
3743 /* link into return list */
3744 if (!first)
3745 {
3746 first = dev_iif;
3747 }
3748 if (last)
3749 {
3750 last->next = dev_iif;
3751 }
3752 last = dev_iif;
3753
3754 dev_if += strlen(dev_if) + 1;
3755 }
3756
3757next:
3758 RegCloseKey(dev_key);
3759 }
3760
3761 SetupDiDestroyDeviceInfoList(dev_info_set);
3762
3763 return first;
3764}
3765
3766static const struct tap_reg *
3768{
3769 HKEY adapter_key;
3770 LONG status;
3771 DWORD len;
3772 struct tap_reg *first = NULL;
3773 struct tap_reg *last = NULL;
3774 int i = 0;
3775
3776 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ADAPTER_KEY, 0, KEY_READ, &adapter_key);
3777
3778 if (status != ERROR_SUCCESS)
3779 {
3780 msg(M_FATAL, "Error opening registry key: %s", ADAPTER_KEY);
3781 }
3782
3783 msg(D_TAP_WIN_DEBUG, "Enumerate drivers in registy: ");
3784 while (true)
3785 {
3786 char enum_name[256];
3787 char unit_string[256];
3788 HKEY unit_key;
3789 char component_id_string[] = "ComponentId";
3790 char component_id[256];
3791 char net_cfg_instance_id_string[] = "NetCfgInstanceId";
3792 BYTE net_cfg_instance_id[256];
3793 DWORD data_type;
3794
3795 len = sizeof(enum_name);
3796 status = RegEnumKeyEx(adapter_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
3797 if (status == ERROR_NO_MORE_ITEMS)
3798 {
3799 break;
3800 }
3801 else if (status != ERROR_SUCCESS)
3802 {
3803 msg(M_FATAL, "Error enumerating registry subkeys of key: %s", ADAPTER_KEY);
3804 }
3805
3806 snprintf(unit_string, sizeof(unit_string), "%s\\%s", ADAPTER_KEY, enum_name);
3807
3808 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key);
3809
3810 if (status != ERROR_SUCCESS)
3811 {
3812 dmsg(D_REGISTRY, "Error opening registry key: %s", unit_string);
3813 }
3814 else
3815 {
3816 len = sizeof(component_id);
3817 status = RegQueryValueEx(unit_key, component_id_string, NULL, &data_type,
3818 (LPBYTE)component_id, &len);
3819
3820 if (status != ERROR_SUCCESS || data_type != REG_SZ)
3821 {
3822 dmsg(D_REGISTRY, "Error opening registry key: %s\\%s", unit_string,
3823 component_id_string);
3824 }
3825 else
3826 {
3827 len = sizeof(net_cfg_instance_id);
3828 status = RegQueryValueEx(unit_key, net_cfg_instance_id_string, NULL, &data_type,
3829 net_cfg_instance_id, &len);
3830
3831 if (status == ERROR_SUCCESS && data_type == REG_SZ)
3832 {
3833 /* Is this adapter supported? */
3835 if (strcasecmp(component_id, TAP_WIN_COMPONENT_ID) == 0
3836 || strcasecmp(component_id, "root\\" TAP_WIN_COMPONENT_ID) == 0)
3837 {
3839 }
3840 else if (strcasecmp(component_id, "ovpn-dco") == 0)
3841 {
3843 }
3844
3846 {
3847 struct tap_reg *reg;
3848 ALLOC_OBJ_CLEAR_GC(reg, struct tap_reg, gc);
3849 reg->guid = string_alloc((char *)net_cfg_instance_id, gc);
3851
3852 /* link into return list */
3853 if (!first)
3854 {
3855 first = reg;
3856 }
3857 if (last)
3858 {
3859 last->next = reg;
3860 }
3861 last = reg;
3862
3863 msg(D_TAP_WIN_DEBUG, "NetCfgInstanceId: %s, Driver: %s", reg->guid,
3865 }
3866 }
3867 }
3868 RegCloseKey(unit_key);
3869 }
3870 ++i;
3871 }
3872
3873 RegCloseKey(adapter_key);
3874 return first;
3875}
3876
3877static const struct panel_reg *
3879{
3880 LONG status;
3881 HKEY network_connections_key;
3882 DWORD len;
3883 struct panel_reg *first = NULL;
3884 struct panel_reg *last = NULL;
3885 int i = 0;
3886
3887 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NETWORK_CONNECTIONS_KEY, 0, KEY_READ,
3888 &network_connections_key);
3889
3890 if (status != ERROR_SUCCESS)
3891 {
3892 msg(M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);
3893 }
3894
3895 while (true)
3896 {
3897 char enum_name[256];
3898 char connection_string[256];
3899 HKEY connection_key;
3900 WCHAR name_data[256];
3901 DWORD name_type;
3902 const WCHAR name_string[] = L"Name";
3903
3904 len = sizeof(enum_name);
3905 status = RegEnumKeyEx(network_connections_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
3906 if (status == ERROR_NO_MORE_ITEMS)
3907 {
3908 break;
3909 }
3910 else if (status != ERROR_SUCCESS)
3911 {
3912 msg(M_FATAL, "Error enumerating registry subkeys of key: %s", NETWORK_CONNECTIONS_KEY);
3913 }
3914
3915 snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection",
3916 NETWORK_CONNECTIONS_KEY, enum_name);
3917
3918 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key);
3919
3920 if (status != ERROR_SUCCESS)
3921 {
3922 dmsg(D_REGISTRY, "Error opening registry key: %s", connection_string);
3923 }
3924 else
3925 {
3926 len = sizeof(name_data);
3927 status = RegQueryValueExW(connection_key, name_string, NULL, &name_type,
3928 (LPBYTE)name_data, &len);
3929
3930 if (status != ERROR_SUCCESS || name_type != REG_SZ)
3931 {
3932 dmsg(D_REGISTRY, "Error opening registry key: %s\\%s\\%ls", NETWORK_CONNECTIONS_KEY,
3933 connection_string, name_string);
3934 }
3935 else
3936 {
3937 int n;
3938 LPSTR name;
3939 struct panel_reg *reg;
3940
3941 ALLOC_OBJ_CLEAR_GC(reg, struct panel_reg, gc);
3942 n = WideCharToMultiByte(CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL);
3943 name = gc_malloc(n, false, gc);
3944 WideCharToMultiByte(CP_UTF8, 0, name_data, -1, name, n, NULL, NULL);
3945 reg->name = name;
3946 reg->guid = string_alloc(enum_name, gc);
3947
3948 /* link into return list */
3949 if (!first)
3950 {
3951 first = reg;
3952 }
3953 if (last)
3954 {
3955 last->next = reg;
3956 }
3957 last = reg;
3958 }
3959 RegCloseKey(connection_key);
3960 }
3961 ++i;
3962 }
3963
3964 RegCloseKey(network_connections_key);
3965
3966 return first;
3967}
3968
3969/*
3970 * Check that two addresses are part of the same 255.255.255.252 subnet.
3971 */
3972void
3973verify_255_255_255_252(in_addr_t local, in_addr_t remote)
3974{
3975 struct gc_arena gc = gc_new();
3976 const unsigned int mask = 3;
3977 const char *err = NULL;
3978
3979 if (local == remote)
3980 {
3981 err = "must be different";
3982 goto error;
3983 }
3984 if ((local & (~mask)) != (remote & (~mask)))
3985 {
3986 err =
3987 "must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
3988 goto error;
3989 }
3990 if ((local & mask) == 0 || (local & mask) == 3 || (remote & mask) == 0 || (remote & mask) == 3)
3991 {
3992 err =
3993 "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";
3994 goto error;
3995 }
3996
3997 gc_free(&gc);
3998 return;
3999
4000error:
4001 msg(M_FATAL,
4002 "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s]. The local and remote VPN endpoints %s. Try '" PACKAGE
4003 " --show-valid-subnets' option for more info.",
4004 print_in_addr_t(local, 0, &gc), print_in_addr_t(remote, 0, &gc), err);
4005 gc_free(&gc);
4006}
4007
4008void
4010{
4011 int i;
4012 int col = 0;
4013
4014 printf("On Windows, point-to-point IP support (i.e. --dev tun)\n");
4015 printf("is emulated by the TAP-Windows driver. The major limitation\n");
4016 printf("imposed by this approach is that the --ifconfig local and\n");
4017 printf("remote endpoints must be part of the same 255.255.255.252\n");
4018 printf("subnet. The following list shows examples of endpoint\n");
4019 printf("pairs which satisfy this requirement. Only the final\n");
4020 printf("component of the IP address pairs is at issue.\n\n");
4021 printf("As an example, the following option would be correct:\n");
4022 printf(" --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n");
4023 printf(" --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n");
4024 printf("because [5,6] is part of the below list.\n\n");
4025
4026 for (i = 0; i < 256; i += 4)
4027 {
4028 printf("[%3d,%3d] ", i + 1, i + 2);
4029 if (++col > 4)
4030 {
4031 col = 0;
4032 printf("\n");
4033 }
4034 }
4035 if (col)
4036 {
4037 printf("\n");
4038 }
4039}
4040
4041void
4043{
4044 struct gc_arena gc = gc_new();
4045
4046 bool warn_panel_null = false;
4047 bool warn_panel_dup = false;
4048 bool warn_tap_dup = false;
4049
4050 int links;
4051
4052 const struct tap_reg *tr;
4053 const struct tap_reg *tr1;
4054 const struct panel_reg *pr;
4055
4056 const struct tap_reg *tap_reg = get_tap_reg(&gc);
4057 const struct panel_reg *panel_reg = get_panel_reg(&gc);
4058
4059 msg(msglevel, "Available adapters [name, GUID, driver]:");
4060
4061 /* loop through each TAP-Windows adapter registry entry */
4062 for (tr = tap_reg; tr != NULL; tr = tr->next)
4063 {
4064 links = 0;
4065
4066 /* loop through each network connections entry in the control panel */
4067 for (pr = panel_reg; pr != NULL; pr = pr->next)
4068 {
4069 if (!strcmp(tr->guid, pr->guid))
4070 {
4071 msg(msglevel, "'%s' %s %s", pr->name, tr->guid,
4073 ++links;
4074 }
4075 }
4076
4077 if (links > 1)
4078 {
4079 warn_panel_dup = true;
4080 }
4081 else if (links == 0)
4082 {
4083 /* a TAP adapter exists without a link from the network
4084 * connections control panel */
4085 warn_panel_null = true;
4086 msg(msglevel, "[NULL] %s", tr->guid);
4087 }
4088 }
4089
4090 /* check for TAP-Windows adapter duplicated GUIDs */
4091 for (tr = tap_reg; tr != NULL; tr = tr->next)
4092 {
4093 for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
4094 {
4095 if (tr != tr1 && !strcmp(tr->guid, tr1->guid))
4096 {
4097 warn_tap_dup = true;
4098 }
4099 }
4100 }
4101
4102 /* warn on registry inconsistencies */
4103 if (warn_tap_dup)
4104 {
4105 msg(warnlevel, "WARNING: Some TAP-Windows adapters have duplicate GUIDs");
4106 }
4107
4108 if (warn_panel_dup)
4109 {
4110 msg(warnlevel,
4111 "WARNING: Some TAP-Windows adapters have duplicate links from the Network Connections control panel");
4112 }
4113
4114 if (warn_panel_null)
4115 {
4116 msg(warnlevel,
4117 "WARNING: Some TAP-Windows adapters have no link from the Network Connections control panel");
4118 }
4119
4120 gc_free(&gc);
4121}
4122
4123/*
4124 * Lookup an adapter by GUID.
4125 */
4126static const struct tap_reg *
4127get_adapter_by_guid(const char *guid, const struct tap_reg *tap_reg)
4128{
4129 const struct tap_reg *tr;
4130
4131 for (tr = tap_reg; tr != NULL; tr = tr->next)
4132 {
4133 if (guid && !strcmp(tr->guid, guid))
4134 {
4135 return tr;
4136 }
4137 }
4138
4139 return NULL;
4140}
4141
4142static const char *
4143guid_to_name(const char *guid, const struct panel_reg *panel_reg)
4144{
4145 const struct panel_reg *pr;
4146
4147 for (pr = panel_reg; pr != NULL; pr = pr->next)
4148 {
4149 if (guid && !strcmp(pr->guid, guid))
4150 {
4151 return pr->name;
4152 }
4153 }
4154
4155 return NULL;
4156}
4157
4158static const struct tap_reg *
4159get_adapter_by_name(const char *name, const struct tap_reg *tap_reg,
4160 const struct panel_reg *panel_reg)
4161{
4162 const struct panel_reg *pr;
4163
4164 for (pr = panel_reg; pr != NULL; pr = pr->next)
4165 {
4166 if (name && !strcmp(pr->name, name))
4167 {
4168 return get_adapter_by_guid(pr->guid, tap_reg);
4169 }
4170 }
4171
4172 return NULL;
4173}
4174
4175static void
4177{
4178 if (!tap_reg)
4179 {
4180 msg(M_FATAL, "There are no TAP-Windows or ovpn-dco adapters "
4181 "on this system. You should be able to create an adapter "
4182 "by using tapctl.exe utility.");
4183 }
4184}
4185
4186/*
4187 * Get an adapter GUID and optional actual_name from the
4188 * registry for the TAP device # = device_number.
4189 */
4190static const char *
4191get_unspecified_device_guid(const int device_number, uint8_t *actual_name, int actual_name_size,
4192 const struct tap_reg *tap_reg_src,
4193 const struct panel_reg *panel_reg_src,
4194 enum tun_driver_type *windows_driver, struct gc_arena *gc)
4195{
4196 const struct tap_reg *tap_reg = tap_reg_src;
4197 struct buffer actual = clear_buf();
4198 int i;
4199
4200 ASSERT(device_number >= 0);
4201
4202 /* Make sure we have at least one TAP adapter */
4203 if (!tap_reg)
4204 {
4205 return NULL;
4206 }
4207
4208 /* The actual_name output buffer may be NULL */
4209 if (actual_name)
4210 {
4212 buf_set_write(&actual, actual_name, actual_name_size);
4213 }
4214
4215 /* Move on to specified device number */
4216 for (i = 0; i < device_number; i++)
4217 {
4218 tap_reg = tap_reg->next;
4219 if (!tap_reg)
4220 {
4221 return NULL;
4222 }
4223 }
4224
4225 /* Save Network Panel name (if exists) in actual_name */
4226 if (actual_name)
4227 {
4228 const char *act = guid_to_name(tap_reg->guid, panel_reg_src);
4229 if (act)
4230 {
4231 buf_printf(&actual, "%s", act);
4232 }
4233 else
4234 {
4235 buf_printf(&actual, "%s", tap_reg->guid);
4236 }
4237 }
4238
4239 /* Save GUID for return value */
4240 struct buffer ret = alloc_buf_gc(256, gc);
4241 buf_printf(&ret, "%s", tap_reg->guid);
4242 if (windows_driver != NULL)
4243 {
4244 *windows_driver = tap_reg->windows_driver;
4245 }
4246 return BSTR(&ret);
4247}
4248
4249/*
4250 * Lookup a --dev-node adapter name in the registry
4251 * returning the GUID and optional actual_name and device type
4252 */
4253static const char *
4254get_device_guid(const char *name, uint8_t *actual_name, int actual_name_size,
4255 enum tun_driver_type *windows_driver, const struct tap_reg *tap_reg,
4256 const struct panel_reg *panel_reg, struct gc_arena *gc)
4257{
4258 struct buffer ret = alloc_buf_gc(256, gc);
4259 struct buffer actual = clear_buf();
4260 const struct tap_reg *tr;
4261
4262 /* Make sure we have at least one TAP adapter */
4263 if (!tap_reg)
4264 {
4265 return NULL;
4266 }
4267
4268 /* The actual_name output buffer may be NULL */
4269 if (actual_name)
4270 {
4271 ASSERT(actual_name_size > 0);
4272 buf_set_write(&actual, actual_name, actual_name_size);
4273 }
4274
4275 /* Check if GUID was explicitly specified as --dev-node parameter */
4276 tr = get_adapter_by_guid(name, tap_reg);
4277 if (tr)
4278 {
4279 const char *act = guid_to_name(name, panel_reg);
4280 buf_printf(&ret, "%s", name);
4281 if (act)
4282 {
4283 buf_printf(&actual, "%s", act);
4284 }
4285 else
4286 {
4287 buf_printf(&actual, "%s", name);
4288 }
4289 if (windows_driver)
4290 {
4292 }
4293 return BSTR(&ret);
4294 }
4295
4296 /* Lookup TAP adapter in network connections list */
4297 {
4299 if (tr)
4300 {
4301 buf_printf(&actual, "%s", name);
4302 if (windows_driver)
4303 {
4305 }
4306 buf_printf(&ret, "%s", tr->guid);
4307 return BSTR(&ret);
4308 }
4309 }
4310
4311 return NULL;
4312}
4313
4314/*
4315 * Get adapter info list
4316 */
4317const IP_ADAPTER_INFO *
4319{
4320 ULONG size = 0;
4321 IP_ADAPTER_INFO *pi = NULL;
4322 DWORD status;
4323
4324 if ((status = GetAdaptersInfo(NULL, &size)) != ERROR_BUFFER_OVERFLOW)
4325 {
4326 msg(M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s", (unsigned int)status,
4328 }
4329 else
4330 {
4331 pi = (PIP_ADAPTER_INFO)gc_malloc(size, false, gc);
4332 if ((status = GetAdaptersInfo(pi, &size)) != NO_ERROR)
4333 {
4334 msg(M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s", (unsigned int)status,
4336 pi = NULL;
4337 }
4338 }
4339 return pi;
4340}
4341
4342const IP_PER_ADAPTER_INFO *
4343get_per_adapter_info(const DWORD index, struct gc_arena *gc)
4344{
4345 ULONG size = 0;
4346 IP_PER_ADAPTER_INFO *pi = NULL;
4347 DWORD status;
4348
4349 if (index != TUN_ADAPTER_INDEX_INVALID)
4350 {
4351 if ((status = GetPerAdapterInfo(index, NULL, &size)) != ERROR_BUFFER_OVERFLOW)
4352 {
4353 msg(M_INFO, "GetPerAdapterInfo #1 failed (status=%u) : %s", (unsigned int)status,
4355 }
4356 else
4357 {
4358 pi = (PIP_PER_ADAPTER_INFO)gc_malloc(size, false, gc);
4359 if ((status = GetPerAdapterInfo((ULONG)index, pi, &size)) == ERROR_SUCCESS)
4360 {
4361 return pi;
4362 }
4363 else
4364 {
4365 msg(M_INFO, "GetPerAdapterInfo #2 failed (status=%u) : %s", (unsigned int)status,
4367 }
4368 }
4369 }
4370 return pi;
4371}
4372
4373static const IP_INTERFACE_INFO *
4375{
4376 ULONG size = 0;
4377 IP_INTERFACE_INFO *ii = NULL;
4378 DWORD status;
4379
4380 if ((status = GetInterfaceInfo(NULL, &size)) != ERROR_INSUFFICIENT_BUFFER)
4381 {
4382 msg(M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s", (unsigned int)status,
4384 }
4385 else
4386 {
4387 ii = (PIP_INTERFACE_INFO)gc_malloc(size, false, gc);
4388 if ((status = GetInterfaceInfo(ii, &size)) == NO_ERROR)
4389 {
4390 return ii;
4391 }
4392 else
4393 {
4394 msg(M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s", (unsigned int)status,
4396 }
4397 }
4398 return ii;
4399}
4400
4401static const IP_ADAPTER_INDEX_MAP *
4402get_interface_info(DWORD index, struct gc_arena *gc)
4403{
4404 const IP_INTERFACE_INFO *list = get_interface_info_list(gc);
4405 if (list)
4406 {
4407 int i;
4408 for (i = 0; i < list->NumAdapters; ++i)
4409 {
4410 const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i];
4411 if (index == inter->Index)
4412 {
4413 return inter;
4414 }
4415 }
4416 }
4417 return NULL;
4418}
4419
4420/*
4421 * Given an adapter index, return a pointer to the
4422 * IP_ADAPTER_INFO structure for that adapter.
4423 */
4424
4425const IP_ADAPTER_INFO *
4426get_adapter(const IP_ADAPTER_INFO *ai, DWORD index)
4427{
4428 if (ai && index != TUN_ADAPTER_INDEX_INVALID)
4429 {
4430 const IP_ADAPTER_INFO *a;
4431
4432 /* find index in the linked list */
4433 for (a = ai; a != NULL; a = a->Next)
4434 {
4435 if (a->Index == index)
4436 {
4437 return a;
4438 }
4439 }
4440 }
4441 return NULL;
4442}
4443
4444const IP_ADAPTER_INFO *
4445get_adapter_info(DWORD index, struct gc_arena *gc)
4446{
4447 return get_adapter(get_adapter_info_list(gc), index);
4448}
4449
4450static int
4451get_adapter_n_ip_netmask(const IP_ADAPTER_INFO *ai)
4452{
4453 if (ai)
4454 {
4455 int n = 0;
4456 const IP_ADDR_STRING *ip = &ai->IpAddressList;
4457
4458 while (ip)
4459 {
4460 ++n;
4461 ip = ip->Next;
4462 }
4463 return n;
4464 }
4465 else
4466 {
4467 return 0;
4468 }
4469}
4470
4471static bool
4472get_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask)
4473{
4474 bool ret = false;
4475 *ip = 0;
4476 *netmask = 0;
4477
4478 if (ai)
4479 {
4480 const IP_ADDR_STRING *iplist = &ai->IpAddressList;
4481 int i = 0;
4482
4483 while (iplist)
4484 {
4485 if (i == n)
4486 {
4487 break;
4488 }
4489 ++i;
4490 iplist = iplist->Next;
4491 }
4492
4493 if (iplist)
4494 {
4495 const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
4496 const char *ip_str = iplist->IpAddress.String;
4497 const char *netmask_str = iplist->IpMask.String;
4498 bool succeed1 = false;
4499 bool succeed2 = false;
4500
4501 if (ip_str && netmask_str && strlen(ip_str) && strlen(netmask_str))
4502 {
4503 *ip = getaddr(getaddr_flags, ip_str, 0, &succeed1, NULL);
4504 *netmask = getaddr(getaddr_flags, netmask_str, 0, &succeed2, NULL);
4505 ret = (succeed1 == true && succeed2 == true);
4506 }
4507 }
4508 }
4509
4510 return ret;
4511}
4512
4513static bool
4514test_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
4515{
4516 if (ai)
4517 {
4518 in_addr_t ip_adapter = 0;
4519 in_addr_t netmask_adapter = 0;
4520 const bool status = get_adapter_ip_netmask(ai, 0, &ip_adapter, &netmask_adapter);
4521 return (status && ip_adapter == ip && netmask_adapter == netmask);
4522 }
4523 else
4524 {
4525 return false;
4526 }
4527}
4528
4529const IP_ADAPTER_INFO *
4530get_tun_adapter(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
4531{
4532 if (list && tt)
4533 {
4534 return get_adapter(list, tt->adapter_index);
4535 }
4536 else
4537 {
4538 return NULL;
4539 }
4540}
4541
4542bool
4543is_adapter_up(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
4544{
4545 int i;
4546 bool ret = false;
4547
4548 const IP_ADAPTER_INFO *ai = get_tun_adapter(tt, list);
4549
4550 if (ai)
4551 {
4552 const int n = get_adapter_n_ip_netmask(ai);
4553
4554 /* loop once for every IP/netmask assigned to adapter */
4555 for (i = 0; i < n; ++i)
4556 {
4557 in_addr_t ip, netmask;
4558 if (get_adapter_ip_netmask(ai, i, &ip, &netmask))
4559 {
4560 if (tt->local && tt->adapter_netmask)
4561 {
4562 /* wait for our --ifconfig parms to match the actual adapter parms */
4563 if (tt->local == ip && tt->adapter_netmask == netmask)
4564 {
4565 ret = true;
4566 }
4567 }
4568 else
4569 {
4570 /* --ifconfig was not defined, maybe using a real DHCP server */
4571 if (ip && netmask)
4572 {
4573 ret = true;
4574 }
4575 }
4576 }
4577 }
4578 }
4579 else
4580 {
4581 ret = true; /* this can occur when TAP adapter is bridged */
4582 }
4583 return ret;
4584}
4585
4586bool
4587is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
4588{
4589 int i;
4590 bool ret = false;
4591
4592 if (highest_netmask)
4593 {
4594 *highest_netmask = 0;
4595 }
4596
4597 if (ai)
4598 {
4599 const int n = get_adapter_n_ip_netmask(ai);
4600 for (i = 0; i < n; ++i)
4601 {
4602 in_addr_t adapter_ip, adapter_netmask;
4603 if (get_adapter_ip_netmask(ai, i, &adapter_ip, &adapter_netmask))
4604 {
4605 if (adapter_ip && adapter_netmask
4606 && (ip & adapter_netmask) == (adapter_ip & adapter_netmask))
4607 {
4608 if (highest_netmask && adapter_netmask > *highest_netmask)
4609 {
4610 *highest_netmask = adapter_netmask;
4611 }
4612 ret = true;
4613 }
4614 }
4615 }
4616 }
4617 return ret;
4618}
4619
4620DWORD
4621adapter_index_of_ip(const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count, in_addr_t *netmask)
4622{
4623 struct gc_arena gc = gc_new();
4624 DWORD ret = TUN_ADAPTER_INDEX_INVALID;
4625 in_addr_t highest_netmask = 0;
4626 int lowest_metric = INT_MAX;
4627 bool first = true;
4628
4629 if (count)
4630 {
4631 *count = 0;
4632 }
4633
4634 while (list)
4635 {
4636 in_addr_t hn;
4637
4638 if (is_ip_in_adapter_subnet(list, ip, &hn))
4639 {
4640 int metric = get_interface_metric(list->Index, AF_INET, NULL);
4641 if (first || hn > highest_netmask)
4642 {
4643 highest_netmask = hn;
4644 if (metric >= 0)
4645 {
4646 lowest_metric = metric;
4647 }
4648 if (count)
4649 {
4650 *count = 1;
4651 }
4652 ret = list->Index;
4653 first = false;
4654 }
4655 else if (hn == highest_netmask)
4656 {
4657 if (count)
4658 {
4659 ++*count;
4660 }
4661 if (metric >= 0 && metric < lowest_metric)
4662 {
4663 ret = list->Index;
4664 lowest_metric = metric;
4665 }
4666 }
4667 }
4668 list = list->Next;
4669 }
4670
4671 dmsg(D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d metric=%d",
4672 print_in_addr_t(ip, 0, &gc), print_in_addr_t(highest_netmask, 0, &gc), (int)ret,
4673 count ? *count : -1, lowest_metric);
4674
4675 if (ret == TUN_ADAPTER_INDEX_INVALID && count)
4676 {
4677 *count = 0;
4678 }
4679
4680 if (netmask)
4681 {
4682 *netmask = highest_netmask;
4683 }
4684
4685 gc_free(&gc);
4686 return ret;
4687}
4688
4689/*
4690 * Given an adapter index, return true if the adapter
4691 * is DHCP disabled.
4692 */
4693
4694#define DHCP_STATUS_UNDEF 0
4695#define DHCP_STATUS_ENABLED 1
4696#define DHCP_STATUS_DISABLED 2
4697
4698static int
4699dhcp_status(DWORD index)
4700{
4701 struct gc_arena gc = gc_new();
4702 int ret = DHCP_STATUS_UNDEF;
4703 if (index != TUN_ADAPTER_INDEX_INVALID)
4704 {
4705 const IP_ADAPTER_INFO *ai = get_adapter_info(index, &gc);
4706
4707 if (ai)
4708 {
4709 if (ai->DhcpEnabled)
4710 {
4711 ret = DHCP_STATUS_ENABLED;
4712 }
4713 else
4714 {
4716 }
4717 }
4718 }
4719 gc_free(&gc);
4720 return ret;
4721}
4722
4723/*
4724 * Delete all temporary address/netmask pairs which were added
4725 * to adapter (given by index) by previous calls to AddIPAddress.
4726 */
4727static void
4729{
4730 struct gc_arena gc = gc_new();
4731 const IP_ADAPTER_INFO *a = get_adapter_info(index, &gc);
4732
4733 if (a)
4734 {
4735 const IP_ADDR_STRING *ip = &a->IpAddressList;
4736 while (ip)
4737 {
4738 DWORD status;
4739 const DWORD context = ip->Context;
4740
4741 if ((status = DeleteIPAddress((ULONG)context)) == NO_ERROR)
4742 {
4743 msg(M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s",
4744 ip->IpAddress.String, ip->IpMask.String);
4745 }
4746 else
4747 {
4748 const char *empty = "0.0.0.0";
4749 if (strcmp(ip->IpAddress.String, empty) || strcmp(ip->IpMask.String, empty))
4750 {
4751 msg(M_INFO,
4752 "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)",
4753 ip->IpAddress.String, ip->IpMask.String, (unsigned int)status);
4754 }
4755 }
4756 ip = ip->Next;
4757 }
4758 }
4759 gc_free(&gc);
4760}
4761
4762/*
4763 * Get interface index for use with IP Helper API functions.
4764 */
4765static DWORD
4767{
4768 DWORD index;
4769 ULONG aindex;
4770 wchar_t wbuf[256];
4771 swprintf(wbuf, SIZE(wbuf), L"\\DEVICE\\TCPIP_%hs", guid);
4772 if (GetAdapterIndex(wbuf, &aindex) != NO_ERROR)
4773 {
4775 }
4776 else
4777 {
4778 index = (DWORD)aindex;
4779 }
4780 return index;
4781}
4782
4783static DWORD
4785{
4786 struct gc_arena gc = gc_new();
4787 DWORD index = TUN_ADAPTER_INDEX_INVALID;
4788
4789 const IP_ADAPTER_INFO *list = get_adapter_info_list(&gc);
4790
4791 while (list)
4792 {
4793 if (!strcmp(guid, list->AdapterName))
4794 {
4795 index = list->Index;
4796 break;
4797 }
4798 list = list->Next;
4799 }
4800
4801 gc_free(&gc);
4802 return index;
4803}
4804
4805static DWORD
4806get_adapter_index(const char *guid)
4807{
4808 DWORD index;
4809 index = get_adapter_index_method_1(guid);
4810 if (index == TUN_ADAPTER_INDEX_INVALID)
4811 {
4812 index = get_adapter_index_method_2(guid);
4813 }
4814 if (index == TUN_ADAPTER_INDEX_INVALID)
4815 {
4816 msg(M_INFO, "NOTE: could not get adapter index for %s", guid);
4817 }
4818 return index;
4819}
4820
4821/*
4822 * Return a string representing a PIP_ADDR_STRING
4823 */
4824static const char *
4825format_ip_addr_string(const IP_ADDR_STRING *ip, struct gc_arena *gc)
4826{
4827 struct buffer out = alloc_buf_gc(256, gc);
4828 while (ip)
4829 {
4830 buf_printf(&out, "%s", ip->IpAddress.String);
4831 if (strlen(ip->IpMask.String))
4832 {
4833 buf_printf(&out, "/");
4834 buf_printf(&out, "%s", ip->IpMask.String);
4835 }
4836 buf_printf(&out, " ");
4837 ip = ip->Next;
4838 }
4839 return BSTR(&out);
4840}
4841
4842/*
4843 * Show info for a single adapter
4844 */
4845static void
4847{
4848 msg(msglevel, "%s", a->Description);
4849 msg(msglevel, " Index = %d", (int)a->Index);
4850 msg(msglevel, " GUID = %s", a->AdapterName);
4851 msg(msglevel, " IP = %s", format_ip_addr_string(&a->IpAddressList, gc));
4852 msg(msglevel, " MAC = %s", format_hex_ex(a->Address, a->AddressLength, 0, 1, ":", gc));
4853 msg(msglevel, " GATEWAY = %s", format_ip_addr_string(&a->GatewayList, gc));
4854 if (a->DhcpEnabled)
4855 {
4856 msg(msglevel, " DHCP SERV = %s", format_ip_addr_string(&a->DhcpServer, gc));
4857 msg(msglevel, " DHCP LEASE OBTAINED = %s", time_string(a->LeaseObtained, 0, false, gc));
4858 msg(msglevel, " DHCP LEASE EXPIRES = %s", time_string(a->LeaseExpires, 0, false, gc));
4859 }
4860 if (a->HaveWins)
4861 {
4862 msg(msglevel, " PRI WINS = %s", format_ip_addr_string(&a->PrimaryWinsServer, gc));
4863 msg(msglevel, " SEC WINS = %s", format_ip_addr_string(&a->SecondaryWinsServer, gc));
4864 }
4865
4866 {
4868 if (pai)
4869 {
4870 msg(msglevel, " DNS SERV = %s", format_ip_addr_string(&pai->DnsServerList, gc));
4871 }
4872 }
4873}
4874
4875/*
4876 * Show current adapter list
4877 */
4878void
4880{
4881 struct gc_arena gc = gc_new();
4882 const IP_ADAPTER_INFO *ai = get_adapter_info_list(&gc);
4883
4884 msg(msglevel, "SYSTEM ADAPTER LIST");
4885 if (ai)
4886 {
4887 const IP_ADAPTER_INFO *a;
4888
4889 /* find index in the linked list */
4890 for (a = ai; a != NULL; a = a->Next)
4891 {
4892 show_adapter(msglevel, a, &gc);
4893 }
4894 }
4895 gc_free(&gc);
4896}
4897
4898/*
4899 * Set a particular TAP-Windows adapter (or all of them if
4900 * adapter_name == NULL) to allow it to be opened from
4901 * a non-admin account. This setting will only persist
4902 * for the lifetime of the device object.
4903 */
4904
4905static void
4906tap_allow_nonadmin_access_handle(const char *device_path, HANDLE hand)
4907{
4908 struct security_attributes sa;
4909 BOOL status;
4910
4912 {
4913 msg(M_ERR, "Error: init SA failed");
4914 }
4915
4916 status = SetKernelObjectSecurity(hand, DACL_SECURITY_INFORMATION, &sa.sd);
4917 if (!status)
4918 {
4919 msg(M_ERRNO, "Error: SetKernelObjectSecurity failed on %s", device_path);
4920 }
4921 else
4922 {
4923 msg(M_INFO | M_NOPREFIX, "TAP-Windows device: %s [Non-admin access allowed]", device_path);
4924 }
4925}
4926
4927void
4928tap_allow_nonadmin_access(const char *dev_node)
4929{
4930 struct gc_arena gc = gc_new();
4931 const struct tap_reg *tap_reg = get_tap_reg(&gc);
4932 const struct panel_reg *panel_reg = get_panel_reg(&gc);
4933 const char *device_guid = NULL;
4934 HANDLE hand;
4935 uint8_t actual_buffer[256];
4936 char device_path[256];
4937
4939
4940 if (dev_node)
4941 {
4942 /* Get the device GUID for the device specified with --dev-node. */
4943 device_guid = get_device_guid(dev_node, actual_buffer, sizeof(actual_buffer), NULL, tap_reg,
4944 panel_reg, &gc);
4945
4946 if (!device_guid)
4947 {
4948 msg(M_FATAL, "TAP-Windows adapter '%s' not found", dev_node);
4949 }
4950
4951 /* Open Windows TAP-Windows adapter */
4952 snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid,
4953 TAP_WIN_SUFFIX);
4954
4955 hand = CreateFile(device_path, MAXIMUM_ALLOWED, 0, /* was: FILE_SHARE_READ */
4956 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
4957
4958 if (hand == INVALID_HANDLE_VALUE)
4959 {
4960 msg(M_ERR, "CreateFile failed on TAP device: %s", device_path);
4961 }
4962
4963 tap_allow_nonadmin_access_handle(device_path, hand);
4964 CloseHandle(hand);
4965 }
4966 else
4967 {
4968 int device_number = 0;
4969
4970 /* Try opening all TAP devices */
4971 while (true)
4972 {
4973 device_guid = get_unspecified_device_guid(
4974 device_number, actual_buffer, sizeof(actual_buffer), tap_reg, panel_reg, NULL, &gc);
4975
4976 if (!device_guid)
4977 {
4978 break;
4979 }
4980
4981 /* Open Windows TAP-Windows adapter */
4982 snprintf(device_path, sizeof(device_path), "%s%s%s", USERMODEDEVICEDIR, device_guid,
4983 TAP_WIN_SUFFIX);
4984
4985 hand = CreateFile(device_path, MAXIMUM_ALLOWED, 0, /* was: FILE_SHARE_READ */
4986 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
4987
4988 if (hand == INVALID_HANDLE_VALUE)
4989 {
4990 msg(M_WARN, "CreateFile failed on TAP device: %s", device_path);
4991 }
4992 else
4993 {
4994 tap_allow_nonadmin_access_handle(device_path, hand);
4995 CloseHandle(hand);
4996 }
4997
4998 device_number++;
4999 }
5000 }
5001 gc_free(&gc);
5002}
5003
5004/*
5005 * DHCP release/renewal
5006 */
5007bool
5008dhcp_release_by_adapter_index(const DWORD adapter_index)
5009{
5010 struct gc_arena gc = gc_new();
5011 bool ret = false;
5012 const IP_ADAPTER_INDEX_MAP *inter = get_interface_info(adapter_index, &gc);
5013
5014 if (inter)
5015 {
5016 DWORD status = IpReleaseAddress((IP_ADAPTER_INDEX_MAP *)inter);
5017 if (status == NO_ERROR)
5018 {
5019 msg(D_TUNTAP_INFO, "TAP: DHCP address released");
5020 ret = true;
5021 }
5022 else
5023 {
5024 msg(M_WARN,
5025 "NOTE: Release of DHCP-assigned IP address lease on TAP-Windows adapter failed: %s (code=%u)",
5026 strerror_win32(status, &gc), (unsigned int)status);
5027 }
5028 }
5029
5030 gc_free(&gc);
5031 return ret;
5032}
5033
5034static bool
5035dhcp_release(const struct tuntap *tt)
5036{
5039 {
5041 }
5042 else
5043 {
5044 return false;
5045 }
5046}
5047
5048bool
5049dhcp_renew_by_adapter_index(const DWORD adapter_index)
5050{
5051 struct gc_arena gc = gc_new();
5052 bool ret = false;
5053 const IP_ADAPTER_INDEX_MAP *inter = get_interface_info(adapter_index, &gc);
5054
5055 if (inter)
5056 {
5057 DWORD status = IpRenewAddress((IP_ADAPTER_INDEX_MAP *)inter);
5058 if (status == NO_ERROR)
5059 {
5060 msg(D_TUNTAP_INFO, "TAP: DHCP address renewal succeeded");
5061 ret = true;
5062 }
5063 else
5064 {
5065 msg(M_WARN,
5066 "WARNING: Failed to renew DHCP IP address lease on TAP-Windows adapter: %s (code=%u)",
5067 strerror_win32(status, &gc), (unsigned int)status);
5068 }
5069 }
5070 gc_free(&gc);
5071 return ret;
5072}
5073
5074static bool
5075dhcp_renew(const struct tuntap *tt)
5076{
5079 {
5081 }
5082 else
5083 {
5084 return false;
5085 }
5086}
5087
5088static void
5089exec_command(const char *prefix, const struct argv *a, int n, msglvl_t msglevel)
5090{
5091 int i;
5092 for (i = 0; i < n; ++i)
5093 {
5094 bool status;
5097 argv_msg_prefix(M_INFO, a, prefix);
5098 status = openvpn_execve_check(a, NULL, 0, "ERROR: command failed");
5100 if (status)
5101 {
5102 return;
5103 }
5105 }
5106 msg(msglevel, "%s: command failed", prefix);
5107}
5108
5109static void
5110netsh_command(const struct argv *a, int n, msglvl_t msglevel)
5111{
5112 exec_command("NETSH", a, n, msglevel);
5113}
5114
5115void
5117{
5118 struct argv argv = argv_new();
5119 const char err[] = "ERROR: Windows ipconfig command failed";
5120
5121 msg(D_TUNTAP_INFO, "Start ipconfig commands for register-dns...");
5123
5126 openvpn_execve_check(&argv, es, 0, err);
5127
5128 argv_printf(&argv, "%s%s /registerdns", get_win_sys_path(), WIN_IPCONFIG_PATH_SUFFIX);
5130 openvpn_execve_check(&argv, es, 0, err);
5131 argv_free(&argv);
5132
5134 msg(D_TUNTAP_INFO, "End ipconfig commands for register-dns...");
5135}
5136
5137void
5138ip_addr_string_to_array(in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
5139{
5140 int i = 0;
5141 while (src)
5142 {
5143 const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
5144 const char *ip_str = src->IpAddress.String;
5145 in_addr_t ip = 0;
5146 bool succeed = false;
5147
5148 if (i >= *dest_len)
5149 {
5150 break;
5151 }
5152 if (!ip_str || !strlen(ip_str))
5153 {
5154 break;
5155 }
5156
5157 ip = getaddr(getaddr_flags, ip_str, 0, &succeed, NULL);
5158 if (!succeed)
5159 {
5160 break;
5161 }
5162 dest[i++] = ip;
5163
5164 src = src->Next;
5165 }
5166 *dest_len = i;
5167
5168#if 0
5169 {
5170 struct gc_arena gc = gc_new();
5171 msg(M_INFO, "ip_addr_string_to_array [%d]", *dest_len);
5172 for (i = 0; i < *dest_len; ++i)
5173 {
5174 msg(M_INFO, "%s", print_in_addr_t(dest[i], 0, &gc));
5175 }
5176 gc_free(&gc);
5177 }
5178#endif
5179}
5180
5181static bool
5182ip_addr_one_to_one(const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
5183{
5184 in_addr_t a2[8];
5185 int a2len = SIZE(a2);
5186 int i;
5187
5188 ip_addr_string_to_array(a2, &a2len, ias);
5189 /*msg (M_INFO, "a1len=%d a2len=%d", a1len, a2len);*/
5190 if (a1len != a2len)
5191 {
5192 return false;
5193 }
5194
5195 for (i = 0; i < a1len; ++i)
5196 {
5197 if (a1[i] != a2[i])
5198 {
5199 return false;
5200 }
5201 }
5202 return true;
5203}
5204
5205static bool
5206ip_addr_member_of(const in_addr_t addr, const IP_ADDR_STRING *ias)
5207{
5208 in_addr_t aa[8];
5209 int len = SIZE(aa);
5210 int i;
5211
5212 ip_addr_string_to_array(aa, &len, ias);
5213 for (i = 0; i < len; ++i)
5214 {
5215 if (addr == aa[i])
5216 {
5217 return true;
5218 }
5219 }
5220 return false;
5221}
5222
5228static void
5229netsh_set_dns6_servers(const struct in6_addr *addr_list, const int addr_len, DWORD adapter_index)
5230{
5231 struct gc_arena gc = gc_new();
5232 struct argv argv = argv_new();
5233
5234 /* delete existing DNS settings from TAP interface */
5235 argv_printf(&argv, "%s%s interface ipv6 delete dns %lu all", get_win_sys_path(),
5236 NETSH_PATH_SUFFIX, adapter_index);
5238
5239 for (int i = 0; i < addr_len; ++i)
5240 {
5241 const char *fmt = (i == 0) ? "%s%s interface ipv6 set dns %lu static %s"
5242 : "%s%s interface ipv6 add dns %lu %s";
5243 argv_printf(&argv, fmt, get_win_sys_path(), NETSH_PATH_SUFFIX, adapter_index,
5244 print_in6_addr(addr_list[i], 0, &gc));
5245
5246 /* disable slow address validation */
5247 argv_printf_cat(&argv, "%s", "validate=no");
5248
5249 /* Treat errors while adding as non-fatal as we do not check for duplicates */
5250 netsh_command(&argv, 1, (i == 0) ? M_FATAL : M_NONFATAL);
5251 }
5252
5253 argv_free(&argv);
5254 gc_free(&gc);
5255}
5256
5257static void
5258netsh_ifconfig_options(const char *type, const in_addr_t *addr_list, const int addr_len,
5259 const IP_ADDR_STRING *current, DWORD adapter_index, const bool test_first)
5260{
5261 struct gc_arena gc = gc_new();
5262 struct argv argv = argv_new();
5263 bool delete_first = false;
5264 bool is_dns = !strcmp(type, "dns");
5265
5266 /* first check if we should delete existing DNS/WINS settings from TAP interface */
5267 if (test_first)
5268 {
5269 if (!ip_addr_one_to_one(addr_list, addr_len, current))
5270 {
5271 delete_first = true;
5272 }
5273 }
5274 else
5275 {
5276 delete_first = true;
5277 }
5278
5279 /* delete existing DNS/WINS settings from TAP interface */
5280 if (delete_first)
5281 {
5282 argv_printf(&argv, "%s%s interface ip delete %s %lu all", get_win_sys_path(),
5283 NETSH_PATH_SUFFIX, type, adapter_index);
5285 }
5286
5287 /* add new DNS/WINS settings to TAP interface */
5288 {
5289 int count = 0;
5290 int i;
5291 for (i = 0; i < addr_len; ++i)
5292 {
5293 if (delete_first || !test_first || !ip_addr_member_of(addr_list[i], current))
5294 {
5295 const char *fmt = count ? "%s%s interface ip add %s %lu %s"
5296 : "%s%s interface ip set %s %lu static %s";
5297
5298 argv_printf(&argv, fmt, get_win_sys_path(), NETSH_PATH_SUFFIX, type, adapter_index,
5299 print_in_addr_t(addr_list[i], 0, &gc));
5300
5301 /* disable slow address validation for DNS */
5302 if (is_dns)
5303 {
5304 argv_printf_cat(&argv, "%s", "validate=no");
5305 }
5306
5308
5309 ++count;
5310 }
5311 else
5312 {
5313 msg(M_INFO, "NETSH: %lu %s %s [already set]", adapter_index, type,
5314 print_in_addr_t(addr_list[i], 0, &gc));
5315 }
5316 }
5317 }
5318
5319 argv_free(&argv);
5320 gc_free(&gc);
5321}
5322
5323static void
5324init_ip_addr_string2(IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
5325{
5326 CLEAR(dest[0]);
5327 CLEAR(dest[1]);
5328 if (src1)
5329 {
5330 dest[0] = *src1;
5331 dest[0].Next = NULL;
5332 }
5333 if (src2)
5334 {
5335 dest[1] = *src2;
5336 dest[0].Next = &dest[1];
5337 dest[1].Next = NULL;
5338 }
5339}
5340
5341static void
5342netsh_ifconfig(const struct tuntap_options *to, DWORD adapter_index, const in_addr_t ip,
5343 const in_addr_t netmask, const unsigned int flags)
5344{
5345 struct gc_arena gc = gc_new();
5346 struct argv argv = argv_new();
5347 const IP_ADAPTER_INFO *ai = NULL;
5348 const IP_PER_ADAPTER_INFO *pai = NULL;
5349
5350 if (flags & NI_TEST_FIRST)
5351 {
5352 const IP_ADAPTER_INFO *list = get_adapter_info_list(&gc);
5353 ai = get_adapter(list, adapter_index);
5354 pai = get_per_adapter_info(adapter_index, &gc);
5355 }
5356
5357 if (flags & NI_IP_NETMASK)
5358 {
5359 if (test_adapter_ip_netmask(ai, ip, netmask))
5360 {
5361 msg(M_INFO, "NETSH: %lu %s/%s [already set]", adapter_index,
5362 print_in_addr_t(ip, 0, &gc), print_in_addr_t(netmask, 0, &gc));
5363 }
5364 else
5365 {
5366 /* example: netsh interface ip set address 42 static 10.3.0.1 255.255.255.0 */
5367 argv_printf(&argv, "%s%s interface ip set address %lu static %s %s", get_win_sys_path(),
5368 NETSH_PATH_SUFFIX, adapter_index, print_in_addr_t(ip, 0, &gc),
5369 print_in_addr_t(netmask, 0, &gc));
5370
5372 }
5373 }
5374
5375 /* set WINS/DNS options */
5376 if (flags & NI_OPTIONS)
5377 {
5378 IP_ADDR_STRING wins[2];
5379 CLEAR(wins[0]);
5380 CLEAR(wins[1]);
5381
5382 netsh_ifconfig_options("dns", to->dns, to->dns_len, pai ? &pai->DnsServerList : NULL,
5383 adapter_index, BOOL_CAST(flags & NI_TEST_FIRST));
5384 if (ai && ai->HaveWins)
5385 {
5386 init_ip_addr_string2(wins, &ai->PrimaryWinsServer, &ai->SecondaryWinsServer);
5387 }
5388
5389 netsh_ifconfig_options("wins", to->wins, to->wins_len, ai ? wins : NULL, adapter_index,
5390 BOOL_CAST(flags & NI_TEST_FIRST));
5391 }
5392
5393 argv_free(&argv);
5394 gc_free(&gc);
5395}
5396
5397static void
5398netsh_enable_dhcp(DWORD adapter_index)
5399{
5400 struct argv argv = argv_new();
5401
5402 /* example: netsh interface ip set address 42 dhcp */
5403 argv_printf(&argv, "%s%s interface ip set address %lu dhcp", get_win_sys_path(),
5404 NETSH_PATH_SUFFIX, adapter_index);
5405
5407
5408 argv_free(&argv);
5409}
5410
5411/* Enable dhcp on tap adapter using iservice */
5412static bool
5414{
5415 bool ret = false;
5416 ack_message_t ack;
5417 struct gc_arena gc = gc_new();
5418 HANDLE pipe = tt->options.msg_channel;
5419
5421 .iface = { .index = tt->adapter_index, .name = "" } };
5422
5423 if (!send_msg_iservice(pipe, &dhcp, sizeof(dhcp), &ack, "Enable_dhcp"))
5424 {
5425 goto out;
5426 }
5427
5428 if (ack.error_number != NO_ERROR)
5429 {
5430 msg(M_NONFATAL, "TUN: enabling dhcp using service failed: %s [status=%u if_index=%d]",
5431 strerror_win32(ack.error_number, &gc), ack.error_number, dhcp.iface.index);
5432 }
5433 else
5434 {
5435 msg(M_INFO, "DHCP enabled on interface %d using service", dhcp.iface.index);
5436 ret = true;
5437 }
5438
5439out:
5440 gc_free(&gc);
5441 return ret;
5442}
5443
5444static void
5445windows_set_mtu(const int iface_index, const short family, const int mtu)
5446{
5447 DWORD err = 0;
5448 struct gc_arena gc = gc_new();
5449 MIB_IPINTERFACE_ROW ipiface;
5450 InitializeIpInterfaceEntry(&ipiface);
5451 const char *family_name = (family == AF_INET6) ? "IPv6" : "IPv4";
5452 ipiface.Family = family;
5453 ipiface.InterfaceIndex = iface_index;
5454 if (family == AF_INET6 && mtu < 1280)
5455 {
5456 msg(M_INFO,
5457 "NOTE: IPv6 interface MTU < 1280 conflicts with IETF standards and might not work");
5458 }
5459
5460 err = GetIpInterfaceEntry(&ipiface);
5461 if (err == NO_ERROR)
5462 {
5463 if (family == AF_INET)
5464 {
5465 ipiface.SitePrefixLength = 0;
5466 }
5467 ipiface.NlMtu = mtu;
5468 err = SetIpInterfaceEntry(&ipiface);
5469 }
5470
5471 if (err != NO_ERROR)
5472 {
5473 msg(M_WARN, "TUN: Setting %s mtu failed: %s [status=%lu if_index=%d]", family_name,
5474 strerror_win32(err, &gc), err, iface_index);
5475 }
5476 else
5477 {
5478 msg(M_INFO, "%s MTU set to %d on interface %d using SetIpInterfaceEntry()", family_name,
5479 mtu, iface_index);
5480 }
5481}
5482
5483
5484/*
5485 * Return a TAP name for netsh commands.
5486 */
5487static const char *
5488netsh_get_id(const char *dev_node, struct gc_arena *gc)
5489{
5490 const struct tap_reg *tap_reg = get_tap_reg(gc);
5491 const struct panel_reg *panel_reg = get_panel_reg(gc);
5492 struct buffer actual = alloc_buf_gc(256, gc);
5493 const char *guid;
5494
5496
5497 if (dev_node)
5498 {
5499 guid =
5500 get_device_guid(dev_node, BPTR(&actual), BCAP(&actual), NULL, tap_reg, panel_reg, gc);
5501 }
5502 else
5503 {
5504 guid = get_unspecified_device_guid(0, BPTR(&actual), BCAP(&actual), tap_reg, panel_reg,
5505 NULL, gc);
5506
5508 gc)) /* ambiguous if more than one TAP-Windows adapter */
5509 {
5510 guid = NULL;
5511 }
5512 }
5513
5514 if (!guid)
5515 {
5516 return "NULL"; /* not found */
5517 }
5518 else if (strcmp(BSTR(&actual), "NULL"))
5519 {
5520 return BSTR(&actual); /* control panel name */
5521 }
5522 else
5523 {
5524 return guid; /* no control panel name, return GUID instead */
5525 }
5526}
5527
5528/*
5529 * Called iteratively on TAP-Windows wait-for-initialization polling loop
5530 */
5531void
5533{
5534 tt->standby_iter = 0;
5535}
5536
5537bool
5539{
5540 bool ret = true;
5541 ++tt->standby_iter;
5542 if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
5543 {
5544 if (tt->standby_iter == IPW32_SET_ADAPTIVE_TRY_NETSH)
5545 {
5546 msg(M_INFO, "NOTE: now trying netsh (this may take some time)");
5547 netsh_ifconfig(&tt->options, tt->adapter_index, tt->local, tt->adapter_netmask,
5549 }
5550 else if (tt->standby_iter >= IPW32_SET_ADAPTIVE_TRY_NETSH * 2)
5551 {
5552 ret = false;
5553 }
5554 }
5555 return ret;
5556}
5557
5558static void
5560{
5561 if (tt->options.dhcp_pre_release || tt->options.dhcp_renew)
5562 {
5563 struct gc_arena gc = gc_new();
5564 struct buffer cmd = alloc_buf_gc(256, &gc);
5565 const int verb = 3;
5566 const int pre_sleep = 1;
5567
5568 buf_printf(&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep);
5569 if (tt->options.dhcp_pre_release)
5570 {
5571 buf_printf(&cmd, " --dhcp-pre-release");
5572 }
5573 if (tt->options.dhcp_renew)
5574 {
5575 buf_printf(&cmd, " --dhcp-renew");
5576 }
5577 buf_printf(&cmd, " --dhcp-internal %lu", tt->adapter_index);
5578
5580 gc_free(&gc);
5581 }
5582}
5583
5584static void
5586{
5587 HANDLE msg_channel = tt->options.msg_channel;
5589 struct gc_arena gc = gc_new();
5590
5591 message_header_t rdns = { msg_register_dns, sizeof(message_header_t), 0 };
5592
5593 if (!send_msg_iservice(msg_channel, &rdns, sizeof(rdns), &ack, "Register_dns"))
5594 {
5595 gc_free(&gc);
5596 return;
5597 }
5598
5599 else if (ack.error_number != NO_ERROR)
5600 {
5601 msg(M_WARN, "Register_dns failed using service: %s [status=0x%x]",
5603 }
5604
5605 else
5606 {
5607 msg(M_INFO, "Register_dns request sent to the service");
5608 }
5609
5610 gc_free(&gc);
5611}
5612
5613void
5615{
5616 if (tt && tt->options.register_dns && tt->options.msg_channel)
5617 {
5619 }
5620 else if (tt && tt->options.register_dns)
5621 {
5622 struct gc_arena gc = gc_new();
5623 struct buffer cmd = alloc_buf_gc(256, &gc);
5624 const int verb = 3;
5625
5626 buf_printf(&cmd, "openvpn --verb %d --register-dns --rdns-internal", verb);
5628 gc_free(&gc);
5629 }
5630}
5631
5632static uint32_t
5633dhcp_masq_addr(const in_addr_t local, const in_addr_t netmask, const int offset)
5634{
5635 struct gc_arena gc = gc_new();
5636 in_addr_t dsa; /* DHCP server addr */
5637
5638 if (offset < 0)
5639 {
5640 dsa = (local | (~netmask)) + offset;
5641 }
5642 else
5643 {
5644 dsa = (local & netmask) + offset;
5645 }
5646
5647 if (dsa == local)
5648 {
5649 msg(M_FATAL,
5650 "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",
5651 print_in_addr_t(dsa, 0, &gc));
5652 }
5653
5654 if ((local & netmask) != (dsa & netmask))
5655 {
5656 msg(M_FATAL, "ERROR: --ip-win32 dynamic [offset] : offset is outside of --ifconfig subnet");
5657 }
5658
5659 gc_free(&gc);
5660 return htonl(dsa);
5661}
5662
5663static void
5665{
5666 ULONG info[3];
5667 DWORD len;
5668 CLEAR(info);
5669 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_VERSION, &info, sizeof(info), &info,
5670 sizeof(info), &len, NULL))
5671 {
5672 msg(D_TUNTAP_INFO, "TAP-Windows Driver Version %d.%d %s", (int)info[0], (int)info[1],
5673 (info[2] ? "(DEBUG)" : ""));
5674 }
5675 if (!(info[0] == TAP_WIN_MIN_MAJOR && info[1] >= TAP_WIN_MIN_MINOR))
5676 {
5677 msg(M_FATAL,
5678 "ERROR: This version of " PACKAGE_NAME
5679 " requires a TAP-Windows driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME
5680 " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
5681 TAP_WIN_MIN_MAJOR, TAP_WIN_MIN_MINOR);
5682 }
5683
5684 /* usage of numeric constants is ugly, but this is really tied to
5685 * *this* version of the driver
5686 */
5687 if (tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] < 8)
5688 {
5689 msg(M_INFO,
5690 "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will not work. Upgrade your Tap-Win32 driver.",
5691 (int)info[0], (int)info[1]);
5692 }
5693
5694 /* tap driver 9.8 (2.2.0 and 2.2.1 release) is buggy
5695 */
5696 if (tt->type == DEV_TYPE_TUN && info[0] == 9 && info[1] == 8)
5697 {
5698 msg(M_FATAL,
5699 "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade your Tap-Win32 driver.",
5700 (int)info[0], (int)info[1]);
5701 }
5702}
5703
5704static void
5706{
5707 ULONG mtu = 0;
5708 DWORD len;
5709 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_MTU, &mtu, sizeof(mtu), &mtu, sizeof(mtu), &len,
5710 NULL))
5711 {
5712 msg(D_MTU_INFO, "TAP-Windows MTU=%d", (int)mtu);
5713 }
5714}
5715
5716static void
5717tuntap_set_ip_addr(struct tuntap *tt, const char *device_guid, bool dhcp_masq_post)
5718{
5719 struct gc_arena gc = gc_new();
5720 const DWORD index = tt->adapter_index;
5721
5722 /* flush arp cache */
5724 {
5725 DWORD status = -1;
5726
5727 if (tt->options.msg_channel)
5728 {
5729 ack_message_t ack;
5731 sizeof(flush_neighbors_message_t), 0 },
5732 .family = AF_INET,
5733 .iface = { .index = index, .name = "" } };
5734
5735 if (send_msg_iservice(tt->options.msg_channel, &msg, sizeof(msg), &ack, "TUN"))
5736 {
5737 status = ack.error_number;
5738 }
5739 }
5740 else
5741 {
5742 status = FlushIpNetTable(index);
5743 }
5744
5745 if (status == NO_ERROR)
5746 {
5747 msg(M_INFO, "Successful ARP Flush on interface [%lu] %s", index, device_guid);
5748 }
5749 else if (status != -1)
5750 {
5752 "NOTE: FlushIpNetTable failed on interface [%lu] %s (status=%lu) : %s", index,
5753 device_guid, status, strerror_win32(status, &gc));
5754 }
5755
5756 /*
5757 * If the TAP-Windows driver is masquerading as a DHCP server
5758 * make sure the TCP/IP properties for the adapter are
5759 * set correctly.
5760 */
5761 if (dhcp_masq_post)
5762 {
5763 /* check dhcp enable status */
5764 if (dhcp_status(index) == DHCP_STATUS_DISABLED)
5765 {
5766 msg(M_WARN,
5767 "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'");
5768 }
5769
5770 /* force an explicit DHCP lease renewal on TAP adapter? */
5771 if (tt->options.dhcp_pre_release)
5772 {
5773 dhcp_release(tt);
5774 }
5775 if (tt->options.dhcp_renew)
5776 {
5777 dhcp_renew(tt);
5778 }
5779 }
5780 else
5781 {
5782 fork_dhcp_action(tt);
5783 }
5784 }
5785
5787 {
5788 DWORD status;
5789 const char *error_suffix =
5790 "I am having trouble using the Windows 'IP helper API' to automatically set the IP address -- consider using other --ip-win32 methods (not 'ipapi')";
5791
5792 /* couldn't get adapter index */
5793 if (index == TUN_ADAPTER_INDEX_INVALID)
5794 {
5795 msg(M_FATAL, "ERROR: unable to get adapter index for interface %s -- %s", device_guid,
5796 error_suffix);
5797 }
5798
5799 /* check dhcp enable status */
5800 if (dhcp_status(index) == DHCP_STATUS_DISABLED)
5801 {
5802 msg(M_WARN,
5803 "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'");
5804 }
5805
5806 /* delete previously added IP addresses which were not
5807 * correctly deleted */
5808 delete_temp_addresses(index);
5809
5810 /* add a new IP address */
5811 if ((status = AddIPAddress(htonl(tt->local), htonl(tt->adapter_netmask), index,
5812 &tt->ipapi_context, &tt->ipapi_instance))
5813 == NO_ERROR)
5814 {
5815 msg(M_INFO,
5816 "Succeeded in adding a temporary IP/netmask of %s/%s to interface %s using the Win32 IP Helper API",
5818 device_guid);
5819 }
5820 else
5821 {
5822 msg(M_FATAL,
5823 "ERROR: AddIPAddress %s/%s failed on interface %s, index=%lu, status=%lu (windows error: '%s') -- %s",
5825 device_guid, index, status, strerror_win32(status, &gc), error_suffix);
5826 }
5827 tt->ipapi_context_defined = true;
5828 }
5829
5830 gc_free(&gc);
5831}
5832
5833static void
5835{
5836 ULONG status = TRUE;
5837 DWORD len;
5838 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status,
5839 sizeof(status), &len, NULL))
5840 {
5841 msg(M_WARN,
5842 "WARNING: The TAP-Windows driver rejected a TAP_WIN_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
5843 }
5844
5845 int s = tt->options.tap_sleep;
5846 if (s > 0)
5847 {
5848 msg(M_INFO, "Sleeping for %d seconds...", s);
5850 }
5851}
5852
5853static void
5854tuntap_set_ptp(const struct tuntap *tt)
5855{
5856 DWORD len;
5857 struct gc_arena gc = gc_new();
5858
5860 {
5861 msg(M_FATAL, "ERROR: --dev tun also requires --ifconfig");
5862 }
5863
5864 /* send 0/0/0 to the TAP driver even if we have no IPv4 configured to
5865 * ensure it is somehow initialized.
5866 */
5867 if (!tt->did_ifconfig_setup || tt->topology == TOP_SUBNET)
5868 {
5869 in_addr_t ep[3];
5870 BOOL status;
5871
5872 ep[0] = htonl(tt->local);
5873 ep[1] = htonl(tt->local & tt->remote_netmask);
5874 ep[2] = htonl(tt->remote_netmask);
5875
5876 status = DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_TUN, ep, sizeof(ep), ep, sizeof(ep),
5877 &len, NULL);
5878
5879 if (tt->did_ifconfig_setup)
5880 {
5882 "Set TAP-Windows TUN subnet mode network/local/netmask = %s/%s/%s [%s]",
5885 print_in_addr_t(ep[2], IA_NET_ORDER, &gc), status ? "SUCCEEDED" : "FAILED");
5886 }
5887 else
5888 {
5889 msg(status ? M_INFO : M_FATAL, "Set TAP-Windows TUN with fake IPv4 [%s]",
5890 status ? "SUCCEEDED" : "FAILED");
5891 }
5892 }
5893 else
5894 {
5895 in_addr_t ep[2];
5896 ep[0] = htonl(tt->local);
5897 ep[1] = htonl(tt->remote_netmask);
5898
5899 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT, ep, sizeof(ep), ep,
5900 sizeof(ep), &len, NULL))
5901 {
5902 msg(M_FATAL,
5903 "ERROR: The TAP-Windows driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun");
5904 }
5905 }
5906
5907 gc_free(&gc);
5908}
5909
5910static void
5911tuntap_dhcp_mask(const struct tuntap *tt, const char *device_guid)
5912{
5913 struct gc_arena gc = gc_new();
5914 DWORD len;
5915 uint32_t ep[4];
5916
5917 /* We will answer DHCP requests with a reply to set IP/subnet to these values */
5918 ep[0] = htonl(tt->local);
5919 ep[1] = htonl(tt->adapter_netmask);
5920
5921 /* At what IP address should the DHCP server masquerade at? */
5922 if (tt->type == DEV_TYPE_TUN)
5923 {
5924 if (tt->topology == TOP_SUBNET)
5925 {
5926 ep[2] = dhcp_masq_addr(
5927 tt->local, tt->remote_netmask,
5929 }
5930 else
5931 {
5932 ep[2] = htonl(tt->remote_netmask);
5933 }
5934 }
5935 else
5936 {
5937 ASSERT(tt->type == DEV_TYPE_TAP);
5938 ep[2] =
5941 }
5942
5943 /* lease time in seconds */
5944 ep[3] = (uint32_t)tt->options.dhcp_lease_time;
5945
5946 ASSERT(ep[3] > 0);
5947
5948#ifndef SIMULATE_DHCP_FAILED /* this code is disabled to simulate bad DHCP negotiation */
5949 if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_CONFIG_DHCP_MASQ, ep, sizeof(ep), ep, sizeof(ep),
5950 &len, NULL))
5951 {
5952 msg(M_FATAL,
5953 "ERROR: The TAP-Windows driver rejected a DeviceIoControl call to set TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode");
5954 }
5955
5956 msg(M_INFO,
5957 "Notified TAP-Windows driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]",
5959 device_guid, print_in_addr_t(ep[2], IA_NET_ORDER, &gc), ep[3]);
5960
5961 /* user-supplied DHCP options capability */
5962 if (tt->options.dhcp_options)
5963 {
5964 struct buffer buf = alloc_buf(256);
5965 if (build_dhcp_options_string(&buf, &tt->options))
5966 {
5967 msg(D_DHCP_OPT, "DHCP option string: %s", format_hex(BPTR(&buf), BLEN(&buf), 0, &gc));
5969 BLEN(&buf), BPTR(&buf), BLEN(&buf), &len, NULL))
5970 {
5971 msg(M_FATAL,
5972 "ERROR: The TAP-Windows driver rejected a TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");
5973 }
5974 }
5975 else
5976 {
5977 msg(M_WARN, "DHCP option string not set due to error");
5978 }
5979 free_buf(&buf);
5980 }
5981#endif /* ifndef SIMULATE_DHCP_FAILED */
5982
5983 gc_free(&gc);
5984}
5985
5986static bool
5989{
5990 const char *path = NULL;
5991 char tuntap_device_path[256];
5992
5993 if (tt->backend_driver == DRIVER_DCO)
5994 {
5995 const struct device_instance_id_interface *dev_if;
5996
5997 for (dev_if = device_instance_id_interface; dev_if != NULL; dev_if = dev_if->next)
5998 {
5999 if (strcmp((const char *)dev_if->net_cfg_instance_id, device_guid) != 0)
6000 {
6001 continue;
6002 }
6003
6004 if (tt->backend_driver == DRIVER_DCO)
6005 {
6006 char *last_sep = strrchr(dev_if->device_interface, '\\');
6007 if (!last_sep || strcmp(last_sep + 1, DCO_WIN_REFERENCE_STRING) != 0)
6008 {
6009 continue;
6010 }
6011 }
6012
6013 path = dev_if->device_interface;
6014 break;
6015 }
6016 if (path == NULL)
6017 {
6018 return false;
6019 }
6020 }
6021 else
6022 {
6023 /* Open TAP-Windows */
6024 snprintf(tuntap_device_path, sizeof(tuntap_device_path), "%s%s%s", USERMODEDEVICEDIR,
6025 device_guid, TAP_WIN_SUFFIX);
6026 path = tuntap_device_path;
6027 }
6028
6029 msg(D_TAP_WIN_DEBUG, "Using device interface: %s", path);
6030
6031 tt->hand = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, /* was: FILE_SHARE_READ */
6032 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
6033 if (tt->hand == INVALID_HANDLE_VALUE)
6034 {
6035 msg(D_TUNTAP_INFO | M_ERRNO, "CreateFile failed on %s device: %s",
6037 return false;
6038 }
6039
6040 return true;
6041}
6042
6043void
6044tun_open_device(struct tuntap *tt, const char *dev_node, const char **device_guid,
6045 struct gc_arena *gc)
6046{
6047 const struct tap_reg *tap_reg = get_tap_reg(gc);
6048 const struct panel_reg *panel_reg = get_panel_reg(gc);
6051
6052 uint8_t actual_buffer[256];
6053
6054 /*
6055 * Lookup the device name in the registry, using the --dev-node high level name.
6056 */
6057 if (dev_node)
6058 {
6059 enum tun_driver_type windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
6060
6061 /* Get the device GUID for the device specified with --dev-node. */
6062 *device_guid = get_device_guid(dev_node, actual_buffer, sizeof(actual_buffer),
6063 &windows_driver, tap_reg, panel_reg, gc);
6064
6065 if (!*device_guid)
6066 {
6067 msg(M_FATAL, "Adapter '%s' not found", dev_node);
6068 }
6069
6070 if (tt->backend_driver != windows_driver)
6071 {
6072 msg(M_FATAL,
6073 "Adapter '%s' is using %s driver, %s expected. If you want to use this device, adjust --windows-driver.",
6074 dev_node, print_tun_backend_driver(windows_driver),
6076 }
6077
6078 if (!tun_try_open_device(tt, *device_guid, device_instance_id_interface))
6079 {
6080 msg(M_FATAL, "Failed to open %s adapter: %s",
6082 }
6083 }
6084 else
6085 {
6086 int device_number = 0;
6087 int adapters_created = 0;
6088
6089 /* Try opening all TAP devices until we find one available */
6090 while (true)
6091 {
6092 enum tun_driver_type windows_driver = WINDOWS_DRIVER_UNSPECIFIED;
6093 *device_guid =
6094 get_unspecified_device_guid(device_number, actual_buffer, sizeof(actual_buffer),
6095 tap_reg, panel_reg, &windows_driver, gc);
6096
6097 if (!*device_guid)
6098 {
6099 /* try to create an adapter a few times if we have a service pipe handle */
6100 if ((++adapters_created > 10)
6102 {
6103 msg(M_FATAL, "All %s adapters on this system are currently in use or disabled.",
6105 }
6106 else
6107 {
6108 /* we have created a new adapter so we must reinitialize adapters structs */
6112
6113 device_number = 0;
6114
6115 continue;
6116 }
6117 }
6118
6119 if (tt->backend_driver != windows_driver)
6120 {
6121 goto next;
6122 }
6123
6125 {
6126 break;
6127 }
6128
6129next:
6130 device_number++;
6131 }
6132 }
6133
6134 /* translate high-level device name into a device instance
6135 * GUID using the registry */
6136 tt->actual_name = string_alloc((const char *)actual_buffer, NULL);
6137
6138 tt->adapter_index = get_adapter_index(*device_guid);
6139}
6140
6141static void
6142tuntap_set_ip_props(const struct tuntap *tt, bool *dhcp_masq, bool *dhcp_masq_post)
6143{
6145 {
6146 /*
6147 * If adapter is set to non-DHCP, set to DHCP mode.
6148 */
6150 {
6151 /* try using the service if available, else directly execute netsh */
6152 if (tt->options.msg_channel)
6153 {
6155 }
6156 else
6157 {
6159 }
6160 }
6161 *dhcp_masq = true;
6162 *dhcp_masq_post = true;
6163 }
6165 {
6166 /*
6167 * If adapter is set to non-DHCP, use netsh right away.
6168 */
6170 {
6173 }
6174 else
6175 {
6176 *dhcp_masq = true;
6177 }
6178 }
6179}
6180
6181static void
6182tuntap_post_open(struct tuntap *tt, const char *device_guid)
6183{
6184 bool dhcp_masq = false;
6185 bool dhcp_masq_post = false;
6186
6188 {
6189 /* get driver version info */
6191
6192 /* get driver MTU */
6193 tuntap_get_mtu(tt);
6194
6195 /*
6196 * Preliminaries for setting TAP-Windows adapter TCP/IP
6197 * properties via --ip-win32 dynamic or --ip-win32 adaptive.
6198 */
6199 if (tt->did_ifconfig_setup)
6200 {
6201 tuntap_set_ip_props(tt, &dhcp_masq, &dhcp_masq_post);
6202 }
6203
6204 /* set point-to-point mode if TUN device */
6205 if (tt->type == DEV_TYPE_TUN)
6206 {
6207 tuntap_set_ptp(tt);
6208 }
6209
6210 /* should we tell the TAP-Windows driver to masquerade as a DHCP server as a means
6211 * of setting the adapter address? */
6212 if (dhcp_masq)
6213 {
6214 tuntap_dhcp_mask(tt, device_guid);
6215 }
6216
6217 /* set driver media status to 'connected' */
6219 }
6220
6221 /* possibly use IP Helper API to set IP address on adapter */
6222 tuntap_set_ip_addr(tt, device_guid, dhcp_masq_post);
6223}
6224
6225void
6226open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
6227 openvpn_net_ctx_t *ctx)
6228{
6231 {
6232 msg(M_WARN,
6233 "Some --dhcp-option or --dns options require DHCP server,"
6234 " which is not supported by the selected %s driver. They will be"
6235 " ignored.",
6237 }
6238
6239 /* dco-win already opened the device, which handle we treat as socket */
6240 if (tuntap_is_dco_win(tt))
6241 {
6242 return;
6243 }
6244
6245 const char *device_guid = NULL;
6246
6247 /*netcmd_semaphore_lock ();*/
6248
6249 msg(M_INFO, "open_tun");
6250
6251 if (tt->type != DEV_TYPE_TAP && tt->type != DEV_TYPE_TUN)
6252 {
6253 msg(M_FATAL | M_NOPREFIX, "Unknown virtual device type: '%s'", dev);
6254 }
6255
6256 struct gc_arena gc = gc_new(); /* used also for device_guid allocation */
6257 tun_open_device(tt, dev_node, &device_guid, &gc);
6258
6259 tuntap_post_open(tt, device_guid);
6260
6261 gc_free(&gc);
6262
6263 /*netcmd_semaphore_release ();*/
6264}
6265
6266const char *
6267tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc)
6268{
6270 {
6271 struct buffer out = alloc_buf_gc(256, gc);
6272 DWORD len;
6273 if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_INFO, BSTR(&out), BCAP(&out), BSTR(&out),
6274 BCAP(&out), &len, NULL))
6275 {
6276 return BSTR(&out);
6277 }
6278 }
6279 return NULL;
6280}
6281
6282void
6284{
6285 if (tt->backend_driver == WINDOWS_DRIVER_TAP_WINDOWS6)
6286 {
6287 struct buffer out = alloc_buf(1024);
6288 DWORD len;
6289 while (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_LOG_LINE, BSTR(&out), BCAP(&out),
6290 BSTR(&out), BCAP(&out), &len, NULL))
6291 {
6292 msg(D_TAP_WIN_DEBUG, "TAP-Windows: %s", BSTR(&out));
6293 }
6294 free_buf(&out);
6295 }
6296}
6297
6298static void
6299netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc)
6300{
6301 const char *ifconfig_ip_local;
6302 struct argv argv = argv_new();
6303
6304 /* delete ipvX dns servers if any were set */
6305 int len = ipv6 ? tt->options.dns6_len : tt->options.dns_len;
6306 if (len > 0)
6307 {
6308 argv_printf(&argv, "%s%s interface %s delete dns %lu all", get_win_sys_path(),
6309 NETSH_PATH_SUFFIX, ipv6 ? "ipv6" : "ipv4", tt->adapter_index);
6311 }
6312
6313 if (!ipv6 && tt->options.wins_len > 0)
6314 {
6315 argv_printf(&argv, "%s%s interface ipv4 delete winsservers %lu all", get_win_sys_path(),
6318 }
6319
6320 if (ipv6 && tt->type == DEV_TYPE_TUN)
6321 {
6323 }
6324
6325 /* "store=active" is needed in Windows 8(.1) to delete the
6326 * address we added (pointed out by Cedric Tabary).
6327 */
6328
6329 /* netsh interface ipvX delete address %lu %s */
6330 if (ipv6)
6331 {
6332 ifconfig_ip_local = print_in6_addr(tt->local_ipv6, 0, gc);
6333 }
6334 else
6335 {
6336 ifconfig_ip_local = print_in_addr_t(tt->local, 0, gc);
6337 }
6338 argv_printf(&argv, "%s%s interface %s delete address %lu %s store=active", get_win_sys_path(),
6339 NETSH_PATH_SUFFIX, ipv6 ? "ipv6" : "ipv4", tt->adapter_index, ifconfig_ip_local);
6341
6342 argv_free(&argv);
6343}
6344
6345void
6347{
6348 const char *adaptertype = print_tun_backend_driver(tt->backend_driver);
6349
6350 if (tt->hand)
6351 {
6352 dmsg(D_WIN32_IO_LOW, "Attempting CancelIO on %s adapter", adaptertype);
6353 if (!CancelIo(tt->hand))
6354 {
6355 msg(M_WARN | M_ERRNO, "Warning: CancelIO failed on %s adapter", adaptertype);
6356 }
6357 }
6358
6359 dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped read event on %s adapter", adaptertype);
6361
6362 dmsg(D_WIN32_IO_LOW, "Attempting close of overlapped write event on %s adapter", adaptertype);
6364
6365 if (tt->hand)
6366 {
6367 dmsg(D_WIN32_IO_LOW, "Attempting CloseHandle on %s adapter", adaptertype);
6368 if (!CloseHandle(tt->hand))
6369 {
6370 msg(M_WARN | M_ERRNO, "Warning: CloseHandle failed on %s adapter", adaptertype);
6371 }
6372 tt->hand = NULL;
6373 }
6374}
6375
6376void
6378{
6379 ASSERT(tt);
6380
6381 struct gc_arena gc = gc_new();
6382
6384 {
6386 {
6387 /* We didn't do ifconfig. */
6388 }
6389 else if (tt->options.msg_channel)
6390 {
6391 /* If IPv4 is not enabled, delete DNS domain here */
6392 if (!tt->did_ifconfig_setup)
6393 {
6394 do_dns_domain_service(false, tt);
6395 }
6396 do_dns_service(false, AF_INET6, tt);
6398 do_address_service(false, AF_INET6, tt);
6399 }
6400 else
6401 {
6402 if (!tt->did_ifconfig_setup)
6403 {
6404 do_dns_domain_pwsh(false, tt);
6405 }
6406
6407 netsh_delete_address_dns(tt, true, &gc);
6408 }
6409 }
6410
6411 if (tt->did_ifconfig_setup)
6412 {
6414 {
6415 /* We didn't do ifconfig. */
6416 }
6419 {
6420 /* We don't have to clean the configuration with DHCP. */
6421 }
6422 else if (tt->options.msg_channel)
6423 {
6424 do_wins_service(false, tt);
6425 do_dns_domain_service(false, tt);
6426 do_dns_service(false, AF_INET, tt);
6427 do_address_service(false, AF_INET, tt);
6428 }
6429 else
6430 {
6431 do_dns_domain_pwsh(false, tt);
6432
6434 {
6435 netsh_delete_address_dns(tt, false, &gc);
6436 }
6437 }
6438 }
6439
6440 if (tt->ipapi_context_defined)
6441 {
6442 DWORD status;
6443 if ((status = DeleteIPAddress(tt->ipapi_context)) != NO_ERROR)
6444 {
6445 msg(M_WARN,
6446 "Warning: DeleteIPAddress[%u] failed on TAP-Windows adapter, status=%u : %s",
6447 (unsigned int)tt->ipapi_context, (unsigned int)status, strerror_win32(status, &gc));
6448 }
6449 }
6450
6451 dhcp_release(tt);
6452
6453 close_tun_handle(tt);
6454
6455 free(tt->actual_name);
6456
6457 clear_tuntap(tt);
6458 free(tt);
6459 gc_free(&gc);
6460}
6461
6462/*
6463 * Convert --ip-win32 constants between index and ascii form.
6464 */
6465
6467{
6468 const char *short_form;
6469};
6470
6471/* Indexed by IPW32_SET_x */
6472static const struct ipset_names ipset_names[] = {
6473 { "manual" }, { "netsh" }, { "ipapi" }, { "dynamic" }, { "adaptive" }
6474};
6475
6476int
6477ascii2ipset(const char *name)
6478{
6479 int i;
6481 for (i = 0; i < IPW32_SET_N; ++i)
6482 {
6483 if (!strcmp(name, ipset_names[i].short_form))
6484 {
6485 return i;
6486 }
6487 }
6488 return -1;
6489}
6490
6491const char *
6492ipset2ascii(int index)
6493{
6495 if (index < 0 || index >= IPW32_SET_N)
6496 {
6497 return "[unknown --ip-win32 type]";
6498 }
6499 else
6500 {
6501 return ipset_names[index].short_form;
6502 }
6503}
6504
6505const char *
6507{
6508 struct buffer out = alloc_buf_gc(256, gc);
6509 int i;
6510
6512 for (i = 0; i < IPW32_SET_N; ++i)
6513 {
6514 if (i)
6515 {
6516 buf_printf(&out, " ");
6517 }
6518 buf_printf(&out, "[%s]", ipset2ascii(i));
6519 }
6520 return BSTR(&out);
6521}
6522
6523#else /* generic */
6524
6525void
6526open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt,
6527 openvpn_net_ctx_t *ctx)
6528{
6529 open_tun_generic(dev, dev_type, dev_node, tt);
6530}
6531
6532void
6533close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
6534{
6535 ASSERT(tt);
6536
6538 free(tt);
6539}
6540
6541int
6542write_tun(struct tuntap *tt, uint8_t *buf, int len)
6543{
6544 return write(tt->fd, buf, len);
6545}
6546
6547int
6548read_tun(struct tuntap *tt, uint8_t *buf, int len)
6549{
6550 return read(tt->fd, buf, len);
6551}
6552
6553#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
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition buffer.c:483
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
struct buffer alloc_buf(size_t size)
Definition buffer.c:63
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:649
static bool has_digit(const char *src)
Definition buffer.h:372
#define ALLOC_OBJ(dptr, type)
Definition buffer.h:1047
static char * format_hex(const uint8_t *data, int size, int maxoutput, struct gc_arena *gc)
Definition buffer.h:503
#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
#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:297
static void close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition dco.h:303
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:4784
const char * time_string(time_t t, long usec, bool show_usec, struct gc_arena *gc)
Definition otime.c:109
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:3905
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:1476
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:1790
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:2566
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:2198
void route_ipv6_clear_host_bits(struct route_ipv6 *r6)
Definition route.c:1765
#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:2860
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:192
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:417
struct device_instance_id_interface * next
Definition tun.h:418
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:6468
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:411
const char * name
Definition tun.h:409
const char * guid
Definition tun.h:410
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:261
Definition tun.h:401
struct tap_reg * next
Definition tun.h:404
enum tun_driver_type windows_driver
Definition tun.h:403
const char * guid
Definition tun.h:402
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
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:4191
void ipconfig_register_dns(const struct env_set *es)
Definition tun.c:5116
void tun_show_debug(struct tuntap *tt)
Definition tun.c:6283
static const struct tap_reg * get_tap_reg(struct gc_arena *gc)
Definition tun.c:3767
static DWORD get_adapter_index_method_1(const char *guid)
Definition tun.c:4766
static void tuntap_post_open(struct tuntap *tt, const char *device_guid)
Definition tun.c:6182
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:5488
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:6226
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:3878
void close_tun_handle(struct tuntap *tt)
Definition tun.c:6346
void fork_register_dns_action(struct tuntap *tt)
Definition tun.c:5614
static bool test_adapter_ip_netmask(const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
Definition tun.c:4514
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:5398
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:4042
bool dhcp_renew_by_adapter_index(const DWORD adapter_index)
Definition tun.c:5049
static void tuntap_get_version_info(const struct tuntap *tt)
Definition tun.c:5664
static bool service_enable_dhcp(const struct tuntap *tt)
Definition tun.c:5413
static void netsh_delete_address_dns(const struct tuntap *tt, bool ipv6, struct gc_arena *gc)
Definition tun.c:6299
static void exec_command(const char *prefix, const struct argv *a, int n, msglvl_t msglevel)
Definition tun.c:5089
int ascii2ipset(const char *name)
Definition tun.c:6477
const IP_ADAPTER_INFO * get_tun_adapter(const struct tuntap *tt, const IP_ADAPTER_INFO *list)
Definition tun.c:4530
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:4543
static void tuntap_set_ptp(const struct tuntap *tt)
Definition tun.c:5854
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:5987
static DWORD get_adapter_index(const char *guid)
Definition tun.c:4806
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:5342
const IP_ADAPTER_INFO * get_adapter_info(DWORD index, struct gc_arena *gc)
Definition tun.c:4445
static bool dhcp_release(const struct tuntap *tt)
Definition tun.c:5035
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:5559
static void show_adapter(msglvl_t msglevel, const IP_ADAPTER_INFO *a, struct gc_arena *gc)
Definition tun.c:4846
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:4472
const IP_PER_ADAPTER_INFO * get_per_adapter_info(const DWORD index, struct gc_arena *gc)
Definition tun.c:4343
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:3615
#define DHCP_STATUS_DISABLED
Definition tun.c:4696
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:4254
bool is_ip_in_adapter_subnet(const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
Definition tun.c:4587
static void delete_temp_addresses(DWORD index)
Definition tun.c:4728
static void tuntap_set_ip_addr(struct tuntap *tt, const char *device_guid, bool dhcp_masq_post)
Definition tun.c:5717
const char * tap_win_getinfo(const struct tuntap *tt, struct gc_arena *gc)
Definition tun.c:6267
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:4159
static const IP_ADAPTER_INDEX_MAP * get_interface_info(DWORD index, struct gc_arena *gc)
Definition tun.c:4402
static const IP_INTERFACE_INFO * get_interface_info_list(struct gc_arena *gc)
Definition tun.c:4374
#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:5633
#define DHCP_STATUS_UNDEF
Definition tun.c:4694
#define DHCP_STATUS_ENABLED
Definition tun.c:4695
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:5258
static void tuntap_set_ip_props(const struct tuntap *tt, bool *dhcp_masq, bool *dhcp_masq_post)
Definition tun.c:6142
static void register_dns_service(const struct tuntap *tt)
Definition tun.c:5585
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:3560
bool dhcp_release_by_adapter_index(const DWORD adapter_index)
Definition tun.c:5008
void delete_route_connected_v6_net(const struct tuntap *tt)
Definition tun.c:995
bool tun_standby(struct tuntap *tt)
Definition tun.c:5538
static void tuntap_dhcp_mask(const struct tuntap *tt, const char *device_guid)
Definition tun.c:5911
static void init_ip_addr_string2(IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
Definition tun.c:5324
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:3641
void close_tun(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition tun.c:6377
static const char * guid_to_name(const char *guid, const struct panel_reg *panel_reg)
Definition tun.c:4143
static DWORD get_adapter_index_method_2(const char *guid)
Definition tun.c:4784
static int dhcp_status(DWORD index)
Definition tun.c:4699
const IP_ADAPTER_INFO * get_adapter_info_list(struct gc_arena *gc)
Definition tun.c:4318
void tap_allow_nonadmin_access(const char *dev_node)
Definition tun.c:4928
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:5206
static const char * format_ip_addr_string(const IP_ADDR_STRING *ip, struct gc_arena *gc)
Definition tun.c:4825
const IP_ADAPTER_INFO * get_adapter(const IP_ADAPTER_INFO *ai, DWORD index)
Definition tun.c:4426
static void at_least_one_tap_win(const struct tap_reg *tap_reg)
Definition tun.c:4176
void show_adapters(msglvl_t msglevel)
Definition tun.c:4879
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:5075
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:3504
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:5834
static const struct tap_reg * get_adapter_by_guid(const char *guid, const struct tap_reg *tap_reg)
Definition tun.c:4127
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:5705
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:6492
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:5445
const char * ipset2ascii_all(struct gc_arena *gc)
Definition tun.c:6506
static int get_adapter_n_ip_netmask(const IP_ADAPTER_INFO *ai)
Definition tun.c:4451
void tun_standby_init(struct tuntap *tt)
Definition tun.c:5532
#define NI_IP_NETMASK
Definition tun.c:98
void show_valid_win32_tun_subnets(void)
Definition tun.c:4009
static void tap_allow_nonadmin_access_handle(const char *device_path, HANDLE hand)
Definition tun.c:4906
void ip_addr_string_to_array(in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
Definition tun.c:5138
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:5229
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:5110
DWORD adapter_index_of_ip(const IP_ADAPTER_INFO *list, const in_addr_t ip, int *count, in_addr_t *netmask)
Definition tun.c:4621
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:6044
void verify_255_255_255_252(in_addr_t local, in_addr_t remote)
Definition tun.c:3973
static bool ip_addr_one_to_one(const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
Definition tun.c:5182
#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:532
#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)
void tuncfg(const char *dev, const char *dev_type, const char *dev_node, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options, openvpn_net_ctx_t *ctx)
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