Browse code

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

james authored on 2009/09/18 08:43:37
Showing 8 changed files
... ...
@@ -33,11 +33,11 @@
33 33
 #include "memdbg.h"
34 34
 
35 35
 size_t
36
-array_mult_safe (const size_t m1, const size_t m2)
36
+array_mult_safe (const size_t m1, const size_t m2, const size_t extra)
37 37
 {
38 38
   const size_t limit = 0xFFFFFFFF;
39
-  unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2;
40
-  if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(res > (unsigned long long)limit))
39
+  unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra;
40
+  if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit))
41 41
     msg (M_FATAL, "attemped allocation of excessively large array");
42 42
   return (size_t) res;
43 43
 }
... ...
@@ -88,7 +88,7 @@ bool buf_assign (struct buffer *dest, const struct buffer *src);
88 88
 void string_clear (char *str);
89 89
 int string_array_len (const char **array);
90 90
 
91
-size_t array_mult_safe (const size_t m1, const size_t m2);
91
+size_t array_mult_safe (const size_t m1, const size_t m2, const size_t extra);
92 92
 
93 93
 #define PA_BRACKET (1<<0)
94 94
 char *print_argv (const char **p, struct gc_arena *gc, const unsigned int flags);
... ...
@@ -776,23 +776,28 @@ void out_of_memory (void);
776 776
 
777 777
 #define ALLOC_ARRAY(dptr, type, n) \
778 778
 { \
779
-  check_malloc_return ((dptr) = (type *) malloc (array_mult_safe (sizeof (type), (n)))); \
779
+  check_malloc_return ((dptr) = (type *) malloc (array_mult_safe (sizeof (type), (n), 0))); \
780 780
 }
781 781
 
782 782
 #define ALLOC_ARRAY_GC(dptr, type, n, gc) \
783 783
 { \
784
-  (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n)), false, (gc)); \
784
+  (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n), 0), false, (gc)); \
785 785
 }
786 786
 
787 787
 #define ALLOC_ARRAY_CLEAR(dptr, type, n) \
788 788
 { \
789 789
   ALLOC_ARRAY (dptr, type, n); \
790
-  memset ((dptr), 0, (array_mult_safe (sizeof(type), (n)))); \
790
+  memset ((dptr), 0, (array_mult_safe (sizeof(type), (n), 0)));	\
791 791
 }
792 792
 
793 793
 #define ALLOC_ARRAY_CLEAR_GC(dptr, type, n, gc) \
794 794
 { \
795
-  (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n)), true, (gc)); \
795
+  (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (type), (n), 0), true, (gc)); \
796
+}
797
+
798
+#define ALLOC_VAR_ARRAY_CLEAR_GC(dptr, type, atype, n, gc)	\
799
+{ \
800
+  (dptr) = (type *) gc_malloc (array_mult_safe (sizeof (atype), (n), sizeof (type)), true, (gc)); \
796 801
 }
797 802
 
798 803
 #define ALLOC_OBJ_GC(dptr, type, gc) \
... ...
@@ -847,7 +847,7 @@ static void
847 847
 do_alloc_route_list (struct context *c)
848 848
 {
849 849
   if (c->options.routes && !c->c1.route_list)
850
-    c->c1.route_list = new_route_list (&c->gc);
850
+    c->c1.route_list = new_route_list (c->options.max_routes, &c->gc);
851 851
 }
852 852
 
853 853
 
... ...
@@ -946,6 +946,13 @@ table (not supported on all OSes).
946 946
 address if OpenVPN is being run in client mode, and is undefined in server mode.
947 947
 .\"*********************************************************
948 948
 .TP
949
+.B --max-routes n
950
+Allow a maximum number of n
951
+.B --route
952
+options to be specified, either in the local configuration file,
953
+or pulled from an OpenVPN server.  By default, n=100.
954
+.\"*********************************************************
955
+.TP
949 956
 .B --route-gateway gw|'dhcp'
950 957
 Specify a default gateway
951 958
 .B gw
... ...
@@ -170,6 +170,8 @@ static const char usage_message[] =
170 170
   "                  netmask default: 255.255.255.255\n"
171 171
   "                  gateway default: taken from --route-gateway or --ifconfig\n"
172 172
   "                  Specify default by leaving blank or setting to \"nil\".\n"
173
+  "--max-routes n :  Specify the maximum number of routes that may be defined\n"
174
+  "                  or pulled from a server.\n"
173 175
   "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n"
174 176
   "--route-metric m : Specify a default metric for use with --route.\n"
175 177
   "--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)
680 680
   o->mtu_discover_type = -1;
681 681
   o->mssfix = MSSFIX_DEFAULT;
682 682
   o->route_delay_window = 30;
683
+  o->max_routes = MAX_ROUTES_DEFAULT;
683 684
   o->resolve_retry_seconds = RESOLV_RETRY_INFINITE;
684 685
 #ifdef ENABLE_OCC
685 686
   o->occ = true;
... ...
@@ -1075,7 +1078,7 @@ void
1075 1075
 rol_check_alloc (struct options *options)
1076 1076
 {
1077 1077
   if (!options->routes)
1078
-    options->routes = new_route_option_list (&options->gc);
1078
+    options->routes = new_route_option_list (options->max_routes, &options->gc);
1079 1079
 }
1080 1080
 
1081 1081
 #ifdef ENABLE_DEBUG
... ...
@@ -1264,6 +1267,7 @@ show_settings (const struct options *o)
1264 1264
   SHOW_BOOL (route_delay_defined);
1265 1265
   SHOW_BOOL (route_nopull);
1266 1266
   SHOW_BOOL (route_gateway_via_dhcp);
1267
+  SHOW_INT (max_routes);
1267 1268
   SHOW_BOOL (allow_pull_fqdn);
1268 1269
   if (o->routes)
1269 1270
     print_route_options (o->routes, D_SHOW_PARMS);
... ...
@@ -2160,7 +2164,7 @@ pre_pull_save (struct options *o)
2160 2160
       o->pre_pull->foreign_option_index = o->foreign_option_index;
2161 2161
       if (o->routes)
2162 2162
 	{
2163
-	  o->pre_pull->routes = *o->routes;
2163
+	  o->pre_pull->routes = clone_route_option_list(o->routes, &o->gc);
2164 2164
 	  o->pre_pull->routes_defined = true;
2165 2165
 	}
2166 2166
     }
... ...
@@ -2179,7 +2183,7 @@ pre_pull_restore (struct options *o)
2179 2179
       if (pp->routes_defined)
2180 2180
 	{
2181 2181
 	  rol_check_alloc (o);
2182
-	  *o->routes = pp->routes;
2182
+	  copy_route_option_list (o->routes, pp->routes);
2183 2183
 	}
2184 2184
       else
2185 2185
 	o->routes = NULL;
... ...
@@ -4343,6 +4347,19 @@ add_option (struct options *options,
4343 4343
 	}
4344 4344
       add_route_to_option_list (options->routes, p[1], p[2], p[3], p[4]);
4345 4345
     }
4346
+  else if (streq (p[0], "max-routes") && p[1])
4347
+    {
4348
+      int max_routes;
4349
+
4350
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4351
+      max_routes = atoi (p[1]);
4352
+      if (max_routes < 0 || max_routes > 100000000)
4353
+	{
4354
+	  msg (msglevel, "--max-routes parameter is out of range");
4355
+	  goto err;
4356
+	}
4357
+      options->max_routes = max_routes;
4358
+    }
4346 4359
   else if (streq (p[0], "route-gateway") && p[1])
4347 4360
     {
4348 4361
       VERIFY_PERMISSION (OPT_P_ROUTE_EXTRAS);
... ...
@@ -75,7 +75,7 @@ struct options_pre_pull
75 75
   struct tuntap_options tuntap_options;
76 76
 
77 77
   bool routes_defined;
78
-  struct route_option_list routes;
78
+  struct route_option_list *routes;
79 79
 
80 80
   int foreign_option_index;
81 81
 };
... ...
@@ -306,6 +306,7 @@ struct options
306 306
   int route_delay;
307 307
   int route_delay_window;
308 308
   bool route_delay_defined;
309
+  int max_routes;
309 310
   struct route_option_list *routes;
310 311
   bool route_nopull;
311 312
   bool route_gateway_via_dhcp;
... ...
@@ -80,18 +80,38 @@ add_bypass_address (struct route_bypass *rb, const in_addr_t a)
80 80
 }
81 81
 
82 82
 struct route_option_list *
83
-new_route_option_list (struct gc_arena *a)
83
+new_route_option_list (const int max_routes, struct gc_arena *a)
84 84
 {
85 85
   struct route_option_list *ret;
86
-  ALLOC_OBJ_CLEAR_GC (ret, struct route_option_list, a);
86
+  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_option_list, struct route_option, max_routes, a);
87
+  ret->capacity = max_routes;
87 88
   return ret;
88 89
 }
89 90
 
91
+struct route_option_list *
92
+clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
93
+{
94
+  const size_t rl_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
95
+  struct route_option_list *ret = gc_malloc (rl_size, false, a);
96
+  memcpy (ret, src, rl_size);
97
+  return ret;
98
+}
99
+
100
+void
101
+copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src)
102
+{
103
+  const size_t src_size = array_mult_safe (sizeof(struct route_option), src->capacity, sizeof(struct route_option_list));
104
+  if (src->n > dest->capacity)
105
+    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);
106
+  memcpy (dest, src, src_size);
107
+}
108
+
90 109
 struct route_list *
91
-new_route_list (struct gc_arena *a)
110
+new_route_list (const int max_routes, struct gc_arena *a)
92 111
 {
93 112
   struct route_list *ret;
94
-  ALLOC_OBJ_CLEAR_GC (ret, struct route_list, a);
113
+  ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route, max_routes, a);
114
+  ret->capacity = max_routes;
95 115
   return ret;
96 116
 }
97 117
 
... ...
@@ -317,9 +337,9 @@ add_route_to_option_list (struct route_option_list *l,
317 317
 			  const char *metric)
318 318
 {
319 319
   struct route_option *ro;
320
-  if (l->n >= MAX_ROUTES)
321
-    msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes",
322
-	 MAX_ROUTES);
320
+  if (l->n >= l->capacity)
321
+    msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d routes -- please increase the max-routes option in the client configuration file",
322
+	 l->capacity);
323 323
   ro = &l->routes[l->n];
324 324
   ro->network = network;
325 325
   ro->netmask = netmask;
... ...
@@ -331,7 +351,10 @@ add_route_to_option_list (struct route_option_list *l,
331 331
 void
332 332
 clear_route_list (struct route_list *rl)
333 333
 {
334
-  CLEAR (*rl);
334
+  const int capacity = rl->capacity;
335
+  const size_t rl_size = array_mult_safe (sizeof(struct route), capacity, sizeof(struct route_list));
336
+  memset(rl, 0, rl_size);
337
+  rl->capacity = capacity;
335 338
 }
336 339
 
337 340
 void
... ...
@@ -415,7 +438,8 @@ init_route_list (struct route_list *rl,
415 415
   else
416 416
     rl->spec.remote_endpoint_defined = false;
417 417
 
418
-  ASSERT (opt->n >= 0 && opt->n < MAX_ROUTES);
418
+  if (!(opt->n >= 0 && opt->n <= rl->capacity))
419
+    msg (M_FATAL, PACKAGE_NAME " ROUTE: (init) number of route options (%d) is greater than route list capacity (%d)", opt->n, rl->capacity);
419 420
 
420 421
   /* parse the routes from opt to rl */
421 422
   {
... ...
@@ -32,7 +32,7 @@
32 32
 #include "tun.h"
33 33
 #include "misc.h"
34 34
 
35
-#define MAX_ROUTES 100
35
+#define MAX_ROUTES_DEFAULT 100
36 36
 
37 37
 #ifdef WIN32
38 38
 /*
... ...
@@ -86,9 +86,10 @@ struct route_option {
86 86
 #define RG_AUTO_LOCAL     (1<<6)
87 87
 
88 88
 struct route_option_list {
89
-  int n;
90 89
   unsigned int flags;
91
-  struct route_option routes[MAX_ROUTES];
90
+  int capacity;
91
+  int n;
92
+  struct route_option routes[EMPTY_ARRAY_SIZE];
92 93
 };
93 94
 
94 95
 struct route {
... ...
@@ -107,8 +108,9 @@ struct route_list {
107 107
   unsigned int flags;
108 108
   bool did_redirect_default_gateway;
109 109
   bool did_local;
110
+  int capacity;
110 111
   int n;
111
-  struct route routes[MAX_ROUTES];
112
+  struct route routes[EMPTY_ARRAY_SIZE];
112 113
 };
113 114
 
114 115
 #if P2MP
... ...
@@ -120,9 +122,11 @@ struct iroute {
120 120
 };
121 121
 #endif
122 122
 
123
-struct route_option_list *new_route_option_list (struct gc_arena *a);
123
+struct route_option_list *new_route_option_list (const int max_routes, struct gc_arena *a);
124
+struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a);
125
+void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src);
124 126
 
125
-struct route_list *new_route_list (struct gc_arena *a);
127
+struct route_list *new_route_list (const int max_routes, struct gc_arena *a);
126 128
 
127 129
 void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
128 130
 
... ...
@@ -132,8 +136,6 @@ void add_route_to_option_list (struct route_option_list *l,
132 132
 			       const char *gateway,
133 133
 			       const char *metric);
134 134
 
135
-void clear_route_list (struct route_list *rl);
136
-
137 135
 bool init_route_list (struct route_list *rl,
138 136
 		      const struct route_option_list *opt,
139 137
 		      const char *remote_endpoint,