summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2009-09-17 23:43:37 +0000
committerjames <james@e7ae566f-a301-0410-adde-c780ea21d3b5>2009-09-17 23:43:37 +0000
commit673f583f76358b57e7f610084d3cb28bb2a9c4a2 (patch)
tree6d9c8bdd75055e42049937f69bdbcf9368eaab89
parent72bf37c7130719ce105d73600341379389c4031f (diff)
downloadopenvpn-673f583f76358b57e7f610084d3cb28bb2a9c4a2.tar.gz
openvpn-673f583f76358b57e7f610084d3cb28bb2a9c4a2.tar.xz
openvpn-673f583f76358b57e7f610084d3cb28bb2a9c4a2.zip
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.c6
-rw-r--r--buffer.h15
-rw-r--r--init.c2
-rw-r--r--openvpn.87
-rw-r--r--options.c23
-rw-r--r--options.h3
-rw-r--r--route.c42
-rw-r--r--route.h18
8 files changed, 86 insertions, 30 deletions
diff --git a/buffer.c b/buffer.c
index 15ab776..d448e5d 100644
--- a/buffer.c
+++ b/buffer.c
@@ -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;
}
diff --git a/buffer.h b/buffer.h
index 91b3cc6..b046a5c 100644
--- a/buffer.h
+++ b/buffer.h
@@ -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) \
diff --git a/init.c b/init.c
index 80b2849..a2821b9 100644
--- a/init.c
+++ b/init.c
@@ -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);
}
diff --git a/openvpn.8 b/openvpn.8
index 6e2541a..e9bc113 100644
--- a/openvpn.8
+++ b/openvpn.8
@@ -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
diff --git a/options.c b/options.c
index a7cab80..c1692e7 100644
--- a/options.c
+++ b/options.c
@@ -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);
diff --git a/options.h b/options.h
index 8cabf09..9210aca 100644
--- a/options.h
+++ b/options.h
@@ -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;
diff --git a/route.c b/route.c
index 3809c82..988c7ab 100644
--- a/route.c
+++ b/route.c
@@ -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 */
{
diff --git a/route.h b/route.h
index d827801..6f713ca 100644
--- a/route.h
+++ b/route.h
@@ -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,