Browse code

Eliminated the limitation on the number of options that can be pushed to clients, including routes. Previously, all pushed options needed to fit within a 1024 byte options string.

Remember that to make use of this feature to allow many routes to
be pushed to clients, the client config file must specify the
max-routes option, and the number of pushed routes cannot exceed
this limit. Also, both server and client must include this commit.


git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4991 e7ae566f-a301-0410-adde-c780ea21d3b5

james authored on 2009/09/27 11:12:15
Showing 16 changed files
... ...
@@ -123,6 +123,7 @@ openvpn_SOURCES = \
123 123
 	ieproxy.h ieproxy.c \
124 124
         ps.c ps.h \
125 125
 	push.c push.h \
126
+	pushlist.h \
126 127
 	reliable.c reliable.h \
127 128
 	route.c route.h \
128 129
 	schedule.c schedule.h \
... ...
@@ -74,12 +74,10 @@ typedef unsigned long ptr_type;
74 74
 #define CCD_DEFAULT "DEFAULT"
75 75
 
76 76
 /*
77
- * This parameter controls the TLS channel buffer size.  Among
78
- * other things, this buffer must be large enough to contain
79
- * the full --push/--pull list.  If you increase it, do so
80
- * on both server and client.
77
+ * This parameter controls the TLS channel buffer size and the
78
+ * maximum size of a single TLS message (cleartext).
81 79
  */
82
-#define TLS_CHANNEL_BUF_SIZE 2048
80
+#define TLS_CHANNEL_BUF_SIZE 1024
83 81
 
84 82
 /*
85 83
  * A sort of pseudo-filename for data provided inline within
... ...
@@ -1796,4 +1796,49 @@ free_ssl_lib (void)
1796 1796
 }
1797 1797
 
1798 1798
 #endif /* USE_SSL */
1799
+
1800
+/*
1801
+ * md5 functions
1802
+ */
1803
+
1804
+void
1805
+md5_state_init (struct md5_state *s)
1806
+{
1807
+  MD5_Init (&s->ctx);
1808
+}
1809
+
1810
+void
1811
+md5_state_update (struct md5_state *s, void *data, size_t len)
1812
+{
1813
+  MD5_Update (&s->ctx, data, len);
1814
+}
1815
+
1816
+void
1817
+md5_state_final (struct md5_state *s, struct md5_digest *out)
1818
+{
1819
+  MD5_Final (out->digest, &s->ctx);
1820
+}
1821
+
1822
+void
1823
+md5_digest_clear (struct md5_digest *digest)
1824
+{
1825
+  CLEAR (*digest);
1826
+}
1827
+
1828
+bool
1829
+md5_digest_defined (const struct md5_digest *digest)
1830
+{
1831
+  int i;
1832
+  for (i = 0; i < MD5_DIGEST_LENGTH; ++i)
1833
+    if (digest->digest[i])
1834
+      return true;
1835
+  return false;
1836
+}
1837
+
1838
+bool
1839
+md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2)
1840
+{
1841
+  return memcmp(d1->digest, d2->digest, MD5_DIGEST_LENGTH) == 0;
1842
+}
1843
+
1799 1844
 #endif /* USE_CRYPTO */
... ...
@@ -398,5 +398,24 @@ key_ctx_bi_defined(const struct key_ctx_bi* key)
398 398
   return key->encrypt.cipher || key->encrypt.hmac || key->decrypt.cipher || key->decrypt.hmac;
399 399
 }
400 400
 
401
+/*
402
+ * md5 functions
403
+ */
404
+
405
+struct md5_state {
406
+  MD5_CTX ctx;
407
+};
408
+
409
+struct md5_digest {
410
+  uint8_t digest [MD5_DIGEST_LENGTH];
411
+};
412
+
413
+void md5_state_init (struct md5_state *s);
414
+void md5_state_update (struct md5_state *s, void *data, size_t len);
415
+void md5_state_final (struct md5_state *s, struct md5_digest *out);
416
+void md5_digest_clear (struct md5_digest *digest);
417
+bool md5_digest_defined (const struct md5_digest *digest);
418
+bool md5_digest_equal (const struct md5_digest *d1, const struct md5_digest *d2);
419
+
401 420
 #endif /* USE_CRYPTO */
402 421
 #endif /* CRYPTO_H */
... ...
@@ -33,7 +33,7 @@
33 33
 #ifdef ENABLE_PKCS11
34 34
 #define ERR_BUF_SIZE 8192
35 35
 #else
36
-#define ERR_BUF_SIZE 1024
36
+#define ERR_BUF_SIZE 1280
37 37
 #endif
38 38
 
39 39
 struct gc_arena;
... ...
@@ -992,15 +992,12 @@ do_route (const struct options *options,
992 992
  */
993 993
 #if P2MP
994 994
 static void
995
-save_pulled_options_string (struct context *c, const char *newstring)
995
+save_pulled_options_digest (struct context *c, const struct md5_digest *newdigest)
996 996
 {
997
-  if (c->c1.pulled_options_string_save)
998
-    free (c->c1.pulled_options_string_save);
999
-
1000
-  c->c1.pulled_options_string_save = NULL;
1001
-
1002
-  if (newstring)
1003
-    c->c1.pulled_options_string_save = string_alloc (newstring, NULL);
997
+  if (newdigest)
998
+    c->c1.pulled_options_digest_save = *newdigest;
999
+  else
1000
+    md5_digest_clear (&c->c1.pulled_options_digest_save);
1004 1001
 }
1005 1002
 #endif
1006 1003
 
... ...
@@ -1144,7 +1141,7 @@ do_close_tun_simple (struct context *c)
1144 1144
   c->c1.tuntap = NULL;
1145 1145
   c->c1.tuntap_owned = false;
1146 1146
 #if P2MP
1147
-  save_pulled_options_string (c, NULL); /* delete C1-saved pulled_options_string */
1147
+  save_pulled_options_digest (c, NULL); /* delete C1-saved pulled_options_digest */
1148 1148
 #endif
1149 1149
 }
1150 1150
 
... ...
@@ -1244,8 +1241,8 @@ do_up (struct context *c, bool pulled_options, unsigned int option_types_found)
1244 1244
 	  if (!c->c2.did_open_tun
1245 1245
 	      && PULL_DEFINED (&c->options)
1246 1246
 	      && c->c1.tuntap
1247
-	      && (!c->c1.pulled_options_string_save || !c->c2.pulled_options_string
1248
-		  || strcmp (c->c1.pulled_options_string_save, c->c2.pulled_options_string)))
1247
+	      && (!md5_digest_defined (&c->c1.pulled_options_digest_save) || !md5_digest_defined (&c->c2.pulled_options_digest)
1248
+		  || !md5_digest_equal (&c->c1.pulled_options_digest_save, &c->c2.pulled_options_digest)))
1249 1249
 	    {
1250 1250
 	      /* if so, close tun, delete routes, then reinitialize tun and add routes */
1251 1251
 	      msg (M_INFO, "NOTE: Pulled options changed on restart, will need to close and reopen TUN/TAP device.");
... ...
@@ -1260,7 +1257,7 @@ do_up (struct context *c, bool pulled_options, unsigned int option_types_found)
1260 1260
       if (c->c2.did_open_tun)
1261 1261
 	{
1262 1262
 #if P2MP
1263
-	  save_pulled_options_string (c, c->c2.pulled_options_string);
1263
+	  save_pulled_options_digest (c, &c->c2.pulled_options_digest);
1264 1264
 #endif
1265 1265
 
1266 1266
 	  /* if --route-delay was specified, start timer */
... ...
@@ -189,8 +189,8 @@ struct context_1
189 189
   bool ifconfig_pool_persist_owned;
190 190
 #endif
191 191
 
192
-  /* if client mode, option strings we pulled from server */
193
-  char *pulled_options_string_save;
192
+  /* if client mode, hash of option strings we pulled from server */
193
+  struct md5_digest pulled_options_digest_save;
194 194
 
195 195
   /* save user/pass for authentication */
196 196
   struct user_pass *auth_user_pass;
... ...
@@ -427,7 +427,11 @@ struct context_2
427 427
 #endif
428 428
 
429 429
   struct event_timeout push_request_interval;
430
-  const char *pulled_options_string;
430
+  bool did_pre_pull_restore;
431
+
432
+  /* hash of pulled options, so we can compare when options change */
433
+  struct md5_state pulled_options_state;
434
+  struct md5_digest pulled_options_digest;
431 435
 
432 436
   struct event_timeout scheduled_exit;
433 437
 #endif
... ...
@@ -960,11 +960,15 @@ show_p2mp_parms (const struct options *o)
960 960
   msg (D_SHOW_PARMS, "  server_bridge_netmask = %s", print_in_addr_t (o->server_bridge_netmask, 0, &gc));
961 961
   msg (D_SHOW_PARMS, "  server_bridge_pool_start = %s", print_in_addr_t (o->server_bridge_pool_start, 0, &gc));
962 962
   msg (D_SHOW_PARMS, "  server_bridge_pool_end = %s", print_in_addr_t (o->server_bridge_pool_end, 0, &gc));
963
-  if (o->push_list)
963
+  if (o->push_list.head)
964 964
     {
965
-      const struct push_list *l = o->push_list;
966
-      const char *printable_push_list = l->options;
967
-      msg (D_SHOW_PARMS, "  push_list = '%s'", printable_push_list);
965
+      const struct push_entry *e = o->push_list.head;
966
+      while (e)
967
+	{
968
+	  if (e->enable)
969
+	    msg (D_SHOW_PARMS, "  push_entry = '%s'", e->option);
970
+	  e = e->next;
971
+	}
968 972
     }
969 973
   SHOW_BOOL (ifconfig_pool_defined);
970 974
   msg (D_SHOW_PARMS, "  ifconfig_pool_start = %s", print_in_addr_t (o->ifconfig_pool_start, 0, &gc));
... ...
@@ -1065,12 +1069,7 @@ options_detach (struct options *o)
1065 1065
   gc_detach (&o->gc);
1066 1066
   o->routes = NULL;
1067 1067
 #if P2MP_SERVER
1068
-  if (o->push_list) /* clone push_list */
1069
-    {
1070
-      const struct push_list *old = o->push_list;
1071
-      ALLOC_OBJ_GC (o->push_list, struct push_list, &o->gc);
1072
-      strcpy (o->push_list->options, old->options);
1073
-    }
1068
+  clone_push_list(o);
1074 1069
 #endif
1075 1070
 }
1076 1071
 
... ...
@@ -2190,6 +2189,8 @@ pre_pull_restore (struct options *o)
2190 2190
 
2191 2191
       o->foreign_option_index = pp->foreign_option_index;
2192 2192
     }
2193
+
2194
+  o->push_continuation = 0;
2193 2195
 }
2194 2196
 
2195 2197
 #endif
... ...
@@ -4881,6 +4882,11 @@ add_option (struct options *options,
4881 4881
       VERIFY_PERMISSION (OPT_P_GENERAL);
4882 4882
       options->pull = true;
4883 4883
     }
4884
+  else if (streq (p[0], "push-continuation") && p[1])
4885
+    {
4886
+      VERIFY_PERMISSION (OPT_P_PULL_MODE);
4887
+      options->push_continuation = atoi(p[1]);
4888
+    }
4884 4889
   else if (streq (p[0], "auth-user-pass"))
4885 4890
     {
4886 4891
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -40,6 +40,7 @@
40 40
 #include "manage.h"
41 41
 #include "proxy.h"
42 42
 #include "lzo.h"
43
+#include "pushlist.h"
43 44
 
44 45
 /*
45 46
  * Maximum number of parameters associated with an option,
... ...
@@ -57,17 +58,6 @@ extern const char title_string[];
57 57
 
58 58
 #if P2MP
59 59
 
60
-#if P2MP_SERVER
61
-/* parameters to be pushed to peer */
62
-
63
-#define MAX_PUSH_LIST_LEN TLS_CHANNEL_BUF_SIZE /* This parm is related to PLAINTEXT_BUFFER_SIZE in ssl.h */
64
-
65
-struct push_list {
66
-  /* newline delimited options, like config file */
67
-  char options[MAX_PUSH_LIST_LEN];
68
-};
69
-#endif
70
-
71 60
 /* certain options are saved before --pull modifications are applied */
72 61
 struct options_pre_pull
73 62
 {
... ...
@@ -362,7 +352,7 @@ struct options
362 362
   in_addr_t server_bridge_pool_start;
363 363
   in_addr_t server_bridge_pool_end;
364 364
 
365
-  struct push_list *push_list;
365
+  struct push_list push_list;
366 366
   bool ifconfig_pool_defined;
367 367
   in_addr_t ifconfig_pool_start;
368 368
   in_addr_t ifconfig_pool_end;
... ...
@@ -405,6 +395,7 @@ struct options
405 405
 
406 406
   bool client;
407 407
   bool pull; /* client pull of config options from server */
408
+  int push_continuation;
408 409
   const char *auth_user_pass_file;
409 410
   struct options_pre_pull *pre_pull;
410 411
 
... ...
@@ -99,9 +99,10 @@ incoming_push_message (struct context *c, const struct buffer *buffer)
99 99
 
100 100
   if (status == PUSH_MSG_ERROR)
101 101
     msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", BSTR (buffer));
102
-  else if (status == PUSH_MSG_REPLY)
102
+  else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION)
103 103
     {
104
-      do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */
104
+      if (status == PUSH_MSG_REPLY)
105
+	do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */
105 106
       event_timeout_clear (&c->c2.push_request_interval);
106 107
     }
107 108
 
... ...
@@ -115,60 +116,114 @@ send_push_request (struct context *c)
115 115
 }
116 116
 
117 117
 #if P2MP_SERVER
118
+
118 119
 bool
119 120
 send_push_reply (struct context *c)
120 121
 {
121 122
   struct gc_arena gc = gc_new ();
122
-  struct buffer buf = alloc_buf_gc (MAX_PUSH_LIST_LEN + 256, &gc);
123
-  bool ret = false;
123
+  struct buffer buf = alloc_buf_gc (TLS_CHANNEL_BUF_SIZE, &gc);
124
+  struct push_entry *e = c->options.push_list.head;
125
+  bool multi_push = false;
126
+  static char cmd[] = "PUSH_REPLY";
127
+  const int extra = 64; /* extra space for possible trailing ifconfig and push-continuation */
128
+  const int safe_cap = BCAP (&buf) - extra;
124 129
 
125
-  buf_printf (&buf, "PUSH_REPLY");
130
+  buf_printf (&buf, cmd);
126 131
 
127
-  if (c->options.push_list && strlen (c->options.push_list->options))
128
-    buf_printf (&buf, ",%s", c->options.push_list->options);
132
+  while (e)
133
+    {
134
+      if (e->enable)
135
+	{
136
+	  const int l = strlen (e->option);
137
+	  if (BLEN (&buf) + l >= safe_cap)
138
+	    {
139
+	      buf_printf (&buf, ",push-continuation 2");
140
+	      {
141
+		const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
142
+		if (!status)
143
+		  goto fail;
144
+		multi_push = true;
145
+		buf_reset_len (&buf);
146
+		buf_printf (&buf, cmd);
147
+	      }
148
+	    }
149
+	  if (BLEN (&buf) + l >= safe_cap)
150
+	    {
151
+	      msg (M_WARN, "--push option is too long");
152
+	      goto fail;
153
+	    }
154
+	  buf_printf (&buf, ",%s", e->option);
155
+	}
156
+      e = e->next;
157
+    }
129 158
 
130 159
   if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask)
131 160
     buf_printf (&buf, ",ifconfig %s %s",
132 161
 		print_in_addr_t (c->c2.push_ifconfig_local, 0, &gc),
133 162
 		print_in_addr_t (c->c2.push_ifconfig_remote_netmask, 0, &gc));
163
+  if (multi_push)
164
+    buf_printf (&buf, ",push-continuation 1");
134 165
 
135
-  if (strlen (BSTR (&buf)) < MAX_PUSH_LIST_LEN)
136
-    ret = send_control_channel_string (c, BSTR (&buf), D_PUSH);
137
-  else
138
-    msg (M_WARN, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN);
166
+  if (BLEN (&buf) > sizeof(cmd)-1)
167
+    {
168
+      const bool status = send_control_channel_string (c, BSTR (&buf), D_PUSH);
169
+      if (!status)
170
+	goto fail;
171
+    }
139 172
 
140 173
   gc_free (&gc);
141
-  return ret;
174
+  return true;
175
+
176
+ fail:
177
+  gc_free (&gc);
178
+  return false;
142 179
 }
143 180
 
144
-void
145
-push_option (struct options *o, const char *opt, int msglevel)
181
+static void
182
+push_option_ex (struct options *o, const char *opt, bool enable, int msglevel)
146 183
 {
147
-  int len;
148
-  bool first = false;
149
-
150 184
   if (!string_class (opt, CC_ANY, CC_COMMA))
151 185
     {
152 186
       msg (msglevel, "PUSH OPTION FAILED (illegal comma (',') in string): '%s'", opt);
153 187
     }
154 188
   else
155 189
     {
156
-      if (!o->push_list)
190
+      struct push_entry *e;
191
+      ALLOC_OBJ_CLEAR_GC (e, struct push_entry, &o->gc);
192
+      e->enable = true;
193
+      e->option = opt;
194
+      if (o->push_list.head)
157 195
 	{
158
-	  ALLOC_OBJ_CLEAR_GC (o->push_list, struct push_list, &o->gc);
159
-	  first = true;
196
+	  ASSERT(o->push_list.tail);
197
+	  o->push_list.tail->next = e;
198
+	  o->push_list.tail = e;
160 199
 	}
161
-
162
-      len = strlen (o->push_list->options);
163
-      if (len + strlen (opt) + 2 >= MAX_PUSH_LIST_LEN)
200
+      else
164 201
 	{
165
-	  msg (msglevel, "Maximum length of --push buffer (%d) has been exceeded", MAX_PUSH_LIST_LEN);
202
+	  ASSERT(!o->push_list.tail);
203
+	  o->push_list.head = e;
204
+	  o->push_list.tail = e;
166 205
 	}
167
-      else
206
+    }
207
+}
208
+
209
+void
210
+push_option (struct options *o, const char *opt, int msglevel)
211
+{
212
+  push_option_ex (o, opt, true, msglevel);
213
+}
214
+
215
+void
216
+clone_push_list (struct options *o)
217
+{
218
+  if (o->push_list.head)
219
+    {
220
+      const struct push_entry *e = o->push_list.head;
221
+      push_reset (o);
222
+      while (e)
168 223
 	{
169
-	  if (!first)
170
-	    strcat (o->push_list->options, ",");
171
-	  strcat (o->push_list->options, opt);
224
+	  push_option_ex (o, string_alloc (e->option, &o->gc), true, M_FATAL);
225
+	  e = e->next;
172 226
 	}
173 227
     }
174 228
 }
... ...
@@ -184,7 +239,7 @@ push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc)
184 184
 void
185 185
 push_reset (struct options *o)
186 186
 {
187
-  o->push_list = NULL;
187
+  CLEAR (o->push_list);
188 188
 }
189 189
 #endif
190 190
 
... ...
@@ -224,14 +279,31 @@ process_incoming_push_msg (struct context *c,
224 224
       const uint8_t ch = buf_read_u8 (&buf);
225 225
       if (ch == ',')
226 226
 	{
227
-	  pre_pull_restore (&c->options);
228
-	  c->c2.pulled_options_string = string_alloc (BSTR (&buf), &c->c2.gc);
227
+	  struct buffer buf_orig = buf;
228
+	  if (!c->c2.did_pre_pull_restore)
229
+	    {
230
+	      pre_pull_restore (&c->options);
231
+	      md5_state_init (&c->c2.pulled_options_state);
232
+	      c->c2.did_pre_pull_restore = true;
233
+	    }
229 234
 	  if (apply_push_options (&c->options,
230 235
 				  &buf,
231 236
 				  permission_mask,
232 237
 				  option_types_found,
233 238
 				  c->c2.es))
234
-	    ret = PUSH_MSG_REPLY;
239
+	    switch (c->options.push_continuation)
240
+	      {
241
+	      case 0:
242
+	      case 1:
243
+		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
244
+		md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
245
+		ret = PUSH_MSG_REPLY;
246
+		break;
247
+	      case 2:
248
+		md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
249
+		ret = PUSH_MSG_CONTINUATION;
250
+		break;
251
+	      }
235 252
 	}
236 253
       else if (ch == '\0')
237 254
 	{
... ...
@@ -243,36 +315,27 @@ process_incoming_push_msg (struct context *c,
243 243
 }
244 244
 
245 245
 #if P2MP_SERVER
246
+
246 247
 /*
247 248
  * Remove iroutes from the push_list.
248 249
  */
249 250
 void
250 251
 remove_iroutes_from_push_route_list (struct options *o)
251 252
 {
252
-  if (o && o->push_list && o->iroutes)
253
+  if (o && o->push_list.head && o->iroutes)
253 254
     {
254 255
       struct gc_arena gc = gc_new ();
255
-      struct push_list *pl;
256
-      struct buffer in, out;
257
-      char *line;
258
-      bool first = true;
259
-
260
-      /* prepare input and output buffers */
261
-      ALLOC_OBJ_CLEAR_GC (pl, struct push_list, &gc);
262
-      ALLOC_ARRAY_CLEAR_GC (line, char, MAX_PUSH_LIST_LEN, &gc);
263
-
264
-      buf_set_read (&in, (const uint8_t*) o->push_list->options, strlen (o->push_list->options));
265
-      buf_set_write (&out, (uint8_t*) pl->options, sizeof (pl->options));
256
+      struct push_entry *e = o->push_list.head;
266 257
 
267 258
       /* cycle through the push list */
268
-      while (buf_parse (&in, ',', line, MAX_PUSH_LIST_LEN))
259
+      while (e)
269 260
 	{
270 261
 	  char *p[MAX_PARMS];
271
-	  bool copy = true;
262
+	  bool enable = true;
272 263
 
273 264
 	  /* parse the push item */
274 265
 	  CLEAR (p);
275
-	  if (parse_line (line, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
266
+	  if (parse_line (e->option, p, SIZE (p), "[PUSH_ROUTE_REMOVE]", 1, D_ROUTE_DEBUG, &gc))
276 267
 	    {
277 268
 	      /* is the push item a route directive? */
278 269
 	      if (p[0] && !strcmp (p[0], "route") && !p[3])
... ...
@@ -292,7 +355,7 @@ remove_iroutes_from_push_route_list (struct options *o)
292 292
 			{
293 293
 			  if (network == ir->network && netmask == netbits_to_netmask (ir->netbits >= 0 ? ir->netbits : 32))
294 294
 			    {
295
-			      copy = false;
295
+			      enable = false;
296 296
 			      break;
297 297
 			    }
298 298
 			}
... ...
@@ -301,28 +364,17 @@ remove_iroutes_from_push_route_list (struct options *o)
301 301
 	    }
302 302
 
303 303
 	  /* should we copy the push item? */
304
-	  if (copy)
305
-	    {
306
-	      if (!first)
307
-		buf_printf (&out, ",");
308
-	      buf_printf (&out, "%s", line);
309
-	      first = false;
310
-	    }
311
-	  else
312
-	    msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", line);
313
-	}
314
-
315
-#if 0
316
-      msg (M_INFO, "BEFORE: '%s'", o->push_list->options);
317
-      msg (M_INFO, "AFTER:  '%s'", pl->options);
318
-#endif
304
+	  e->enable = enable;
305
+	  if (!enable)
306
+	    msg (D_PUSH, "REMOVE PUSH ROUTE: '%s'", e->option);
319 307
 
320
-      /* copy new push list back to options */
321
-      *o->push_list = *pl;
308
+	  e = e->next;
309
+	}
322 310
 
323 311
       gc_free (&gc);
324 312
     }
325 313
 }
314
+
326 315
 #endif
327 316
 
328 317
 #endif
... ...
@@ -34,6 +34,7 @@
34 34
 #define PUSH_MSG_REPLY            2
35 35
 #define PUSH_MSG_REQUEST_DEFERRED 3
36 36
 #define PUSH_MSG_AUTH_FAILURE     4
37
+#define PUSH_MSG_CONTINUATION     5
37 38
 
38 39
 void incoming_push_message (struct context *c,
39 40
 			    const struct buffer *buffer);
... ...
@@ -50,6 +51,8 @@ void receive_auth_failed (struct context *c, const struct buffer *buffer);
50 50
 
51 51
 #if P2MP_SERVER
52 52
 
53
+void clone_push_list (struct options *o);
54
+
53 55
 void push_option (struct options *o, const char *opt, int msglevel);
54 56
 void push_options (struct options *o, char **p, int msglevel, struct gc_arena *gc);
55 57
 
56 58
new file mode 100644
... ...
@@ -0,0 +1,42 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+#if !defined(PUSHLIST_H) && P2MP && P2MP_SERVER
25
+#define PUSHLIST_H
26
+
27
+/* parameters to be pushed to peer */
28
+
29
+struct push_entry {
30
+  struct push_entry *next;
31
+  bool enable;
32
+  const char *option;
33
+};
34
+
35
+struct push_list {
36
+  struct push_entry *head;
37
+  struct push_entry *tail;
38
+};
39
+
40
+
41
+#endif
... ...
@@ -740,7 +740,7 @@ delete_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flag
740 740
     }
741 741
   undo_redirect_default_route_to_vpn (rl, tt, flags, es);
742 742
 
743
-  CLEAR (*rl);
743
+  clear_route_list (rl);
744 744
 }
745 745
 
746 746
 #ifdef ENABLE_DEBUG
... ...
@@ -2069,8 +2069,8 @@ key_state_init (struct tls_session *session, struct key_state *ks)
2069 2069
   ALLOC_OBJ_CLEAR (ks->rec_ack, struct reliable_ack);
2070 2070
 
2071 2071
   /* allocate buffers */
2072
-  ks->plaintext_read_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE);
2073
-  ks->plaintext_write_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE);
2072
+  ks->plaintext_read_buf = alloc_buf (TLS_CHANNEL_BUF_SIZE);
2073
+  ks->plaintext_write_buf = alloc_buf (TLS_CHANNEL_BUF_SIZE);
2074 2074
   ks->ack_write_buf = alloc_buf (BUF_SIZE (&session->opt->frame));
2075 2075
   reliable_init (ks->send_reliable, BUF_SIZE (&session->opt->frame),
2076 2076
 		 FRAME_HEADROOM (&session->opt->frame), TLS_RELIABLE_N_SEND_BUFFERS,
... ...
@@ -3750,7 +3750,7 @@ tls_process (struct tls_multi *multi,
3750 3750
 	      int status;
3751 3751
 
3752 3752
 	      ASSERT (buf_init (buf, 0));
3753
-	      status = key_state_read_plaintext (multi, ks, buf, PLAINTEXT_BUFFER_SIZE);
3753
+	      status = key_state_read_plaintext (multi, ks, buf, TLS_CHANNEL_BUF_SIZE);
3754 3754
 	      update_time ();
3755 3755
 	      if (status == -1)
3756 3756
 		{
... ...
@@ -278,8 +278,6 @@
278 278
  * Buffer sizes (also see mtu.h).
279 279
  */
280 280
 
281
-#define PLAINTEXT_BUFFER_SIZE TLS_CHANNEL_BUF_SIZE
282
-
283 281
 /* Maximum length of common name */
284 282
 #define TLS_CN_LEN 64
285 283
 
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc19d])
2
+define(PRODUCT_VERSION,[2.1_rc19e])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])