Browse code

Merged connection profiles from http://svn.openvpn.net/projects/openvpn/test/conn

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

james authored on 2008/06/11 19:48:50
Showing 23 changed files
... ...
@@ -315,6 +315,26 @@ x_gc_free (struct gc_arena *a)
315 315
 }
316 316
 
317 317
 /*
318
+ * Transfer src arena to dest, resetting src to an empty arena.
319
+ */
320
+void
321
+gc_transfer (struct gc_arena *dest, struct gc_arena *src)
322
+{
323
+  if (dest && src)
324
+    {
325
+      struct gc_entry *e = src->list;
326
+      if (e)
327
+	{
328
+	  while (e->next != NULL)
329
+	    e = e->next;
330
+	  e->next = dest->list;
331
+	  dest->list = src->list;
332
+	  src->list = NULL;
333
+	}
334
+    }
335
+}
336
+
337
+/*
318 338
  * Hex dump -- Output a binary buffer to a hex string and return it.
319 339
  */
320 340
 
... ...
@@ -632,6 +632,8 @@ void character_class_debug (void);
632 632
  * char ptrs to malloced strings.
633 633
  */
634 634
 
635
+void gc_transfer (struct gc_arena *dest, struct gc_arena *src);
636
+
635 637
 void x_gc_free (struct gc_arena *a);
636 638
 
637 639
 static inline void
... ...
@@ -120,7 +120,7 @@
120 120
 #define D_MULTI_DEBUG        LOGLEV(7, 70, M_DEBUG)  /* show medium-freq multi debugging info */
121 121
 #define D_MSS                LOGLEV(7, 70, M_DEBUG)  /* show MSS adjustments */
122 122
 #define D_COMP_LOW           LOGLEV(7, 70, M_DEBUG)  /* show adaptive compression state changes */
123
-#define D_REMOTE_LIST        LOGLEV(7, 70, M_DEBUG)  /* show --remote list */
123
+#define D_CONNECTION_LIST    LOGLEV(7, 70, M_DEBUG)  /* show <connection> list info */
124 124
 #define D_SCRIPT             LOGLEV(7, 70, M_DEBUG)  /* show parms & env vars passed to scripts */
125 125
 #define D_SHOW_NET           LOGLEV(7, 70, M_DEBUG)  /* show routing table and adapter list */
126 126
 #define D_ROUTE_DEBUG        LOGLEV(7, 70, M_DEBUG)  /* show verbose route.[ch] output */
... ...
@@ -356,7 +356,7 @@ check_fragment_dowork (struct context *c)
356 356
   if (lsi->mtu_changed && c->c2.ipv4_tun)
357 357
     {
358 358
       frame_adjust_path_mtu (&c->c2.frame_fragment, c->c2.link_socket->mtu,
359
-			     c->options.proto);
359
+			     c->options.ce.proto);
360 360
       lsi->mtu_changed = false;
361 361
     }
362 362
 
... ...
@@ -1038,7 +1038,7 @@ process_outgoing_link (struct context *c)
1038 1038
 #ifdef HAVE_GETTIMEOFDAY
1039 1039
 	  if (c->options.shaper)
1040 1040
 	    shaper_wrote_bytes (&c->c2.shaper, BLEN (&c->c2.to_link)
1041
-				+ datagram_overhead (c->options.proto));
1041
+				+ datagram_overhead (c->options.ce.proto));
1042 1042
 #endif
1043 1043
 	  /*
1044 1044
 	   * Let the pinger know that we sent a packet.
... ...
@@ -281,9 +281,6 @@ helper_client_server (struct options *o)
281 281
 	  o->push_ifconfig_constraint_network = o->server_network;
282 282
 	  o->push_ifconfig_constraint_netmask = o->server_netmask;
283 283
 	}
284
-
285
-      if (o->proto == PROTO_TCPv4)
286
-	o->proto = PROTO_TCPv4_SERVER;
287 284
     }
288 285
 
289 286
   /*
... ...
@@ -325,9 +322,6 @@ helper_client_server (struct options *o)
325 325
       ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
326 326
       o->ifconfig_pool_netmask = o->server_bridge_netmask;
327 327
       push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE);
328
-
329
-      if (o->proto == PROTO_TCPv4)
330
-	o->proto = PROTO_TCPv4_SERVER;
331 328
     }
332 329
   else
333 330
 #endif /* P2MP_SERVER */
... ...
@@ -349,16 +343,10 @@ helper_client_server (struct options *o)
349 349
 
350 350
       o->pull = true;
351 351
       o->tls_client = true;
352
-
353
-      if (o->proto == PROTO_TCPv4)
354
-	o->proto = PROTO_TCPv4_CLIENT;
355 352
     }
356 353
 
357 354
 #endif /* P2MP */
358 355
 
359
-  if (o->proto == PROTO_TCPv4)
360
-    msg (M_USAGE, "--proto tcp is ambiguous in this context.  Please specify --proto tcp-server or --proto tcp-client");
361
-
362 356
   gc_free (&gc);
363 357
 }
364 358
 
... ...
@@ -78,23 +78,100 @@ context_clear_all_except_first_time (struct context *c)
78 78
 }
79 79
 
80 80
 /*
81
- * Initialize and possibly randomize remote list.
81
+ * Should be called after options->ce is modified at the top
82
+ * of a SIGUSR1 restart.
82 83
  */
83 84
 static void
84
-init_remote_list (struct context *c)
85
+update_options_ce_post (struct options *options)
85 86
 {
86
-  c->c1.remote_list = NULL;
87
+#if P2MP
88
+  /*
89
+   * In pull mode, we usually import --ping/--ping-restart parameters from
90
+   * the server.  However we should also set an initial default --ping-restart
91
+   * for the period of time before we pull the --ping-restart parameter
92
+   * from the server.
93
+   */
94
+  if (options->pull
95
+      && options->ping_rec_timeout_action == PING_UNDEF
96
+      && options->ce.proto == PROTO_UDPv4)
97
+    {
98
+      options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART;
99
+      options->ping_rec_timeout_action = PING_RESTART;
100
+    }
101
+#endif
102
+#ifdef USE_CRYPTO
103
+  /* 
104
+   * Don't use replay window for TCP mode (i.e. require that packets be strictly in sequence).
105
+   */
106
+  if (link_socket_proto_connection_oriented (options->ce.proto))
107
+    options->replay_window = options->replay_time = 0;
108
+#endif
109
+}
87 110
 
88
-  if (c->options.remote_list)
111
+/*
112
+ * Initialize and possibly randomize connection list.
113
+ */
114
+static void
115
+init_connection_list (struct context *c)
116
+{
117
+#ifdef ENABLE_CONNECTION
118
+  struct connection_list *l = c->options.connection_list;
119
+  if (l)
89 120
     {
90
-      struct remote_list *l;
91
-      ALLOC_OBJ_GC (c->c1.remote_list, struct remote_list, &c->gc);
92
-      l = c->c1.remote_list;
93
-      *l = *c->options.remote_list;
94 121
       l->current = -1;
95 122
       if (c->options.remote_random)
96
-	remote_list_randomize (l);
123
+	{
124
+	  int i;
125
+	  for (i = 0; i < l->len; ++i)
126
+	    {
127
+	      const int j = get_random () % l->len;
128
+	      if (i != j)
129
+		{
130
+		  struct connection_entry *tmp;
131
+		  tmp = l->array[i];
132
+		  l->array[i] = l->array[j];
133
+		  l->array[j] = tmp;
134
+		}
135
+	    }
136
+	}
97 137
     }
138
+#endif
139
+}
140
+
141
+/*
142
+ * Increment to next connection entry
143
+ */
144
+static void
145
+next_connection_entry (struct context *c)
146
+{
147
+#ifdef ENABLE_CONNECTION
148
+  struct connection_list *l = c->options.connection_list;
149
+  if (l)
150
+    {
151
+      if (l->no_advance && l->current >= 0)
152
+	{
153
+	  l->no_advance = false;
154
+	}
155
+      else
156
+	{
157
+	  int i;
158
+	  if (++l->current >= l->len)
159
+	    l->current = 0;
160
+
161
+	  dmsg (D_CONNECTION_LIST, "CONNECTION_LIST len=%d current=%d",
162
+		l->len, l->current);
163
+	  for (i = 0; i < l->len; ++i)
164
+	    {
165
+	      dmsg (D_CONNECTION_LIST, "[%d] %s:%d",
166
+		    i,
167
+		    l->array[i]->remote,
168
+		    l->array[i]->remote_port);
169
+	    }
170
+	}
171
+      c->options.ce = *l->array[l->current];
172
+    }
173
+#endif
174
+  update_options_ce_post (&c->options);
98 175
 }
99 176
 
100 177
 /*
... ...
@@ -116,8 +193,41 @@ init_query_passwords (struct context *c)
116 116
 #endif
117 117
 }
118 118
 
119
-void
120
-context_init_1 (struct context *c)
119
+/*
120
+ * Initialize/Uninitialize HTTP or SOCKS proxy
121
+ */
122
+
123
+#ifdef GENERAL_PROXY_SUPPORT
124
+
125
+static int
126
+proxy_scope (struct context *c)
127
+{
128
+  return connection_list_defined (&c->options) ? 2 : 1;
129
+}
130
+
131
+static void
132
+uninit_proxy_dowork (struct context *c)
133
+{
134
+#ifdef ENABLE_HTTP_PROXY
135
+  if (c->c1.http_proxy_owned && c->c1.http_proxy)
136
+    {
137
+      http_proxy_close (c->c1.http_proxy);
138
+      c->c1.http_proxy = NULL;
139
+      c->c1.http_proxy_owned = false;
140
+    }
141
+#endif
142
+#ifdef ENABLE_SOCKS
143
+  if (c->c1.socks_proxy_owned && c->c1.socks_proxy)
144
+    {
145
+      socks_proxy_close (c->c1.socks_proxy);
146
+      c->c1.socks_proxy = NULL;
147
+      c->c1.socks_proxy_owned = false;
148
+    }
149
+#endif
150
+}
151
+
152
+static void
153
+init_proxy_dowork (struct context *c)
121 154
 {
122 155
 #ifdef ENABLE_HTTP_PROXY
123 156
   bool did_http = false;
... ...
@@ -125,10 +235,73 @@ context_init_1 (struct context *c)
125 125
   const bool did_http = false;
126 126
 #endif
127 127
 
128
+  uninit_proxy_dowork (c);
129
+
130
+#ifdef ENABLE_HTTP_PROXY
131
+  if (c->options.ce.http_proxy_options || c->options.auto_proxy_info)
132
+    {
133
+      /* Possible HTTP proxy user/pass input */
134
+      c->c1.http_proxy = http_proxy_new (c->options.ce.http_proxy_options,
135
+					 c->options.auto_proxy_info);
136
+      if (c->c1.http_proxy)
137
+	{
138
+	  did_http = true;
139
+	  c->c1.http_proxy_owned = true;
140
+	}
141
+    }
142
+#endif
143
+
144
+#ifdef ENABLE_SOCKS
145
+  if (!did_http && (c->options.ce.socks_proxy_server || c->options.auto_proxy_info))
146
+    {
147
+      c->c1.socks_proxy = socks_proxy_new (c->options.ce.socks_proxy_server,
148
+					   c->options.ce.socks_proxy_port,
149
+					   c->options.ce.socks_proxy_retry,
150
+					   c->options.auto_proxy_info);
151
+      if (c->c1.socks_proxy)
152
+	{
153
+	  c->c1.socks_proxy_owned = true;
154
+	}
155
+    }
156
+#endif
157
+}
158
+
159
+static void
160
+init_proxy (struct context *c, const int scope)
161
+{
162
+  if (scope == proxy_scope (c))
163
+    init_proxy_dowork (c);
164
+}
165
+
166
+static void
167
+uninit_proxy (struct context *c)
168
+{
169
+  if (c->sig->signal_received != SIGUSR1 || proxy_scope (c) == 2)
170
+    uninit_proxy_dowork (c);
171
+}
172
+
173
+#else
174
+
175
+static inline void
176
+init_proxy (struct context *c, const int scope)
177
+{
178
+}
179
+
180
+static inline void
181
+uninit_proxy (struct context *c, const int scope)
182
+{
183
+}
184
+
185
+#endif
186
+
187
+void
188
+context_init_1 (struct context *c)
189
+{
128 190
   context_clear_1 (c);
129 191
 
130 192
   packet_id_persist_init (&c->c1.pid_persist);
131
-  init_remote_list (c);
193
+
194
+  init_connection_list (c);
132 195
 
133 196
   init_query_passwords (c);
134 197
 
... ...
@@ -156,28 +329,8 @@ context_init_1 (struct context *c)
156 156
  }
157 157
 #endif
158 158
 
159
-#ifdef ENABLE_HTTP_PROXY
160
-  if (c->options.http_proxy_options || c->options.auto_proxy_info)
161
-    {
162
-      /* Possible HTTP proxy user/pass input */
163
-      c->c1.http_proxy = new_http_proxy (c->options.http_proxy_options,
164
-					 c->options.auto_proxy_info,
165
-					 &c->gc);
166
-      if (c->c1.http_proxy)
167
-	did_http = true;
168
-    }
169
-#endif
170
-
171
-#ifdef ENABLE_SOCKS
172
-  if (!did_http && (c->options.socks_proxy_server || c->options.auto_proxy_info))
173
-    {
174
-      c->c1.socks_proxy = new_socks_proxy (c->options.socks_proxy_server,
175
-					   c->options.socks_proxy_port,
176
-					   c->options.socks_proxy_retry,
177
-					   c->options.auto_proxy_info,
178
-					   &c->gc);
179
-    }
180
-#endif
159
+  /* initialize HTTP or SOCKS proxy object at scope level 1 */
160
+  init_proxy (c, 1);
181 161
 }
182 162
 
183 163
 void
... ...
@@ -407,7 +560,7 @@ do_persist_tuntap (const struct options *options)
407 407
     {
408 408
       /* sanity check on options for --mktun or --rmtun */
409 409
       notnull (options->dev, "TUN/TAP device (--dev)");
410
-      if (options->remote_list || options->ifconfig_local
410
+      if (options->ce.remote || options->ifconfig_local
411 411
 	  || options->ifconfig_remote_netmask
412 412
 #ifdef USE_CRYPTO
413 413
 	  || options->shared_secret_file
... ...
@@ -684,9 +837,9 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
684 684
   else
685 685
     msg (M_INFO, "%s", message);
686 686
 
687
-  /* Flag remote_list that we initialized */
688
-  if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && c->c1.remote_list && c->c1.remote_list->len > 1)
689
-    c->c1.remote_list->no_advance = true;
687
+  /* Flag connection_list that we initialized */
688
+  if ((flags & (ISC_ERRORS|ISC_SERVER)) == 0 && connection_list_defined (&c->options))
689
+    connection_list_set_no_advance (&c->options);
690 690
 
691 691
 #ifdef ENABLE_MANAGEMENT
692 692
   /* Tell management interface that we initialized */
... ...
@@ -1099,7 +1252,7 @@ do_deferred_options (struct context *c, const unsigned int found)
1099 1099
 #ifdef ENABLE_OCC
1100 1100
   if (found & OPT_P_EXPLICIT_NOTIFY)
1101 1101
     {
1102
-      if (c->options.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
1102
+      if (c->options.ce.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
1103 1103
 	{
1104 1104
 	  msg (D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp");
1105 1105
 	  c->options.explicit_exit_notification = 0;
... ...
@@ -1183,25 +1336,25 @@ socket_restart_pause (struct context *c)
1183 1183
   int sec = 2;
1184 1184
 
1185 1185
 #ifdef ENABLE_HTTP_PROXY
1186
-  if (c->options.http_proxy_options)
1186
+  if (c->options.ce.http_proxy_options)
1187 1187
     proxy = true;
1188 1188
 #endif
1189 1189
 #ifdef ENABLE_SOCKS
1190
-  if (c->options.socks_proxy_server)
1190
+  if (c->options.ce.socks_proxy_server)
1191 1191
     proxy = true;
1192 1192
 #endif
1193 1193
 
1194
-  switch (c->options.proto)
1194
+  switch (c->options.ce.proto)
1195 1195
     {
1196 1196
     case PROTO_UDPv4:
1197 1197
       if (proxy)
1198
-	sec = c->options.connect_retry_seconds;
1198
+	sec = c->options.ce.connect_retry_seconds;
1199 1199
       break;
1200 1200
     case PROTO_TCPv4_SERVER:
1201 1201
       sec = 1;
1202 1202
       break;
1203 1203
     case PROTO_TCPv4_CLIENT:
1204
-      sec = c->options.connect_retry_seconds;
1204
+      sec = c->options.ce.connect_retry_seconds;
1205 1205
       break;
1206 1206
     }
1207 1207
 
... ...
@@ -1537,7 +1690,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
1537 1537
 
1538 1538
   /* should we not xmit any packets until we get an initial
1539 1539
      response from client? */
1540
-  if (to.server && options->proto == PROTO_TCPv4_SERVER)
1540
+  if (to.server && options->ce.proto == PROTO_TCPv4_SERVER)
1541 1541
     to.xmit_hold = true;
1542 1542
 
1543 1543
 #ifdef ENABLE_OCC
... ...
@@ -1584,7 +1737,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)
1584 1584
 
1585 1585
   /* If we are running over TCP, allow for
1586 1586
      length prefix */
1587
-  socket_adjust_frame_parameters (&to.frame, options->proto);
1587
+  socket_adjust_frame_parameters (&to.frame, options->ce.proto);
1588 1588
 
1589 1589
   /*
1590 1590
    * Initialize OpenVPN's master TLS-mode object.
... ...
@@ -1682,8 +1835,8 @@ do_init_frame (struct context *c)
1682 1682
   /*
1683 1683
    * Adjust frame size for UDP Socks support.
1684 1684
    */
1685
-  if (c->options.socks_proxy_server)
1686
-    socks_adjust_frame_parameters (&c->c2.frame, c->options.proto);
1685
+  if (c->options.ce.socks_proxy_server)
1686
+    socks_adjust_frame_parameters (&c->c2.frame, c->options.ce.proto);
1687 1687
 #endif
1688 1688
 
1689 1689
   /*
... ...
@@ -1697,7 +1850,7 @@ do_init_frame (struct context *c)
1697 1697
    * (Since TCP is a stream protocol, we need to insert
1698 1698
    * a packet length uint16_t in the buffer.)
1699 1699
    */
1700
-  socket_adjust_frame_parameters (&c->c2.frame, c->options.proto);
1700
+  socket_adjust_frame_parameters (&c->c2.frame, c->options.ce.proto);
1701 1701
 
1702 1702
   /*
1703 1703
    * Fill in the blanks in the frame parameters structure,
... ...
@@ -1739,7 +1892,7 @@ do_option_warnings (struct context *c)
1739 1739
   const struct options *o = &c->options;
1740 1740
 
1741 1741
 #if 1 /* JYFIXME -- port warning */
1742
-  if (!o->port_option_used && (o->local_port == OPENVPN_PORT && o->remote_port == OPENVPN_PORT))
1742
+  if (!o->ce.port_option_used && (o->ce.local_port == OPENVPN_PORT && o->ce.remote_port == OPENVPN_PORT))
1743 1743
     msg (M_WARN, "IMPORTANT: OpenVPN's default port number is now %d, based on an official port number assignment by IANA.  OpenVPN 2.0-beta16 and earlier used 5000 as the default port.",
1744 1744
 	 OPENVPN_PORT);
1745 1745
 #endif
... ...
@@ -1793,7 +1946,7 @@ do_option_warnings (struct context *c)
1793 1793
 #endif
1794 1794
 
1795 1795
 #ifndef CONNECT_NONBLOCK
1796
-  if (o->connect_timeout_defined)
1796
+  if (o->ce.connect_timeout_defined)
1797 1797
     msg (M_WARN, "NOTE: --connect-timeout option is not supported on this OS");
1798 1798
 #endif
1799 1799
 }
... ...
@@ -1918,10 +2071,12 @@ do_init_socket_1 (struct context *c, const int mode)
1918 1918
 #endif
1919 1919
 
1920 1920
   link_socket_init_phase1 (c->c2.link_socket,
1921
-			   c->options.local,
1922
-			   c->c1.remote_list,
1923
-			   c->options.local_port,
1924
-			   c->options.proto,
1921
+			   connection_list_defined (&c->options),
1922
+			   c->options.ce.local,
1923
+			   c->options.ce.local_port,
1924
+			   c->options.ce.remote,
1925
+			   c->options.ce.remote_port,
1926
+			   c->options.ce.proto,
1925 1927
 			   mode,
1926 1928
 			   c->c2.accept_from,
1927 1929
 #ifdef ENABLE_HTTP_PROXY
... ...
@@ -1933,16 +2088,16 @@ do_init_socket_1 (struct context *c, const int mode)
1933 1933
 #ifdef ENABLE_DEBUG
1934 1934
 			   c->options.gremlin,
1935 1935
 #endif
1936
-			   c->options.bind_local,
1937
-			   c->options.remote_float,
1936
+			   c->options.ce.bind_local,
1937
+			   c->options.ce.remote_float,
1938 1938
 			   c->options.inetd,
1939 1939
 			   &c->c1.link_socket_addr,
1940 1940
 			   c->options.ipchange,
1941 1941
 			   c->plugins,
1942 1942
 			   c->options.resolve_retry_seconds,
1943
-			   c->options.connect_retry_seconds,
1944
-			   c->options.connect_timeout,
1945
-			   c->options.connect_retry_max,
1943
+			   c->options.ce.connect_retry_seconds,
1944
+			   c->options.ce.connect_timeout,
1945
+			   c->options.ce.connect_retry_max,
1946 1946
 			   c->options.mtu_discover_type,
1947 1947
 			   c->options.rcvbuf,
1948 1948
 			   c->options.sndbuf,
... ...
@@ -2302,7 +2457,7 @@ do_setup_fast_io (struct context *c)
2302 2302
 #ifdef WIN32
2303 2303
       msg (M_INFO, "NOTE: --fast-io is disabled since we are running on Windows");
2304 2304
 #else
2305
-      if (c->options.proto != PROTO_UDPv4)
2305
+      if (c->options.ce.proto != PROTO_UDPv4)
2306 2306
 	msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP");
2307 2307
       else
2308 2308
 	{
... ...
@@ -2556,10 +2711,13 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
2556 2556
   c->sig->signal_text = NULL;
2557 2557
   c->sig->hard = false;
2558 2558
 
2559
+  /* map in current connection entry */
2560
+  next_connection_entry (c);
2561
+
2559 2562
   /* link_socket_mode allows CM_CHILD_TCP
2560 2563
      instances to inherit acceptable fds
2561 2564
      from a top-level parent */
2562
-  if (c->options.proto == PROTO_TCPv4_SERVER)
2565
+  if (c->options.ce.proto == PROTO_TCPv4_SERVER)
2563 2566
     {
2564 2567
       if (c->mode == CM_TOP)
2565 2568
 	link_socket_mode = LS_MODE_TCP_LISTEN;
... ...
@@ -2633,6 +2791,9 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
2633 2633
   else if (c->mode == CM_CHILD_TCP)
2634 2634
     do_event_set_init (c, false);
2635 2635
 
2636
+  /* initialize HTTP or SOCKS proxy object at scope level 2 */
2637
+  init_proxy (c, 2);
2638
+
2636 2639
   /* allocate our socket object */
2637 2640
   if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
2638 2641
     do_link_socket_new (c);
... ...
@@ -2825,6 +2986,9 @@ close_instance (struct context *c)
2825 2825
 	/* free up environmental variable store */
2826 2826
 	do_env_set_destroy (c);
2827 2827
 
2828
+	/* close HTTP or SOCKS proxy */
2829
+	uninit_proxy (c);
2830
+
2828 2831
 	/* garbage collect */
2829 2832
 	gc_free (&c->c2.gc);
2830 2833
       }
... ...
@@ -2836,7 +3000,7 @@ inherit_context_child (struct context *dest,
2836 2836
 {
2837 2837
   CLEAR (*dest);
2838 2838
 
2839
-  switch (src->options.proto)
2839
+  switch (src->options.ce.proto)
2840 2840
     {
2841 2841
     case PROTO_UDPv4:
2842 2842
       dest->mode = CM_CHILD_UDP;
... ...
@@ -2952,7 +3116,7 @@ inherit_context_top (struct context *dest,
2952 2952
   dest->c2.es_owned = false;
2953 2953
 
2954 2954
   dest->c2.event_set = NULL;
2955
-  if (src->options.proto == PROTO_UDPv4)
2955
+  if (src->options.ce.proto == PROTO_UDPv4)
2956 2956
     do_event_set_init (dest, false);
2957 2957
 }
2958 2958
 
... ...
@@ -940,6 +940,7 @@ setenv_str_ex (struct env_set *es,
940 940
 	{
941 941
 	  const char *str = construct_name_value (name_tmp, val_tmp, &gc);
942 942
 	  env_set_add (es, str);
943
+	  /*msg (M_INFO, "SETENV_ES '%s'", str);*/
943 944
 	}
944 945
       else
945 946
 	env_set_del (es, name_tmp);
... ...
@@ -975,6 +976,38 @@ setenv_str_ex (struct env_set *es,
975 975
 }
976 976
 
977 977
 /*
978
+ * Setenv functions that append an integer index to the name
979
+ */
980
+static const char *
981
+setenv_format_indexed_name (const char *name, const int i, struct gc_arena *gc)
982
+{
983
+  struct buffer out = alloc_buf_gc (strlen (name) + 16, gc);
984
+  if (i >= 0)
985
+    buf_printf (&out, "%s_%d", name, i);
986
+  else
987
+    buf_printf (&out, "%s", name);
988
+  return BSTR (&out);
989
+}
990
+
991
+void
992
+setenv_int_i (struct env_set *es, const char *name, const int value, const int i)
993
+{
994
+  struct gc_arena gc = gc_new ();
995
+  const char *name_str = setenv_format_indexed_name (name, i, &gc);
996
+  setenv_int (es, name_str, value);
997
+  gc_free (&gc);
998
+}
999
+
1000
+void
1001
+setenv_str_i (struct env_set *es, const char *name, const char *value, const int i)
1002
+{
1003
+  struct gc_arena gc = gc_new ();
1004
+  const char *name_str = setenv_format_indexed_name (name, i, &gc);
1005
+  setenv_str (es, name_str, value);
1006
+  gc_free (&gc);
1007
+}
1008
+
1009
+/*
978 1010
  * taken from busybox networking/ifupdown.c
979 1011
  */
980 1012
 unsigned int
... ...
@@ -165,6 +165,9 @@ void setenv_str (struct env_set *es, const char *name, const char *value);
165 165
 void setenv_str_safe (struct env_set *es, const char *name, const char *value);
166 166
 void setenv_del (struct env_set *es, const char *name);
167 167
 
168
+void setenv_int_i (struct env_set *es, const char *name, const int value, const int i);
169
+void setenv_str_i (struct env_set *es, const char *name, const char *value, const int i);
170
+
168 171
 /* struct env_set functions */
169 172
 
170 173
 struct env_set *env_set_create (struct gc_arena *gc);
... ...
@@ -2619,7 +2619,7 @@ tunnel_server (struct context *top)
2619 2619
 {
2620 2620
   ASSERT (top->options.mode == MODE_SERVER);
2621 2621
 
2622
-  switch (top->options.proto) {
2622
+  switch (top->options.ce.proto) {
2623 2623
   case PROTO_UDPv4:
2624 2624
     tunnel_server_udp (top);
2625 2625
     break;
... ...
@@ -149,7 +149,7 @@ check_send_occ_req_dowork (struct context *c)
149 149
 {
150 150
   if (++c->c2.occ_n_tries >= OCC_N_TRIES)
151 151
     {
152
-      if (c->options.remote_list)
152
+      if (c->options.ce.remote)
153 153
 	/*
154 154
 	 * No OCC_REPLY from peer after repeated attempts.
155 155
 	 * Give up.
... ...
@@ -369,7 +369,7 @@ process_received_occ_msg (struct context *c)
369 369
 	       c->c2.max_send_size_remote,
370 370
 	       c->c2.max_recv_size_local);
371 371
 	  if (!c->options.fragment
372
-	      && c->options.proto == PROTO_UDPv4
372
+	      && c->options.ce.proto == PROTO_UDPv4
373 373
 	      && c->c2.max_send_size_local > TUN_MTU_MIN
374 374
 	      && (c->c2.max_recv_size_remote < c->c2.max_send_size_local
375 375
 		  || c->c2.max_recv_size_local < c->c2.max_send_size_remote))
... ...
@@ -466,11 +466,16 @@ If specified, OpenVPN will bind to this address only.
466 466
 If unspecified, OpenVPN will bind to all interfaces.
467 467
 .\"*********************************************************
468 468
 .TP
469
-.B --remote host [port]
469
+.B --remote host [port] [proto]
470 470
 Remote host name or IP address.  On the client, multiple
471 471
 .B --remote
472 472
 options may be specified for redundancy, each referring
473
-to a different OpenVPN server.
473
+to a different OpenVPN server.  Specifying multiple
474
+.B --remote
475
+options for this purpose is a special case of the more
476
+general connection-profile feature.  See the
477
+.B <connection>
478
+documentation below.
474 479
 
475 480
 The OpenVPN client will try to connect to a server at
476 481
 .B host:port
... ...
@@ -478,6 +483,10 @@ in the order specified by the list of
478 478
 .B --remote
479 479
 options.
480 480
 
481
+.B proto
482
+indicates the protocol to use when connecting with the
483
+remote, and may be "tcp" or "udp".
484
+
481 485
 The client will move on to the next host in the list,
482 486
 in the event of connection failure.
483 487
 Note that at any given time, the OpenVPN client
... ...
@@ -527,10 +536,124 @@ chosen, providing a sort of basic load-balancing and
527 527
 failover capability.
528 528
 .\"*********************************************************
529 529
 .TP
530
+.B <connection>
531
+Define a client connection
532
+profile.  Client connection profiles are groups of OpenVPN options that
533
+describe how to connect to a given OpenVPN server.  Client connection
534
+profiles are specified within an OpenVPN configuration file, and
535
+each profile is bracketed by
536
+.B <connection>
537
+and
538
+.B </connection>.
539
+
540
+An OpenVPN client will try each connection profile sequentially
541
+until it achieves a successful connection.  
542
+
543
+.B --remote-random
544
+can be used to initially "scramble" the connection
545
+list.
546
+
547
+Here is an example of connection profile usage:
548
+
549
+.RS
550
+.ft 3
551
+.nf
552
+.sp
553
+client
554
+dev tun
555
+
556
+<connection>
557
+remote 198.19.34.56 1194 udp
558
+</connection>
559
+
560
+<connection>
561
+remote 198.19.34.56 443 tcp
562
+</connection>
563
+
564
+<connection>
565
+remote 198.19.34.56 443 tcp
566
+http-proxy 192.168.0.8 8080
567
+http-proxy-retry
568
+</connection>
569
+
570
+<connection>
571
+remote 198.19.36.99 443 tcp
572
+http-proxy 192.168.0.8 8080
573
+http-proxy-retry
574
+</connection>
575
+
576
+persist-key
577
+persist-tun
578
+pkcs12 client.p12
579
+ns-cert-type server
580
+verb 3
581
+.ft
582
+.LP
583
+.RE
584
+.fi
585
+
586
+First we try to connect to a server at 198.19.34.56:1194 using UDP.
587
+If that fails, we then try to connect to 198.19.34.56:443 using TCP.
588
+If that also fails, then try connecting through an HTTP proxy at 
589
+192.168.0.8:8080 to 198.19.34.56:443 using TCP.  Finally, try to
590
+connect through the same proxy to a server at 198.19.36.99:443
591
+using TCP.
592
+
593
+The following OpenVPN options may be used inside of
594
+a
595
+.B <connection>
596
+block:
597
+
598
+.B bind,
599
+.B connect-retry,
600
+.B connect-retry-max,
601
+.B connect-timeout,
602
+.B float,
603
+.B http-proxy,
604
+.B http-proxy-option,
605
+.B http-proxy-retry,
606
+.B http-proxy-timeout,
607
+.B local,
608
+.B lport,
609
+.B nobind,
610
+.B port,
611
+.B proto,
612
+.B remote,
613
+.B rport,
614
+.B socks-proxy, and
615
+.B socks-proxy-retry.
616
+
617
+A defaulting mechanism exists for specifying options to apply to
618
+all
619
+.B <connection>
620
+profiles.  If any of the above options (with the exception of
621
+.B remote
622
+) appear outside of a
623
+.B <connection>
624
+block, but in a configuration file which has one or more
625
+.B <connection>
626
+blocks, the option setting will be used as a default for
627
+.B <connection>
628
+blocks which follow it in the configuration file.
629
+
630
+For example, suppose the
631
+.B nobind
632
+option were placed in the sample configuration file above, near
633
+the top of the file, before the first
634
+.B <connection>
635
+block.  The effect would be as if
636
+.B nobind
637
+were declared in all
638
+.B <connection>
639
+blocks below it.
640
+
641
+.\"*********************************************************
642
+.TP
530 643
 .B --remote-random
531 644
 When multiple
532 645
 .B --remote
533
-address/ports are specified, initially randomize the order of the list
646
+address/ports are specified, or if connection profiles are being
647
+used, initially randomize the order of the list
534 648
 as a kind of basic load-balancing measure.
535 649
 .\"*********************************************************
536 650
 .TP
... ...
@@ -138,7 +138,7 @@ main (int argc, char *argv[])
138 138
 #endif
139 139
 
140 140
 	  /* initialize options to default state */
141
-	  init_options (&c.options);
141
+	  init_options (&c.options, true);
142 142
 
143 143
 	  /* parse command line options, and read configuration file */
144 144
 	  parse_argv (&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, c.es);
... ...
@@ -169,7 +169,7 @@ main (int argc, char *argv[])
169 169
 	    break;
170 170
 
171 171
 	  /* sanity check on options */
172
-	  options_postprocess (&c.options, c.first_time);
172
+	  options_postprocess (&c.options);
173 173
 
174 174
 	  /* show all option settings */
175 175
 	  show_settings (&c.options);
... ...
@@ -158,9 +158,6 @@ struct context_1
158 158
   /* persist crypto sequence number to/from file */
159 159
   struct packet_id_persist pid_persist;
160 160
 
161
-  /* array of remote addresses */
162
-  struct remote_list *remote_list;
163
-
164 161
   /* TUN/TAP interface */
165 162
   struct tuntap *tuntap;
166 163
   bool tuntap_owned;
... ...
@@ -175,11 +172,13 @@ struct context_1
175 175
 #ifdef ENABLE_HTTP_PROXY
176 176
   /* HTTP proxy object */
177 177
   struct http_proxy_info *http_proxy;
178
+  bool http_proxy_owned;
178 179
 #endif
179 180
 
180 181
 #ifdef ENABLE_SOCKS
181 182
   /* SOCKS proxy object */
182 183
   struct socks_proxy_info *socks_proxy;
184
+  bool socks_proxy_owned;
183 185
 #endif
184 186
 
185 187
 #if P2MP
... ...
@@ -619,21 +619,25 @@ static const char usage_message[] =
619 619
  * will be set to 0.
620 620
  */
621 621
 void
622
-init_options (struct options *o)
622
+init_options (struct options *o, const bool init_gc)
623 623
 {
624 624
   CLEAR (*o);
625
-  gc_init (&o->gc);
625
+  if (init_gc)
626
+    {
627
+      gc_init (&o->gc);
628
+      o->gc_owned = true;
629
+    }
626 630
   o->mode = MODE_POINT_TO_POINT;
627 631
   o->topology = TOP_NET30;
628
-  o->proto = PROTO_UDPv4;
629
-  o->connect_retry_seconds = 5;
630
-  o->connect_timeout = 10;
631
-  o->connect_retry_max = 0;
632
-  o->local_port = o->remote_port = OPENVPN_PORT;
632
+  o->ce.proto = PROTO_UDPv4;
633
+  o->ce.connect_retry_seconds = 5;
634
+  o->ce.connect_timeout = 10;
635
+  o->ce.connect_retry_max = 0;
636
+  o->ce.local_port = o->ce.remote_port = OPENVPN_PORT;
633 637
   o->verbosity = 1;
634 638
   o->status_file_update_freq = 60;
635 639
   o->status_file_version = 1;
636
-  o->bind_local = true;
640
+  o->ce.bind_local = true;
637 641
   o->tun_mtu = TUN_MTU_DEFAULT;
638 642
   o->link_mtu = LINK_MTU_DEFAULT;
639 643
   o->mtu_discover_type = -1;
... ...
@@ -709,7 +713,8 @@ init_options (struct options *o)
709 709
 void
710 710
 uninit_options (struct options *o)
711 711
 {
712
-  gc_free (&o->gc);
712
+  if (o->gc_owned)
713
+    gc_free (&o->gc);
713 714
 }
714 715
 
715 716
 #ifdef ENABLE_DEBUG
... ...
@@ -724,46 +729,50 @@ uninit_options (struct options *o)
724 724
 #endif
725 725
 
726 726
 void
727
+setenv_connection_entry (struct env_set *es,
728
+			 const struct connection_entry *e,
729
+			 const int i)
730
+{
731
+  setenv_str_i (es, "proto", proto2ascii (e->proto, false), i);
732
+  setenv_str_i (es, "local", e->local, i);
733
+  setenv_int_i (es, "local_port", e->local_port, i);
734
+  setenv_str_i (es, "remote", e->local, i);
735
+  setenv_int_i (es, "remote_port", e->local_port, i);
736
+
737
+#ifdef ENABLE_HTTP_PROXY
738
+  if (e->http_proxy_options)
739
+    {
740
+      setenv_str_i (es, "http_proxy_server", e->http_proxy_options->server, i);
741
+      setenv_int_i (es, "http_proxy_port", e->http_proxy_options->port, i);
742
+    }
743
+#endif
744
+#ifdef ENABLE_SOCKS
745
+  if (e->socks_proxy_server)
746
+    {
747
+      setenv_str_i (es, "socks_proxy_server", e->socks_proxy_server, i);
748
+      setenv_int_i (es, "socks_proxy_port", e->socks_proxy_port, i);
749
+    }
750
+#endif
751
+}
752
+
753
+void
727 754
 setenv_settings (struct env_set *es, const struct options *o)
728 755
 {
729 756
   setenv_str (es, "config", o->config);
730
-  setenv_str (es, "proto", proto2ascii (o->proto, false));
731
-  setenv_str (es, "local", o->local);
732
-  setenv_int (es, "local_port", o->local_port);
733 757
   setenv_int (es, "verb", o->verbosity);
734 758
   setenv_int (es, "daemon", o->daemon);
735 759
   setenv_int (es, "daemon_log_redirect", o->log);
736 760
 
737
-  if (o->remote_list)
761
+#ifdef ENABLE_CONNECTION
762
+  if (o->connection_list)
738 763
     {
739 764
       int i;
740
-
741
-      for (i = 0; i < o->remote_list->len; ++i)
742
-	{
743
-	  char remote_string[64];
744
-	  char remote_port_string[64];
745
-
746
-	  openvpn_snprintf (remote_string, sizeof (remote_string), "remote_%d", i+1);
747
-	  openvpn_snprintf (remote_port_string, sizeof (remote_port_string), "remote_port_%d", i+1);
748
-
749
-	  setenv_str (es, remote_string,      o->remote_list->array[i].hostname);
750
-	  setenv_int (es, remote_port_string, o->remote_list->array[i].port);
751
-	}
765
+      for (i = 0; i < o->connection_list->len; ++i)
766
+	setenv_connection_entry (es, o->connection_list->array[i], i+1);
752 767
     }
753
-#ifdef ENABLE_HTTP_PROXY
754
-    if (o->http_proxy_options)
755
-      {
756
-        setenv_str (es, "http_proxy_server", o->http_proxy_options->server);
757
-        setenv_int (es, "http_proxy_port", o->http_proxy_options->port);
758
-      }
759
-#endif
760
-#ifdef ENABLE_SOCKS
761
-    if(o->socks_proxy_server)
762
-      {
763
-        setenv_str (es, "socks_proxy_server", o->socks_proxy_server);
764
-        setenv_int (es, "socks_proxy_port", o->socks_proxy_port);
765
-      }
768
+  else
766 769
 #endif
770
+    setenv_connection_entry (es, &o->ce, 1);
767 771
 }
768 772
 
769 773
 static in_addr_t
... ...
@@ -816,7 +825,7 @@ is_persist_option (const struct options *o)
816 816
 bool
817 817
 is_stateful_restart (const struct options *o)
818 818
 {
819
-  return is_persist_option (o) || (o->remote_list && o->remote_list->len > 1);
819
+  return is_persist_option (o) || connection_list_defined (o);
820 820
 }
821 821
 
822 822
 #ifdef WIN32
... ...
@@ -983,26 +992,6 @@ option_iroute (struct options *o,
983 983
 #endif /* P2MP_SERVER */
984 984
 #endif /* P2MP */
985 985
 
986
-#ifdef ENABLE_DEBUG
987
-static void
988
-show_remote_list (const struct remote_list *l)
989
-{
990
-  if (l)
991
-    {
992
-      int i;
993
-      for (i = 0; i < l->len; ++i)
994
-	{
995
-	  msg (D_SHOW_PARMS, "  remote_list[%d] = {'%s', %d}",
996
-	       i, l->array[i].hostname, l->array[i].port);
997
-	}
998
-    }
999
-  else
1000
-    {
1001
-      msg (D_SHOW_PARMS, "  remote_list = NULL");
1002
-    }
1003
-}
1004
-#endif
1005
-
1006 986
 #if defined(ENABLE_HTTP_PROXY) && defined(ENABLE_DEBUG)
1007 987
 static void
1008 988
 show_http_proxy_options (const struct http_proxy_options *o)
... ...
@@ -1042,6 +1031,55 @@ rol_check_alloc (struct options *options)
1042 1042
     options->routes = new_route_option_list (&options->gc);
1043 1043
 }
1044 1044
 
1045
+#ifdef ENABLE_DEBUG
1046
+static void
1047
+show_connection_entry (const struct connection_entry *o)
1048
+{
1049
+  msg (D_SHOW_PARMS, "  proto = %s", proto2ascii (o->proto, false));
1050
+  SHOW_STR (local);
1051
+  SHOW_INT (local_port);
1052
+  SHOW_STR (remote);
1053
+  SHOW_INT (remote_port);
1054
+  SHOW_BOOL (remote_float);
1055
+  SHOW_BOOL (bind_defined);
1056
+  SHOW_BOOL (bind_local);
1057
+  SHOW_INT (connect_retry_seconds);
1058
+  SHOW_INT (connect_timeout);
1059
+  SHOW_INT (connect_retry_max);
1060
+
1061
+#ifdef ENABLE_HTTP_PROXY
1062
+  if (o->http_proxy_options)
1063
+    show_http_proxy_options (o->http_proxy_options);
1064
+#endif
1065
+#ifdef ENABLE_SOCKS
1066
+  SHOW_STR (socks_proxy_server);
1067
+  SHOW_INT (socks_proxy_port);
1068
+  SHOW_BOOL (socks_proxy_retry);
1069
+#endif
1070
+}
1071
+
1072
+static void
1073
+show_connection_entries (const struct options *o)
1074
+{
1075
+  msg (D_SHOW_PARMS, "Connection profiles [default]:");
1076
+  show_connection_entry (&o->ce);
1077
+#ifdef ENABLE_CONNECTION
1078
+ if (o->connection_list)
1079
+   {
1080
+     const struct connection_list *l = o->connection_list;
1081
+     int i;
1082
+     for (i = 0; i < l->len; ++i)
1083
+       {
1084
+	 msg (D_SHOW_PARMS, "Connection profiles [%d]:", i);
1085
+	 show_connection_entry (l->array[i]);
1086
+       }
1087
+   }
1088
+#endif
1089
+  msg (D_SHOW_PARMS, "Connection profiles END");
1090
+}
1091
+
1092
+#endif
1093
+
1045 1094
 void
1046 1095
 show_settings (const struct options *o)
1047 1096
 {
... ...
@@ -1068,17 +1106,11 @@ show_settings (const struct options *o)
1068 1068
 #endif
1069 1069
 #endif
1070 1070
 
1071
-  SHOW_INT (proto);
1072
-  SHOW_STR (local);
1073
-  show_remote_list (o->remote_list);
1071
+  show_connection_entries (o);
1072
+
1074 1073
   SHOW_BOOL (remote_random);
1075 1074
 
1076
-  SHOW_INT (local_port);
1077
-  SHOW_INT (remote_port);
1078
-  SHOW_BOOL (remote_float);
1079 1075
   SHOW_STR (ipchange);
1080
-  SHOW_BOOL (bind_defined);
1081
-  SHOW_BOOL (bind_local);
1082 1076
   SHOW_STR (dev);
1083 1077
   SHOW_STR (dev_type);
1084 1078
   SHOW_STR (dev_node);
... ...
@@ -1135,9 +1167,6 @@ show_settings (const struct options *o)
1135 1135
 #endif
1136 1136
 
1137 1137
   SHOW_INT (resolve_retry_seconds);
1138
-  SHOW_INT (connect_retry_seconds);
1139
-  SHOW_INT (connect_timeout);
1140
-  SHOW_INT (connect_retry_max);
1141 1138
 
1142 1139
   SHOW_STR (username);
1143 1140
   SHOW_STR (groupname);
... ...
@@ -1170,17 +1199,6 @@ show_settings (const struct options *o)
1170 1170
   SHOW_INT (sndbuf);
1171 1171
   SHOW_INT (sockflags);
1172 1172
 
1173
-#ifdef ENABLE_HTTP_PROXY
1174
-  if (o->http_proxy_options)
1175
-    show_http_proxy_options (o->http_proxy_options);
1176
-#endif
1177
-
1178
-#ifdef ENABLE_SOCKS
1179
-  SHOW_STR (socks_proxy_server);
1180
-  SHOW_INT (socks_proxy_port);
1181
-  SHOW_BOOL (socks_proxy_retry);
1182
-#endif
1183
-
1184 1173
   SHOW_BOOL (fast_io);
1185 1174
 
1186 1175
 #ifdef USE_LZO
... ...
@@ -1318,32 +1336,89 @@ show_settings (const struct options *o)
1318 1318
 struct http_proxy_options *
1319 1319
 init_http_options_if_undefined (struct options *o)
1320 1320
 {
1321
-  if (!o->http_proxy_options)
1321
+  if (!o->ce.http_proxy_options)
1322 1322
     {
1323
-      ALLOC_OBJ_CLEAR_GC (o->http_proxy_options, struct http_proxy_options, &o->gc);
1323
+      ALLOC_OBJ_CLEAR_GC (o->ce.http_proxy_options, struct http_proxy_options, &o->gc);
1324 1324
       /* http proxy defaults */
1325
-      o->http_proxy_options->timeout = 5;
1326
-      o->http_proxy_options->http_version = "1.0";
1325
+      o->ce.http_proxy_options->timeout = 5;
1326
+      o->ce.http_proxy_options->http_version = "1.0";
1327 1327
     }
1328
-  return o->http_proxy_options;
1328
+  return o->ce.http_proxy_options;
1329
+}
1330
+
1331
+#endif
1332
+
1333
+#if ENABLE_CONNECTION
1334
+
1335
+static struct connection_list *
1336
+alloc_connection_list_if_undef (struct options *options)
1337
+{
1338
+  if (!options->connection_list)
1339
+    ALLOC_OBJ_CLEAR_GC (options->connection_list, struct connection_list, &options->gc);
1340
+  return options->connection_list;
1341
+}
1342
+
1343
+static struct connection_entry *
1344
+alloc_connection_entry (struct options *options, const int msglevel)
1345
+{
1346
+  struct connection_list *l = alloc_connection_list_if_undef (options);
1347
+  struct connection_entry *e;
1348
+
1349
+  if (l->len >= CONNECTION_LIST_SIZE)
1350
+    {
1351
+      msg (msglevel, "Maximum number of 'connection' options (%d) exceeded", CONNECTION_LIST_SIZE);
1352
+      return NULL;
1353
+    }
1354
+  ALLOC_OBJ_GC (e, struct connection_entry, &options->gc);
1355
+  l->array[l->len++] = e;
1356
+  return e;
1357
+}
1358
+
1359
+static struct remote_list *
1360
+alloc_remote_list_if_undef (struct options *options)
1361
+{
1362
+  if (!options->remote_list)
1363
+    ALLOC_OBJ_CLEAR_GC (options->remote_list, struct remote_list, &options->gc);
1364
+  return options->remote_list;
1365
+}
1366
+
1367
+static struct remote_entry *
1368
+alloc_remote_entry (struct options *options, const int msglevel)
1369
+{
1370
+  struct remote_list *l = alloc_remote_list_if_undef (options);
1371
+  struct remote_entry *e;
1372
+
1373
+  if (l->len >= CONNECTION_LIST_SIZE)
1374
+    {
1375
+      msg (msglevel, "Maximum number of 'remote' options (%d) exceeded", CONNECTION_LIST_SIZE);
1376
+      return NULL;
1377
+    }
1378
+  ALLOC_OBJ_GC (e, struct remote_entry, &options->gc);
1379
+  l->array[l->len++] = e;
1380
+  return e;
1329 1381
 }
1330 1382
 
1331 1383
 #endif
1332 1384
 
1333
-/*
1334
- * Sanity check on options.
1335
- * Also set some options based on other
1336
- * options.
1337
- */
1338 1385
 void
1339
-options_postprocess (struct options *options, bool first_time)
1386
+connection_entry_load_re (struct connection_entry *ce, const struct remote_entry *re)
1387
+{
1388
+  if (re->remote)
1389
+    ce->remote = re->remote;
1390
+  if (re->remote_port >= 0)
1391
+    ce->remote_port = re->remote_port;
1392
+  if (re->proto >= 0)
1393
+    ce->proto = re->proto;
1394
+}
1395
+
1396
+static void
1397
+options_postprocess_verify_ce (const struct options *options, const struct connection_entry *ce)
1340 1398
 {
1341 1399
   struct options defaults;
1342 1400
   int dev = DEV_TYPE_UNDEF;
1343
-  int i;
1344 1401
   bool pull = false;
1345 1402
 
1346
-  init_options (&defaults);
1403
+  init_options (&defaults, true);
1347 1404
 
1348 1405
 #ifdef USE_CRYPTO
1349 1406
   if (options->test_crypto)
... ...
@@ -1360,31 +1435,11 @@ options_postprocess (struct options *options, bool first_time)
1360 1360
   dev = dev_type_enum (options->dev, options->dev_type);
1361 1361
 
1362 1362
   /*
1363
-   * Fill in default port number for --remote list
1364
-   */
1365
-  if (options->remote_list)
1366
-    {
1367
-      for (i = 0; i < options->remote_list->len; ++i)
1368
-	{
1369
-	  struct remote_entry *e = &options->remote_list->array[i];
1370
-	  if (e->port < 0)
1371
-	    e->port = options->remote_port;
1372
-	}
1373
-    }
1374
-
1375
-  /*
1376
-   * If --mssfix is supplied without a parameter, default
1377
-   * it to --fragment value, if --fragment is specified.
1363
+   * If "proto tcp" is specified, make sure we know whether it is
1364
+   * tcp-client or tcp-server.
1378 1365
    */
1379
-  if (options->mssfix_default)
1380
-    {
1381
-#ifdef ENABLE_FRAGMENT
1382
-      if (options->fragment)
1383
-	options->mssfix = options->fragment;
1384
-#else
1385
-      msg (M_USAGE, "--mssfix must specify a parameter");
1386
-#endif      
1387
-    }
1366
+  if (ce->proto == PROTO_TCPv4)
1367
+    msg (M_USAGE, "--proto tcp is ambiguous in this context.  Please specify --proto tcp-server or --proto tcp-client");
1388 1368
 
1389 1369
   /*
1390 1370
    * Sanity check on daemon/inetd modes
... ...
@@ -1393,13 +1448,13 @@ options_postprocess (struct options *options, bool first_time)
1393 1393
   if (options->daemon && options->inetd)
1394 1394
     msg (M_USAGE, "only one of --daemon or --inetd may be specified");
1395 1395
 
1396
-  if (options->inetd && (options->local || options->remote_list))
1396
+  if (options->inetd && (ce->local || ce->remote))
1397 1397
     msg (M_USAGE, "--local or --remote cannot be used with --inetd");
1398 1398
 
1399
-  if (options->inetd && options->proto == PROTO_TCPv4_CLIENT)
1399
+  if (options->inetd && ce->proto == PROTO_TCPv4_CLIENT)
1400 1400
     msg (M_USAGE, "--proto tcp-client cannot be used with --inetd");
1401 1401
 
1402
-  if (options->inetd == INETD_NOWAIT && options->proto != PROTO_TCPv4_SERVER)
1402
+  if (options->inetd == INETD_NOWAIT && ce->proto != PROTO_TCPv4_SERVER)
1403 1403
     msg (M_USAGE, "--inetd nowait can only be used with --proto tcp-server");
1404 1404
 
1405 1405
   if (options->inetd == INETD_NOWAIT
... ...
@@ -1417,20 +1472,13 @@ options_postprocess (struct options *options, bool first_time)
1417 1417
     msg (M_USAGE, "--lladdr can only be used in --dev tap mode");
1418 1418
  
1419 1419
   /*
1420
-   * In forking TCP server mode, you don't need to ifconfig
1421
-   * the tap device (the assumption is that it will be bridged).
1422
-   */
1423
-  if (options->inetd == INETD_NOWAIT)
1424
-    options->ifconfig_noexec = true;
1425
-
1426
-  /*
1427 1420
    * Sanity check on TCP mode options
1428 1421
    */
1429 1422
 
1430
-  if (options->connect_retry_defined && options->proto != PROTO_TCPv4_CLIENT)
1423
+  if (ce->connect_retry_defined && ce->proto != PROTO_TCPv4_CLIENT)
1431 1424
     msg (M_USAGE, "--connect-retry doesn't make sense unless also used with --proto tcp-client");
1432 1425
 
1433
-  if (options->connect_timeout_defined && options->proto != PROTO_TCPv4_CLIENT)
1426
+  if (ce->connect_timeout_defined && ce->proto != PROTO_TCPv4_CLIENT)
1434 1427
     msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with --proto tcp-client");
1435 1428
 
1436 1429
   /*
... ...
@@ -1440,32 +1488,10 @@ options_postprocess (struct options *options, bool first_time)
1440 1440
     msg (M_USAGE, "only one of --tun-mtu or --link-mtu may be defined (note that --ifconfig implies --link-mtu %d)", LINK_MTU_DEFAULT);
1441 1441
 
1442 1442
 #ifdef ENABLE_OCC
1443
-  if (options->proto != PROTO_UDPv4 && options->mtu_test)
1443
+  if (ce->proto != PROTO_UDPv4 && options->mtu_test)
1444 1444
     msg (M_USAGE, "--mtu-test only makes sense with --proto udp");
1445 1445
 #endif
1446 1446
 
1447
-  /*
1448
-   * Set MTU defaults
1449
-   */
1450
-  {
1451
-    if (!options->tun_mtu_defined && !options->link_mtu_defined)
1452
-      {
1453
-	options->tun_mtu_defined = true;
1454
-      }
1455
-    if ((dev == DEV_TYPE_TAP) && !options->tun_mtu_extra_defined)
1456
-      {
1457
-	options->tun_mtu_extra_defined = true;
1458
-	options->tun_mtu_extra = TAP_MTU_EXTRA_DEFAULT;
1459
-      }
1460
-  }
1461
-
1462
-  /*
1463
-   * Process helper-type options which map to other, more complex
1464
-   * sequences of options.
1465
-   */
1466
-  helper_client_server (options);
1467
-  helper_keepalive (options);
1468
-
1469 1447
   /* will we be pulling options from server? */
1470 1448
 #if P2MP
1471 1449
   pull = options->pull;
... ...
@@ -1475,56 +1501,33 @@ options_postprocess (struct options *options, bool first_time)
1475 1475
    * Sanity check on --local, --remote, and --ifconfig
1476 1476
    */
1477 1477
 
1478
-  if (options->remote_list)
1479
-    {
1480
-      int i;
1481
-      struct remote_list *l = options->remote_list;
1482
-
1483
-      for (i = 0; i < l->len; ++i)
1484
-	{
1485
-	  const char *remote = l->array[i].hostname;
1486
-	  const int remote_port = l->array[i].port;
1487
-
1488
-	  if (string_defined_equal (options->local, remote)
1489
-	      && options->local_port == remote_port)
1490
-	    msg (M_USAGE, "--remote and --local addresses are the same");
1491
-	
1492
-	  if (string_defined_equal (remote, options->ifconfig_local)
1493
-	      || string_defined_equal (remote, options->ifconfig_remote_netmask))
1494
-	    msg (M_USAGE, "--local and --remote addresses must be distinct from --ifconfig addresses");
1495
-	}
1496
-    }
1478
+  if (string_defined_equal (ce->local, ce->remote)
1479
+      && ce->local_port == ce->remote_port)
1480
+    msg (M_USAGE, "--remote and --local addresses are the same");
1481
+  
1482
+  if (string_defined_equal (ce->remote, options->ifconfig_local)
1483
+      || string_defined_equal (ce->remote, options->ifconfig_remote_netmask))
1484
+    msg (M_USAGE, "--local and --remote addresses must be distinct from --ifconfig addresses");
1497 1485
 
1498
-  if (string_defined_equal (options->local, options->ifconfig_local)
1499
-      || string_defined_equal (options->local, options->ifconfig_remote_netmask))
1486
+  if (string_defined_equal (ce->local, options->ifconfig_local)
1487
+      || string_defined_equal (ce->local, options->ifconfig_remote_netmask))
1500 1488
     msg (M_USAGE, "--local addresses must be distinct from --ifconfig addresses");
1501 1489
 
1502 1490
   if (string_defined_equal (options->ifconfig_local, options->ifconfig_remote_netmask))
1503 1491
     msg (M_USAGE, "local and remote/netmask --ifconfig addresses must be different");
1504 1492
 
1505
-  if (options->bind_defined && !options->bind_local)
1493
+  if (ce->bind_defined && !ce->bind_local)
1506 1494
     msg (M_USAGE, "--bind and --nobind can't be used together");
1507 1495
 
1508
-  if (options->local && !options->bind_local)
1496
+  if (ce->local && !ce->bind_local)
1509 1497
     msg (M_USAGE, "--local and --nobind don't make sense when used together");
1510 1498
 
1511
-  if (options->local_port_defined && !options->bind_local)
1499
+  if (ce->local_port_defined && !ce->bind_local)
1512 1500
     msg (M_USAGE, "--lport and --nobind don't make sense when used together");
1513 1501
 
1514
-  if (!options->remote_list && !options->bind_local)
1502
+  if (!ce->remote && !ce->bind_local)
1515 1503
     msg (M_USAGE, "--nobind doesn't make sense unless used with --remote");
1516 1504
 
1517
-  if (options->proto == PROTO_TCPv4_CLIENT && !options->local && !options->local_port_defined && !options->bind_defined)
1518
-    options->bind_local = false;
1519
-
1520
-#ifdef ENABLE_SOCKS
1521
-  if (options->proto == PROTO_UDPv4 && options->socks_proxy_server && !options->local && !options->local_port_defined && !options->bind_defined)
1522
-    options->bind_local = false;
1523
-#endif
1524
-
1525
-  if (!options->bind_local)
1526
-    options->local_port = 0;
1527
-
1528 1505
   /*
1529 1506
    * Check for consistency of management options
1530 1507
    */
... ...
@@ -1552,18 +1555,6 @@ options_postprocess (struct options *options, bool first_time)
1552 1552
 	  && options->tuntap_options.ip_win32_type != IPW32_SET_DHCP_MASQ
1553 1553
 	  && options->tuntap_options.ip_win32_type != IPW32_SET_ADAPTIVE)
1554 1554
 	msg (M_USAGE, "--dhcp-options requires --ip-win32 dynamic or adaptive");
1555
-
1556
-      if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && !options->route_delay_defined)
1557
-	{
1558
-	  options->route_delay_defined = true;
1559
-	  options->route_delay = 5; /* Vista sometimes has a race without this */
1560
-	}
1561
-
1562
-      if (options->ifconfig_noexec)
1563
-	{
1564
-	  options->tuntap_options.ip_win32_type = IPW32_SET_MANUAL;
1565
-	  options->ifconfig_noexec = false;
1566
-	}
1567 1555
 #endif
1568 1556
 
1569 1557
   /*
... ...
@@ -1571,34 +1562,34 @@ options_postprocess (struct options *options, bool first_time)
1571 1571
    */
1572 1572
 
1573 1573
 #ifdef ENABLE_FRAGMENT
1574
-  if (options->proto != PROTO_UDPv4 && options->fragment)
1574
+  if (ce->proto != PROTO_UDPv4 && options->fragment)
1575 1575
     msg (M_USAGE, "--fragment can only be used with --proto udp");
1576 1576
 #endif
1577 1577
 
1578 1578
 #ifdef ENABLE_OCC
1579
-  if (options->proto != PROTO_UDPv4 && options->explicit_exit_notification)
1579
+  if (ce->proto != PROTO_UDPv4 && options->explicit_exit_notification)
1580 1580
     msg (M_USAGE, "--explicit-exit-notify can only be used with --proto udp");
1581 1581
 #endif
1582 1582
 
1583
-  if (!options->remote_list && options->proto == PROTO_TCPv4_CLIENT)
1583
+  if (!ce->remote && ce->proto == PROTO_TCPv4_CLIENT)
1584 1584
     msg (M_USAGE, "--remote MUST be used in TCP Client mode");
1585 1585
 
1586 1586
 #ifdef ENABLE_HTTP_PROXY
1587
-  if ((options->http_proxy_options || options->auto_proxy_info) && options->proto != PROTO_TCPv4_CLIENT)
1587
+  if ((ce->http_proxy_options || options->auto_proxy_info) && ce->proto != PROTO_TCPv4_CLIENT)
1588 1588
     msg (M_USAGE, "--http-proxy or --auto-proxy MUST be used in TCP Client mode (i.e. --proto tcp-client)");
1589 1589
 #endif
1590 1590
 
1591 1591
 #if defined(ENABLE_HTTP_PROXY) && defined(ENABLE_SOCKS)
1592
-  if (options->http_proxy_options && options->socks_proxy_server)
1592
+  if (ce->http_proxy_options && ce->socks_proxy_server)
1593 1593
     msg (M_USAGE, "--http-proxy can not be used together with --socks-proxy");
1594 1594
 #endif
1595 1595
 
1596 1596
 #ifdef ENABLE_SOCKS
1597
-  if (options->socks_proxy_server && options->proto == PROTO_TCPv4_SERVER)
1597
+  if (ce->socks_proxy_server && ce->proto == PROTO_TCPv4_SERVER)
1598 1598
     msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode");
1599 1599
 #endif
1600 1600
 
1601
-  if (options->proto == PROTO_TCPv4_SERVER && remote_list_len (options->remote_list) > 1)
1601
+  if (ce->proto == PROTO_TCPv4_SERVER && connection_list_defined (options))
1602 1602
     msg (M_USAGE, "TCP server mode allows at most one --remote address");
1603 1603
 
1604 1604
 #if P2MP_SERVER
... ...
@@ -1608,41 +1599,34 @@ options_postprocess (struct options *options, bool first_time)
1608 1608
    */
1609 1609
   if (options->mode == MODE_SERVER)
1610 1610
     {
1611
-#ifdef WIN32
1612
-      /*
1613
-       * We need to explicitly set --tap-sleep because
1614
-       * we do not schedule event timers in the top-level context.
1615
-       */
1616
-      options->tuntap_options.tap_sleep = 10;
1617
-      if (options->route_delay_defined && options->route_delay)
1618
-	options->tuntap_options.tap_sleep = options->route_delay;	
1619
-      options->route_delay_defined = false;
1620
-#endif
1621
-
1622 1611
       if (!(dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP))
1623 1612
 	msg (M_USAGE, "--mode server only works with --dev tun or --dev tap");
1624 1613
       if (options->pull)
1625 1614
 	msg (M_USAGE, "--pull cannot be used with --mode server");
1626
-      if (!(options->proto == PROTO_UDPv4 || options->proto == PROTO_TCPv4_SERVER))
1615
+      if (!(ce->proto == PROTO_UDPv4 || ce->proto == PROTO_TCPv4_SERVER))
1627 1616
 	msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server");
1628 1617
 #if PORT_SHARE
1629
-      if ((options->port_share_host || options->port_share_port) && options->proto != PROTO_TCPv4_SERVER)
1618
+      if ((options->port_share_host || options->port_share_port) && ce->proto != PROTO_TCPv4_SERVER)
1630 1619
 	msg (M_USAGE, "--port-share only works in TCP server mode (--proto tcp-server)");
1631 1620
 #endif
1632 1621
       if (!options->tls_server)
1633 1622
 	msg (M_USAGE, "--mode server requires --tls-server");
1634
-      if (options->remote_list)
1623
+      if (ce->remote)
1635 1624
 	msg (M_USAGE, "--remote cannot be used with --mode server");
1636
-      if (!options->bind_local)
1625
+      if (!ce->bind_local)
1637 1626
 	msg (M_USAGE, "--nobind cannot be used with --mode server");
1638 1627
 #ifdef ENABLE_HTTP_PROXY
1639
-      if (options->http_proxy_options)
1628
+      if (ce->http_proxy_options)
1640 1629
 	msg (M_USAGE, "--http-proxy cannot be used with --mode server");
1641 1630
 #endif
1642 1631
 #ifdef ENABLE_SOCKS
1643
-      if (options->socks_proxy_server)
1632
+      if (ce->socks_proxy_server)
1644 1633
 	msg (M_USAGE, "--socks-proxy cannot be used with --mode server");
1645 1634
 #endif
1635
+#ifdef ENABLE_CONNECTION
1636
+      if (options->connection_list)
1637
+	msg (M_USAGE, "<connection> cannot be used with --mode server");
1638
+#endif
1646 1639
       if (options->tun_ipv6)
1647 1640
 	msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server");
1648 1641
       if (options->shaper)
... ...
@@ -1651,9 +1635,9 @@ options_postprocess (struct options *options, bool first_time)
1651 1651
 	msg (M_USAGE, "--inetd cannot be used with --mode server");
1652 1652
       if (options->ipchange)
1653 1653
 	msg (M_USAGE, "--ipchange cannot be used with --mode server (use --client-connect instead)");
1654
-      if (!(options->proto == PROTO_UDPv4 || options->proto == PROTO_TCPv4_SERVER))
1654
+      if (!(ce->proto == PROTO_UDPv4 || ce->proto == PROTO_TCPv4_SERVER))
1655 1655
 	msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server");
1656
-      if (options->proto != PROTO_UDPv4 && (options->cf_max || options->cf_per))
1656
+      if (ce->proto != PROTO_UDPv4 && (options->cf_max || options->cf_per))
1657 1657
 	msg (M_USAGE, "--connect-freq only works with --mode server --proto udp.  Try --max-clients instead.");
1658 1658
       if (!(dev == DEV_TYPE_TAP || (dev == DEV_TYPE_TUN && options->topology == TOP_SUBNET)) && options->ifconfig_pool_netmask)
1659 1659
 	msg (M_USAGE, "The third parameter to --ifconfig-pool (netmask) is only valid in --dev tap mode");
... ...
@@ -1733,7 +1717,7 @@ options_postprocess (struct options *options, bool first_time)
1733 1733
   /*
1734 1734
    * Check consistency of replay options
1735 1735
    */
1736
-  if ((options->proto != PROTO_UDPv4)
1736
+  if ((ce->proto != PROTO_UDPv4)
1737 1737
       && (options->replay_window != defaults.replay_window
1738 1738
 	  || options->replay_time != defaults.replay_time))
1739 1739
     msg (M_USAGE, "--replay-window only makes sense with --proto udp");
... ...
@@ -1743,13 +1727,6 @@ options_postprocess (struct options *options, bool first_time)
1743 1743
 	  || options->replay_time != defaults.replay_time))
1744 1744
     msg (M_USAGE, "--replay-window doesn't make sense when replay protection is disabled with --no-replay");
1745 1745
 
1746
-  /* 
1747
-   * Don't use replay window for TCP mode (i.e. require that packets
1748
-   * be strictly in sequence).
1749
-   */
1750
-  if (link_socket_proto_connection_oriented (options->proto))
1751
-    options->replay_window = options->replay_time = 0;
1752
-
1753 1746
   /*
1754 1747
    * SSL/TLS mode sanity checks.
1755 1748
    */
... ...
@@ -1887,30 +1864,211 @@ options_postprocess (struct options *options, bool first_time)
1887 1887
 #endif /* USE_SSL */
1888 1888
 
1889 1889
 #if P2MP
1890
+  if (options->auth_user_pass_file && !options->pull)
1891
+    msg (M_USAGE, "--auth-user-pass requires --pull");
1892
+#endif
1893
+
1894
+  uninit_options (&defaults);
1895
+}
1896
+
1897
+static void
1898
+options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
1899
+{
1900
+#if P2MP_SERVER
1901
+  if (o->server_defined || o->server_bridge_defined)
1902
+    {
1903
+      if (ce->proto == PROTO_TCPv4)
1904
+	ce->proto = PROTO_TCPv4_SERVER;
1905
+    }
1906
+#endif
1907
+#if P2MP
1908
+  if (o->client)
1909
+    {
1910
+      if (ce->proto == PROTO_TCPv4)
1911
+	ce->proto = PROTO_TCPv4_CLIENT;
1912
+    }
1913
+#endif
1914
+
1915
+  if (ce->proto == PROTO_TCPv4_CLIENT && !ce->local && !ce->local_port_defined && !ce->bind_defined)
1916
+    ce->bind_local = false;
1917
+
1918
+#ifdef ENABLE_SOCKS
1919
+  if (ce->proto == PROTO_UDPv4 && ce->socks_proxy_server && !ce->local && !ce->local_port_defined && !ce->bind_defined)
1920
+    ce->bind_local = false;
1921
+#endif
1922
+
1923
+  if (!ce->bind_local)
1924
+    ce->local_port = 0;
1925
+}
1926
+
1927
+static void
1928
+options_postprocess_mutate_invariant (struct options *options)
1929
+{
1930
+  const int dev = dev_type_enum (options->dev, options->dev_type);
1931
+
1890 1932
   /*
1891
-   * In pull mode, we usually import --ping/--ping-restart parameters from
1892
-   * the server.  However we should also set an initial default --ping-restart
1893
-   * for the period of time before we pull the --ping-restart parameter
1894
-   * from the server.
1933
+   * If --mssfix is supplied without a parameter, default
1934
+   * it to --fragment value, if --fragment is specified.
1895 1935
    */
1896
-  if (options->pull
1897
-      && options->ping_rec_timeout_action == PING_UNDEF
1898
-      && options->proto == PROTO_UDPv4)
1936
+  if (options->mssfix_default)
1899 1937
     {
1900
-      options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART;
1901
-      options->ping_rec_timeout_action = PING_RESTART;
1938
+#ifdef ENABLE_FRAGMENT
1939
+      if (options->fragment)
1940
+	options->mssfix = options->fragment;
1941
+#else
1942
+      msg (M_USAGE, "--mssfix must specify a parameter");
1943
+#endif      
1902 1944
     }
1903 1945
 
1904
-  if (options->auth_user_pass_file && !options->pull)
1905
-    msg (M_USAGE, "--auth-user-pass requires --pull");
1946
+  /*
1947
+   * In forking TCP server mode, you don't need to ifconfig
1948
+   * the tap device (the assumption is that it will be bridged).
1949
+   */
1950
+  if (options->inetd == INETD_NOWAIT)
1951
+    options->ifconfig_noexec = true;
1906 1952
 
1907 1953
   /*
1954
+   * Set MTU defaults
1955
+   */
1956
+  {
1957
+    if (!options->tun_mtu_defined && !options->link_mtu_defined)
1958
+      {
1959
+	options->tun_mtu_defined = true;
1960
+      }
1961
+    if ((dev == DEV_TYPE_TAP) && !options->tun_mtu_extra_defined)
1962
+      {
1963
+	options->tun_mtu_extra_defined = true;
1964
+	options->tun_mtu_extra = TAP_MTU_EXTRA_DEFAULT;
1965
+      }
1966
+  }
1967
+
1968
+#ifdef WIN32
1969
+  if ((dev == DEV_TYPE_TUN || dev == DEV_TYPE_TAP) && !options->route_delay_defined)
1970
+    {
1971
+      if (options->mode == MODE_POINT_TO_POINT)
1972
+	{
1973
+	  options->route_delay_defined = true;
1974
+	  options->route_delay = 5; /* Vista sometimes has a race without this */
1975
+	}
1976
+    }
1977
+
1978
+  if (options->ifconfig_noexec)
1979
+    {
1980
+      options->tuntap_options.ip_win32_type = IPW32_SET_MANUAL;
1981
+      options->ifconfig_noexec = false;
1982
+    }
1983
+#endif
1984
+
1985
+#if P2MP_SERVER
1986
+  /*
1987
+   * Check consistency of --mode server options.
1988
+   */
1989
+  if (options->mode == MODE_SERVER)
1990
+    {
1991
+#ifdef WIN32
1992
+      /*
1993
+       * We need to explicitly set --tap-sleep because
1994
+       * we do not schedule event timers in the top-level context.
1995
+       */
1996
+      options->tuntap_options.tap_sleep = 10;
1997
+      if (options->route_delay_defined && options->route_delay)
1998
+	options->tuntap_options.tap_sleep = options->route_delay;	
1999
+      options->route_delay_defined = false;
2000
+#endif
2001
+    }
2002
+#endif
2003
+}
2004
+
2005
+static void
2006
+options_postprocess_verify (const struct options *o)
2007
+{
2008
+#ifdef ENABLE_CONNECTION
2009
+  if (o->connection_list)
2010
+    {
2011
+      int i;
2012
+      for (i = 0; i < o->connection_list->len; ++i)
2013
+	options_postprocess_verify_ce (o, o->connection_list->array[i]);
2014
+    }
2015
+  else
2016
+#endif
2017
+    options_postprocess_verify_ce (o, &o->ce);
2018
+}
2019
+
2020
+static void
2021
+options_postprocess_mutate (struct options *o)
2022
+{
2023
+  /*
2024
+   * Process helper-type options which map to other, more complex
2025
+   * sequences of options.
2026
+   */
2027
+  helper_client_server (o);
2028
+  helper_keepalive (o);
2029
+
2030
+  options_postprocess_mutate_invariant (o);
2031
+
2032
+#ifdef ENABLE_CONNECTION
2033
+  if (o->remote_list && !o->connection_list)
2034
+    {
2035
+      /*
2036
+       * For compatibility with 2.0.x, map multiple --remote options
2037
+       * into connection list (connection lists added in 2.1).
2038
+       */
2039
+      if (o->remote_list->len > 1)
2040
+	{
2041
+	  const struct remote_list *rl = o->remote_list;
2042
+	  int i;
2043
+	  for (i = 0; i < rl->len; ++i)
2044
+	    {
2045
+	      const struct remote_entry *re = rl->array[i];
2046
+	      struct connection_entry ce = o->ce;
2047
+	      struct connection_entry *ace;
2048
+
2049
+	      ASSERT (re->remote);
2050
+	      connection_entry_load_re (&ce, re);
2051
+	      ace = alloc_connection_entry (o, M_USAGE);
2052
+	      ASSERT (ace);
2053
+	      *ace = ce;
2054
+	    }
2055
+	}
2056
+      else if (o->remote_list->len == 1) /* one --remote option specfied */
2057
+	{
2058
+	  connection_entry_load_re (&o->ce, o->remote_list->array[0]);
2059
+	}
2060
+      else
2061
+	{
2062
+	  ASSERT (0);
2063
+	}
2064
+    }
2065
+  if (o->connection_list)
2066
+    {
2067
+      int i;
2068
+      for (i = 0; i < o->connection_list->len; ++i)
2069
+	options_postprocess_mutate_ce (o, o->connection_list->array[i]);
2070
+    }
2071
+  else
2072
+#endif
2073
+    options_postprocess_mutate_ce (o, &o->ce);  
2074
+
2075
+#if P2MP
2076
+  /*
1908 2077
    * Save certain parms before modifying options via --pull
1909 2078
    */
1910
-  pre_pull_save (options);
2079
+  pre_pull_save (o);
1911 2080
 #endif
1912 2081
 }
1913 2082
 
2083
+/*
2084
+ * Sanity check on options.
2085
+ * Also set some options based on other
2086
+ * options.
2087
+ */
2088
+void
2089
+options_postprocess (struct options *options)
2090
+{
2091
+  options_postprocess_mutate (options);
2092
+  options_postprocess_verify (options);
2093
+}
2094
+
1914 2095
 #if P2MP
1915 2096
 
1916 2097
 /*
... ...
@@ -2023,7 +2181,7 @@ options_string (const struct options *o,
2023 2023
   buf_printf (&out, ",dev-type %s", dev_type_string (o->dev, o->dev_type));
2024 2024
   buf_printf (&out, ",link-mtu %d", EXPANDED_SIZE (frame));
2025 2025
   buf_printf (&out, ",tun-mtu %d", PAYLOAD_SIZE (frame));
2026
-  buf_printf (&out, ",proto %s", proto2ascii (proto_remote (o->proto, remote), true));
2026
+  buf_printf (&out, ",proto %s", proto2ascii (proto_remote (o->ce.proto, remote), true));
2027 2027
   if (o->tun_ipv6)
2028 2028
     buf_printf (&out, ",tun-ipv6");
2029 2029
 
... ...
@@ -2451,13 +2609,13 @@ usage (void)
2451 2451
 #else
2452 2452
 
2453 2453
   struct options o;
2454
-  init_options (&o);
2454
+  init_options (&o, true);
2455 2455
 
2456 2456
 #if defined(USE_CRYPTO) && defined(USE_SSL)
2457 2457
   fprintf (fp, usage_message,
2458 2458
 	   title_string,
2459
-	   o.connect_retry_seconds,
2460
-	   o.local_port, o.remote_port,
2459
+	   o.ce.connect_retry_seconds,
2460
+	   o.ce.local_port, o.ce.remote_port,
2461 2461
 	   TUN_MTU_DEFAULT, TAP_MTU_EXTRA_DEFAULT,
2462 2462
 	   o.verbosity,
2463 2463
 	   o.authname, o.ciphername,
... ...
@@ -2467,8 +2625,8 @@ usage (void)
2467 2467
 #elif defined(USE_CRYPTO)
2468 2468
   fprintf (fp, usage_message,
2469 2469
 	   title_string,
2470
-	   o.connect_retry_seconds,
2471
-	   o.local_port, o.remote_port,
2470
+	   o.ce.connect_retry_seconds,
2471
+	   o.ce.local_port, o.ce.remote_port,
2472 2472
 	   TUN_MTU_DEFAULT, TAP_MTU_EXTRA_DEFAULT,
2473 2473
 	   o.verbosity,
2474 2474
 	   o.authname, o.ciphername,
... ...
@@ -2476,8 +2634,8 @@ usage (void)
2476 2476
 #else
2477 2477
   fprintf (fp, usage_message,
2478 2478
 	   title_string,
2479
-	   o.connect_retry_seconds,
2480
-	   o.local_port, o.remote_port,
2479
+	   o.ce.connect_retry_seconds,
2480
+	   o.ce.local_port, o.ce.remote_port,
2481 2481
 	   TUN_MTU_DEFAULT, TAP_MTU_EXTRA_DEFAULT,
2482 2482
 	   o.verbosity);
2483 2483
 #endif
... ...
@@ -2857,14 +3015,14 @@ read_config_file (struct options *options,
2857 2857
 }
2858 2858
 
2859 2859
 static void
2860
-read_config_string (struct options *options,
2860
+read_config_string (const char *prefix,
2861
+		    struct options *options,
2861 2862
 		    const char *config,
2862 2863
 		    const int msglevel,
2863 2864
 		    const unsigned int permission_mask,
2864 2865
 		    unsigned int *option_types_found,
2865 2866
 		    struct env_set *es)
2866 2867
 {
2867
-  const char *file = "[CONFIG-STRING]";
2868 2868
   char line[OPTION_LINE_SIZE];
2869 2869
   struct buffer multiline;
2870 2870
   int line_num = 0;
... ...
@@ -2876,7 +3034,7 @@ read_config_string (struct options *options,
2876 2876
       char *p[MAX_PARMS];
2877 2877
       CLEAR (p);
2878 2878
       ++line_num;
2879
-      if (parse_line (line, p, SIZE (p), file, line_num, msglevel, &options->gc))
2879
+      if (parse_line (line, p, SIZE (p), prefix, line_num, msglevel, &options->gc))
2880 2880
 	{
2881 2881
 	  bypass_doubledash (&p[0]);
2882 2882
 #if ENABLE_INLINE_FILES
... ...
@@ -2997,7 +3155,7 @@ void options_string_import (struct options *options,
2997 2997
 			    unsigned int *option_types_found,
2998 2998
 			    struct env_set *es)
2999 2999
 {
3000
-  read_config_string (options, config, msglevel, permission_mask, option_types_found, es);
3000
+  read_config_string ("[CONFIG-STRING]", options, config, msglevel, permission_mask, option_types_found, es);
3001 3001
 }
3002 3002
 
3003 3003
 #if P2MP
... ...
@@ -3281,41 +3439,82 @@ add_option (struct options *options,
3281 3281
     }
3282 3282
   else if (streq (p[0], "local") && p[1])
3283 3283
     {
3284
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3285
-      options->local = p[1];
3284
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3285
+      options->ce.local = p[1];
3286 3286
     }
3287 3287
   else if (streq (p[0], "remote-random"))
3288 3288
     {
3289 3289
       VERIFY_PERMISSION (OPT_P_GENERAL);
3290 3290
       options->remote_random = true;
3291 3291
     }
3292
-  else if (streq (p[0], "remote") && p[1])
3292
+#if ENABLE_CONNECTION
3293
+  else if (streq (p[0], "connection") && p[1])
3293 3294
     {
3294
-      struct remote_list *l;
3295
-      struct remote_entry e;
3296
-
3297 3295
       VERIFY_PERMISSION (OPT_P_GENERAL);
3298
-      if (!options->remote_list)
3299
-	ALLOC_OBJ_CLEAR_GC (options->remote_list, struct remote_list, &options->gc);
3300
-      l = options->remote_list;
3301
-      if (l->len >= REMOTE_LIST_SIZE)
3296
+      if (streq (p[1], INLINE_FILE_TAG) && p[2])
3302 3297
 	{
3303
-	  msg (msglevel, "Maximum number of --remote options (%d) exceeded", REMOTE_LIST_SIZE);
3304
-	  goto err;
3298
+	  struct options sub;
3299
+	  struct connection_entry *e;
3300
+
3301
+	  init_options (&sub, true);
3302
+	  sub.ce = options->ce;
3303
+	  read_config_string ("[CONNECTION-OPTIONS]", &sub, p[2], msglevel, OPT_P_CONNECTION, option_types_found, es);
3304
+	  if (!sub.ce.remote)
3305
+	    {
3306
+	      msg (msglevel, "Each 'connection' block must contain exactly one 'remote' directive");
3307
+	      goto err;
3308
+	    }
3309
+
3310
+	  e = alloc_connection_entry (options, msglevel);
3311
+	  if (!e)
3312
+	    goto err;
3313
+	  *e = sub.ce;
3314
+	  gc_transfer (&options->gc, &sub.gc);
3315
+	  uninit_options (&sub);
3305 3316
 	}
3306
-      e.hostname = p[1];
3317
+    }
3318
+#endif
3319
+  else if (streq (p[0], "remote") && p[1])
3320
+    {
3321
+      struct remote_entry re;
3322
+      re.remote = NULL;
3323
+      re.remote_port = re.proto = -1;
3324
+
3325
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3326
+      re.remote = p[1];
3307 3327
       if (p[2])
3308 3328
 	{
3309
-	  e.port = atoi (p[2]);
3310
-	  if (!legal_ipv4_port (e.port))
3329
+	  const int port = atoi (p[2]);
3330
+	  if (!legal_ipv4_port (port))
3311 3331
 	    {
3312
-	      msg (msglevel, "port number associated with host %s is out of range", e.hostname);
3332
+	      msg (msglevel, "remote: port number associated with host %s is out of range", p[1]);
3313 3333
 	      goto err;
3314 3334
 	    }
3335
+	  re.remote_port = port;
3336
+	  if (p[3])
3337
+	    {
3338
+	      const int proto = ascii2proto (p[3]);
3339
+	      if (proto < 0)
3340
+		{
3341
+		  msg (msglevel, "remote: bad protocol associated with host %s: '%s'", p[1], p[3]);
3342
+		  goto err;
3343
+		}
3344
+	      re.proto = proto;
3345
+	    }
3346
+	}
3347
+#ifdef ENABLE_CONNECTION
3348
+      if (permission_mask & OPT_P_GENERAL)
3349
+	{
3350
+	  struct remote_entry *e = alloc_remote_entry (options, msglevel);
3351
+	  if (!e)
3352
+	    goto err;
3353
+	  *e = re;
3354
+	}
3355
+      else if (permission_mask & OPT_P_CONNECTION)
3356
+#endif
3357
+	{
3358
+	  connection_entry_load_re (&options->ce, &re);
3315 3359
 	}
3316
-      else
3317
-	e.port = -1;
3318
-      l->array[l->len++] = e;
3319 3360
     }
3320 3361
   else if (streq (p[0], "resolv-retry") && p[1])
3321 3362
     {
... ...
@@ -3327,20 +3526,20 @@ add_option (struct options *options,
3327 3327
     }
3328 3328
   else if (streq (p[0], "connect-retry") && p[1])
3329 3329
     {
3330
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3331
-      options->connect_retry_seconds = positive_atoi (p[1]);
3332
-      options->connect_retry_defined = true;
3330
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3331
+      options->ce.connect_retry_seconds = positive_atoi (p[1]);
3332
+      options->ce.connect_retry_defined = true;
3333 3333
     }
3334 3334
   else if (streq (p[0], "connect-timeout") && p[1])
3335 3335
     {
3336
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3337
-      options->connect_timeout = positive_atoi (p[1]);
3338
-      options->connect_timeout_defined = true;
3336
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3337
+      options->ce.connect_timeout = positive_atoi (p[1]);
3338
+      options->ce.connect_timeout_defined = true;
3339 3339
     }
3340 3340
   else if (streq (p[0], "connect-retry-max") && p[1])
3341 3341
     {
3342
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3343
-      options->connect_retry_max = positive_atoi (p[1]);
3342
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3343
+      options->ce.connect_retry_max = positive_atoi (p[1]);
3344 3344
     }
3345 3345
   else if (streq (p[0], "ipchange") && p[1])
3346 3346
     {
... ...
@@ -3351,8 +3550,8 @@ add_option (struct options *options,
3351 3351
     }
3352 3352
   else if (streq (p[0], "float"))
3353 3353
     {
3354
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3355
-      options->remote_float = true;
3354
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3355
+      options->ce.remote_float = true;
3356 3356
     }
3357 3357
 #ifdef ENABLE_DEBUG
3358 3358
   else if (streq (p[0], "gremlin") && p[1])
... ...
@@ -3687,54 +3886,54 @@ add_option (struct options *options,
3687 3687
     {
3688 3688
       int port;
3689 3689
 
3690
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3690
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3691 3691
       port = atoi (p[1]);
3692 3692
       if (!legal_ipv4_port (port))
3693 3693
 	{
3694 3694
 	  msg (msglevel, "Bad port number: %s", p[1]);
3695 3695
 	  goto err;
3696 3696
 	}
3697
-      options->port_option_used = true;
3698
-      options->local_port = options->remote_port = port;
3697
+      options->ce.port_option_used = true;
3698
+      options->ce.local_port = options->ce.remote_port = port;
3699 3699
     }
3700 3700
   else if (streq (p[0], "lport") && p[1])
3701 3701
     {
3702 3702
       int port;
3703 3703
 
3704
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3704
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3705 3705
       port = atoi (p[1]);
3706 3706
       if (!legal_ipv4_port (port))
3707 3707
 	{
3708 3708
 	  msg (msglevel, "Bad local port number: %s", p[1]);
3709 3709
 	  goto err;
3710 3710
 	}
3711
-      options->local_port_defined = true;
3712
-      options->port_option_used = true;
3713
-      options->local_port = port;
3711
+      options->ce.local_port_defined = true;
3712
+      options->ce.port_option_used = true;
3713
+      options->ce.local_port = port;
3714 3714
     }
3715 3715
   else if (streq (p[0], "rport") && p[1])
3716 3716
     {
3717 3717
       int port;
3718 3718
 
3719
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3719
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3720 3720
       port = atoi (p[1]);
3721 3721
       if (!legal_ipv4_port (port))
3722 3722
 	{
3723 3723
 	  msg (msglevel, "Bad remote port number: %s", p[1]);
3724 3724
 	  goto err;
3725 3725
 	}
3726
-      options->port_option_used = true;
3727
-      options->remote_port = port;
3726
+      options->ce.port_option_used = true;
3727
+      options->ce.remote_port = port;
3728 3728
     }
3729 3729
   else if (streq (p[0], "bind"))
3730 3730
     {
3731
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3732
-      options->bind_defined = true;
3731
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3732
+      options->ce.bind_defined = true;
3733 3733
     }
3734 3734
   else if (streq (p[0], "nobind"))
3735 3735
     {
3736
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3737
-      options->bind_local = false;
3736
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3737
+      options->ce.bind_local = false;
3738 3738
     }
3739 3739
   else if (streq (p[0], "fast-io"))
3740 3740
     {
... ...
@@ -3751,7 +3950,7 @@ add_option (struct options *options,
3751 3751
   else if (streq (p[0], "proto") && p[1])
3752 3752
     {
3753 3753
       int proto;
3754
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3754
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3755 3755
       proto = ascii2proto (p[1]);
3756 3756
       if (proto < 0)
3757 3757
 	{
... ...
@@ -3760,7 +3959,7 @@ add_option (struct options *options,
3760 3760
 	       proto2ascii_all (&gc));
3761 3761
 	  goto err;
3762 3762
 	}
3763
-      options->proto = proto;
3763
+      options->ce.proto = proto;
3764 3764
     }
3765 3765
 #ifdef GENERAL_PROXY_SUPPORT
3766 3766
   else if (streq (p[0], "auto-proxy"))
... ...
@@ -3799,7 +3998,7 @@ add_option (struct options *options,
3799 3799
     {
3800 3800
       struct http_proxy_options *ho;
3801 3801
 
3802
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3802
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3803 3803
 
3804 3804
       {
3805 3805
 	int port;
... ...
@@ -3844,7 +4043,7 @@ add_option (struct options *options,
3844 3844
   else if (streq (p[0], "http-proxy-retry"))
3845 3845
     {
3846 3846
       struct http_proxy_options *ho;
3847
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3847
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3848 3848
       ho = init_http_options_if_undefined (options);
3849 3849
       ho->retry = true;
3850 3850
     }
... ...
@@ -3852,7 +4051,7 @@ add_option (struct options *options,
3852 3852
     {
3853 3853
       struct http_proxy_options *ho;
3854 3854
 
3855
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3855
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3856 3856
       ho = init_http_options_if_undefined (options);
3857 3857
       ho->timeout = positive_atoi (p[1]);
3858 3858
     }
... ...
@@ -3860,7 +4059,7 @@ add_option (struct options *options,
3860 3860
     {
3861 3861
       struct http_proxy_options *ho;
3862 3862
 
3863
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3863
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3864 3864
       ho = init_http_options_if_undefined (options);
3865 3865
 
3866 3866
       if (streq (p[1], "VERSION") && p[2])
... ...
@@ -3880,7 +4079,7 @@ add_option (struct options *options,
3880 3880
 #ifdef ENABLE_SOCKS
3881 3881
   else if (streq (p[0], "socks-proxy") && p[1])
3882 3882
     {
3883
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3883
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3884 3884
 
3885 3885
       if (p[2])
3886 3886
 	{
... ...
@@ -3891,18 +4090,18 @@ add_option (struct options *options,
3891 3891
 	      msg (msglevel, "Bad socks-proxy port number: %s", p[2]);
3892 3892
 	      goto err;
3893 3893
 	    }
3894
-          options->socks_proxy_port = port;
3894
+          options->ce.socks_proxy_port = port;
3895 3895
 	}
3896 3896
       else
3897 3897
 	{
3898
-	  options->socks_proxy_port = 1080;
3898
+	  options->ce.socks_proxy_port = 1080;
3899 3899
 	}
3900
-      options->socks_proxy_server = p[1];
3900
+      options->ce.socks_proxy_server = p[1];
3901 3901
     }
3902 3902
   else if (streq (p[0], "socks-proxy-retry"))
3903 3903
     {
3904
-      VERIFY_PERMISSION (OPT_P_GENERAL);
3905
-      options->socks_proxy_retry = true;
3904
+      VERIFY_PERMISSION (OPT_P_GENERAL|OPT_P_CONNECTION);
3905
+      options->ce.socks_proxy_retry = true;
3906 3906
     }
3907 3907
 #endif
3908 3908
   else if (streq (p[0], "keepalive") && p[1] && p[2])
... ...
@@ -82,10 +82,65 @@ struct options_pre_pull
82 82
 
83 83
 #endif
84 84
 
85
+struct connection_entry
86
+{
87
+  int proto;
88
+  int local_port;
89
+  bool local_port_defined;
90
+  int remote_port;
91
+  bool port_option_used;
92
+  const char *local;
93
+  const char *remote;
94
+  bool remote_float;
95
+  bool bind_defined;
96
+  bool bind_local;
97
+  int connect_retry_seconds;
98
+  bool connect_retry_defined;
99
+  int connect_retry_max;
100
+  int connect_timeout;
101
+  bool connect_timeout_defined;
102
+#ifdef ENABLE_HTTP_PROXY
103
+  struct http_proxy_options *http_proxy_options;
104
+#endif  
105
+#ifdef ENABLE_SOCKS
106
+  const char *socks_proxy_server;
107
+  int socks_proxy_port;
108
+  bool socks_proxy_retry;
109
+#endif
110
+};
111
+
112
+struct remote_entry
113
+{
114
+  const char *remote;
115
+  int remote_port;
116
+  int proto;
117
+};
118
+
119
+#ifdef ENABLE_CONNECTION
120
+
121
+#define CONNECTION_LIST_SIZE 64
122
+
123
+struct connection_list
124
+{
125
+  int len;
126
+  int current;
127
+  bool no_advance;
128
+  struct connection_entry *array[CONNECTION_LIST_SIZE];
129
+};
130
+
131
+struct remote_list
132
+{
133
+  int len;
134
+  struct remote_entry *array[CONNECTION_LIST_SIZE];
135
+};
136
+
137
+#endif
138
+
85 139
 /* Command line options */
86 140
 struct options
87 141
 {
88 142
   struct gc_arena gc;
143
+  bool gc_owned;
89 144
 
90 145
   /* first config file */
91 146
   const char *config;
... ...
@@ -111,17 +166,19 @@ struct options
111 111
 #endif
112 112
 
113 113
   /* Networking parms */
114
-  const char *local;
115
-  int local_port;
116
-  bool local_port_defined;
117
-  int remote_port;
118
-  bool port_option_used;
119
-  bool remote_float;
114
+  struct connection_entry ce;
115
+
116
+#ifdef ENABLE_CONNECTION
117
+  struct connection_list *connection_list;
120 118
   struct remote_list *remote_list;
119
+#endif
120
+
121
+#ifdef GENERAL_PROXY_SUPPORT
122
+  struct auto_proxy_info *auto_proxy_info;
123
+#endif
124
+
121 125
   bool remote_random;
122 126
   const char *ipchange;
123
-  bool bind_defined;
124
-  bool bind_local;
125 127
   const char *dev;
126 128
   const char *dev_type;
127 129
   const char *dev_node;
... ...
@@ -141,14 +198,6 @@ struct options
141 141
   bool tun_mtu_defined;  /* true if user overriding parm with command line option */
142 142
   bool link_mtu_defined; /* true if user overriding parm with command line option */
143 143
 
144
-  /* Protocol type (PROTO_UDP or PROTO_TCP) */
145
-  int proto;
146
-  int connect_retry_seconds;
147
-  int connect_retry_max;
148
-  bool connect_retry_defined;
149
-  int connect_timeout;
150
-  bool connect_timeout_defined;
151
-
152 144
   /* Advanced MTU negotiation and datagram fragmentation options */
153 145
   int mtu_discover_type; /* used if OS supports setting Path MTU discovery options on socket */
154 146
 
... ...
@@ -254,21 +303,6 @@ struct options
254 254
   struct route_option_list *routes;
255 255
   bool route_nopull;
256 256
 
257
-#ifdef GENERAL_PROXY_SUPPORT
258
-  struct auto_proxy_info *auto_proxy_info;
259
-#endif
260
-
261
-#ifdef ENABLE_HTTP_PROXY
262
-  struct http_proxy_options *http_proxy_options;
263
-#endif
264
-
265
-#ifdef ENABLE_SOCKS
266
-  /* socks proxy */
267
-  const char *socks_proxy_server;
268
-  int socks_proxy_port;
269
-  bool socks_proxy_retry;
270
-#endif
271
-
272 257
 #ifdef ENABLE_OCC
273 258
   /* Enable options consistency check between peers */
274 259
   bool occ;
... ...
@@ -499,6 +533,7 @@ struct options
499 499
 #define OPT_P_PLUGIN          (1<<24)
500 500
 #define OPT_P_SOCKBUF         (1<<25)
501 501
 #define OPT_P_SOCKFLAGS       (1<<26)
502
+#define OPT_P_CONNECTION      (1<<27)
502 503
 
503 504
 #define OPT_P_DEFAULT   (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
504 505
 
... ...
@@ -553,7 +588,7 @@ void notnull (const char *arg, const char *description);
553 553
 
554 554
 void usage_small (void);
555 555
 
556
-void init_options (struct options *o);
556
+void init_options (struct options *o, const bool init_gc);
557 557
 void uninit_options (struct options *o);
558 558
 
559 559
 void setenv_settings (struct env_set *es, const struct options *o);
... ...
@@ -578,7 +613,7 @@ void options_warning (char *actual, const char *expected);
578 578
 
579 579
 #endif
580 580
 
581
-void options_postprocess (struct options *options, bool first_time);
581
+void options_postprocess (struct options *options);
582 582
 
583 583
 void pre_pull_save (struct options *o);
584 584
 void pre_pull_restore (struct options *o);
... ...
@@ -643,4 +678,26 @@ void options_string_import (struct options *options,
643 643
 			    unsigned int *option_types_found,
644 644
 			    struct env_set *es);
645 645
 
646
+/*
647
+ * inline functions
648
+ */
649
+static inline bool
650
+connection_list_defined (const struct options *o)
651
+{
652
+#ifdef ENABLE_CONNECTION
653
+  return o->connection_list != NULL;
654
+#else
655
+  return false;
656
+#endif
657
+}
658
+
659
+static inline void
660
+connection_list_set_no_advance (struct options *o)
661
+{
662
+#ifdef ENABLE_CONNECTION
663
+  if (o->connection_list)
664
+    o->connection_list->no_advance = true;
665
+#endif
666
+}
667
+
646 668
 #endif
... ...
@@ -229,9 +229,8 @@ get_user_pass_http (struct http_proxy_info *p, const bool force)
229 229
 }
230 230
 
231 231
 struct http_proxy_info *
232
-new_http_proxy (const struct http_proxy_options *o,
233
-		struct auto_proxy_info *auto_proxy_info,
234
-		struct gc_arena *gc)
232
+http_proxy_new (const struct http_proxy_options *o,
233
+		struct auto_proxy_info *auto_proxy_info)
235 234
 {
236 235
   struct http_proxy_info *p;
237 236
   struct http_proxy_options opt;
... ...
@@ -275,7 +274,7 @@ new_http_proxy (const struct http_proxy_options *o,
275 275
 
276 276
   ASSERT (legal_ipv4_port (o->port));
277 277
 
278
-  ALLOC_OBJ_CLEAR_GC (p, struct http_proxy_info, gc);
278
+  ALLOC_OBJ_CLEAR (p, struct http_proxy_info);
279 279
   p->options = *o;
280 280
 
281 281
   /* parse authentication method */
... ...
@@ -310,6 +309,12 @@ new_http_proxy (const struct http_proxy_options *o,
310 310
   return p;
311 311
 }
312 312
 
313
+void
314
+http_proxy_close (struct http_proxy_info *hp)
315
+{
316
+  free (hp);
317
+}
318
+
313 319
 bool
314 320
 establish_http_proxy_passthru (struct http_proxy_info *p,
315 321
 			       socket_descriptor_t sd, /* already open to proxy */
... ...
@@ -80,9 +80,10 @@ struct http_proxy_info {
80 80
   struct user_pass up;
81 81
 };
82 82
 
83
-struct http_proxy_info *new_http_proxy (const struct http_proxy_options *o,
84
-					struct auto_proxy_info *auto_proxy_info,
85
-					struct gc_arena *gc);
83
+struct http_proxy_info *http_proxy_new (const struct http_proxy_options *o,
84
+					struct auto_proxy_info *auto_proxy_info);
85
+
86
+void http_proxy_close (struct http_proxy_info *hp);
86 87
 
87 88
 bool establish_http_proxy_passthru (struct http_proxy_info *p,
88 89
 				    socket_descriptor_t sd, /* already open to proxy */
... ...
@@ -403,77 +403,6 @@ link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf)
403 403
 }
404 404
 
405 405
 /*
406
- * Remote list code allows clients to specify a list of
407
- * potential remote server addresses.
408
- */
409
-
410
-static void
411
-remote_list_next (struct remote_list *l)
412
-{
413
-  if (l)
414
-    {
415
-      if (l->no_advance && l->current >= 0)
416
-	{
417
-	  l->no_advance = false;
418
-	}
419
-      else
420
-	{
421
-	  int i;
422
-	  if (++l->current >= l->len)
423
-	    l->current = 0;
424
-
425
-	  dmsg (D_REMOTE_LIST, "REMOTE_LIST len=%d current=%d",
426
-		l->len, l->current);
427
-	  for (i = 0; i < l->len; ++i)
428
-	    {
429
-	      dmsg (D_REMOTE_LIST, "[%d] %s:%d",
430
-		    i,
431
-		    l->array[i].hostname,
432
-		    l->array[i].port);
433
-	    }
434
-	}
435
-    }
436
-}
437
-
438
-void
439
-remote_list_randomize (struct remote_list *l)
440
-{
441
-  int i;
442
-  if (l)
443
-    {
444
-      for (i = 0; i < l->len; ++i)
445
-	{
446
-	  const int j = get_random () % l->len;
447
-	  if (i != j)
448
-	    {
449
-	      struct remote_entry tmp;
450
-	      tmp = l->array[i];
451
-	      l->array[i] = l->array[j];
452
-	      l->array[j] = tmp;
453
-	    }
454
-	}
455
-    }
456
-}
457
-
458
-static const char *
459
-remote_list_host (const struct remote_list *rl)
460
-{
461
-  if (rl)
462
-    return rl->array[rl->current].hostname;
463
-  else
464
-    return NULL;
465
-}
466
-
467
-static int
468
-remote_list_port (const struct remote_list *rl)
469
-{
470
-  if (rl)
471
-    return rl->array[rl->current].port;
472
-  else
473
-    return 0;
474
-}
475
-
476
-/*
477 406
  * SOCKET INITALIZATION CODE.
478 407
  * Create a TCP/UDP socket
479 408
  */
... ...
@@ -813,7 +742,7 @@ socket_connect (socket_descriptor_t *sd,
813 813
                 struct openvpn_sockaddr *local,
814 814
                 bool bind_local,
815 815
 		struct openvpn_sockaddr *remote,
816
-		struct remote_list *remote_list,
816
+		const bool connection_profiles_defined,
817 817
 		const char *remote_dynamic,
818 818
 		bool *remote_changed,
819 819
 		const int connect_retry_seconds,
... ...
@@ -865,7 +794,7 @@ socket_connect (socket_descriptor_t *sd,
865 865
       openvpn_close_socket (*sd);
866 866
       *sd = SOCKET_UNDEFINED;
867 867
 
868
-      if (connect_retry_max > 0 && ++retry >= connect_retry_max)
868
+      if ((connect_retry_max > 0 && ++retry >= connect_retry_max) || connection_profiles_defined)
869 869
 	{
870 870
 	  *signal_received = SIGUSR1;
871 871
 	  goto done;
... ...
@@ -877,14 +806,6 @@ socket_connect (socket_descriptor_t *sd,
877 877
       if (*signal_received)
878 878
 	goto done;
879 879
 
880
-      if (remote_list)
881
-	{
882
-	  remote_list_next (remote_list);
883
-	  remote_dynamic = remote_list_host (remote_list);
884
-	  remote->sa.sin_port = htons (remote_list_port (remote_list));
885
-	  *remote_changed = true;
886
-	}
887
-
888 880
       *sd = create_socket_tcp ();
889 881
       if (bind_local)
890 882
         socket_bind (*sd, local, "TCP Client");
... ...
@@ -996,7 +917,7 @@ resolve_remote (struct link_socket *sock,
996 996
 	      int retry = 0;
997 997
 	      bool status = false;
998 998
 
999
-	      if (remote_list_len (sock->remote_list) > 1 && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
999
+	      if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
1000 1000
 		{
1001 1001
 		  if (phase == 2)
1002 1002
 		    flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
... ...
@@ -1099,9 +1020,11 @@ link_socket_new (void)
1099 1099
 /* bind socket if necessary */
1100 1100
 void
1101 1101
 link_socket_init_phase1 (struct link_socket *sock,
1102
+			 const bool connection_profiles_defined,
1102 1103
 			 const char *local_host,
1103
-			 struct remote_list *remote_list,
1104 1104
 			 int local_port,
1105
+			 const char *remote_host,
1106
+			 int remote_port,
1105 1107
 			 int proto,
1106 1108
 			 int mode,
1107 1109
 			 const struct link_socket *accept_from,
... ...
@@ -1129,18 +1052,14 @@ link_socket_init_phase1 (struct link_socket *sock,
1129 1129
 			 int sndbuf,
1130 1130
 			 unsigned int sockflags)
1131 1131
 {
1132
-  const char *remote_host;
1133
-  int remote_port;
1134
-
1135 1132
   ASSERT (sock);
1136 1133
 
1137
-  sock->remote_list = remote_list;
1138
-  remote_list_next (remote_list);
1139
-  remote_host = remote_list_host (remote_list);
1140
-  remote_port = remote_list_port (remote_list);
1134
+  sock->connection_profiles_defined = connection_profiles_defined;
1141 1135
 
1142 1136
   sock->local_host = local_host;
1143 1137
   sock->local_port = local_port;
1138
+  sock->remote_host = remote_host;
1139
+  sock->remote_port = remote_port;
1144 1140
 
1145 1141
 #ifdef ENABLE_HTTP_PROXY
1146 1142
   sock->http_proxy = http_proxy;
... ...
@@ -1198,10 +1117,6 @@ link_socket_init_phase1 (struct link_socket *sock,
1198 1198
       /* the OpenVPN server we will use the proxy to connect to */
1199 1199
       sock->proxy_dest_host = remote_host;
1200 1200
       sock->proxy_dest_port = remote_port;
1201
-
1202
-      /* this is needed so that connection retries will go to the proxy server,
1203
-	 not the remote OpenVPN address */
1204
-      sock->remote_list = NULL;
1205 1201
     }
1206 1202
 #endif
1207 1203
 #ifdef ENABLE_SOCKS
... ...
@@ -1218,10 +1133,6 @@ link_socket_init_phase1 (struct link_socket *sock,
1218 1218
       /* the OpenVPN server we will use the proxy to connect to */
1219 1219
       sock->proxy_dest_host = remote_host;
1220 1220
       sock->proxy_dest_port = remote_port;
1221
-
1222
-      /* this is needed so that connection retries will go to the proxy server,
1223
-	 not the remote OpenVPN address */
1224
-      sock->remote_list = NULL;
1225 1221
     }
1226 1222
 #endif
1227 1223
   else
... ...
@@ -1357,7 +1268,7 @@ link_socket_init_phase2 (struct link_socket *sock,
1357 1357
 			    &sock->info.lsa->local,
1358 1358
 			    sock->bind_local,
1359 1359
 			    &sock->info.lsa->actual.dest,
1360
-			    sock->remote_list,
1360
+			    sock->connection_profiles_defined,
1361 1361
 			    remote_dynamic,
1362 1362
 			    &remote_changed,
1363 1363
 			    sock->connect_retry_seconds,
... ...
@@ -1405,7 +1316,7 @@ link_socket_init_phase2 (struct link_socket *sock,
1405 1405
                           &sock->info.lsa->local,
1406 1406
                           sock->bind_local,
1407 1407
 			  &sock->info.lsa->actual.dest,
1408
-			  NULL,
1408
+			  sock->connection_profiles_defined,
1409 1409
 			  remote_dynamic,
1410 1410
 			  &remote_changed,
1411 1411
 			  sock->connect_retry_seconds,
... ...
@@ -47,22 +47,6 @@
47 47
  */
48 48
 #define RESOLV_RETRY_INFINITE 1000000000
49 49
 
50
-#define REMOTE_LIST_SIZE 64
51
-
52
-struct remote_entry
53
-{
54
-  const char *hostname;
55
-  int port;
56
-};
57
-
58
-struct remote_list
59
-{
60
-  int len;
61
-  int current;
62
-  bool no_advance;
63
-  struct remote_entry array[REMOTE_LIST_SIZE];
64
-};
65
-
66 50
 /* 
67 51
  * packet_size_type is used to communicate packet size
68 52
  * over the wire when stream oriented protocols are
... ...
@@ -175,8 +159,9 @@ struct link_socket
175 175
   /* used for long-term queueing of pre-accepted socket listen */
176 176
   bool listen_persistent_queued;
177 177
 
178
-  /* set on initial call to init phase 1 */
179
-  struct remote_list *remote_list;
178
+  /* Does config file contain any <connection> ... </connection> blocks? */
179
+  bool connection_profiles_defined;
180
+
180 181
   const char *remote_host;
181 182
   int remote_port;
182 183
   const char *local_host;
... ...
@@ -290,9 +275,11 @@ int openvpn_connect (socket_descriptor_t sd,
290 290
 
291 291
 void
292 292
 link_socket_init_phase1 (struct link_socket *sock,
293
+			 const bool connection_profiles_defined,
293 294
 			 const char *local_host,
294
-			 struct remote_list *remote_list,
295 295
 			 int local_port,
296
+			 const char *remote_host,
297
+			 int remote_port,
296 298
 			 int proto,
297 299
 			 int mode,
298 300
 			 const struct link_socket *accept_from,
... ...
@@ -391,8 +378,6 @@ void link_socket_bad_outgoing_addr (void);
391 391
 
392 392
 void setenv_trusted (struct env_set *es, const struct link_socket_info *info);
393 393
 
394
-void remote_list_randomize (struct remote_list *l);
395
-
396 394
 bool link_socket_update_flags (struct link_socket *ls, unsigned int sockflags);
397 395
 void link_socket_update_buffer_sizes (struct link_socket *ls, int rcvbuf, int sndbuf);
398 396
 
... ...
@@ -467,15 +452,6 @@ datagram_overhead (int proto)
467 467
  * Misc inline functions
468 468
  */
469 469
 
470
-static inline int
471
-remote_list_len (const struct remote_list *rl)
472
-{
473
-  if (rl)
474
-    return rl->len;
475
-  else
476
-    return 0;
477
-}
478
-
479 470
 static inline bool
480 471
 legal_ipv4_port (int port)
481 472
 {
... ...
@@ -51,11 +51,10 @@ socks_adjust_frame_parameters (struct frame *frame, int proto)
51 51
 }
52 52
 
53 53
 struct socks_proxy_info *
54
-new_socks_proxy (const char *server,
54
+socks_proxy_new (const char *server,
55 55
 		 int port,
56 56
 		 bool retry,
57
-		 struct auto_proxy_info *auto_proxy_info,
58
-		 struct gc_arena *gc)
57
+		 struct auto_proxy_info *auto_proxy_info)
59 58
 {
60 59
   struct socks_proxy_info *p;
61 60
 
... ...
@@ -71,7 +70,7 @@ new_socks_proxy (const char *server,
71 71
 	}
72 72
     }
73 73
 
74
-  ALLOC_OBJ_CLEAR_GC (p, struct socks_proxy_info, gc);
74
+  ALLOC_OBJ_CLEAR (p, struct socks_proxy_info);
75 75
 
76 76
   ASSERT (server);
77 77
   ASSERT (legal_ipv4_port (port));
... ...
@@ -84,6 +83,12 @@ new_socks_proxy (const char *server,
84 84
   return p;
85 85
 }
86 86
 
87
+void
88
+socks_proxy_close (struct socks_proxy_info *sp)
89
+{
90
+  free (sp);
91
+}
92
+
87 93
 static bool
88 94
 socks_handshake (socket_descriptor_t sd, volatile int *signal_received)
89 95
 {
... ...
@@ -47,11 +47,12 @@ struct socks_proxy_info {
47 47
 
48 48
 void socks_adjust_frame_parameters (struct frame *frame, int proto);
49 49
 
50
-struct socks_proxy_info *new_socks_proxy (const char *server,
50
+struct socks_proxy_info *socks_proxy_new (const char *server,
51 51
 					  int port,
52 52
 					  bool retry,
53
-					  struct auto_proxy_info *auto_proxy_info,
54
-					  struct gc_arena *gc);
53
+					  struct auto_proxy_info *auto_proxy_info);
54
+
55
+void socks_proxy_close (struct socks_proxy_info *sp);
55 56
 
56 57
 void establish_socks_proxy_passthru (struct socks_proxy_info *p,
57 58
 				     socket_descriptor_t sd, /* already open to proxy */
... ...
@@ -605,4 +605,11 @@ socket_defined (const socket_descriptor_t sd)
605 605
 #define AUTO_USERID 0
606 606
 #endif
607 607
 
608
+/*
609
+ * Support "connection" directive
610
+ */
611
+#if ENABLE_INLINE_FILES
612
+#define ENABLE_CONNECTION 1
613
+#endif
614
+
608 615
 #endif
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc7e])
2
+define(PRODUCT_VERSION,[2.1_rc7f])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])