diff options
author | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2009-09-17 23:43:37 +0000 |
---|---|---|
committer | james <james@e7ae566f-a301-0410-adde-c780ea21d3b5> | 2009-09-17 23:43:37 +0000 |
commit | 673f583f76358b57e7f610084d3cb28bb2a9c4a2 (patch) | |
tree | 6d9c8bdd75055e42049937f69bdbcf9368eaab89 | |
parent | Modified client to send a PUSH_REQUEST message to server 1 second (diff) | |
download | openvpn-673f583f76358b57e7f610084d3cb28bb2a9c4a2.tar.xz |
The maximum number of "route" directives (specified in the config
file or pulled from a server) can now be configured via the new
"max-routes" directive.
Previously, the limit was set to 100 and fixed by a compile-time
constant. Now the limit is dynamic and can be modified by the
"max-routes" directive. If max-routes is not specified, the default
limit is 100.
Note that this change does not address the maximum size of the
pushed options string sent from server to client, which is still
controlled by the TLS_CHANNEL_BUF_SIZE compile-time constant.
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4967 e7ae566f-a301-0410-adde-c780ea21d3b5
-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, |