static void
check_add_routes_action(struct context *c, const bool errors)
{
- do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ bool route_status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+
+ int flags = (errors ? ISC_ERRORS : 0);
+ flags |= (!route_status ? ISC_ROUTE_ERRORS : 0);
+
update_time();
event_timeout_clear(&c->c2.route_wakeup);
event_timeout_clear(&c->c2.route_wakeup_expire);
- initialization_sequence_completed(c, errors ? ISC_ERRORS : 0); /* client/p2p --route-delay was defined */
+ initialization_sequence_completed(c, flags); /* client/p2p --route-delay was defined */
}
static void
{
detail = "ERROR";
}
+ /* Flag route error only on platforms where trivial "already exists" errors
+ * are filtered out. Currently this is the case on Windows or if usng netlink.
+ */
+#if defined(_WIN32) || defined(ENABLE_SITNL)
+ else if (flags & ISC_ROUTE_ERRORS)
+ {
+ detail = "ROUTE_ERROR";
+ }
+#endif
CLEAR(local);
actual = &get_link_socket_info(c)->lsa->actual;
* Possibly add routes and/or call route-up script
* based on options.
*/
-void
+bool
do_route(const struct options *options,
struct route_list *route_list,
struct route_ipv6_list *route_ipv6_list,
struct env_set *es,
openvpn_net_ctx_t *ctx)
{
+ bool ret = true;
if (!options->route_noexec && ( route_list || route_ipv6_list ) )
{
- add_routes(route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS(options),
- es, ctx);
+ ret = add_routes(route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS(options),
+ es, ctx);
setenv_int(es, "redirect_gateway", route_did_redirect_default_gateway(route_list));
}
#ifdef ENABLE_MANAGEMENT
show_adapters(D_SHOW_NET|M_NOPREFIX);
}
#endif
+ return ret;
}
/*
}
static bool
-do_open_tun(struct context *c)
+do_open_tun(struct context *c, int *error_flags)
{
struct gc_arena gc = gc_new();
bool ret = false;
+ *error_flags = 0;
if (!can_preserve_tun(c->c1.tuntap))
{
if (route_order() == ROUTE_BEFORE_TUN)
{
/* Ignore route_delay, would cause ROUTE_BEFORE_TUN to be ignored */
- do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ bool status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ *error_flags |= (status ? 0 : ISC_ROUTE_ERRORS);
}
#ifdef TARGET_ANDROID
/* Store the old fd inside the fd so open_tun can use it */
/* possibly add routes */
if ((route_order() == ROUTE_AFTER_TUN) && (!c->options.route_delay_defined))
{
- do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
- c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ int status = do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list,
+ c->c1.tuntap, c->plugins, c->c2.es, &c->net_ctx);
+ *error_flags |= (status ? 0 : ISC_ROUTE_ERRORS);
}
ret = true;
bool
do_up(struct context *c, bool pulled_options, unsigned int option_types_found)
{
+ int error_flags = 0;
if (!c->c2.do_up_ran)
{
reset_coarse_timers(c);
/* if --up-delay specified, open tun, do ifconfig, and run up script now */
if (c->options.up_delay || PULL_DEFINED(&c->options))
{
- c->c2.did_open_tun = do_open_tun(c);
+ c->c2.did_open_tun = do_open_tun(c, &error_flags);
update_time();
/*
else
{
management_sleep(1);
- c->c2.did_open_tun = do_open_tun(c);
+ c->c2.did_open_tun = do_open_tun(c, &error_flags);
update_time();
}
}
}
else
{
- initialization_sequence_completed(c, 0); /* client/p2p --route-delay undefined */
+ initialization_sequence_completed(c, error_flags); /* client/p2p --route-delay undefined */
}
}
else if (c->options.mode == MODE_POINT_TO_POINT)
{
- initialization_sequence_completed(c, 0); /* client/p2p restart with --persist-tun */
+ initialization_sequence_completed(c, error_flags); /* client/p2p restart with --persist-tun */
}
c->c2.do_up_ran = true;
* open tun/tap device, ifconfig, run up script, etc. */
if (!(options->up_delay || PULL_DEFINED(options)) && (c->mode == CM_P2P || c->mode == CM_TOP))
{
- c->c2.did_open_tun = do_open_tun(c);
+ int error_flags = 0;
+ c->c2.did_open_tun = do_open_tun(c, &error_flags);
}
c->c2.frame_initial = c->c2.frame;
*/
void init_query_passwords(const struct context *c);
-void do_route(const struct options *options,
- struct route_list *route_list,
- struct route_ipv6_list *route_ipv6_list,
- const struct tuntap *tt,
- const struct plugin_list *plugins,
- struct env_set *es,
+bool do_route(const struct options *options, struct route_list *route_list,
+ struct route_ipv6_list *route_ipv6_list, const struct tuntap *tt,
+ const struct plugin_list *plugins, struct env_set *es,
openvpn_net_ctx_t *ctx);
void close_instance(struct context *c);
#define ISC_ERRORS (1<<0)
#define ISC_SERVER (1<<1)
+#define ISC_ROUTE_ERRORS (1<<2)
void initialization_sequence_completed(struct context *c, const unsigned int flags);
#ifdef ENABLE_MANAGEMENT
return ret;
}
-static void
+static bool
add_route3(in_addr_t network,
in_addr_t netmask,
in_addr_t gateway,
r.network = network;
r.netmask = netmask;
r.gateway = gateway;
- add_route(&r, tt, flags, rgi, es, ctx);
+ return add_route(&r, tt, flags, rgi, es, ctx);
}
static void
delete_route(&r, tt, flags, rgi, es, ctx);
}
-static void
+static bool
add_bypass_routes(struct route_bypass *rb,
in_addr_t gateway,
const struct tuntap *tt,
const struct env_set *es,
openvpn_net_ctx_t *ctx)
{
- int i;
- for (i = 0; i < rb->n_bypass; ++i)
+ int ret = true;
+ for (int i = 0; i < rb->n_bypass; ++i)
{
if (rb->bypass[i])
{
- add_route3(rb->bypass[i],
- IPV4_NETMASK_HOST,
- gateway,
- tt,
- flags | ROUTE_REF_GW,
- rgi,
- es,
- ctx);
+ ret = add_route3(rb->bypass[i], IPV4_NETMASK_HOST, gateway, tt,
+ flags | ROUTE_REF_GW, rgi, es, ctx) && ret;
}
}
+ return ret;
}
static void
}
}
-static void
+static bool
redirect_default_route_to_vpn(struct route_list *rl, const struct tuntap *tt,
unsigned int flags, const struct env_set *es,
openvpn_net_ctx_t *ctx)
{
const char err[] = "NOTE: unable to redirect IPv4 default gateway --";
+ bool ret = true;
if (rl && rl->flags & RG_ENABLE)
{
if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT) && (rl->flags & RG_REROUTE_GW))
{
msg(M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err);
+ ret = false;
}
/*
* check if a default route is defined, unless:
&& (rl->spec.flags & RTSA_REMOTE_HOST))
{
msg(M_WARN, "%s Cannot read current default gateway from system", err);
+ ret = false;
}
else
{
if ((rl->spec.flags & RTSA_REMOTE_HOST)
&& rl->spec.remote_host != IPV4_INVALID_ADDR)
{
- add_route3(rl->spec.remote_host,
- IPV4_NETMASK_HOST,
- rl->rgi.gateway.addr,
- tt,
- flags | ROUTE_REF_GW,
- &rl->rgi,
- es,
- ctx);
+ ret = add_route3(rl->spec.remote_host, IPV4_NETMASK_HOST,
+ rl->rgi.gateway.addr, tt, flags | ROUTE_REF_GW,
+ &rl->rgi, es, ctx);
rl->iflags |= RL_DID_LOCAL;
}
else
#endif /* ifndef TARGET_ANDROID */
/* route DHCP/DNS server traffic through original default gateway */
- add_bypass_routes(&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags,
- &rl->rgi, es, ctx);
+ ret = add_bypass_routes(&rl->spec.bypass, rl->rgi.gateway.addr, tt, flags,
+ &rl->rgi, es, ctx);
if (rl->flags & RG_REROUTE_GW)
{
if (rl->flags & RG_DEF1)
{
/* add new default route (1st component) */
- add_route3(0x00000000,
- 0x80000000,
- rl->spec.remote_endpoint,
- tt,
- flags,
- &rl->rgi,
- es,
- ctx);
+ ret = add_route3(0x00000000, 0x80000000, rl->spec.remote_endpoint,
+ tt, flags, &rl->rgi, es, ctx) && ret;
/* add new default route (2nd component) */
- add_route3(0x80000000,
- 0x80000000,
- rl->spec.remote_endpoint,
- tt,
- flags,
- &rl->rgi,
- es,
- ctx);
+ ret = add_route3(0x80000000, 0x80000000, rl->spec.remote_endpoint,
+ tt, flags, &rl->rgi, es, ctx) && ret;
}
else
{
}
/* add new default route */
- add_route3(0,
- 0,
- rl->spec.remote_endpoint,
- tt,
- flags,
- &rl->rgi,
- es,
- ctx);
+ ret = add_route3(0, 0, rl->spec.remote_endpoint, tt,
+ flags, &rl->rgi, es, ctx) && ret;
}
}
rl->iflags |= RL_DID_REDIRECT_DEFAULT_GATEWAY;
}
}
+ return ret;
}
static void
}
}
-void
+bool
add_routes(struct route_list *rl, struct route_ipv6_list *rl6,
const struct tuntap *tt, unsigned int flags,
const struct env_set *es, openvpn_net_ctx_t *ctx)
{
- redirect_default_route_to_vpn(rl, tt, flags, es, ctx);
+ bool ret = redirect_default_route_to_vpn(rl, tt, flags, es, ctx);
if (rl && !(rl->iflags & RL_ROUTES_ADDED) )
{
struct route_ipv4 *r;
{
delete_route(r, tt, flags, &rl->rgi, es, ctx);
}
- add_route(r, tt, flags, &rl->rgi, es, ctx);
+ ret = add_route(r, tt, flags, &rl->rgi, es, ctx) && ret;
}
rl->iflags |= RL_ROUTES_ADDED;
}
{
delete_route_ipv6(r, tt, flags, es, ctx);
}
- add_route_ipv6(r, tt, flags, es, ctx);
+ ret = add_route_ipv6(r, tt, flags, es, ctx) && ret;
}
rl6->iflags |= RL_ROUTES_ADDED;
}
+ return ret;
}
void
return rgi && (is_local_route == LR_MATCH || ((flags & ROUTE_REF_GW) && (rgi->flags & RGI_ON_LINK)));
}
-void
+bool
add_route(struct route_ipv4 *r,
const struct tuntap *tt,
unsigned int flags,
if (!(r->flags & RT_DEFINED))
{
- return;
+ return true; /* no error */
}
struct argv argv = argv_new();
{
openvpn_snprintf(out, sizeof(out), "%s %s %s", network, netmask, gateway);
}
- management_android_control(management, "ROUTE", out);
+ status = management_android_control(management, "ROUTE", out);
#elif defined (_WIN32)
{
gc_free(&gc);
/* release resources potentially allocated during route setup */
net_ctx_reset(ctx);
+
+ return (status != 0);
}
}
}
-void
+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)
if (!(r6->flags & RT_DEFINED) )
{
- return;
+ return true; /* no error */
}
struct argv argv = argv_new();
openvpn_snprintf(out, sizeof(out), "%s/%d %s", network, r6->netbits, device);
- management_android_control(management, "ROUTE6", out);
+ status = management_android_control(management, "ROUTE6", out);
#elif defined (_WIN32)
gc_free(&gc);
/* release resources potentially allocated during route setup */
net_ctx_reset(ctx);
+
+ return (status != 0);
}
static void
void route_ipv6_clear_host_bits( struct route_ipv6 *r6 );
-void add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx);
+bool add_route_ipv6(struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx);
void delete_route_ipv6(const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es, openvpn_net_ctx_t *ctx);
-void add_route(struct route_ipv4 *r,
- const struct tuntap *tt,
- unsigned int flags,
- const struct route_gateway_info *rgi,
- const struct env_set *es,
+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);
void add_route_to_option_list(struct route_option_list *l,
struct env_set *es,
const in_addr_t addr);
-void add_routes(struct route_list *rl,
- struct route_ipv6_list *rl6,
- const struct tuntap *tt,
- unsigned int flags,
- const struct env_set *es,
- openvpn_net_ctx_t *ctx);
+bool add_routes(struct route_list *rl, struct route_ipv6_list *rl6,
+ const struct tuntap *tt, unsigned int flags,
+ const struct env_set *es, openvpn_net_ctx_t *ctx);
void delete_routes(struct route_list *rl,
struct route_ipv6_list *rl6,