Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 123249 Details for
Bug 183457
net-misc/openvpn UDPv6 patch
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
openvpn-2.1-udp6.patch
openvpn-2.1-udp6.patch (text/plain), 75.44 KB, created by
Marcel Pennewiß
on 2007-06-27 20:57:38 UTC
(
hide
)
Description:
openvpn-2.1-udp6.patch
Filename:
MIME Type:
Creator:
Marcel Pennewiß
Created:
2007-06-27 20:57:38 UTC
Size:
75.44 KB
patch
obsolete
>diff --git a/jjo-tests/libtest.sh b/jjo-tests/libtest.sh >new file mode 100755 >index 0000000..ab0d4b5 >--- /dev/null >+++ b/jjo-tests/libtest.sh >@@ -0,0 +1,115 @@ >+#!/bin/bash >+ >+typeset -i test_num=0 # increments w/each test_define >+typeset test_msg # prefix: "test nr#" for msgs >+typeset test_name # test name given >+typeset test_sanename # test name with all whitespace (and alike) replaced by '_' >+ >+TEST_CLEANUP=":" >+ >+say () { >+ echo "$@" >&3 >+} >+err () { >+ echo "$@" >&4 >+} >+debug () { >+ echo "$@" >&4 >+} >+test_define() { >+ test_name="$*" >+ test_sanename="$(echo -n $test_name| tr -c '[A-Za-z0-9._]' _ )" >+ test_num=test_num+1 >+ test_msg="test $test_num" >+ test_bg_cleanup >+} >+test_expect_success () { >+ local msg="$1" >+ test $# -ge 2 || { err "usage error: test_expect_failure msg cmd args ..."; return 1; } >+ say -n "$test_msg: -- $msg (expecting success) " >+ shift >+ (eval "$@" 4>&1) && { say -e "\n$test_msg: OK %%% $test_sanename" ; return 0 ; } >+ say -e "\n$test_msg: FAILED %%% $test_sanename" >+ return 1 >+} >+ >+test_expect_failure () { >+ local msg="$1" >+ test $# -ge 2 || { err "usage error: test_expect_failure msg cmd args ..."; return 1;} >+ say -n "$test_msg: -- $msg (expecting failure) " >+ shift >+ (eval "$@") && { say -e "\n$test_msg: FAILED %%% $test_sanename" >&3 ; return 0 ; } >+ say -e "\n$test_msg: OK %%% $test_sanename" >+ return 1 >+} >+ >+test_bg_egrep() { >+ local nsecs="$1" >+ local txt="$2" >+ local ret >+ shift 2 >+ test_expect_success "$test_name" \ >+ "set -m ; $@ &> $t/out-$test_sanename & >+ s=1; >+ for i in \$(seq 1 $nsecs);do >+ say -n '.' >+ kill -0 %1 || { egrep failed $t/out-$test_sanename >&4; break; } >+ o=\$(egrep \"$txt\" $t/out-$test_sanename ) && { debug \$o; s=0; break; } >+ sleep 1; >+ done; >+ kill %1 >+ wait >+ exit \$s >+ " 2>/dev/null 4>$t/err >+ ret=$? >+ test $ret -eq 0 && return 0 >+ say "$test_msg: see: $t/out-$test_sanename*" >+ return $ret >+} >+# run command in *current* shell ignoring stderr, evals args passed >+quiet2() { >+ #backup fd=2 >+ exec 250>&2 >+ exec 2>/dev/null >+ eval "$@" >+ #close auxfd >+ exec 2>&250 >+ exec 250>&- >+} >+test_bg_prev(){ local out=$t/out-$test_sanename-prev; $@ >& $out & } >+test_bg_cleanup() { quiet2 "$TEST_CLEANUP;${@:-:};kill % 2>/dev/null;wait" ;} >+test_set_cleanup () { TEST_CLEANUP="${*:-:}" ;} >+ >+t=/tmp >+exec 3>&1 >+exec 4>&2 >+ >+#========= >+ >+ln -sf $PWD/openvpn $t/openvpn-test >+export OPENVPN=$t/openvpn-test >+ >+test_set_cleanup "killall $OPENVPN" >+ >+trap 'test_bg_cleanup;exit' 0 2 15 >+ >+test_define "UDP6 loopback" >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-udp6-0-loopback-self.sh >+ >+test_define "UDP6 loopback byname" >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-udp6-0-loopback-byname.sh >+ >+test_define "TCP6 loopback" >+test_bg_prev ../jjo-tests/run-tcp6-0-loopback-server.sh >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-tcp6-0-loopback-client.sh >+ >+test_define "TCP6 loopback byname" >+test_bg_prev ../jjo-tests/run-tcp6-0-loopback-server-byname.sh >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-tcp6-0-loopback-client-byname.sh >+ >+test_define "UDP4 loopback" >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-udp4-0-loopback-self.sh >+ >+test_define "TCP4 loopback" >+test_bg_prev ../jjo-tests/run-tcp4-0-loopback-server.sh >+test_bg_egrep 30 "Initialization Sequence Completed" ../jjo-tests/run-tcp4-0-loopback-client.sh >diff --git a/jjo-tests/qemu-ifup-2.jjo.sh b/jjo-tests/qemu-ifup-2.jjo.sh >new file mode 100755 >index 0000000..60418ad >--- /dev/null >+++ b/jjo-tests/qemu-ifup-2.jjo.sh >@@ -0,0 +1,12 @@ >+#!/bin/sh -x >+#sudo sh -c "/sbin/ifconfig $1 hw ether 00:00:00:00:00:01; /sbin/ifconfig $1 192.168.254.1" >+export PATH=/sbin:/usr/sbin:$PATH >+NUM=2 >+DEV=qemutun$NUM >+sudo sh -x <<EOF >+ip li set $1 name $DEV >+ip li set $DEV address 00:00:00:00:00:01 >+ip li set $DEV up >+ip ad add 192.168.254.1 dev $DEV >+ip ro add 192.168.254.$NUM dev $DEV >+EOF >diff --git a/jjo-tests/qemu-ifup-3.jjo.sh b/jjo-tests/qemu-ifup-3.jjo.sh >new file mode 100755 >index 0000000..56c2f33 >--- /dev/null >+++ b/jjo-tests/qemu-ifup-3.jjo.sh >@@ -0,0 +1,12 @@ >+#!/bin/sh -x >+#sudo sh -c "/sbin/ifconfig $1 hw ether 00:00:00:00:00:01; /sbin/ifconfig $1 192.168.254.1" >+export PATH=/sbin:/usr/sbin:$PATH >+NUM=3 >+DEV=qemutun$NUM >+sudo sh -x <<EOF >+ip li set $1 name $DEV >+ip li set $DEV address 00:00:00:00:00:01 >+ip li set $DEV up >+ip ad add 192.168.254.1 dev $DEV >+ip ro add 192.168.254.$NUM dev $DEV >+EOF >diff --git a/jjo-tests/run-afunix-0-loop.sh b/jjo-tests/run-afunix-0-loop.sh >new file mode 100755 >index 0000000..ed50691 >--- /dev/null >+++ b/jjo-tests/run-afunix-0-loop.sh >@@ -0,0 +1,4 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+rm -fv /tmp/o.s >+${OPENVPN} --proto unix-dgram --local /tmp/o.s --remote /tmp/o.s --dev tun --ifconfig 1.1.1.1 1.1.1.2 --secret ../openvpn.key $* >diff --git a/jjo-tests/run-afunix-1-o1.sh b/jjo-tests/run-afunix-1-o1.sh >new file mode 100755 >index 0000000..3f1df0f >--- /dev/null >+++ b/jjo-tests/run-afunix-1-o1.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --proto unix-dgram --local /tmp/o1.s --remote /tmp/o2.s --dev tun --ifconfig 1.1.1.1 1.1.1.2 --secret ../openvpn.key $* >diff --git a/jjo-tests/run-afunix-1-o2.sh b/jjo-tests/run-afunix-1-o2.sh >new file mode 100755 >index 0000000..6e94213 >--- /dev/null >+++ b/jjo-tests/run-afunix-1-o2.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --proto unix-dgram --local /tmp/o2.s --remote /tmp/o1.s --dev tun --ifconfig 1.1.1.2 1.1.1.1 --secret ../openvpn.key $* >diff --git a/jjo-tests/run-oxg-1.sh b/jjo-tests/run-oxg-1.sh >new file mode 100755 >index 0000000..21fd02f >--- /dev/null >+++ b/jjo-tests/run-oxg-1.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev tun --proto udp --remote localhost --lport 5020 --rport 1194 --secret ../openvpn.key --ifconfig 1.1.1.1 1.1.1.2 "$@" >diff --git a/jjo-tests/run-oxg-2.sh b/jjo-tests/run-oxg-2.sh >new file mode 100755 >index 0000000..aea6345 >--- /dev/null >+++ b/jjo-tests/run-oxg-2.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev tun --proto udp --remote localhost --lport 5020 --rport 1194 --secret ../openvpn.key --ifconfig 1.1.1.2 1.1.1.1 "$@" >diff --git a/jjo-tests/run-tcp4-0-loopback-client.sh b/jjo-tests/run-tcp4-0-loopback-client.sh >new file mode 100755 >index 0000000..956d437 >--- /dev/null >+++ b/jjo-tests/run-tcp4-0-loopback-client.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp-client --remote localhost --rport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-tcp4-0-loopback-server.sh b/jjo-tests/run-tcp4-0-loopback-server.sh >new file mode 100755 >index 0000000..0cab380 >--- /dev/null >+++ b/jjo-tests/run-tcp4-0-loopback-server.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp-server --remote localhost --lport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-tcp6-0-loopback-client-byname.sh b/jjo-tests/run-tcp6-0-loopback-client-byname.sh >new file mode 100755 >index 0000000..f8b2cdd >--- /dev/null >+++ b/jjo-tests/run-tcp6-0-loopback-client-byname.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp6-client --remote ip6-localhost --rport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-tcp6-0-loopback-client.sh b/jjo-tests/run-tcp6-0-loopback-client.sh >new file mode 100755 >index 0000000..09851c5 >--- /dev/null >+++ b/jjo-tests/run-tcp6-0-loopback-client.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp6-client --remote ::1 --rport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-tcp6-0-loopback-server-byname.sh b/jjo-tests/run-tcp6-0-loopback-server-byname.sh >new file mode 100755 >index 0000000..8fead3c >--- /dev/null >+++ b/jjo-tests/run-tcp6-0-loopback-server-byname.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp6-server --local ip6-localhost --lport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-tcp6-0-loopback-server.sh b/jjo-tests/run-tcp6-0-loopback-server.sh >new file mode 100755 >index 0000000..ad36555 >--- /dev/null >+++ b/jjo-tests/run-tcp6-0-loopback-server.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${OPENVPN} --dev null --proto tcp6-server --local :: --lport 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-udp4-0-loopback-self.sh b/jjo-tests/run-udp4-0-loopback-self.sh >new file mode 100755 >index 0000000..7a29a3d >--- /dev/null >+++ b/jjo-tests/run-udp4-0-loopback-self.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev null --proto udp --remote localhost --port 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-udp4-1-qemu-guest.sh b/jjo-tests/run-udp4-1-qemu-guest.sh >new file mode 100755 >index 0000000..adcb641 >--- /dev/null >+++ b/jjo-tests/run-udp4-1-qemu-guest.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev tun --proto udp --remote 10.0.2.2 --port 5011 --secret ../openvpn.key --ifconfig 1.1.1.253 1.1.1.1 >diff --git a/jjo-tests/run-udp4-1-qemu-host.sh b/jjo-tests/run-udp4-1-qemu-host.sh >new file mode 100755 >index 0000000..8db45f2 >--- /dev/null >+++ b/jjo-tests/run-udp4-1-qemu-host.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev tun --proto udp --float --port 5011 --secret ../openvpn.key --ifconfig 1.1.1.1 1.1.1.253 >diff --git a/jjo-tests/run-udp4-2-MH.sh b/jjo-tests/run-udp4-2-MH.sh >new file mode 100755 >index 0000000..5358fbc >--- /dev/null >+++ b/jjo-tests/run-udp4-2-MH.sh >@@ -0,0 +1,4 @@ >+#!/bin/sh -x >+#pass --local ADDR --remote ADDR >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev tun --proto udp --port 5011 --secret ../openvpn.key --ifconfig-noexec "$@" >diff --git a/jjo-tests/run-udp6-0-loopback-byname.sh b/jjo-tests/run-udp6-0-loopback-byname.sh >new file mode 100755 >index 0000000..993eec9 >--- /dev/null >+++ b/jjo-tests/run-udp6-0-loopback-byname.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev null --proto udp6 --remote ip6-localhost --port 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-udp6-0-loopback-self.sh b/jjo-tests/run-udp6-0-loopback-self.sh >new file mode 100755 >index 0000000..469bc39 >--- /dev/null >+++ b/jjo-tests/run-udp6-0-loopback-self.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev null --proto udp6 --remote ::1 --port 5011 --secret ../openvpn.key "$@" >diff --git a/jjo-tests/run-udp6-1-carpediem.sh b/jjo-tests/run-udp6-1-carpediem.sh >new file mode 100755 >index 0000000..bcce35e >--- /dev/null >+++ b/jjo-tests/run-udp6-1-carpediem.sh >@@ -0,0 +1,4 @@ >+#!/bin/sh -x >+REM6="fe80::2e0:7dff:fee3:ef17" >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --dev tun --proto udp6 --remote "$REM6" --port 5010 --secret ../openvpn.key --ifconfig 1.1.1.253 1.1.1.1 >diff --git a/jjo-tests/run-udp6-1-cx.sh b/jjo-tests/run-udp6-1-cx.sh >new file mode 100755 >index 0000000..ab69ea8 >--- /dev/null >+++ b/jjo-tests/run-udp6-1-cx.sh >@@ -0,0 +1,3 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+${GDB} ${OPENVPN} --verb 5 --dev tun --proto udp6 --port 5010 --secret /home/jjo/src/juanjo/openvpn/openvpn.key --float --ifconfig 1.1.1.1 1.1.1.253 >diff --git a/jjo-tests/run-udp6-2-qemu-guest.sh b/jjo-tests/run-udp6-2-qemu-guest.sh >new file mode 100755 >index 0000000..0e280a7 >--- /dev/null >+++ b/jjo-tests/run-udp6-2-qemu-guest.sh >@@ -0,0 +1,8 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+case "$1" in >+--freebsd) shift;set -- ed0 "$@";; >+--openbsd) shift;set -- ne3 --dev tun0 "$@";; >+esac >+DEV=${1:?missing devname};shift >+${GDB} ${OPENVPN} --dev tun --proto udp6 --remote fe80::200:ff:fe00:1%$DEV --port 5010 --secret ../openvpn.key "$@" --ifconfig 1.1.1.253 1.1.1.1 >diff --git a/jjo-tests/run-udp6-2-qemu-host.sh b/jjo-tests/run-udp6-2-qemu-host.sh >new file mode 100755 >index 0000000..500f0d3 >--- /dev/null >+++ b/jjo-tests/run-udp6-2-qemu-host.sh >@@ -0,0 +1,4 @@ >+#!/bin/sh -x >+: ${OPENVPN:=./openvpn} >+DEV=${1:?missing devname};shift >+${GDB} ${OPENVPN} --dev tun --proto udp6 --remote fe80::5054:ff:fe12:3456%$DEV --port 5010 --secret ../openvpn.key --ifconfig 1.1.1.1 1.1.1.253 "$@" >diff --git a/openvpn/buffer.c b/openvpn/buffer.c >index 64307ef..0650745 100644 >--- a/openvpn/buffer.c >+++ b/openvpn/buffer.c >@@ -198,6 +198,19 @@ buf_printf (struct buffer *buf, const ch > } > } > >+void buf_puts(struct buffer *buf, const char *str) >+{ >+ uint8_t *ptr = BEND (buf); >+ int cap = buf_forward_capacity (buf); >+ if (cap > 0) >+ { >+ strncpynt ((char *)ptr,str, cap); >+ *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ >+ buf->len += (int) strlen ((char *)ptr); >+ } >+} >+ >+ > /* > * This is necessary due to certain buggy implementations of snprintf, > * that don't guarantee null termination for size > 0. >diff --git a/openvpn/configure.ac b/openvpn/configure.ac >index 8843a2c..8cea204 100644 >--- a/openvpn/configure.ac >+++ b/openvpn/configure.ac >@@ -101,6 +101,12 @@ AC_ARG_ENABLE(multihome, > [MULTIHOME="yes"] > ) > >+AC_ARG_ENABLE(ipv6, >+ [ --disable-ipv6 Disable UDP/IPv6 support], >+ [PF_INET6="$enableval"], >+ [PF_INET6="yes"] >+) >+ > AC_ARG_ENABLE(port-share, > [ --disable-port-share Disable TCP server port-share support (--port-share)], > [PORT_SHARE="$enableval"], >@@ -406,6 +412,16 @@ LDFLAGS="$LDFLAGS -Wl,--fatal-warnings" > AC_CHECK_FUNCS(epoll_create, AC_DEFINE([HAVE_EPOLL_CREATE], 1, [])) > LDFLAGS="$OLDLDFLAGS" > >+dnl ipv6 support >+if test "$PF_INET6" = "yes"; then >+ AC_CHECKING([for struct sockaddr_in6 for IPv6 support]) >+ AC_CHECK_TYPE( >+ [struct sockaddr_in6], >+ [AC_DEFINE(USE_PF_INET6, 1, [struct sockaddr_in6 is needed for IPv6 peer support])], >+ [], >+ [#include "syshead.h"]) >+fi >+ > dnl > dnl check for valgrind tool > dnl >diff --git a/openvpn/helper.c b/openvpn/helper.c >index d2b3d6f..459f00d 100644 >--- a/openvpn/helper.c >+++ b/openvpn/helper.c >@@ -358,6 +358,10 @@ #endif /* P2MP_SERVER */ > > if (o->proto == PROTO_TCPv4) > o->proto = PROTO_TCPv4_CLIENT; >+#ifdef USE_PF_INET6 >+ else if (o->proto == PROTO_TCPv6) >+ o->proto = PROTO_TCPv6_CLIENT; >+#endif > } > > #endif /* P2MP */ >diff --git a/openvpn/init.c b/openvpn/init.c >index 244f03c..0d929e4 100644 >--- a/openvpn/init.c >+++ b/openvpn/init.c >@@ -703,7 +703,7 @@ #ifdef ENABLE_MANAGEMENT > const char *detail = "SUCCESS"; > if (c->c1.tuntap) > tun_local = c->c1.tuntap->local; >- tun_remote = htonl (c->c1.link_socket_addr.actual.dest.sa.sin_addr.s_addr); >+ tun_remote = htonl (c->c1.link_socket_addr.actual.dest.addr.in4.sin_addr.s_addr); > if (flags & ISC_ERRORS) > detail = "ERROR"; > management_set_state (management, >@@ -1105,7 +1105,7 @@ do_deferred_options (struct context *c, > #ifdef ENABLE_OCC > if (found & OPT_P_EXPLICIT_NOTIFY) > { >- if (c->options.proto != PROTO_UDPv4 && c->options.explicit_exit_notification) >+ if (!proto_is_udp(c->options.proto) && c->options.explicit_exit_notification) > { > msg (D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp"); > c->options.explicit_exit_notification = 0; >@@ -1200,12 +1200,21 @@ #endif > switch (c->options.proto) > { > case PROTO_UDPv4: >+#ifdef USE_PF_INET6 >+ case PROTO_UDPv6: >+#endif > if (proxy) > sec = c->options.connect_retry_seconds; > break; >+#ifdef USE_PF_INET6 >+ case PROTO_TCPv6_SERVER: >+#endif > case PROTO_TCPv4_SERVER: > sec = 1; > break; >+#ifdef USE_PF_INET6 >+ case PROTO_TCPv6_CLIENT: >+#endif > case PROTO_TCPv4_CLIENT: > sec = c->options.connect_retry_seconds; > break; >@@ -2292,7 +2301,7 @@ do_setup_fast_io (struct context *c) > #ifdef WIN32 > msg (M_INFO, "NOTE: --fast-io is disabled since we are running on Windows"); > #else >- if (c->options.proto != PROTO_UDPv4) >+ if (!proto_is_udp(c->options.proto)) > msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP"); > else > { >@@ -2549,7 +2558,11 @@ init_instance (struct context *c, const > /* link_socket_mode allows CM_CHILD_TCP > instances to inherit acceptable fds > from a top-level parent */ >+#ifdef USE_PF_INET6 >+ if (c->options.proto == PROTO_TCPv4_SERVER || c->options.proto == PROTO_TCPv6_SERVER) >+#else > if (c->options.proto == PROTO_TCPv4_SERVER) >+#endif > { > if (c->mode == CM_TOP) > link_socket_mode = LS_MODE_TCP_LISTEN; >@@ -2809,17 +2822,7 @@ inherit_context_child (struct context *d > { > CLEAR (*dest); > >- switch (src->options.proto) >- { >- case PROTO_UDPv4: >- dest->mode = CM_CHILD_UDP; >- break; >- case PROTO_TCPv4_SERVER: >- dest->mode = CM_CHILD_TCP; >- break; >- default: >- ASSERT (0); >- } >+ dest->mode = proto_is_dgram(src->options.proto)? CM_CHILD_UDP : CM_CHILD_TCP; > > dest->gc = gc_new (); > >@@ -2924,7 +2927,7 @@ #endif > dest->c2.buffers_owned = false; > > dest->c2.event_set = NULL; >- if (src->options.proto == PROTO_UDPv4) >+ if (proto_is_dgram(src->options.proto)) > do_event_set_init (dest, false); > } > >diff --git a/openvpn/manage.c b/openvpn/manage.c >index 993afa2..2615137 100644 >--- a/openvpn/manage.c >+++ b/openvpn/manage.c >@@ -1351,9 +1351,9 @@ man_settings_init (struct man_settings * > /* > * Initialize socket address > */ >- ms->local.sa.sin_family = AF_INET; >- ms->local.sa.sin_addr.s_addr = 0; >- ms->local.sa.sin_port = htons (port); >+ ms->local.addr.in4.sin_family = AF_INET; >+ ms->local.addr.in4.sin_addr.s_addr = 0; >+ ms->local.addr.in4.sin_port = htons (port); > > /* > * Run management over tunnel, or >@@ -1365,7 +1365,7 @@ man_settings_init (struct man_settings * > } > else > { >- ms->local.sa.sin_addr.s_addr = getaddr >+ ms->local.addr.in4.sin_addr.s_addr = getaddr > (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL); > } > >@@ -1634,7 +1634,7 @@ management_post_tunnel_open (struct mana > && man->connection.state == MS_INITIAL) > { > /* listen on our local TUN/TAP IP address */ >- man->settings.local.sa.sin_addr.s_addr = htonl (tun_local_ip); >+ man->settings.local.addr.in4.sin_addr.s_addr = htonl (tun_local_ip); > man_connection_init (man); > } > >diff --git a/openvpn/mroute.c b/openvpn/mroute.c >index a7d1215..8d85518 100644 >--- a/openvpn/mroute.c >+++ b/openvpn/mroute.c >@@ -175,25 +175,47 @@ bool mroute_extract_openvpn_sockaddr (st > const struct openvpn_sockaddr *osaddr, > bool use_port) > { >- if (osaddr->sa.sin_family == AF_INET) >+ switch (osaddr->addr.sa.sa_family) >+ { >+ case AF_INET: > { > if (use_port) > { > addr->type = MR_ADDR_IPV4 | MR_WITH_PORT; > addr->netbits = 0; > addr->len = 6; >- memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4); >- memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2); >+ memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4); >+ memcpy (addr->addr + 4, &osaddr->addr.in4.sin_port, 2); > } > else > { > addr->type = MR_ADDR_IPV4; > addr->netbits = 0; > addr->len = 4; >- memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4); >+ memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4); > } > return true; > } >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ if (use_port) >+ { >+ addr->type = MR_ADDR_IPV6 | MR_WITH_PORT; >+ addr->netbits = 0; >+ addr->len = 18; >+ memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16); >+ memcpy (addr->addr + 16, &osaddr->addr.in6.sin6_port, 2); >+ } >+ else >+ { >+ addr->type = MR_ADDR_IPV6; >+ addr->netbits = 0; >+ addr->len = 16; >+ memcpy (addr->addr, &osaddr->addr.in6.sin6_addr, 16); >+ } >+ return true; >+#endif >+ } > return false; > } > >@@ -268,7 +290,37 @@ mroute_addr_print (const struct mroute_a > } > break; > case MR_ADDR_IPV6: >+#ifdef USE_PF_INET6 >+ { >+ struct buffer buf; >+ struct sockaddr_in6 sin6; >+ int port; >+ char buf6[INET6_ADDRSTRLEN] = ""; >+ memset(&sin6, 0, sizeof sin6); >+ sin6.sin6_family = AF_INET6; >+ buf_set_read (&buf, maddr.addr, maddr.len); >+ if (buf_read(&buf, &sin6.sin6_addr, sizeof (sin6.sin6_addr))) >+ { >+ if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct sockaddr_in6), >+ buf6, sizeof (buf6), NULL, 0, NI_NUMERICHOST) != 0) >+ { >+ buf_printf (&out, "MR_ADDR_IPV6 getnameinfo() err"); >+ break; >+ } >+ buf_puts (&out, buf6); >+ if (maddr.type & MR_WITH_NETBITS) >+ buf_printf (&out, "/%d", maddr.netbits); >+ if (maddr.type & MR_WITH_PORT) >+ { >+ port = buf_read_u16 (&buf); >+ if (port >= 0) >+ buf_printf (&out, ":%d", port); >+ } >+ } >+ } >+#else /* old pre IPV6 1-line code: */ > buf_printf (&out, "IPV6"); >+#endif > break; > default: > buf_printf (&out, "UNKNOWN"); >diff --git a/openvpn/mtcp.c b/openvpn/mtcp.c >index 6ec9974..5011688 100644 >--- a/openvpn/mtcp.c >+++ b/openvpn/mtcp.c >@@ -159,6 +159,7 @@ multi_tcp_instance_specific_init (struct > ASSERT (mi->context.c2.link_socket); > ASSERT (mi->context.c2.link_socket->info.lsa); > ASSERT (mi->context.c2.link_socket->mode == LS_MODE_TCP_ACCEPT_FROM); >+ ASSERT (mi->context.c2.link_socket->info.lsa->actual.dest.addr.sa.sa_family == AF_INET); > if (!mroute_extract_openvpn_sockaddr (&mi->real, &mi->context.c2.link_socket->info.lsa->actual.dest, true)) > { > msg (D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined"); >diff --git a/openvpn/multi.c b/openvpn/multi.c >index ee74a46..bfd79b3 100644 >--- a/openvpn/multi.c >+++ b/openvpn/multi.c >@@ -990,8 +990,8 @@ multi_learn_in_addr_t (struct multi_cont > struct mroute_addr addr; > > CLEAR (remote_si); >- remote_si.sa.sin_family = AF_INET; >- remote_si.sa.sin_addr.s_addr = htonl (a); >+ remote_si.addr.in4.sin_family = AF_INET; >+ remote_si.addr.in4.sin_addr.s_addr = htonl (a); > ASSERT (mroute_extract_openvpn_sockaddr (&addr, &remote_si, false)); > > if (netbits >= 0) >@@ -2224,9 +2224,9 @@ management_callback_kill_by_addr (void * > int count = 0; > > CLEAR (saddr); >- saddr.sa.sin_family = AF_INET; >- saddr.sa.sin_addr.s_addr = htonl (addr); >- saddr.sa.sin_port = htons (port); >+ saddr.addr.in4.sin_family = AF_INET; >+ saddr.addr.in4.sin_addr.s_addr = htonl (addr); >+ saddr.addr.in4.sin_port = htons (port); > if (mroute_extract_openvpn_sockaddr (&maddr, &saddr, true)) > { > hash_iterator_init (m->iter, &hi, true); >@@ -2287,18 +2287,13 @@ tunnel_server (struct context *top) > { > ASSERT (top->options.mode == MODE_SERVER); > >- switch (top->options.proto) { >- case PROTO_UDPv4: >- tunnel_server_udp (top); >- break; >- case PROTO_TCPv4_SERVER: >- tunnel_server_tcp (top); >- break; >- default: >- ASSERT (0); >- } >+ if (proto_is_dgram(top->options.proto)) >+ tunnel_server_udp(top); >+ else >+ tunnel_server_tcp(top); > } > >+ > #else > static void dummy(void) {} > #endif /* P2MP_SERVER */ >diff --git a/openvpn/occ.c b/openvpn/occ.c >index 6b136dc..3ec7784 100644 >--- a/openvpn/occ.c >+++ b/openvpn/occ.c >@@ -375,7 +375,7 @@ process_received_occ_msg (struct context > c->c2.max_send_size_remote, > c->c2.max_recv_size_local); > if (!c->options.fragment >- && c->options.proto == PROTO_UDPv4 >+ && (proto_is_dgram(c->options.proto)) > && c->c2.max_send_size_local > TUN_MTU_MIN > && (c->c2.max_recv_size_remote < c->c2.max_send_size_local > || c->c2.max_recv_size_local < c->c2.max_send_size_remote)) >diff --git a/openvpn/options.c b/openvpn/options.c >index 94da98e..1490009 100644 >--- a/openvpn/options.c >+++ b/openvpn/options.c >@@ -73,6 +73,12 @@ #endif > #ifdef USE_PTHREAD > " [PTHREAD]" > #endif >+#ifdef ENABLE_IP_PKTINFO >+ " [MH]" >+#endif >+#ifdef USE_PF_INET6 >+ " [PF_INET6]" >+#endif > " built on " __DATE__ > ; > >@@ -93,6 +99,9 @@ static const char usage_message[] = > "--mode m : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n" > "--proto p : Use protocol p for communicating with peer.\n" > " p = udp (default), tcp-server, or tcp-client\n" >+#ifdef USE_PF_INET6 >+ " p = udp6, tcp6-server, or tcp6-client (IPv6)\n" >+#endif > "--connect-retry n : For --proto tcp-client, number of seconds to wait\n" > " between connection retries (default=%d).\n" > "--connect-timeout n : For --proto tcp-client, connection timeout (in seconds).\n" >@@ -1421,10 +1430,10 @@ #endif > * Sanity check on TCP mode options > */ > >- if (options->connect_retry_defined && options->proto != PROTO_TCPv4_CLIENT) >+ if (options->connect_retry_defined && options->proto != PROTO_TCPv4_CLIENT && options->proto != PROTO_TCPv6_CLIENT) > msg (M_USAGE, "--connect-retry doesn't make sense unless also used with --proto tcp-client"); > >- if (options->connect_timeout_defined && options->proto != PROTO_TCPv4_CLIENT) >+ if (options->connect_timeout_defined && options->proto != PROTO_TCPv4_CLIENT && options->proto != PROTO_TCPv6_CLIENT) > msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with --proto tcp-client"); > > /* >@@ -1434,7 +1443,7 @@ #endif > msg (M_USAGE, "only one of --tun-mtu or --link-mtu may be defined (note that --ifconfig implies --link-mtu %d)", LINK_MTU_DEFAULT); > > #ifdef ENABLE_OCC >- if (options->proto != PROTO_UDPv4 && options->mtu_test) >+ if (!proto_is_udp(options->proto) && options->mtu_test) > msg (M_USAGE, "--mtu-test only makes sense with --proto udp"); > #endif > >@@ -1479,7 +1488,8 @@ #endif > const char *remote = l->array[i].hostname; > const int remote_port = l->array[i].port; > >- if (string_defined_equal (options->local, remote) >+ if (proto_is_net(options->proto) >+ && string_defined_equal (options->local, remote) > && options->local_port == remote_port) > msg (M_USAGE, "--remote and --local addresses are the same"); > >@@ -1508,7 +1518,7 @@ #endif > if (!options->remote_list && !options->bind_local) > msg (M_USAGE, "--nobind doesn't make sense unless used with --remote"); > >- if (options->proto == PROTO_TCPv4_CLIENT && !options->local && !options->local_port_defined && !options->bind_defined) >+ if ((options->proto == PROTO_TCPv4_CLIENT||options->proto == PROTO_TCPv6_CLIENT) && !options->local && !options->local_port_defined && !options->bind_defined) > options->bind_local = false; > > #ifdef ENABLE_SOCKS >@@ -1565,16 +1575,16 @@ #endif > */ > > #ifdef ENABLE_FRAGMENT >- if (options->proto != PROTO_UDPv4 && options->fragment) >+ if (!proto_is_udp(options->proto) && options->fragment) > msg (M_USAGE, "--fragment can only be used with --proto udp"); > #endif > > #ifdef ENABLE_OCC >- if (options->proto != PROTO_UDPv4 && options->explicit_exit_notification) >+ if (!proto_is_udp(options->proto) && options->explicit_exit_notification) > msg (M_USAGE, "--explicit-exit-notify can only be used with --proto udp"); > #endif > >- if (!options->remote_list && options->proto == PROTO_TCPv4_CLIENT) >+ if (!options->remote_list && (options->proto == PROTO_TCPv4_CLIENT||options->proto == PROTO_TCPv6_CLIENT)) > msg (M_USAGE, "--remote MUST be used in TCP Client mode"); > > #ifdef ENABLE_HTTP_PROXY >@@ -1592,7 +1602,8 @@ #ifdef ENABLE_SOCKS > msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode"); > #endif > >- if (options->proto == PROTO_TCPv4_SERVER && remote_list_len (options->remote_list) > 1) >+ if ((options->proto == PROTO_TCPv4_SERVER||options->proto == PROTO_TCPv6_SERVER) >+ && remote_list_len (options->remote_list) > 1) > msg (M_USAGE, "TCP server mode allows at most one --remote address"); > > #if P2MP_SERVER >@@ -1617,7 +1628,7 @@ #endif > msg (M_USAGE, "--mode server only works with --dev tun or --dev tap"); > if (options->pull) > msg (M_USAGE, "--pull cannot be used with --mode server"); >- if (!(options->proto == PROTO_UDPv4 || options->proto == PROTO_TCPv4_SERVER)) >+ if (!(proto_is_udp(options->proto) || options->proto == PROTO_TCPv4_SERVER || options->proto == PROTO_TCPv6_SERVER)) > msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server"); > #if PORT_SHARE > if ((options->port_share_host || options->port_share_port) && options->proto != PROTO_TCPv4_SERVER) >@@ -1645,9 +1656,9 @@ #endif > msg (M_USAGE, "--inetd cannot be used with --mode server"); > if (options->ipchange) > msg (M_USAGE, "--ipchange cannot be used with --mode server (use --client-connect instead)"); >- if (!(options->proto == PROTO_UDPv4 || options->proto == PROTO_TCPv4_SERVER)) >- msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server"); >- if (options->proto != PROTO_UDPv4 && (options->cf_max || options->cf_per)) >+ if (!(proto_is_dgram(options->proto) || options->proto == PROTO_TCPv4_SERVER || options->proto == PROTO_TCPv6_SERVER )) >+ msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server (also udp6/tcp6)"); >+ if (!proto_is_udp(options->proto) && (options->cf_max || options->cf_per)) > msg (M_USAGE, "--connect-freq only works with --mode server --proto udp. Try --max-clients instead."); > if (!(dev == DEV_TYPE_TAP || (dev == DEV_TYPE_TUN && options->topology == TOP_SUBNET)) && options->ifconfig_pool_netmask) > msg (M_USAGE, "The third parameter to --ifconfig-pool (netmask) is only valid in --dev tap mode"); >@@ -1724,7 +1735,7 @@ #ifdef USE_CRYPTO > /* > * Check consistency of replay options > */ >- if ((options->proto != PROTO_UDPv4) >+ if ((!proto_is_udp(options->proto)) > && (options->replay_window != defaults.replay_window > || options->replay_time != defaults.replay_time)) > msg (M_USAGE, "--replay-window only makes sense with --proto udp"); >@@ -1913,7 +1924,7 @@ #if P2MP > */ > if (options->pull > && options->ping_rec_timeout_action == PING_UNDEF >- && options->proto == PROTO_UDPv4) >+ && proto_is_udp(options->proto)) > { > options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART; > options->ping_rec_timeout_action = PING_RESTART; >diff --git a/openvpn/ps.c b/openvpn/ps.c >index 49b1a2c..472c626 100644 >--- a/openvpn/ps.c >+++ b/openvpn/ps.c >@@ -337,9 +337,9 @@ sock_addr_set (struct openvpn_sockaddr * > const int port) > { > CLEAR (*osaddr); >- osaddr->sa.sin_family = AF_INET; >- osaddr->sa.sin_addr.s_addr = htonl (addr); >- osaddr->sa.sin_port = htons (port); >+ osaddr->addr.in4.sin_family = AF_INET; >+ osaddr->addr.in4.sin_addr.s_addr = htonl (addr); >+ osaddr->addr.in4.sin_port = htons (port); > } > > static inline void >diff --git a/openvpn/socket.c b/openvpn/socket.c >index 70d8ffd..3074267 100644 >--- a/openvpn/socket.c >+++ b/openvpn/socket.c >@@ -42,10 +42,16 @@ #include "manage.h" > #include "memdbg.h" > > const int proto_overhead[] = { /* indexed by PROTO_x */ >- IPv4_UDP_HEADER_SIZE, >+ 0, >+ IPv4_UDP_HEADER_SIZE, /* IPv4 */ > IPv4_TCP_HEADER_SIZE, > IPv4_TCP_HEADER_SIZE, >- IPv4_TCP_HEADER_SIZE >+#ifdef USE_PF_INET6 >+ IPv6_UDP_HEADER_SIZE, /* IPv6 */ >+ IPv6_TCP_HEADER_SIZE, >+ IPv6_TCP_HEADER_SIZE, >+ IPv6_TCP_HEADER_SIZE, >+#endif > }; > > /* >@@ -260,20 +266,49 @@ update_remote (const char* host, > struct openvpn_sockaddr *addr, > bool *changed) > { >- if (host && addr) >- { >- const in_addr_t new_addr = getaddr ( >- GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, >- host, >- 1, >- NULL, >- NULL); >- if (new_addr && addr->sa.sin_addr.s_addr != new_addr) >+ switch(addr->addr.sa.sa_family) { >+ case AF_INET: >+ if (host && addr) >+ { >+ const in_addr_t new_addr = getaddr ( >+ GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, >+ host, >+ 1, >+ NULL, >+ NULL); >+ if (new_addr && addr->addr.in4.sin_addr.s_addr != new_addr) > { >- addr->sa.sin_addr.s_addr = new_addr; >+ addr->addr.in4.sin_addr.s_addr = new_addr; > *changed = true; > } >- } >+ } >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: /* jjoFIXME: should adapt getaddr() for AF_INET6 */ >+ if (host && addr) >+ { >+ struct addrinfo hints , *ai; >+ int err; >+ memset(&hints, 0, sizeof hints); >+ hints.ai_flags=AI_PASSIVE; >+ hints.ai_family=AF_INET6; >+ if ((err=getaddrinfo(host, NULL, &hints, &ai))==0) >+ { >+ struct sockaddr_in6 *sin6=(struct sockaddr_in6*)ai->ai_addr; >+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &addr->addr.in6.sin6_addr)) >+ { >+ int port=addr->addr.in6.sin6_port; /* backup current port for easier copy, restore later */ >+ addr->addr.in6=*sin6; /* ipv6 requires also eg. sin6_scope_id => easy to full copy*/ >+ addr->addr.in6.sin6_port=port; >+ } >+ freeaddrinfo(ai); >+ } >+ } >+ break; >+#endif >+ default: >+ ASSERT(0); >+ } > } > > static int >@@ -531,6 +566,44 @@ #endif > return sd; > } > >+#ifdef USE_PF_INET6 >+static socket_descriptor_t >+create_socket_udp6 (const unsigned int flags) >+{ >+ socket_descriptor_t sd; >+ >+ if ((sd = socket (PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0) >+ msg (M_SOCKERR, "UDP: Cannot create UDP6 socket"); >+#if ENABLE_IP_PKTINFO >+ else if (flags & SF_USE_IP_PKTINFO) >+ { >+ int pad = 1; >+ setsockopt (sd, IPPROTO_IPV6, IPV6_PKTINFO, (void*)&pad, sizeof(pad)); >+ } >+#endif >+ return sd; >+} >+ >+static socket_descriptor_t >+create_socket_tcp6 (void) >+{ >+ socket_descriptor_t sd; >+ >+ if ((sd = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) >+ msg (M_SOCKERR, "Cannot create TCP6 socket"); >+ >+ /* set SO_REUSEADDR on socket */ >+ { >+ int on = 1; >+ if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, >+ (void *) &on, sizeof (on)) < 0) >+ msg (M_SOCKERR, "TCP: Cannot setsockopt SO_REUSEADDR on TCP6 socket"); >+ } >+ >+ return sd; >+} >+ >+#endif > static void > create_socket (struct link_socket *sock) > { >@@ -549,6 +622,17 @@ #endif > { > sock->sd = create_socket_tcp (); > } >+#ifdef USE_PF_INET6 >+ else if (sock->info.proto == PROTO_TCPv6_SERVER >+ || sock->info.proto == PROTO_TCPv6_CLIENT) >+ { >+ sock->sd = create_socket_tcp6 (); >+ } >+ else if (sock->info.proto == PROTO_UDPv6) >+ { >+ sock->sd = create_socket_udp6 (sock->sockflags); >+ } >+#endif > else > { > ASSERT (0); >@@ -586,7 +670,12 @@ socket_do_accept (socket_descriptor_t sd > struct link_socket_actual *act, > const bool nowait) > { >- socklen_t remote_len = sizeof (act->dest.sa); >+ /* af_addr_size WILL return 0 in this case if AFs other than AF_INET >+ * are compiled because act is empty here. >+ * could use getsockname() to support later remote_len check >+ */ >+ socklen_t remote_len_af = af_addr_size(act->dest.addr.sa.sa_family); >+ socklen_t remote_len = sizeof(act->dest.addr); > socket_descriptor_t new_sd = SOCKET_UNDEFINED; > > CLEAR (*act); >@@ -594,7 +683,7 @@ socket_do_accept (socket_descriptor_t sd > #ifdef HAVE_GETPEERNAME > if (nowait) > { >- new_sd = getpeername (sd, (struct sockaddr *) &act->dest.sa, &remote_len); >+ new_sd = getpeername (sd, &act->dest.addr.sa, &remote_len); > > if (!socket_defined (new_sd)) > msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: getpeername() failed"); >@@ -607,7 +696,7 @@ #else > #endif > else > { >- new_sd = accept (sd, (struct sockaddr *) &act->dest.sa, &remote_len); >+ new_sd = accept (sd, &act->dest.addr.sa, &remote_len); > } > > #if 0 /* For debugging only, test the effect of accept() failures */ >@@ -623,7 +712,8 @@ #endif > { > msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: accept(%d) failed", sd); > } >- else if (remote_len != sizeof (act->dest.sa)) >+ /* only valid if we have remote_len_af!=0 */ >+ else if (remote_len_af && remote_len != remote_len_af) > { > msg (D_LINK_ERRORS, "TCP: Received strange incoming connection with unknown address length=%d", remote_len); > openvpn_close_socket (new_sd); >@@ -724,7 +814,7 @@ socket_bind (socket_descriptor_t sd, > { > struct gc_arena gc = gc_new (); > >- if (bind (sd, (struct sockaddr *) &local->sa, sizeof (local->sa))) >+ if (bind (sd, &local->addr.sa, af_addr_size(local->addr.sa.sa_family))) > { > const int errnum = openvpn_errno_socket (); > msg (M_FATAL, "%s: Socket bind failed on local address %s: %s", >@@ -745,7 +835,7 @@ openvpn_connect (socket_descriptor_t sd, > > #ifdef CONNECT_NONBLOCK > set_nonblock (sd); >- status = connect (sd, (struct sockaddr *) &remote->sa, sizeof (remote->sa)); >+ status = connect (sd, &remote->addr.sa, af_addr_size(remote->addr.sa.sa_family)); > if (status) > status = openvpn_errno_socket (); > if (status == EINPROGRESS) >@@ -829,73 +919,95 @@ socket_connect (socket_descriptor_t *sd, > > #ifdef CONNECT_NONBLOCK > msg (M_INFO, "Attempting to establish TCP connection with %s [nonblock]", >- print_sockaddr (remote, &gc)); >+ print_sockaddr (remote, &gc)); > #else > msg (M_INFO, "Attempting to establish TCP connection with %s", >- print_sockaddr (remote, &gc)); >+ print_sockaddr (remote, &gc)); > #endif > > while (true) >- { >- int status; >+ { >+ int status; > > #ifdef ENABLE_MANAGEMENT >- if (management) >- management_set_state (management, >- OPENVPN_STATE_TCP_CONNECT, >- NULL, >- (in_addr_t)0, >- (in_addr_t)0); >+ if (management) >+ management_set_state (management, >+ OPENVPN_STATE_TCP_CONNECT, >+ NULL, >+ (in_addr_t)0, >+ (in_addr_t)0); > #endif > >- status = openvpn_connect (*sd, remote, connect_timeout, signal_received); >+ status = openvpn_connect (*sd, remote, connect_timeout, signal_received); > >- get_signal (signal_received); >- if (*signal_received) >- goto done; >+ get_signal (signal_received); >+ if (*signal_received) >+ goto done; > >- if (!status) >- break; >+ if (!status) >+ break; > >- msg (D_LINK_ERRORS, >- "TCP: connect to %s failed, will try again in %d seconds: %s", >- print_sockaddr (remote, &gc), >- connect_retry_seconds, >- strerror_ts (status, &gc)); >+ msg (D_LINK_ERRORS, >+ "TCP: connect to %s failed, will try again in %d seconds: %s", >+ print_sockaddr (remote, &gc), >+ connect_retry_seconds, >+ strerror_ts (status, &gc)); > >- openvpn_close_socket (*sd); >- *sd = SOCKET_UNDEFINED; >+ openvpn_close_socket (*sd); >+ *sd = SOCKET_UNDEFINED; > >- if (connect_retry_max > 0 && ++retry >= connect_retry_max) >- { >- *signal_received = SIGUSR1; >- goto done; >- } >+ if (connect_retry_max > 0 && ++retry >= connect_retry_max) >+ { >+ *signal_received = SIGUSR1; >+ goto done; >+ } > >- openvpn_sleep (connect_retry_seconds); >+ openvpn_sleep (connect_retry_seconds); > >- get_signal (signal_received); >- if (*signal_received) >- goto done; >+ get_signal (signal_received); >+ if (*signal_received) >+ goto done; > >- if (remote_list) >+ switch(remote->addr.sa.sa_family) { >+ case AF_INET: >+ if (remote_list) > { > remote_list_next (remote_list); > remote_dynamic = remote_list_host (remote_list); >- remote->sa.sin_port = htons (remote_list_port (remote_list)); >+ remote->addr.in4.sin_port = htons (remote_list_port (remote_list)); > *remote_changed = true; > } > >- *sd = create_socket_tcp (); >- if (bind_local) >- socket_bind (*sd, local, "TCP Client"); >- update_remote (remote_dynamic, remote, remote_changed); >+ *sd = create_socket_tcp (); >+ if (bind_local) >+ socket_bind (*sd, local, "TCP Client"); >+ update_remote (remote_dynamic, remote, remote_changed); >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ if (remote_list) >+ { >+ remote_list_next (remote_list); >+ remote_dynamic = remote_list_host (remote_list); >+ remote->addr.in6.sin6_port = htons (remote_list_port (remote_list)); >+ *remote_changed = true; >+ } >+ *sd = create_socket_tcp6 (); >+ if (bind_local) >+ socket_bind (*sd, local, "TCP6 Client"); >+ update_remote (remote_dynamic, remote, remote_changed); >+ break; >+#endif >+ default: >+ msg(M_FATAL, "Only TCP is supported for connection oriented, sa_family=%d", >+ remote->addr.sa.sa_family); > } >+ } > > msg (M_INFO, "TCP connection established with %s", >- print_sockaddr (remote, &gc)); >+ print_sockaddr (remote, &gc)); > >- done: >+done: > gc_free (&gc); > } > >@@ -950,17 +1062,44 @@ resolve_bind_local (struct link_socket * > > /* resolve local address if undefined */ > if (!addr_defined (&sock->info.lsa->local)) >- { >- sock->info.lsa->local.sa.sin_family = AF_INET; >- sock->info.lsa->local.sa.sin_addr.s_addr = >- (sock->local_host ? getaddr (GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL, >- sock->local_host, >- 0, >- NULL, >- NULL) >- : htonl (INADDR_ANY)); >- sock->info.lsa->local.sa.sin_port = htons (sock->local_port); >+ { >+ /* may return AF_{INET|INET6} guessed from local_host */ >+ switch(addr_guess_family(sock->info.proto, sock->local_host)) { >+ case AF_INET: >+ sock->info.lsa->local.addr.in4.sin_family = AF_INET; >+ sock->info.lsa->local.addr.in4.sin_addr.s_addr = >+ (sock->local_host ? getaddr (GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL, >+ sock->local_host, >+ 0, >+ NULL, >+ NULL) >+ : htonl (INADDR_ANY)); >+ sock->info.lsa->local.addr.in4.sin_port = htons (sock->local_port); >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ { >+ struct addrinfo hints , *ai; >+ int err; >+ memset(&hints, 0, sizeof hints); >+ hints.ai_flags=AI_PASSIVE; >+ hints.ai_family=AF_INET6; >+ /* if no local_host provided, ask for IN6ADDR_ANY ... */ >+ if ((err=getaddrinfo(sock->local_host? sock->local_host : "::", >+ NULL, &hints, &ai))==0) { >+ sock->info.lsa->local.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); >+ freeaddrinfo(ai); >+ } else { >+ msg (M_FATAL, "getaddrinfo() failed for local \"%s\": %s", >+ sock->local_host, >+ gai_strerror(err)); >+ } >+ sock->info.lsa->local.addr.in6.sin6_port = htons (sock->local_port); >+ } >+ break; >+#endif > } >+ } > > /* bind to local address/port */ > if (sock->bind_local) >@@ -984,103 +1123,128 @@ resolve_remote (struct link_socket *sock > struct gc_arena gc = gc_new (); > > if (!sock->did_resolve_remote) >+ { >+ /* resolve remote address if undefined */ >+ if (!addr_defined (&sock->info.lsa->remote)) > { >- /* resolve remote address if undefined */ >- if (!addr_defined (&sock->info.lsa->remote)) >- { >- sock->info.lsa->remote.sa.sin_family = AF_INET; >- sock->info.lsa->remote.sa.sin_addr.s_addr = 0; >+ switch(addr_guess_family(sock->info.proto, sock->remote_host)) >+ { >+ case AF_INET: >+ sock->info.lsa->remote.addr.in4.sin_family = AF_INET; >+ sock->info.lsa->remote.addr.in4.sin_addr.s_addr = 0; > > if (sock->remote_host) >- { >- unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE; >- int retry = 0; >- bool status = false; >+ { >+ unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE; >+ int retry = 0; >+ bool status = false; > >- if (remote_list_len (sock->remote_list) > 1 && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) >- { >- if (phase == 2) >- flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); >- retry = 0; >- } >- else if (phase == 1) >- { >- if (sock->resolve_retry_seconds) >- { >- retry = 0; >- } >- else >- { >- flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); >- retry = 0; >- } >- } >- else if (phase == 2) >- { >- if (sock->resolve_retry_seconds) >- { >- flags |= GETADDR_FATAL; >- retry = sock->resolve_retry_seconds; >- } >- else >- { >- ASSERT (0); >- } >- } >+ if (remote_list_len (sock->remote_list) > 1 && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) >+ { >+ if (phase == 2) >+ flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL); >+ retry = 0; >+ } >+ else if (phase == 1) >+ { >+ if (sock->resolve_retry_seconds) >+ { >+ retry = 0; >+ } > else >- { >- ASSERT (0); >- } >- >- sock->info.lsa->remote.sa.sin_addr.s_addr = getaddr ( >- flags, >- sock->remote_host, >- retry, >- &status, >- signal_received); >- >- dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", >- flags, >- phase, >- retry, >- signal_received ? *signal_received : -1, >- status); >+ { >+ flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY); >+ retry = 0; >+ } >+ } >+ else if (phase == 2) >+ { >+ if (sock->resolve_retry_seconds) >+ { >+ flags |= GETADDR_FATAL; >+ retry = sock->resolve_retry_seconds; >+ } >+ else >+ { >+ ASSERT (0); >+ } >+ } >+ else >+ { >+ ASSERT (0); >+ } > >+ sock->info.lsa->remote.addr.in4.sin_addr.s_addr = getaddr ( >+ flags, >+ sock->remote_host, >+ retry, >+ &status, >+ signal_received); >+ >+ dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", >+ flags, >+ phase, >+ retry, >+ signal_received ? *signal_received : -1, >+ status); >+ >+ if (signal_received) >+ { >+ if (*signal_received) >+ goto done; >+ } >+ if (!status) >+ { > if (signal_received) >- { >- if (*signal_received) >- goto done; >- } >- if (!status) >- { >- if (signal_received) >- *signal_received = SIGUSR1; >- goto done; >- } >+ *signal_received = SIGUSR1; >+ goto done; > } >+ } > >- sock->info.lsa->remote.sa.sin_port = htons (sock->remote_port); >- } >- >- /* should we re-use previous active remote address? */ >- if (link_socket_actual_defined (&sock->info.lsa->actual)) >- { >- msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", >- print_link_socket_actual (&sock->info.lsa->actual, &gc)); >- if (remote_dynamic) >- *remote_dynamic = NULL; >- } >- else >- { >- CLEAR (sock->info.lsa->actual); >- sock->info.lsa->actual.dest = sock->info.lsa->remote; >- } >+ sock->info.lsa->remote.addr.in4.sin_port = htons (sock->remote_port); >+ break; > >- /* remember that we finished */ >- sock->did_resolve_remote = true; >+#ifdef USE_PF_INET6 >+ case AF_INET6: /* jjoFIXME: ipv6 signal logic */ >+ { >+ struct addrinfo hints , *ai; >+ int err; >+ memset(&hints, 0, sizeof hints); >+ hints.ai_flags=0; >+ hints.ai_family=AF_INET6; >+ if ((err=getaddrinfo(sock->remote_host? sock->remote_host : "::" , NULL, &hints, &ai))==0) { >+ sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); >+ freeaddrinfo(ai); >+ } else { >+ msg (M_FATAL, "getaddrinfo() failed for remote \"%s\": %s", >+ sock->remote_host, >+ gai_strerror(err)); >+ } >+ sock->info.lsa->remote.addr.in6.sin6_port = htons (sock->remote_port); >+ } >+ break; >+#endif >+ } >+ } >+ /* should we re-use previous active remote address? */ >+ if (link_socket_actual_defined (&sock->info.lsa->actual)) >+ { >+ msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", >+ print_link_socket_actual (&sock->info.lsa->actual, &gc)); >+ if (remote_dynamic) >+ *remote_dynamic = NULL; >+ } >+ else >+ { >+ CLEAR (sock->info.lsa->actual); >+ sock->info.lsa->actual.dest = sock->info.lsa->remote; > } > >- done: >+ /* remember that we finished */ >+ sock->did_resolve_remote = true; >+ } >+ >+done: > gc_free (&gc); > } > >@@ -1310,7 +1474,11 @@ link_socket_init_phase2 (struct link_soc > goto done; > > /* TCP client/server */ >- if (sock->info.proto == PROTO_TCPv4_SERVER) >+ if (sock->info.proto == PROTO_TCPv4_SERVER >+#ifdef USE_PF_INET6 >+ ||sock->info.proto == PROTO_TCPv6_SERVER >+#endif >+ ) > { > switch (sock->mode) > { >@@ -1345,7 +1513,11 @@ link_socket_init_phase2 (struct link_soc > ASSERT (0); > } > } >- else if (sock->info.proto == PROTO_TCPv4_CLIENT) >+ else if (sock->info.proto == PROTO_TCPv4_CLIENT >+#ifdef USE_PF_INET6 >+ ||sock->info.proto == PROTO_TCPv6_CLIENT >+#endif >+ ) > { > > #ifdef GENERAL_PROXY_SUPPORT >@@ -1430,8 +1602,8 @@ #ifdef ENABLE_SOCKS > sock->remote_port = sock->proxy_dest_port; > sock->did_resolve_remote = false; > >- sock->info.lsa->actual.dest.sa.sin_addr.s_addr = 0; >- sock->info.lsa->remote.sa.sin_addr.s_addr = 0; >+ addr_zero_host(&sock->info.lsa->actual.dest); >+ addr_zero_host(&sock->info.lsa->remote); > > resolve_remote (sock, 1, NULL, signal_received); > >@@ -1446,7 +1618,7 @@ #endif > if (remote_changed) > { > msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment"); >- sock->info.lsa->remote.sa.sin_addr.s_addr = sock->info.lsa->actual.dest.sa.sin_addr.s_addr; >+ addr_copy_host(&sock->info.lsa->remote, &sock->info.lsa->actual.dest); > } > } > >@@ -1618,13 +1790,20 @@ link_socket_bad_incoming_addr (struct bu > { > struct gc_arena gc = gc_new (); > >- msg (D_LINK_ERRORS, >- "TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)", >- print_link_socket_actual (from_addr, &gc), >- (int)from_addr->dest.sa.sin_family, >- print_sockaddr (&info->lsa->remote, &gc)); >+ switch(from_addr->dest.addr.sa.sa_family) >+ { >+ case AF_INET: >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+#endif >+ msg (D_LINK_ERRORS, >+ "TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)", >+ print_link_socket_actual (from_addr, &gc), >+ (int)from_addr->dest.addr.sa.sa_family, >+ print_sockaddr (&info->lsa->remote, &gc)); >+ break; >+ } > buf->len = 0; >- > gc_free (&gc); > } > >@@ -1639,10 +1818,25 @@ link_socket_current_remote (const struct > { > const struct link_socket_addr *lsa = info->lsa; > >+/* >+ * This logic supports "redirect-gateway" semantic, which >+ * makes sense only for PF_INET routes over PF_INET endpoints >+ * >+ * Maybe in the future consider PF_INET6 endpoints also ... >+ * by now just ignore it >+ * >+ */ >+#if defined ( USE_PF_INET6 ) >+ if(lsa->actual.dest.addr.sa.sa_family != AF_INET) >+ return 0; >+#else >+ ASSERT(lsa->actual.dest.addr.sa.sa_family == AF_INET); >+#endif >+ > if (link_socket_actual_defined (&lsa->actual)) >- return ntohl (lsa->actual.dest.sa.sin_addr.s_addr); >+ return ntohl (lsa->actual.dest.addr.in4.sin_addr.s_addr); > else if (addr_defined (&lsa->remote)) >- return ntohl (lsa->remote.sa.sin_addr.s_addr); >+ return ntohl (lsa->remote.addr.in4.sin_addr.s_addr); > else > return 0; > } >@@ -1869,27 +2063,58 @@ print_sockaddr_ex (const struct openvpn_ > const unsigned int flags, > struct gc_arena *gc) > { >- if (addr) >- { >- struct buffer out = alloc_buf_gc (64, gc); >- const int port = ntohs (addr->sa.sin_port); >- >- mutex_lock_static (L_INET_NTOA); >- buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sa.sin_addr) : "[undef]")); >- mutex_unlock_static (L_INET_NTOA); >- >- if (((flags & PS_SHOW_PORT) || (addr_defined (addr) && (flags & PS_SHOW_PORT_IF_DEFINED))) >- && port) >+ struct buffer out; >+ bool addr_is_defined; >+ if (!addr) { >+ return "[NULL]"; >+ } >+ addr_is_defined = addr_defined (addr); >+ switch(addr->addr.sa.sa_family) { >+ case AF_INET: >+ { >+ const int port= ntohs (addr->addr.in4.sin_port); >+ out = alloc_buf_gc (128, gc); >+ buf_puts (&out, "[AF_INET]"); >+ mutex_lock_static (L_INET_NTOA); >+ buf_puts (&out, (addr_is_defined ? inet_ntoa (addr->addr.in4.sin_addr) : "[undef]")); >+ mutex_unlock_static (L_INET_NTOA); >+ >+ if (((flags & PS_SHOW_PORT) || (addr_is_defined && (flags & PS_SHOW_PORT_IF_DEFINED))) >+ && port) > { > if (separator) > buf_printf (&out, "%s", separator); > > buf_printf (&out, "%d", port); > } >- return BSTR (&out); >- } >- else >- return "[NULL]"; >+ } >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ { >+ const int port= ntohs (addr->addr.in6.sin6_port); >+ char buf[INET6_ADDRSTRLEN] = "[undef]"; >+ out = alloc_buf_gc (128, gc); >+ buf_puts (&out, "[AF_INET6]"); >+ if (addr_is_defined) >+ { >+ getnameinfo(&addr->addr.sa, sizeof (struct sockaddr_in6), >+ buf, sizeof (buf), NULL, 0, NI_NUMERICHOST); >+ buf_puts (&out, buf); >+ } >+ if (((flags & PS_SHOW_PORT) || (addr_is_defined && (flags & PS_SHOW_PORT_IF_DEFINED))) >+ && port) >+ { >+ if (separator) >+ buf_puts (&out, separator); >+ >+ buf_printf (&out, "%d", port); >+ } >+ } >+ break; >+#endif >+ } >+ return BSTR (&out); > } > > const char * >@@ -1909,12 +2134,38 @@ print_link_socket_actual_ex (const struc > struct buffer out = alloc_buf_gc (128, gc); > buf_printf (&out, "%s", print_sockaddr_ex (&act->dest, separator, flags, gc)); > #if ENABLE_IP_PKTINFO >- if ((flags & PS_SHOW_PKTINFO) && act->pi.ipi_spec_dst.s_addr) >+ if ((flags & PS_SHOW_PKTINFO) && addr_defined_ipi(act)) > { >+ switch(act->dest.addr.sa.sa_family) >+ { >+ case AF_INET: >+ { > struct openvpn_sockaddr sa; > CLEAR (sa); >- sa.sa.sin_addr = act->pi.ipi_spec_dst; >+ sa.addr.in4.sin_addr = act->pi.in4.ipi_spec_dst; > buf_printf (&out, " (via %s)", print_sockaddr_ex (&sa, separator, 0, gc)); >+ } >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ { >+ struct sockaddr_in6 sin6; >+ char buf[INET6_ADDRSTRLEN] = "[undef]"; >+ memset(&sin6, 0, sizeof sin6); >+ sin6.sin6_family = AF_INET6; >+ sin6.sin6_addr = act->pi.in6.ipi6_addr; >+ { >+ if (getnameinfo((struct sockaddr *)&sin6, sizeof (struct sockaddr_in6), >+ buf, sizeof (buf), NULL, 0, NI_NUMERICHOST) == 0) >+ buf_printf (&out, " (via %s)", buf); >+ else >+ buf_printf (&out, " (via [getnameinfo() err])"); >+ } >+ } >+ break; >+#endif >+ } >+ > } > #endif > return BSTR (&out); >@@ -1950,21 +2201,37 @@ void > setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const bool flags) > { > char name_buf[256]; >+ char buf[128]; > >- if (flags & SA_IP_PORT) >- openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix); >- else >- openvpn_snprintf (name_buf, sizeof (name_buf), "%s", name_prefix); >+ switch(addr->addr.sa.sa_family) { >+ case AF_INET: >+ if (flags & SA_IP_PORT) >+ openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix); >+ else >+ openvpn_snprintf (name_buf, sizeof (name_buf), "%s", name_prefix); > >- mutex_lock_static (L_INET_NTOA); >- setenv_str (es, name_buf, inet_ntoa (addr->sa.sin_addr)); >- mutex_unlock_static (L_INET_NTOA); >+ mutex_lock_static (L_INET_NTOA); >+ setenv_str (es, name_buf, inet_ntoa (addr->addr.in4.sin_addr)); >+ mutex_unlock_static (L_INET_NTOA); >+ >+ if ((flags & SA_IP_PORT) && addr->addr.in4.sin_port) >+ { >+ openvpn_snprintf (name_buf, sizeof (name_buf), "%s_port", name_prefix); >+ setenv_int (es, name_buf, ntohs (addr->addr.in4.sin_port)); >+ } >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip6", name_prefix); >+ getnameinfo(&addr->addr.sa, sizeof (struct sockaddr_in6), >+ buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); >+ setenv_str (es, name_buf, buf); > >- if ((flags & SA_IP_PORT) && addr->sa.sin_port) >- { > openvpn_snprintf (name_buf, sizeof (name_buf), "%s_port", name_prefix); >- setenv_int (es, name_buf, ntohs (addr->sa.sin_port)); >- } >+ setenv_int (es, name_buf, ntohs (addr->addr.in6.sin6_port)); >+ break; >+#endif >+ } > } > > void >@@ -1974,7 +2241,8 @@ setenv_in_addr_t (struct env_set *es, co > { > struct openvpn_sockaddr si; > CLEAR (si); >- si.sa.sin_addr.s_addr = htonl (addr); >+ si.addr.in4.sin_family = AF_INET; >+ si.addr.in4.sin_addr.s_addr = htonl (addr); > setenv_sockaddr (es, name_prefix, &si, flags); > } > } >@@ -1995,16 +2263,63 @@ setenv_link_socket_actual (struct env_se > struct proto_names { > const char *short_form; > const char *display_form; >+ bool is_dgram; >+ bool is_net; >+ sa_family_t proto_af; > }; > > /* Indexed by PROTO_x */ >-static const struct proto_names proto_names[] = { >- {"udp", "UDPv4"}, >- {"tcp-server", "TCPv4_SERVER"}, >- {"tcp-client", "TCPv4_CLIENT"}, >- {"tcp", "TCPv4"} >+static const struct proto_names proto_names[PROTO_N] = { >+ {"proto-uninitialized", "proto-NONE",0,0, AF_UNSPEC}, >+ {"udp", "UDPv4",1,1, AF_INET}, >+ {"tcp-server", "TCPv4_SERVER",0,1, AF_INET}, >+ {"tcp-client", "TCPv4_CLIENT",0,1, AF_INET}, >+ {"tcp", "TCPv4",0,1, AF_INET}, >+#ifdef USE_PF_INET6 >+ {"udp6" ,"UDPv6",1,1, AF_INET6}, >+ {"tcp6-server","TCPv6_SERVER",0,1, AF_INET6}, >+ {"tcp6-client","TCPv6_CLIENT",0,1, AF_INET6}, >+ {"tcp6" ,"TCPv6",0,1, AF_INET6}, >+#endif > }; > >+bool >+proto_is_net(int proto) >+{ >+ if (proto < 0 || proto >= PROTO_N) >+ ASSERT(0); >+ return proto_names[proto].is_net; >+} >+bool >+proto_is_dgram(int proto) >+{ >+ if (proto < 0 || proto >= PROTO_N) >+ ASSERT(0); >+ return proto_names[proto].is_dgram; >+} >+bool >+proto_is_udp(int proto) >+{ >+ if (proto < 0 || proto >= PROTO_N) >+ ASSERT(0); >+ return proto_names[proto].is_dgram&&proto_names[proto].is_net; >+} >+bool >+proto_is_tcp(int proto) >+{ >+ if (proto < 0 || proto >= PROTO_N) >+ ASSERT(0); >+ return (!proto_names[proto].is_dgram)&&proto_names[proto].is_net; >+} >+ >+sa_family_t >+proto_sa_family(int proto) >+{ >+ if (proto < 0 || proto >= PROTO_N) >+ ASSERT(0); >+ return proto_names[proto].proto_af; >+} >+ > int > ascii2proto (const char* proto_name) > { >@@ -2044,6 +2359,46 @@ proto2ascii_all (struct gc_arena *gc) > return BSTR (&out); > } > >+int >+addr_guess_family(int proto, const char *name) >+{ >+ sa_family_t ret; >+ if (proto) { >+ return proto_sa_family(proto); /* already stamped */ >+ } >+#ifdef USE_PF_UNIX >+ else if (name && name[0] == '/') { >+ return AF_UNIX; >+ } >+#endif >+#ifdef USE_PF_INET6 >+ else { >+ struct addrinfo hints , *ai; >+ int err; >+ memset(&hints, 0, sizeof hints); >+ hints.ai_flags=AI_NUMERICHOST; >+ if ((err=getaddrinfo(name, NULL, &hints, &ai))==0) { >+ ret=ai->ai_family; >+ freeaddrinfo(ai); >+ return ret; >+ } >+ } >+#endif >+ return AF_INET; /* default */ >+} >+const char * >+addr_family_name (int af) >+{ >+ switch (af) { >+ case AF_INET: return "AF_INET"; >+ case AF_INET6: return "AF_INET6"; >+#ifdef USE_PF_UNIX >+ case AF_UNIX: return "AF_UNIX"; >+#endif >+ } >+ return "AF_UNSPEC"; >+} >+ > /* > * Given a local proto, return local proto > * if !remote, or compatible remote proto >@@ -2058,10 +2413,15 @@ proto_remote (int proto, bool remote) > ASSERT (proto >= 0 && proto < PROTO_N); > if (remote) > { >- if (proto == PROTO_TCPv4_SERVER) >- return PROTO_TCPv4_CLIENT; >- if (proto == PROTO_TCPv4_CLIENT) >- return PROTO_TCPv4_SERVER; >+ switch (proto) >+ { >+ case PROTO_TCPv4_SERVER: return PROTO_TCPv4_CLIENT; >+ case PROTO_TCPv4_CLIENT: return PROTO_TCPv4_SERVER; >+#ifdef USE_PF_INET6 >+ case PROTO_TCPv6_SERVER: return PROTO_TCPv6_CLIENT; >+ case PROTO_TCPv6_CLIENT: return PROTO_TCPv6_SERVER; >+#endif >+ } > } > return proto; > } >@@ -2119,11 +2479,26 @@ #ifndef WIN32 > > #if ENABLE_IP_PKTINFO > >-struct openvpn_pktinfo >+struct openvpn_in4_pktinfo > { > struct cmsghdr cmsghdr; >- struct in_pktinfo in_pktinfo; >+ struct in_pktinfo pi; > }; >+#ifdef USE_PF_INET6 >+struct openvpn_in6_pktinfo >+{ >+ struct cmsghdr cmsghdr; >+ struct in6_pktinfo pi6; >+}; >+#endif >+ >+union openvpn_pktinfo { >+ struct openvpn_in4_pktinfo cmsgpi; >+#ifdef USE_PF_INET6 >+ struct openvpn_in6_pktinfo cmsgpi6; >+#endif >+}; >+ > > static socklen_t > link_socket_read_udp_posix_recvmsg (struct link_socket *sock, >@@ -2132,15 +2507,15 @@ link_socket_read_udp_posix_recvmsg (stru > struct link_socket_actual *from) > { > struct iovec iov; >- struct openvpn_pktinfo opi; >+ union openvpn_pktinfo opi; > struct msghdr mesg; >- socklen_t fromlen = sizeof (from->dest.sa); >+ socklen_t fromlen = sizeof (from->dest.addr); > > iov.iov_base = BPTR (buf); > iov.iov_len = maxsize; > mesg.msg_iov = &iov; > mesg.msg_iovlen = 1; >- mesg.msg_name = &from->dest.sa; >+ mesg.msg_name = &from->dest.addr; > mesg.msg_namelen = fromlen; > mesg.msg_control = &opi; > mesg.msg_controllen = sizeof (opi); >@@ -2157,9 +2532,21 @@ link_socket_read_udp_posix_recvmsg (stru > && cmsg->cmsg_len >= sizeof (opi)) > { > struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg); >- from->pi.ipi_ifindex = pkti->ipi_ifindex; >- from->pi.ipi_spec_dst = pkti->ipi_spec_dst; >+ from->pi.in4.ipi_ifindex = pkti->ipi_ifindex; >+ from->pi.in4.ipi_spec_dst = pkti->ipi_spec_dst; >+ } >+#ifdef USE_PF_INET6 >+ else if (cmsg != NULL >+ && CMSG_NXTHDR (&mesg, cmsg) == NULL >+ && cmsg->cmsg_level == IPPROTO_IPV6 >+ && cmsg->cmsg_type == IPV6_PKTINFO >+ && cmsg->cmsg_len >= sizeof (struct openvpn_in6_pktinfo)) >+ { >+ struct in6_pktinfo *pkti6 = (struct in6_pktinfo *) CMSG_DATA (cmsg); >+ from->pi.in6.ipi6_ifindex = pkti6->ipi6_ifindex; >+ from->pi.in6.ipi6_addr = pkti6->ipi6_addr; > } >+#endif > } > return fromlen; > } >@@ -2171,18 +2558,20 @@ link_socket_read_udp_posix (struct link_ > int maxsize, > struct link_socket_actual *from) > { >- socklen_t fromlen = sizeof (from->dest.sa); >- from->dest.sa.sin_addr.s_addr = 0; >+ socklen_t fromlen = sizeof (from->dest.addr); >+ socklen_t expectedlen = af_addr_size(proto_sa_family(sock->info.proto)); >+ addr_zero_host(&from->dest); > ASSERT (buf_safe (buf, maxsize)); > #if ENABLE_IP_PKTINFO >- if (sock->sockflags & SF_USE_IP_PKTINFO) >+ /* Both PROTO_UDPv4 and PROTO_UDPv6 */ >+ if (proto_is_udp(sock->info.proto) && sock->sockflags & SF_USE_IP_PKTINFO) > fromlen = link_socket_read_udp_posix_recvmsg (sock, buf, maxsize, from); > else > #endif > buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0, >- (struct sockaddr *) &from->dest.sa, &fromlen); >- if (fromlen != sizeof (from->dest.sa)) >- bad_address_length (fromlen, sizeof (from->dest.sa)); >+ &from->dest.addr.sa, &fromlen); >+ if (buf->len >= 0 && expectedlen && fromlen != expectedlen) >+ bad_address_length (fromlen, expectedlen); > return buf->len; > } > >@@ -2219,26 +2608,52 @@ link_socket_write_udp_posix_sendmsg (str > struct iovec iov; > struct msghdr mesg; > struct cmsghdr *cmsg; >- struct in_pktinfo *pkti; >- struct openvpn_pktinfo opi; > > iov.iov_base = BPTR (buf); > iov.iov_len = BLEN (buf); > mesg.msg_iov = &iov; > mesg.msg_iovlen = 1; >- mesg.msg_name = &to->dest.sa; >- mesg.msg_namelen = sizeof (to->dest.sa); >- mesg.msg_control = &opi; >- mesg.msg_controllen = sizeof (opi); >- mesg.msg_flags = 0; >- cmsg = CMSG_FIRSTHDR (&mesg); >- cmsg->cmsg_len = sizeof (opi); >- cmsg->cmsg_level = SOL_IP; >- cmsg->cmsg_type = IP_PKTINFO; >- pkti = (struct in_pktinfo *) CMSG_DATA (cmsg); >- pkti->ipi_ifindex = to->pi.ipi_ifindex; >- pkti->ipi_spec_dst = to->pi.ipi_spec_dst; >- pkti->ipi_addr.s_addr = 0; >+ switch (sock->info.lsa->remote.addr.sa.sa_family) >+ { >+ case AF_INET: { >+ struct openvpn_in4_pktinfo opi; >+ struct in_pktinfo *pkti; >+ mesg.msg_name = &to->dest.addr.sa; >+ mesg.msg_namelen = sizeof (struct sockaddr_in); >+ mesg.msg_control = &opi; >+ mesg.msg_controllen = sizeof (opi); >+ mesg.msg_flags = 0; >+ cmsg = CMSG_FIRSTHDR (&mesg); >+ cmsg->cmsg_len = sizeof (opi); >+ cmsg->cmsg_level = SOL_IP; >+ cmsg->cmsg_type = IP_PKTINFO; >+ pkti = (struct in_pktinfo *) CMSG_DATA (cmsg); >+ pkti->ipi_ifindex = to->pi.in4.ipi_ifindex; >+ pkti->ipi_spec_dst = to->pi.in4.ipi_spec_dst; >+ pkti->ipi_addr.s_addr = 0; >+ break; >+ } >+#ifdef USE_PF_INET6 >+ case AF_INET6: { >+ struct openvpn_in6_pktinfo opi6; >+ struct in6_pktinfo *pkti6; >+ mesg.msg_name = &to->dest.addr.sa; >+ mesg.msg_namelen = sizeof (struct sockaddr_in6); >+ mesg.msg_control = &opi6; >+ mesg.msg_controllen = sizeof (opi6); >+ mesg.msg_flags = 0; >+ cmsg = CMSG_FIRSTHDR (&mesg); >+ cmsg->cmsg_len = sizeof (opi6); >+ cmsg->cmsg_level = IPPROTO_IPV6; >+ cmsg->cmsg_type = IPV6_PKTINFO; >+ pkti6 = (struct in6_pktinfo *) CMSG_DATA (cmsg); >+ pkti6->ipi6_ifindex = to->pi.in6.ipi6_ifindex; >+ pkti6->ipi6_addr = to->pi.in6.ipi6_addr; >+ break; >+ } >+#endif >+ default: ASSERT(0); >+ } > return sendmsg (sock->sd, &mesg, 0); > } > >@@ -2382,7 +2797,7 @@ socket_send_queue (struct link_socket *s > { > /* set destination address for UDP writes */ > sock->writes.addr_defined = true; >- sock->writes.addr = to->dest.sa; >+ sock->writes.addr = to->dest.addr.in4; > sock->writes.addrlen = sizeof (sock->writes.addr); > > status = WSASendTo( >@@ -2538,10 +2953,10 @@ socket_finalize (SOCKET s, > { > if (io->addrlen != sizeof (io->addr)) > bad_address_length (io->addrlen, sizeof (io->addr)); >- from->dest.sa = io->addr; >+ from->dest.addr.sa = io->addr; > } > else >- CLEAR (from->dest.sa); >+ CLEAR (from->dest.addr.sa); > } > > if (buf) >diff --git a/openvpn/socket.h b/openvpn/socket.h >index 28bf41f..435cf38 100644 >--- a/openvpn/socket.h >+++ b/openvpn/socket.h >@@ -81,7 +81,13 @@ #define ntohps(x) ntohs(x) > struct openvpn_sockaddr > { > /*int dummy;*/ /* add offset to force a bug if sa not explicitly dereferenced */ >- struct sockaddr_in sa; >+ union { >+ struct sockaddr sa; >+ struct sockaddr_in in4; >+#ifdef USE_PF_INET6 >+ struct sockaddr_in6 in6; >+#endif >+ } addr; > }; > > /* actual address of remote, based on source address of received packets */ >@@ -90,7 +96,12 @@ struct link_socket_actual > int dummy; /* JYFIXME -- add offset to force a bug if dest not explicitly dereferenced */ > struct openvpn_sockaddr dest; > #if ENABLE_IP_PKTINFO >- struct in_pktinfo pi; >+ union { >+ struct in_pktinfo in4; >+#ifdef USE_PF_INET6 >+ struct in6_pktinfo in6; >+#endif >+ } pi; > #endif > }; > >@@ -411,6 +422,14 @@ socket_descriptor_t create_socket_tcp (v > socket_descriptor_t socket_do_accept (socket_descriptor_t sd, > struct link_socket_actual *act, > const bool nowait); >+/* >+ * proto related >+ */ >+bool proto_is_net(int proto); >+bool proto_is_dgram(int proto); >+bool proto_is_udp(int proto); >+bool proto_is_tcp(int proto); >+ > > /* > * DNS resolution >@@ -436,23 +455,49 @@ in_addr_t getaddr (unsigned int flags, > * Transport protocol naming and other details. > */ > >-#define PROTO_UDPv4 0 >-#define PROTO_TCPv4_SERVER 1 >-#define PROTO_TCPv4_CLIENT 2 >-#define PROTO_TCPv4 3 >-#define PROTO_N 4 >+#if 0 /* PRE UDPv6/TCPv6 code */ >+#define PROTO_NONE 0 /* catch for uninitialized */ >+#define PROTO_UDPv4 1 >+#define PROTO_TCPv4_SERVER 2 >+#define PROTO_TCPv4_CLIENT 3 >+#define PROTO_TCPv4 4 >+#define PROTO_UDPv6 5 >+#define PROTO_TCPv6_SERVER 6 >+#define PROTO_TCPv6_CLIENT 7 >+#define PROTO_TCPv6 8 >+#define PROTO_N 9 >+#endif /* if 0 */ >+ >+/* >+ * Use enum's instead of #define to allow for easier >+ * optional proto support >+ */ >+enum proto_num { >+ PROTO_NONE, /* catch for uninitialized */ >+ PROTO_UDPv4, >+ PROTO_TCPv4_SERVER, >+ PROTO_TCPv4_CLIENT, >+ PROTO_TCPv4, >+ PROTO_UDPv6, >+ PROTO_TCPv6_SERVER, >+ PROTO_TCPv6_CLIENT, >+ PROTO_TCPv6, >+ PROTO_N >+}; > > int ascii2proto (const char* proto_name); > const char *proto2ascii (int proto, bool display_form); > const char *proto2ascii_all (struct gc_arena *gc); > int proto_remote (int proto, bool remote); >+const char *addr_family_name(int af); > > /* > * Overhead added to packets by various protocols. > */ > #define IPv4_UDP_HEADER_SIZE 28 > #define IPv4_TCP_HEADER_SIZE 40 >-#define IPv6_UDP_HEADER_SIZE 40 >+#define IPv6_UDP_HEADER_SIZE 48 >+#define IPv6_TCP_HEADER_SIZE 60 > > extern const int proto_overhead[]; > >@@ -485,7 +530,7 @@ legal_ipv4_port (int port) > static inline bool > link_socket_proto_connection_oriented (int proto) > { >- return proto == PROTO_TCPv4_SERVER || proto == PROTO_TCPv4_CLIENT; >+ return !proto_is_dgram(proto); > } > > static inline bool >@@ -500,7 +545,30 @@ link_socket_connection_oriented (const s > static inline bool > addr_defined (const struct openvpn_sockaddr *addr) > { >- return addr->sa.sin_addr.s_addr != 0; >+ if (!addr) return 0; >+ switch (addr->addr.sa.sa_family) { >+ case AF_INET: return addr->addr.in4.sin_addr.s_addr != 0; >+#ifdef USE_PF_INET6 >+ case AF_INET6: return !IN6_IS_ADDR_UNSPECIFIED(&addr->addr.in6.sin6_addr); >+#endif >+ default: return 0; >+ } >+} >+static inline bool >+addr_defined_ipi (const struct link_socket_actual *lsa) >+{ >+#if ENABLE_IP_PKTINFO >+ if (!lsa) return 0; >+ switch (lsa->dest.addr.sa.sa_family) { >+ case AF_INET: return lsa->pi.in4.ipi_spec_dst.s_addr != 0; >+#ifdef USE_PF_INET6 >+ case AF_INET6: return !IN6_IS_ADDR_UNSPECIFIED(&lsa->pi.in6.ipi6_addr); >+#endif >+ default: return 0; >+ } >+#else >+ ASSERT(0); >+#endif > } > > static inline bool >@@ -512,20 +580,50 @@ link_socket_actual_defined (const struct > static inline bool > addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) > { >- return a1->sa.sin_addr.s_addr == a2->sa.sin_addr.s_addr; >+ switch(a1->addr.sa.sa_family) { >+ case AF_INET: >+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr); >+#endif >+ } >+ ASSERT(0); >+ return false; > } > > static inline in_addr_t >-addr_host (const struct openvpn_sockaddr *s) >+addr_host (const struct openvpn_sockaddr *addr) > { >- return ntohl (s->sa.sin_addr.s_addr); >+ /* >+ * "public" addr returned is checked against ifconfig for >+ * possible clash: non sense for now given >+ * that we do ifconfig only IPv4 >+ */ >+#if defined(USE_PF_INET6) >+ if(addr->addr.sa.sa_family != AF_INET) >+ return 0; >+#else >+ ASSERT(addr->addr.sa.sa_family == AF_INET); >+#endif >+ return ntohl (addr->addr.in4.sin_addr.s_addr); > } > > static inline bool > addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2) > { >- return a1->sa.sin_addr.s_addr == a2->sa.sin_addr.s_addr >- && a1->sa.sin_port == a2->sa.sin_port; >+ switch(a1->addr.sa.sa_family) { >+ case AF_INET: >+ return a1->addr.in4.sin_addr.s_addr == a2->addr.in4.sin_addr.s_addr >+ && a1->addr.in4.sin_port == a2->addr.in4.sin_port; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ return IN6_ARE_ADDR_EQUAL(&a1->addr.in6.sin6_addr, &a2->addr.in6.sin6_addr) >+ && a1->addr.in6.sin6_port == a2->addr.in6.sin6_port; >+#endif >+ } >+ ASSERT(0); >+ return false; > } > > static inline bool >@@ -538,6 +636,74 @@ addr_match_proto (const struct openvpn_s > : addr_port_match (a1, a2); > } > >+static inline void >+addr_zero_host(struct openvpn_sockaddr *addr) >+{ >+ switch(addr->addr.sa.sa_family) { >+ case AF_INET: >+ addr->addr.in4.sin_addr.s_addr = 0; >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ memset(&addr->addr.in6.sin6_addr, 0, sizeof (struct in6_addr)); >+ break; >+#endif >+ } >+} >+ >+static inline void >+addr_copy_sa(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src) >+{ >+ dst->addr = src->addr; >+} >+ >+static inline void >+addr_copy_host(struct openvpn_sockaddr *dst, const struct openvpn_sockaddr *src) >+{ >+ switch(src->addr.sa.sa_family) { >+ case AF_INET: >+ dst->addr.in4.sin_addr.s_addr = src->addr.in4.sin_addr.s_addr; >+ break; >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+ dst->addr.in6.sin6_addr = src->addr.in6.sin6_addr; >+ break; >+#endif >+ } >+} >+ >+static inline bool >+addr_inet4or6(struct sockaddr *addr) >+{ >+ return addr->sa_family == AF_INET || addr->sa_family == AF_INET6; >+} >+ >+int addr_guess_family(int proto, const char *name); >+static inline int >+af_addr_size(sa_family_t af) >+{ >+#if defined(USE_PF_INET6) || defined (USE_PF_UNIX) >+ switch(af) { >+ case AF_INET: return sizeof (struct sockaddr_in); >+#ifdef USE_PF_UNIX >+ case AF_UNIX: return sizeof (struct sockaddr_un); >+#endif >+#ifdef USE_PF_INET6 >+ case AF_INET6: return sizeof (struct sockaddr_in6); >+#endif >+ default: >+#if 0 >+ /* could be called from socket_do_accept() with empty addr */ >+ msg (M_ERR, "Bad address family: %d\n", addr->sa_family); >+ ASSERT(0); >+#endif >+ return 0; >+ } >+#else /* only AF_INET */ >+ return sizeof(struct sockaddr_in); >+#endif >+} >+ > static inline bool > link_socket_actual_match (const struct link_socket_actual *a1, const struct link_socket_actual *a2) > { >@@ -594,14 +760,18 @@ link_socket_verify_incoming_addr (struct > { > if (buf->len > 0) > { >- if (from_addr->dest.sa.sin_family != AF_INET) >- return false; >- if (!link_socket_actual_defined (from_addr)) >- return false; >- if (info->remote_float || !addr_defined (&info->lsa->remote)) >- return true; >- if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto)) >- return true; >+ switch (from_addr->dest.addr.sa.sa_family) { >+#ifdef USE_PF_INET6 >+ case AF_INET6: >+#endif >+ case AF_INET: >+ if (!link_socket_actual_defined (from_addr)) >+ return false; >+ if (info->remote_float || !addr_defined (&info->lsa->remote)) >+ return true; >+ if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto)) >+ return true; >+ } > } > return false; > } >@@ -707,7 +877,7 @@ link_socket_read (struct link_socket *so > int maxsize, > struct link_socket_actual *from) > { >- if (sock->info.proto == PROTO_UDPv4) >+ if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */ > { > int res; > >@@ -718,10 +888,10 @@ #else > #endif > return res; > } >- else if (sock->info.proto == PROTO_TCPv4_SERVER || sock->info.proto == PROTO_TCPv4_CLIENT) >+ else if (proto_is_tcp(sock->info.proto)) /* unified TCPv4 and TCPv6 */ > { > /* from address was returned by accept */ >- from->dest.sa = sock->info.lsa->actual.dest.sa; >+ addr_copy_sa(&from->dest, &sock->info.lsa->actual.dest); > return link_socket_read_tcp (sock, buf); > } > else >@@ -776,13 +946,14 @@ #if ENABLE_IP_PKTINFO > struct buffer *buf, > struct link_socket_actual *to); > >- if (sock->sockflags & SF_USE_IP_PKTINFO) >+ if (proto_is_udp(sock->info.proto) && (sock->sockflags & SF_USE_IP_PKTINFO) >+ && addr_defined_ipi(to)) > return link_socket_write_udp_posix_sendmsg (sock, buf, to); > else > #endif > return sendto (sock->sd, BPTR (buf), BLEN (buf), 0, >- (struct sockaddr *) &to->dest.sa, >- (socklen_t) sizeof (to->dest.sa)); >+ (struct sockaddr *) &to->dest.addr.sa, >+ (socklen_t) af_addr_size(to->dest.addr.sa.sa_family)); > } > > static inline int >@@ -813,11 +984,11 @@ link_socket_write (struct link_socket *s > struct buffer *buf, > struct link_socket_actual *to) > { >- if (sock->info.proto == PROTO_UDPv4) >+ if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */ > { > return link_socket_write_udp (sock, buf, to); > } >- else if (sock->info.proto == PROTO_TCPv4_SERVER || sock->info.proto == PROTO_TCPv4_CLIENT) >+ else if (proto_is_tcp(sock->info.proto)) /* unified TCPv4 and TCPv6 */ > { > return link_socket_write_tcp (sock, buf, to); > } >diff --git a/openvpn/socks.c b/openvpn/socks.c >index cc9d82f..7ec9a3e 100644 >--- a/openvpn/socks.c >+++ b/openvpn/socks.c >@@ -175,9 +175,9 @@ recv_socks_reply (socket_descriptor_t sd > > if (addr != NULL) > { >- addr->sa.sin_family = AF_INET; >- addr->sa.sin_addr.s_addr = htonl (INADDR_ANY); >- addr->sa.sin_port = htons (0); >+ addr->addr.in4.sin_family = AF_INET; >+ addr->addr.in4.sin_addr.s_addr = htonl (INADDR_ANY); >+ addr->addr.in4.sin_port = htons (0); > } > > while (len < 4 + alen + 2) >@@ -264,8 +264,8 @@ recv_socks_reply (socket_descriptor_t sd > /* ATYP == 1 (IP V4 address) */ > if (atyp == '\x01' && addr != NULL) > { >- memcpy (&addr->sa.sin_addr, buf + 4, sizeof (addr->sa.sin_addr)); >- memcpy (&addr->sa.sin_port, buf + 8, sizeof (addr->sa.sin_port)); >+ memcpy (&addr->addr.in4.sin_addr, buf + 4, sizeof (addr->addr.in4.sin_addr)); >+ memcpy (&addr->addr.in4.sin_port, buf + 8, sizeof (addr->addr.in4.sin_port)); > } > > >@@ -383,8 +383,8 @@ socks_process_incoming_udp (struct buffe > if (atyp != 1) /* ATYP == 1 (IP V4) */ > goto error; > >- buf_read (buf, &from->dest.sa.sin_addr, sizeof (from->dest.sa.sin_addr)); >- buf_read (buf, &from->dest.sa.sin_port, sizeof (from->dest.sa.sin_port)); >+ buf_read (buf, &from->dest.addr.in4.sin_addr, sizeof (from->dest.addr.in4.sin_addr)); >+ buf_read (buf, &from->dest.addr.in4.sin_port, sizeof (from->dest.addr.in4.sin_port)); > > return; > >@@ -416,8 +416,8 @@ socks_process_outgoing_udp (struct buffe > buf_write_u16 (&head, 0); /* RSV = 0 */ > buf_write_u8 (&head, 0); /* FRAG = 0 */ > buf_write_u8 (&head, '\x01'); /* ATYP = 1 (IP V4) */ >- buf_write (&head, &to->dest.sa.sin_addr, sizeof (to->dest.sa.sin_addr)); >- buf_write (&head, &to->dest.sa.sin_port, sizeof (to->dest.sa.sin_port)); >+ buf_write (&head, &to->dest.addr.in4.sin_addr, sizeof (to->dest.addr.in4.sin_addr)); >+ buf_write (&head, &to->dest.addr.in4.sin_port, sizeof (to->dest.addr.in4.sin_port)); > > return 10; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 183457
:
123241
|
123242
|
123247
|
123248
| 123249 |
142939
|
142940
|
149997
|
162041
|
162043