I'm trying to put together a patch to implement my desired behaviour wrt resolv-retry and multiple remote hosts.
So far, I've made the following changes: Setting the default resolv-retry count: * Create a new constant, RESOLV_RETRY_UNSET * Initialize resolve_retry_seconds to RESOLV_RETRY_UNSET rather than RESOLV_RETRY_INFINITE * In options_postprocess(), set resolve_retry_seconds appropriately based on the number of remote hosts provided Retrying on DNS failures with resolv-retry 0 and multiple hosts: * Modify resolve_remote() to accept a boolean argument multiple_remotes * In the phase-specific handlers within that same function, treat multiple_remotes as an alternative to resolve_retry_seconds when determining whether GETADDR_FATAL and GETADDR_MENTION_RESOLVE_RETRY should be set (in phase 1) and whether to fail out with an assertion error (in phase 2). Thing is, this doesn't actually work: When I run it in a test case in with the first remote specified by DNS and the second host specified by IP, it tries to resolve the first host in phase 1; fails; tries again in phase 2; and fails again (fatally, there, because GETADDR_FATAL is set). I presume that it's supposed to loop around to trying phase1 with the next host if getaddr fails (on account of using all the available retries on the current host) rather than proceeding to phase 2 -- but what's the mechanism? My work-in-progress, known-broken patch is attached, just for reference.
diff -ru openvpn-2.0_rc19/init.c openvpn-2.0_rc19.patched/init.c --- openvpn-2.0_rc19/init.c 2005-02-17 14:36:08.000000000 -0600 +++ openvpn-2.0_rc19.patched/init.c 2005-04-06 18:38:57.360000000 -0500 @@ -1687,7 +1687,8 @@ do_init_socket_2 (struct context *c) { link_socket_init_phase2 (c->c2.link_socket, &c->c2.frame, - &c->sig->signal_received); + &c->sig->signal_received, + remote_list_len(c->c1.remote_list) > 1); } /* diff -ru openvpn-2.0_rc19/options.c openvpn-2.0_rc19.patched/options.c --- openvpn-2.0_rc19/options.c 2005-02-10 20:18:08.000000000 -0600 +++ openvpn-2.0_rc19.patched/options.c 2005-04-06 19:08:05.610000000 -0500 @@ -533,7 +533,7 @@ o->mtu_discover_type = -1; o->mssfix = MSSFIX_DEFAULT; o->route_delay_window = 30; - o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; + o->resolve_retry_seconds = RESOLV_RETRY_UNSET; #ifdef ENABLE_OCC o->occ = true; #endif @@ -1203,6 +1203,19 @@ } /* + * Set resolv_retry value if not provided + */ + if ((options->resolve_retry_seconds == RESOLV_RETRY_UNSET) && + (remote_list_len(options->remote_list) > 1)) + { + options->resolve_retry_seconds = RESOLV_RETRY_INFINITE; + } + else + { + options->resolve_retry_seconds = 0; + } + + /* * If --mssfix is supplied without a parameter, default * it to --fragment value, if --fragment is specified. */ diff -ru openvpn-2.0_rc19/socket.c openvpn-2.0_rc19.patched/socket.c --- openvpn-2.0_rc19/socket.c 2005-02-05 02:42:13.000000000 -0600 +++ openvpn-2.0_rc19.patched/socket.c 2005-04-06 18:39:22.320000000 -0500 @@ -746,7 +746,8 @@ resolve_remote (struct link_socket *sock, int phase, const char **remote_dynamic, - volatile int *signal_received) + volatile int *signal_received, + bool multiple_remotes) { struct gc_arena gc = gc_new (); @@ -766,7 +767,7 @@ if (phase == 1) { - if (sock->resolve_retry_seconds) + if (sock->resolve_retry_seconds || multiple_remotes) { flags = GETADDR_RESOLVE; retry = 0; @@ -779,7 +780,7 @@ } else if (phase == 2) { - if (sock->resolve_retry_seconds) + if (sock->resolve_retry_seconds || multiple_remotes) { flags = GETADDR_RESOLVE | GETADDR_FATAL; retry = sock->resolve_retry_seconds; @@ -1007,7 +1008,7 @@ { create_socket (sock); resolve_bind_local (sock); - resolve_remote (sock, 1, NULL, NULL); + resolve_remote (sock, 1, NULL, NULL, (remote_list_len(remote_list) > 1)); } } @@ -1015,7 +1016,8 @@ void link_socket_init_phase2 (struct link_socket *sock, const struct frame *frame, - volatile int *signal_received) + volatile int *signal_received, + bool multiple_remotes) { struct gc_arena gc = gc_new (); const char *remote_dynamic = NULL; @@ -1053,7 +1055,7 @@ } else { - resolve_remote (sock, 2, &remote_dynamic, signal_received); + resolve_remote (sock, 2, &remote_dynamic, signal_received, multiple_remotes); if (*signal_received) goto done; @@ -1159,7 +1161,7 @@ sock->info.lsa->actual.sin_addr.s_addr = 0; sock->info.lsa->remote.sin_addr.s_addr = 0; - resolve_remote (sock, 1, NULL, signal_received); + resolve_remote (sock, 1, NULL, signal_received, multiple_remotes); if (*signal_received) goto done; diff -ru openvpn-2.0_rc19/socket.h openvpn-2.0_rc19.patched/socket.h --- openvpn-2.0_rc19/socket.h 2005-02-05 02:36:31.000000000 -0600 +++ openvpn-2.0_rc19.patched/socket.h 2005-04-06 18:34:46.120000000 -0500 @@ -47,6 +47,7 @@ * represents. */ #define RESOLV_RETRY_INFINITE 1000000000 +#define RESOLV_RETRY_UNSET 999999999 #define REMOTE_LIST_SIZE 64 @@ -281,7 +282,8 @@ void link_socket_init_phase2 (struct link_socket *sock, const struct frame *frame, - volatile int *signal_received); + volatile int *signal_received, + bool multiple_remotes); void link_socket_post_fork (const struct link_socket *sock, const struct sockaddr_in *remote);