diff options
Diffstat (limited to '')
-rw-r--r-- | buffer.c | 6 | ||||
-rw-r--r-- | buffer.h | 15 | ||||
-rw-r--r-- | init.c | 2 | ||||
-rw-r--r-- | openvpn.8 | 7 | ||||
-rw-r--r-- | options.c | 23 | ||||
-rw-r--r-- | options.h | 3 | ||||
-rw-r--r-- | route.c | 42 | ||||
-rw-r--r-- | route.h | 18 |
8 files changed, 86 insertions, 30 deletions
@@ -33,11 +33,11 @@ #include "memdbg.h" size_t -array_mult_safe (const size_t m1, const size_t m2) +array_mult_safe (const size_t m1, const size_t m2, const size_t extra) { const size_t limit = 0xFFFFFFFF; - unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2; - if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(res > (unsigned long long)limit)) + unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra; + if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit)) msg (M_FATAL, "attemped allocation of excessively large array"); return (size_t) res; } @@ -88,7 +88,7 @@ bool buf_assign (struct buffer *dest, const struct buffer *src); void string_clear (char *str); int string_array_len (const char **array); -size_t array_mult_safe (const size_t m1, const size_t m2); +size_t array_mult_safe (const size_t m1, const size_t m2, const size_t extra); #define PA_BRACKET (1<<0) char *print_argv (const char **p, struct gc_arena *gc, const unsigned int flags); @@ -776,23 +776,28 @@ void out_of_memory (void); #define ALLOC_ARRAY(dptr, type, n) \ { \ - check_malloc_return ((dptr) = (type *) malloc (array_mult_safe (sizeof (type), (n)))); \ + check_malloc_return ((dptr) = (type *) malloc (array_mult_safe (sizeof (type), (n), 0))); \ } #define ALLOC_ARRAY_GC(dptr, type, n, gc) \ { \ - (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n)), false, (gc)); \ + (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n), 0), false, (gc)); \ } #define ALLOC_ARRAY_CLEAR(dptr, type, n) \ { \ ALLOC_ARRAY (dptr, type, n); \ - memset ((dptr), 0, (array_mult_safe (sizeof(type), (n)))); \ + memset ((dptr), 0, (array_mult_safe (sizeof(type), (n), 0))); \ } #define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc) \ { \ - (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n)), true, (gc)); \ + (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n), 0), true, (gc)); \ +} + +#define ALLOC_VAR_ARRAY_CLEAR_GC(dptr, type, atype, n, gc) \ +{ \ + (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (atype), (n), sizeof (type)), true, (gc)); \ } #define ALLOC_OBJ_GC(dptr, type, gc) \ @@ -847,7 +847,7 @@ static void do_alloc_route_list (struct context *c) { if (c->options.routes && !c->c1.route_list) - c->c1.route_list = new_route_list (&c->gc); + c->c1.route_list = new_route_list (c->options.max_routes, &c->gc); } @@ -946,6 +946,13 @@ table (not supported on all OSes). address if OpenVPN is being run in client mode, and is undefined in server mode. .\"********************************************************* .TP +.B --max-routes n +Allow a maximum number of n +.B --route +options to be specified, either in the local configuration file, +or pulled from an OpenVPN server. By default, n=100. +.\"********************************************************* +.TP .B --route-gateway gw|'dhcp' Specify a default gateway .B gw @@ -170,6 +170,8 @@ static const char usage_message[] = " netmask default: 255.255.255.255\n" " gateway default: taken from --route-gateway or --ifconfig\n" " Specify default by leaving blank or setting to \"nil\".\n" + "--max-routes n : Specify the maximum number of routes that may be defined\n" + " or pulled from a server.\n" "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n" "--route-metric m : Specify a default metric for use with --route.\n" "--route-delay n [w] : Delay n seconds after connection initiation before\n" @@ -680,6 +682,7 @@ init_options (struct options *o, const bool init_gc) o->mtu_discover_type = -1; o->mssfix = MSSFIX_DEFAULT; o->route_delay_window = 30; + o->max_routes = MAX_ROUTES_DEFAULT; o->resolve_retry_seconds = RESOLV_RETRY_INFINITE; #ifdef ENABLE_OCC o->occ = true; @@ -1075,7 +1078,7 @@ void rol_check_alloc (struct options *options) { if (!options->routes) - options->routes = new_route_option_list (&options->gc); + options->routes = new_route_option_list (options->max_routes, &options->gc); } #ifdef ENABLE_DEBUG @@ -1264,6 +1267,7 @@ show_settings (const struct options *o) SHOW_BOOL (route_delay_defined); SHOW_BOOL (route_nopull); SHOW_BOOL (route_gateway_via_dhcp); + SHOW_INT (max_routes); SHOW_BOOL (allow_pull_fqdn); if (o->routes) print_route_options (o->routes, D_SHOW_PARMS); @@ -2160,7 +2164,7 @@ pre_pull_save (struct options *o) o->pre_pull->foreign_option_index = o->foreign_option_index; if (o->routes) { - o->pre_pull->routes = *o->routes; + o->pre_pull->routes = clone_route_option_list(o->routes, &o->gc); o->pre_pull->routes_defined = true; } } @@ -2179,7 +2183,7 @@ pre_pull_restore (struct options *o) if (pp->routes_defined) { rol_check_alloc (o); - *o->routes = pp->routes; + copy_route_option_list (o->routes, pp->routes); } else o->routes = NULL; @@ -4343,6 +4347,19 @@ add_option (struct options *options, } add_route_to_option_list (options->routes, p[1], p[2], p[3], p[4]); } + else if (streq (p[0], "max-routes") && p[1]) + { + int max_routes; + + VERIFY_PERMISSION (OPT_P_GENERAL); + max_routes = atoi (p[1]); + if (max_routes < 0 || max_routes > 100000000) + { + msg (msglevel, "--max-routes parameter is out of range"); + goto err; + } + options->max_routes = max_routes; + } else if (streq (p[0], "route-gateway") && p[1]) { VERIFY_PERMISSION (OPT_P_ROUTE_EXTRAS); @@ -75,7 +75,7 @@ struct options_pre_pull struct tuntap_options tuntap_options; bool routes_defined; - struct route_option_list routes; + struct route_option_list *routes; int foreign_option_index; }; @@ -306,6 +306,7 @@ struct options int route_delay; int route_delay_window; bool route_delay_defined; + int max_routes; struct route_option_list *routes; bool route_nopull; bool route_gateway_via_dhcp; @@ -80,18 +80,38 @@ add_bypass_address (struct route_bypass *rb, const in_addr_t a) } struct route_option_list * -new_route_option_list (struct gc_arena *a) +new_route_option_list (const int max_routes, struct gc_arena *a) { struct route_option_list *ret; - ALLOC_OBJ_CLEAR_GC (ret, struct route_option_list, a); + ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_option_list, struct route_option, max_routes, a); + ret->capacity = max_routes; return ret; } +struct route_option_list * +clone_route_option_list (const struct route_option_list *src, struct gc_arena *a) +{ + const size_t rl_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list)); + struct route_option_list *ret = gc_malloc (rl_size, false, a); + memcpy (ret, src, rl_size); + return ret; +} + +void +copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src) +{ + const size_t src_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list)); + if (src->n > dest->capacity) + msg (M_FATAL, PACKAGE_NAME " ROUTE: (copy) number of route options in src (%d) is greater than route list capacity in dest (%d)", src->n, dest->capacity); + memcpy (dest, src, src_size); +} + struct route_list * -new_route_list (struct gc_arena *a) +new_route_list (const int max_routes, struct gc_arena *a) { struct route_list *ret; - ALLOC_OBJ_CLEAR_GC (ret, struct route_list, a); + ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route, max_routes, a); + ret->capacity = max_routes; return ret; } @@ -317,9 +337,9 @@ add_route_to_option_list (struct route_option_list *l, const char *metric) { struct route_option *ro; - if (l->n >= MAX_ROUTES) - msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes", - MAX_ROUTES); + if (l->n >= l->capacity) + msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes -- please increase the max-routes option in the client configuration file", + l->capacity); ro = &l->routes[l->n]; ro->network = network; ro->netmask = netmask; @@ -331,7 +351,10 @@ add_route_to_option_list (struct route_option_list *l, void clear_route_list (struct route_list *rl) { - CLEAR (*rl); + const int capacity = rl->capacity; + const size_t rl_size = array_mult_safe (sizeof(struct route), capacity, sizeof(struct route_list)); + memset(rl, 0, rl_size); + rl->capacity = capacity; } void @@ -415,7 +438,8 @@ init_route_list (struct route_list *rl, else rl->spec.remote_endpoint_defined = false; - ASSERT (opt->n >= 0 && opt->n < MAX_ROUTES); + 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 */ { @@ -32,7 +32,7 @@ #include "tun.h" #include "misc.h" -#define MAX_ROUTES 100 +#define MAX_ROUTES_DEFAULT 100 #ifdef WIN32 /* @@ -86,9 +86,10 @@ struct route_option { #define RG_AUTO_LOCAL (1<<6) struct route_option_list { - int n; unsigned int flags; - struct route_option routes[MAX_ROUTES]; + int capacity; + int n; + struct route_option routes[EMPTY_ARRAY_SIZE]; }; struct route { @@ -107,8 +108,9 @@ struct route_list { unsigned int flags; bool did_redirect_default_gateway; bool did_local; + int capacity; int n; - struct route routes[MAX_ROUTES]; + struct route routes[EMPTY_ARRAY_SIZE]; }; #if P2MP @@ -120,9 +122,11 @@ struct iroute { }; #endif -struct route_option_list *new_route_option_list (struct gc_arena *a); +struct route_option_list *new_route_option_list (const int max_routes, struct gc_arena *a); +struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a); +void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src); -struct route_list *new_route_list (struct gc_arena *a); +struct route_list *new_route_list (const int max_routes, struct gc_arena *a); void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); @@ -132,8 +136,6 @@ void add_route_to_option_list (struct route_option_list *l, const char *gateway, const char *metric); -void clear_route_list (struct route_list *rl); - bool init_route_list (struct route_list *rl, const struct route_option_list *opt, const char *remote_endpoint, |