Browse code

Added "--server-bridge" (without parameters) to enable DHCP proxy mode: Configure server mode for ethernet bridging using a DHCP-proxy, where clients talk to the OpenVPN server-side DHCP server to receive their IP address allocation and DNS server addresses.

Added "--route-gateway dhcp", to enable the extraction
of the gateway address from a DHCP negotiation with the
OpenVPN server-side LAN.

Modified client.conf and server.conf to reflect new option
modes.

Incremented version to 2.1_rc9a.


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

james authored on 2008/08/02 17:02:53
Showing 14 changed files
... ...
@@ -79,6 +79,7 @@ openvpn_SOURCES = \
79 79
 	circ_list.h \
80 80
 	common.h \
81 81
 	crypto.c crypto.h \
82
+	dhcp.c dhcp.h \
82 83
 	errlevel.h \
83 84
 	error.c error.h \
84 85
 	event.c event.h \
85 86
new file mode 100644
... ...
@@ -0,0 +1,183 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2008 Telethra, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+#include "syshead.h"
25
+
26
+#include "dhcp.h"
27
+#include "socket.h"
28
+#include "error.h"
29
+
30
+#include "memdbg.h"
31
+
32
+static int
33
+get_dhcp_message_type (const struct dhcp *dhcp, const int optlen)
34
+{
35
+  const uint8_t *p = (uint8_t *) (dhcp + 1);
36
+  int i;
37
+
38
+  for (i = 0; i < optlen; ++i)
39
+    {
40
+      const uint8_t type = p[i];
41
+      const int room = optlen - i;
42
+      if (type == DHCP_END)           /* didn't find what we were looking for */
43
+	return -1;
44
+      else if (type == DHCP_PAD)      /* no-operation */
45
+	;
46
+      else if (type == DHCP_MSG_TYPE) /* what we are looking for */
47
+	{
48
+	  if (room >= 3)
49
+	    {
50
+	      if (p[i+1] == 1)        /* option length should be 1 */
51
+		return p[i+2];        /* return message type */
52
+	    }
53
+	  return -1;
54
+	}
55
+      else                            /* some other option */
56
+	{
57
+	  if (room >= 2)
58
+	    {
59
+	      const int len = p[i+1]; /* get option length */
60
+	      i += (len + 1);         /* advance to next option */
61
+	    }
62
+	}
63
+    }
64
+  return -1;
65
+}
66
+
67
+static in_addr_t
68
+do_extract (struct dhcp *dhcp, const int optlen)
69
+{
70
+  uint8_t *p = (uint8_t *) (dhcp + 1);
71
+  int i;
72
+  in_addr_t ret = 0;
73
+
74
+  for (i = 0; i < optlen; ++i)
75
+    {
76
+      const uint8_t type = p[i];
77
+      const int room = optlen - i;
78
+      if (type == DHCP_END)
79
+	break;
80
+      else if (type == DHCP_PAD)
81
+	;
82
+      else if (type == DHCP_ROUTER)
83
+	{
84
+	  if (room >= 2)
85
+	    {
86
+	      const int len = p[i+1]; /* get option length */
87
+	      if (len <= (room-2))
88
+		{
89
+		  if (!ret && len >= 4 && (len & 3) == 0)
90
+		    {
91
+		      memcpy (&ret, p+i+2, 4);      /* get router IP address */
92
+		      ret = ntohl (ret);
93
+		    }
94
+		  memset (p+i, DHCP_PAD, len+2);    /* delete the router option by padding it out */
95
+		}
96
+	      i += (len + 1);         /* advance to next option */
97
+	    }
98
+	}
99
+      else                            /* some other option */
100
+	{
101
+	  if (room >= 2)
102
+	    {
103
+	      const int len = p[i+1]; /* get option length */
104
+	      i += (len + 1);         /* advance to next option */
105
+	    }
106
+	}
107
+    }
108
+  return ret;
109
+}
110
+
111
+static uint16_t
112
+udp_checksum (const uint8_t *buf,
113
+	      const int len_udp,
114
+	      const uint8_t *src_addr,
115
+	      const uint8_t *dest_addr)
116
+{
117
+  uint16_t word16;
118
+  uint32_t sum = 0;
119
+  int i;
120
+	
121
+  /* make 16 bit words out of every two adjacent 8 bit words and  */
122
+  /* calculate the sum of all 16 bit words */
123
+  for (i = 0; i < len_udp; i += 2){
124
+    word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0);
125
+    sum += word16;
126
+  }
127
+
128
+  /* add the UDP pseudo header which contains the IP source and destination addresses */
129
+  for (i = 0; i < 4; i += 2){
130
+    word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF);
131
+    sum += word16;
132
+  }
133
+  for (i = 0; i < 4; i += 2){
134
+    word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF);
135
+    sum += word16; 	
136
+  }
137
+
138
+  /* the protocol number and the length of the UDP packet */
139
+  sum += (uint16_t) OPENVPN_IPPROTO_UDP + (uint16_t) len_udp;
140
+
141
+  /* keep only the last 16 bits of the 32 bit calculated sum and add the carries */
142
+  while (sum >> 16)
143
+    sum = (sum & 0xFFFF) + (sum >> 16);
144
+		
145
+  /* Take the one's complement of sum */
146
+  return ((uint16_t) ~sum);
147
+}
148
+
149
+in_addr_t
150
+dhcp_extract_router_msg (struct buffer *ipbuf)
151
+{
152
+  struct dhcp_full *df = (struct dhcp_full *) BPTR (ipbuf);
153
+  const int optlen = BLEN (ipbuf) - (sizeof (struct openvpn_iphdr) + sizeof (struct openvpn_udphdr) + sizeof (struct dhcp));
154
+
155
+  if (optlen >= 0
156
+      && df->ip.protocol == OPENVPN_IPPROTO_UDP
157
+      && df->udp.source == htons (BOOTPS_PORT)
158
+      && df->udp.dest == htons (BOOTPC_PORT)
159
+      && df->dhcp.op == BOOTREPLY
160
+      && get_dhcp_message_type (&df->dhcp, optlen) == DHCPACK)
161
+    {
162
+      /* get the router IP address while padding out all DHCP router options */
163
+      const in_addr_t ret = do_extract (&df->dhcp, optlen);
164
+
165
+      /* recompute the UDP checksum */
166
+      df->udp.check = htons (udp_checksum ((uint8_t *) &df->udp, 
167
+					   sizeof (struct openvpn_udphdr) + sizeof (struct dhcp) + optlen,
168
+					   (uint8_t *)&df->ip.saddr,
169
+					   (uint8_t *)&df->ip.daddr));
170
+
171
+      if (ret)
172
+	{
173
+	  struct gc_arena gc = gc_new ();
174
+	  msg (D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t (ret, 0, &gc));
175
+	  gc_free (&gc);
176
+	}
177
+
178
+      return ret;
179
+    }
180
+  else
181
+    return 0;
182
+}
0 183
new file mode 100644
... ...
@@ -0,0 +1,87 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2008 Telethra, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+#ifndef DHCP_H
25
+#define DHCP_H
26
+
27
+#include "common.h"
28
+#include "buffer.h"
29
+#include "proto.h"
30
+
31
+#pragma pack(1)
32
+
33
+/* DHCP Option types */
34
+#define DHCP_PAD          0
35
+#define DHCP_ROUTER       3
36
+#define DHCP_MSG_TYPE    53  /* message type (u8) */
37
+#define DHCP_END        255
38
+
39
+/* DHCP Messages types */
40
+#define DHCPDISCOVER 1
41
+#define DHCPOFFER    2
42
+#define DHCPREQUEST  3
43
+#define DHCPDECLINE  4
44
+#define DHCPACK      5
45
+#define DHCPNAK      6
46
+#define DHCPRELEASE  7
47
+#define DHCPINFORM   8
48
+
49
+/* DHCP UDP port numbers */
50
+#define BOOTPS_PORT 67
51
+#define BOOTPC_PORT 68
52
+
53
+struct dhcp {
54
+# define BOOTREQUEST 1
55
+# define BOOTREPLY   2
56
+  uint8_t op;          /* message op */
57
+
58
+  uint8_t  htype;      /* hardware address type (e.g. '1' = 10Mb Ethernet) */
59
+  uint8_t  hlen;       /* hardware address length (e.g. '6' for 10Mb Ethernet) */
60
+  uint8_t  hops;       /* client sets to 0, may be used by relay agents */
61
+  uint32_t xid;        /* transaction ID, chosen by client */
62
+  uint16_t secs;       /* seconds since request process began, set by client */
63
+  uint16_t flags;
64
+  uint32_t ciaddr;     /* client IP address, client sets if known */
65
+  uint32_t yiaddr;     /* 'your' IP address -- server's response to client */
66
+  uint32_t siaddr;     /* server IP address */
67
+  uint32_t giaddr;     /* relay agent IP address */
68
+  uint8_t  chaddr[16]; /* client hardware address */
69
+  uint8_t  sname[64];  /* optional server host name */
70
+  uint8_t  file[128];  /* boot file name */
71
+  uint32_t magic;      /* must be 0x63825363 (network order) */
72
+};
73
+
74
+struct dhcp_full {
75
+  struct openvpn_iphdr ip;
76
+  struct openvpn_udphdr udp;
77
+  struct dhcp dhcp;
78
+# define DHCP_OPTIONS_BUFFER_SIZE 256
79
+  uint8_t options[DHCP_OPTIONS_BUFFER_SIZE];
80
+};
81
+
82
+#pragma pack()
83
+
84
+in_addr_t dhcp_extract_router_msg (struct buffer *ipbuf);
85
+
86
+#endif
... ...
@@ -31,6 +31,7 @@
31 31
 #include "mss.h"
32 32
 #include "event.h"
33 33
 #include "ps.h"
34
+#include "dhcp.h"
34 35
 
35 36
 #include "memdbg.h"
36 37
 
... ...
@@ -976,6 +977,8 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
976 976
   if (!c->options.passtos)
977 977
     flags &= ~PIPV4_PASSTOS;
978 978
 #endif
979
+  if (!c->options.route_gateway_via_dhcp || !route_list_default_gateway_needed (c->c1.route_list))
980
+    flags &= ~PIPV4_EXTRACT_DHCP_ROUTER;
979 981
 
980 982
   if (buf->len > 0)
981 983
     {
... ...
@@ -1001,6 +1004,13 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
1001 1001
 	      /* possibly alter the TCP MSS */
1002 1002
 	      if (flags & PIPV4_MSSFIX)
1003 1003
 		mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
1004
+
1005
+	      /* possibly extract a DHCP router message */
1006
+	      if (flags & PIPV4_EXTRACT_DHCP_ROUTER)
1007
+		{
1008
+		  const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf);
1009
+		  route_list_add_default_gateway (c->c1.route_list, c->c2.es, dhcp_router);
1010
+		}
1004 1011
 	    }
1005 1012
 	}
1006 1013
     }
... ...
@@ -1149,7 +1159,7 @@ process_outgoing_tun (struct context *c)
1149 1149
    * The --mssfix option requires
1150 1150
    * us to examine the IPv4 header.
1151 1151
    */
1152
-  process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_OUTGOING, &c->c2.to_tun);
1152
+  process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_OUTGOING, &c->c2.to_tun);
1153 1153
 
1154 1154
   if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
1155 1155
     {
... ...
@@ -75,6 +75,7 @@ bool send_control_channel_string (struct context *c, const char *str, int msglev
75 75
 #define PIPV4_PASSTOS         (1<<0)
76 76
 #define PIPV4_MSSFIX          (1<<1)
77 77
 #define PIPV4_OUTGOING        (1<<2)
78
+#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
78 79
 
79 80
 void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf);
80 81
 
... ...
@@ -54,6 +54,14 @@ print_opt_route_gateway (const in_addr_t route_gateway, struct gc_arena *gc)
54 54
 }
55 55
 
56 56
 static const char *
57
+print_opt_route_gateway_dhcp (struct gc_arena *gc)
58
+{
59
+  struct buffer out = alloc_buf_gc (32, gc);
60
+  buf_printf (&out, "route-gateway dhcp");
61
+  return BSTR (&out);
62
+}
63
+
64
+static const char *
57 65
 print_opt_route (const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc)
58 66
 {
59 67
   struct buffer out = alloc_buf_gc (128, gc);
... ...
@@ -170,7 +178,7 @@ helper_client_server (struct options *o)
170 170
       if (o->client)
171 171
 	msg (M_USAGE, "--server and --client cannot be used together");
172 172
 
173
-      if (o->server_bridge_defined)
173
+      if (o->server_bridge_defined || o->server_bridge_proxy_dhcp)
174 174
 	msg (M_USAGE, "--server and --server-bridge cannot be used together");
175 175
 
176 176
       if (o->shared_secret_file)
... ...
@@ -295,8 +303,19 @@ helper_client_server (struct options *o)
295 295
    *
296 296
    * ifconfig-pool 10.8.0.128 10.8.0.254 255.255.255.0
297 297
    * push "route-gateway 10.8.0.4"
298
+   *
299
+   * OR
300
+   *
301
+   * server-bridge
302
+   *
303
+   * EXPANDS TO:
304
+   *
305
+   * mode server
306
+   * tls-server
307
+   *
308
+   * push "route-gateway dhcp"
298 309
    */
299
-  else if (o->server_bridge_defined)
310
+  else if (o->server_bridge_defined | o->server_bridge_proxy_dhcp)
300 311
     {
301 312
       if (o->client)
302 313
 	msg (M_USAGE, "--server-bridge and --client cannot be used together");
... ...
@@ -310,18 +329,29 @@ helper_client_server (struct options *o)
310 310
       if (dev != DEV_TYPE_TAP)
311 311
 	msg (M_USAGE, "--server-bridge directive only makes sense with --dev tap");
312 312
 
313
-      verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_start, o->server_bridge_netmask); 
314
-      verify_common_subnet ("--server-bridge", o->server_bridge_pool_start, o->server_bridge_pool_end, o->server_bridge_netmask); 
315
-      verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_end, o->server_bridge_netmask); 
313
+      if (o->server_bridge_defined)
314
+	{
315
+	  verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_start, o->server_bridge_netmask); 
316
+	  verify_common_subnet ("--server-bridge", o->server_bridge_pool_start, o->server_bridge_pool_end, o->server_bridge_netmask); 
317
+	  verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_end, o->server_bridge_netmask); 
318
+	}
316 319
 
317 320
       o->mode = MODE_SERVER;
318 321
       o->tls_server = true;
319
-      o->ifconfig_pool_defined = true;
320
-      o->ifconfig_pool_start = o->server_bridge_pool_start;
321
-      o->ifconfig_pool_end = o->server_bridge_pool_end;
322
-      ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
323
-      o->ifconfig_pool_netmask = o->server_bridge_netmask;
324
-      push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE);
322
+
323
+      if (o->server_bridge_defined)
324
+	{
325
+	  o->ifconfig_pool_defined = true;
326
+	  o->ifconfig_pool_start = o->server_bridge_pool_start;
327
+	  o->ifconfig_pool_end = o->server_bridge_pool_end;
328
+	  ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
329
+	  o->ifconfig_pool_netmask = o->server_bridge_netmask;
330
+	  push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE);
331
+	}
332
+      else if (o->server_bridge_proxy_dhcp)
333
+	{
334
+	  push_option (o, print_opt_route_gateway_dhcp (&o->gc), M_USAGE);
335
+	}
325 336
     }
326 337
   else
327 338
 #endif /* P2MP_SERVER */
... ...
@@ -1214,11 +1214,18 @@ table (not supported on all OSes).
1214 1214
 address if OpenVPN is being run in client mode, and is undefined in server mode.
1215 1215
 .\"*********************************************************
1216 1216
 .TP
1217
-.B --route-gateway gw
1217
+.B --route-gateway gw|'dhcp'
1218 1218
 Specify a default gateway
1219 1219
 .B gw
1220 1220
 for use with
1221 1221
 .B --route.
1222
+
1223
+If
1224
+.B dhcp
1225
+is specified as the parameter,
1226
+the gateway address will be extracted from a DHCP
1227
+negotiation with the OpenVPN server-side LAN.
1228
+.\"*********************************************************
1222 1229
 .TP
1223 1230
 .B --route-metric m
1224 1231
 Specify a default metric
... ...
@@ -2607,13 +2614,23 @@ if you are ethernet bridging.  Use
2607 2607
 instead.
2608 2608
 .\"*********************************************************
2609 2609
 .TP
2610
-.B --server-bridge gateway netmask pool-start-IP pool-end-IP
2610
+.B --server-bridge [ gateway netmask pool-start-IP pool-end-IP ]
2611 2611
 
2612 2612
 A helper directive similar to
2613 2613
 .B --server
2614 2614
 which is designed to simplify the configuration
2615 2615
 of OpenVPN's server mode in ethernet bridging configurations.
2616 2616
 
2617
+If
2618
+.B --server-bridge
2619
+is used without any parameters, it will enable a DHCP-proxy
2620
+mode, where connecting OpenVPN clients will receive an IP
2621
+address for their TAP adapter from the DHCP server running
2622
+on the OpenVPN server-side LAN.
2623
+Note that only clients that support
2624
+the binding of a DHCP client with the TAP adapter (such as
2625
+Windows) can support this mode.
2626
+
2617 2627
 To configure ethernet bridging, you 
2618 2628
 must first use your OS's bridging capability
2619 2629
 to bridge the TAP interface with the ethernet
... ...
@@ -2662,6 +2679,23 @@ push "route-gateway 10.8.0.4"
2662 2662
 .LP
2663 2663
 .RE
2664 2664
 .fi
2665
+
2666
+In another example,
2667
+.B --server-bridge
2668
+(without parameters) expands as follows:
2669
+
2670
+.RS
2671
+.ft 3
2672
+.nf
2673
+.sp
2674
+mode server
2675
+tls-server
2676
+
2677
+push "route-gateway dhcp"
2678
+.ft
2679
+.LP
2680
+.RE
2681
+.fi
2665 2682
 .\"*********************************************************
2666 2683
 .TP
2667 2684
 .B --push "option"
... ...
@@ -169,7 +169,7 @@ static const char usage_message[] =
169 169
   "                  netmask default: 255.255.255.255\n"
170 170
   "                  gateway default: taken from --route-gateway or --ifconfig\n"
171 171
   "                  Specify default by leaving blank or setting to \"nil\".\n"
172
-  "--route-gateway gw : Specify a default gateway for use with --route.\n"
172
+  "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n"
173 173
   "--route-metric m : Specify a default metric for use with --route.\n"
174 174
   "--route-delay n [w] : Delay n seconds after connection initiation before\n"
175 175
   "                  adding routes (may be 0).  If not specified, routes will\n"
... ...
@@ -339,7 +339,7 @@ static const char usage_message[] =
339 339
   "\n"
340 340
   "Multi-Client Server options (when --mode server is used):\n"
341 341
   "--server network netmask : Helper option to easily configure server mode.\n"
342
-  "--server-bridge IP netmask pool-start-IP pool-end-IP : Helper option to\n"
342
+  "--server-bridge [IP netmask pool-start-IP pool-end-IP] : Helper option to\n"
343 343
   "                    easily configure ethernet bridging server mode.\n"
344 344
   "--push \"option\" : Push a config file option back to the peer for remote\n"
345 345
   "                  execution.  Peer must specify --pull in its config file.\n"
... ...
@@ -1226,6 +1226,7 @@ show_settings (const struct options *o)
1226 1226
   SHOW_INT (route_delay_window);
1227 1227
   SHOW_BOOL (route_delay_defined);
1228 1228
   SHOW_BOOL (route_nopull);
1229
+  SHOW_BOOL (route_gateway_via_dhcp);
1229 1230
   if (o->routes)
1230 1231
     print_route_options (o->routes, D_SHOW_PARMS);
1231 1232
 
... ...
@@ -1888,7 +1889,7 @@ static void
1888 1888
 options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
1889 1889
 {
1890 1890
 #if P2MP_SERVER
1891
-  if (o->server_defined || o->server_bridge_defined)
1891
+  if (o->server_defined || o->server_bridge_defined || o->server_bridge_proxy_dhcp)
1892 1892
     {
1893 1893
       if (ce->proto == PROTO_TCPv4)
1894 1894
 	ce->proto = PROTO_TCPv4_SERVER;
... ...
@@ -4237,14 +4238,21 @@ add_option (struct options *options,
4237 4237
   else if (streq (p[0], "route-gateway") && p[1])
4238 4238
     {
4239 4239
       VERIFY_PERMISSION (OPT_P_ROUTE_EXTRAS);
4240
-      if (ip_addr_dotted_quad_safe (p[1]) || is_special_addr (p[1]))
4240
+      if (streq (p[1], "dhcp"))
4241 4241
 	{
4242
-	  options->route_default_gateway = p[1];
4242
+	  options->route_gateway_via_dhcp = true;
4243 4243
 	}
4244 4244
       else
4245 4245
 	{
4246
-	  msg (msglevel, "route-gateway parm '%s' must be an IP address", p[1]);
4247
-	  goto err;
4246
+	  if (ip_addr_dotted_quad_safe (p[1]) || is_special_addr (p[1]))
4247
+	    {
4248
+	      options->route_default_gateway = p[1];
4249
+	    }
4250
+	  else
4251
+	    {
4252
+	      msg (msglevel, "route-gateway parm '%s' must be an IP address", p[1]);
4253
+	      goto err;
4254
+	    }
4248 4255
 	}
4249 4256
     }
4250 4257
   else if (streq (p[0], "route-metric") && p[1])
... ...
@@ -4395,6 +4403,11 @@ add_option (struct options *options,
4395 4395
       options->server_bridge_pool_start = pool_start;
4396 4396
       options->server_bridge_pool_end = pool_end;
4397 4397
     }
4398
+  else if (streq (p[0], "server-bridge") && !p[1])
4399
+    {
4400
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4401
+      options->server_bridge_proxy_dhcp = true;
4402
+    }
4398 4403
   else if (streq (p[0], "push") && p[1])
4399 4404
     {
4400 4405
       VERIFY_PERMISSION (OPT_P_PUSH);
... ...
@@ -302,6 +302,7 @@ struct options
302 302
   bool route_delay_defined;
303 303
   struct route_option_list *routes;
304 304
   bool route_nopull;
305
+  bool route_gateway_via_dhcp;
305 306
 
306 307
 #ifdef ENABLE_OCC
307 308
   /* Enable options consistency check between peers */
... ...
@@ -340,6 +341,8 @@ struct options
340 340
 # define SF_NOPOOL (1<<0)
341 341
   unsigned int server_flags;
342 342
 
343
+  bool server_bridge_proxy_dhcp;
344
+
343 345
   bool server_bridge_defined;
344 346
   in_addr_t server_bridge_ip;
345 347
   in_addr_t server_bridge_netmask;
... ...
@@ -335,6 +335,16 @@ clear_route_list (struct route_list *rl)
335 335
   CLEAR (*rl);
336 336
 }
337 337
 
338
+void
339
+route_list_add_default_gateway (struct route_list *rl,
340
+				struct env_set *es,
341
+				const in_addr_t addr)
342
+{
343
+  rl->spec.remote_endpoint = addr;
344
+  rl->spec.remote_endpoint_defined = true;
345
+  setenv_route_addr (es, "vpn_gateway", rl->spec.remote_endpoint, -1);
346
+}
347
+
338 348
 bool
339 349
 init_route_list (struct route_list *rl,
340 350
 		 const struct route_option_list *opt,
... ...
@@ -138,6 +138,10 @@ bool init_route_list (struct route_list *rl,
138 138
 		      in_addr_t remote_host,
139 139
 		      struct env_set *es);
140 140
 
141
+void route_list_add_default_gateway (struct route_list *rl,
142
+				     struct env_set *es,
143
+				     const in_addr_t addr);
144
+
141 145
 void add_routes (struct route_list *rl,
142 146
 		 const struct tuntap *tt,
143 147
 		 unsigned int flags,
... ...
@@ -186,4 +190,13 @@ netbits_to_netmask (const int netbits)
186 186
   return mask;
187 187
 }
188 188
 
189
+static inline bool
190
+route_list_default_gateway_needed (const struct route_list *rl)
191
+{
192
+  if (!rl)
193
+    return false;
194
+  else
195
+    return !rl->spec.remote_endpoint_defined;
196
+}
197
+
189 198
 #endif
... ...
@@ -100,7 +100,7 @@ key client.key
100 100
 # your server certificates with the nsCertType
101 101
 # field set to "server".  The build-key-server
102 102
 # script in the easy-rsa folder will do this.
103
-;ns-cert-type server
103
+ns-cert-type server
104 104
 
105 105
 # If a tls-auth key is used on the server
106 106
 # then every client must also have the key.
... ...
@@ -114,6 +114,18 @@ ifconfig-pool-persist ipp.txt
114 114
 # out unless you are ethernet bridging.
115 115
 ;server-bridge 10.8.0.4 255.255.255.0 10.8.0.50 10.8.0.100
116 116
 
117
+# Configure server mode for ethernet bridging
118
+# using a DHCP-proxy, where clients talk
119
+# to the OpenVPN server-side DHCP server
120
+# to receive their IP address allocation
121
+# and DNS server addresses.  You must first use
122
+# your OS's bridging capability to bridge the TAP
123
+# interface with the ethernet NIC interface.
124
+# Note: this mode only works on clients (such as
125
+# Windows), where the client-side TAP adapter is
126
+# bound to a DHCP client.
127
+;server-bridge
128
+
117 129
 # Push routes to the client to allow it
118 130
 # to reach other private subnets behind
119 131
 # the server.  Remember that these
... ...
@@ -170,22 +182,18 @@ ifconfig-pool-persist ipp.txt
170 170
 # all IP traffic such as web browsing and
171 171
 # and DNS lookups to go through the VPN
172 172
 # (The OpenVPN server machine may need to NAT
173
-# the TUN/TAP interface to the internet in
174
-# order for this to work properly).
175
-# CAVEAT: May break client's network config if
176
-# client's local DHCP server packets get routed
177
-# through the tunnel.  Solution: make sure
178
-# client's local DHCP server is reachable via
179
-# a more specific route than the default route
180
-# of 0.0.0.0/0.0.0.0.
181
-;push "redirect-gateway"
173
+# or bridge the TUN/TAP interface to the internet
174
+# in order for this to work properly).
175
+;push "redirect-gateway def1 bypass-dhcp"
182 176
 
183 177
 # Certain Windows-specific network settings
184 178
 # can be pushed to clients, such as DNS
185 179
 # or WINS server addresses.  CAVEAT:
186 180
 # http://openvpn.net/faq.html#dhcpcaveats
187
-;push "dhcp-option DNS 10.8.0.1"
188
-;push "dhcp-option WINS 10.8.0.1"
181
+# The addresses below refer to the public
182
+# DNS servers provided by opendns.com.
183
+;push "dhcp-option DNS 208.67.222.222"
184
+;push "dhcp-option DNS 208.67.220.220"
189 185
 
190 186
 # Uncomment this directive to allow different
191 187
 # clients to be able to "see" each other.
... ...
@@ -1,5 +1,5 @@
1 1
 dnl define the OpenVPN version
2
-define(PRODUCT_VERSION,[2.1_rc9])
2
+define(PRODUCT_VERSION,[2.1_rc9a])
3 3
 dnl define the TAP version
4 4
 define(PRODUCT_TAP_ID,[tap0901])
5 5
 define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9])