diff options
-rw-r--r-- | error.c | 4 | ||||
-rw-r--r-- | init.c | 21 | ||||
-rw-r--r-- | openvpn.8 | 6 | ||||
-rw-r--r-- | options.c | 44 | ||||
-rw-r--r-- | proxy.c | 7 | ||||
-rw-r--r-- | route.c | 53 | ||||
-rw-r--r-- | socket.c | 33 | ||||
-rw-r--r-- | socket.h | 12 | ||||
-rw-r--r-- | tun.c | 39 | ||||
-rw-r--r-- | tun.h | 5 | ||||
-rw-r--r-- | version.m4 | 2 | ||||
-rw-r--r-- | win/build_exe.py | 15 | ||||
-rw-r--r-- | win/config.py | 1 | ||||
-rw-r--r-- | win/make_dist.py | 44 | ||||
-rw-r--r-- | win/msvc.mak.in | 19 | ||||
-rw-r--r-- | win/settings.in | 3 | ||||
-rw-r--r-- | win32.c | 8 | ||||
-rw-r--r-- | win32.h | 1 |
18 files changed, 244 insertions, 73 deletions
@@ -521,6 +521,10 @@ redirect_stdout_stderr (const char *file, bool append) if (msgfp == NULL) msg (M_ERR, "Error: --log redirect failed due to _fdopen"); + /* redirect C-library stdout/stderr to log file */ + if (_dup2 (log_fd, 1) == -1 || _dup2 (log_fd, 2) == -1) + msg (M_WARN, "Error: --log redirect of stdout/stderr failed"); + std_redir = true; } #elif defined(HAVE_DUP2) @@ -122,7 +122,8 @@ ce_http_proxy_fallback_defined(const struct context *c) int i; for (i = 0; i < l->len; ++i) { - if (l->array[i]->flags & CE_HTTP_PROXY_FALLBACK) + const struct connection_entry *ce = l->array[i]; + if (ce->flags & CE_HTTP_PROXY_FALLBACK) return true; } } @@ -193,12 +194,9 @@ management_callback_http_proxy_fallback_cmd (void *arg, const char *server, cons struct connection_entry *ce = l->array[i]; if (ce->flags & CE_HTTP_PROXY_FALLBACK) { - if (ho) - { - ce->http_proxy_options = ho; - ret = true; - } + ce->http_proxy_options = ho; ce->ce_http_proxy_fallback_timestamp = now; + ret = true; } } } @@ -278,7 +276,7 @@ next_connection_entry (struct context *c) do { const char *remote_ip_hint = NULL; - bool advanced = false; + bool newcycle = false; ce_defined = true; if (l->no_advance && l->current >= 0) @@ -295,7 +293,8 @@ next_connection_entry (struct context *c) msg (M_FATAL, "No usable connection profiles are present"); } - advanced = true; + if (l->current == 0) + newcycle = true; show_connection_list(l); } @@ -305,7 +304,7 @@ next_connection_entry (struct context *c) remote_ip_hint = c->options.remote_ip_hint; #if HTTP_PROXY_FALLBACK - if (advanced && ce_http_proxy_fallback_defined(c)) + if (newcycle && ce_http_proxy_fallback_defined(c)) ce_http_proxy_fallback_start(c, remote_ip_hint); if (ce->flags & CE_HTTP_PROXY_FALLBACK) @@ -1139,6 +1138,10 @@ initialization_sequence_completed (struct context *c, const unsigned int flags) if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && connection_list_defined (&c->options)) connection_list_set_no_advance (&c->options); +#ifdef WIN32 + fork_register_dns_action (c->c1.tuntap); +#endif + #ifdef ENABLE_MANAGEMENT /* Tell management interface that we initialized */ if (management) @@ -4750,6 +4750,12 @@ This option has the same caveats as above. .\"********************************************************* .TP +.B \-\-register-dns +Run ipconfig /flushdns and ipconfig /registerdns on +connection initiation. This is known to kick Windows into +recognizing pushed DNS servers. +.\"********************************************************* +.TP .B \-\-pause-exit Put up a "press any key to continue" message on the console prior to OpenVPN program exit. This option is automatically used by the @@ -615,6 +615,8 @@ static const char usage_message[] = "--dhcp-pre-release : Ask Windows to release the previous TAP adapter lease on\n" " startup.\n" "--dhcp-release : Ask Windows to release the TAP adapter lease on shutdown.\n" + "--register-dns : Run ipconfig /flushdns and ipconfig /registerdns on\n" + " connection initiation.\n" "--tap-sleep n : Sleep for n seconds after TAP adapter open before\n" " attempting to set adapter properties.\n" "--pause-exit : When run from a console window, pause before exiting.\n" @@ -1464,19 +1466,24 @@ parse_http_proxy_fallback (struct context *c, const char *flags, const int msglevel) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new (); + struct http_proxy_options *ret = NULL; struct http_proxy_options *hp = parse_http_proxy_override(server, port, flags, msglevel, &gc); - struct hpo_store *hpos = c->options.hpo_store; - if (!hpos) + if (hp) { - ALLOC_OBJ_CLEAR_GC (hpos, struct hpo_store, &c->options.gc); - c->options.hpo_store = hpos; + struct hpo_store *hpos = c->options.hpo_store; + if (!hpos) + { + ALLOC_OBJ_CLEAR_GC (hpos, struct hpo_store, &c->options.gc); + c->options.hpo_store = hpos; + } + hpos->hpo = *hp; + hpos->hpo.server = hpos->server; + strncpynt(hpos->server, hp->server, sizeof(hpos->server)); + ret = &hpos->hpo; } - hpos->hpo = *hp; - hpos->hpo.server = hpos->server; - strncpynt(hpos->server, hp->server, sizeof(hpos->server)); gc_free (&gc); - return &hpos->hpo; + return ret; } static void @@ -5283,7 +5290,7 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_IPWIN32); options->tuntap_options.dhcp_release = true; } - else if (streq (p[0], "dhcp-rr") && p[1]) /* standalone method for internal use */ + else if (streq (p[0], "dhcp-internal") && p[1]) /* standalone method for internal use */ { unsigned int adapter_index; VERIFY_PERMISSION (OPT_P_GENERAL); @@ -5294,13 +5301,26 @@ add_option (struct options *options, dhcp_release_by_adapter_index (adapter_index); if (options->tuntap_options.dhcp_renew) dhcp_renew_by_adapter_index (adapter_index); - openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */ + openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */ + } + else if (streq (p[0], "register-dns")) + { + VERIFY_PERMISSION (OPT_P_IPWIN32); + options->tuntap_options.register_dns = true; + } + else if (streq (p[0], "rdns-internal")) /* standalone method for internal use */ + { + VERIFY_PERMISSION (OPT_P_GENERAL); + set_debug_level (options->verbosity, SDL_CONSTRAIN); + if (options->tuntap_options.register_dns) + ipconfig_register_dns (NULL); + openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */ } else if (streq (p[0], "show-valid-subnets")) { VERIFY_PERMISSION (OPT_P_GENERAL); show_valid_win32_tun_subnets (); - openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */ + openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */ } else if (streq (p[0], "pause-exit")) { @@ -620,8 +620,11 @@ establish_http_proxy_passthru (struct http_proxy_info *p, { msg (D_PROXY, "Proxy requires authentication"); - /* check for NTLM */ - if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) + if (p->auth_method == HTTP_AUTH_BASIC && !processed) + { + processed = true; + } + else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */ { #if NTLM /* look for the phase 2 response */ @@ -219,6 +219,7 @@ is_special_addr (const char *addr_str) static bool init_route (struct route *r, + struct resolve_list *network_list, const struct route_option *ro, const struct route_special_addr *spec) { @@ -237,14 +238,15 @@ init_route (struct route *r, if (!get_special_addr (spec, ro->network, &r->network, &status)) { - r->network = getaddr ( - GETADDR_RESOLVE - | GETADDR_HOST_ORDER - | GETADDR_WARN_ON_SIGNAL, - ro->network, - 0, - &status, - NULL); + r->network = getaddr_multi ( + GETADDR_RESOLVE + | GETADDR_HOST_ORDER + | GETADDR_WARN_ON_SIGNAL, + ro->network, + 0, + &status, + NULL, + network_list); } if (!status) @@ -438,20 +440,45 @@ init_route_list (struct route_list *rl, else rl->spec.remote_endpoint_defined = false; - if (!(opt->n >= 0 && opt->n <= rl->capacity)) - msg (M_FATAL, PACKAGE_NAME " ROUTE: (init) number of route options (%d) is greater than route list capacity (%d)", opt->n, rl->capacity); - /* parse the routes from opt to rl */ { int i, j = 0; + bool warned = false; for (i = 0; i < opt->n; ++i) { - if (!init_route (&rl->routes[j], + struct resolve_list netlist; + struct route r; + int k; + + if (!init_route (&r, + &netlist, &opt->routes[i], &rl->spec)) ret = false; else - ++j; + { + if (!netlist.len) + { + netlist.data[0] = r.network; + netlist.len = 1; + } + for (k = 0; k < netlist.len; ++k) + { + if (j < rl->capacity) + { + r.network = netlist.data[k]; + rl->routes[j++] = r; + } + else + { + if (!warned) + { + msg (M_WARN, PACKAGE_NAME " ROUTE: routes dropped because number of expanded routes is greater than route list capacity (%d)", rl->capacity); + warned = true; + } + } + } + } } rl->n = j; } @@ -89,12 +89,26 @@ getaddr (unsigned int flags, bool *succeeded, volatile int *signal_received) { + return getaddr_multi (flags, hostname, resolve_retry_seconds, succeeded, signal_received, NULL); +} + +in_addr_t +getaddr_multi (unsigned int flags, + const char *hostname, + int resolve_retry_seconds, + bool *succeeded, + volatile int *signal_received, + struct resolve_list *reslist) +{ struct in_addr ia; int status; int sigrec = 0; int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS; struct gc_arena gc = gc_new (); + if (reslist) + reslist->len = 0; + if (flags & GETADDR_RANDOMIZE) hostname = hostname_randomize(hostname, &gc); @@ -212,11 +226,28 @@ getaddr (unsigned int flags, ++n; ASSERT (n >= 2); - msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses, choosing the first resolved IP address", + msg (D_RESOLVE_ERRORS, "RESOLVE: NOTE: %s resolves to %d addresses", hostname, n); + /* choose address randomly, for basic load-balancing capability */ + /*ia.s_addr = *(in_addr_t *) (h->h_addr_list[get_random () % n]);* + + /* choose first address */ ia.s_addr = *(in_addr_t *) (h->h_addr_list[0]); + + if (reslist) + { + int i; + for (i = 0; i < n && i < SIZE(reslist->data); ++i) + { + in_addr_t a = *(in_addr_t *) (h->h_addr_list[i]); + if (flags & GETADDR_HOST_ORDER) + a = ntohl(a); + reslist->data[i] = a; + } + reslist->len = i; + } } } @@ -439,6 +439,11 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int * * DNS resolution */ +struct resolve_list { + int len; + in_addr_t data[16]; +}; + #define GETADDR_RESOLVE (1<<0) #define GETADDR_FATAL (1<<1) #define GETADDR_HOST_ORDER (1<<2) @@ -456,6 +461,13 @@ in_addr_t getaddr (unsigned int flags, bool *succeeded, volatile int *signal_received); +in_addr_t getaddr_multi (unsigned int flags, + const char *hostname, + int resolve_retry_seconds, + bool *succeeded, + volatile int *signal_received, + struct resolve_list *reslist); + /* * Transport protocol naming and other details. */ @@ -3372,6 +3372,28 @@ netsh_command (const struct argv *a, int n) } void +ipconfig_register_dns (const struct env_set *es) +{ + struct argv argv; + bool status; + const char err[] = "ERROR: Windows ipconfig command failed"; + + netcmd_semaphore_lock (); + argv_init (&argv); + argv_printf (&argv, "%s%sc /flushdns", + get_win_sys_path(), + WIN_IPCONFIG_PATH_SUFFIX); + status = openvpn_execve_check (&argv, es, 0, err); + argv_reset(&argv); + argv_printf (&argv, "%s%sc /registerdns", + get_win_sys_path(), + WIN_IPCONFIG_PATH_SUFFIX); + status = openvpn_execve_check (&argv, es, 0, err); + argv_reset(&argv); + netcmd_semaphore_release (); +} + +void ip_addr_string_to_array (in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src) { int i = 0; @@ -3806,7 +3828,7 @@ fork_dhcp_action (struct tuntap *tt) buf_printf (&cmd, " --dhcp-pre-release"); if (tt->options.dhcp_renew) buf_printf (&cmd, " --dhcp-renew"); - buf_printf (&cmd, " --dhcp-rr %u", (unsigned int)tt->adapter_index); + buf_printf (&cmd, " --dhcp-internal %u", (unsigned int)tt->adapter_index); fork_to_self (BSTR (&cmd)); gc_free (&gc); @@ -3814,6 +3836,21 @@ fork_dhcp_action (struct tuntap *tt) } void +fork_register_dns_action (struct tuntap *tt) +{ + if (tt && tt->options.register_dns) + { + struct gc_arena gc = gc_new (); + struct buffer cmd = alloc_buf_gc (256, &gc); + const int verb = 3; + + buf_printf (&cmd, "openvpn --verb %d --register-dns --rdns-internal", verb); + fork_to_self (BSTR (&cmd)); + gc_free (&gc); + } +} + +void open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt) { struct gc_arena gc = gc_new (); @@ -99,6 +99,8 @@ struct tuntap_options { bool dhcp_renew; bool dhcp_pre_release; bool dhcp_release; + + bool register_dns; }; #elif TARGET_LINUX @@ -335,6 +337,9 @@ void tun_show_debug (struct tuntap *tt); bool dhcp_release_by_adapter_index(const DWORD adapter_index); bool dhcp_renew_by_adapter_index (const DWORD adapter_index); +void fork_register_dns_action (struct tuntap *tt); +void ipconfig_register_dns (const struct env_set *es); + void tun_standby_init (struct tuntap *tt); bool tun_standby (struct tuntap *tt); @@ -1,5 +1,5 @@ dnl define the OpenVPN version -define(PRODUCT_VERSION,[2.1.1i]) +define(PRODUCT_VERSION,[2.1.1m]) dnl define the TAP version define(PRODUCT_TAP_ID,[tap0901]) define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9]) diff --git a/win/build_exe.py b/win/build_exe.py new file mode 100644 index 0000000..087f9a3 --- /dev/null +++ b/win/build_exe.py @@ -0,0 +1,15 @@ +from config import main as config_main
+from build import main as build_openvpn
+from build_ddk import main as build_ddk
+from sign import main as sign
+from make_dist import main as make_dist
+
+def main(config):
+ config_main(config)
+ build_openvpn()
+ make_dist(config, tap=False)
+
+# if we are run directly, and not loaded as a module
+if __name__ == "__main__":
+ from wb import config
+ main(config)
diff --git a/win/config.py b/win/config.py index 67c1d82..cf38cac 100644 --- a/win/config.py +++ b/win/config.py @@ -9,6 +9,7 @@ def main(config): out_fn=home_fn('msvc.mak'),
quote_begin='@',
quote_end='@',
+ if_prefix='!',
head_comment='# %s\n\n' % autogen)
# if we are run directly, and not loaded as a module
diff --git a/win/make_dist.py b/win/make_dist.py index 3011279..a6a0563 100644 --- a/win/make_dist.py +++ b/win/make_dist.py @@ -1,7 +1,7 @@ import os
from wb import home_fn, rm_rf, mkdir, cp_a, cp
-def main(config):
+def main(config, tap=True):
dist = config['DIST']
assert dist
dist = home_fn(dist)
@@ -13,8 +13,9 @@ def main(config): rm_rf(dist)
mkdir(dist)
mkdir(bin)
- mkdir(i386)
- mkdir(amd64)
+ if tap:
+ mkdir(i386)
+ mkdir(amd64)
# copy openvpn.exe and manifest
cp(home_fn('openvpn.exe'), bin)
@@ -28,25 +29,26 @@ def main(config): # copy MSVC CRT
cp_a(home_fn(config['MSVC_CRT']), bin)
- # copy TAP drivers
- for dir_name, dest in (('amd64', amd64), ('i386', i386)):
- dir = home_fn(os.path.join('tap-win32', dir_name))
- for dirpath, dirnames, filenames in os.walk(dir):
+ if tap:
+ # copy TAP drivers
+ for dir_name, dest in (('amd64', amd64), ('i386', i386)):
+ dir = home_fn(os.path.join('tap-win32', dir_name))
+ for dirpath, dirnames, filenames in os.walk(dir):
+ for f in filenames:
+ root, ext = os.path.splitext(f)
+ if ext in ('.inf', '.cat', '.sys'):
+ cp(os.path.join(dir, f), dest)
+ break
+
+ # copy tapinstall
+ dest = {'amd64' : amd64, 'i386' : i386}
+ for dirpath, dirnames, filenames in os.walk(home_fn('tapinstall')):
for f in filenames:
- root, ext = os.path.splitext(f)
- if ext in ('.inf', '.cat', '.sys'):
- cp(os.path.join(dir, f), dest)
- break
-
- # copy tapinstall
- dest = {'amd64' : amd64, 'i386' : i386}
- for dirpath, dirnames, filenames in os.walk(home_fn('tapinstall')):
- for f in filenames:
- if f == 'tapinstall.exe':
- dir_name = os.path.basename(dirpath)
- src = os.path.join(dirpath, f)
- if dir_name in dest:
- cp(src, dest[dir_name])
+ if f == 'tapinstall.exe':
+ dir_name = os.path.basename(dirpath)
+ src = os.path.join(dirpath, f)
+ if dir_name in dest:
+ cp(src, dest[dir_name])
# if we are run directly, and not loaded as a module
if __name__ == "__main__":
diff --git a/win/msvc.mak.in b/win/msvc.mak.in index 3f8102a..5d94a6e 100644 --- a/win/msvc.mak.in +++ b/win/msvc.mak.in @@ -23,17 +23,22 @@ LIB_DIRS = -LIBPATH:$(OPENSSL)\lib -LIBPATH:$(LZO)\lib EXE = openvpn.exe
CPP=cl.exe
-CPP_ARG_COMMON=/nologo /W3 /O2 -DWIN32 -DWIN32_LEAN_AND_MEAN -D_CONSOLE -D_MBCS -D_CRT_SECURE_NO_DEPRECATE $(INCLUDE_DIRS) /FD /c
-# release:
-CPP_PROJ=$(CPP_ARG_COMMON) /MD -DNDEBUG
-# debug:
-#CPP_PROJ=$(CPP_ARG_COMMON) /MDd /Zi /Od -D_DEBUG
+CPP_ARG_COMMON=/nologo /W3 -DWIN32 -DWIN32_LEAN_AND_MEAN -D_CONSOLE -D_MBCS -D_CRT_SECURE_NO_DEPRECATE $(INCLUDE_DIRS) /FD /c
LINK32=link.exe
-# release:
-LINK32_FLAGS=/nologo /subsystem:console /incremental:no /out:"$(EXE)"
+
+!ifdef PRODUCT_OPENVPN_DEBUG
# debug:
+CPP_PROJ=$(CPP_ARG_COMMON) /MD /Z7
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /opt:ref /opt:icf /debug /out:"$(EXE)"
+# old debug:
+#CPP_PROJ=$(CPP_ARG_COMMON) /MDd /Zi /Od -D_DEBUG
#LINK32_FLAGS=/nologo /subsystem:console /incremental:no /debug /out:"$(EXE)"
+!else
+# release:
+CPP_PROJ=$(CPP_ARG_COMMON) /O2 /MD -DNDEBUG
+LINK32_FLAGS=/nologo /subsystem:console /incremental:no /out:"$(EXE)"
+!endif
# HEADERS and OBJS definitions, automatically generated
@HEADERS_OBJS@
diff --git a/win/settings.in b/win/settings.in index 044834a..0e1bb1c 100644 --- a/win/settings.in +++ b/win/settings.in @@ -40,6 +40,9 @@ # Build debugging version of TAP driver ;!define PRODUCT_TAP_DEBUG +# Build debugging version of openvpn.exe +;!define PRODUCT_OPENVPN_DEBUG + # DDK path -- currently Windows 7 WDK !define DDK_PATH "c:/winddk/7600.16385.1" ;!define DDK_PATH "c:/winddk/6001.18002" @@ -971,10 +971,8 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i /* fill in STARTUPINFO struct */ GetStartupInfo(&start_info); start_info.cb = sizeof(start_info); - start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + start_info.dwFlags = STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_HIDE; - start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - start_info.hStdOutput = start_info.hStdError = GetStdHandle(STD_OUTPUT_HANDLE); if (CreateProcess (cmd, cl, NULL, NULL, FALSE, 0, env, NULL, &start_info, &proc_info)) { @@ -1042,10 +1040,8 @@ fork_to_self (const char *cmdline) /* fill in STARTUPINFO struct */ GetStartupInfo(&start_info); start_info.cb = sizeof(start_info); - start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + start_info.dwFlags = STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_HIDE; - start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - start_info.hStdOutput = start_info.hStdError = GetStdHandle(STD_OUTPUT_HANDLE); if (CreateProcess (self_exe, cl, NULL, NULL, FALSE, 0, NULL, NULL, &start_info, &proc_info)) { @@ -33,6 +33,7 @@ #define DEFAULT_WIN_SYS_PATH "C:\\WINDOWS" /* --win-sys default value */ #define NETSH_PATH_SUFFIX "\\system32\\netsh.exe" #define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe" +#define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe" /* * Win32-specific OpenVPN code, targetted at the mingw |