1 diff -durN openvpn-2.2.2.orig/ChangeLog.IPv6 openvpn-2.2.2/ChangeLog.IPv6
2 --- openvpn-2.2.2.orig/ChangeLog.IPv6 1970-01-01 01:00:00.000000000 +0100
3 +++ openvpn-2.2.2/ChangeLog.IPv6 2012-06-01 10:40:28.000000000 +0200
5 +Do 31. Dez 15:32:40 CET 2009 Gert Doering
7 + * Basic IPv6 p2mp functionality implemented
12 + - ifconfig-ipv6-pool
17 + - init.c: init & setup IPv6 route list & add/delete IPv6 routes
18 + - tun.c: add "ifconfig" and "route" handling for IPv6
19 + - multi.c: IPv6 ifconfig-pool assignments
20 + put to route-hash table
22 + - pool.c: extend pools to handle IPv4+IPv6, and also return IPv6 address
23 + IPv6 address saved to file if ifconfig-pool-persist is set
24 + (but ignored on read due to the way pools work)
25 + - mroute.c: handle reading src/dst addresses from IPv6 packets
26 + (so multi.c can check against route-hash table)
27 + handle printing of IPv6 mroute_addr structure
28 + - helper.c: implement "server-ipv6" macro (->ifconfig-ipv6, pool, ...)
29 + - options.c: implement all the new options
30 + add helper functions for IPv6 address handling
31 + - forward.c: tell do_route() about IPv6 routes
32 + - route.c: handle IPv6 route lists + route option lists
33 + extend add_routes() to do IPv4 + IPv6 route lists
34 + extend delete_routes() to do IPv4 + IPv6 route lists
35 + implement add_route_ipv6(), delete_route_ipv6() to call
36 + system-dependend external program to do the work
37 + - push.c: handle pushing of "ifconfig-ipv6" option
38 + - socket.c: helper function to check & print IPv6 address strings
41 + - operating system support on all but Linux (ifconfig, route)
42 + - route-ipv6 gateway handling
43 + - iroute-ipv6 not implemented
44 + - TAP support: ifconfig, routing (route needs gateway!)
46 + * release as patch 20091231-1
48 +Thu Dec 31 17:02:08 CET 2009
50 + * NetBSD port (NetBSD 3.1 on Sparc64)
52 + * mroute.c, socket.c: make byte/word access to in6_addr more portable
54 + * tun.c: fix IPv6 ifconfig arguments on NetBSD
56 + still doesn't work on NetBSD 3.1, "ifconfig tun0 inet6..." errors with
58 + ifconfig: SIOCAIFADDR: Address family not supported by protocol family
60 + (sys/net/if_tun.c, needs to be revision 1.80 or later, NetBSD PR 32944,
61 + included in NetBSD 4.0 and up)
64 +Fri Jan 1 14:07:15 CET 2010
66 + * FreeBSD port (FreeBSD 6.3-p12 on i386)
68 + * tun.c: implement IPv6 ifconfig setting for FreeBSD
70 + * route.c: fix %s/%s argument to IPv6 route add/delete command for *BSD
72 + * TEST SUCCESS: FreeBSD 6.3-p12, server-ipv6, route-ipv6, ccd/iroute-ipv6
74 + * multi.c: implement setting and deleting of iroute-ipv6
75 + (multi_add_iroutes(), multi_del_iroutes())
76 + * mroute.c: add mroute_helper_add_iroute6(), mroute_helper_del_iroute6()
77 + * mroute.h: add prototypes, increase MR_HELPER_NET_LEN to 129 (/0.../128)
78 + * multi.c: zeroize host part of IPv6 iroutes in multi_learn_in6_addr()
79 + * mroute.c: implement mroute_addr_mask_host_bits() for IPv6
81 + * TEST SUCCESS: Linux 2.6.30 (Gentoo)/iproute2, server-ipv6, ccd/iroute-ipv6
83 + * TEST SUCCESS: Linux 2.6.30 (Gentoo)/ifconfig, client-ipv6
85 + * TEST FAIL: NetBSD 5.0, IPv6 client
86 + - "ifconfig tun0 .../64" does not create a "connected" route
87 + - adding routes fails
89 + --> more work to do here.
91 + * release as patch 20100101-1
94 + FreeBSD 6.3-p12 server "--topology subnet"
95 + Linux/ifconfig client
96 + - BSD sends ICMP6 neighbor solicitations, which are ignored by Linux
97 + - server tun interface is not in p2p mode, client tun interface *is*
99 + * TEST SUCCESS: non-ipv6 enabled client -> "--server-ipv6" server
100 + (warnings in the log file, but no malfunctions)
103 +Sat Jan 2 19:48:35 CET 2010
105 + * tun.c: change "ipv6_support()", do not turn off tt->ipv6 unconditionally
106 + if we don't know about OS IPv6 support - just log warning
108 + * tun.c: implement "ifconfig inet6" setting for MacOS X / Darwin
110 + * route.c: split *BSD system dependent part of add/delete_route_ipv6()
111 + into FreeBSD/Dragonfly and NetBSD/Darwin/OpenBSD variants
112 + ("2001:db8::/64" vs. "2001:db8:: --prefixlen 64").
114 + * tun.c: on MacOS X, NetBSD and OpenBSD, explicitely set on-link route
116 + * TEST SUCCESS: MacOS X, client-ipv6 with route-ipv6
119 +Sun Jan 3 10:55:31 CET 2010
121 + * route.c: NetBSD fails with "-iface tun0", needs gateway address
122 + (assume that the same syntax is needed for OpenBSD)
124 + * route.h: introduce "remote_endpoint_ipv6" into "struct route_ipv6_list"
126 + * init.c: pass "ifconfig_ipv6_remote" as gateway to init_route_ipv6_list()
129 + - init_route_ipv6(): use "remote_endpoint_ipv6" as IPv6 gateway address
130 + if no gateway was specified explicitely
132 + - init_route_ipv6_list(): fill in "remote_endpoint_ipv6", if parseable
134 + - get rid of "GATEWAY-LESS ROUTE6" warning
136 + * route.c, add_route_ipv6()
137 + - explicitely clear host bits of base address, to be able to more
138 + easily set up "connected" /64 routes on NetBSD+Darwin
140 + - split system-dependent part between Darwin and NetBSD/OpenBSD
141 + (Darwin can use "-iface tun0", NetBSD/OpenBSD get gateway address)
143 + - change Solaris comments from "known-broken" to "unknown"
145 + * tun.c: rework NetBSD tunnel initialization and tun_read() / tun_write()
146 + to work the same way OpenBSD and NetBSD do - tunnel is put into
147 + "multi-af" mode, and all packet read/write activity is prepended by
148 + a 32 bit value specifying the address family.
150 + * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6
152 + * TEST SUCCESS: MacOS X 10.5: client-ipv6 with route-ipv6
154 + * (RE-)TEST SUCCESS: Linux/iproute2: server-ipv6
155 + Linux/ifconfig: client-ipv6
156 + FreeBSD 6.3: server-ipv6
158 + * release as patch 20100103-1
160 + * options.c: document all new options in "--help"
162 + * tun.c: fix typo in Solaris-specific section
164 + * socket.h, socket.c: change u_int32_t to uint32_t
165 + (Solaris - and all the rest of the code uses "uintNN" anyway)
167 +Mon Jan 4 17:46:58 CET 2010
169 + * socket.c: rework add_in6_addr() to use 32-bit access to struct in6_addr
170 + (Solaris has no 16-bit values in union, but this is more elegant as well)
172 + * tun.c: fix "ifconfig inet6" command for Solaris
174 + * tun.c: make sure "tun0 inet6" is unplumbed first, cleanup leftovers
176 + * route.c: add routes with "metric 0" on solaris, otherwise they just
177 + don't work (someone who understands Solaris might want to fix this).
179 + * Solaris "sort of" works now - ifconfig works, route add does not give
180 + errors, "netstat -rn" looks right, but packets are discarded unless
181 + the routes are installed with "metric 0". So we just use "metric 0"...
183 + * CAVEAT: Solaris "ifconfig ... preferred" interferes with source address
184 + selection. So if there are any active IPv6 interfaces configured with
185 + "preferred", packets leaving out the tunnel will use the wrong source
186 + IPv6 address. Not fixable from within OpenVPN.
188 + * CAVEAT2: Solaris insists on doing DHCPv6 on tun0 interfaces by default,
189 + so DHCPv6 solicitation packets will be seen. Since the server end has
190 + no idea what to do with them, they are a harmless nuisance. Fixable
191 + on the Solaris side via "ndpd.conf" (see ``man ifconfig'').
193 + * release as patch 20100104-1
195 +Fri Jan 8 10:00:50 CET 2010
197 + * import into git repository
199 + * options.c: add sanity checks for most typical error cases
200 + (--ifconfig-ipv6-pool configured with no --ifconfig-ipv6, etc)
202 + * options.c: modify get_ipv6_addr() to be more flexible about netbits
203 + (optional now, default to /64) and to return the address-without-netbits
204 + string now (-> for options that want the IPv6 address in printable
205 + form, but without /nn)
207 + * options.c: modify --ifconfig-ipv6 to optionally accept /netbits,
208 + you can do now "ifconfig-ipv6 2001:df8::1/64 2001:df8::2" or just
209 + "ifconfig-ipv6 2001:df8::5 2001:df8::7", defaulting to /64
211 + * options.h: add necessary structure elements for --ifconfig-ipv6-push
213 + * options.c: implement "parse options" side of --ifconfig-ipv6-push
215 +Tue Jan 12 22:42:09 CET 2010
217 + * tun.c: in TARGET_NETBSD #ifdef, distinguish between "old" code
218 + (IPv4 only, but unmodified read/write) and "new" code (multi-af,
219 + extra 32 bit AF on read/write of the tun interface) - pre-4.0
220 + NetBSD systems don't have TUNSIFHEAD, no way to have common code.
222 + * TEST SUCCESS: NetBSD 5.0/Sparc64: client-ipv6 with route-ipv6 (v4+v6)
224 + * TEST SUCCESS: NetBSD 3.1/Sparc64: client-ipv6 with route-ipv6 (v4-only)
226 +Thu Jan 14 15:41:50 CET 2010
228 + * multi.c: if "--ifconfig-push" is used together with "--ifconfig-ipv6-pool"
229 + and no "--ifconfig-ipv6-push" is seen, issue warning - the current
230 + implementation of pools has IPv6 tied to IPv4, so if v4 does not use
231 + the pool, it breaks for IPv6. Not a *big* problem (since there is
232 + enough v6, just give those users a static v6 address as well), but needs
233 + to be pointed out clearly.
235 + * release as patch 20100114-1
237 +Tue Feb 16 14:43:28 CET 2010
239 + * options.c: print "IPv6 payload patch" release date in "--version"
241 + * tun.c: undo change to init_tun() (moving "bool tun" and call to
242 + "is_tun_p2p()" further up) - it wasn't needed and breaks "make check"
244 + * git stuff: rebase on David Sommerseth's openvpn-testing git tree
246 + * release as patch 20100216-1
248 +Fri Feb 26 19:59:01 CET 2010
250 + * init.c: initialize tuntap->ipv6 in do_init_tun() (to make sure it's
251 + always initialized early-enough, independent of the sequence of
252 + do_ifconfig()/open_tun() [see ifconfig_order() in tun.h])
254 + * tun.c, init.c: remove "bool ipv6" argument to tuncfg(), open_tun()
255 + and open_tun_generic() - obsoleted by previous change
257 + * tun.c: remove ipv6_support() - original purpose was unclear, and all
258 + current platforms (except linux-very-old) fully support IPv6 now :-)
260 + * tun.c: initial implementation of "netsh" IPv6-ifconfig for Win32
262 + * RE-TEST SUCCESS: Linux/i386/ifconfig, client-tun/net30, v4+v6
264 +Sun Feb 28 17:05:57 CET 2010
266 + * tun.c: NetBSD dependent part: correct destroying/re-creation of tun dev
268 + * tun.c: move adding of "connected" IPv6 prefix to new helper function,
269 + add_route_connected_v6_net()
271 + * RE-TEST SUCCESS: NetBSD 5.0/Sparc64, client-tun/net30, v4+v6
273 + * RE-TEST SUCCESS: NetBSD 3.1/Sparc64: client-tun/net30, v4-only
275 + * RE-TEST SUCCESS: Linux/i386/iproute2: server-tun/net30, v4+v6
277 + * tun.c: add #ifdef TARGET_DARWIN block for *_tun() functions, to
278 + be able to modify close_tun() for unconfiguring IPv6
280 + * tun.c: on close_tun() on MacOS X, need to de-configure "lo0" route for
281 + configured IPv6 address
283 + * RE-TEST SUCCESS: MacOS X (10.5)/i386: client-tun/net30, v4+v6
285 + * route.c: implement ipv6 route adding / deletion via "netsh" for WIN32
287 + * TEST FAIL: Windows XP fails, because the tun/tap driver does not
288 + forward IPv6 frames kernel->userland if in "tun" mode
290 + * options.c: set IPv6 version to 20100228-1
292 + * release as patch 20100228-1
294 +Sun Mar 7 19:17:33 CET 2010
296 + * options.c: set IPv6 version to 20100307-1
298 + * TODO.IPv6: add note about OpenBSD TODO (#16)
300 + * route.c: set (and remove) "magic next hop" fe80::8 for IPv6 routes on
303 + * install-win32/settings.in: bump TAP driver version from 9.6 to 9.7
304 + and TAP_RELDATE to "07/03/2010"
306 + * tap-win32/proto.h: add data types and definitions needed for IPv6
308 + * tap-win32/types.h: add m_UserToTap_IPv6 ethernet header for IPv6 packets
310 + * tap-win32/tapdrvr.c: implement support for IPv6 in TUN mode:
311 + - IPv6 packets User->OS need correct ether type
312 + - IPv6 packets OS->User get correctly forwarded
313 + - IPv6 neighbour discovery packets for "fe80::8" (magic address
314 + installed as route-nexthop by OpenVPN.exe) get answered locally
316 + * TEST SUCCESS: WindowsXP/32bit: client-tun/net30, v4+v6
318 + * tun.c: if IPv6 requested in TUN mode, and TUN/TAP driver version
319 + is older than 9.7, log warning and disable IPv6 (won't work anyway).
321 + * release as patch 20100307-1
323 +Sat Jul 10 14:37:52 CEST 2010
325 + * TEST SUCCESS: point-to-point tun mode with --ifconfig-ipv6 between
326 + Solaris10/sparc and Linux (Michal Ludvig)
327 + (using the whiteboard tun driver on Solaris, otherwise "no IPv6")
329 +Sun Aug 8 12:30:44 CEST 2010
331 + * route.c: split NetBSD and OpenBSD parts of add_route_ipv6() and
332 + delete_route_ipv6(), implement OpenBSD variant
333 + (needs "-prefixlen nn" while NetBSD uses "/nn")
335 + * tun.c: implement IPv6 ifconfig for OpenBSD
337 + * tun.c: destroy tunX interface at tun_close() on OpenBSD (cleanup)
339 + * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
341 +Thu Sep 2 21:18:32 CEST 2010
343 + * tun.c: the TAP binary in 2.2-beta3 has the IPv6 related changes, but
344 + the version number is 9.8 now -> check for 9.8, not 9.7
346 +Wed Sep 22 22:20:37 CEST 2010
348 + * tun.c: bugfix for Linux/iproute2/"topology subnet". Works :-)
350 + * TEST SUCCESS: Linux/ifconfig: client-tun/net30+subnet, v4+v6
352 + * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
354 + * options.c: tag as 20100922-1 so "allmerged" users can see IPv6 change
356 +Fri Sep 24 17:57:41 CEST 2010
358 + * TEST SUCCESS: Linux/<both>: client-tap, v4+v6, ping6 on connected addr
360 + * TEST FAIL: Linux/<both>: client-tap, v6, route6 (gateway missing)
362 +Do 21. Okt 19:36:49 CEST 2010
364 + * t_client.sh.in: cherrypick commit f25fe91a40aa3f and 6f1e61b41be52
365 + (proper exit codes to signal "SKIP" if we do not want to run)
367 +So 16. Jan 17:25:23 CET 2011
369 + * tun.c, route.c: cherrypick 121755c2cb4891f and f0eac1a5979096c67
370 + (TAP driver and "topology subnet" support for Solaris)
372 + * tun.c: add IPv6 configuration for TAP interfaces (<device>:1 inet6)
374 + * tun.c: on close_tun on Solaris, unplumb IPv6 TUN or TAP interfaces
376 + * TEST SUCCESS: OpenSolaris: client-tun, v4+v6
377 + TEST SUCCESS: OpenSolaris: client-tap, v4+v6, ping6 on connected addr
378 + TEST FAIL: OpenSolaris: client-tap, v6, route6 (gateway missing)
380 +So 24. Apr 16:51:45 CEST 2011
382 + * rebase to "beta2.2" branch (at 2.2RC2 tag)
384 + * mroute.c: remove mroute_helper_lock/_unlock() calls for IPv6
385 + * socket.c: remove locking with L_INET_NTOA mutex
386 + (all the threading stuff got removed by David Sommerseth for 2.2)
388 + * mroute.c: remove duplicate mroute_helper_add_iroute6() and
389 + mroute_helper_del_iroute6() - "git rebase" artefact
391 + * ChangeLog.IPv6 and TODO.IPv6: add to commit
393 + * options.c: tag as 20110424-2 (2.2RC2)
395 + * TEST SUCCESS: Linux/ifconfig: client-tun/net30+subnet, v4+v6
397 + * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
399 +Thu Apr 28 19:10:01 CEST 2011
401 + * rebase to "origin/release/2.2" branch (at v2.2.0 tag)
403 +Thu May 19 20:51:12 CEST 2011
405 + * include Windows "netsh add" -> "netsh set ... store=active" patch from
406 + Seth Mos, to fix restart problems on Windows due to persistant addresses
408 + * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
410 +Sat May 21 17:03:20 CEST 2011
412 + * tun.c: Solaris cleanup (use CLEAR() to zero-out "ifr")
414 + * tun.c: Windows cleanup: remove route and IPv6 address on disconnect
416 + * route.c, route.h: remove "static" from delete_route_ipv6(), needed
417 + for ipv6-route cleanup on disconnect
419 + * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
421 + * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
423 +So 22. Mai 14:46:12 CEST 2011
425 + * Tony Lim: removing routes fails on windows if certain bits are set
426 + in the "host part" (others are silently ignored) -->
428 + * route.c: create print_in6_addr_netbits_only() helper, call from
429 + add_route_ipv6() and delete_route_ipv6() to get only network part
430 + of route-to-be-modified
432 + * route.c: set 'store=active' on adding routes on WIN32 as well (Tony Lim)
434 + * options.c: bump IPv6 release to 20110522-1
436 + * TEST SUCCESS: Linux/iproute2: client-tun/net30+subnet, v4+v6
438 + * TEST SUCCESS: Windows XP SP3: client-tun/net30, v4+v6
440 + * TEST SUCCESS: Windows 7 Home Premium: client-tun/net30, v4+v6
442 + * TEST SUCCESS: OpenBSD 4.7: client-tun/net30, v4+v6
443 + TEST FAIL: OpenBSD 4.7: client-tun/subnet, v4
444 + (seems to be due to "topology subnet has just not been implemented yet")
445 diff -durN openvpn-2.2.2.orig/README.IPv6 openvpn-2.2.2/README.IPv6
446 --- openvpn-2.2.2.orig/README.IPv6 1970-01-01 01:00:00.000000000 +0100
447 +++ openvpn-2.2.2/README.IPv6 2012-06-01 10:40:28.000000000 +0200
449 +This is an experimentally patched version of OpenVPN 2.1 with IPv6
452 +Go here for release notes and documentation:
454 + http://www.greenie.net/ipv6/openvpn.html
456 +Gert Doering, 31.12.2009
457 diff -durN openvpn-2.2.2.orig/TODO.IPv6 openvpn-2.2.2/TODO.IPv6
458 --- openvpn-2.2.2.orig/TODO.IPv6 1970-01-01 01:00:00.000000000 +0100
459 +++ openvpn-2.2.2/TODO.IPv6 2012-06-01 10:40:28.000000000 +0200
461 +known issues for IPv6 payload support in OpenVPN
462 +-----------------------------------------------
464 +1.) "--topology subnet" doesn't work together with IPv6 payload on FreeBSD
465 + (verified for FreeBSD server, Linux/ifconfig client, problems
466 + with ICMP6 neighbor solicitations from BSD not being answered by Linux)
468 +2.) NetBSD IPv6 support doesn't work
469 + ("connected" route is not auto-created, "route-ipv6" adding fails)
473 +3.) route deletion for IPv6 routes is not yet done
475 + * fixed for configured routes, 3.1.10 *
476 + * missing for manual-ifconfig-connected (NetBSD, Darwin, Win32)
477 + * fixed for Win32, 22.5.2011
479 +4.) do "ifconfig tun0 inet6 unplumb" or "ifconfig tun0 destroy" for
480 + Solaris, *BSD, ... at program termination time, to clean up leftovers
481 + (unless tunnel persistance is desired).
483 + For Solaris, only the "ipv6 tun0" is affected, for the *BSDs all tun0
486 +4a.) deconfigure IPv6 on tun interface on session termination, otherwise
487 + one could end up with something like this (on NetBSD):
489 +tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
490 + inet 10.9.0.18 -> 10.9.0.17 netmask 0xffffffff
491 + inet6 fe80::a00:20ff:fece:d299%tun0 -> prefixlen 64 scopeid 0x3
492 + inet6 2001:608:4:eff::2000:3 -> prefixlen 64
493 + inet6 2001:608:4:eff::1:3 -> prefixlen 64
495 + (pool was changed, previous address still active on tun0, breakage)
497 + * semi-fixed for NetBSD, 28.2.10, always do tun0 destroy / tun0 create
498 + before actual ifconfig -- tunnel still lingers after OpenVPN quits
500 +4b.) verify this - on FreeBSD, tun0 is auto-destroyed if created by
501 + opening /dev/tun (and lingers if created by "ifconfig tun0 create")
503 + -> use for persistant tunnels on not-linux?
505 +5.) add new option "ifconfig-ipv6-push"
506 + (per-client static IPv6 assignment, -> radiusplugin, etc)
508 + * implemented, 14.1.10 *
510 +6.) add new option "route-ipv6-gateway"
512 +7.) add "full" gateway handling for IPv6 in route.c
513 + (right now, the routes are just sent down the tun interface, if the
514 + operating system in questions supports that, without care for the
515 + gateway address - which does not work for gateways that are supposed
516 + to point elsewhere. Also, it doesn't work for TAP interfaces.
518 +8.) full IPv6 support for TAP interfaces
519 + (main issue should be routes+gateway - and testing :-) )
521 + test 2010/09/24: TAP itself works on linux/ifconfig+iproute2, but
522 + route-via-tap doesn't work at all (route points to "tap0" which fails)
524 +17:51:14.075412 fe:ab:6e:c5:53:71 > 33:33:ff:00:00:01, ethertype IPv6 (0x86dd), length 86: 2001:608:4:a053::1:0 > ff02::1:ff00:1: ICMP6, neighbor solicitation, who has 2001:608:4:a001::1, length 32
526 + how is iroute-via-tap supposed to work??
528 +9.) verify that iroute-ipv6 and route-ipv6 interact in the same way as
529 + documented for iroute/route:
531 + A's subnet, OpenVPN must push this route to all clients
532 + EXCEPT for A, since the subnet is already owned by A.
533 + OpenVPN accomplishes this by not
534 + not pushing a route to a client
535 + if it matches one of the client's iroutes.
537 +10.) extend "ifconfig-ipv6" to handle specification of /netbits, pushing
538 + of /netbits, and correctly ifconfig'ing this
539 + (default, if not specified: /64)
541 +11.) do not add ipv6-routes if tun-ipv6 is not set - complain instead
545 +12.) handle incoming [::] and [fe80:...] packets in tun-p2mp MULTI mode
546 + (most likely those are DAD packets)
547 + silently ignore DAD?
548 + Or accept-and-forward iff (multicast && client2client)?
551 +13.) from Martin List-Petersen:
553 + One thing, and I guess this requires modifications in
554 + network-manager-openvpn: It also works, BUT ignores "push
555 + route-ipv6-gateway" and "push route-ipv6 ...." (obviously routes pushed
556 + from the server) entirely.
558 +14.) from ##openvpn-discussion:
560 + new features should be #ifdef'ed
562 + (check whether this is feasible at all)
564 +15.) IPv6 related environment variables
566 + - document all of them in openvpn.8
567 + - make sure that all existing IPv4 stuff has IPv6 counterparts
570 + - implement ifconfig/route for IPv6
571 + - revert ifconfig/open_tun order to "normal" (separate commit!!!)
572 + (openvpn-devel, Subject: OpenBSD)
575 +17.) client-option (Elwood)
576 + - ignore-v6-push-options yes/no
577 + - ignore-v6-route-push ("as for IPv4 routes")
579 +18.) fail-save? "what if 'ip -6 addr add' fails" -> fail, or fallback to v4?
580 + (-> recomment setting "ignore-v6-push-options yes")
582 +19.) safety check: if connecting over IPv6 (v6 transport) and the pushed
583 + route-ipv6 network encompasses the server IPv6 address, make sure
584 + we at least log a warning (until we can fiddle with external routing
585 + to make this work correctly).
587 +20.) show "route add" / "route delete" commands for IPv6 in log file
588 + (we show the "ifconfig" commands, so why not the routes?)
590 + 2010-08-07: this is a null-feature - it's already there, but with
591 + different debug level (M_INFO vs. D_ROUTE) so user
594 +21.) enable ipv6-only server operations
595 + - decouple ipv6 pool handling from ipv4 pool
596 + - make sure Rest of OpenVPN doesn't assume "there will always be IPv4"
598 +22.) implement --learn-address for IPv6
600 +23.) FreeBSD 8 seems to require explicit setting of the "ifconfig" IPv6
601 + route, while FreeBSD 6+7 don't --> more testing, and code fix
603 + workaround for the time being: just add
605 + server-ipv6 2001:608:4:a051::/64
606 + route-ipv6 2001:608:4:a051::/64
610 + (problem + workaround applies both to tun and tap style devices)
612 +24.) implement link-local IPv6 addresses
613 + (OSPFv3 over TUN/multipoint does not work right now)
614 diff -durN openvpn-2.2.2.orig/forward.c openvpn-2.2.2/forward.c
615 --- openvpn-2.2.2.orig/forward.c 2011-12-13 17:58:56.000000000 +0100
616 +++ openvpn-2.2.2/forward.c 2012-06-01 10:40:28.000000000 +0200
619 check_add_routes_action (struct context *c, const bool errors)
621 - do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
622 + do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
623 + c->c1.tuntap, c->plugins, c->c2.es);
625 event_timeout_clear (&c->c2.route_wakeup);
626 event_timeout_clear (&c->c2.route_wakeup_expire);
627 diff -durN openvpn-2.2.2.orig/helper.c openvpn-2.2.2/helper.c
628 --- openvpn-2.2.2.orig/helper.c 2011-12-13 17:58:56.000000000 +0100
629 +++ openvpn-2.2.2/helper.c 2012-06-01 10:40:28.000000000 +0200
637 + * HELPER DIRECTIVE for IPv6
639 + * server-ipv6 2001:db8::/64
645 + * ifconfig-ipv6 2001:db8::1 2001:db8::2
647 + * ifconfig-ipv6-pool 2001:db8::1:0/64
650 + if ( o->server_ipv6_defined )
652 + if ( ! o->server_defined )
654 + msg (M_USAGE, "--server-ipv6 must be used together with --server");
656 + if ( o->server_flags & SF_NOPOOL )
658 + msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
660 + if ( o->ifconfig_ipv6_pool_defined )
662 + msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
665 + /* local ifconfig is "base address + 1" and "+2" */
666 + o->ifconfig_ipv6_local =
667 + print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc );
668 + o->ifconfig_ipv6_remote =
669 + print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc );
671 + /* pool starts at "base address + 0x10000" */
672 + ASSERT( o->server_netbits_ipv6 < 96 ); /* want 32 bits */
673 + o->ifconfig_ipv6_pool_defined = true;
674 + o->ifconfig_ipv6_pool_base =
675 + add_in6_addr( o->server_network_ipv6, 0x10000 );
676 + o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6;
678 + o->tun_ipv6 = true;
680 + push_option( o, "tun-ipv6", M_USAGE );
686 diff -durN openvpn-2.2.2.orig/init.c openvpn-2.2.2/init.c
687 --- openvpn-2.2.2.orig/init.c 2011-12-13 17:58:56.000000000 +0100
688 +++ openvpn-2.2.2/init.c 2012-06-01 10:40:28.000000000 +0200
690 msg (M_FATAL|M_OPTERR,
691 "options --mktun or --rmtun should only be used together with --dev");
692 tuncfg (options->dev, options->dev_type, options->dev_node,
693 - options->tun_ipv6, options->persist_mode,
694 + options->persist_mode,
695 options->username, options->groupname, &options->tuntap_options);
696 if (options->persist_mode && options->lladdr)
697 set_lladdr(options->dev, options->lladdr, NULL);
698 @@ -1066,6 +1066,8 @@
700 if (c->options.routes && !c->c1.route_list)
701 c->c1.route_list = new_route_list (c->options.max_routes, &c->gc);
702 + if (c->options.routes_ipv6 && !c->c1.route_ipv6_list)
703 + c->c1.route_ipv6_list = new_route_ipv6_list (c->options.max_routes, &c->gc);
707 @@ -1108,6 +1110,45 @@
712 +do_init_route_ipv6_list (const struct options *options,
713 + struct route_ipv6_list *route_ipv6_list,
715 + struct env_set *es)
717 + const char *gw = NULL;
718 + int dev = dev_type_enum (options->dev, options->dev_type);
721 + if (dev != DEV_TYPE_TUN )
722 + msg( M_WARN, "IPv6 routes on TAP devices are going to fail on some platforms (need gateway spec)" ); /* TODO-GERT */
724 + gw = options->ifconfig_ipv6_remote; /* default GW = remote end */
725 +#if 0 /* not yet done for IPv6 - TODO!*/
726 + if ( options->route_ipv6_default_gateway ) /* override? */
727 + gw = options->route_ipv6_default_gateway;
730 + if (options->route_default_metric)
731 + metric = options->route_default_metric;
733 + if (!init_route_ipv6_list (route_ipv6_list,
734 + options->routes_ipv6,
740 + openvpn_exit (OPENVPN_EXIT_STATUS_ERROR); /* exit point */
744 + /* copy routes to environment */
745 + setenv_routes_ipv6 (es, route_ipv6_list);
751 * Called after all initialization has been completed.
753 @@ -1172,12 +1213,13 @@
755 do_route (const struct options *options,
756 struct route_list *route_list,
757 + struct route_ipv6_list *route_ipv6_list,
758 const struct tuntap *tt,
759 const struct plugin_list *plugins,
762 - if (!options->route_noexec && route_list)
763 - add_routes (route_list, tt, ROUTE_OPTION_FLAGS (options), es);
764 + if (!options->route_noexec && ( route_list || route_ipv6_list ) )
765 + add_routes (route_list, route_ipv6_list, tt, ROUTE_OPTION_FLAGS (options), es);
767 if (plugin_defined (plugins, OPENVPN_PLUGIN_ROUTE_UP))
769 @@ -1234,11 +1276,16 @@
771 c->options.ifconfig_local,
772 c->options.ifconfig_remote_netmask,
773 + c->options.ifconfig_ipv6_local,
774 + c->options.ifconfig_ipv6_remote,
775 addr_host (&c->c1.link_socket_addr.local),
776 addr_host (&c->c1.link_socket_addr.remote),
777 !c->options.ifconfig_nowarn,
780 + /* flag tunnel for IPv6 config if --tun-ipv6 is set */
781 + c->c1.tuntap->ipv6 = c->options.tun_ipv6;
783 init_tun_post (c->c1.tuntap,
785 &c->options.tuntap_options);
786 @@ -1270,6 +1317,8 @@
787 /* parse and resolve the route option list */
788 if (c->options.routes && c->c1.route_list && c->c2.link_socket)
789 do_init_route_list (&c->options, c->c1.route_list, &c->c2.link_socket->info, false, c->c2.es);
790 + if (c->options.routes_ipv6 && c->c1.route_ipv6_list )
791 + do_init_route_ipv6_list (&c->options, c->c1.route_ipv6_list, false, c->c2.es);
794 if (!c->options.ifconfig_noexec
795 @@ -1286,7 +1335,7 @@
797 /* open the tun device */
798 open_tun (c->options.dev, c->options.dev_type, c->options.dev_node,
799 - c->options.tun_ipv6, c->c1.tuntap);
802 /* set the hardware address */
803 if (c->options.lladdr)
804 @@ -1315,7 +1364,8 @@
806 /* possibly add routes */
807 if (!c->options.route_delay_defined)
808 - do_route (&c->options, c->c1.route_list, c->c1.tuntap, c->plugins, c->c2.es);
809 + do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list,
810 + c->c1.tuntap, c->plugins, c->c2.es);
813 * Did tun/tap driver give us an MTU?
814 @@ -1389,8 +1439,9 @@
817 /* delete any routes we added */
818 - if (c->c1.route_list)
819 - delete_routes (c->c1.route_list, c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
820 + if (c->c1.route_list || c->c1.route_ipv6_list )
821 + delete_routes (c->c1.route_list, c->c1.route_ipv6_list,
822 + c->c1.tuntap, ROUTE_OPTION_FLAGS (&c->options), c->c2.es);
824 /* actually close tun/tap device based on --down-pre flag */
825 if (!c->options.down_pre)
826 diff -durN openvpn-2.2.2.orig/init.h openvpn-2.2.2/init.h
827 --- openvpn-2.2.2.orig/init.h 2011-12-13 17:58:56.000000000 +0100
828 +++ openvpn-2.2.2/init.h 2012-06-01 10:40:28.000000000 +0200
831 void do_route (const struct options *options,
832 struct route_list *route_list,
833 + struct route_ipv6_list *route_ipv6_list,
834 const struct tuntap *tt,
835 const struct plugin_list *plugins,
837 diff -durN openvpn-2.2.2.orig/misc.c openvpn-2.2.2/misc.c
838 --- openvpn-2.2.2.orig/misc.c 2011-12-13 17:58:56.000000000 +0100
839 +++ openvpn-2.2.2/misc.c 2012-06-01 10:40:28.000000000 +0200
840 @@ -1001,7 +1001,9 @@
842 const char *str = construct_name_value (name_tmp, val_tmp, &gc);
843 env_set_add (es, str);
844 - /*msg (M_INFO, "SETENV_ES '%s'", str);*/
845 +#if DEBUG_VERBOSE_SETENV
846 + msg (M_INFO, "SETENV_ES '%s'", str);
850 env_set_del (es, name_tmp);
851 diff -durN openvpn-2.2.2.orig/mroute.c openvpn-2.2.2/mroute.c
852 --- openvpn-2.2.2.orig/mroute.c 2011-12-13 21:17:06.000000000 +0100
853 +++ openvpn-2.2.2/mroute.c 2012-06-01 10:42:51.000000000 +0200
859 +mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
863 + ma->type = MR_ADDR_IPV6 | mask;
866 + *(struct in6_addr *)ma->addr = src;
871 mroute_is_mcast (const in_addr_t addr)
873 return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
876 +/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
877 + * the address as being a multicast address"
880 +mroute_is_mcast_ipv6 (const struct in6_addr addr)
882 + return (addr.s6_addr[0] == 0xff);
888 @@ -157,13 +178,29 @@
893 - if( !ipv6warned ) {
894 - msg (M_WARN, "IPv6 in tun mode is not supported in OpenVPN 2.2");
899 + if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr))
901 + const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf);
902 +#if 0 /* very basic debug */
903 + struct gc_arena gc = gc_new ();
904 + msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
905 + print_in6_addr( ipv6->saddr, 0, &gc ),
906 + print_in6_addr( ipv6->daddr, 0, &gc ));
910 + mroute_get_in6_addr (src, ipv6->saddr, 0);
911 + mroute_get_in6_addr (dest, ipv6->daddr, 0);
913 + if (mroute_is_mcast_ipv6 (ipv6->daddr))
914 + ret |= MROUTE_EXTRACT_MCAST;
916 + ret |= MROUTE_EXTRACT_SUCCEEDED;
920 + msg (M_WARN, "IP packet with unknown IP version=%d seen",
921 + OPENVPN_IPH_GET_VER (*BPTR(buf)));
925 @@ -257,14 +294,36 @@
926 * Zero off the host bits in an address, leaving
927 * only the network bits, using the netbits member of
928 * struct mroute_addr as the controlling parameter.
930 + * TODO: this is called for route-lookup for every yet-unhashed
931 + * destination address, so for lots of active net-iroutes, this
932 + * might benefit from some "zeroize 32 bit at a time" improvements
935 mroute_addr_mask_host_bits (struct mroute_addr *ma)
937 in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
938 - ASSERT ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4);
939 - addr &= netbits_to_netmask (ma->netbits);
940 - *(in_addr_t*)ma->addr = htonl (addr);
941 + if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
943 + addr &= netbits_to_netmask (ma->netbits);
944 + *(in_addr_t*)ma->addr = htonl (addr);
946 + else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
948 + int byte = ma->len-1; /* rightmost byte in address */
949 + int bits_to_clear = 128 - ma->netbits;
951 + while( byte >= 0 && bits_to_clear > 0 )
953 + if ( bits_to_clear >= 8 )
954 + { ma->addr[byte--] = 0; bits_to_clear -= 8; }
956 + { ma->addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
958 + ASSERT( bits_to_clear == 0 );
965 @@ -342,17 +401,24 @@
969 - buf_printf (&out, "IPV6");
972 - buf_printf (&out, "UNKNOWN");
975 - return BSTR (&out);
981 + buf_printf (&out, "%s",
982 + print_in6_addr( *(struct in6_addr*)&maddr.addr, 0, gc));
983 + if (maddr.type & MR_WITH_NETBITS)
985 + buf_printf (&out, "/%d", maddr.netbits);
990 + buf_printf (&out, "UNKNOWN");
993 + return BSTR (&out);
1000 * mroute_helper's main job is keeping track of
1001 @@ -422,6 +488,40 @@
1002 mroute_helper_regenerate (mh);
1006 +/* this is a bit inelegant, we really should have a helper to that
1007 + * is only passed the netbits value, and not the whole struct iroute *
1008 + * - thus one helper could do IPv4 and IPv6. For the sake of "not change
1009 + * code unrelated to IPv4" this is left for later cleanup, for now.
1012 +mroute_helper_add_iroute6 (struct mroute_helper *mh,
1013 + const struct iroute_ipv6 *ir6)
1015 + if (ir6->netbits >= 0)
1017 + ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
1018 + ++mh->cache_generation;
1019 + ++mh->net_len_refcount[ir6->netbits];
1020 + if (mh->net_len_refcount[ir6->netbits] == 1)
1021 + mroute_helper_regenerate (mh);
1026 +mroute_helper_del_iroute6 (struct mroute_helper *mh,
1027 + const struct iroute_ipv6 *ir6)
1029 + if (ir6->netbits >= 0)
1031 + ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
1032 + ++mh->cache_generation;
1033 + --mh->net_len_refcount[ir6->netbits];
1034 + ASSERT (mh->net_len_refcount[ir6->netbits] >= 0);
1035 + if (!mh->net_len_refcount[ir6->netbits])
1036 + mroute_helper_regenerate (mh);
1041 mroute_helper_free (struct mroute_helper *mh)
1042 diff -durN openvpn-2.2.2.orig/mroute.c~ openvpn-2.2.2/mroute.c~
1043 --- openvpn-2.2.2.orig/mroute.c~ 1970-01-01 01:00:00.000000000 +0100
1044 +++ openvpn-2.2.2/mroute.c~ 2012-06-01 10:40:28.000000000 +0200
1047 + * OpenVPN -- An application to securely tunnel IP networks
1048 + * over a single TCP/UDP port, with support for SSL/TLS-based
1049 + * session authentication and key exchange,
1050 + * packet encryption, packet authentication, and
1051 + * packet compression.
1053 + * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
1055 + * This program is free software; you can redistribute it and/or modify
1056 + * it under the terms of the GNU General Public License version 2
1057 + * as published by the Free Software Foundation.
1059 + * This program is distributed in the hope that it will be useful,
1060 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1061 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1062 + * GNU General Public License for more details.
1064 + * You should have received a copy of the GNU General Public License
1065 + * along with this program (see the file COPYING included with this
1066 + * distribution); if not, write to the Free Software Foundation, Inc.,
1067 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1070 +#include "syshead.h"
1074 +#include "mroute.h"
1077 +#include "socket.h"
1079 +#include "memdbg.h"
1082 +mroute_addr_init (struct mroute_addr *addr)
1088 + * Ethernet multicast addresses.
1092 +is_mac_mcast_addr (const uint8_t *mac)
1094 + return (bool) mac[0] & 1;
1098 +is_mac_mcast_maddr (const struct mroute_addr *addr)
1100 + return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr);
1104 + * Don't learn certain addresses.
1107 +mroute_learnable_address (const struct mroute_addr *addr)
1110 + bool not_all_zeros = false;
1111 + bool not_all_ones = false;
1113 + for (i = 0; i < addr->len; ++i)
1115 + int b = addr->addr[i];
1117 + not_all_zeros = true;
1119 + not_all_ones = true;
1121 + return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
1125 +mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
1129 + ma->type = MR_ADDR_IPV4 | mask;
1132 + *(in_addr_t*)ma->addr = src;
1137 +mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
1141 + ma->type = MR_ADDR_IPV6 | mask;
1144 + *(struct in6_addr *)ma->addr = src;
1149 +mroute_is_mcast (const in_addr_t addr)
1151 + return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
1154 +/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
1155 + * the address as being a multicast address"
1158 +mroute_is_mcast_ipv6 (const struct in6_addr addr)
1160 + return (addr.s6_addr[0] == 0xff);
1165 +static unsigned int
1166 +mroute_extract_addr_arp (struct mroute_addr *src,
1167 + struct mroute_addr *dest,
1168 + const struct buffer *buf)
1170 + unsigned int ret = 0;
1171 + if (BLEN (buf) >= (int) sizeof (struct openvpn_arp))
1173 + const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf);
1174 + if (arp->mac_addr_type == htons(0x0001)
1175 + && arp->proto_addr_type == htons(0x0800)
1176 + && arp->mac_addr_size == 0x06
1177 + && arp->proto_addr_size == 0x04)
1179 + mroute_get_in_addr_t (src, arp->ip_src, MR_ARP);
1180 + mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP);
1182 + /* multicast packet? */
1183 + if (mroute_is_mcast (arp->ip_dest))
1184 + ret |= MROUTE_EXTRACT_MCAST;
1186 + ret |= MROUTE_EXTRACT_SUCCEEDED;
1195 +mroute_extract_addr_ipv4 (struct mroute_addr *src,
1196 + struct mroute_addr *dest,
1197 + const struct buffer *buf)
1199 + unsigned int ret = 0;
1200 + static bool ipv6warned = false;
1202 + if (BLEN (buf) >= 1)
1204 + switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
1207 + if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
1209 + const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
1211 + mroute_get_in_addr_t (src, ip->saddr, 0);
1212 + mroute_get_in_addr_t (dest, ip->daddr, 0);
1214 + /* multicast packet? */
1215 + if (mroute_is_mcast (ip->daddr))
1216 + ret |= MROUTE_EXTRACT_MCAST;
1218 + /* IGMP message? */
1219 + if (ip->protocol == OPENVPN_IPPROTO_IGMP)
1220 + ret |= MROUTE_EXTRACT_IGMP;
1222 + ret |= MROUTE_EXTRACT_SUCCEEDED;
1227 + if( !ipv6warned ) {
1228 + msg (M_WARN, "IPv6 in tun mode is not supported in OpenVPN 2.2");
1229 + ipv6warned = true;
1239 +mroute_extract_addr_ether (struct mroute_addr *src,
1240 + struct mroute_addr *dest,
1241 + struct mroute_addr *esrc,
1242 + struct mroute_addr *edest,
1243 + const struct buffer *buf)
1245 + unsigned int ret = 0;
1246 + if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
1248 + const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
1251 + src->type = MR_ADDR_ETHER;
1254 + memcpy (src->addr, eth->source, 6);
1258 + dest->type = MR_ADDR_ETHER;
1259 + dest->netbits = 0;
1261 + memcpy (dest->addr, eth->dest, 6);
1263 + /* ethernet broadcast/multicast packet? */
1264 + if (is_mac_mcast_addr (eth->dest))
1265 + ret |= MROUTE_EXTRACT_BCAST;
1268 + ret |= MROUTE_EXTRACT_SUCCEEDED;
1271 + if (esrc || edest)
1273 + struct buffer b = *buf;
1274 + if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
1276 + switch (ntohs (eth->proto))
1278 + case OPENVPN_ETH_P_IPV4:
1279 + ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT);
1281 + case OPENVPN_ETH_P_ARP:
1282 + ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT);
1293 + * Translate a struct openvpn_sockaddr (osaddr)
1294 + * to a struct mroute_addr (addr).
1296 +bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
1297 + const struct openvpn_sockaddr *osaddr,
1300 + if (osaddr->sa.sin_family == AF_INET)
1304 + addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
1305 + addr->netbits = 0;
1307 + memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
1308 + memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2);
1312 + addr->type = MR_ADDR_IPV4;
1313 + addr->netbits = 0;
1315 + memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
1323 + * Zero off the host bits in an address, leaving
1324 + * only the network bits, using the netbits member of
1325 + * struct mroute_addr as the controlling parameter.
1327 + * TODO: this is called for route-lookup for every yet-unhashed
1328 + * destination address, so for lots of active net-iroutes, this
1329 + * might benefit from some "zeroize 32 bit at a time" improvements
1332 +mroute_addr_mask_host_bits (struct mroute_addr *ma)
1334 + in_addr_t addr = ntohl(*(in_addr_t*)ma->addr);
1335 + if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
1337 + addr &= netbits_to_netmask (ma->netbits);
1338 + *(in_addr_t*)ma->addr = htonl (addr);
1340 + else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
1342 + int byte = ma->len-1; /* rightmost byte in address */
1343 + int bits_to_clear = 128 - ma->netbits;
1345 + while( byte >= 0 && bits_to_clear > 0 )
1347 + if ( bits_to_clear >= 8 )
1348 + { ma->addr[byte--] = 0; bits_to_clear -= 8; }
1350 + { ma->addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
1352 + ASSERT( bits_to_clear == 0 );
1359 + * The mroute_addr hash function takes into account the
1360 + * address type, number of bits in the network address,
1361 + * and the actual address.
1364 +mroute_addr_hash_function (const void *key, uint32_t iv)
1366 + return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key),
1367 + mroute_addr_hash_len ((const struct mroute_addr *) key),
1372 +mroute_addr_compare_function (const void *key1, const void *key2)
1374 + return mroute_addr_equal ((const struct mroute_addr *) key1,
1375 + (const struct mroute_addr *) key2);
1379 +mroute_addr_print (const struct mroute_addr *ma,
1380 + struct gc_arena *gc)
1382 + return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
1386 +mroute_addr_print_ex (const struct mroute_addr *ma,
1387 + const unsigned int flags,
1388 + struct gc_arena *gc)
1390 + struct buffer out = alloc_buf_gc (64, gc);
1393 + struct mroute_addr maddr = *ma;
1395 + switch (maddr.type & MR_ADDR_MASK)
1397 + case MR_ADDR_ETHER:
1398 + buf_printf (&out, "%s", format_hex_ex (ma->addr, 6, 0, 1, ":", gc));
1400 + case MR_ADDR_IPV4:
1402 + struct buffer buf;
1406 + buf_set_read (&buf, maddr.addr, maddr.len);
1407 + addr = buf_read_u32 (&buf, &status);
1410 + if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
1411 + buf_printf (&out, "ARP/");
1412 + buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
1413 + if (maddr.type & MR_WITH_NETBITS)
1415 + if (flags & MAPF_SUBNET)
1417 + const in_addr_t netmask = netbits_to_netmask (maddr.netbits);
1418 + buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc));
1421 + buf_printf (&out, "/%d", maddr.netbits);
1424 + if (maddr.type & MR_WITH_PORT)
1426 + port = buf_read_u16 (&buf);
1428 + buf_printf (&out, ":%d", port);
1432 + case MR_ADDR_IPV6:
1434 + buf_printf (&out, "%s",
1435 + print_in6_addr( *(struct in6_addr*)&maddr.addr, 0, gc));
1436 + if (maddr.type & MR_WITH_NETBITS)
1438 + buf_printf (&out, "/%d", maddr.netbits);
1443 + buf_printf (&out, "UNKNOWN");
1446 + return BSTR (&out);
1453 + * mroute_helper's main job is keeping track of
1454 + * currently used CIDR netlengths, so we don't
1455 + * have to cycle through all 33.
1458 +struct mroute_helper *
1459 +mroute_helper_init (int ageable_ttl_secs)
1461 + struct mroute_helper *mh;
1462 + ALLOC_OBJ_CLEAR (mh, struct mroute_helper);
1463 + mh->ageable_ttl_secs = ageable_ttl_secs;
1468 +mroute_helper_regenerate (struct mroute_helper *mh)
1471 + for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
1473 + if (mh->net_len_refcount[i] > 0)
1474 + mh->net_len[j++] = (uint8_t) i;
1476 + mh->n_net_len = j;
1478 +#ifdef ENABLE_DEBUG
1479 + if (check_debug_level (D_MULTI_DEBUG))
1481 + struct gc_arena gc = gc_new ();
1482 + struct buffer out = alloc_buf_gc (256, &gc);
1483 + buf_printf (&out, "MROUTE CIDR netlen:");
1484 + for (i = 0; i < mh->n_net_len; ++i)
1486 + buf_printf (&out, " /%d", mh->net_len[i]);
1488 + dmsg (D_MULTI_DEBUG, "%s", BSTR (&out));
1495 +mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir)
1497 + if (ir->netbits >= 0)
1499 + ASSERT (ir->netbits < MR_HELPER_NET_LEN);
1500 + ++mh->cache_generation;
1501 + ++mh->net_len_refcount[ir->netbits];
1502 + if (mh->net_len_refcount[ir->netbits] == 1)
1503 + mroute_helper_regenerate (mh);
1508 +mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir)
1510 + if (ir->netbits >= 0)
1512 + ASSERT (ir->netbits < MR_HELPER_NET_LEN);
1513 + ++mh->cache_generation;
1514 + --mh->net_len_refcount[ir->netbits];
1515 + ASSERT (mh->net_len_refcount[ir->netbits] >= 0);
1516 + if (!mh->net_len_refcount[ir->netbits])
1517 + mroute_helper_regenerate (mh);
1521 +/* this is a bit inelegant, we really should have a helper to that
1522 + * is only passed the netbits value, and not the whole struct iroute *
1523 + * - thus one helper could do IPv4 and IPv6. For the sake of "not change
1524 + * code unrelated to IPv4" this is left for later cleanup, for now.
1527 +mroute_helper_add_iroute6 (struct mroute_helper *mh,
1528 + const struct iroute_ipv6 *ir6)
1530 + if (ir6->netbits >= 0)
1532 + ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
1533 + ++mh->cache_generation;
1534 + ++mh->net_len_refcount[ir6->netbits];
1535 + if (mh->net_len_refcount[ir6->netbits] == 1)
1536 + mroute_helper_regenerate (mh);
1541 +mroute_helper_del_iroute6 (struct mroute_helper *mh,
1542 + const struct iroute_ipv6 *ir6)
1544 + if (ir6->netbits >= 0)
1546 + ASSERT (ir6->netbits < MR_HELPER_NET_LEN);
1547 + ++mh->cache_generation;
1548 + --mh->net_len_refcount[ir6->netbits];
1549 + ASSERT (mh->net_len_refcount[ir6->netbits] >= 0);
1550 + if (!mh->net_len_refcount[ir6->netbits])
1551 + mroute_helper_regenerate (mh);
1556 +mroute_helper_free (struct mroute_helper *mh)
1562 +static void dummy(void) {}
1563 +#endif /* P2MP_SERVER */
1564 diff -durN openvpn-2.2.2.orig/mroute.h openvpn-2.2.2/mroute.h
1565 --- openvpn-2.2.2.orig/mroute.h 2011-12-13 17:58:56.000000000 +0100
1566 +++ openvpn-2.2.2/mroute.h 2012-06-01 10:40:28.000000000 +0200
1569 * Number of bits in an address. Should be raised for IPv6.
1571 -#define MR_HELPER_NET_LEN 32
1572 +#define MR_HELPER_NET_LEN 129
1575 * Used to help maintain CIDR routing table.
1577 void mroute_helper_free (struct mroute_helper *mh);
1578 void mroute_helper_add_iroute (struct mroute_helper *mh, const struct iroute *ir);
1579 void mroute_helper_del_iroute (struct mroute_helper *mh, const struct iroute *ir);
1580 +void mroute_helper_add_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
1581 +void mroute_helper_del_iroute6 (struct mroute_helper *mh, const struct iroute_ipv6 *ir6);
1584 * Given a raw packet in buf, return the src and dest
1585 diff -durN openvpn-2.2.2.orig/multi.c openvpn-2.2.2/multi.c
1586 --- openvpn-2.2.2.orig/multi.c 2011-12-13 17:58:56.000000000 +0100
1587 +++ openvpn-2.2.2/multi.c 2012-06-01 10:40:28.000000000 +0200
1588 @@ -316,25 +316,18 @@
1590 if (t->options.ifconfig_pool_defined)
1592 - if (dev == DEV_TYPE_TAP)
1594 - m->ifconfig_pool = ifconfig_pool_init (IFCONFIG_POOL_INDIV,
1595 - t->options.ifconfig_pool_start,
1596 - t->options.ifconfig_pool_end,
1597 - t->options.duplicate_cn);
1599 - else if (dev == DEV_TYPE_TUN)
1601 - m->ifconfig_pool = ifconfig_pool_init (
1602 - (t->options.topology == TOP_NET30) ? IFCONFIG_POOL_30NET : IFCONFIG_POOL_INDIV,
1603 - t->options.ifconfig_pool_start,
1604 - t->options.ifconfig_pool_end,
1605 - t->options.duplicate_cn);
1611 + int pool_type = IFCONFIG_POOL_INDIV;
1613 + if ( dev == DEV_TYPE_TUN && t->options.topology == TOP_NET30 )
1614 + pool_type = IFCONFIG_POOL_30NET;
1616 + m->ifconfig_pool = ifconfig_pool_init (pool_type,
1617 + t->options.ifconfig_pool_start,
1618 + t->options.ifconfig_pool_end,
1619 + t->options.duplicate_cn,
1620 + t->options.ifconfig_ipv6_pool_defined,
1621 + t->options.ifconfig_ipv6_pool_base,
1622 + t->options.ifconfig_ipv6_pool_netbits );
1624 /* reload pool data from file */
1625 if (t->c1.ifconfig_pool_persist)
1626 @@ -429,10 +422,14 @@
1627 struct multi_instance *mi)
1629 const struct iroute *ir;
1630 + const struct iroute_ipv6 *ir6;
1631 if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)
1633 for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)
1634 mroute_helper_del_iroute (m->route_helper, ir);
1636 + for ( ir6 = mi->context.options.iroutes_ipv6; ir6 != NULL; ir6 = ir6->next )
1637 + mroute_helper_del_iroute6 (m->route_helper, ir6);
1641 @@ -1078,6 +1075,37 @@
1645 +static struct multi_instance *
1646 +multi_learn_in6_addr (struct multi_context *m,
1647 + struct multi_instance *mi,
1648 + struct in6_addr a6,
1649 + int netbits, /* -1 if host route, otherwise # of network bits in address */
1652 + struct mroute_addr addr;
1655 + addr.type = MR_ADDR_IPV6;
1657 + memcpy( &addr.addr, &a6, sizeof(a6) );
1661 + addr.type |= MR_WITH_NETBITS;
1662 + addr.netbits = (uint8_t) netbits;
1663 + mroute_addr_mask_host_bits( &addr );
1667 + struct multi_instance *owner = multi_learn_addr (m, mi, &addr, 0);
1668 +#ifdef MANAGEMENT_DEF_AUTH
1669 + if (management && owner)
1670 + management_learn_addr (management, &mi->context.c2.mda_context, &addr, primary);
1677 * A new client has connected, add routes (server -> client)
1678 * to internal routing table.
1679 @@ -1088,6 +1116,7 @@
1681 struct gc_arena gc = gc_new ();
1682 const struct iroute *ir;
1683 + const struct iroute_ipv6 *ir6;
1684 if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)
1686 mi->did_iroutes = true;
1687 @@ -1107,6 +1136,22 @@
1689 multi_learn_in_addr_t (m, mi, ir->network, ir->netbits, false);
1691 + for ( ir6 = mi->context.options.iroutes_ipv6; ir6 != NULL; ir6 = ir6->next )
1693 + if (ir6->netbits >= 0)
1694 + msg (D_MULTI_LOW, "MULTI: internal route %s/%d -> %s",
1695 + print_in6_addr (ir6->network, 0, &gc),
1697 + multi_instance_string (mi, false, &gc));
1699 + msg (D_MULTI_LOW, "MULTI: internal route %s -> %s",
1700 + print_in6_addr (ir6->network, 0, &gc),
1701 + multi_instance_string (mi, false, &gc));
1703 + mroute_helper_add_iroute6 (m->route_helper, ir6);
1705 + multi_learn_in6_addr (m, mi, ir6->network, ir6->netbits, false);
1710 @@ -1192,21 +1237,37 @@
1711 mi->context.c2.push_ifconfig_defined = true;
1712 mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;
1713 mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;
1715 + /* the current implementation does not allow "static IPv4, pool IPv6",
1716 + * (see below) so issue a warning if that happens - don't break the
1717 + * session, though, as we don't even know if this client WANTS IPv6
1719 + if ( mi->context.c1.tuntap->ipv6 &&
1720 + mi->context.options.ifconfig_ipv6_pool_defined &&
1721 + ! mi->context.options.push_ifconfig_ipv6_defined )
1723 + msg( M_INFO, "MULTI_sva: WARNING: if --ifconfig-push is used for IPv4, automatic IPv6 assignment from --ifconfig-ipv6-pool does not work. Use --ifconfig-ipv6-push for IPv6 then." );
1726 else if (m->ifconfig_pool && mi->vaddr_handle < 0) /* otherwise, choose a pool address */
1728 in_addr_t local=0, remote=0;
1729 + struct in6_addr remote_ipv6;
1730 const char *cn = NULL;
1732 if (!mi->context.options.duplicate_cn)
1733 cn = tls_common_name (mi->context.c2.tls_multi, true);
1735 - mi->vaddr_handle = ifconfig_pool_acquire (m->ifconfig_pool, &local, &remote, cn);
1736 + mi->vaddr_handle = ifconfig_pool_acquire (m->ifconfig_pool, &local, &remote, &remote_ipv6, cn);
1737 if (mi->vaddr_handle >= 0)
1739 const int tunnel_type = TUNNEL_TYPE (mi->context.c1.tuntap);
1740 const int tunnel_topology = TUNNEL_TOPOLOGY (mi->context.c1.tuntap);
1742 + msg( M_INFO, "MULTI_sva: pool returned IPv4=%s, IPv6=%s",
1743 + print_in_addr_t( remote, 0, &gc ),
1744 + print_in6_addr( remote_ipv6, 0, &gc ) );
1746 /* set push_ifconfig_remote_netmask from pool ifconfig address(es) */
1747 mi->context.c2.push_ifconfig_local = remote;
1748 if (tunnel_type == DEV_TYPE_TAP || (tunnel_type == DEV_TYPE_TUN && tunnel_topology == TOP_SUBNET))
1749 @@ -1228,12 +1289,46 @@
1751 msg (D_MULTI_ERRORS, "MULTI: no --ifconfig-pool netmask parameter is available to push to %s",
1752 multi_instance_string (mi, false, &gc));
1754 + if ( mi->context.options.ifconfig_ipv6_pool_defined )
1756 + mi->context.c2.push_ifconfig_ipv6_local = remote_ipv6;
1757 + mi->context.c2.push_ifconfig_ipv6_remote =
1758 + mi->context.c1.tuntap->local_ipv6;
1759 + mi->context.c2.push_ifconfig_ipv6_netbits =
1760 + mi->context.options.ifconfig_ipv6_pool_netbits;
1761 + mi->context.c2.push_ifconfig_ipv6_defined = true;
1766 msg (D_MULTI_ERRORS, "MULTI: no free --ifconfig-pool addresses are available");
1770 + /* IPv6 push_ifconfig is a bit problematic - since IPv6 shares the
1771 + * pool handling with IPv4, the combination "static IPv4, dynamic IPv6"
1772 + * will fail (because no pool will be allocated in this case).
1773 + * OTOH, this doesn't make too much sense in reality - and the other
1774 + * way round ("dynamic IPv4, static IPv6") or "both static" makes sense
1775 + * -> and so it's implemented right now
1777 + if ( mi->context.c1.tuntap->ipv6 &&
1778 + mi->context.options.push_ifconfig_ipv6_defined )
1780 + mi->context.c2.push_ifconfig_ipv6_local =
1781 + mi->context.options.push_ifconfig_ipv6_local;
1782 + mi->context.c2.push_ifconfig_ipv6_remote =
1783 + mi->context.options.push_ifconfig_ipv6_remote;
1784 + mi->context.c2.push_ifconfig_ipv6_netbits =
1785 + mi->context.options.push_ifconfig_ipv6_netbits;
1786 + mi->context.c2.push_ifconfig_ipv6_defined = true;
1788 + msg( M_INFO, "MULTI_sva: push_ifconfig_ipv6 %s/%d",
1789 + print_in6_addr( mi->context.c2.push_ifconfig_ipv6_local, 0, &gc ),
1790 + mi->context.c2.push_ifconfig_ipv6_netbits );
1796 @@ -1272,6 +1367,11 @@
1801 + /* TODO: I'm not exactly sure what these environment variables are
1802 + * used for, but if we have them for IPv4, we should also have
1803 + * them for IPv6, no?
1808 @@ -1661,6 +1761,15 @@
1809 print_in_addr_t (mi->context.c2.push_ifconfig_local, 0, &gc));
1812 + if (mi->context.c2.push_ifconfig_ipv6_defined)
1814 + multi_learn_in6_addr (m, mi, mi->context.c2.push_ifconfig_ipv6_local, -1, true);
1815 + /* TODO: find out where addresses are "unlearned"!! */
1816 + msg (D_MULTI_LOW, "MULTI: primary virtual IPv6 for %s: %s",
1817 + multi_instance_string (mi, false, &gc),
1818 + print_in6_addr (mi->context.c2.push_ifconfig_ipv6_local, 0, &gc));
1821 /* add routes locally, pointing to new client, if
1822 --iroute options have been specified */
1823 multi_add_iroutes (m, mi);
1824 diff -durN openvpn-2.2.2.orig/openvpn.8 openvpn-2.2.2/openvpn.8
1825 --- openvpn-2.2.2.orig/openvpn.8 2011-12-13 17:58:56.000000000 +0100
1826 +++ openvpn-2.2.2/openvpn.8 2012-06-01 10:40:28.000000000 +0200
1829 A warning will be displayed
1830 if no specific IPv6 TUN support for your OS has been compiled into OpenVPN.
1832 +See below for further IPv6-related configuration options.
1833 .\"*********************************************************
1835 .B \-\-dev-node node
1836 @@ -4949,6 +4951,57 @@
1838 option can be used BEFORE this option to produce debugging information.
1839 .\"*********************************************************
1840 +.SS IPv6 Related Options
1841 +.\"*********************************************************
1842 +The following options exist to support IPv6 tunneling in peer-to-peer
1843 +and client-server mode. As of now, this is just very basic
1844 +documentation of the IPv6-related options. More documentation can be
1845 +found on http://www.greenie.net/ipv6/openvpn.html.
1847 +.B --ifconfig-ipv6 ipv6addr/bits ipv6remote
1848 +configure IPv6 address
1850 +on the ``tun'' device. The second parameter is used as route target for
1852 +if no gateway is specified.
1854 +.B --route-ipv6 ipv6addr/bits [gateway] [metric]
1855 +setup IPv6 routing in the system to send the specified IPv6 network
1856 +into OpenVPN's ``tun'' device
1858 +.B --server-ipv6 ipv6addr/bits
1859 +convenience-function to enable a number of IPv6 related options at
1861 +.B --ifconfig-ipv6, --ifconfig-ipv6-pool, --tun-ipv6
1864 +Is only accepted if ``--mode server'' or ``--server'' is set.
1866 +.B --ifconfig-ipv6-pool ipv6addr/bits
1867 +Specify an IPv6 address pool for dynamic assignment to clients. The
1870 +and increments by +1 for every new client (linear mode). The
1872 +setting controls the size of the pool.
1874 +.B --ifconfig-ipv6-push ipv6addr/bits ipv6remote
1875 +for ccd/ per-client static IPv6 interface configuration, see
1876 +.B --client-config-dir
1881 +.B --iroute-ipv6 ipv6addr/bits
1882 +for ccd/ per-client static IPv6 route configuration, see
1884 +for more details how to setup and use this, and how
1890 +.\"*********************************************************
1891 .SH SCRIPTING AND ENVIRONMENTAL VARIABLES
1892 OpenVPN exports a series
1893 of environmental variables for use by user-defined scripts.
1894 diff -durN openvpn-2.2.2.orig/openvpn.h openvpn-2.2.2/openvpn.h
1895 --- openvpn-2.2.2.orig/openvpn.h 2011-12-13 17:58:56.000000000 +0100
1896 +++ openvpn-2.2.2/openvpn.h 2012-06-01 10:40:28.000000000 +0200
1898 /* list of --route directives */
1899 struct route_list *route_list;
1901 + /* list of --route-ipv6 directives */
1902 + struct route_ipv6_list *route_ipv6_list;
1905 struct status_output *status_output;
1906 bool status_output_owned;
1907 @@ -417,6 +420,11 @@
1908 in_addr_t push_ifconfig_local;
1909 in_addr_t push_ifconfig_remote_netmask;
1911 + bool push_ifconfig_ipv6_defined;
1912 + struct in6_addr push_ifconfig_ipv6_local;
1913 + int push_ifconfig_ipv6_netbits;
1914 + struct in6_addr push_ifconfig_ipv6_remote;
1916 /* client authentication state, CAS_SUCCEEDED must be 0 */
1917 # define CAS_SUCCEEDED 0
1918 # define CAS_PENDING 1
1919 diff -durN openvpn-2.2.2.orig/options.c openvpn-2.2.2/options.c
1920 --- openvpn-2.2.2.orig/options.c 2011-12-13 17:58:56.000000000 +0100
1921 +++ openvpn-2.2.2/options.c 2012-06-01 10:40:28.000000000 +0200
1923 #ifdef ENABLE_EUREPHIA
1926 + " [IPv6 payload 20110522-1 (2.2.0)]"
1927 " built on " __DATE__
1931 " addresses outside of the subnets used by either peer.\n"
1932 " TAP: configure device to use IP address l as a local\n"
1933 " endpoint and rn as a subnet mask.\n"
1934 + "--ifconfig-ipv6 l r : configure device to use IPv6 address l as local\n"
1935 + " endpoint (as a /64) and r as remote endpoint\n"
1936 "--ifconfig-noexec : Don't actually execute ifconfig/netsh command, instead\n"
1937 " pass --ifconfig parms by environment to scripts.\n"
1938 "--ifconfig-nowarn : Don't warn if the --ifconfig option on this side of the\n"
1939 @@ -182,6 +185,10 @@
1940 " netmask default: 255.255.255.255\n"
1941 " gateway default: taken from --route-gateway or --ifconfig\n"
1942 " Specify default by leaving blank or setting to \"nil\".\n"
1943 + "--route-ipv6 network/bits [gateway] [metric] :\n"
1944 + " Add IPv6 route to routing table after connection\n"
1945 + " is established. Multiple routes can be specified.\n"
1946 + " gateway default: taken from --route-ipv6-gateway or --ifconfig\n"
1947 "--max-routes n : Specify the maximum number of routes that may be defined\n"
1948 " or pulled from a server.\n"
1949 "--route-gateway gw|'dhcp' : Specify a default gateway for use with --route.\n"
1952 "Multi-Client Server options (when --mode server is used):\n"
1953 "--server network netmask : Helper option to easily configure server mode.\n"
1954 + "--server-ipv6 network/bits : Configure IPv6 server mode.\n"
1955 "--server-bridge [IP netmask pool-start-IP pool-end-IP] : Helper option to\n"
1956 " easily configure ethernet bridging server mode.\n"
1957 "--push \"option\" : Push a config file option back to the peer for remote\n"
1958 @@ -383,10 +391,16 @@
1959 "--ifconfig-pool-persist file [seconds] : Persist/unpersist ifconfig-pool\n"
1960 " data to file, at seconds intervals (default=600).\n"
1961 " If seconds=0, file will be treated as read-only.\n"
1962 + "--ifconfig-ipv6-pool base-IP/bits : set aside an IPv6 network block\n"
1963 + " to be dynamically allocated to connecting clients.\n"
1964 "--ifconfig-push local remote-netmask : Push an ifconfig option to remote,\n"
1965 " overrides --ifconfig-pool dynamic allocation.\n"
1966 " Only valid in a client-specific config file.\n"
1967 + "--ifconfig-ipv6-push local/bits remote : Push an ifconfig-ipv6 option to\n"
1968 + " remote, overrides --ifconfig-ipv6-pool allocation.\n"
1969 + " Only valid in a client-specific config file.\n"
1970 "--iroute network [netmask] : Route subnet to client.\n"
1971 + "--iroute-ipv6 network/bits : Route IPv6 subnet to client.\n"
1972 " Sets up internal routes only.\n"
1973 " Only valid in a client-specific config file.\n"
1974 "--disable : Client is disabled.\n"
1975 @@ -871,6 +885,78 @@
1979 +/* helper: parse a text string containing an IPv6 address + netbits
1980 + * in "standard format" (2001:dba::/32)
1981 + * "/nn" is optional, default to /64 if missing
1983 + * return true if parsing succeeded, modify *network and *netbits
1984 + * return address part without "/nn" in *printable_ipv6 (if != NULL)
1987 +get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
1988 + unsigned int * netbits, char ** printable_ipv6, int msglevel )
1991 + char * sep, * endp;
1993 + struct in6_addr t_network;
1995 + sep = strchr( prefix_str, '/' );
1996 + if ( sep == NULL )
2002 + bits = strtol( sep+1, &endp, 10 );
2003 + if ( *endp != '\0' || bits < 0 || bits > 128 )
2005 + msg (msglevel, "IPv6 prefix '%s': invalid '/bits' spec", prefix_str);
2010 + /* temporary replace '/' in caller-provided string with '\0', otherwise
2011 + * inet_pton() will refuse prefix string
2012 + * (alternative would be to strncpy() the prefix to temporary buffer)
2015 + if ( sep != NULL ) *sep = '\0';
2017 + rc = inet_pton( AF_INET6, prefix_str, &t_network );
2019 + if ( rc == 1 && printable_ipv6 != NULL )
2021 + *printable_ipv6 = string_alloc( prefix_str, NULL );
2024 + if ( sep != NULL ) *sep = '/';
2028 + msg (msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str);
2032 + if ( netbits != NULL )
2036 + if ( network != NULL )
2038 + *network = t_network;
2040 + return true; /* parsing OK, values set */
2043 +static bool ipv6_addr_safe_hexplusbits( const char * ipv6_prefix_spec )
2045 + struct in6_addr t_addr;
2046 + unsigned int t_bits;
2048 + return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, NULL, M_WARN );
2052 string_substitute (const char *src, int from, int to, struct gc_arena *gc)
2054 @@ -989,6 +1075,8 @@
2056 msg (D_SHOW_PARMS, " server_network = %s", print_in_addr_t (o->server_network, 0, &gc));
2057 msg (D_SHOW_PARMS, " server_netmask = %s", print_in_addr_t (o->server_netmask, 0, &gc));
2058 + msg (D_SHOW_PARMS, " server_network_ipv6 = %s", print_in6_addr (o->server_network_ipv6, 0, &gc) );
2059 + SHOW_INT (server_netbits_ipv6);
2060 msg (D_SHOW_PARMS, " server_bridge_ip = %s", print_in_addr_t (o->server_bridge_ip, 0, &gc));
2061 msg (D_SHOW_PARMS, " server_bridge_netmask = %s", print_in_addr_t (o->server_bridge_netmask, 0, &gc));
2062 msg (D_SHOW_PARMS, " server_bridge_pool_start = %s", print_in_addr_t (o->server_bridge_pool_start, 0, &gc));
2063 @@ -1009,6 +1097,9 @@
2064 msg (D_SHOW_PARMS, " ifconfig_pool_netmask = %s", print_in_addr_t (o->ifconfig_pool_netmask, 0, &gc));
2065 SHOW_STR (ifconfig_pool_persist_filename);
2066 SHOW_INT (ifconfig_pool_persist_refresh_freq);
2067 + SHOW_BOOL (ifconfig_ipv6_pool_defined);
2068 + msg (D_SHOW_PARMS, " ifconfig_ipv6_pool_base = %s", print_in6_addr (o->ifconfig_ipv6_pool_base, 0, &gc));
2069 + SHOW_INT (ifconfig_ipv6_pool_netbits);
2070 SHOW_INT (n_bcast_buf);
2071 SHOW_INT (tcp_queue_limit);
2072 SHOW_INT (real_hash_size);
2073 @@ -1022,6 +1113,9 @@
2074 SHOW_BOOL (push_ifconfig_defined);
2075 msg (D_SHOW_PARMS, " push_ifconfig_local = %s", print_in_addr_t (o->push_ifconfig_local, 0, &gc));
2076 msg (D_SHOW_PARMS, " push_ifconfig_remote_netmask = %s", print_in_addr_t (o->push_ifconfig_remote_netmask, 0, &gc));
2077 + SHOW_BOOL (push_ifconfig_ipv6_defined);
2078 + msg (D_SHOW_PARMS, " push_ifconfig_ipv6_local = %s/%d", print_in6_addr (o->push_ifconfig_ipv6_local, 0, &gc), o->push_ifconfig_ipv6_netbits );
2079 + msg (D_SHOW_PARMS, " push_ifconfig_ipv6_remote = %s", print_in6_addr (o->push_ifconfig_ipv6_remote, 0, &gc));
2080 SHOW_BOOL (enable_c2c);
2081 SHOW_BOOL (duplicate_cn);
2083 @@ -1076,6 +1170,25 @@
2088 +option_iroute_ipv6 (struct options *o,
2089 + const char *prefix_str,
2092 + struct iroute_ipv6 *ir;
2094 + ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc);
2096 + if ( get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel ) < 0 )
2098 + msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification",
2103 + ir->next = o->iroutes_ipv6;
2104 + o->iroutes_ipv6 = ir;
2106 #endif /* P2MP_SERVER */
2109 @@ -1113,6 +1226,13 @@
2110 options->routes = new_route_option_list (options->max_routes, &options->gc);
2114 +rol6_check_alloc (struct options *options)
2116 + if (!options->routes_ipv6)
2117 + options->routes_ipv6 = new_route_ipv6_option_list (options->max_routes, &options->gc);
2122 show_connection_entry (const struct connection_entry *o)
2123 @@ -1203,6 +1323,9 @@
2124 SHOW_STR (ifconfig_remote_netmask);
2125 SHOW_BOOL (ifconfig_noexec);
2126 SHOW_BOOL (ifconfig_nowarn);
2127 + SHOW_STR (ifconfig_ipv6_local);
2128 + SHOW_INT (ifconfig_ipv6_netbits);
2129 + SHOW_STR (ifconfig_ipv6_remote);
2131 #ifdef HAVE_GETTIMEOFDAY
2133 @@ -1863,8 +1986,10 @@
2134 if (options->connection_list)
2135 msg (M_USAGE, "<connection> cannot be used with --mode server");
2138 if (options->tun_ipv6)
2139 msg (M_USAGE, "--tun-ipv6 cannot be used with --mode server");
2141 if (options->shaper)
2142 msg (M_USAGE, "--shaper cannot be used with --mode server");
2144 @@ -1889,6 +2014,11 @@
2145 msg (M_USAGE, "--up-delay cannot be used with --mode server");
2146 if (!options->ifconfig_pool_defined && options->ifconfig_pool_persist_filename)
2147 msg (M_USAGE, "--ifconfig-pool-persist must be used with --ifconfig-pool");
2148 + if (options->ifconfig_ipv6_pool_defined && !options->ifconfig_ipv6_local )
2149 + msg (M_USAGE, "--ifconfig-ipv6-pool needs --ifconfig-ipv6");
2150 + if (options->ifconfig_ipv6_local && !options->tun_ipv6 )
2151 + msg (M_INFO, "Warning: --ifconfig-ipv6 without --tun-ipv6 will not do IPv6");
2153 if (options->auth_user_pass_file)
2154 msg (M_USAGE, "--auth-user-pass cannot be used with --mode server (it should be used on the client side only)");
2155 if (options->ccd_exclusive && !options->client_config_dir)
2156 @@ -1920,6 +2050,8 @@
2158 if (options->ifconfig_pool_defined || options->ifconfig_pool_persist_filename)
2159 msg (M_USAGE, "--ifconfig-pool/--ifconfig-pool-persist requires --mode server");
2160 + if (options->ifconfig_ipv6_pool_defined)
2161 + msg (M_USAGE, "--ifconfig-ipv6-pool requires --mode server");
2162 if (options->real_hash_size != defaults.real_hash_size
2163 || options->virtual_hash_size != defaults.virtual_hash_size)
2164 msg (M_USAGE, "--hash-size requires --mode server");
2165 @@ -2461,6 +2593,8 @@
2168 o->ifconfig_remote_netmask,
2169 + o->ifconfig_ipv6_local,
2170 + o->ifconfig_ipv6_remote,
2174 @@ -3786,6 +3920,30 @@
2178 + else if (streq (p[0], "ifconfig-ipv6") && p[1] && p[2] )
2180 + unsigned int netbits;
2181 + char * ipv6_local;
2183 + VERIFY_PERMISSION (OPT_P_UP);
2184 + if ( get_ipv6_addr( p[1], NULL, &netbits, &ipv6_local, msglevel ) &&
2185 + ipv6_addr_safe( p[2] ) )
2187 + if ( netbits < 64 || netbits > 124 )
2189 + msg( msglevel, "ifconfig-ipv6: /netbits must be between 64 and 124, not '/%d'", netbits );
2192 + options->ifconfig_ipv6_local = ipv6_local;
2193 + options->ifconfig_ipv6_netbits = netbits;
2194 + options->ifconfig_ipv6_remote = p[2];
2198 + msg (msglevel, "ifconfig-ipv6 parms '%s' and '%s' must be valid addresses", p[1], p[2]);
2202 else if (streq (p[0], "ifconfig-noexec"))
2204 VERIFY_PERMISSION (OPT_P_UP);
2205 @@ -4586,6 +4744,26 @@
2207 add_route_to_option_list (options->routes, p[1], p[2], p[3], p[4]);
2209 + else if (streq (p[0], "route-ipv6") && p[1])
2211 + VERIFY_PERMISSION (OPT_P_ROUTE);
2212 + rol6_check_alloc (options);
2215 + if (!ipv6_addr_safe_hexplusbits (p[1]))
2217 + msg (msglevel, "route-ipv6 parameter network/IP '%s' must be a valid address", p[1]);
2220 + if (p[2] && !ipv6_addr_safe (p[2]))
2222 + msg (msglevel, "route-ipv6 parameter gateway '%s' must be a valid address", p[2]);
2225 + /* p[3] is metric, if present */
2227 + add_route_ipv6_to_option_list (options->routes_ipv6, p[1], p[2], p[3]);
2229 else if (streq (p[0], "max-routes") && p[1])
2232 @@ -4797,6 +4975,33 @@
2236 + else if (streq (p[0], "server-ipv6") && p[1] )
2238 + const int lev = M_WARN;
2239 + struct in6_addr network;
2240 + unsigned int netbits = 0;
2242 + VERIFY_PERMISSION (OPT_P_GENERAL);
2243 + if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev) )
2245 + msg (msglevel, "error parsing --server-ipv6 parameter");
2248 + if ( netbits != 64 )
2250 + msg( msglevel, "--server-ipv6 settings: only /64 supported right now (not /%d)", netbits );
2253 + options->server_ipv6_defined = true;
2254 + options->server_network_ipv6 = network;
2255 + options->server_netbits_ipv6 = netbits;
2257 + if (p[2]) /* no "nopool" options or similar for IPv6 */
2259 + msg (msglevel, "error parsing --server-ipv6: %s is not a recognized flag", p[3]);
2263 else if (streq (p[0], "server-bridge") && p[1] && p[2] && p[3] && p[4])
2265 const int lev = M_WARN;
2266 @@ -4881,6 +5086,28 @@
2267 VERIFY_PERMISSION (OPT_P_GENERAL);
2268 options->topology = TOP_P2P;
2270 + else if (streq (p[0], "ifconfig-ipv6-pool") && p[1] )
2272 + const int lev = M_WARN;
2273 + struct in6_addr network;
2274 + unsigned int netbits = 0;
2276 + VERIFY_PERMISSION (OPT_P_GENERAL);
2277 + if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev ) )
2279 + msg (msglevel, "error parsing --ifconfig-ipv6-pool parameters");
2282 + if ( netbits != 64 )
2284 + msg( msglevel, "--ifconfig-ipv6-pool settings: only /64 supported right now (not /%d)", netbits );
2288 + options->ifconfig_ipv6_pool_defined = true;
2289 + options->ifconfig_ipv6_pool_base = network;
2290 + options->ifconfig_ipv6_pool_netbits = netbits;
2292 else if (streq (p[0], "hash-size") && p[1] && p[2])
2295 @@ -5076,6 +5303,11 @@
2297 option_iroute (options, p[1], netmask, msglevel);
2299 + else if (streq (p[0], "iroute-ipv6") && p[1])
2301 + VERIFY_PERMISSION (OPT_P_INSTANCE);
2302 + option_iroute_ipv6 (options, p[1], msglevel);
2304 else if (streq (p[0], "ifconfig-push") && p[1] && p[2])
2306 in_addr_t local, remote_netmask;
2307 @@ -5114,6 +5346,43 @@
2311 + else if (streq (p[0], "ifconfig-ipv6-push") && p[1] )
2313 + struct in6_addr local, remote;
2314 + unsigned int netbits;
2316 + VERIFY_PERMISSION (OPT_P_INSTANCE);
2318 + if ( ! get_ipv6_addr( p[1], &local, &netbits, NULL, msglevel ) )
2320 + msg (msglevel, "cannot parse --ifconfig-ipv6-push addresses");
2326 + if ( !get_ipv6_addr( p[2], &remote, NULL, NULL, msglevel ) )
2328 + msg( msglevel, "cannot parse --ifconfig-ipv6-push addresses");
2334 + if ( ! options->ifconfig_ipv6_local ||
2335 + ! get_ipv6_addr( options->ifconfig_ipv6_local, &remote,
2336 + NULL, NULL, msglevel ) )
2338 + msg( msglevel, "second argument to --ifconfig-ipv6-push missing and no global --ifconfig-ipv6 address set");
2343 + options->push_ifconfig_ipv6_defined = true;
2344 + options->push_ifconfig_ipv6_local = local;
2345 + options->push_ifconfig_ipv6_netbits = netbits;
2346 + options->push_ifconfig_ipv6_remote = remote;
2348 else if (streq (p[0], "disable"))
2350 VERIFY_PERMISSION (OPT_P_INSTANCE);
2351 diff -durN openvpn-2.2.2.orig/options.h openvpn-2.2.2/options.h
2352 --- openvpn-2.2.2.orig/options.h 2011-12-13 17:58:56.000000000 +0100
2353 +++ openvpn-2.2.2/options.h 2012-06-01 10:44:37.000000000 +0200
2355 int topology; /* one of the TOP_x values from proto.h */
2356 const char *ifconfig_local;
2357 const char *ifconfig_remote_netmask;
2358 + const char *ifconfig_ipv6_local;
2359 + int ifconfig_ipv6_netbits;
2360 + const char *ifconfig_ipv6_remote;
2361 bool ifconfig_noexec;
2362 bool ifconfig_nowarn;
2363 #ifdef HAVE_GETTIMEOFDAY
2365 bool route_delay_defined;
2367 struct route_option_list *routes;
2368 + struct route_ipv6_option_list *routes_ipv6; /* IPv6 */
2370 bool route_gateway_via_dhcp;
2371 bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
2373 bool server_defined;
2374 in_addr_t server_network;
2375 in_addr_t server_netmask;
2376 + bool server_ipv6_defined; /* IPv6 */
2377 + struct in6_addr server_network_ipv6; /* IPv6 */
2378 + unsigned int server_netbits_ipv6; /* IPv6 */
2380 # define SF_NOPOOL (1<<0)
2381 # define SF_TCP_NODELAY_HELPER (1<<1)
2382 @@ -384,6 +391,11 @@
2383 in_addr_t ifconfig_pool_netmask;
2384 const char *ifconfig_pool_persist_filename;
2385 int ifconfig_pool_persist_refresh_freq;
2387 + bool ifconfig_ipv6_pool_defined; /* IPv6 */
2388 + struct in6_addr ifconfig_ipv6_pool_base; /* IPv6 */
2389 + int ifconfig_ipv6_pool_netbits; /* IPv6 */
2392 int virtual_hash_size;
2393 const char *client_connect_script;
2394 @@ -395,12 +407,17 @@
2396 int tcp_queue_limit;
2397 struct iroute *iroutes;
2398 + struct iroute_ipv6 *iroutes_ipv6; /* IPv6 */
2399 bool push_ifconfig_defined;
2400 in_addr_t push_ifconfig_local;
2401 in_addr_t push_ifconfig_remote_netmask;
2402 bool push_ifconfig_constraint_defined;
2403 in_addr_t push_ifconfig_constraint_network;
2404 in_addr_t push_ifconfig_constraint_netmask;
2405 + bool push_ifconfig_ipv6_defined; /* IPv6 */
2406 + struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */
2407 + int push_ifconfig_ipv6_netbits; /* IPv6 */
2408 + struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */
2412 @@ -723,6 +740,10 @@
2413 unsigned int *option_types_found,
2414 struct env_set *es);
2416 +bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
2417 + unsigned int * netbits, char ** printable_ipv6,
2423 diff -durN openvpn-2.2.2.orig/options.h~ openvpn-2.2.2/options.h~
2424 --- openvpn-2.2.2.orig/options.h~ 1970-01-01 01:00:00.000000000 +0100
2425 +++ openvpn-2.2.2/options.h~ 2012-06-01 10:44:29.000000000 +0200
2428 + * OpenVPN -- An application to securely tunnel IP networks
2429 + * over a single UDP port, with support for SSL/TLS-based
2430 + * session authentication and key exchange,
2431 + * packet encryption, packet authentication, and
2432 + * packet compression.
2434 + * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
2436 + * This program is free software; you can redistribute it and/or modify
2437 + * it under the terms of the GNU General Public License version 2
2438 + * as published by the Free Software Foundation.
2440 + * This program is distributed in the hope that it will be useful,
2441 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2442 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2443 + * GNU General Public License for more details.
2445 + * You should have received a copy of the GNU General Public License
2446 + * along with this program (see the file COPYING included with this
2447 + * distribution); if not, write to the Free Software Foundation, Inc.,
2448 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2452 + * 2004-01-28: Added Socks5 proxy support
2453 + * (Christof Meerwald, http://cmeerw.org)
2460 +#include "common.h"
2464 +#include "socket.h"
2465 +#include "plugin.h"
2466 +#include "manage.h"
2469 +#include "pushlist.h"
2472 + * Maximum number of parameters associated with an option,
2473 + * including the option name itself.
2475 +#define MAX_PARMS 16
2478 + * Max size of options line and parameter.
2480 +#define OPTION_PARM_SIZE 256
2481 +#define OPTION_LINE_SIZE 256
2483 +extern const char title_string[];
2487 +/* certain options are saved before --pull modifications are applied */
2488 +struct options_pre_pull
2490 + bool tuntap_options_defined;
2491 + struct tuntap_options tuntap_options;
2493 + bool routes_defined;
2494 + struct route_option_list *routes;
2496 + int foreign_option_index;
2501 +struct connection_entry
2505 + bool local_port_defined;
2507 + bool port_option_used;
2508 + const char *local;
2509 + const char *remote;
2510 + bool remote_float;
2511 + bool bind_defined;
2513 + int connect_retry_seconds;
2514 + bool connect_retry_defined;
2515 + int connect_retry_max;
2516 + int connect_timeout;
2517 + bool connect_timeout_defined;
2518 +#ifdef ENABLE_HTTP_PROXY
2519 + struct http_proxy_options *http_proxy_options;
2521 +#ifdef ENABLE_SOCKS
2522 + const char *socks_proxy_server;
2523 + int socks_proxy_port;
2524 + const char *socks_proxy_authfile;
2525 + bool socks_proxy_retry;
2528 +# define CE_DISABLED (1<<0)
2529 +#if HTTP_PROXY_FALLBACK
2530 +# define CE_HTTP_PROXY_FALLBACK (1<<1)
2531 + time_t ce_http_proxy_fallback_timestamp; /* time when fallback http_proxy_options was last updated */
2534 + unsigned int flags;
2537 +struct remote_entry
2539 + const char *remote;
2544 +#ifdef ENABLE_CONNECTION
2546 +#define CONNECTION_LIST_SIZE 64
2548 +struct connection_list
2554 + struct connection_entry *array[CONNECTION_LIST_SIZE];
2560 + struct remote_entry *array[CONNECTION_LIST_SIZE];
2565 +#if HTTP_PROXY_FALLBACK
2568 + struct http_proxy_options hpo;
2573 +/* Command line options */
2576 + struct gc_arena gc;
2579 + /* first config file */
2580 + const char *config;
2583 +# define MODE_POINT_TO_POINT 0
2584 +# define MODE_SERVER 1
2587 + /* enable forward compatibility for post-2.1 features */
2588 + bool forward_compatible;
2590 + /* persist parms */
2591 + bool persist_config;
2595 + const char *key_pass_file;
2596 + bool show_ciphers;
2597 + bool show_digests;
2598 + bool show_engines;
2600 + bool show_tls_ciphers;
2605 + /* Networking parms */
2606 + struct connection_entry ce;
2608 +#ifdef ENABLE_CONNECTION
2609 + char *remote_ip_hint;
2610 + struct connection_list *connection_list;
2611 + struct remote_list *remote_list;
2612 + bool force_connection_list;
2615 +#ifdef GENERAL_PROXY_SUPPORT
2616 + struct auto_proxy_info *auto_proxy_info;
2619 +#if HTTP_PROXY_FALLBACK
2620 + bool http_proxy_fallback;
2621 + struct http_proxy_options *http_proxy_override;
2622 + struct hpo_store *hpo_store; /* used to store dynamic proxy info given by management interface */
2625 + bool remote_random;
2626 + const char *ipchange;
2628 + const char *dev_type;
2629 + const char *dev_node;
2630 + const char *lladdr;
2631 + int topology; /* one of the TOP_x values from proto.h */
2632 + const char *ifconfig_local;
2633 + const char *ifconfig_remote_netmask;
2634 + const char *ifconfig_ipv6_local;
2635 + int ifconfig_ipv6_netbits;
2636 + const char *ifconfig_ipv6_remote;
2637 + bool ifconfig_noexec;
2638 + bool ifconfig_nowarn;
2639 +#ifdef HAVE_GETTIMEOFDAY
2642 + int tun_mtu; /* MTU of tun device */
2643 + int tun_mtu_extra;
2644 + bool tun_mtu_extra_defined;
2645 + int link_mtu; /* MTU of device over which tunnel packets pass via TCP/UDP */
2646 + bool tun_mtu_defined; /* true if user overriding parm with command line option */
2647 + bool link_mtu_defined; /* true if user overriding parm with command line option */
2651 + /* Advanced MTU negotiation and datagram fragmentation options */
2652 + int mtu_discover_type; /* used if OS supports setting Path MTU discovery options on socket */
2658 + int fragment; /* internal fragmentation size */
2662 + int keepalive_ping; /* a proxy for ping/ping-restart */
2663 + int keepalive_timeout;
2665 + int inactivity_timeout; /* --inactive */
2666 + int inactivity_minimum_bytes;
2668 + int ping_send_timeout; /* Send a TCP/UDP ping to remote every n seconds */
2669 + int ping_rec_timeout; /* Expect a TCP/UDP ping from remote at least once every n seconds */
2670 + bool ping_timer_remote; /* Run ping timer only if we have a remote address */
2671 + bool tun_ipv6; /* Build tun dev that supports IPv6 */
2673 +# define PING_UNDEF 0
2674 +# define PING_EXIT 1
2675 +# define PING_RESTART 2
2676 + int ping_rec_timeout_action; /* What action to take on ping_rec_timeout (exit or restart)? */
2679 + int explicit_exit_notification; /* Explicitly tell peer when we are exiting via OCC_EXIT message */
2682 + bool persist_tun; /* Don't close/reopen TUN/TAP dev on SIGUSR1 or PING_RESTART */
2683 + bool persist_local_ip; /* Don't re-resolve local address on SIGUSR1 or PING_RESTART */
2684 + bool persist_remote_ip; /* Don't re-resolve remote address on SIGUSR1 or PING_RESTART */
2685 + bool persist_key; /* Don't re-read key files on SIGUSR1 or PING_RESTART */
2687 + int mssfix; /* Upper bound on TCP MSS */
2688 + bool mssfix_default; /* true if --mssfix was supplied without a parameter */
2690 +#if PASSTOS_CAPABILITY
2694 + int resolve_retry_seconds; /* If hostname resolve fails, retry for n seconds */
2696 + struct tuntap_options tuntap_options;
2699 + const char *username;
2700 + const char *groupname;
2701 + const char *chroot_dir;
2702 + const char *cd_dir;
2704 + char *selinux_context;
2706 + const char *writepid;
2707 + const char *up_script;
2708 + const char *down_script;
2714 + int remap_sigusr1;
2716 + /* inetd modes defined in socket.h */
2720 + bool suppress_timestamps;
2725 +#ifdef ENABLE_DEBUG
2729 + const char *status_file;
2730 + int status_file_version;
2731 + int status_file_update_freq;
2733 + /* optimize TUN/TAP/UDP writes */
2737 + /* LZO_x flags from lzo.h */
2741 + /* buffer sizes */
2745 + /* socket flags */
2746 + unsigned int sockflags;
2748 + /* route management */
2749 + const char *route_script;
2750 + const char *route_default_gateway;
2751 + int route_default_metric;
2752 + bool route_noexec;
2754 + int route_delay_window;
2755 + bool route_delay_defined;
2757 + struct route_option_list *routes;
2758 + struct route_ipv6_option_list *routes_ipv6; /* IPv6 */
2759 + bool route_nopull;
2760 + bool route_gateway_via_dhcp;
2761 + bool allow_pull_fqdn; /* as a client, allow server to push a FQDN for certain parameters */
2764 + /* Enable options consistency check between peers */
2768 +#ifdef ENABLE_MANAGEMENT
2769 + const char *management_addr;
2770 + int management_port;
2771 + const char *management_user_pass;
2772 + int management_log_history_cache;
2773 + int management_echo_buffer_size;
2774 + int management_state_buffer_size;
2775 + const char *management_write_peer_info_file;
2777 + const char *management_client_user;
2778 + const char *management_client_group;
2780 + /* Mask of MF_ values of manage.h */
2781 + unsigned int management_flags;
2784 +#ifdef ENABLE_PLUGIN
2785 + struct plugin_option_list *plugin_list;
2788 + const char *tmp_dir;
2793 + bool server_defined;
2794 + in_addr_t server_network;
2795 + in_addr_t server_netmask;
2796 + bool server_ipv6_defined; /* IPv6 */
2797 + struct in6_addr server_network_ipv6; /* IPv6 */
2798 + unsigned int server_netbits_ipv6; /* IPv6 */
2800 +# define SF_NOPOOL (1<<0)
2801 +# define SF_TCP_NODELAY_HELPER (1<<1)
2802 +# define SF_NO_PUSH_ROUTE_GATEWAY (1<<2)
2803 + unsigned int server_flags;
2805 + bool server_bridge_proxy_dhcp;
2807 + bool server_bridge_defined;
2808 + in_addr_t server_bridge_ip;
2809 + in_addr_t server_bridge_netmask;
2810 + in_addr_t server_bridge_pool_start;
2811 + in_addr_t server_bridge_pool_end;
2813 + struct push_list push_list;
2814 + bool ifconfig_pool_defined;
2815 + in_addr_t ifconfig_pool_start;
2816 + in_addr_t ifconfig_pool_end;
2817 + in_addr_t ifconfig_pool_netmask;
2818 + const char *ifconfig_pool_persist_filename;
2819 + int ifconfig_pool_persist_refresh_freq;
2821 + bool ifconfig_ipv6_pool_defined; /* IPv6 */
2822 + struct in6_addr ifconfig_ipv6_pool_base; /* IPv6 */
2823 + int ifconfig_ipv6_pool_netbits; /* IPv6 */
2825 + int real_hash_size;
2826 + int virtual_hash_size;
2827 + const char *client_connect_script;
2828 + const char *client_disconnect_script;
2829 + const char *learn_address_script;
2830 + const char *client_config_dir;
2831 + bool ccd_exclusive;
2834 + int tcp_queue_limit;
2835 + struct iroute *iroutes;
2836 + struct iroute_ipv6 *iroutes_ipv6; /* IPv6 */
2837 + bool push_ifconfig_defined;
2838 + in_addr_t push_ifconfig_local;
2839 + in_addr_t push_ifconfig_remote_netmask;
2840 + bool push_ifconfig_constraint_defined;
2841 + in_addr_t push_ifconfig_constraint_network;
2842 + in_addr_t push_ifconfig_constraint_netmask;
2843 + bool push_ifconfig_ipv6_defined; /* IPv6 */
2844 + struct in6_addr push_ifconfig_ipv6_local; /* IPv6 */
2845 + int push_ifconfig_ipv6_netbits; /* IPv6 */
2846 + struct in6_addr push_ifconfig_ipv6_remote; /* IPv6 */
2848 + bool duplicate_cn;
2852 + int max_routes_per_client;
2854 + const char *auth_user_pass_verify_script;
2855 + bool auth_user_pass_verify_script_via_file;
2856 + unsigned int ssl_flags; /* set to SSLF_x flags from ssl.h */
2858 + char *port_share_host;
2859 + int port_share_port;
2864 + bool pull; /* client pull of config options from server */
2865 + int push_continuation;
2866 + const char *auth_user_pass_file;
2867 + struct options_pre_pull *pre_pull;
2869 + int server_poll_timeout;
2871 + int scheduled_exit_interval;
2876 + /* Cipher parms */
2877 + const char *shared_secret_file;
2878 +#if ENABLE_INLINE_FILES
2879 + const char *shared_secret_file_inline;
2881 + int key_direction;
2882 + bool ciphername_defined;
2883 + const char *ciphername;
2884 + bool authname_defined;
2885 + const char *authname;
2887 + const char *prng_hash;
2888 + int prng_nonce_secret_len;
2889 + const char *engine;
2891 + bool mute_replay_warnings;
2892 + int replay_window;
2894 + const char *packet_id_file;
2899 + /* TLS (control channel) parms */
2902 + const char *ca_file;
2903 + const char *ca_path;
2904 + const char *dh_file;
2905 + const char *cert_file;
2906 + const char *priv_key_file;
2907 + const char *pkcs12_file;
2908 + const char *cipher_list;
2909 + const char *tls_verify;
2910 + const char *tls_export_cert;
2911 + const char *tls_remote;
2912 + const char *crl_file;
2914 +#if ENABLE_INLINE_FILES
2915 + const char *ca_file_inline;
2916 + const char *cert_file_inline;
2917 + char *priv_key_file_inline;
2918 + const char *dh_file_inline;
2919 + const char *pkcs12_file_inline; /* contains the base64 encoding of pkcs12 file */
2922 + int ns_cert_type; /* set to 0, NS_SSL_SERVER, or NS_SSL_CLIENT */
2923 + unsigned remote_cert_ku[MAX_PARMS];
2924 + const char *remote_cert_eku;
2926 +#ifdef ENABLE_PKCS11
2927 + const char *pkcs11_providers[MAX_PARMS];
2928 + unsigned pkcs11_private_mode[MAX_PARMS];
2929 + bool pkcs11_protected_authentication[MAX_PARMS];
2930 + bool pkcs11_cert_private[MAX_PARMS];
2931 + int pkcs11_pin_cache_period;
2932 + const char *pkcs11_id;
2933 + bool pkcs11_id_management;
2937 + const char *cryptoapi_cert;
2940 + /* data channel key exchange method */
2943 + /* Per-packet timeout on control channel */
2946 + /* Data channel key renegotiation parameters */
2947 + int renegotiate_bytes;
2948 + int renegotiate_packets;
2949 + int renegotiate_seconds;
2951 + /* Data channel key handshake must finalize
2952 + within n seconds of handshake initiation. */
2953 + int handshake_window;
2955 +#ifdef ENABLE_X509ALTUSERNAME
2956 + /* Field used to be the username in X509 cert. */
2957 + char *x509_username_field;
2960 + /* Old key allowed to live n seconds after new key goes active */
2961 + int transition_window;
2963 + /* Special authentication MAC for TLS control channel */
2964 + const char *tls_auth_file; /* shared secret */
2965 +#if ENABLE_INLINE_FILES
2966 + const char *tls_auth_file_inline;
2969 + /* Allow only one session */
2970 + bool single_session;
2972 +#ifdef ENABLE_PUSH_PEER_INFO
2973 + bool push_peer_info;
2978 +#endif /* USE_SSL */
2979 +#endif /* USE_CRYPTO */
2981 + /* special state parms */
2982 + int foreign_option_index;
2985 + const char *exit_event_name;
2986 + bool exit_event_initial_state;
2992 +#define streq(x, y) (!strcmp((x), (y)))
2997 +#define OPT_P_GENERAL (1<<0)
2998 +#define OPT_P_UP (1<<1)
2999 +#define OPT_P_ROUTE (1<<2)
3000 +#define OPT_P_IPWIN32 (1<<3)
3001 +#define OPT_P_SCRIPT (1<<4)
3002 +#define OPT_P_SETENV (1<<5)
3003 +#define OPT_P_SHAPER (1<<6)
3004 +#define OPT_P_TIMER (1<<7)
3005 +#define OPT_P_PERSIST (1<<8)
3006 +#define OPT_P_PERSIST_IP (1<<9)
3007 +#define OPT_P_COMP (1<<10) /* TODO */
3008 +#define OPT_P_MESSAGES (1<<11)
3009 +#define OPT_P_CRYPTO (1<<12) /* TODO */
3010 +#define OPT_P_TLS_PARMS (1<<13) /* TODO */
3011 +#define OPT_P_MTU (1<<14) /* TODO */
3012 +#define OPT_P_NICE (1<<15)
3013 +#define OPT_P_PUSH (1<<16)
3014 +#define OPT_P_INSTANCE (1<<17)
3015 +#define OPT_P_CONFIG (1<<18)
3016 +#define OPT_P_EXPLICIT_NOTIFY (1<<19)
3017 +#define OPT_P_ECHO (1<<20)
3018 +#define OPT_P_INHERIT (1<<21)
3019 +#define OPT_P_ROUTE_EXTRAS (1<<22)
3020 +#define OPT_P_PULL_MODE (1<<23)
3021 +#define OPT_P_PLUGIN (1<<24)
3022 +#define OPT_P_SOCKBUF (1<<25)
3023 +#define OPT_P_SOCKFLAGS (1<<26)
3024 +#define OPT_P_CONNECTION (1<<27)
3026 +#define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE))
3029 +#define PULL_DEFINED(opt) ((opt)->pull)
3031 +#define PUSH_DEFINED(opt) ((opt)->push_list)
3035 +#ifndef PULL_DEFINED
3036 +#define PULL_DEFINED(opt) (false)
3039 +#ifndef PUSH_DEFINED
3040 +#define PUSH_DEFINED(opt) (false)
3044 +#define ROUTE_OPTION_FLAGS(o) ((o)->route_method & ROUTE_METHOD_MASK)
3046 +#define ROUTE_OPTION_FLAGS(o) (0)
3049 +#ifdef HAVE_GETTIMEOFDAY
3050 +#define SHAPER_DEFINED(opt) ((opt)->shaper)
3052 +#define SHAPER_DEFINED(opt) (false)
3055 +#ifdef ENABLE_PLUGIN
3056 +#define PLUGIN_OPTION_LIST(opt) ((opt)->plugin_list)
3058 +#define PLUGIN_OPTION_LIST(opt) (NULL)
3061 +#ifdef MANAGEMENT_DEF_AUTH
3062 +#define MAN_CLIENT_AUTH_ENABLED(opt) ((opt)->management_flags & MF_CLIENT_AUTH)
3064 +#define MAN_CLIENT_AUTH_ENABLED(opt) (false)
3067 +void parse_argv (struct options *options,
3070 + const int msglevel,
3071 + const unsigned int permission_mask,
3072 + unsigned int *option_types_found,
3073 + struct env_set *es);
3075 +void notnull (const char *arg, const char *description);
3077 +void usage_small (void);
3079 +void init_options (struct options *o, const bool init_gc);
3080 +void uninit_options (struct options *o);
3082 +void setenv_settings (struct env_set *es, const struct options *o);
3083 +void show_settings (const struct options *o);
3085 +bool string_defined_equal (const char *s1, const char *s2);
3089 +const char *options_string_version (const char* s, struct gc_arena *gc);
3091 +char *options_string (const struct options *o,
3092 + const struct frame *frame,
3093 + struct tuntap *tt,
3095 + struct gc_arena *gc);
3097 +bool options_cmp_equal_safe (char *actual, const char *expected, size_t actual_n);
3098 +void options_warning_safe (char *actual, const char *expected, size_t actual_n);
3099 +bool options_cmp_equal (char *actual, const char *expected);
3100 +void options_warning (char *actual, const char *expected);
3104 +void options_postprocess (struct options *options);
3106 +void pre_pull_save (struct options *o);
3107 +void pre_pull_restore (struct options *o);
3109 +bool apply_push_options (struct options *options,
3110 + struct buffer *buf,
3111 + unsigned int permission_mask,
3112 + unsigned int *option_types_found,
3113 + struct env_set *es);
3115 +bool is_persist_option (const struct options *o);
3116 +bool is_stateful_restart (const struct options *o);
3118 +void options_detach (struct options *o);
3120 +void options_server_import (struct options *o,
3121 + const char *filename,
3123 + unsigned int permission_mask,
3124 + unsigned int *option_types_found,
3125 + struct env_set *es);
3127 +void pre_pull_default (struct options *o);
3129 +void rol_check_alloc (struct options *options);
3131 +int parse_line (const char *line,
3135 + const int line_num,
3137 + struct gc_arena *gc);
3140 + * parse/print topology coding
3143 +int parse_topology (const char *str, const int msglevel);
3144 +const char *print_topology (const int topology);
3147 + * Manage auth-retry variable
3153 +#define AR_INTERACT 1
3154 +#define AR_NOINTERACT 2
3156 +int auth_retry_get (void);
3157 +bool auth_retry_set (const int msglevel, const char *option);
3158 +const char *auth_retry_print (void);
3162 +void options_string_import (struct options *options,
3163 + const char *config,
3164 + const int msglevel,
3165 + const unsigned int permission_mask,
3166 + unsigned int *option_types_found,
3167 + struct env_set *es);
3169 +bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network,
3170 + unsigned int * netbits, char ** printable_ipv6,
3174 + * inline functions
3177 +connection_list_defined (const struct options *o)
3179 +#ifdef ENABLE_CONNECTION
3180 + return o->connection_list != NULL;
3187 +connection_list_set_no_advance (struct options *o)
3189 +#ifdef ENABLE_CONNECTION
3190 + if (o->connection_list)
3191 + o->connection_list->no_advance = true;
3195 +#if HTTP_PROXY_FALLBACK
3197 +struct http_proxy_options *
3198 +parse_http_proxy_fallback (struct context *c,
3199 + const char *server,
3201 + const char *flags,
3202 + const int msglevel);
3204 +#endif /* HTTP_PROXY_FALLBACK */
3207 diff -durN openvpn-2.2.2.orig/pool.c openvpn-2.2.2/pool.c
3208 --- openvpn-2.2.2.orig/pool.c 2011-12-13 17:58:56.000000000 +0100
3209 +++ openvpn-2.2.2/pool.c 2012-06-01 10:40:28.000000000 +0200
3210 @@ -132,7 +132,10 @@
3213 struct ifconfig_pool *
3214 -ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn)
3215 +ifconfig_pool_init (int type, in_addr_t start, in_addr_t end,
3216 + const bool duplicate_cn,
3217 + const bool ipv6_pool, const struct in6_addr ipv6_base,
3218 + const int ipv6_netbits )
3220 struct gc_arena gc = gc_new ();
3221 struct ifconfig_pool *pool = NULL;
3222 @@ -157,11 +160,31 @@
3226 + /* IPv6 pools are always "INDIV" type */
3227 + pool->ipv6 = ipv6_pool;
3231 + pool->base_ipv6 = ipv6_base;
3232 + pool->size_ipv6 = ipv6_netbits>96? ( 1<<(128-ipv6_netbits) )
3233 + : IFCONFIG_POOL_MAX;
3235 + msg( D_IFCONFIG_POOL, "IFCONFIG POOL IPv6: (IPv4) size=%d, size_ipv6=%d, netbits=%d, base_ipv6=%s",
3236 + pool->size, pool->size_ipv6, ipv6_netbits,
3237 + print_in6_addr( pool->base_ipv6, 0, &gc ));
3239 + /* the current code is very simple and assumes that the IPv6
3240 + * pool is at least as big as the IPv4 pool, and we don't need
3241 + * to do separate math etc. for IPv6
3243 + ASSERT( pool->size < pool->size_ipv6 );
3246 ALLOC_ARRAY_CLEAR (pool->list, struct ifconfig_pool_entry, pool->size);
3248 - msg (D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d",
3249 + msg (D_IFCONFIG_POOL, "IFCONFIG POOL: base=%s size=%d, ipv6=%d",
3250 print_in_addr_t (pool->base, 0, &gc),
3252 + pool->size, pool->ipv6 );
3259 ifconfig_pool_handle
3260 -ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, const char *common_name)
3261 +ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, struct in6_addr *remote_ipv6, const char *common_name)
3265 @@ -214,6 +237,12 @@
3270 + /* IPv6 pools are always INDIV (--linear) */
3271 + if ( pool->ipv6 && remote_ipv6 )
3273 + *remote_ipv6 = add_in6_addr( pool->base_ipv6, i );
3278 @@ -288,6 +317,19 @@
3282 +static struct in6_addr
3283 +ifconfig_pool_handle_to_ipv6_base (const struct ifconfig_pool* pool, ifconfig_pool_handle hand)
3285 + struct in6_addr ret = in6addr_any;
3287 + /* IPv6 pools are always INDIV (--linear) */
3288 + if (hand >= 0 && hand < pool->size_ipv6 )
3290 + ret = add_in6_addr( pool->base_ipv6, hand );
3296 ifconfig_pool_set (struct ifconfig_pool* pool, const char *cn, const in_addr_t addr, const bool fixed)
3298 @@ -317,9 +359,20 @@
3301 const in_addr_t ip = ifconfig_pool_handle_to_ip_base (pool, i);
3302 - status_printf (out, "%s,%s",
3304 - print_in_addr_t (ip, 0, &gc));
3307 + struct in6_addr ip6 = ifconfig_pool_handle_to_ipv6_base (pool, i);
3308 + status_printf (out, "%s,%s,%s",
3310 + print_in_addr_t (ip, 0, &gc),
3311 + print_in6_addr (ip6, 0, &gc));
3315 + status_printf (out, "%s,%s",
3317 + print_in_addr_t (ip, 0, &gc));
3324 if (c == '#' || c == ';')
3326 + msg( M_INFO, "ifconfig_pool_read(), in='%s', TODO: IPv6",
3329 if (buf_parse (&in, ',', cn_buf, buf_size)
3330 && buf_parse (&in, ',', ip_buf, buf_size))
3333 const in_addr_t addr = getaddr (GETADDR_HOST_ORDER, ip_buf, 0, &succeeded, NULL);
3336 + msg( M_INFO, "succeeded -> ifconfig_pool_set()");
3337 ifconfig_pool_set (pool, cn_buf, addr, persist->fixed);
3344 - h = ifconfig_pool_acquire (p, &local, &remote, cn);
3345 + h = ifconfig_pool_acquire (p, &local, &remote, NULL, cn);
3348 msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 1: l=%s r=%s cn=%s",
3353 - h = ifconfig_pool_acquire (p, &local, &remote, cn);
3354 + h = ifconfig_pool_acquire (p, &local, &remote, NULL, cn);
3357 msg (M_INFO | M_NOPREFIX, "IFCONFIG_POOL TEST pass 3: l=%s r=%s cn=%s",
3358 diff -durN openvpn-2.2.2.orig/pool.h openvpn-2.2.2/pool.h
3359 --- openvpn-2.2.2.orig/pool.h 2011-12-13 17:58:56.000000000 +0100
3360 +++ openvpn-2.2.2/pool.h 2012-06-01 10:40:28.000000000 +0200
3366 + struct in6_addr base_ipv6;
3367 + unsigned int size_ipv6;
3368 struct ifconfig_pool_entry *list;
3373 typedef int ifconfig_pool_handle;
3375 -struct ifconfig_pool *ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn);
3376 +struct ifconfig_pool *ifconfig_pool_init (int type, in_addr_t start, in_addr_t end, const bool duplicate_cn, const bool ipv6_pool, const struct in6_addr ipv6_base, const int ipv6_netbits );
3378 void ifconfig_pool_free (struct ifconfig_pool *pool);
3380 bool ifconfig_pool_verify_range (const int msglevel, const in_addr_t start, const in_addr_t end);
3382 -ifconfig_pool_handle ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, const char *common_name);
3383 +ifconfig_pool_handle ifconfig_pool_acquire (struct ifconfig_pool *pool, in_addr_t *local, in_addr_t *remote, struct in6_addr *remote_ipv6, const char *common_name);
3385 bool ifconfig_pool_release (struct ifconfig_pool* pool, ifconfig_pool_handle hand, const bool hard);
3387 diff -durN openvpn-2.2.2.orig/proto.h openvpn-2.2.2/proto.h
3388 --- openvpn-2.2.2.orig/proto.h 2011-12-13 17:58:56.000000000 +0100
3389 +++ openvpn-2.2.2/proto.h 2012-06-01 10:40:28.000000000 +0200
3390 @@ -108,6 +108,21 @@
3396 +struct openvpn_ipv6hdr {
3397 + uint8_t version_prio;
3398 + uint8_t flow_lbl[3];
3399 + uint16_t payload_len;
3401 + uint8_t hop_limit;
3403 + struct in6_addr saddr;
3404 + struct in6_addr daddr;
3411 struct openvpn_udphdr {
3412 diff -durN openvpn-2.2.2.orig/push.c openvpn-2.2.2/push.c
3413 --- openvpn-2.2.2.orig/push.c 2011-12-13 17:58:56.000000000 +0100
3414 +++ openvpn-2.2.2/push.c 2012-06-01 10:40:28.000000000 +0200
3415 @@ -189,8 +189,26 @@
3416 const int safe_cap = BCAP (&buf) - extra;
3417 bool push_sent = false;
3419 + msg( M_INFO, "send_push_reply(): safe_cap=%d", safe_cap );
3421 buf_printf (&buf, "%s", cmd);
3423 + if ( c->c2.push_ifconfig_ipv6_defined )
3425 + /* IPv6 is put into buffer first, could be lengthy */
3426 + /* TODO: push "/netbits" as well, to allow non-/64 subnet sizes
3427 + * (needs changes in options.c, options.h, and other places)
3429 + buf_printf( &buf, ",ifconfig-ipv6 %s %s",
3430 + print_in6_addr( c->c2.push_ifconfig_ipv6_local, 0, &gc),
3431 + print_in6_addr( c->c2.push_ifconfig_ipv6_remote, 0, &gc) );
3432 + if (BLEN (&buf) >= safe_cap)
3434 + msg (M_WARN, "--push ifconfig-ipv6 option is too long");
3442 diff -durN openvpn-2.2.2.orig/route.c openvpn-2.2.2/route.c
3443 --- openvpn-2.2.2.orig/route.c 2011-12-13 17:58:56.000000000 +0100
3444 +++ openvpn-2.2.2/route.c 2012-06-01 10:40:28.000000000 +0200
3449 +#include "options.h"
3457 +struct route_ipv6_option_list *
3458 +new_route_ipv6_option_list (const int max_routes, struct gc_arena *a)
3460 + struct route_ipv6_option_list *ret;
3461 + ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_option_list, struct route_ipv6_option, max_routes, a);
3462 + ret->capacity = max_routes;
3466 struct route_option_list *
3467 clone_route_option_list (const struct route_option_list *src, struct gc_arena *a)
3473 +struct route_ipv6_list *
3474 +new_route_ipv6_list (const int max_routes, struct gc_arena *a)
3476 + struct route_ipv6_list *ret;
3477 + ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_ipv6_list, struct route_ipv6, max_routes, a);
3478 + ret->capacity = max_routes;
3483 route_string (const struct route *r, struct gc_arena *gc)
3485 @@ -311,6 +330,68 @@
3490 +init_route_ipv6 (struct route_ipv6 *r6,
3491 + const struct route_ipv6_option *r6o,
3492 + const struct route_ipv6_list *rl6 )
3495 + r6->defined = false;
3497 + if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN ))
3501 + if (is_route_parm_defined (r6o->gateway))
3503 + if ( inet_pton( AF_INET6, r6o->gateway, &r6->gateway ) != 1 )
3505 + msg( M_WARN, PACKAGE_NAME "ROUTE6: cannot parse gateway spec '%s'", r6o->gateway );
3508 + else if (rl6->remote_endpoint_defined)
3510 + r6->gateway = rl6->remote_endpoint_ipv6;
3514 + msg (M_WARN, PACKAGE_NAME " ROUTE6: " PACKAGE_NAME " needs a gateway parameter for a --route-ipv6 option and no default was specified by either --route-ipv6-gateway or --ifconfig-ipv6 options");
3520 + r6->metric_defined = false;
3522 + if (is_route_parm_defined (r6o->metric))
3524 + r6->metric = atoi (r6o->metric);
3525 + if (r6->metric < 0)
3527 + msg (M_WARN, PACKAGE_NAME " ROUTE: route metric for network %s (%s) must be >= 0",
3532 + r6->metric_defined = true;
3534 + else if (rl6->default_metric_defined)
3536 + r6->metric = rl6->default_metric;
3537 + r6->metric_defined = true;
3540 + r6->defined = true;
3545 + msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve route for host/network: %s",
3547 + r6->defined = false;
3552 add_route_to_option_list (struct route_option_list *l,
3553 const char *network,
3554 @@ -331,6 +412,23 @@
3558 +add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
3559 + const char *prefix,
3560 + const char *gateway,
3561 + const char *metric)
3563 + struct route_ipv6_option *ro;
3564 + if (l->n >= l->capacity)
3565 + msg (M_FATAL, PACKAGE_NAME " ROUTE: cannot add more than %d IPv6 routes -- please increase the max-routes option in the client configuration file",
3567 + ro = &l->routes_ipv6[l->n];
3568 + ro->prefix = prefix;
3569 + ro->gateway = gateway;
3570 + ro->metric = metric;
3575 clear_route_list (struct route_list *rl)
3577 const int capacity = rl->capacity;
3578 @@ -340,6 +438,15 @@
3582 +clear_route_ipv6_list (struct route_ipv6_list *rl6)
3584 + const int capacity = rl6->capacity;
3585 + const size_t rl6_size = array_mult_safe (sizeof(struct route_ipv6), capacity, sizeof(struct route_ipv6_list));
3586 + memset(rl6, 0, rl6_size);
3587 + rl6->capacity = capacity;
3591 route_list_add_default_gateway (struct route_list *rl,
3593 const in_addr_t addr)
3594 @@ -469,6 +576,72 @@
3599 +init_route_ipv6_list (struct route_ipv6_list *rl6,
3600 + const struct route_ipv6_option_list *opt6,
3601 + const char *remote_endpoint,
3602 + int default_metric,
3603 + struct env_set *es)
3605 + struct gc_arena gc = gc_new ();
3608 + clear_route_ipv6_list (rl6);
3610 + rl6->flags = opt6->flags;
3612 + if (default_metric)
3614 + rl6->default_metric = default_metric;
3615 + rl6->default_metric_defined = true;
3618 + /* "default_gateway" is stuff for "redirect-gateway", which we don't
3619 + * do for IPv6 yet -> TODO
3622 + dmsg (D_ROUTE, "ROUTE6: default_gateway=UNDEF");
3625 + if ( is_route_parm_defined( remote_endpoint ))
3627 + if ( inet_pton( AF_INET6, remote_endpoint,
3628 + &rl6->remote_endpoint_ipv6) == 1 )
3630 + rl6->remote_endpoint_defined = true;
3634 + msg (M_WARN, PACKAGE_NAME " ROUTE: failed to parse/resolve default gateway: %s", remote_endpoint);
3639 + rl6->remote_endpoint_defined = false;
3642 + if (!(opt6->n >= 0 && opt6->n <= rl6->capacity))
3643 + msg (M_FATAL, PACKAGE_NAME " ROUTE6: (init) number of route options (%d) is greater than route list capacity (%d)", opt6->n, rl6->capacity);
3645 + /* parse the routes from opt to rl6 */
3648 + for (i = 0; i < opt6->n; ++i)
3650 + if (!init_route_ipv6 (&rl6->routes_ipv6[j],
3651 + &opt6->routes_ipv6[i],
3665 add_route3 (in_addr_t network,
3667 @@ -704,10 +877,13 @@
3671 -add_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3672 +add_routes (struct route_list *rl, struct route_ipv6_list *rl6,
3673 + const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3675 - redirect_default_route_to_vpn (rl, tt, flags, es);
3676 - if (!rl->routes_added)
3678 + redirect_default_route_to_vpn (rl, tt, flags, es);
3680 + if (rl && !rl->routes_added)
3684 @@ -732,12 +908,27 @@
3686 rl->routes_added = true;
3689 + if (rl6 && !rl6->routes_added)
3693 + for (i = 0; i < rl6->n; ++i)
3695 + struct route_ipv6 *r = &rl6->routes_ipv6[i];
3696 + if (flags & ROUTE_DELETE_FIRST)
3697 + delete_route_ipv6 (r, tt, flags, es);
3698 + add_route_ipv6 (r, tt, flags, es);
3700 + rl6->routes_added = true;
3705 -delete_routes (struct route_list *rl, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3706 +delete_routes (struct route_list *rl, struct route_ipv6_list *rl6,
3707 + const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3709 - if (rl->routes_added)
3710 + if (rl && rl->routes_added)
3713 for (i = rl->n - 1; i >= 0; --i)
3714 @@ -747,9 +938,28 @@
3716 rl->routes_added = false;
3718 - undo_redirect_default_route_to_vpn (rl, tt, flags, es);
3720 - clear_route_list (rl);
3723 + undo_redirect_default_route_to_vpn (rl, tt, flags, es);
3724 + clear_route_list (rl);
3727 + if ( rl6 && rl6->routes_added )
3730 + for (i = rl6->n - 1; i >= 0; --i)
3732 + const struct route_ipv6 *r6 = &rl6->routes_ipv6[i];
3733 + delete_route_ipv6 (r6, tt, flags, es);
3735 + rl6->routes_added = false;
3740 + clear_route_ipv6_list (rl6);
3745 @@ -832,6 +1042,34 @@
3746 setenv_route (es, &rl->routes[i], i + 1);
3750 +setenv_route_ipv6 (struct env_set *es, const struct route_ipv6 *r6, int i)
3752 + struct gc_arena gc = gc_new ();
3755 + struct buffer name1 = alloc_buf_gc( 256, &gc );
3756 + struct buffer val = alloc_buf_gc( 256, &gc );
3757 + struct buffer name2 = alloc_buf_gc( 256, &gc );
3759 + buf_printf( &name1, "route_ipv6_network_%d", i );
3760 + buf_printf( &val, "%s/%d", print_in6_addr( r6->network, 0, &gc ),
3762 + setenv_str( es, BSTR(&name1), BSTR(&val) );
3764 + buf_printf( &name2, "route_ipv6_gateway_%d", i );
3765 + setenv_str( es, BSTR(&name2), print_in6_addr( r6->gateway, 0, &gc ));
3770 +setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6)
3773 + for (i = 0; i < rl6->n; ++i)
3774 + setenv_route_ipv6 (es, &rl6->routes_ipv6[i], i + 1);
3778 add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3780 @@ -1025,6 +1263,187 @@
3785 +static const char *
3786 +print_in6_addr_netbits_only( struct in6_addr network_copy, int netbits,
3787 + struct gc_arena * gc)
3789 + /* clear host bit parts of route
3790 + * (needed if routes are specified improperly, or if we need to
3791 + * explicitely setup/clear the "connected" network routes on some OSes)
3794 + int bits_to_clear = 128 - netbits;
3796 + while( byte >= 0 && bits_to_clear > 0 )
3798 + if ( bits_to_clear >= 8 )
3799 + { network_copy.s6_addr[byte--] = 0; bits_to_clear -= 8; }
3801 + { network_copy.s6_addr[byte--] &= (~0 << bits_to_clear); bits_to_clear = 0; }
3804 + return print_in6_addr( network_copy, 0, gc);
3808 +add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3810 + struct gc_arena gc;
3813 + const char *network;
3814 + const char *gateway;
3815 + bool status = false;
3816 + const char *device = tt->actual_name;
3822 + argv_init (&argv);
3824 + network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
3825 + gateway = print_in6_addr( r6->gateway, 0, &gc);
3829 + msg( M_INFO, "add_route_ipv6(): not adding %s/%d, no IPv6 on if %s",
3830 + network, r6->netbits, device );
3834 + msg( M_INFO, "add_route_ipv6(%s/%d -> %s metric %d) dev %s",
3835 + network, r6->netbits, gateway, r6->metric, device );
3838 + * Filter out routes which are essentially no-ops
3839 + * (not currently done for IPv6)
3842 +#if defined(TARGET_LINUX)
3843 +#ifdef CONFIG_FEATURE_IPROUTE
3844 + argv_printf (&argv, "%s -6 route add %s/%d dev %s",
3849 + if (r6->metric_defined)
3850 + argv_printf_cat (&argv, " metric %d", r6->metric);
3853 + argv_printf (&argv, "%s -A inet6 add %s/%d dev %s",
3858 + if (r6->metric_defined)
3859 + argv_printf_cat (&argv, " metric %d", r6->metric);
3860 +#endif /*CONFIG_FEATURE_IPROUTE*/
3861 + argv_msg (D_ROUTE, &argv);
3862 + status = openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 add command failed");
3864 +#elif defined (WIN32)
3866 + /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */
3867 + argv_printf (&argv, "%s%sc interface ipv6 add route %s/%d %s",
3868 + get_win_sys_path(),
3869 + NETSH_PATH_SUFFIX,
3874 + /* next-hop depends on TUN or TAP mode:
3875 + * - in TAP mode, we use the "real" next-hop
3876 + * - in TUN mode we use a special-case link-local address that the tapdrvr
3877 + * knows about and will answer ND (neighbor discovery) packets for
3879 + if ( tt->type == DEV_TYPE_TUN )
3880 + argv_printf_cat( &argv, " %s", "fe80::8" );
3882 + argv_printf_cat( &argv, " %s", gateway );
3885 + if (r->metric_defined)
3886 + argv_printf_cat (&argv, " METRIC %d", r->metric);
3889 + /* in some versions of Windows, routes are persistent across reboots by
3890 + * default, unless "store=active" is set (pointed out by Tony Lim, thanks)
3892 + argv_printf_cat( &argv, " store=active" );
3894 + argv_msg (D_ROUTE, &argv);
3896 + netcmd_semaphore_lock ();
3897 + status = openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
3898 + netcmd_semaphore_release ();
3900 +#elif defined (TARGET_SOLARIS)
3902 + /* example: route add -inet6 2001:db8::/32 somegateway 0 */
3904 + /* for some weird reason, this does not work for me unless I set
3905 + * "metric 0" - otherwise, the routes will be nicely installed, but
3906 + * packets will just disappear somewhere. So we use "0" now...
3909 + argv_printf (&argv, "%s add -inet6 %s/%d %s 0",
3915 + argv_msg (D_ROUTE, &argv);
3916 + status = openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route add -inet6 command failed");
3918 +#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
3920 + argv_printf (&argv, "%s add -inet6 %s/%d -iface %s",
3926 + argv_msg (D_ROUTE, &argv);
3927 + status = openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route add -inet6 command failed");
3929 +#elif defined(TARGET_DARWIN)
3931 + argv_printf (&argv, "%s add -inet6 %s -prefixlen %d -iface %s",
3933 + network, r6->netbits, device );
3935 + argv_msg (D_ROUTE, &argv);
3936 + status = openvpn_execve_check (&argv, es, 0, "ERROR: MacOS X route add -inet6 command failed");
3938 +#elif defined(TARGET_OPENBSD)
3940 + argv_printf (&argv, "%s add -inet6 %s -prefixlen %d %s",
3942 + network, r6->netbits, gateway );
3944 + argv_msg (D_ROUTE, &argv);
3945 + status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route add -inet6 command failed");
3947 +#elif defined(TARGET_NETBSD)
3949 + argv_printf (&argv, "%s add -inet6 %s/%d %s",
3951 + network, r6->netbits, gateway );
3953 + argv_msg (D_ROUTE, &argv);
3954 + status = openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route add -inet6 command failed");
3957 + msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-up script");
3960 + r6->defined = status;
3961 + argv_reset (&argv);
3966 delete_route (const struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3968 @@ -1161,6 +1580,142 @@
3976 +delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flags, const struct env_set *es)
3978 + struct gc_arena gc;
3980 + const char *network;
3981 + const char *gateway;
3982 + const char *device = tt->actual_name;
3988 + argv_init (&argv);
3990 + network = print_in6_addr_netbits_only( r6->network, r6->netbits, &gc);
3991 + gateway = print_in6_addr( r6->gateway, 0, &gc);
3995 + msg( M_INFO, "delete_route_ipv6(): not deleting %s/%d, no IPv6 on if %s",
3996 + network, r6->netbits, device );
4000 + msg( M_INFO, "delete_route_ipv6(%s/%d)", network, r6->netbits );
4002 +#if defined(TARGET_LINUX)
4003 +#ifdef CONFIG_FEATURE_IPROUTE
4004 + argv_printf (&argv, "%s -6 route del %s/%d dev %s",
4010 + argv_printf (&argv, "%s -A inet6 del %s/%d dev %s",
4015 +#endif /*CONFIG_FEATURE_IPROUTE*/
4016 + argv_msg (D_ROUTE, &argv);
4017 + openvpn_execve_check (&argv, es, 0, "ERROR: Linux route -6/-A inet6 del command failed");
4019 +#elif defined (WIN32)
4021 + /* netsh interface ipv6 delete route 2001:db8::/32 MyTunDevice */
4022 + argv_printf (&argv, "%s%sc interface ipv6 delete route %s/%d %s",
4023 + get_win_sys_path(),
4024 + NETSH_PATH_SUFFIX,
4029 + /* next-hop depends on TUN or TAP mode:
4030 + * - in TAP mode, we use the "real" next-hop
4031 + * - in TUN mode we use a special-case link-local address that the tapdrvr
4032 + * knows about and will answer ND (neighbor discovery) packets for
4033 + * (and "route deletion without specifying next-hop" does not work...)
4035 + if ( tt->type == DEV_TYPE_TUN )
4036 + argv_printf_cat( &argv, " %s", "fe80::8" );
4038 + argv_printf_cat( &argv, " %s", gateway );
4041 + if (r->metric_defined)
4042 + argv_printf_cat (&argv, "METRIC %d", r->metric);
4045 + argv_msg (D_ROUTE, &argv);
4047 + netcmd_semaphore_lock ();
4048 + openvpn_execve_check (&argv, es, 0, "ERROR: Windows route add ipv6 command failed");
4049 + netcmd_semaphore_release ();
4051 +#elif defined (TARGET_SOLARIS)
4053 + /* example: route delete -inet6 2001:db8::/32 somegateway */
4054 + /* GERT-TODO: this is untested, but should work */
4056 + argv_printf (&argv, "%s delete -inet6 %s/%d %s",
4062 + argv_msg (D_ROUTE, &argv);
4063 + openvpn_execve_check (&argv, es, 0, "ERROR: Solaris route delete -inet6 command failed");
4065 +#elif defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY)
4067 + argv_printf (&argv, "%s delete -inet6 %s/%d -iface %s",
4073 + argv_msg (D_ROUTE, &argv);
4074 + openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
4076 +#elif defined(TARGET_DARWIN)
4078 + argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d -iface %s",
4080 + network, r6->netbits, device );
4082 + argv_msg (D_ROUTE, &argv);
4083 + openvpn_execve_check (&argv, es, 0, "ERROR: *BSD route delete -inet6 command failed");
4085 +#elif defined(TARGET_OPENBSD)
4087 + argv_printf (&argv, "%s delete -inet6 %s -prefixlen %d %s",
4089 + network, r6->netbits, gateway );
4091 + argv_msg (D_ROUTE, &argv);
4092 + openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD route delete -inet6 command failed");
4094 +#elif defined(TARGET_NETBSD)
4096 + argv_printf (&argv, "%s delete -inet6 %s/%d %s",
4098 + network, r6->netbits, gateway );
4100 + argv_msg (D_ROUTE, &argv);
4101 + openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed");
4104 + msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system. Try putting your routes in a --route-down script");
4107 + argv_reset (&argv);
4111 diff -durN openvpn-2.2.2.orig/route.h openvpn-2.2.2/route.h
4112 --- openvpn-2.2.2.orig/route.h 2011-12-13 17:58:56.000000000 +0100
4113 +++ openvpn-2.2.2/route.h 2012-06-01 10:40:28.000000000 +0200
4115 struct route_option routes[EMPTY_ARRAY_SIZE];
4118 +struct route_ipv6_option {
4119 + const char *prefix; /* e.g. "2001:db8:1::/64" */
4120 + const char *gateway; /* e.g. "2001:db8:0::2" */
4121 + const char *metric; /* e.g. "5" */
4124 +struct route_ipv6_option_list {
4125 + unsigned int flags;
4128 + struct route_ipv6_option routes_ipv6[EMPTY_ARRAY_SIZE];
4133 const struct route_option *option;
4134 @@ -113,6 +126,31 @@
4135 struct route routes[EMPTY_ARRAY_SIZE];
4138 +struct route_ipv6 {
4140 + const struct route_ipv6_option *option;
4141 + struct in6_addr network;
4142 + unsigned int netbits;
4143 + struct in6_addr gateway;
4144 + bool metric_defined;
4148 +struct route_ipv6_list {
4149 + bool routes_added;
4150 + unsigned int flags;
4151 + int default_metric;
4152 + bool default_metric_defined;
4153 + struct in6_addr remote_endpoint_ipv6;
4154 + bool remote_endpoint_defined;
4155 + bool did_redirect_default_gateway; /* TODO (?) */
4156 + bool did_local; /* TODO (?) */
4159 + struct route_ipv6 routes_ipv6[EMPTY_ARRAY_SIZE];
4164 /* internal OpenVPN route */
4166 @@ -120,15 +158,25 @@
4168 struct iroute *next;
4171 +struct iroute_ipv6 {
4172 + struct in6_addr network;
4173 + unsigned int netbits;
4174 + struct iroute_ipv6 *next;
4178 struct route_option_list *new_route_option_list (const int max_routes, struct gc_arena *a);
4179 +struct route_ipv6_option_list *new_route_ipv6_option_list (const int max_routes, struct gc_arena *a);
4180 struct route_option_list *clone_route_option_list (const struct route_option_list *src, struct gc_arena *a);
4181 void copy_route_option_list (struct route_option_list *dest, const struct route_option_list *src);
4183 struct route_list *new_route_list (const int max_routes, struct gc_arena *a);
4184 +struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_arena *a);
4186 void add_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
4187 +void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
4188 +void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es);
4190 void add_route_to_option_list (struct route_option_list *l,
4191 const char *network,
4192 @@ -136,6 +184,11 @@
4193 const char *gateway,
4194 const char *metric);
4196 +void add_route_ipv6_to_option_list (struct route_ipv6_option_list *l,
4197 + const char *prefix,
4198 + const char *gateway,
4199 + const char *metric);
4201 bool init_route_list (struct route_list *rl,
4202 const struct route_option_list *opt,
4203 const char *remote_endpoint,
4204 @@ -143,21 +196,30 @@
4205 in_addr_t remote_host,
4206 struct env_set *es);
4208 +bool init_route_ipv6_list (struct route_ipv6_list *rl6,
4209 + const struct route_ipv6_option_list *opt6,
4210 + const char *remote_endpoint,
4211 + int default_metric,
4212 + struct env_set *es);
4214 void route_list_add_default_gateway (struct route_list *rl,
4216 const in_addr_t addr);
4218 void add_routes (struct route_list *rl,
4219 + struct route_ipv6_list *rl6,
4220 const struct tuntap *tt,
4222 const struct env_set *es);
4224 void delete_routes (struct route_list *rl,
4225 + struct route_ipv6_list *rl6,
4226 const struct tuntap *tt,
4228 const struct env_set *es);
4230 void setenv_routes (struct env_set *es, const struct route_list *rl);
4231 +void setenv_routes_ipv6 (struct env_set *es, const struct route_ipv6_list *rl6);
4233 bool is_special_addr (const char *addr_str);
4235 diff -durN openvpn-2.2.2.orig/socket.c openvpn-2.2.2/socket.c
4236 --- openvpn-2.2.2.orig/socket.c 2011-12-13 17:58:56.000000000 +0100
4237 +++ openvpn-2.2.2/socket.c 2012-06-01 10:40:28.000000000 +0200
4238 @@ -342,6 +342,24 @@
4243 +ipv6_addr_safe (const char *ipv6_text_addr)
4245 + /* verify non-NULL */
4246 + if (!ipv6_text_addr)
4249 + /* verify length is within limits */
4250 + if (strlen (ipv6_text_addr) > INET6_ADDRSTRLEN )
4253 + /* verify that string will convert to IPv6 address */
4255 + struct in6_addr a6;
4256 + return inet_pton( AF_INET6, ipv6_text_addr, &a6 ) == 1;
4261 dns_addr_safe (const char *addr)
4263 @@ -2032,6 +2050,55 @@
4268 + * Convert an in6_addr in host byte order
4269 + * to an ascii representation of an IPv6 address
4272 +print_in6_addr (struct in6_addr a6, unsigned int flags, struct gc_arena *gc)
4274 + struct buffer out = alloc_buf_gc (64, gc);
4275 + char tmp_out_buf[64]; /* inet_ntop wants pointer to buffer */
4277 + if ( memcmp(&a6, &in6addr_any, sizeof(a6)) != 0 ||
4278 + !(flags & IA_EMPTY_IF_UNDEF))
4280 + inet_ntop (AF_INET6, &a6, tmp_out_buf, sizeof(tmp_out_buf)-1);
4281 + buf_printf (&out, "%s", tmp_out_buf );
4283 + return BSTR (&out);
4286 +/* add some offset to an ipv6 address
4287 + * (add in steps of 32 bits, taking overflow into next round)
4290 +# ifdef TARGET_SOLARIS
4291 +# define s6_addr32 _S6_un._S6_u32
4293 +# define s6_addr32 __u6_addr.__u6_addr32
4297 +# define UINT32_MAX (4294967295U)
4299 +struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add )
4304 + for( i=3; i>=0 && add > 0 ; i-- )
4306 + h = ntohl( base.s6_addr32[i] );
4307 + base.s6_addr32[i] = htonl( (h+add) & UINT32_MAX );
4308 + /* 32-bit overrun?
4309 + * caveat: can't do "h+add > UINT32_MAX" with 32bit math!
4311 + add = ( h > UINT32_MAX - add )? 1: 0;
4316 /* set environmental variables for ip/port in *addr */
4318 setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const bool flags)
4319 @@ -2337,6 +2404,58 @@
4324 + * inet_ntop() and inet_pton() wrap-implementations using
4325 + * WSAAddressToString() and WSAStringToAddress() functions
4328 +inet_ntop(int af, const void *src, char *dst, socklen_t size)
4330 + struct sockaddr_storage ss;
4331 + unsigned long s = size;
4334 + ss.ss_family = af;
4338 + ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
4341 + ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
4346 + // cannot direclty use &size because of strict aliasing rules
4347 + return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)?
4352 +inet_pton(int af, const char *src, void *dst)
4354 + struct sockaddr_storage ss;
4355 + int size = sizeof(ss);
4356 + char src_copy[INET6_ADDRSTRLEN+1];
4359 + // stupid non-const API
4360 + strncpynt(src_copy, src, INET6_ADDRSTRLEN+1);
4362 + if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
4365 + *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
4368 + *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
4376 socket_recv_queue (struct link_socket *sock, int maxsize)
4378 diff -durN openvpn-2.2.2.orig/socket.h openvpn-2.2.2/socket.h
4379 --- openvpn-2.2.2.orig/socket.h 2011-12-13 17:58:56.000000000 +0100
4380 +++ openvpn-2.2.2/socket.h 2012-06-01 10:40:28.000000000 +0200
4382 #define IA_EMPTY_IF_UNDEF (1<<0)
4383 #define IA_NET_ORDER (1<<1)
4384 const char *print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc);
4385 +const char *print_in6_addr (struct in6_addr addr6, unsigned int flags, struct gc_arena *gc);
4386 +struct in6_addr add_in6_addr( struct in6_addr base, uint32_t add );
4388 #define SA_IP_PORT (1<<0)
4389 #define SA_SET_IF_NONZERO (1<<1)
4391 bool ip_addr_dotted_quad_safe (const char *dotted_quad);
4392 bool ip_or_dns_addr_safe (const char *addr, const bool allow_fqdn);
4393 bool mac_addr_safe (const char *mac_addr);
4394 +bool ipv6_addr_safe (const char *ipv6_text_addr);
4396 socket_descriptor_t create_socket_tcp (void);
4398 diff -durN openvpn-2.2.2.orig/syshead.h openvpn-2.2.2/syshead.h
4399 --- openvpn-2.2.2.orig/syshead.h 2011-12-13 17:58:56.000000000 +0100
4400 +++ openvpn-2.2.2/syshead.h 2012-06-01 10:40:28.000000000 +0200
4403 * Only include if not during configure
4406 +/* USE_PF_INET6: win32 ipv6 exists only after 0x0501 (XP) */
4407 +#define WINVER 0x0501
4409 #ifndef PACKAGE_NAME
4414 #include <iphlpapi.h>
4415 #include <wininet.h>
4416 +/* The following two headers are needed of USE_PF_INET6 */
4417 +#include <winsock2.h>
4418 +#include <ws2tcpip.h>
4421 #ifdef HAVE_SYS_MMAN_H
4422 diff -durN openvpn-2.2.2.orig/tun.c openvpn-2.2.2/tun.c
4423 --- openvpn-2.2.2.orig/tun.c 2011-12-13 17:58:56.000000000 +0100
4424 +++ openvpn-2.2.2/tun.c 2012-06-01 10:46:55.000000000 +0200
4427 const in_addr_t netmask,
4428 const unsigned int flags);
4429 +static void netsh_command (const struct argv *a, int n);
4431 static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc);
4435 #ifdef TARGET_SOLARIS
4436 -static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual);
4437 +static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual, bool unplumb_inet6);
4438 #include <stropts.h>
4441 @@ -129,30 +130,6 @@
4446 - * Called by the open_tun function of OSes to check if we
4447 - * explicitly support IPv6.
4449 - * In this context, explicit means that the OS expects us to
4450 - * do something special to the tun socket in order to support
4451 - * IPv6, i.e. it is not transparent.
4453 - * ipv6_explicitly_supported should be set to false if we don't
4454 - * have any explicit IPv6 code in the tun device handler.
4456 - * If ipv6_explicitly_supported is true, then we have explicit
4457 - * OS-specific tun dev code for handling IPv6. If so, tt->ipv6
4458 - * is set according to the --tun-ipv6 command line option.
4461 -ipv6_support (bool ipv6, bool ipv6_explicitly_supported, struct tuntap* tt)
4464 - if (ipv6_explicitly_supported)
4467 - msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
4470 /* --ifconfig-nowarn disables some options sanity checking */
4471 static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)";
4473 int topology, /* one of the TOP_x values */
4474 const char *ifconfig_local_parm, /* --ifconfig parm 1 */
4475 const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
4476 + const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
4477 + const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
4478 in_addr_t local_public,
4479 in_addr_t remote_public,
4480 const bool strict_warn,
4481 @@ -537,6 +516,40 @@
4483 tt->did_ifconfig_setup = true;
4486 + if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm)
4488 + const char *ifconfig_ipv6_local = NULL;
4489 + const char *ifconfig_ipv6_remote = NULL;
4492 + * Convert arguments to binary IPv6 addresses.
4495 + if ( inet_pton( AF_INET6, ifconfig_ipv6_local_parm, &tt->local_ipv6 ) != 1 ||
4496 + inet_pton( AF_INET6, ifconfig_ipv6_remote_parm, &tt->remote_ipv6 ) != 1 )
4498 + msg( M_FATAL, "init_tun: problem converting IPv6 ifconfig addresses %s and %s to binary", ifconfig_ipv6_local_parm, ifconfig_ipv6_remote_parm );
4500 + tt->netbits_ipv6 = 64;
4503 + * Set ifconfig parameters
4505 + ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
4506 + ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
4509 + * Set environmental variables with ifconfig parameters.
4513 + setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
4514 + setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
4516 + tt->did_ifconfig_ipv6_setup = true;
4522 @@ -559,6 +572,40 @@
4526 +#if defined(TARGET_WIN32) || \
4527 + defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD)
4529 +/* some of the platforms will auto-add a "network route" pointing
4530 + * to the interface on "ifconfig tunX 2001:db8::1/64", others need
4531 + * an extra call to "route add..."
4532 + * -> helper function to simplify code below
4534 +void add_route_connected_v6_net(struct tuntap * tt,
4535 + const struct env_set *es)
4537 + struct route_ipv6 r6;
4539 + r6.defined = true;
4540 + r6.network = tt->local_ipv6;
4541 + r6.netbits = tt->netbits_ipv6;
4542 + r6.gateway = tt->local_ipv6;
4543 + add_route_ipv6 (&r6, tt, 0, es);
4546 +void delete_route_connected_v6_net(struct tuntap * tt,
4547 + const struct env_set *es)
4549 + struct route_ipv6 r6;
4551 + r6.defined = true;
4552 + r6.network = tt->local_ipv6;
4553 + r6.netbits = tt->netbits_ipv6;
4554 + r6.gateway = tt->local_ipv6;
4555 + delete_route_ipv6 (&r6, tt, 0, es);
4560 /* execute the ifconfig command through the shell */
4562 do_ifconfig (struct tuntap *tt,
4563 @@ -574,10 +621,16 @@
4564 const char *ifconfig_local = NULL;
4565 const char *ifconfig_remote_netmask = NULL;
4566 const char *ifconfig_broadcast = NULL;
4567 + const char *ifconfig_ipv6_local = NULL;
4568 + const char *ifconfig_ipv6_remote = NULL;
4569 + bool do_ipv6 = false;
4574 + msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
4575 + tt->ipv6, tt->did_ifconfig_ipv6_setup );
4578 * We only handle TUN/TAP devices here, not --dev null devices.
4580 @@ -589,6 +642,13 @@
4581 ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
4582 ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
4584 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
4586 + ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
4587 + ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
4592 * If TAP-style device, generate broadcast address.
4594 @@ -647,7 +707,19 @@
4595 argv_msg (M_INFO, &argv);
4596 openvpn_execve_check (&argv, es, S_FATAL, "Linux ip addr add failed");
4598 - tt->did_ifconfig = true;
4601 + argv_printf( &argv,
4602 + "%s -6 addr add %s/%d dev %s",
4604 + ifconfig_ipv6_local,
4608 + argv_msg (M_INFO, &argv);
4609 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ip -6 addr add failed");
4611 + tt->did_ifconfig = true;
4615 @@ -670,6 +742,18 @@
4617 argv_msg (M_INFO, &argv);
4618 openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig failed");
4621 + argv_printf (&argv,
4622 + "%s %s inet6 add %s/%d",
4625 + ifconfig_ipv6_local,
4628 + argv_msg (M_INFO, &argv);
4629 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig inet6 failed");
4631 tt->did_ifconfig = true;
4633 #endif /*CONFIG_FEATURE_IPROUTE*/
4636 argv_msg (M_INFO, &argv);
4637 if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-1 failed"))
4638 - solaris_error_close (tt, es, actual);
4639 + solaris_error_close (tt, es, actual, false);
4642 "%s %s netmask 255.255.255.255",
4643 @@ -725,7 +809,53 @@
4645 argv_msg (M_INFO, &argv);
4646 if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-2 failed"))
4647 - solaris_error_close (tt, es, actual);
4648 + solaris_error_close (tt, es, actual, false);
4652 + argv_printf (&argv, "%s %s inet6 unplumb",
4653 + IFCONFIG_PATH, actual );
4654 + argv_msg (M_INFO, &argv);
4655 + openvpn_execve_check (&argv, es, 0, NULL);
4657 + if ( tt->type == DEV_TYPE_TUN )
4659 + argv_printf (&argv,
4660 + "%s %s inet6 plumb %s/%d %s up",
4663 + ifconfig_ipv6_local,
4665 + ifconfig_ipv6_remote
4668 + else /* tap mode */
4670 + /* base IPv6 tap interface needs to be brought up first
4672 + argv_printf (&argv, "%s %s inet6 plumb up",
4673 + IFCONFIG_PATH, actual );
4674 + argv_msg (M_INFO, &argv);
4675 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 (prepare) failed"))
4676 + solaris_error_close (tt, es, actual, true);
4678 + /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
4679 + * after the system has noticed the interface and fired up
4680 + * the DHCPv6 client - but this takes quite a while, and the
4681 + * server will ignore the DHCPv6 packets anyway. So we don't.
4684 + /* static IPv6 addresses need to go to a subinterface (tap0:1)
4686 + argv_printf (&argv,
4687 + "%s %s inet6 addif %s/%d up",
4688 + IFCONFIG_PATH, actual,
4689 + ifconfig_ipv6_local, tt->netbits_ipv6 );
4691 + argv_msg (M_INFO, &argv);
4692 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 failed"))
4693 + solaris_error_close (tt, es, actual, true);
4696 if (!tun && tt->topology == TOP_SUBNET)
4698 @@ -787,10 +917,42 @@
4700 argv_msg (M_INFO, &argv);
4701 openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig failed");
4704 + argv_printf (&argv,
4705 + "%s %s inet6 %s/%d",
4708 + ifconfig_ipv6_local,
4711 + argv_msg (M_INFO, &argv);
4712 + openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig inet6 failed");
4714 + /* and, hooray, we explicitely need to add a route... */
4715 + add_route_connected_v6_net(tt, es);
4717 tt->did_ifconfig = true;
4719 #elif defined(TARGET_NETBSD)
4721 +/* whether or not NetBSD can do IPv6 can be seen by the availability of
4722 + * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
4725 +# define NETBSD_MULTI_AF
4728 + /* as on OpenBSD and Darwin, destroy and re-create tun<x> interface
4730 + argv_printf (&argv, "%s %s destroy", IFCONFIG_PATH, actual );
4731 + argv_msg (M_INFO, &argv);
4732 + openvpn_execve_check (&argv, es, 0, "NetBSD ifconfig destroy failed");
4734 + argv_printf (&argv, "%s %s create", IFCONFIG_PATH, actual );
4735 + argv_msg (M_INFO, &argv);
4736 + openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig create failed");
4740 "%s %s %s %s mtu %d netmask 255.255.255.255 up",
4741 @@ -817,6 +979,27 @@
4743 argv_msg (M_INFO, &argv);
4744 openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig failed");
4748 +#ifdef NETBSD_MULTI_AF
4749 + argv_printf (&argv,
4750 + "%s %s inet6 %s/%d",
4753 + ifconfig_ipv6_local,
4756 + argv_msg (M_INFO, &argv);
4757 + openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig inet6 failed");
4759 + /* and, hooray, we explicitely need to add a route... */
4760 + add_route_connected_v6_net(tt, es);
4762 + msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 (if your system is newer, recompile openvpn)" );
4766 tt->did_ifconfig = true;
4768 #elif defined(TARGET_DARWIN)
4769 @@ -882,6 +1065,22 @@
4770 add_route (&r, tt, 0, es);
4775 + argv_printf (&argv,
4776 + "%s %s inet6 %s/%d",
4779 + ifconfig_ipv6_local,
4782 + argv_msg (M_INFO, &argv);
4783 + openvpn_execve_check (&argv, es, S_FATAL, "MacOS X ifconfig inet6 failed");
4785 + /* and, hooray, we explicitely need to add a route... */
4786 + add_route_connected_v6_net(tt, es);
4789 #elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
4791 /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
4792 @@ -920,6 +1119,19 @@
4793 add_route (&r, tt, 0, es);
4798 + argv_printf (&argv,
4799 + "%s %s inet6 %s/%d",
4802 + ifconfig_ipv6_local,
4805 + argv_msg (M_INFO, &argv);
4806 + openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed");
4809 #elif defined (WIN32)
4812 @@ -959,6 +1171,34 @@
4813 tt->did_ifconfig = true;
4816 + /* IPv6 always uses "netsh" interface */
4819 + char * saved_actual;
4821 + if (!strcmp (actual, "NULL"))
4822 + msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than one TAP-Win32 adapter, you must also specify --dev-node");
4824 + /* example: netsh interface ipv6 set address MyTap 2001:608:8003::d store=active */
4825 + argv_printf (&argv,
4826 + "%s%sc interface ipv6 set address %s %s store=active",
4827 + get_win_sys_path(),
4828 + NETSH_PATH_SUFFIX,
4830 + ifconfig_ipv6_local );
4832 + netsh_command (&argv, 4);
4834 + /* explicit route needed */
4835 + /* on windows, OpenVPN does ifconfig first, open_tun later, so
4836 + * tt->actual_name might not yet be initialized, but routing code
4837 + * needs to know interface name - point to "actual", restore later
4839 + saved_actual = tt->actual_name;
4840 + tt->actual_name = (char*) actual;
4841 + add_route_connected_v6_net(tt, es);
4842 + tt->actual_name = saved_actual;
4845 msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
4847 @@ -991,14 +1231,16 @@
4850 open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
4851 - bool ipv6, bool ipv6_explicitly_supported, bool dynamic,
4852 + bool ipv6_explicitly_supported, bool dynamic,
4856 char dynamic_name[256];
4857 bool dynamic_opened = false;
4859 - ipv6_support (ipv6, ipv6_explicitly_supported, tt);
4861 + if ( tt->ipv6 && ! ipv6_explicitly_supported )
4862 + msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
4864 if (tt->type == DEV_TYPE_NULL)
4866 @@ -1094,16 +1336,16 @@
4870 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
4871 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
4876 - * Set tt->ipv6 to true if
4877 - * (a) we have the capability of supporting --tun-ipv6, and
4878 - * (b) --tun-ipv6 was specified.
4879 + /* warn if a very old linux version is used & --tun-ipv6 set
4881 - ipv6_support (ipv6, LINUX_IPV6, tt);
4882 +#if LINUX_IPV6 == 0
4884 + msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
4888 * We handle --dev null specially, we do not open /dev/null for this.
4889 @@ -1222,9 +1464,9 @@
4893 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
4894 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
4896 - open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
4897 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
4900 #endif /* HAVE_LINUX_IF_TUN_H */
4901 @@ -1244,7 +1486,7 @@
4905 -tuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
4906 +tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
4910 @@ -1252,7 +1494,7 @@
4912 tt->type = dev_type_enum (dev, dev_type);
4913 tt->options = *options;
4914 - open_tun (dev, dev_type, dev_node, ipv6, tt);
4915 + open_tun (dev, dev_type, dev_node, tt);
4916 if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
4917 msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
4918 if (username != NULL)
4919 @@ -1395,7 +1637,7 @@
4923 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
4924 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
4926 int if_fd, ip_muxid, arp_muxid, arp_fd, ppa = -1;
4928 @@ -1406,8 +1648,11 @@
4930 struct strioctl strioc_if, strioc_ppa;
4932 - ipv6_support (ipv6, true, tt);
4933 - memset(&ifr, 0x0, sizeof(ifr));
4934 + /* improved generic TUN/TAP driver from
4935 + * http://www.whiteboard.ne.jp/~admin2/tuntap/
4936 + * has IPv6 support
4940 if (tt->type == DEV_TYPE_NULL)
4942 @@ -1561,6 +1806,18 @@
4946 + /* IPv6 interfaces need to be 'manually' de-configured */
4947 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
4950 + argv_init (&argv);
4951 + argv_printf( &argv, "%s %s inet6 unplumb",
4952 + IFCONFIG_PATH, tt->actual_name );
4953 + argv_msg (M_INFO, &argv);
4954 + openvpn_execve_check (&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed");
4955 + argv_reset (&argv);
4961 @@ -1613,11 +1870,20 @@
4965 -solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual)
4966 +solaris_error_close (struct tuntap *tt, const struct env_set *es,
4967 + const char *actual, bool unplumb_inet6 )
4972 + if (unplumb_inet6)
4974 + argv_printf( &argv, "%s %s inet6 unplumb",
4975 + IFCONFIG_PATH, actual );
4976 + argv_msg (M_INFO, &argv);
4977 + openvpn_execve_check (&argv, es, 0, "Solaris ifconfig inet6 unplumb failed");
4983 @@ -1674,9 +1940,9 @@
4987 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
4988 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
4990 - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
4991 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
4993 /* Enable multicast on the interface */
4995 @@ -1697,12 +1963,31 @@
4999 +/* the current way OpenVPN handles tun devices on OpenBSD leads to
5000 + * lingering tunX interfaces after close -> for a full cleanup, they
5001 + * need to be explicitely destroyed
5005 close_tun (struct tuntap* tt)
5009 + struct gc_arena gc = gc_new ();
5012 + /* setup command, close tun dev (clears tt->actual_name!), run command
5015 + argv_init (&argv);
5016 + argv_printf (&argv, "%s %s destroy",
5017 + IFCONFIG_PATH, tt->actual_name);
5019 close_tun_generic (tt);
5021 + argv_msg (M_INFO, &argv);
5022 + openvpn_execve_check (&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)");
5027 @@ -1765,33 +2050,51 @@
5028 #elif defined(TARGET_NETBSD)
5031 - * NetBSD does not support IPv6 on tun out of the box,
5032 - * but there exists a patch. When this patch is applied,
5033 - * only two things are left to openvpn:
5034 - * 1. Activate multicasting (this has already been done
5035 - * before by the kernel, but we make sure that nobody
5036 - * has deactivated multicasting inbetween.
5037 - * 2. Deactivate "link layer mode" (otherwise NetBSD
5038 - * prepends the address family to the packet, and we
5039 - * would run into the same trouble as with OpenBSD.
5040 + * NetBSD before 4.0 does not support IPv6 on tun out of the box,
5041 + * but there exists a patch (sys/net/if_tun.c, 1.79->1.80, see PR 32944).
5043 + * NetBSD 4.0 and up do, but we need to put the tun interface into
5044 + * "multi_af" mode, which will prepend the address family to all packets
5045 + * (same as OpenBSD and FreeBSD). If this is not enabled, the kernel
5046 + * silently drops all IPv6 packets on output and gets confused on input.
5048 + * On earlier versions, multi_af is not available at all, so we have
5049 + * two different NetBSD code variants here :-(
5054 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
5055 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5057 - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
5058 +#ifdef NETBSD_MULTI_AF
5059 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
5061 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
5066 int i = IFF_POINTOPOINT|IFF_MULTICAST;
5067 ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */
5069 ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */
5071 +#ifdef NETBSD_MULTI_AF
5073 + if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
5075 + msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
5082 close_tun (struct tuntap *tt)
5084 + /* TODO: we really should cleanup non-persistant tunX with
5085 + * "ifconfig tunX destroy" here...
5089 close_tun_generic (tt);
5090 @@ -1799,6 +2102,65 @@
5094 +#ifdef NETBSD_MULTI_AF
5097 +netbsd_modify_read_write_return (int len)
5100 + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
5106 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
5108 + if (tt->type == DEV_TYPE_TUN)
5111 + struct iovec iv[2];
5112 + struct openvpn_iphdr *iph;
5114 + iph = (struct openvpn_iphdr *) buf;
5116 + if (tt->ipv6 && OPENVPN_IPH_GET_VER(iph->version_len) == 6)
5117 + type = htonl (AF_INET6);
5119 + type = htonl (AF_INET);
5121 + iv[0].iov_base = (char *)&type;
5122 + iv[0].iov_len = sizeof (type);
5123 + iv[1].iov_base = buf;
5124 + iv[1].iov_len = len;
5126 + return netbsd_modify_read_write_return (writev (tt->fd, iv, 2));
5129 + return write (tt->fd, buf, len);
5133 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
5135 + if (tt->type == DEV_TYPE_TUN)
5138 + struct iovec iv[2];
5140 + iv[0].iov_base = (char *)&type;
5141 + iv[0].iov_len = sizeof (type);
5142 + iv[1].iov_base = buf;
5143 + iv[1].iov_len = len;
5145 + return netbsd_modify_read_write_return (readv (tt->fd, iv, 2));
5148 + return read (tt->fd, buf, len);
5151 +#else /* not NETBSD_MULTI_AF -> older code, IPv4 only */
5154 write_tun (struct tuntap* tt, uint8_t *buf, int len)
5156 @@ -1810,6 +2172,7 @@
5158 return read (tt->fd, buf, len);
5160 +#endif /* NETBSD_MULTI_AF */
5162 #elif defined(TARGET_FREEBSD)
5164 @@ -1823,9 +2186,9 @@
5168 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
5169 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5171 - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
5172 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
5174 if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
5176 @@ -1911,9 +2274,9 @@
5180 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
5181 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5183 - open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt);
5184 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
5188 @@ -1982,6 +2345,61 @@
5189 return read (tt->fd, buf, len);
5192 +#elif defined(TARGET_DARWIN)
5194 +/* Darwin (MacOS X) is mostly "just use the generic stuff", but there
5195 + * is always one caveat...:
5197 + * If IPv6 is configured, and the tun device is closed, the IPv6 address
5198 + * configured to the tun interface changes to a lingering /128 route
5199 + * pointing to lo0. Need to unconfigure... (observed on 10.5)
5203 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5205 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
5209 +close_tun (struct tuntap* tt)
5213 + struct gc_arena gc = gc_new ();
5215 + argv_init (&argv);
5217 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
5219 + const char * ifconfig_ipv6_local =
5220 + print_in6_addr (tt->local_ipv6, 0, &gc);
5222 + argv_printf (&argv, "%s delete -inet6 %s",
5223 + ROUTE_PATH, ifconfig_ipv6_local );
5224 + argv_msg (M_INFO, &argv);
5225 + openvpn_execve_check (&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)");
5228 + close_tun_generic (tt);
5230 + argv_reset (&argv);
5236 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
5238 + return write (tt->fd, buf, len);
5242 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
5244 + return read (tt->fd, buf, len);
5247 #elif defined(WIN32)
5250 @@ -3967,7 +4385,7 @@
5254 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
5255 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5257 struct gc_arena gc = gc_new ();
5258 char device_path[256];
5259 @@ -3978,7 +4396,7 @@
5261 /*netcmd_semaphore_lock ();*/
5263 - ipv6_support (ipv6, false, tt);
5264 + msg( M_INFO, "open_tun, tt->ipv6=%d", tt->ipv6 );
5266 if (tt->type == DEV_TYPE_NULL)
5268 @@ -4108,6 +4526,16 @@
5270 msg( M_FATAL, "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade to Tap-Win32 9.9 (2.2.2 release or later) or use TAP mode", (int) info[0], (int) info[1] );
5273 + /* usage of numeric constants is ugly, but this is really tied to
5274 + * *this* version of the driver
5276 + if ( tt->ipv6 && tt->type == DEV_TYPE_TUN &&
5277 + info[0] == 9 && info[1] < 8)
5279 + msg( M_INFO, "WARNING: Tap-Win32 driver version %d.%d does not support IPv6 in TUN mode. IPv6 will be disabled. Upgrade to Tap-Win32 9.8 (2.2-beta3 release or later) or use TAP mode to get IPv6", (int) info[0], (int) info[1] );
5284 /* get driver MTU */
5285 @@ -4432,6 +4860,26 @@
5289 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
5292 + argv_init (&argv);
5294 + /* remove route pointing to interface */
5295 + delete_route_connected_v6_net(tt, NULL);
5297 + /* netsh interface ipv6 delete address \"%s\" %s */
5298 + const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
5299 + argv_printf (&argv,
5300 + "%s%sc interface ipv6 delete address %s %s",
5301 + get_win_sys_path(),
5302 + NETSH_PATH_SUFFIX,
5304 + ifconfig_ipv6_local );
5306 + netsh_command (&argv, 1);
5307 + argv_reset (&argv);
5310 if (tt->ipapi_context_defined)
5312 @@ -4535,9 +4983,9 @@
5316 -open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
5317 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
5319 - open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
5320 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
5324 diff -durN openvpn-2.2.2.orig/tun.c~ openvpn-2.2.2/tun.c~
5325 --- openvpn-2.2.2.orig/tun.c~ 1970-01-01 01:00:00.000000000 +0100
5326 +++ openvpn-2.2.2/tun.c~ 2012-06-01 10:45:07.000000000 +0200
5329 + * OpenVPN -- An application to securely tunnel IP networks
5330 + * over a single TCP/UDP port, with support for SSL/TLS-based
5331 + * session authentication and key exchange,
5332 + * packet encryption, packet authentication, and
5333 + * packet compression.
5335 + * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
5337 + * This program is free software; you can redistribute it and/or modify
5338 + * it under the terms of the GNU General Public License version 2
5339 + * as published by the Free Software Foundation.
5341 + * This program is distributed in the hope that it will be useful,
5342 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5343 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5344 + * GNU General Public License for more details.
5346 + * You should have received a copy of the GNU General Public License
5347 + * along with this program (see the file COPYING included with this
5348 + * distribution); if not, write to the Free Software Foundation, Inc.,
5349 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5353 + * Support routines for configuring and accessing TUN/TAP
5354 + * virtual network adapters.
5356 + * This file is based on the TUN/TAP driver interface routines
5357 + * from VTun by Maxim Krasnyansky <max_mk@yahoo.com>.
5360 +#include "syshead.h"
5363 +#include "fdmisc.h"
5364 +#include "common.h"
5366 +#include "socket.h"
5367 +#include "manage.h"
5371 +#include "memdbg.h"
5375 +/* #define SIMULATE_DHCP_FAILED */ /* simulate bad DHCP negotiation */
5377 +#define NI_TEST_FIRST (1<<0)
5378 +#define NI_IP_NETMASK (1<<1)
5379 +#define NI_OPTIONS (1<<2)
5381 +static void netsh_ifconfig (const struct tuntap_options *to,
5382 + const char *flex_name,
5383 + const in_addr_t ip,
5384 + const in_addr_t netmask,
5385 + const unsigned int flags);
5386 +static void netsh_command (const struct argv *a, int n);
5388 +static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc);
5392 +#ifdef TARGET_SOLARIS
5393 +static void solaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual, bool unplumb_inet6);
5394 +#include <stropts.h>
5398 +is_dev_type (const char *dev, const char *dev_type, const char *match_type)
5400 + ASSERT (match_type);
5404 + return !strcmp (dev_type, match_type);
5406 + return !strncmp (dev, match_type, strlen (match_type));
5410 +dev_type_enum (const char *dev, const char *dev_type)
5412 + if (is_dev_type (dev, dev_type, "tun"))
5413 + return DEV_TYPE_TUN;
5414 + else if (is_dev_type (dev, dev_type, "tap"))
5415 + return DEV_TYPE_TAP;
5416 + else if (is_dev_type (dev, dev_type, "null"))
5417 + return DEV_TYPE_NULL;
5419 + return DEV_TYPE_UNDEF;
5423 +dev_type_string (const char *dev, const char *dev_type)
5425 + switch (dev_type_enum (dev, dev_type))
5427 + case DEV_TYPE_TUN:
5429 + case DEV_TYPE_TAP:
5431 + case DEV_TYPE_NULL:
5434 + return "[unknown-dev-type]";
5439 + * Try to predict the actual TUN/TAP device instance name,
5440 + * before the device is actually opened.
5443 +guess_tuntap_dev (const char *dev,
5444 + const char *dev_type,
5445 + const char *dev_node,
5446 + struct gc_arena *gc)
5449 + const int dt = dev_type_enum (dev, dev_type);
5450 + if (dt == DEV_TYPE_TUN || dt == DEV_TYPE_TAP)
5452 + return netsh_get_id (dev_node, gc);
5456 + /* default case */
5461 +/* --ifconfig-nowarn disables some options sanity checking */
5462 +static const char ifconfig_warn_how_to_silence[] = "(silence this warning with --ifconfig-nowarn)";
5465 + * If !tun, make sure ifconfig_remote_netmask looks
5468 + * If tun, make sure ifconfig_remote_netmask looks
5469 + * like an IPv4 address.
5472 +ifconfig_sanity_check (bool tun, in_addr_t addr, int topology)
5474 + struct gc_arena gc = gc_new ();
5475 + const bool looks_like_netmask = ((addr & 0xFF000000) == 0xFF000000);
5478 + if (looks_like_netmask && (topology == TOP_NET30 || topology == TOP_P2P))
5479 + msg (M_WARN, "WARNING: Since you are using --dev tun with a point-to-point topology, the second argument to --ifconfig must be an IP address. You are using something (%s) that looks more like a netmask. %s",
5480 + print_in_addr_t (addr, 0, &gc),
5481 + ifconfig_warn_how_to_silence);
5485 + if (!looks_like_netmask)
5486 + msg (M_WARN, "WARNING: Since you are using --dev tap, the second argument to --ifconfig must be a netmask, for example something like 255.255.255.0. %s",
5487 + ifconfig_warn_how_to_silence);
5493 + * For TAP-style devices, generate a broadcast address.
5496 +generate_ifconfig_broadcast_addr (in_addr_t local,
5497 + in_addr_t netmask)
5499 + return local | ~netmask;
5503 + * Check that --local and --remote addresses do not
5504 + * clash with ifconfig addresses or subnet.
5507 +check_addr_clash (const char *name,
5511 + in_addr_t remote_netmask)
5513 + struct gc_arena gc = gc_new ();
5515 + msg (M_INFO, "CHECK_ADDR_CLASH type=%d public=%s local=%s, remote_netmask=%s",
5517 + print_in_addr_t (public, 0, &gc),
5518 + print_in_addr_t (local, 0, &gc),
5519 + print_in_addr_t (remote_netmask, 0, &gc));
5524 + if (type == DEV_TYPE_TUN)
5526 + const in_addr_t test_netmask = 0xFFFFFF00;
5527 + const in_addr_t public_net = public & test_netmask;
5528 + const in_addr_t local_net = local & test_netmask;
5529 + const in_addr_t remote_net = remote_netmask & test_netmask;
5531 + if (public == local || public == remote_netmask)
5533 + "WARNING: --%s address [%s] conflicts with --ifconfig address pair [%s, %s]. %s",
5535 + print_in_addr_t (public, 0, &gc),
5536 + print_in_addr_t (local, 0, &gc),
5537 + print_in_addr_t (remote_netmask, 0, &gc),
5538 + ifconfig_warn_how_to_silence);
5540 + if (public_net == local_net || public_net == remote_net)
5542 + "WARNING: potential conflict between --%s address [%s] and --ifconfig address pair [%s, %s] -- this is a warning only that is triggered when local/remote addresses exist within the same /24 subnet as --ifconfig endpoints. %s",
5544 + print_in_addr_t (public, 0, &gc),
5545 + print_in_addr_t (local, 0, &gc),
5546 + print_in_addr_t (remote_netmask, 0, &gc),
5547 + ifconfig_warn_how_to_silence);
5549 + else if (type == DEV_TYPE_TAP)
5551 + const in_addr_t public_network = public & remote_netmask;
5552 + const in_addr_t virtual_network = local & remote_netmask;
5553 + if (public_network == virtual_network)
5555 + "WARNING: --%s address [%s] conflicts with --ifconfig subnet [%s, %s] -- local and remote addresses cannot be inside of the --ifconfig subnet. %s",
5557 + print_in_addr_t (public, 0, &gc),
5558 + print_in_addr_t (local, 0, &gc),
5559 + print_in_addr_t (remote_netmask, 0, &gc),
5560 + ifconfig_warn_how_to_silence);
5567 + * Issue a warning if ip/netmask (on the virtual IP network) conflicts with
5568 + * the settings on the local LAN. This is designed to flag issues where
5569 + * (for example) the OpenVPN server LAN is running on 192.168.1.x, but then
5570 + * an OpenVPN client tries to connect from a public location that is also running
5571 + * off of a router set to 192.168.1.x.
5574 +check_subnet_conflict (const in_addr_t ip,
5575 + const in_addr_t netmask,
5576 + const char *prefix)
5578 + struct gc_arena gc = gc_new ();
5579 + in_addr_t lan_gw = 0;
5580 + in_addr_t lan_netmask = 0;
5582 + if (get_default_gateway (&lan_gw, &lan_netmask))
5584 + const in_addr_t lan_network = lan_gw & lan_netmask;
5585 + const in_addr_t network = ip & netmask;
5587 + /* do the two subnets defined by network/netmask and lan_network/lan_netmask intersect? */
5588 + if ((network & lan_netmask) == lan_network
5589 + || (lan_network & netmask) == network)
5591 + msg (M_WARN, "WARNING: potential %s subnet conflict between local LAN [%s/%s] and remote VPN [%s/%s]",
5593 + print_in_addr_t (lan_network, 0, &gc),
5594 + print_in_addr_t (lan_netmask, 0, &gc),
5595 + print_in_addr_t (network, 0, &gc),
5596 + print_in_addr_t (netmask, 0, &gc));
5603 +warn_on_use_of_common_subnets (void)
5605 + struct gc_arena gc = gc_new ();
5606 + in_addr_t lan_gw = 0;
5607 + in_addr_t lan_netmask = 0;
5609 + if (get_default_gateway (&lan_gw, &lan_netmask))
5611 + const in_addr_t lan_network = lan_gw & lan_netmask;
5612 + if (lan_network == 0xC0A80000 || lan_network == 0xC0A80100)
5613 + msg (M_WARN, "NOTE: your local LAN uses the extremely common subnet address 192.168.0.x or 192.168.1.x. Be aware that this might create routing conflicts if you connect to the VPN server from public locations such as internet cafes that use the same subnet.");
5619 + * Complain if --dev tap and --ifconfig is used on an OS for which
5620 + * we don't have a custom tap ifconfig template below.
5625 + msg (M_FATAL, "Sorry but you cannot use --dev tap and --ifconfig together on this OS because I have not yet been programmed to understand the appropriate ifconfig syntax to use for TAP-style devices on this OS. Your best alternative is to use an --up script and do the ifconfig command manually.");
5629 + * Return a string to be used for options compatibility check
5633 +ifconfig_options_string (const struct tuntap* tt, bool remote, bool disable, struct gc_arena *gc)
5635 + struct buffer out = alloc_buf_gc (256, gc);
5636 + if (tt->did_ifconfig_setup && !disable)
5638 + if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
5640 + buf_printf (&out, "%s %s",
5641 + print_in_addr_t (tt->local & tt->remote_netmask, 0, gc),
5642 + print_in_addr_t (tt->remote_netmask, 0, gc));
5644 + else if (tt->type == DEV_TYPE_TUN)
5646 + const char *l, *r;
5649 + r = print_in_addr_t (tt->local, 0, gc);
5650 + l = print_in_addr_t (tt->remote_netmask, 0, gc);
5654 + l = print_in_addr_t (tt->local, 0, gc);
5655 + r = print_in_addr_t (tt->remote_netmask, 0, gc);
5657 + buf_printf (&out, "%s %s", r, l);
5660 + buf_printf (&out, "[undef]");
5662 + return BSTR (&out);
5666 + * Return a status string describing wait state.
5669 +tun_stat (const struct tuntap *tt, unsigned int rwflags, struct gc_arena *gc)
5671 + struct buffer out = alloc_buf_gc (64, gc);
5674 + if (rwflags & EVENT_READ)
5676 + buf_printf (&out, "T%s",
5677 + (tt->rwflags_debug & EVENT_READ) ? "R" : "r");
5679 + buf_printf (&out, "%s",
5680 + overlapped_io_state_ascii (&tt->reads));
5683 + if (rwflags & EVENT_WRITE)
5685 + buf_printf (&out, "T%s",
5686 + (tt->rwflags_debug & EVENT_WRITE) ? "W" : "w");
5688 + buf_printf (&out, "%s",
5689 + overlapped_io_state_ascii (&tt->writes));
5695 + buf_printf (&out, "T?");
5697 + return BSTR (&out);
5701 + * Return true for point-to-point topology, false for subnet topology
5704 +is_tun_p2p (const struct tuntap *tt)
5708 + if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
5710 + else if (tt->type == DEV_TYPE_TUN)
5713 + msg (M_FATAL, "Error: problem with tun vs. tap setting"); /* JYFIXME -- needs to be caught earlier, in init_tun? */
5719 + * Init tun/tap object.
5721 + * Set up tuntap structure for ifconfig,
5722 + * but don't execute yet.
5725 +init_tun (const char *dev, /* --dev option */
5726 + const char *dev_type, /* --dev-type option */
5727 + int topology, /* one of the TOP_x values */
5728 + const char *ifconfig_local_parm, /* --ifconfig parm 1 */
5729 + const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
5730 + const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 IPv6 */
5731 + const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 IPv6 */
5732 + in_addr_t local_public,
5733 + in_addr_t remote_public,
5734 + const bool strict_warn,
5735 + struct env_set *es)
5737 + struct gc_arena gc = gc_new ();
5738 + struct tuntap *tt;
5740 + ALLOC_OBJ (tt, struct tuntap);
5741 + clear_tuntap (tt);
5743 + tt->type = dev_type_enum (dev, dev_type);
5744 + tt->topology = topology;
5746 + if (ifconfig_local_parm && ifconfig_remote_netmask_parm)
5749 + const char *ifconfig_local = NULL;
5750 + const char *ifconfig_remote_netmask = NULL;
5751 + const char *ifconfig_broadcast = NULL;
5754 + * We only handle TUN/TAP devices here, not --dev null devices.
5756 + tun = is_tun_p2p (tt);
5759 + * Convert arguments to binary IPv4 addresses.
5762 + tt->local = getaddr (
5764 + | GETADDR_HOST_ORDER
5765 + | GETADDR_FATAL_ON_SIGNAL
5767 + ifconfig_local_parm,
5772 + tt->remote_netmask = getaddr (
5773 + (tun ? GETADDR_RESOLVE : 0)
5774 + | GETADDR_HOST_ORDER
5775 + | GETADDR_FATAL_ON_SIGNAL
5777 + ifconfig_remote_netmask_parm,
5783 + * Look for common errors in --ifconfig parms
5787 + ifconfig_sanity_check (tt->type == DEV_TYPE_TUN, tt->remote_netmask, tt->topology);
5790 + * If local_public or remote_public addresses are defined,
5791 + * make sure they do not clash with our virtual subnet.
5794 + check_addr_clash ("local",
5798 + tt->remote_netmask);
5800 + check_addr_clash ("remote",
5804 + tt->remote_netmask);
5806 + if (tt->type == DEV_TYPE_TAP || (tt->type == DEV_TYPE_TUN && tt->topology == TOP_SUBNET))
5807 + check_subnet_conflict (tt->local, tt->remote_netmask, "TUN/TAP adapter");
5808 + else if (tt->type == DEV_TYPE_TUN)
5809 + check_subnet_conflict (tt->local, ~0, "TUN/TAP adapter");
5813 + * Set ifconfig parameters
5815 + ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
5816 + ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
5819 + * If TAP-style interface, generate broadcast address.
5823 + tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask);
5824 + ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
5828 + * Set environmental variables with ifconfig parameters.
5832 + setenv_str (es, "ifconfig_local", ifconfig_local);
5835 + setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask);
5839 + setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask);
5840 + setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast);
5844 + tt->did_ifconfig_setup = true;
5847 + if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm)
5849 + const char *ifconfig_ipv6_local = NULL;
5850 + const char *ifconfig_ipv6_remote = NULL;
5853 + * Convert arguments to binary IPv6 addresses.
5856 + if ( inet_pton( AF_INET6, ifconfig_ipv6_local_parm, &tt->local_ipv6 ) != 1 ||
5857 + inet_pton( AF_INET6, ifconfig_ipv6_remote_parm, &tt->remote_ipv6 ) != 1 )
5859 + msg( M_FATAL, "init_tun: problem converting IPv6 ifconfig addresses %s and %s to binary", ifconfig_ipv6_local_parm, ifconfig_ipv6_remote_parm );
5861 + tt->netbits_ipv6 = 64;
5864 + * Set ifconfig parameters
5866 + ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
5867 + ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
5870 + * Set environmental variables with ifconfig parameters.
5874 + setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local);
5875 + setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote);
5877 + tt->did_ifconfig_ipv6_setup = true;
5885 + * Platform specific tun initializations
5888 +init_tun_post (struct tuntap *tt,
5889 + const struct frame *frame,
5890 + const struct tuntap_options *options)
5892 + tt->options = *options;
5894 + overlapped_io_init (&tt->reads, frame, FALSE, true);
5895 + overlapped_io_init (&tt->writes, frame, TRUE, true);
5896 + tt->rw_handle.read = tt->reads.overlapped.hEvent;
5897 + tt->rw_handle.write = tt->writes.overlapped.hEvent;
5898 + tt->adapter_index = ~0;
5902 +#if defined(TARGET_WIN32) || \
5903 + defined(TARGET_DARWIN) || defined(TARGET_NETBSD) || defined(TARGET_OPENBSD)
5905 +/* some of the platforms will auto-add a "network route" pointing
5906 + * to the interface on "ifconfig tunX 2001:db8::1/64", others need
5907 + * an extra call to "route add..."
5908 + * -> helper function to simplify code below
5910 +void add_route_connected_v6_net(struct tuntap * tt,
5911 + const struct env_set *es)
5913 + struct route_ipv6 r6;
5915 + r6.defined = true;
5916 + r6.network = tt->local_ipv6;
5917 + r6.netbits = tt->netbits_ipv6;
5918 + r6.gateway = tt->local_ipv6;
5919 + add_route_ipv6 (&r6, tt, 0, es);
5922 +void delete_route_connected_v6_net(struct tuntap * tt,
5923 + const struct env_set *es)
5925 + struct route_ipv6 r6;
5927 + r6.defined = true;
5928 + r6.network = tt->local_ipv6;
5929 + r6.netbits = tt->netbits_ipv6;
5930 + r6.gateway = tt->local_ipv6;
5931 + delete_route_ipv6 (&r6, tt, 0, es);
5936 +/* execute the ifconfig command through the shell */
5938 +do_ifconfig (struct tuntap *tt,
5939 + const char *actual, /* actual device name */
5941 + const struct env_set *es)
5943 + struct gc_arena gc = gc_new ();
5945 + if (tt->did_ifconfig_setup)
5948 + const char *ifconfig_local = NULL;
5949 + const char *ifconfig_remote_netmask = NULL;
5950 + const char *ifconfig_broadcast = NULL;
5951 + const char *ifconfig_ipv6_local = NULL;
5952 + const char *ifconfig_ipv6_remote = NULL;
5953 + bool do_ipv6 = false;
5956 + argv_init (&argv);
5958 + msg( M_INFO, "do_ifconfig, tt->ipv6=%d, tt->did_ifconfig_ipv6_setup=%d",
5959 + tt->ipv6, tt->did_ifconfig_ipv6_setup );
5962 + * We only handle TUN/TAP devices here, not --dev null devices.
5964 + tun = is_tun_p2p (tt);
5967 + * Set ifconfig parameters
5969 + ifconfig_local = print_in_addr_t (tt->local, 0, &gc);
5970 + ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc);
5972 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
5974 + ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
5975 + ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc);
5980 + * If TAP-style device, generate broadcast address.
5983 + ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc);
5985 +#ifdef ENABLE_MANAGEMENT
5988 + management_set_state (management,
5989 + OPENVPN_STATE_ASSIGN_IP,
5997 +#if defined(TARGET_LINUX)
5998 +#ifdef CONFIG_FEATURE_IPROUTE
6000 + * Set the MTU for the device
6002 + argv_printf (&argv,
6003 + "%s link set dev %s up mtu %d",
6008 + argv_msg (M_INFO, &argv);
6009 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ip link set failed");
6014 + * Set the address for the device
6016 + argv_printf (&argv,
6017 + "%s addr add dev %s local %s peer %s",
6021 + ifconfig_remote_netmask
6023 + argv_msg (M_INFO, &argv);
6024 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ip addr add failed");
6026 + argv_printf (&argv,
6027 + "%s addr add dev %s %s/%d broadcast %s",
6031 + count_netmask_bits(ifconfig_remote_netmask),
6032 + ifconfig_broadcast
6034 + argv_msg (M_INFO, &argv);
6035 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ip addr add failed");
6039 + argv_printf( &argv,
6040 + "%s -6 addr add %s/%d dev %s",
6042 + ifconfig_ipv6_local,
6046 + argv_msg (M_INFO, &argv);
6047 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ip -6 addr add failed");
6049 + tt->did_ifconfig = true;
6052 + argv_printf (&argv,
6053 + "%s %s %s pointopoint %s mtu %d",
6057 + ifconfig_remote_netmask,
6061 + argv_printf (&argv,
6062 + "%s %s %s netmask %s mtu %d broadcast %s",
6066 + ifconfig_remote_netmask,
6068 + ifconfig_broadcast
6070 + argv_msg (M_INFO, &argv);
6071 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig failed");
6074 + argv_printf (&argv,
6075 + "%s %s inet6 add %s/%d",
6078 + ifconfig_ipv6_local,
6081 + argv_msg (M_INFO, &argv);
6082 + openvpn_execve_check (&argv, es, S_FATAL, "Linux ifconfig inet6 failed");
6084 + tt->did_ifconfig = true;
6086 +#endif /*CONFIG_FEATURE_IPROUTE*/
6087 +#elif defined(TARGET_SOLARIS)
6089 + /* Solaris 2.6 (and 7?) cannot set all parameters in one go...
6091 + * ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up
6092 + * ifconfig tun2 netmask 255.255.255.255
6096 + argv_printf (&argv,
6097 + "%s %s %s %s mtu %d up",
6101 + ifconfig_remote_netmask,
6105 + argv_msg (M_INFO, &argv);
6106 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-1 failed"))
6107 + solaris_error_close (tt, es, actual, false);
6109 + argv_printf (&argv,
6110 + "%s %s netmask 255.255.255.255",
6116 + if (tt->topology == TOP_SUBNET)
6118 + argv_printf (&argv,
6119 + "%s %s %s %s netmask %s mtu %d up",
6124 + ifconfig_remote_netmask,
6129 + argv_printf (&argv,
6130 + " %s %s %s netmask %s broadcast + up",
6134 + ifconfig_remote_netmask
6137 + argv_msg (M_INFO, &argv);
6138 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig phase-2 failed"))
6139 + solaris_error_close (tt, es, actual, false);
6143 + argv_printf (&argv, "%s %s inet6 unplumb",
6144 + IFCONFIG_PATH, actual );
6145 + argv_msg (M_INFO, &argv);
6146 + openvpn_execve_check (&argv, es, 0, NULL);
6148 + if ( tt->type == DEV_TYPE_TUN )
6150 + argv_printf (&argv,
6151 + "%s %s inet6 plumb %s/%d %s up",
6154 + ifconfig_ipv6_local,
6156 + ifconfig_ipv6_remote
6159 + else /* tap mode */
6161 + /* base IPv6 tap interface needs to be brought up first
6163 + argv_printf (&argv, "%s %s inet6 plumb up",
6164 + IFCONFIG_PATH, actual );
6165 + argv_msg (M_INFO, &argv);
6166 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 (prepare) failed"))
6167 + solaris_error_close (tt, es, actual, true);
6169 + /* we might need to do "ifconfig %s inet6 auto-dhcp drop"
6170 + * after the system has noticed the interface and fired up
6171 + * the DHCPv6 client - but this takes quite a while, and the
6172 + * server will ignore the DHCPv6 packets anyway. So we don't.
6175 + /* static IPv6 addresses need to go to a subinterface (tap0:1)
6177 + argv_printf (&argv,
6178 + "%s %s inet6 addif %s/%d up",
6179 + IFCONFIG_PATH, actual,
6180 + ifconfig_ipv6_local, tt->netbits_ipv6 );
6182 + argv_msg (M_INFO, &argv);
6183 + if (!openvpn_execve_check (&argv, es, 0, "Solaris ifconfig IPv6 failed"))
6184 + solaris_error_close (tt, es, actual, true);
6187 + if (!tun && tt->topology == TOP_SUBNET)
6189 + /* Add a network route for the local tun interface */
6193 + r.network = tt->local & tt->remote_netmask;
6194 + r.netmask = tt->remote_netmask;
6195 + r.gateway = tt->local;
6196 + r.metric_defined = true;
6198 + add_route (&r, tt, 0, es);
6201 + tt->did_ifconfig = true;
6203 +#elif defined(TARGET_OPENBSD)
6206 + * OpenBSD tun devices appear to be persistent by default. It seems in order
6207 + * to make this work correctly, we need to delete the previous instance
6208 + * (if it exists), and re-ifconfig. Let me know if you know a better way.
6211 + argv_printf (&argv,
6215 + argv_msg (M_INFO, &argv);
6216 + openvpn_execve_check (&argv, es, 0, NULL);
6217 + argv_printf (&argv,
6221 + argv_msg (M_INFO, &argv);
6222 + openvpn_execve_check (&argv, es, 0, NULL);
6223 + msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure");
6225 + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
6227 + argv_printf (&argv,
6228 + "%s %s %s %s mtu %d netmask 255.255.255.255 up",
6232 + ifconfig_remote_netmask,
6236 + argv_printf (&argv,
6237 + "%s %s %s netmask %s mtu %d broadcast %s link0",
6241 + ifconfig_remote_netmask,
6243 + ifconfig_broadcast
6245 + argv_msg (M_INFO, &argv);
6246 + openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig failed");
6249 + argv_printf (&argv,
6250 + "%s %s inet6 %s/%d",
6253 + ifconfig_ipv6_local,
6256 + argv_msg (M_INFO, &argv);
6257 + openvpn_execve_check (&argv, es, S_FATAL, "OpenBSD ifconfig inet6 failed");
6259 + /* and, hooray, we explicitely need to add a route... */
6260 + add_route_connected_v6_net(tt, es);
6262 + tt->did_ifconfig = true;
6264 +#elif defined(TARGET_NETBSD)
6266 +/* whether or not NetBSD can do IPv6 can be seen by the availability of
6267 + * the TUNSIFHEAD ioctl() - see next TARGET_NETBSD block for more details
6270 +# define NETBSD_MULTI_AF
6273 + /* as on OpenBSD and Darwin, destroy and re-create tun<x> interface
6275 + argv_printf (&argv, "%s %s destroy", IFCONFIG_PATH, actual );
6276 + argv_msg (M_INFO, &argv);
6277 + openvpn_execve_check (&argv, es, 0, "NetBSD ifconfig destroy failed");
6279 + argv_printf (&argv, "%s %s create", IFCONFIG_PATH, actual );
6280 + argv_msg (M_INFO, &argv);
6281 + openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig create failed");
6284 + argv_printf (&argv,
6285 + "%s %s %s %s mtu %d netmask 255.255.255.255 up",
6289 + ifconfig_remote_netmask,
6294 + * NetBSD has distinct tun and tap devices
6295 + * so we don't need the "link0" extra parameter to specify we want to do
6296 + * tunneling at the ethernet level
6298 + argv_printf (&argv,
6299 + "%s %s %s netmask %s mtu %d broadcast %s",
6303 + ifconfig_remote_netmask,
6305 + ifconfig_broadcast
6307 + argv_msg (M_INFO, &argv);
6308 + openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig failed");
6312 +#ifdef NETBSD_MULTI_AF
6313 + argv_printf (&argv,
6314 + "%s %s inet6 %s/%d",
6317 + ifconfig_ipv6_local,
6320 + argv_msg (M_INFO, &argv);
6321 + openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig inet6 failed");
6323 + /* and, hooray, we explicitely need to add a route... */
6324 + add_route_connected_v6_net(tt, es);
6326 + msg( M_INFO, "no IPv6 support for tun interfaces on NetBSD before 4.0 (if your system is newer, recompile openvpn)" );
6330 + tt->did_ifconfig = true;
6332 +#elif defined(TARGET_DARWIN)
6335 + * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD...
6338 + argv_printf (&argv,
6342 + argv_msg (M_INFO, &argv);
6343 + openvpn_execve_check (&argv, es, 0, NULL);
6344 + msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure");
6347 + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
6349 + argv_printf (&argv,
6350 + "%s %s %s %s mtu %d netmask 255.255.255.255 up",
6354 + ifconfig_remote_netmask,
6359 + if (tt->topology == TOP_SUBNET)
6360 + argv_printf (&argv,
6361 + "%s %s %s %s netmask %s mtu %d up",
6366 + ifconfig_remote_netmask,
6370 + argv_printf (&argv,
6371 + "%s %s %s netmask %s mtu %d up",
6375 + ifconfig_remote_netmask,
6379 + argv_msg (M_INFO, &argv);
6380 + openvpn_execve_check (&argv, es, S_FATAL, "Mac OS X ifconfig failed");
6381 + tt->did_ifconfig = true;
6383 + /* Add a network route for the local tun interface */
6384 + if (!tun && tt->topology == TOP_SUBNET)
6389 + r.network = tt->local & tt->remote_netmask;
6390 + r.netmask = tt->remote_netmask;
6391 + r.gateway = tt->local;
6392 + add_route (&r, tt, 0, es);
6397 + argv_printf (&argv,
6398 + "%s %s inet6 %s/%d",
6401 + ifconfig_ipv6_local,
6404 + argv_msg (M_INFO, &argv);
6405 + openvpn_execve_check (&argv, es, S_FATAL, "MacOS X ifconfig inet6 failed");
6407 + /* and, hooray, we explicitely need to add a route... */
6408 + add_route_connected_v6_net(tt, es);
6411 +#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)
6413 + /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */
6415 + argv_printf (&argv,
6416 + "%s %s %s %s mtu %d netmask 255.255.255.255 up",
6420 + ifconfig_remote_netmask,
6424 + argv_printf (&argv,
6425 + "%s %s %s netmask %s mtu %d up",
6429 + ifconfig_remote_netmask,
6433 + argv_msg (M_INFO, &argv);
6434 + openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig failed");
6435 + tt->did_ifconfig = true;
6437 + /* Add a network route for the local tun interface */
6438 + if (!tun && tt->topology == TOP_SUBNET)
6443 + r.network = tt->local & tt->remote_netmask;
6444 + r.netmask = tt->remote_netmask;
6445 + r.gateway = tt->local;
6446 + add_route (&r, tt, 0, es);
6451 + argv_printf (&argv,
6452 + "%s %s inet6 %s/%d",
6455 + ifconfig_ipv6_local,
6458 + argv_msg (M_INFO, &argv);
6459 + openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed");
6462 +#elif defined (WIN32)
6465 + * Make sure that both ifconfig addresses are part of the
6466 + * same .252 subnet.
6470 + verify_255_255_255_252 (tt->local, tt->remote_netmask);
6471 + tt->adapter_netmask = ~3;
6475 + tt->adapter_netmask = tt->remote_netmask;
6478 + switch (tt->options.ip_win32_type)
6480 + case IPW32_SET_MANUAL:
6481 + msg (M_INFO, "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)",
6484 + print_in_addr_t (tt->adapter_netmask, 0, &gc));
6486 + case IPW32_SET_NETSH:
6487 + if (!strcmp (actual, "NULL"))
6488 + msg (M_FATAL, "Error: When using --ip-win32 netsh, if you have more than one TAP-Win32 adapter, you must also specify --dev-node");
6490 + netsh_ifconfig (&tt->options,
6493 + tt->adapter_netmask,
6494 + NI_IP_NETMASK|NI_OPTIONS);
6498 + tt->did_ifconfig = true;
6501 + /* IPv6 always uses "netsh" interface */
6504 + char * saved_actual;
6506 + if (!strcmp (actual, "NULL"))
6507 + msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than one TAP-Win32 adapter, you must also specify --dev-node");
6509 + /* example: netsh interface ipv6 set address MyTap 2001:608:8003::d store=active */
6510 + argv_printf (&argv,
6511 + "%s%sc interface ipv6 set address %s %s store=active",
6512 + get_win_sys_path(),
6513 + NETSH_PATH_SUFFIX,
6515 + ifconfig_ipv6_local );
6517 + netsh_command (&argv, 4);
6519 + /* explicit route needed */
6520 + /* on windows, OpenVPN does ifconfig first, open_tun later, so
6521 + * tt->actual_name might not yet be initialized, but routing code
6522 + * needs to know interface name - point to "actual", restore later
6524 + saved_actual = tt->actual_name;
6525 + tt->actual_name = (char*) actual;
6526 + add_route_connected_v6_net(tt, es);
6527 + tt->actual_name = saved_actual;
6530 + msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");
6532 + argv_reset (&argv);
6538 +clear_tuntap (struct tuntap *tuntap)
6542 + tuntap->hand = NULL;
6546 +#ifdef TARGET_SOLARIS
6547 + tuntap->ip_fd = -1;
6549 + tuntap->ipv6 = false;
6553 +open_null (struct tuntap *tt)
6555 + tt->actual_name = string_alloc ("null", NULL);
6560 +open_tun_generic (const char *dev, const char *dev_type, const char *dev_node,
6561 + bool ipv6_explicitly_supported, bool dynamic,
6562 + struct tuntap *tt)
6564 + char tunname[256];
6565 + char dynamic_name[256];
6566 + bool dynamic_opened = false;
6569 + if ( tt->ipv6 && ! ipv6_explicitly_supported )
6570 + msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
6572 + if (tt->type == DEV_TYPE_NULL)
6579 + * --dev-node specified, so open an explicit device node
6583 + openvpn_snprintf (tunname, sizeof (tunname), "%s", dev_node);
6588 + * dynamic open is indicated by --dev specified without
6589 + * explicit unit number. Try opening /dev/[dev]n
6590 + * where n = [0, 255].
6592 + if (dynamic && !has_digit((unsigned char *)dev))
6595 + for (i = 0; i < 256; ++i)
6597 + openvpn_snprintf (tunname, sizeof (tunname),
6598 + "/dev/%s%d", dev, i);
6599 + openvpn_snprintf (dynamic_name, sizeof (dynamic_name),
6601 + if ((tt->fd = open (tunname, O_RDWR)) > 0)
6603 + dynamic_opened = true;
6606 + msg (D_READ_WRITE | M_ERRNO, "Tried opening %s (failed)", tunname);
6608 + if (!dynamic_opened)
6609 + msg (M_FATAL, "Cannot allocate TUN/TAP dev dynamically");
6612 + * explicit unit number specified
6616 + openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev);
6620 + if (!dynamic_opened)
6622 + if ((tt->fd = open (tunname, O_RDWR)) < 0)
6623 + msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname);
6626 + set_nonblock (tt->fd);
6627 + set_cloexec (tt->fd); /* don't pass fd to scripts */
6628 + msg (M_INFO, "TUN/TAP device %s opened", tunname);
6630 + /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */
6631 + tt->actual_name = string_alloc (dynamic_opened ? dynamic_name : dev, NULL);
6636 +close_tun_generic (struct tuntap *tt)
6640 + if (tt->actual_name)
6641 + free (tt->actual_name);
6642 + clear_tuntap (tt);
6647 +#if defined(TARGET_LINUX)
6649 +#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */
6651 +#ifndef HAVE_LINUX_SOCKIOS_H
6652 +#error header file linux/sockios.h required
6655 +#if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV)
6656 +#define LINUX_IPV6 1
6657 +/* #warning IPv6 ON */
6659 +#define LINUX_IPV6 0
6660 +/* #warning IPv6 OFF */
6666 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
6670 + /* warn if a very old linux version is used & --tun-ipv6 set
6672 +#if LINUX_IPV6 == 0
6674 + msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");
6678 + * We handle --dev null specially, we do not open /dev/null for this.
6680 + if (tt->type == DEV_TYPE_NULL)
6687 + * Process --dev-node
6689 + const char *node = dev_node;
6691 + node = "/dev/net/tun";
6694 + * Open the interface
6696 + if ((tt->fd = open (node, O_RDWR)) < 0)
6698 + msg (M_WARN | M_ERRNO, "Note: Cannot open TUN/TAP dev %s", node);
6703 + * Process --tun-ipv6
6707 + ifr.ifr_flags = IFF_NO_PI;
6709 +#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
6710 + ifr.ifr_flags |= IFF_ONE_QUEUE;
6714 + * Figure out if tun or tap device
6716 + if (tt->type == DEV_TYPE_TUN)
6718 + ifr.ifr_flags |= IFF_TUN;
6720 + else if (tt->type == DEV_TYPE_TAP)
6722 + ifr.ifr_flags |= IFF_TAP;
6726 + msg (M_FATAL, "I don't recognize device %s as a tun or tap device",
6731 + * Set an explicit name, if --dev is not tun or tap
6733 + if (strcmp(dev, "tun") && strcmp(dev, "tap"))
6734 + strncpynt (ifr.ifr_name, dev, IFNAMSIZ);
6737 + * Use special ioctl that configures tun/tap device with the parms
6740 + if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0)
6742 + msg (M_WARN | M_ERRNO, "Note: Cannot ioctl TUNSETIFF %s", dev);
6746 + msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
6749 + * Try making the TX send queue bigger
6751 +#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN)
6752 + if (tt->options.txqueuelen) {
6753 + struct ifreq netifr;
6756 + if ((ctl_fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0)
6759 + strncpynt (netifr.ifr_name, ifr.ifr_name, IFNAMSIZ);
6760 + netifr.ifr_qlen = tt->options.txqueuelen;
6761 + if (ioctl (ctl_fd, SIOCSIFTXQLEN, (void *) &netifr) >= 0)
6762 + msg (D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen);
6764 + msg (M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name);
6769 + msg (M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name);
6774 + set_nonblock (tt->fd);
6775 + set_cloexec (tt->fd);
6776 + tt->actual_name = string_alloc (ifr.ifr_name, NULL);
6784 +open_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt)
6794 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
6796 + open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);
6799 +#endif /* HAVE_LINUX_IF_TUN_H */
6801 +#ifdef TUNSETPERSIST
6804 + * This can be removed in future
6805 + * when all systems will use newer
6808 +#ifndef TUNSETOWNER
6809 +#define TUNSETOWNER _IOW('T', 204, int)
6811 +#ifndef TUNSETGROUP
6812 +#define TUNSETGROUP _IOW('T', 206, int)
6816 +tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist_mode, const char *username, const char *groupname, const struct tuntap_options *options)
6818 + struct tuntap *tt;
6820 + ALLOC_OBJ (tt, struct tuntap);
6821 + clear_tuntap (tt);
6822 + tt->type = dev_type_enum (dev, dev_type);
6823 + tt->options = *options;
6824 + open_tun (dev, dev_type, dev_node, tt);
6825 + if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)
6826 + msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
6827 + if (username != NULL)
6829 + struct user_state user_state;
6831 + if (!get_user (username, &user_state))
6832 + msg (M_ERR, "Cannot get user entry for %s", username);
6834 + if (ioctl (tt->fd, TUNSETOWNER, user_state.pw->pw_uid) < 0)
6835 + msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
6837 + if (groupname != NULL)
6839 + struct group_state group_state;
6841 + if (!get_group (groupname, &group_state))
6842 + msg (M_ERR, "Cannot get group entry for %s", groupname);
6844 + if (ioctl (tt->fd, TUNSETGROUP, group_state.gr->gr_gid) < 0)
6845 + msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", groupname, dev);
6848 + msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));
6851 +#endif /* TUNSETPERSIST */
6854 +close_tun (struct tuntap *tt)
6858 + if (tt->type != DEV_TYPE_NULL && tt->did_ifconfig)
6861 + struct gc_arena gc = gc_new ();
6862 + argv_init (&argv);
6864 +#ifdef CONFIG_FEATURE_IPROUTE
6865 + if (is_tun_p2p (tt))
6867 + argv_printf (&argv,
6868 + "%s addr del dev %s local %s peer %s",
6871 + print_in_addr_t (tt->local, 0, &gc),
6872 + print_in_addr_t (tt->remote_netmask, 0, &gc)
6877 + argv_printf (&argv,
6878 + "%s addr del dev %s %s/%d",
6881 + print_in_addr_t (tt->local, 0, &gc),
6882 + count_netmask_bits(print_in_addr_t (tt->remote_netmask, 0, &gc))
6886 + argv_printf (&argv,
6893 + argv_msg (M_INFO, &argv);
6894 + openvpn_execve_check (&argv, NULL, 0, "Linux ip addr del failed");
6896 + argv_reset (&argv);
6899 + close_tun_generic (tt);
6905 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
6911 + struct iphdr *iph;
6912 + struct iovec vect[2];
6915 + iph = (struct iphdr *)buf;
6919 + if(iph->version == 6)
6920 + pi.proto = htons(ETH_P_IPV6);
6922 + pi.proto = htons(ETH_P_IP);
6924 + vect[0].iov_len = sizeof(pi);
6925 + vect[0].iov_base = π
6926 + vect[1].iov_len = len;
6927 + vect[1].iov_base = buf;
6929 + ret = writev(tt->fd, vect, 2);
6930 + return(ret - sizeof(pi));
6934 + return write (tt->fd, buf, len);
6938 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
6943 + struct iovec vect[2];
6947 + vect[0].iov_len = sizeof(pi);
6948 + vect[0].iov_base = π
6949 + vect[1].iov_len = len;
6950 + vect[1].iov_base = buf;
6952 + ret = readv(tt->fd, vect, 2);
6953 + return(ret - sizeof(pi));
6957 + return read (tt->fd, buf, len);
6960 +#elif defined(TARGET_SOLARIS)
6963 +#error I need the symbol TUNNEWPPA from net/if_tun.h
6967 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
6969 + int if_fd, ip_muxid, arp_muxid, arp_fd, ppa = -1;
6970 + struct lifreq ifr;
6972 + const char *ip_node, *arp_node;
6973 + const char *dev_tuntap_type;
6976 + struct strioctl strioc_if, strioc_ppa;
6978 + /* improved generic TUN/TAP driver from
6979 + * http://www.whiteboard.ne.jp/~admin2/tuntap/
6980 + * has IPv6 support
6984 + if (tt->type == DEV_TYPE_NULL)
6990 + if (tt->type == DEV_TYPE_TUN)
6992 + ip_node = "/dev/udp";
6994 + dev_node = "/dev/tun";
6995 + dev_tuntap_type = "tun";
6996 + link_type = I_PLINK;
6999 + else if (tt->type == DEV_TYPE_TAP)
7001 + ip_node = "/dev/udp";
7003 + dev_node = "/dev/tap";
7004 + arp_node = dev_node;
7005 + dev_tuntap_type = "tap";
7006 + link_type = I_PLINK; /* was: I_LINK */
7011 + msg (M_FATAL, "I don't recognize device %s as a tun or tap device",
7015 + /* get unit number */
7019 + while (*ptr && !isdigit ((int) *ptr))
7024 + if ((tt->ip_fd = open (ip_node, O_RDWR, 0)) < 0)
7025 + msg (M_ERR, "Can't open %s", ip_node);
7027 + if ((tt->fd = open (dev_node, O_RDWR, 0)) < 0)
7028 + msg (M_ERR, "Can't open %s", dev_node);
7030 + /* Assign a new PPA and get its unit number. */
7031 + strioc_ppa.ic_cmd = TUNNEWPPA;
7032 + strioc_ppa.ic_timout = 0;
7033 + strioc_ppa.ic_len = sizeof(ppa);
7034 + strioc_ppa.ic_dp = (char *)&ppa;
7035 + if ((ppa = ioctl (tt->fd, I_STR, &strioc_ppa)) < 0)
7036 + msg (M_ERR, "Can't assign new interface");
7038 + if ((if_fd = open (dev_node, O_RDWR, 0)) < 0)
7039 + msg (M_ERR, "Can't open %s (2)", dev_node);
7041 + if (ioctl (if_fd, I_PUSH, "ip") < 0)
7042 + msg (M_ERR, "Can't push IP module");
7044 + if (tt->type == DEV_TYPE_TUN)
7046 + /* Assign ppa according to the unit number returned by tun device */
7047 + if (ioctl (if_fd, IF_UNITSEL, (char *) &ppa) < 0)
7048 + msg (M_ERR, "Can't set PPA %d", ppa);
7051 + tt->actual_name = (char *) malloc (32);
7052 + check_malloc_return (tt->actual_name);
7054 + openvpn_snprintf (tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa);
7056 + if (tt->type == DEV_TYPE_TAP)
7058 + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0)
7059 + msg (M_ERR, "Can't get flags\n");
7060 + strncpynt (ifr.lifr_name, tt->actual_name, sizeof (ifr.lifr_name));
7061 + ifr.lifr_ppa = ppa;
7062 + /* Assign ppa according to the unit number returned by tun device */
7063 + if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0)
7064 + msg (M_ERR, "Can't set PPA %d", ppa);
7065 + if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0)
7066 + msg (M_ERR, "Can't get flags\n");
7067 + /* Push arp module to if_fd */
7068 + if (ioctl (if_fd, I_PUSH, "arp") < 0)
7069 + msg (M_ERR, "Can't push ARP module");
7071 + /* Pop any modules on the stream */
7074 + if (ioctl (tt->ip_fd, I_POP, NULL) < 0)
7077 + /* Push arp module to ip_fd */
7078 + if (ioctl (tt->ip_fd, I_PUSH, "arp") < 0)
7079 + msg (M_ERR, "Can't push ARP module\n");
7082 + if ((arp_fd = open (arp_node, O_RDWR, 0)) < 0)
7083 + msg (M_ERR, "Can't open %s\n", arp_node);
7084 + /* Push arp module to arp_fd */
7085 + if (ioctl (arp_fd, I_PUSH, "arp") < 0)
7086 + msg (M_ERR, "Can't push ARP module\n");
7088 + /* Set ifname to arp */
7089 + strioc_if.ic_cmd = SIOCSLIFNAME;
7090 + strioc_if.ic_timout = 0;
7091 + strioc_if.ic_len = sizeof(ifr);
7092 + strioc_if.ic_dp = (char *)𝔦
7093 + if (ioctl(arp_fd, I_STR, &strioc_if) < 0){
7094 + msg (M_ERR, "Can't set ifname to arp\n");
7098 + if ((ip_muxid = ioctl (tt->ip_fd, link_type, if_fd)) < 0)
7099 + msg (M_ERR, "Can't link %s device to IP", dev_tuntap_type);
7101 + if (tt->type == DEV_TYPE_TAP) {
7102 + if ((arp_muxid = ioctl (tt->ip_fd, link_type, arp_fd)) < 0)
7103 + msg (M_ERR, "Can't link %s device to ARP", dev_tuntap_type);
7108 + strncpynt (ifr.lifr_name, tt->actual_name, sizeof (ifr.lifr_name));
7109 + ifr.lifr_ip_muxid = ip_muxid;
7110 + if (tt->type == DEV_TYPE_TAP) {
7111 + ifr.lifr_arp_muxid = arp_muxid;
7114 + if (ioctl (tt->ip_fd, SIOCSLIFMUXID, &ifr) < 0)
7116 + if (tt->type == DEV_TYPE_TAP)
7118 + ioctl (tt->ip_fd, I_PUNLINK , arp_muxid);
7120 + ioctl (tt->ip_fd, I_PUNLINK, ip_muxid);
7121 + msg (M_ERR, "Can't set multiplexor id");
7124 + set_nonblock (tt->fd);
7125 + set_cloexec (tt->fd);
7126 + set_cloexec (tt->ip_fd);
7128 + msg (M_INFO, "TUN/TAP device %s opened", tt->actual_name);
7132 +solaris_close_tun (struct tuntap *tt)
7136 + /* IPv6 interfaces need to be 'manually' de-configured */
7137 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
7140 + argv_init (&argv);
7141 + argv_printf( &argv, "%s %s inet6 unplumb",
7142 + IFCONFIG_PATH, tt->actual_name );
7143 + argv_msg (M_INFO, &argv);
7144 + openvpn_execve_check (&argv, NULL, 0, "Solaris ifconfig inet6 unplumb failed");
7145 + argv_reset (&argv);
7148 + if (tt->ip_fd >= 0)
7150 + struct lifreq ifr;
7152 + strncpynt (ifr.lifr_name, tt->actual_name, sizeof (ifr.lifr_name));
7154 + if (ioctl (tt->ip_fd, SIOCGLIFFLAGS, &ifr) < 0)
7155 + msg (M_WARN | M_ERRNO, "Can't get iface flags");
7157 + if (ioctl (tt->ip_fd, SIOCGLIFMUXID, &ifr) < 0)
7158 + msg (M_WARN | M_ERRNO, "Can't get multiplexor id");
7160 + if (tt->type == DEV_TYPE_TAP)
7162 + if (ioctl (tt->ip_fd, I_PUNLINK, ifr.lifr_arp_muxid) < 0)
7163 + msg (M_WARN | M_ERRNO, "Can't unlink interface(arp)");
7166 + if (ioctl (tt->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0)
7167 + msg (M_WARN | M_ERRNO, "Can't unlink interface(ip)");
7169 + close (tt->ip_fd);
7182 + * Close TUN device.
7185 +close_tun (struct tuntap *tt)
7189 + solaris_close_tun (tt);
7191 + if (tt->actual_name)
7192 + free (tt->actual_name);
7194 + clear_tuntap (tt);
7200 +solaris_error_close (struct tuntap *tt, const struct env_set *es,
7201 + const char *actual, bool unplumb_inet6 )
7204 + argv_init (&argv);
7206 + if (unplumb_inet6)
7208 + argv_printf( &argv, "%s %s inet6 unplumb",
7209 + IFCONFIG_PATH, actual );
7210 + argv_msg (M_INFO, &argv);
7211 + openvpn_execve_check (&argv, es, 0, "Solaris ifconfig inet6 unplumb failed");
7214 + argv_printf (&argv,
7219 + argv_msg (M_INFO, &argv);
7220 + openvpn_execve_check (&argv, es, 0, "Solaris ifconfig unplumb failed");
7222 + msg (M_FATAL, "Solaris ifconfig failed");
7223 + argv_reset (&argv);
7227 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7229 + struct strbuf sbuf;
7231 + sbuf.buf = (char *)buf;
7232 + return putmsg (tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;
7236 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7238 + struct strbuf sbuf;
7241 + sbuf.maxlen = len;
7242 + sbuf.buf = (char *)buf;
7243 + return getmsg (tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;
7246 +#elif defined(TARGET_OPENBSD)
7248 +#if !defined(HAVE_READV) || !defined(HAVE_WRITEV)
7249 +#error openbsd build requires readv & writev library functions
7253 + * OpenBSD has a slightly incompatible TUN device from
7254 + * the rest of the world, in that it prepends a
7255 + * uint32 to the beginning of the IP header
7256 + * to designate the protocol (why not just
7257 + * look at the version field in the IP header to
7258 + * determine v4 or v6?).
7260 + * We strip off this field on reads and
7261 + * put it back on writes.
7263 + * I have not tested TAP devices on OpenBSD,
7264 + * but I have conditionalized the special
7265 + * TUN handling code described above to
7266 + * go away for TAP devices.
7270 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
7272 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
7274 + /* Enable multicast on the interface */
7277 + struct tuninfo info;
7279 + if (ioctl (tt->fd, TUNGIFINFO, &info) < 0) {
7280 + msg (M_WARN | M_ERRNO, "Can't get interface info: %s",
7284 + info.flags |= IFF_MULTICAST;
7286 + if (ioctl (tt->fd, TUNSIFINFO, &info) < 0) {
7287 + msg (M_WARN | M_ERRNO, "Can't set interface info: %s",
7293 +/* the current way OpenVPN handles tun devices on OpenBSD leads to
7294 + * lingering tunX interfaces after close -> for a full cleanup, they
7295 + * need to be explicitely destroyed
7299 +close_tun (struct tuntap* tt)
7303 + struct gc_arena gc = gc_new ();
7306 + /* setup command, close tun dev (clears tt->actual_name!), run command
7309 + argv_init (&argv);
7310 + argv_printf (&argv, "%s %s destroy",
7311 + IFCONFIG_PATH, tt->actual_name);
7313 + close_tun_generic (tt);
7315 + argv_msg (M_INFO, &argv);
7316 + openvpn_execve_check (&argv, NULL, 0, "OpenBSD 'destroy tun interface' failed (non-critical)");
7323 +openbsd_modify_read_write_return (int len)
7326 + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
7332 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7334 + if (tt->type == DEV_TYPE_TUN)
7337 + struct iovec iv[2];
7340 + iph = (struct ip *) buf;
7342 + if (tt->ipv6 && iph->ip_v == 6)
7343 + type = htonl (AF_INET6);
7345 + type = htonl (AF_INET);
7347 + iv[0].iov_base = &type;
7348 + iv[0].iov_len = sizeof (type);
7349 + iv[1].iov_base = buf;
7350 + iv[1].iov_len = len;
7352 + return openbsd_modify_read_write_return (writev (tt->fd, iv, 2));
7355 + return write (tt->fd, buf, len);
7359 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7361 + if (tt->type == DEV_TYPE_TUN)
7364 + struct iovec iv[2];
7366 + iv[0].iov_base = &type;
7367 + iv[0].iov_len = sizeof (type);
7368 + iv[1].iov_base = buf;
7369 + iv[1].iov_len = len;
7371 + return openbsd_modify_read_write_return (readv (tt->fd, iv, 2));
7374 + return read (tt->fd, buf, len);
7377 +#elif defined(TARGET_NETBSD)
7380 + * NetBSD before 4.0 does not support IPv6 on tun out of the box,
7381 + * but there exists a patch (sys/net/if_tun.c, 1.79->1.80, see PR 32944).
7383 + * NetBSD 4.0 and up do, but we need to put the tun interface into
7384 + * "multi_af" mode, which will prepend the address family to all packets
7385 + * (same as OpenBSD and FreeBSD). If this is not enabled, the kernel
7386 + * silently drops all IPv6 packets on output and gets confused on input.
7388 + * On earlier versions, multi_af is not available at all, so we have
7389 + * two different NetBSD code variants here :-(
7394 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
7396 +#ifdef NETBSD_MULTI_AF
7397 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
7399 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
7404 + int i = IFF_POINTOPOINT|IFF_MULTICAST;
7405 + ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */
7407 + ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */
7409 +#ifdef NETBSD_MULTI_AF
7411 + if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */
7413 + msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
7420 +close_tun (struct tuntap *tt)
7422 + /* TODO: we really should cleanup non-persistant tunX with
7423 + * "ifconfig tunX destroy" here...
7427 + close_tun_generic (tt);
7432 +#ifdef NETBSD_MULTI_AF
7435 +netbsd_modify_read_write_return (int len)
7438 + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
7444 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7446 + if (tt->type == DEV_TYPE_TUN)
7449 + struct iovec iv[2];
7450 + struct openvpn_iphdr *iph;
7452 + iph = (struct openvpn_iphdr *) buf;
7454 + if (tt->ipv6 && OPENVPN_IPH_GET_VER(iph->version_len) == 6)
7455 + type = htonl (AF_INET6);
7457 + type = htonl (AF_INET);
7459 + iv[0].iov_base = (char *)&type;
7460 + iv[0].iov_len = sizeof (type);
7461 + iv[1].iov_base = buf;
7462 + iv[1].iov_len = len;
7464 + return netbsd_modify_read_write_return (writev (tt->fd, iv, 2));
7467 + return write (tt->fd, buf, len);
7471 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7473 + if (tt->type == DEV_TYPE_TUN)
7476 + struct iovec iv[2];
7478 + iv[0].iov_base = (char *)&type;
7479 + iv[0].iov_len = sizeof (type);
7480 + iv[1].iov_base = buf;
7481 + iv[1].iov_len = len;
7483 + return netbsd_modify_read_write_return (readv (tt->fd, iv, 2));
7486 + return read (tt->fd, buf, len);
7489 +#else /* not NETBSD_MULTI_AF -> older code, IPv4 only */
7492 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7494 + return write (tt->fd, buf, len);
7498 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7500 + return read (tt->fd, buf, len);
7502 +#endif /* NETBSD_MULTI_AF */
7504 +#elif defined(TARGET_FREEBSD)
7507 +freebsd_modify_read_write_return (int len)
7510 + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
7516 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
7518 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
7520 + if (tt->fd >= 0 && tt->type == DEV_TYPE_TUN)
7524 + i = tt->topology == TOP_SUBNET ? IFF_BROADCAST : IFF_POINTOPOINT;
7525 + i |= IFF_MULTICAST;
7526 + if (ioctl (tt->fd, TUNSIFMODE, &i) < 0) {
7527 + msg (M_WARN | M_ERRNO, "ioctl(TUNSIFMODE): %s", strerror(errno));
7530 + if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) {
7531 + msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno));
7537 +close_tun (struct tuntap *tt)
7541 + close_tun_generic (tt);
7547 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7549 + if (tt->type == DEV_TYPE_TUN)
7552 + struct iovec iv[2];
7555 + iph = (struct ip *) buf;
7557 + if (tt->ipv6 && iph->ip_v == 6)
7558 + type = htonl (AF_INET6);
7560 + type = htonl (AF_INET);
7562 + iv[0].iov_base = (char *)&type;
7563 + iv[0].iov_len = sizeof (type);
7564 + iv[1].iov_base = buf;
7565 + iv[1].iov_len = len;
7567 + return freebsd_modify_read_write_return (writev (tt->fd, iv, 2));
7570 + return write (tt->fd, buf, len);
7574 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7576 + if (tt->type == DEV_TYPE_TUN)
7579 + struct iovec iv[2];
7581 + iv[0].iov_base = (char *)&type;
7582 + iv[0].iov_len = sizeof (type);
7583 + iv[1].iov_base = buf;
7584 + iv[1].iov_len = len;
7586 + return freebsd_modify_read_write_return (readv (tt->fd, iv, 2));
7589 + return read (tt->fd, buf, len);
7592 +#elif defined(TARGET_DRAGONFLY)
7595 +dragonfly_modify_read_write_return (int len)
7598 + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0;
7604 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
7606 + open_tun_generic (dev, dev_type, dev_node, true, true, tt);
7612 + /* Disable extended modes */
7613 + ioctl (tt->fd, TUNSLMODE, &i);
7615 + ioctl (tt->fd, TUNSIFHEAD, &i);
7620 +close_tun (struct tuntap *tt)
7624 + close_tun_generic (tt);
7630 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7632 + if (tt->type == DEV_TYPE_TUN)
7635 + struct iovec iv[2];
7638 + iph = (struct ip *) buf;
7640 + if (tt->ipv6 && iph->ip_v == 6)
7641 + type = htonl (AF_INET6);
7643 + type = htonl (AF_INET);
7645 + iv[0].iov_base = (char *)&type;
7646 + iv[0].iov_len = sizeof (type);
7647 + iv[1].iov_base = buf;
7648 + iv[1].iov_len = len;
7650 + return dragonfly_modify_read_write_return (writev (tt->fd, iv, 2));
7653 + return write (tt->fd, buf, len);
7657 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7659 + if (tt->type == DEV_TYPE_TUN)
7662 + struct iovec iv[2];
7664 + iv[0].iov_base = (char *)&type;
7665 + iv[0].iov_len = sizeof (type);
7666 + iv[1].iov_base = buf;
7667 + iv[1].iov_len = len;
7669 + return dragonfly_modify_read_write_return (readv (tt->fd, iv, 2));
7672 + return read (tt->fd, buf, len);
7675 +#elif defined(TARGET_DARWIN)
7677 +/* Darwin (MacOS X) is mostly "just use the generic stuff", but there
7678 + * is always one caveat...:
7680 + * If IPv6 is configured, and the tun device is closed, the IPv6 address
7681 + * configured to the tun interface changes to a lingering /128 route
7682 + * pointing to lo0. Need to unconfigure... (observed on 10.5)
7686 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
7688 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
7692 +close_tun (struct tuntap* tt)
7696 + struct gc_arena gc = gc_new ();
7698 + argv_init (&argv);
7700 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
7702 + const char * ifconfig_ipv6_local =
7703 + print_in6_addr (tt->local_ipv6, 0, &gc);
7705 + argv_printf (&argv, "%s delete -inet6 %s",
7706 + ROUTE_PATH, ifconfig_ipv6_local );
7707 + argv_msg (M_INFO, &argv);
7708 + openvpn_execve_check (&argv, NULL, 0, "MacOS X 'remove inet6 route' failed (non-critical)");
7711 + close_tun_generic (tt);
7713 + argv_reset (&argv);
7719 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
7721 + return write (tt->fd, buf, len);
7725 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
7727 + return read (tt->fd, buf, len);
7730 +#elif defined(WIN32)
7733 +tun_read_queue (struct tuntap *tt, int maxsize)
7735 + if (tt->reads.iostate == IOSTATE_INITIAL)
7741 + /* reset buf to its initial state */
7742 + tt->reads.buf = tt->reads.buf_init;
7744 + len = maxsize ? maxsize : BLEN (&tt->reads.buf);
7745 + ASSERT (len <= BLEN (&tt->reads.buf));
7747 + /* the overlapped read will signal this event on I/O completion */
7748 + ASSERT (ResetEvent (tt->reads.overlapped.hEvent));
7750 + status = ReadFile(
7752 + BPTR (&tt->reads.buf),
7755 + &tt->reads.overlapped
7758 + if (status) /* operation completed immediately? */
7760 + /* since we got an immediate return, we must signal the event object ourselves */
7761 + ASSERT (SetEvent (tt->reads.overlapped.hEvent));
7763 + tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
7764 + tt->reads.status = 0;
7766 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]",
7768 + (int) tt->reads.size);
7772 + err = GetLastError ();
7773 + if (err == ERROR_IO_PENDING) /* operation queued? */
7775 + tt->reads.iostate = IOSTATE_QUEUED;
7776 + tt->reads.status = err;
7777 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]",
7780 + else /* error occurred */
7782 + struct gc_arena gc = gc_new ();
7783 + ASSERT (SetEvent (tt->reads.overlapped.hEvent));
7784 + tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;
7785 + tt->reads.status = err;
7786 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s",
7788 + strerror_win32 (status, &gc));
7793 + return tt->reads.iostate;
7797 +tun_write_queue (struct tuntap *tt, struct buffer *buf)
7799 + if (tt->writes.iostate == IOSTATE_INITIAL)
7804 + /* make a private copy of buf */
7805 + tt->writes.buf = tt->writes.buf_init;
7806 + tt->writes.buf.len = 0;
7807 + ASSERT (buf_copy (&tt->writes.buf, buf));
7809 + /* the overlapped write will signal this event on I/O completion */
7810 + ASSERT (ResetEvent (tt->writes.overlapped.hEvent));
7812 + status = WriteFile(
7814 + BPTR (&tt->writes.buf),
7815 + BLEN (&tt->writes.buf),
7817 + &tt->writes.overlapped
7820 + if (status) /* operation completed immediately? */
7822 + tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
7824 + /* since we got an immediate return, we must signal the event object ourselves */
7825 + ASSERT (SetEvent (tt->writes.overlapped.hEvent));
7827 + tt->writes.status = 0;
7829 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]",
7830 + BLEN (&tt->writes.buf),
7831 + (int) tt->writes.size);
7835 + err = GetLastError ();
7836 + if (err == ERROR_IO_PENDING) /* operation queued? */
7838 + tt->writes.iostate = IOSTATE_QUEUED;
7839 + tt->writes.status = err;
7840 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]",
7841 + BLEN (&tt->writes.buf));
7843 + else /* error occurred */
7845 + struct gc_arena gc = gc_new ();
7846 + ASSERT (SetEvent (tt->writes.overlapped.hEvent));
7847 + tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;
7848 + tt->writes.status = err;
7849 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s",
7850 + BLEN (&tt->writes.buf),
7851 + strerror_win32 (err, &gc));
7856 + return tt->writes.iostate;
7862 + struct overlapped_io *io,
7863 + struct buffer *buf)
7868 + switch (io->iostate)
7870 + case IOSTATE_QUEUED:
7871 + status = GetOverlappedResult(
7879 + /* successful return for a queued operation */
7883 + io->iostate = IOSTATE_INITIAL;
7884 + ASSERT (ResetEvent (io->overlapped.hEvent));
7885 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion success [%d]", ret);
7889 + /* error during a queued operation */
7891 + if (GetLastError() != ERROR_IO_INCOMPLETE)
7893 + /* if no error (i.e. just not finished yet),
7894 + then DON'T execute this code */
7895 + io->iostate = IOSTATE_INITIAL;
7896 + ASSERT (ResetEvent (io->overlapped.hEvent));
7897 + msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion error");
7902 + case IOSTATE_IMMEDIATE_RETURN:
7903 + io->iostate = IOSTATE_INITIAL;
7904 + ASSERT (ResetEvent (io->overlapped.hEvent));
7907 + /* error return for a non-queued operation */
7908 + SetLastError (io->status);
7910 + msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion non-queued error");
7914 + /* successful return for a non-queued operation */
7918 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued success [%d]", ret);
7922 + case IOSTATE_INITIAL: /* were we called without proper queueing? */
7923 + SetLastError (ERROR_INVALID_FUNCTION);
7925 + dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE");
7937 +const struct tap_reg *
7938 +get_tap_reg (struct gc_arena *gc)
7943 + struct tap_reg *first = NULL;
7944 + struct tap_reg *last = NULL;
7947 + status = RegOpenKeyEx(
7948 + HKEY_LOCAL_MACHINE,
7954 + if (status != ERROR_SUCCESS)
7955 + msg (M_FATAL, "Error opening registry key: %s", ADAPTER_KEY);
7959 + char enum_name[256];
7960 + char unit_string[256];
7962 + char component_id_string[] = "ComponentId";
7963 + char component_id[256];
7964 + char net_cfg_instance_id_string[] = "NetCfgInstanceId";
7965 + char net_cfg_instance_id[256];
7968 + len = sizeof (enum_name);
7969 + status = RegEnumKeyEx(
7978 + if (status == ERROR_NO_MORE_ITEMS)
7980 + else if (status != ERROR_SUCCESS)
7981 + msg (M_FATAL, "Error enumerating registry subkeys of key: %s",
7984 + openvpn_snprintf (unit_string, sizeof(unit_string), "%s\\%s",
7985 + ADAPTER_KEY, enum_name);
7987 + status = RegOpenKeyEx(
7988 + HKEY_LOCAL_MACHINE,
7994 + if (status != ERROR_SUCCESS)
7995 + dmsg (D_REGISTRY, "Error opening registry key: %s", unit_string);
7998 + len = sizeof (component_id);
7999 + status = RegQueryValueEx(
8001 + component_id_string,
8007 + if (status != ERROR_SUCCESS || data_type != REG_SZ)
8008 + dmsg (D_REGISTRY, "Error opening registry key: %s\\%s",
8009 + unit_string, component_id_string);
8012 + len = sizeof (net_cfg_instance_id);
8013 + status = RegQueryValueEx(
8015 + net_cfg_instance_id_string,
8018 + net_cfg_instance_id,
8021 + if (status == ERROR_SUCCESS && data_type == REG_SZ)
8023 + if (!strcmp (component_id, TAP_COMPONENT_ID))
8025 + struct tap_reg *reg;
8026 + ALLOC_OBJ_CLEAR_GC (reg, struct tap_reg, gc);
8027 + reg->guid = string_alloc (net_cfg_instance_id, gc);
8029 + /* link into return list */
8038 + RegCloseKey (unit_key);
8043 + RegCloseKey (adapter_key);
8047 +const struct panel_reg *
8048 +get_panel_reg (struct gc_arena *gc)
8051 + HKEY network_connections_key;
8053 + struct panel_reg *first = NULL;
8054 + struct panel_reg *last = NULL;
8057 + status = RegOpenKeyEx(
8058 + HKEY_LOCAL_MACHINE,
8059 + NETWORK_CONNECTIONS_KEY,
8062 + &network_connections_key);
8064 + if (status != ERROR_SUCCESS)
8065 + msg (M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);
8069 + char enum_name[256];
8070 + char connection_string[256];
8071 + HKEY connection_key;
8072 + char name_data[256];
8074 + const char name_string[] = "Name";
8076 + len = sizeof (enum_name);
8077 + status = RegEnumKeyEx(
8078 + network_connections_key,
8086 + if (status == ERROR_NO_MORE_ITEMS)
8088 + else if (status != ERROR_SUCCESS)
8089 + msg (M_FATAL, "Error enumerating registry subkeys of key: %s",
8090 + NETWORK_CONNECTIONS_KEY);
8092 + openvpn_snprintf (connection_string, sizeof(connection_string),
8093 + "%s\\%s\\Connection",
8094 + NETWORK_CONNECTIONS_KEY, enum_name);
8096 + status = RegOpenKeyEx(
8097 + HKEY_LOCAL_MACHINE,
8098 + connection_string,
8103 + if (status != ERROR_SUCCESS)
8104 + dmsg (D_REGISTRY, "Error opening registry key: %s", connection_string);
8107 + len = sizeof (name_data);
8108 + status = RegQueryValueEx(
8116 + if (status != ERROR_SUCCESS || name_type != REG_SZ)
8117 + dmsg (D_REGISTRY, "Error opening registry key: %s\\%s\\%s",
8118 + NETWORK_CONNECTIONS_KEY, connection_string, name_string);
8121 + struct panel_reg *reg;
8123 + ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc);
8124 + reg->name = string_alloc (name_data, gc);
8125 + reg->guid = string_alloc (enum_name, gc);
8127 + /* link into return list */
8134 + RegCloseKey (connection_key);
8139 + RegCloseKey (network_connections_key);
8145 + * Check that two addresses are part of the same 255.255.255.252 subnet.
8148 +verify_255_255_255_252 (in_addr_t local, in_addr_t remote)
8150 + struct gc_arena gc = gc_new ();
8151 + const unsigned int mask = 3;
8152 + const char *err = NULL;
8154 + if (local == remote)
8156 + err = "must be different";
8159 + if ((local & (~mask)) != (remote & (~mask)))
8161 + err = "must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
8164 + if ((local & mask) == 0
8165 + || (local & mask) == 3
8166 + || (remote & mask) == 0
8167 + || (remote & mask) == 3)
8169 + err = "cannot use the first or last address within a given 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver";
8177 + msg (M_FATAL, "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s]. The local and remote VPN endpoints %s. Try '" PACKAGE " --show-valid-subnets' option for more info.",
8178 + print_in_addr_t (local, 0, &gc),
8179 + print_in_addr_t (remote, 0, &gc),
8184 +void show_valid_win32_tun_subnets (void)
8189 + printf ("On Windows, point-to-point IP support (i.e. --dev tun)\n");
8190 + printf ("is emulated by the TAP-Win32 driver. The major limitation\n");
8191 + printf ("imposed by this approach is that the --ifconfig local and\n");
8192 + printf ("remote endpoints must be part of the same 255.255.255.252\n");
8193 + printf ("subnet. The following list shows examples of endpoint\n");
8194 + printf ("pairs which satisfy this requirement. Only the final\n");
8195 + printf ("component of the IP address pairs is at issue.\n\n");
8196 + printf ("As an example, the following option would be correct:\n");
8197 + printf (" --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n");
8198 + printf (" --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n");
8199 + printf ("because [5,6] is part of the below list.\n\n");
8201 + for (i = 0; i < 256; i += 4)
8203 + printf("[%3d,%3d] ", i+1, i+2);
8215 +show_tap_win32_adapters (int msglev, int warnlev)
8217 + struct gc_arena gc = gc_new ();
8219 + bool warn_panel_null = false;
8220 + bool warn_panel_dup = false;
8221 + bool warn_tap_dup = false;
8225 + const struct tap_reg *tr;
8226 + const struct tap_reg *tr1;
8227 + const struct panel_reg *pr;
8229 + const struct tap_reg *tap_reg = get_tap_reg (&gc);
8230 + const struct panel_reg *panel_reg = get_panel_reg (&gc);
8232 + msg (msglev, "Available TAP-WIN32 adapters [name, GUID]:");
8234 + /* loop through each TAP-Win32 adapter registry entry */
8235 + for (tr = tap_reg; tr != NULL; tr = tr->next)
8239 + /* loop through each network connections entry in the control panel */
8240 + for (pr = panel_reg; pr != NULL; pr = pr->next)
8242 + if (!strcmp (tr->guid, pr->guid))
8244 + msg (msglev, "'%s' %s", pr->name, tr->guid);
8251 + warn_panel_dup = true;
8253 + else if (links == 0)
8255 + /* a TAP adapter exists without a link from the network
8256 + connections control panel */
8257 + warn_panel_null = true;
8258 + msg (msglev, "[NULL] %s", tr->guid);
8262 + /* check for TAP-Win32 adapter duplicated GUIDs */
8263 + for (tr = tap_reg; tr != NULL; tr = tr->next)
8265 + for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
8267 + if (tr != tr1 && !strcmp (tr->guid, tr1->guid))
8268 + warn_tap_dup = true;
8272 + /* warn on registry inconsistencies */
8274 + msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate GUIDs");
8276 + if (warn_panel_dup)
8277 + msg (warnlev, "WARNING: Some TAP-Win32 adapters have duplicate links from the Network Connections control panel");
8279 + if (warn_panel_null)
8280 + msg (warnlev, "WARNING: Some TAP-Win32 adapters have no link from the Network Connections control panel");
8286 + * Confirm that GUID is a TAP-Win32 adapter.
8289 +is_tap_win32 (const char *guid, const struct tap_reg *tap_reg)
8291 + const struct tap_reg *tr;
8293 + for (tr = tap_reg; tr != NULL; tr = tr->next)
8295 + if (guid && !strcmp (tr->guid, guid))
8302 +static const char *
8303 +guid_to_name (const char *guid, const struct panel_reg *panel_reg)
8305 + const struct panel_reg *pr;
8307 + for (pr = panel_reg; pr != NULL; pr = pr->next)
8309 + if (guid && !strcmp (pr->guid, guid))
8316 +static const char *
8317 +name_to_guid (const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg)
8319 + const struct panel_reg *pr;
8321 + for (pr = panel_reg; pr != NULL; pr = pr->next)
8323 + if (name && !strcmp (pr->name, name) && is_tap_win32 (pr->guid, tap_reg))
8331 +at_least_one_tap_win32 (const struct tap_reg *tap_reg)
8334 + msg (M_FATAL, "There are no TAP-Win32 adapters on this system. You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Win32 virtual ethernet adapter.");
8338 + * Get an adapter GUID and optional actual_name from the
8339 + * registry for the TAP device # = device_number.
8341 +static const char *
8342 +get_unspecified_device_guid (const int device_number,
8343 + char *actual_name,
8344 + int actual_name_size,
8345 + const struct tap_reg *tap_reg_src,
8346 + const struct panel_reg *panel_reg_src,
8347 + struct gc_arena *gc)
8349 + const struct tap_reg *tap_reg = tap_reg_src;
8350 + struct buffer ret = clear_buf ();
8351 + struct buffer actual = clear_buf ();
8354 + ASSERT (device_number >= 0);
8356 + /* Make sure we have at least one TAP adapter */
8360 + /* The actual_name output buffer may be NULL */
8363 + ASSERT (actual_name_size > 0);
8364 + buf_set_write (&actual, actual_name, actual_name_size);
8367 + /* Move on to specified device number */
8368 + for (i = 0; i < device_number; i++)
8370 + tap_reg = tap_reg->next;
8375 + /* Save Network Panel name (if exists) in actual_name */
8378 + const char *act = guid_to_name (tap_reg->guid, panel_reg_src);
8380 + buf_printf (&actual, "%s", act);
8382 + buf_printf (&actual, "%s", tap_reg->guid);
8385 + /* Save GUID for return value */
8386 + ret = alloc_buf_gc (256, gc);
8387 + buf_printf (&ret, "%s", tap_reg->guid);
8388 + return BSTR (&ret);
8392 + * Lookup a --dev-node adapter name in the registry
8393 + * returning the GUID and optional actual_name.
8395 +static const char *
8396 +get_device_guid (const char *name,
8397 + char *actual_name,
8398 + int actual_name_size,
8399 + const struct tap_reg *tap_reg,
8400 + const struct panel_reg *panel_reg,
8401 + struct gc_arena *gc)
8403 + struct buffer ret = alloc_buf_gc (256, gc);
8404 + struct buffer actual = clear_buf ();
8406 + /* Make sure we have at least one TAP adapter */
8410 + /* The actual_name output buffer may be NULL */
8413 + ASSERT (actual_name_size > 0);
8414 + buf_set_write (&actual, actual_name, actual_name_size);
8417 + /* Check if GUID was explicitly specified as --dev-node parameter */
8418 + if (is_tap_win32 (name, tap_reg))
8420 + const char *act = guid_to_name (name, panel_reg);
8421 + buf_printf (&ret, "%s", name);
8423 + buf_printf (&actual, "%s", act);
8425 + buf_printf (&actual, "%s", name);
8426 + return BSTR (&ret);
8429 + /* Lookup TAP adapter in network connections list */
8431 + const char *guid = name_to_guid (name, tap_reg, panel_reg);
8434 + buf_printf (&actual, "%s", name);
8435 + buf_printf (&ret, "%s", guid);
8436 + return BSTR (&ret);
8444 + * Get adapter info list
8446 +const IP_ADAPTER_INFO *
8447 +get_adapter_info_list (struct gc_arena *gc)
8450 + IP_ADAPTER_INFO *pi = NULL;
8453 + if ((status = GetAdaptersInfo (NULL, &size)) != ERROR_BUFFER_OVERFLOW)
8455 + msg (M_INFO, "GetAdaptersInfo #1 failed (status=%u) : %s",
8456 + (unsigned int)status,
8457 + strerror_win32 (status, gc));
8461 + pi = (PIP_ADAPTER_INFO) gc_malloc (size, false, gc);
8462 + if ((status = GetAdaptersInfo (pi, &size)) == NO_ERROR)
8466 + msg (M_INFO, "GetAdaptersInfo #2 failed (status=%u) : %s",
8467 + (unsigned int)status,
8468 + strerror_win32 (status, gc));
8474 +const IP_PER_ADAPTER_INFO *
8475 +get_per_adapter_info (const DWORD index, struct gc_arena *gc)
8478 + IP_PER_ADAPTER_INFO *pi = NULL;
8483 + if ((status = GetPerAdapterInfo (index, NULL, &size)) != ERROR_BUFFER_OVERFLOW)
8485 + msg (M_INFO, "GetPerAdapterInfo #1 failed (status=%u) : %s",
8486 + (unsigned int)status,
8487 + strerror_win32 (status, gc));
8491 + pi = (PIP_PER_ADAPTER_INFO) gc_malloc (size, false, gc);
8492 + if ((status = GetPerAdapterInfo ((ULONG)index, pi, &size)) == ERROR_SUCCESS)
8496 + msg (M_INFO, "GetPerAdapterInfo #2 failed (status=%u) : %s",
8497 + (unsigned int)status,
8498 + strerror_win32 (status, gc));
8505 +static const IP_INTERFACE_INFO *
8506 +get_interface_info_list (struct gc_arena *gc)
8509 + IP_INTERFACE_INFO *ii = NULL;
8512 + if ((status = GetInterfaceInfo (NULL, &size)) != ERROR_INSUFFICIENT_BUFFER)
8514 + msg (M_INFO, "GetInterfaceInfo #1 failed (status=%u) : %s",
8515 + (unsigned int)status,
8516 + strerror_win32 (status, gc));
8520 + ii = (PIP_INTERFACE_INFO) gc_malloc (size, false, gc);
8521 + if ((status = GetInterfaceInfo (ii, &size)) == NO_ERROR)
8525 + msg (M_INFO, "GetInterfaceInfo #2 failed (status=%u) : %s",
8526 + (unsigned int)status,
8527 + strerror_win32 (status, gc));
8533 +static const IP_ADAPTER_INDEX_MAP *
8534 +get_interface_info (DWORD index, struct gc_arena *gc)
8536 + const IP_INTERFACE_INFO *list = get_interface_info_list (gc);
8540 + for (i = 0; i < list->NumAdapters; ++i)
8542 + const IP_ADAPTER_INDEX_MAP *inter = &list->Adapter[i];
8543 + if (index == inter->Index)
8551 + * Given an adapter index, return a pointer to the
8552 + * IP_ADAPTER_INFO structure for that adapter.
8555 +const IP_ADAPTER_INFO *
8556 +get_adapter (const IP_ADAPTER_INFO *ai, DWORD index)
8558 + if (ai && index != (DWORD)~0)
8560 + const IP_ADAPTER_INFO *a;
8562 + /* find index in the linked list */
8563 + for (a = ai; a != NULL; a = a->Next)
8565 + if (a->Index == index)
8572 +const IP_ADAPTER_INFO *
8573 +get_adapter_info (DWORD index, struct gc_arena *gc)
8575 + return get_adapter (get_adapter_info_list (gc), index);
8579 +get_adapter_n_ip_netmask (const IP_ADAPTER_INFO *ai)
8584 + const IP_ADDR_STRING *ip = &ai->IpAddressList;
8598 +get_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const int n, in_addr_t *ip, in_addr_t *netmask)
8606 + const IP_ADDR_STRING *iplist = &ai->IpAddressList;
8614 + iplist = iplist->Next;
8619 + const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
8620 + const char *ip_str = iplist->IpAddress.String;
8621 + const char *netmask_str = iplist->IpMask.String;
8622 + bool succeed1 = false;
8623 + bool succeed2 = false;
8625 + if (ip_str && netmask_str && strlen (ip_str) && strlen (netmask_str))
8627 + *ip = getaddr (getaddr_flags, ip_str, 0, &succeed1, NULL);
8628 + *netmask = getaddr (getaddr_flags, netmask_str, 0, &succeed2, NULL);
8629 + ret = (succeed1 == true && succeed2 == true);
8638 +test_adapter_ip_netmask (const IP_ADAPTER_INFO *ai, const in_addr_t ip, const in_addr_t netmask)
8642 + in_addr_t ip_adapter = 0;
8643 + in_addr_t netmask_adapter = 0;
8644 + const bool status = get_adapter_ip_netmask (ai, 0, &ip_adapter, &netmask_adapter);
8645 + return (status && ip_adapter == ip && netmask_adapter == netmask);
8651 +const IP_ADAPTER_INFO *
8652 +get_tun_adapter (const struct tuntap *tt, const IP_ADAPTER_INFO *list)
8655 + return get_adapter (list, tt->adapter_index);
8661 +is_adapter_up (const struct tuntap *tt, const IP_ADAPTER_INFO *list)
8666 + const IP_ADAPTER_INFO *ai = get_tun_adapter (tt, list);
8670 + const int n = get_adapter_n_ip_netmask (ai);
8672 + /* loop once for every IP/netmask assigned to adapter */
8673 + for (i = 0; i < n; ++i)
8675 + in_addr_t ip, netmask;
8676 + if (get_adapter_ip_netmask (ai, i, &ip, &netmask))
8678 + if (tt->local && tt->adapter_netmask)
8680 + /* wait for our --ifconfig parms to match the actual adapter parms */
8681 + if (tt->local == ip && tt->adapter_netmask == netmask)
8686 + /* --ifconfig was not defined, maybe using a real DHCP server */
8687 + if (ip && netmask)
8694 + ret = true; /* this can occur when TAP adapter is bridged */
8700 +is_ip_in_adapter_subnet (const IP_ADAPTER_INFO *ai, const in_addr_t ip, in_addr_t *highest_netmask)
8705 + if (highest_netmask)
8706 + *highest_netmask = 0;
8710 + const int n = get_adapter_n_ip_netmask (ai);
8711 + for (i = 0; i < n; ++i)
8713 + in_addr_t adapter_ip, adapter_netmask;
8714 + if (get_adapter_ip_netmask (ai, i, &adapter_ip, &adapter_netmask))
8716 + if (adapter_ip && adapter_netmask && (ip & adapter_netmask) == (adapter_ip & adapter_netmask))
8718 + if (highest_netmask && adapter_netmask > *highest_netmask)
8719 + *highest_netmask = adapter_netmask;
8729 +adapter_index_of_ip (const IP_ADAPTER_INFO *list,
8730 + const in_addr_t ip,
8732 + in_addr_t *netmask)
8734 + struct gc_arena gc = gc_new ();
8736 + in_addr_t highest_netmask = 0;
8737 + bool first = true;
8746 + if (is_ip_in_adapter_subnet (list, ip, &hn))
8748 + if (first || hn > highest_netmask)
8750 + highest_netmask = hn;
8753 + ret = list->Index;
8756 + else if (hn == highest_netmask)
8762 + list = list->Next;
8765 + dmsg (D_ROUTE_DEBUG, "DEBUG: IP Locate: ip=%s nm=%s index=%d count=%d",
8766 + print_in_addr_t (ip, 0, &gc),
8767 + print_in_addr_t (highest_netmask, 0, &gc),
8769 + count ? *count : -1);
8771 + if (ret == ~0 && count)
8775 + *netmask = highest_netmask;
8782 + * Given an adapter index, return true if the adapter
8783 + * is DHCP disabled.
8786 +#define DHCP_STATUS_UNDEF 0
8787 +#define DHCP_STATUS_ENABLED 1
8788 +#define DHCP_STATUS_DISABLED 2
8791 +dhcp_status (DWORD index)
8793 + struct gc_arena gc = gc_new ();
8794 + int ret = DHCP_STATUS_UNDEF;
8797 + const IP_ADAPTER_INFO *ai = get_adapter_info (index, &gc);
8801 + if (ai->DhcpEnabled)
8802 + ret = DHCP_STATUS_ENABLED;
8804 + ret = DHCP_STATUS_DISABLED;
8812 + * Delete all temporary address/netmask pairs which were added
8813 + * to adapter (given by index) by previous calls to AddIPAddress.
8816 +delete_temp_addresses (DWORD index)
8818 + struct gc_arena gc = gc_new ();
8819 + const IP_ADAPTER_INFO *a = get_adapter_info (index, &gc);
8823 + const IP_ADDR_STRING *ip = &a->IpAddressList;
8827 + const DWORD context = ip->Context;
8829 + if ((status = DeleteIPAddress ((ULONG) context)) == NO_ERROR)
8831 + msg (M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s",
8832 + ip->IpAddress.String,
8833 + ip->IpMask.String);
8837 + const char *empty = "0.0.0.0";
8838 + if (strcmp (ip->IpAddress.String, empty)
8839 + || strcmp (ip->IpMask.String, empty))
8840 + msg (M_INFO, "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)",
8841 + ip->IpAddress.String,
8842 + ip->IpMask.String,
8843 + (unsigned int)status);
8852 + * Get interface index for use with IP Helper API functions.
8855 +get_adapter_index_method_1 (const char *guid)
8857 + struct gc_arena gc = gc_new ();
8860 + wchar_t wbuf[256];
8861 + snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);
8862 + wbuf [SIZE(wbuf) - 1] = 0;
8863 + if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR)
8870 +get_adapter_index_method_2 (const char *guid)
8872 + struct gc_arena gc = gc_new ();
8875 + const IP_ADAPTER_INFO *list = get_adapter_info_list (&gc);
8879 + if (!strcmp (guid, list->AdapterName))
8881 + index = list->Index;
8884 + list = list->Next;
8892 +get_adapter_index (const char *guid)
8895 + index = get_adapter_index_method_1 (guid);
8897 + index = get_adapter_index_method_2 (guid);
8899 + msg (M_INFO, "NOTE: could not get adapter index for %s", guid);
8904 +get_adapter_index_flexible (const char *name) /* actual name or GUID */
8906 + struct gc_arena gc = gc_new ();
8908 + index = get_adapter_index_method_1 (name);
8910 + index = get_adapter_index_method_2 (name);
8913 + const struct tap_reg *tap_reg = get_tap_reg (&gc);
8914 + const struct panel_reg *panel_reg = get_panel_reg (&gc);
8915 + const char *guid = name_to_guid (name, tap_reg, panel_reg);
8916 + index = get_adapter_index_method_1 (guid);
8918 + index = get_adapter_index_method_2 (guid);
8921 + msg (M_INFO, "NOTE: could not get adapter index for name/GUID '%s'", name);
8927 + * Return a string representing a PIP_ADDR_STRING
8929 +static const char *
8930 +format_ip_addr_string (const IP_ADDR_STRING *ip, struct gc_arena *gc)
8932 + struct buffer out = alloc_buf_gc (256, gc);
8935 + buf_printf (&out, "%s", ip->IpAddress.String);
8936 + if (strlen (ip->IpMask.String))
8938 + buf_printf (&out, "/");
8939 + buf_printf (&out, "%s", ip->IpMask.String);
8941 + buf_printf (&out, " ");
8944 + return BSTR (&out);
8948 + * Show info for a single adapter
8951 +show_adapter (int msglev, const IP_ADAPTER_INFO *a, struct gc_arena *gc)
8953 + msg (msglev, "%s", a->Description);
8954 + msg (msglev, " Index = %d", (int)a->Index);
8955 + msg (msglev, " GUID = %s", a->AdapterName);
8956 + msg (msglev, " IP = %s", format_ip_addr_string (&a->IpAddressList, gc));
8957 + msg (msglev, " MAC = %s", format_hex_ex (a->Address, a->AddressLength, 0, 1, ":", gc));
8958 + msg (msglev, " GATEWAY = %s", format_ip_addr_string (&a->GatewayList, gc));
8959 + if (a->DhcpEnabled)
8961 + msg (msglev, " DHCP SERV = %s", format_ip_addr_string (&a->DhcpServer, gc));
8962 + msg (msglev, " DHCP LEASE OBTAINED = %s", time_string (a->LeaseObtained, 0, false, gc));
8963 + msg (msglev, " DHCP LEASE EXPIRES = %s", time_string (a->LeaseExpires, 0, false, gc));
8967 + msg (msglev, " PRI WINS = %s", format_ip_addr_string (&a->PrimaryWinsServer, gc));
8968 + msg (msglev, " SEC WINS = %s", format_ip_addr_string (&a->SecondaryWinsServer, gc));
8972 + const IP_PER_ADAPTER_INFO *pai = get_per_adapter_info (a->Index, gc);
8975 + msg (msglev, " DNS SERV = %s", format_ip_addr_string (&pai->DnsServerList, gc));
8981 + * Show current adapter list
8984 +show_adapters (int msglev)
8986 + struct gc_arena gc = gc_new ();
8987 + const IP_ADAPTER_INFO *ai = get_adapter_info_list (&gc);
8989 + msg (msglev, "SYSTEM ADAPTER LIST");
8992 + const IP_ADAPTER_INFO *a;
8994 + /* find index in the linked list */
8995 + for (a = ai; a != NULL; a = a->Next)
8997 + show_adapter (msglev, a, &gc);
9004 + * Set a particular TAP-Win32 adapter (or all of them if
9005 + * adapter_name == NULL) to allow it to be opened from
9006 + * a non-admin account. This setting will only persist
9007 + * for the lifetime of the device object.
9011 +tap_allow_nonadmin_access_handle (const char *device_path, HANDLE hand)
9013 + struct security_attributes sa;
9016 + if (!init_security_attributes_allow_all (&sa))
9017 + msg (M_ERR, "Error: init SA failed");
9019 + status = SetKernelObjectSecurity (hand, DACL_SECURITY_INFORMATION, &sa.sd);
9022 + msg (M_ERRNO, "Error: SetKernelObjectSecurity failed on %s", device_path);
9026 + msg (M_INFO|M_NOPREFIX, "TAP-Win32 device: %s [Non-admin access allowed]", device_path);
9031 +tap_allow_nonadmin_access (const char *dev_node)
9033 + struct gc_arena gc = gc_new ();
9034 + const struct tap_reg *tap_reg = get_tap_reg (&gc);
9035 + const struct panel_reg *panel_reg = get_panel_reg (&gc);
9036 + const char *device_guid = NULL;
9038 + char actual_buffer[256];
9039 + char device_path[256];
9041 + at_least_one_tap_win32 (tap_reg);
9045 + /* Get the device GUID for the device specified with --dev-node. */
9046 + device_guid = get_device_guid (dev_node, actual_buffer, sizeof (actual_buffer), tap_reg, panel_reg, &gc);
9049 + msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node);
9051 + /* Open Windows TAP-Win32 adapter */
9052 + openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
9053 + USERMODEDEVICEDIR,
9057 + hand = CreateFile (
9060 + 0, /* was: FILE_SHARE_READ */
9063 + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
9067 + if (hand == INVALID_HANDLE_VALUE)
9068 + msg (M_ERR, "CreateFile failed on TAP device: %s", device_path);
9070 + tap_allow_nonadmin_access_handle (device_path, hand);
9071 + CloseHandle (hand);
9075 + int device_number = 0;
9077 + /* Try opening all TAP devices */
9080 + device_guid = get_unspecified_device_guid (device_number,
9082 + sizeof (actual_buffer),
9090 + /* Open Windows TAP-Win32 adapter */
9091 + openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
9092 + USERMODEDEVICEDIR,
9096 + hand = CreateFile (
9099 + 0, /* was: FILE_SHARE_READ */
9102 + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
9106 + if (hand == INVALID_HANDLE_VALUE)
9107 + msg (M_WARN, "CreateFile failed on TAP device: %s", device_path);
9110 + tap_allow_nonadmin_access_handle (device_path, hand);
9111 + CloseHandle (hand);
9121 + * DHCP release/renewal
9124 +dhcp_release_by_adapter_index(const DWORD adapter_index)
9126 + struct gc_arena gc = gc_new ();
9128 + const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (adapter_index, &gc);
9132 + DWORD status = IpReleaseAddress ((IP_ADAPTER_INDEX_MAP *)inter);
9133 + if (status == NO_ERROR)
9135 + msg (D_TUNTAP_INFO, "TAP: DHCP address released");
9139 + msg (M_WARN, "NOTE: Release of DHCP-assigned IP address lease on TAP-Win32 adapter failed: %s (code=%u)",
9140 + strerror_win32 (status, &gc),
9141 + (unsigned int)status);
9149 +dhcp_release (const struct tuntap *tt)
9151 + if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0)
9152 + return dhcp_release_by_adapter_index (tt->adapter_index);
9158 +dhcp_renew_by_adapter_index (const DWORD adapter_index)
9160 + struct gc_arena gc = gc_new ();
9162 + const IP_ADAPTER_INDEX_MAP *inter = get_interface_info (adapter_index, &gc);
9166 + DWORD status = IpRenewAddress ((IP_ADAPTER_INDEX_MAP *)inter);
9167 + if (status == NO_ERROR)
9169 + msg (D_TUNTAP_INFO, "TAP: DHCP address renewal succeeded");
9173 + msg (M_WARN, "WARNING: Failed to renew DHCP IP address lease on TAP-Win32 adapter: %s (code=%u)",
9174 + strerror_win32 (status, &gc),
9175 + (unsigned int)status);
9182 +dhcp_renew (const struct tuntap *tt)
9184 + if (tt && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ && tt->adapter_index != ~0)
9185 + return dhcp_renew_by_adapter_index (tt->adapter_index);
9195 +netsh_command (const struct argv *a, int n)
9198 + for (i = 0; i < n; ++i)
9201 + openvpn_sleep (1);
9202 + netcmd_semaphore_lock ();
9203 + argv_msg_prefix (M_INFO, a, "NETSH");
9204 + status = openvpn_execve_check (a, NULL, 0, "ERROR: netsh command failed");
9205 + netcmd_semaphore_release ();
9208 + openvpn_sleep (4);
9210 + msg (M_FATAL, "NETSH: command failed");
9214 +ipconfig_register_dns (const struct env_set *es)
9218 + const char err[] = "ERROR: Windows ipconfig command failed";
9220 + msg (D_TUNTAP_INFO, "Start net commands...");
9221 + netcmd_semaphore_lock ();
9223 + argv_init (&argv);
9225 + argv_printf (&argv, "%s%sc stop dnscache",
9226 + get_win_sys_path(),
9227 + WIN_NET_PATH_SUFFIX);
9228 + argv_msg (D_TUNTAP_INFO, &argv);
9229 + status = openvpn_execve_check (&argv, es, 0, err);
9230 + argv_reset(&argv);
9232 + argv_printf (&argv, "%s%sc start dnscache",
9233 + get_win_sys_path(),
9234 + WIN_NET_PATH_SUFFIX);
9235 + argv_msg (D_TUNTAP_INFO, &argv);
9236 + status = openvpn_execve_check (&argv, es, 0, err);
9237 + argv_reset(&argv);
9239 + argv_printf (&argv, "%s%sc /flushdns",
9240 + get_win_sys_path(),
9241 + WIN_IPCONFIG_PATH_SUFFIX);
9242 + argv_msg (D_TUNTAP_INFO, &argv);
9243 + status = openvpn_execve_check (&argv, es, 0, err);
9244 + argv_reset(&argv);
9246 + argv_printf (&argv, "%s%sc /registerdns",
9247 + get_win_sys_path(),
9248 + WIN_IPCONFIG_PATH_SUFFIX);
9249 + argv_msg (D_TUNTAP_INFO, &argv);
9250 + status = openvpn_execve_check (&argv, es, 0, err);
9251 + argv_reset(&argv);
9253 + netcmd_semaphore_release ();
9254 + msg (D_TUNTAP_INFO, "End net commands...");
9258 +ip_addr_string_to_array (in_addr_t *dest, int *dest_len, const IP_ADDR_STRING *src)
9263 + const unsigned int getaddr_flags = GETADDR_HOST_ORDER;
9264 + const char *ip_str = src->IpAddress.String;
9266 + bool succeed = false;
9268 + if (i >= *dest_len)
9270 + if (!ip_str || !strlen (ip_str))
9273 + ip = getaddr (getaddr_flags, ip_str, 0, &succeed, NULL);
9284 + struct gc_arena gc = gc_new ();
9285 + msg (M_INFO, "ip_addr_string_to_array [%d]", *dest_len);
9286 + for (i = 0; i < *dest_len; ++i)
9288 + msg (M_INFO, "%s", print_in_addr_t (dest[i], 0, &gc));
9296 +ip_addr_one_to_one (const in_addr_t *a1, const int a1len, const IP_ADDR_STRING *ias)
9299 + int a2len = SIZE(a2);
9302 + ip_addr_string_to_array (a2, &a2len, ias);
9303 + /*msg (M_INFO, "a1len=%d a2len=%d", a1len, a2len);*/
9304 + if (a1len != a2len)
9307 + for (i = 0; i < a1len; ++i)
9309 + if (a1[i] != a2[i])
9316 +ip_addr_member_of (const in_addr_t addr, const IP_ADDR_STRING *ias)
9319 + int len = SIZE(aa);
9322 + ip_addr_string_to_array (aa, &len, ias);
9323 + for (i = 0; i < len; ++i)
9325 + if (addr == aa[i])
9332 +netsh_ifconfig_options (const char *type,
9333 + const in_addr_t *addr_list,
9334 + const int addr_len,
9335 + const IP_ADDR_STRING *current,
9336 + const char *flex_name,
9337 + const bool test_first)
9339 + struct gc_arena gc = gc_new ();
9340 + struct argv argv = argv_new ();
9341 + bool delete_first = false;
9343 + /* first check if we should delete existing DNS/WINS settings from TAP interface */
9346 + if (!ip_addr_one_to_one (addr_list, addr_len, current))
9347 + delete_first = true;
9350 + delete_first = true;
9352 + /* delete existing DNS/WINS settings from TAP interface */
9355 + argv_printf (&argv, "%s%sc interface ip delete %s %s all",
9356 + get_win_sys_path(),
9357 + NETSH_PATH_SUFFIX,
9360 + netsh_command (&argv, 2);
9363 + /* add new DNS/WINS settings to TAP interface */
9367 + for (i = 0; i < addr_len; ++i)
9369 + if (delete_first || !test_first || !ip_addr_member_of (addr_list[i], current))
9371 + const char *fmt = count ?
9372 + "%s%sc interface ip add %s %s %s"
9373 + : "%s%sc interface ip set %s %s static %s";
9375 + argv_printf (&argv, fmt,
9376 + get_win_sys_path(),
9377 + NETSH_PATH_SUFFIX,
9380 + print_in_addr_t (addr_list[i], 0, &gc));
9381 + netsh_command (&argv, 2);
9387 + msg (M_INFO, "NETSH: \"%s\" %s %s [already set]",
9390 + print_in_addr_t (addr_list[i], 0, &gc));
9395 + argv_reset (&argv);
9400 +init_ip_addr_string2 (IP_ADDR_STRING *dest, const IP_ADDR_STRING *src1, const IP_ADDR_STRING *src2)
9407 + dest[0].Next = NULL;
9412 + dest[0].Next = &dest[1];
9413 + dest[1].Next = NULL;
9418 +netsh_ifconfig (const struct tuntap_options *to,
9419 + const char *flex_name,
9420 + const in_addr_t ip,
9421 + const in_addr_t netmask,
9422 + const unsigned int flags)
9424 + struct gc_arena gc = gc_new ();
9425 + struct argv argv = argv_new ();
9426 + const IP_ADAPTER_INFO *ai = NULL;
9427 + const IP_PER_ADAPTER_INFO *pai = NULL;
9429 + if (flags & NI_TEST_FIRST)
9431 + const IP_ADAPTER_INFO *list = get_adapter_info_list (&gc);
9432 + const int index = get_adapter_index_flexible (flex_name);
9433 + ai = get_adapter (list, index);
9434 + pai = get_per_adapter_info (index, &gc);
9437 + if (flags & NI_IP_NETMASK)
9439 + if (test_adapter_ip_netmask (ai, ip, netmask))
9441 + msg (M_INFO, "NETSH: \"%s\" %s/%s [already set]",
9443 + print_in_addr_t (ip, 0, &gc),
9444 + print_in_addr_t (netmask, 0, &gc));
9448 + /* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */
9449 + argv_printf (&argv, "%s%sc interface ip set address %s static %s %s",
9450 + get_win_sys_path(),
9451 + NETSH_PATH_SUFFIX,
9453 + print_in_addr_t (ip, 0, &gc),
9454 + print_in_addr_t (netmask, 0, &gc));
9456 + netsh_command (&argv, 4);
9460 + /* set WINS/DNS options */
9461 + if (flags & NI_OPTIONS)
9463 + IP_ADDR_STRING wins[2];
9467 + netsh_ifconfig_options ("dns",
9470 + pai ? &pai->DnsServerList : NULL,
9472 + BOOL_CAST (flags & NI_TEST_FIRST));
9473 + if (ai && ai->HaveWins)
9474 + init_ip_addr_string2 (wins, &ai->PrimaryWinsServer, &ai->SecondaryWinsServer);
9476 + netsh_ifconfig_options ("wins",
9481 + BOOL_CAST (flags & NI_TEST_FIRST));
9484 + argv_reset (&argv);
9489 +netsh_enable_dhcp (const struct tuntap_options *to,
9490 + const char *actual_name)
9493 + argv_init (&argv);
9495 + /* example: netsh interface ip set address my-tap dhcp */
9496 + argv_printf (&argv,
9497 + "%s%sc interface ip set address %s dhcp",
9498 + get_win_sys_path(),
9499 + NETSH_PATH_SUFFIX,
9502 + netsh_command (&argv, 4);
9504 + argv_reset (&argv);
9508 + * Return a TAP name for netsh commands.
9510 +static const char *
9511 +netsh_get_id (const char *dev_node, struct gc_arena *gc)
9513 + const struct tap_reg *tap_reg = get_tap_reg (gc);
9514 + const struct panel_reg *panel_reg = get_panel_reg (gc);
9515 + struct buffer actual = alloc_buf_gc (256, gc);
9518 + at_least_one_tap_win32 (tap_reg);
9522 + guid = get_device_guid (dev_node, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
9526 + guid = get_unspecified_device_guid (0, BPTR (&actual), BCAP (&actual), tap_reg, panel_reg, gc);
9528 + if (get_unspecified_device_guid (1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Win32 adapter */
9533 + return "NULL"; /* not found */
9534 + else if (strcmp (BPTR (&actual), "NULL"))
9535 + return BPTR (&actual); /* control panel name */
9537 + return guid; /* no control panel name, return GUID instead */
9541 + * Called iteratively on TAP-Win32 wait-for-initialization polling loop
9544 +tun_standby_init (struct tuntap *tt)
9546 + tt->standby_iter = 0;
9550 +tun_standby (struct tuntap *tt)
9553 + ++tt->standby_iter;
9554 + if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
9556 + if (tt->standby_iter == IPW32_SET_ADAPTIVE_TRY_NETSH)
9558 + msg (M_INFO, "NOTE: now trying netsh (this may take some time)");
9559 + netsh_ifconfig (&tt->options,
9562 + tt->adapter_netmask,
9563 + NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
9565 + else if (tt->standby_iter >= IPW32_SET_ADAPTIVE_TRY_NETSH*2)
9574 + * Convert DHCP options from the command line / config file
9575 + * into a raw DHCP-format options string.
9579 +write_dhcp_u8 (struct buffer *buf, const int type, const int data, bool *error)
9581 + if (!buf_safe (buf, 3))
9584 + msg (M_WARN, "write_dhcp_u8: buffer overflow building DHCP options");
9587 + buf_write_u8 (buf, type);
9588 + buf_write_u8 (buf, 1);
9589 + buf_write_u8 (buf, data);
9593 +write_dhcp_u32_array (struct buffer *buf, const int type, const uint32_t *data, const unsigned int len, bool *error)
9598 + const int size = len * sizeof (uint32_t);
9600 + if (!buf_safe (buf, 2 + size))
9603 + msg (M_WARN, "write_dhcp_u32_array: buffer overflow building DHCP options");
9606 + if (size < 1 || size > 255)
9609 + msg (M_WARN, "write_dhcp_u32_array: size (%d) must be > 0 and <= 255", size);
9612 + buf_write_u8 (buf, type);
9613 + buf_write_u8 (buf, size);
9614 + for (i = 0; i < len; ++i)
9615 + buf_write_u32 (buf, data[i]);
9620 +write_dhcp_str (struct buffer *buf, const int type, const char *str, bool *error)
9622 + const int len = strlen (str);
9623 + if (!buf_safe (buf, 2 + len))
9626 + msg (M_WARN, "write_dhcp_str: buffer overflow building DHCP options");
9629 + if (len < 1 || len > 255)
9632 + msg (M_WARN, "write_dhcp_str: string '%s' must be > 0 bytes and <= 255 bytes", str);
9635 + buf_write_u8 (buf, type);
9636 + buf_write_u8 (buf, len);
9637 + buf_write (buf, str, len);
9641 +build_dhcp_options_string (struct buffer *buf, const struct tuntap_options *o)
9643 + bool error = false;
9645 + write_dhcp_str (buf, 15, o->domain, &error);
9647 + if (o->netbios_scope)
9648 + write_dhcp_str (buf, 47, o->netbios_scope, &error);
9650 + if (o->netbios_node_type)
9651 + write_dhcp_u8 (buf, 46, o->netbios_node_type, &error);
9653 + write_dhcp_u32_array (buf, 6, (uint32_t*)o->dns, o->dns_len, &error);
9654 + write_dhcp_u32_array (buf, 44, (uint32_t*)o->wins, o->wins_len, &error);
9655 + write_dhcp_u32_array (buf, 42, (uint32_t*)o->ntp, o->ntp_len, &error);
9656 + write_dhcp_u32_array (buf, 45, (uint32_t*)o->nbdd, o->nbdd_len, &error);
9658 + /* the MS DHCP server option 'Disable Netbios-over-TCP/IP
9659 + is implemented as vendor option 001, value 002.
9660 + A value of 001 means 'leave NBT alone' which is the default */
9661 + if (o->disable_nbt)
9663 + if (!buf_safe (buf, 8))
9665 + msg (M_WARN, "build_dhcp_options_string: buffer overflow building DHCP options");
9668 + buf_write_u8 (buf, 43);
9669 + buf_write_u8 (buf, 6); /* total length field */
9670 + buf_write_u8 (buf, 0x001);
9671 + buf_write_u8 (buf, 4); /* length of the vendor specified field */
9672 + buf_write_u32 (buf, 0x002);
9678 +fork_dhcp_action (struct tuntap *tt)
9680 + if (tt->options.dhcp_pre_release || tt->options.dhcp_renew)
9682 + struct gc_arena gc = gc_new ();
9683 + struct buffer cmd = alloc_buf_gc (256, &gc);
9684 + const int verb = 3;
9685 + const int pre_sleep = 1;
9687 + buf_printf (&cmd, "openvpn --verb %d --tap-sleep %d", verb, pre_sleep);
9688 + if (tt->options.dhcp_pre_release)
9689 + buf_printf (&cmd, " --dhcp-pre-release");
9690 + if (tt->options.dhcp_renew)
9691 + buf_printf (&cmd, " --dhcp-renew");
9692 + buf_printf (&cmd, " --dhcp-internal %u", (unsigned int)tt->adapter_index);
9694 + fork_to_self (BSTR (&cmd));
9700 +fork_register_dns_action (struct tuntap *tt)
9702 + if (tt && tt->options.register_dns)
9704 + struct gc_arena gc = gc_new ();
9705 + struct buffer cmd = alloc_buf_gc (256, &gc);
9706 + const int verb = 3;
9708 + buf_printf (&cmd, "openvpn --verb %d --register-dns --rdns-internal", verb);
9709 + fork_to_self (BSTR (&cmd));
9715 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
9717 + struct gc_arena gc = gc_new ();
9718 + char device_path[256];
9719 + const char *device_guid = NULL;
9721 + bool dhcp_masq = false;
9722 + bool dhcp_masq_post = false;
9724 + /*netcmd_semaphore_lock ();*/
9726 + msg( M_INFO, "open_tun, tt->ipv6=%d", tt->ipv6 );
9728 + if (tt->type == DEV_TYPE_NULL)
9734 + else if (tt->type == DEV_TYPE_TAP || tt->type == DEV_TYPE_TUN)
9740 + msg (M_FATAL|M_NOPREFIX, "Unknown virtual device type: '%s'", dev);
9744 + * Lookup the device name in the registry, using the --dev-node high level name.
9747 + const struct tap_reg *tap_reg = get_tap_reg (&gc);
9748 + const struct panel_reg *panel_reg = get_panel_reg (&gc);
9749 + char actual_buffer[256];
9751 + at_least_one_tap_win32 (tap_reg);
9755 + /* Get the device GUID for the device specified with --dev-node. */
9756 + device_guid = get_device_guid (dev_node, actual_buffer, sizeof (actual_buffer), tap_reg, panel_reg, &gc);
9759 + msg (M_FATAL, "TAP-Win32 adapter '%s' not found", dev_node);
9761 + /* Open Windows TAP-Win32 adapter */
9762 + openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
9763 + USERMODEDEVICEDIR,
9767 + tt->hand = CreateFile (
9769 + GENERIC_READ | GENERIC_WRITE,
9770 + 0, /* was: FILE_SHARE_READ */
9773 + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
9777 + if (tt->hand == INVALID_HANDLE_VALUE)
9778 + msg (M_ERR, "CreateFile failed on TAP device: %s", device_path);
9782 + int device_number = 0;
9784 + /* Try opening all TAP devices until we find one available */
9787 + device_guid = get_unspecified_device_guid (device_number,
9789 + sizeof (actual_buffer),
9795 + msg (M_FATAL, "All TAP-Win32 adapters on this system are currently in use.");
9797 + /* Open Windows TAP-Win32 adapter */
9798 + openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",
9799 + USERMODEDEVICEDIR,
9803 + tt->hand = CreateFile (
9805 + GENERIC_READ | GENERIC_WRITE,
9806 + 0, /* was: FILE_SHARE_READ */
9809 + FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
9813 + if (tt->hand == INVALID_HANDLE_VALUE)
9814 + msg (D_TUNTAP_INFO, "CreateFile failed on TAP device: %s", device_path);
9822 + /* translate high-level device name into a device instance
9823 + GUID using the registry */
9824 + tt->actual_name = string_alloc (actual_buffer, NULL);
9827 + msg (M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path);
9828 + tt->adapter_index = get_adapter_index (device_guid);
9830 + /* get driver version info */
9834 + if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_VERSION,
9835 + &info, sizeof (info),
9836 + &info, sizeof (info), &len, NULL))
9838 + msg (D_TUNTAP_INFO, "TAP-Win32 Driver Version %d.%d %s",
9841 + (info[2] ? "(DEBUG)" : ""));
9844 + if (!(info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR))
9845 + msg (M_FATAL, "ERROR: This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.",
9846 + TAP_WIN32_MIN_MAJOR,
9847 + TAP_WIN32_MIN_MINOR);
9849 + /* tap driver 9.8 (2.2.0 and 2.2.1 release) is buggy
9851 + if ( tt->type == DEV_TYPE_TUN &&
9852 + info[0] == 9 && info[1] == 8)
9854 + msg( M_FATAL, "ERROR: Tap-Win32 driver version %d.%d is buggy regarding small IPv4 packets in TUN mode. Upgrade to Tap-Win32 9.9 (2.2.2 release or later) or use TAP mode", (int) info[0], (int) info[1] );
9858 + /* get driver MTU */
9861 + if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_MTU,
9862 + &mtu, sizeof (mtu),
9863 + &mtu, sizeof (mtu), &len, NULL))
9865 + tt->post_open_mtu = (int) mtu;
9866 + msg (D_MTU_INFO, "TAP-Win32 MTU=%d", (int) mtu);
9871 + * Preliminaries for setting TAP-Win32 adapter TCP/IP
9872 + * properties via --ip-win32 dynamic or --ip-win32 adaptive.
9874 + if (tt->did_ifconfig_setup)
9876 + if (tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)
9879 + * If adapter is set to non-DHCP, set to DHCP mode.
9881 + if (dhcp_status (tt->adapter_index) == DHCP_STATUS_DISABLED)
9882 + netsh_enable_dhcp (&tt->options, tt->actual_name);
9884 + dhcp_masq_post = true;
9886 + else if (tt->options.ip_win32_type == IPW32_SET_ADAPTIVE)
9889 + * If adapter is set to non-DHCP, use netsh right away.
9891 + if (dhcp_status (tt->adapter_index) != DHCP_STATUS_ENABLED)
9893 + netsh_ifconfig (&tt->options,
9896 + tt->adapter_netmask,
9897 + NI_TEST_FIRST|NI_IP_NETMASK|NI_OPTIONS);
9906 + /* set point-to-point mode if TUN device */
9908 + if (tt->type == DEV_TYPE_TUN)
9910 + if (!tt->did_ifconfig_setup)
9912 + msg (M_FATAL, "ERROR: --dev tun also requires --ifconfig");
9915 + if (tt->topology == TOP_SUBNET)
9920 + ep[0] = htonl (tt->local);
9921 + ep[1] = htonl (tt->local & tt->remote_netmask);
9922 + ep[2] = htonl (tt->remote_netmask);
9924 + status = DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_TUN,
9926 + ep, sizeof (ep), &len, NULL);
9928 + msg (status ? M_INFO : M_FATAL, "Set TAP-Win32 TUN subnet mode network/local/netmask = %s/%s/%s [%s]",
9929 + print_in_addr_t (ep[1], IA_NET_ORDER, &gc),
9930 + print_in_addr_t (ep[0], IA_NET_ORDER, &gc),
9931 + print_in_addr_t (ep[2], IA_NET_ORDER, &gc),
9932 + status ? "SUCCEEDED" : "FAILED");
9937 + ep[0] = htonl (tt->local);
9938 + ep[1] = htonl (tt->remote_netmask);
9940 + if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_POINT_TO_POINT,
9942 + ep, sizeof (ep), &len, NULL))
9943 + msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun");
9947 + /* should we tell the TAP-Win32 driver to masquerade as a DHCP server as a means
9948 + of setting the adapter address? */
9953 + /* We will answer DHCP requests with a reply to set IP/subnet to these values */
9954 + ep[0] = htonl (tt->local);
9955 + ep[1] = htonl (tt->adapter_netmask);
9957 + /* At what IP address should the DHCP server masquerade at? */
9958 + if (tt->type == DEV_TYPE_TUN)
9960 + if (tt->topology == TOP_SUBNET)
9962 + const in_addr_t netmask_inv = ~tt->remote_netmask;
9963 + ep[2] = netmask_inv ? htonl ((tt->local | netmask_inv) - 1) : 0;
9966 + ep[2] = htonl (tt->remote_netmask);
9968 + if (tt->options.dhcp_masq_custom_offset)
9969 + msg (M_WARN, "WARNING: because you are using '--dev tun' mode, the '--ip-win32 dynamic [offset]' option is ignoring the offset parameter");
9973 + in_addr_t dsa; /* DHCP server addr */
9975 + ASSERT (tt->type == DEV_TYPE_TAP);
9977 + if (tt->options.dhcp_masq_offset < 0)
9978 + dsa = (tt->local | (~tt->adapter_netmask)) + tt->options.dhcp_masq_offset;
9980 + dsa = (tt->local & tt->adapter_netmask) + tt->options.dhcp_masq_offset;
9982 + if (dsa == tt->local)
9983 + msg (M_FATAL, "ERROR: There is a clash between the --ifconfig local address and the internal DHCP server address -- both are set to %s -- please use the --ip-win32 dynamic option to choose a different free address from the --ifconfig subnet for the internal DHCP server", print_in_addr_t (dsa, 0, &gc));
9985 + if ((tt->local & tt->adapter_netmask) != (dsa & tt->adapter_netmask))
9986 + msg (M_FATAL, "ERROR: --tap-win32 dynamic [offset] : offset is outside of --ifconfig subnet");
9988 + ep[2] = htonl (dsa);
9991 + /* lease time in seconds */
9992 + ep[3] = (uint32_t) tt->options.dhcp_lease_time;
9994 + ASSERT (ep[3] > 0);
9996 +#ifndef SIMULATE_DHCP_FAILED /* this code is disabled to simulate bad DHCP negotiation */
9997 + if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ,
9999 + ep, sizeof (ep), &len, NULL))
10000 + msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set TAP_IOCTL_CONFIG_DHCP_MASQ mode");
10002 + msg (M_INFO, "Notified TAP-Win32 driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]",
10003 + print_in_addr_t (tt->local, 0, &gc),
10004 + print_in_addr_t (tt->adapter_netmask, 0, &gc),
10006 + print_in_addr_t (ep[2], IA_NET_ORDER, &gc),
10010 + /* user-supplied DHCP options capability */
10011 + if (tt->options.dhcp_options)
10013 + struct buffer buf = alloc_buf (256);
10014 + if (build_dhcp_options_string (&buf, &tt->options))
10016 + msg (D_DHCP_OPT, "DHCP option string: %s", format_hex (BPTR (&buf), BLEN (&buf), 0, &gc));
10017 + if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
10018 + BPTR (&buf), BLEN (&buf),
10019 + BPTR (&buf), BLEN (&buf), &len, NULL))
10020 + msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a TAP_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");
10023 + msg (M_WARN, "DHCP option string not set due to error");
10029 + /* set driver media status to 'connected' */
10031 + ULONG status = TRUE;
10032 + if (!DeviceIoControl (tt->hand, TAP_IOCTL_SET_MEDIA_STATUS,
10033 + &status, sizeof (status),
10034 + &status, sizeof (status), &len, NULL))
10035 + msg (M_WARN, "WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");
10038 + /* possible wait for adapter to come up */
10040 + int s = tt->options.tap_sleep;
10043 + msg (M_INFO, "Sleeping for %d seconds...", s);
10044 + openvpn_sleep (s);
10048 + /* possibly use IP Helper API to set IP address on adapter */
10050 + const DWORD index = tt->adapter_index;
10052 + /* flush arp cache */
10053 + if (index != (DWORD)~0)
10057 + if ((status = FlushIpNetTable (index)) == NO_ERROR)
10058 + msg (M_INFO, "Successful ARP Flush on interface [%u] %s",
10059 + (unsigned int)index,
10062 + msg (D_TUNTAP_INFO, "NOTE: FlushIpNetTable failed on interface [%u] %s (status=%u) : %s",
10063 + (unsigned int)index,
10065 + (unsigned int)status,
10066 + strerror_win32 (status, &gc));
10070 + * If the TAP-Win32 driver is masquerading as a DHCP server
10071 + * make sure the TCP/IP properties for the adapter are
10074 + if (dhcp_masq_post)
10076 + /* check dhcp enable status */
10077 + if (dhcp_status (index) == DHCP_STATUS_DISABLED)
10078 + msg (M_WARN, "WARNING: You have selected '--ip-win32 dynamic', which will not work unless the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
10080 + /* force an explicit DHCP lease renewal on TAP adapter? */
10081 + if (tt->options.dhcp_pre_release)
10082 + dhcp_release (tt);
10083 + if (tt->options.dhcp_renew)
10087 + fork_dhcp_action (tt);
10089 + if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_IPAPI)
10092 + const char *error_suffix = "I am having trouble using the Windows 'IP helper API' to automatically set the IP address -- consider using other --ip-win32 methods (not 'ipapi')";
10094 + /* couldn't get adapter index */
10095 + if (index == (DWORD)~0)
10097 + msg (M_FATAL, "ERROR: unable to get adapter index for interface %s -- %s",
10102 + /* check dhcp enable status */
10103 + if (dhcp_status (index) == DHCP_STATUS_DISABLED)
10104 + msg (M_WARN, "NOTE: You have selected (explicitly or by default) '--ip-win32 ipapi', which has a better chance of working correctly if the TAP-Win32 TCP/IP properties are set to 'Obtain an IP address automatically'");
10106 + /* delete previously added IP addresses which were not
10107 + correctly deleted */
10108 + delete_temp_addresses (index);
10110 + /* add a new IP address */
10111 + if ((status = AddIPAddress (htonl(tt->local),
10112 + htonl(tt->adapter_netmask),
10114 + &tt->ipapi_context,
10115 + &tt->ipapi_instance)) == NO_ERROR)
10116 + msg (M_INFO, "Succeeded in adding a temporary IP/netmask of %s/%s to interface %s using the Win32 IP Helper API",
10117 + print_in_addr_t (tt->local, 0, &gc),
10118 + print_in_addr_t (tt->adapter_netmask, 0, &gc),
10122 + msg (M_FATAL, "ERROR: AddIPAddress %s/%s failed on interface %s, index=%d, status=%u (windows error: '%s') -- %s",
10123 + print_in_addr_t (tt->local, 0, &gc),
10124 + print_in_addr_t (tt->adapter_netmask, 0, &gc),
10127 + (unsigned int)status,
10128 + strerror_win32 (status, &gc),
10130 + tt->ipapi_context_defined = true;
10133 + /*netcmd_semaphore_release ();*/
10138 +tap_win32_getinfo (const struct tuntap *tt, struct gc_arena *gc)
10140 + if (tt && tt->hand != NULL)
10142 + struct buffer out = alloc_buf_gc (256, gc);
10144 + if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_INFO,
10145 + BSTR (&out), BCAP (&out),
10146 + BSTR (&out), BCAP (&out),
10149 + return BSTR (&out);
10156 +tun_show_debug (struct tuntap *tt)
10158 + if (tt && tt->hand != NULL)
10160 + struct buffer out = alloc_buf (1024);
10162 + while (DeviceIoControl (tt->hand, TAP_IOCTL_GET_LOG_LINE,
10163 + BSTR (&out), BCAP (&out),
10164 + BSTR (&out), BCAP (&out),
10167 + msg (D_TAP_WIN32_DEBUG, "TAP-Win32: %s", BSTR (&out));
10174 +close_tun (struct tuntap *tt)
10176 + struct gc_arena gc = gc_new ();
10180 + if ( tt->ipv6 && tt->did_ifconfig_ipv6_setup )
10182 + struct argv argv;
10183 + argv_init (&argv);
10185 + /* remove route pointing to interface */
10186 + delete_route_connected_v6_net(tt, NULL);
10188 + /* netsh interface ipv6 delete address \"%s\" %s */
10189 + const char * ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc);
10190 + argv_printf (&argv,
10191 + "%s%sc interface ipv6 delete address %s %s",
10192 + get_win_sys_path(),
10193 + NETSH_PATH_SUFFIX,
10195 + ifconfig_ipv6_local );
10197 + netsh_command (&argv, 1);
10198 + argv_reset (&argv);
10201 + if (tt->ipapi_context_defined)
10204 + if ((status = DeleteIPAddress (tt->ipapi_context)) != NO_ERROR)
10206 + msg (M_WARN, "Warning: DeleteIPAddress[%u] failed on TAP-Win32 adapter, status=%u : %s",
10207 + (unsigned int)tt->ipapi_context,
10208 + (unsigned int)status,
10209 + strerror_win32 (status, &gc));
10214 + if (tt->options.dhcp_release)
10215 + dhcp_release (tt);
10217 + if (tt->hand != NULL)
10219 + dmsg (D_WIN32_IO_LOW, "Attempting CancelIO on TAP-Win32 adapter");
10220 + if (!CancelIo (tt->hand))
10221 + msg (M_WARN | M_ERRNO, "Warning: CancelIO failed on TAP-Win32 adapter");
10224 + dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped read event on TAP-Win32 adapter");
10225 + overlapped_io_close (&tt->reads);
10227 + dmsg (D_WIN32_IO_LOW, "Attempting close of overlapped write event on TAP-Win32 adapter");
10228 + overlapped_io_close (&tt->writes);
10230 + if (tt->hand != NULL)
10232 + dmsg (D_WIN32_IO_LOW, "Attempting CloseHandle on TAP-Win32 adapter");
10233 + if (!CloseHandle (tt->hand))
10234 + msg (M_WARN | M_ERRNO, "Warning: CloseHandle failed on TAP-Win32 adapter");
10237 + if (tt->actual_name)
10238 + free (tt->actual_name);
10240 + clear_tuntap (tt);
10247 + * Convert --ip-win32 constants between index and ascii form.
10250 +struct ipset_names {
10251 + const char *short_form;
10254 +/* Indexed by IPW32_SET_x */
10255 +static const struct ipset_names ipset_names[] = {
10264 +ascii2ipset (const char* name)
10267 + ASSERT (IPW32_SET_N == SIZE (ipset_names));
10268 + for (i = 0; i < IPW32_SET_N; ++i)
10269 + if (!strcmp (name, ipset_names[i].short_form))
10275 +ipset2ascii (int index)
10277 + ASSERT (IPW32_SET_N == SIZE (ipset_names));
10278 + if (index < 0 || index >= IPW32_SET_N)
10279 + return "[unknown --ip-win32 type]";
10281 + return ipset_names[index].short_form;
10285 +ipset2ascii_all (struct gc_arena *gc)
10287 + struct buffer out = alloc_buf_gc (256, gc);
10290 + ASSERT (IPW32_SET_N == SIZE (ipset_names));
10291 + for (i = 0; i < IPW32_SET_N; ++i)
10294 + buf_printf(&out, " ");
10295 + buf_printf(&out, "[%s]", ipset2ascii(i));
10297 + return BSTR (&out);
10300 +#else /* generic */
10303 +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
10305 + open_tun_generic (dev, dev_type, dev_node, false, true, tt);
10309 +close_tun (struct tuntap* tt)
10313 + close_tun_generic (tt);
10319 +write_tun (struct tuntap* tt, uint8_t *buf, int len)
10321 + return write (tt->fd, buf, len);
10325 +read_tun (struct tuntap* tt, uint8_t *buf, int len)
10327 + return read (tt->fd, buf, len);
10331 diff -durN openvpn-2.2.2.orig/tun.h openvpn-2.2.2/tun.h
10332 --- openvpn-2.2.2.orig/tun.h 2011-12-13 17:58:56.000000000 +0100
10333 +++ openvpn-2.2.2/tun.h 2012-06-01 10:40:28.000000000 +0200
10334 @@ -130,6 +130,7 @@
10335 int topology; /* one of the TOP_x values */
10337 bool did_ifconfig_setup;
10338 + bool did_ifconfig_ipv6_setup;
10342 @@ -146,6 +147,10 @@
10343 in_addr_t remote_netmask;
10344 in_addr_t broadcast;
10346 + struct in6_addr local_ipv6;
10347 + struct in6_addr remote_ipv6;
10348 + int netbits_ipv6;
10352 struct overlapped_io reads;
10353 @@ -197,7 +202,7 @@
10354 void clear_tuntap (struct tuntap *tuntap);
10356 void open_tun (const char *dev, const char *dev_type, const char *dev_node,
10357 - bool ipv6, struct tuntap *tt);
10358 + struct tuntap *tt);
10360 void close_tun (struct tuntap *tt);
10362 @@ -206,7 +211,7 @@
10363 int read_tun (struct tuntap* tt, uint8_t *buf, int len);
10365 void tuncfg (const char *dev, const char *dev_type, const char *dev_node,
10366 - bool ipv6, int persist_mode, const char *username,
10367 + int persist_mode, const char *username,
10368 const char *groupname, const struct tuntap_options *options);
10370 const char *guess_tuntap_dev (const char *dev,
10371 @@ -219,6 +224,8 @@
10372 int topology, /* one of the TOP_x values */
10373 const char *ifconfig_local_parm, /* --ifconfig parm 1 */
10374 const char *ifconfig_remote_netmask_parm, /* --ifconfig parm 2 */
10375 + const char *ifconfig_ipv6_local_parm, /* --ifconfig parm 1 / IPv6 */
10376 + const char *ifconfig_ipv6_remote_parm, /* --ifconfig parm 2 / IPv6 */
10377 in_addr_t local_public,
10378 in_addr_t remote_public,
10379 const bool strict_warn,
10380 diff -durN openvpn-2.2.2.orig/win32.c openvpn-2.2.2/win32.c
10381 --- openvpn-2.2.2.orig/win32.c 2011-12-13 17:58:56.000000000 +0100
10382 +++ openvpn-2.2.2/win32.c 2012-06-01 10:40:28.000000000 +0200
10383 @@ -874,16 +874,21 @@
10385 env_block (const struct env_set *es)
10387 + char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem";
10391 struct env_item *e;
10395 + bool path_seen = false;
10397 for (e = es->list; e != NULL; e = e->next)
10398 nchars += strlen (e->string) + 1;
10400 + nchars += strlen(force_path)+1;
10402 ret = (char *) malloc (nchars);
10403 check_malloc_return (ret);
10405 @@ -895,7 +900,18 @@
10406 strcpy (p, e->string);
10407 p += strlen (e->string) + 1;
10409 + if ( strncmp(e->string, "PATH=", 5 ) == 0 )
10410 + path_seen = true;
10413 + /* make sure PATH is set */
10414 + if ( !path_seen )
10416 + msg( M_INFO, "env_block: add %s", force_path );
10417 + strcpy( p, force_path );
10418 + p += strlen(force_path) + 1;
10424 diff -durN openvpn-2.2.2.orig/win32.h openvpn-2.2.2/win32.h
10425 --- openvpn-2.2.2.orig/win32.h 2011-12-13 17:58:56.000000000 +0100
10426 +++ openvpn-2.2.2/win32.h 2012-06-01 10:40:28.000000000 +0200
10427 @@ -269,6 +269,8 @@
10429 /* call self in a subprocess */
10430 void fork_to_self (const char *cmdline);
10431 +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
10432 +int inet_pton(int af, const char *src, void *st);
10434 /* Find temporary directory */
10435 const char *win_get_tempdir();