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
This commit is contained in:
james 2009-09-17 23:43:37 +00:00
parent 72bf37c713
commit 673f583f76
8 changed files with 86 additions and 30 deletions

View file

@ -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;
}

View file

@ -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) \

2
init.c
View file

@ -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);
}

View file

@ -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

View file

@ -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);

View file

@ -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;

42
route.c
View file

@ -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 */
{

18
route.h
View file

@ -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,