View | Details | Raw Unified
Collapse All | Expand All

(-) a/jjo-tests/libtest.sh (+115 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/qemu-ifup-2.jjo.sh (+12 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/qemu-ifup-3.jjo.sh (+12 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/run-afunix-0-loop.sh (+4 lines)
Line 0    Link Here 
#!/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 $*
(-) a/jjo-tests/run-afunix-1-o1.sh (+3 lines)
Line 0    Link Here 
#!/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 $*
(-) a/jjo-tests/run-afunix-1-o2.sh (+3 lines)
Line 0    Link Here 
#!/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 $*
(-) a/jjo-tests/run-oxg-1.sh (+3 lines)
Line 0    Link Here 
#!/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 "$@"
(-) a/jjo-tests/run-oxg-2.sh (+3 lines)
Line 0    Link Here 
#!/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 "$@"
(-) a/jjo-tests/run-tcp4-0-loopback-client.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN} --dev null --proto tcp-client --remote localhost --rport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-tcp4-0-loopback-server.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN}  --dev null --proto tcp-server --remote localhost --lport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-tcp6-0-loopback-client-byname.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN}  --dev null --proto tcp6-client --remote ip6-localhost --rport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-tcp6-0-loopback-client.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN}  --dev null --proto tcp6-client --remote ::1 --rport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-tcp6-0-loopback-server-byname.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN}  --dev null --proto tcp6-server --local ip6-localhost --lport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-tcp6-0-loopback-server.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${OPENVPN}  --dev null --proto tcp6-server --local :: --lport 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-udp4-0-loopback-self.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${GDB} ${OPENVPN} --dev null --proto udp --remote localhost --port 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-udp4-1-qemu-guest.sh (+3 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/run-udp4-1-qemu-host.sh (+3 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/run-udp4-2-MH.sh (+4 lines)
Line 0    Link Here 
#!/bin/sh -x
#pass --local ADDR --remote ADDR
: ${OPENVPN:=./openvpn}
${GDB} ${OPENVPN} --dev tun --proto udp --port 5011 --secret ../openvpn.key --ifconfig-noexec "$@"
(-) a/jjo-tests/run-udp6-0-loopback-byname.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${GDB} ${OPENVPN} --dev null --proto udp6 --remote ip6-localhost --port 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-udp6-0-loopback-self.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${GDB} ${OPENVPN} --dev null --proto udp6 --remote ::1 --port 5011 --secret ../openvpn.key "$@"
(-) a/jjo-tests/run-udp6-1-carpediem.sh (+4 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/run-udp6-1-cx.sh (+3 lines)
Line 0    Link Here 
#!/bin/sh -x
: ${OPENVPN:=./openvpn}
${GDB} ${OPENVPN} --verb 5 --dev tun --proto udp6 --port 5010 --secret /home/jjo/src/juanjo/openvpn.key --float --ifconfig 1.1.1.1 1.1.1.253
(-) a/jjo-tests/run-udp6-2-qemu-guest.sh (+8 lines)
Line 0    Link Here 
#!/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
(-) a/jjo-tests/run-udp6-2-qemu-host.sh (+4 lines)
Line 0    Link Here 
#!/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 "$@"
(-) a/buffer.c (+13 lines)
 Lines 215-220   } Link Here 
  return ret;
  return ret;
}
}
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,
 * This is necessary due to certain buggy implementations of snprintf,
 * that don't guarantee null termination for size > 0.
 * that don't guarantee null termination for size > 0.
(-) a/configure.ac (+16 lines)
 Lines 135-140   [MULTIHOME="$enableval"], Link Here 
   [MULTIHOME="yes"]
   [MULTIHOME="yes"]
)
)
AC_ARG_ENABLE(ipv6,
   [  --disable-ipv6          Disable UDP/IPv6 support],
   [PF_INET6="$enableval"],
   [PF_INET6="yes"]
)
AC_ARG_ENABLE(port-share,
AC_ARG_ENABLE(port-share,
   [  --disable-port-share    Disable TCP server port-share support (--port-share)],
   [  --disable-port-share    Disable TCP server port-share support (--port-share)],
   [PORT_SHARE="$enableval"],
   [PORT_SHARE="$enableval"],
 Lines 524-529   LDFLAGS="$LDFLAGS -Wl,--fatal-warnings" Link Here 
AC_CHECK_FUNC(epoll_create, AC_DEFINE(HAVE_EPOLL_CREATE, 1, [epoll_create function is defined]))
AC_CHECK_FUNC(epoll_create, AC_DEFINE(HAVE_EPOLL_CREATE, 1, [epoll_create function is defined]))
LDFLAGS="$OLDLDFLAGS"
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
dnl check for valgrind tool
dnl check for valgrind tool
dnl
dnl
(-) a/init.c (-15 / +18 lines)
 Lines 884-890   #ifdef ENABLE_MANAGEMENT Link Here 
      const char *detail = "SUCCESS";
      const char *detail = "SUCCESS";
      if (c->c1.tuntap)
      if (c->c1.tuntap)
	tun_local = c->c1.tuntap->local;
	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)
      if (flags & ISC_ERRORS)
	detail = "ERROR";
	detail = "ERROR";
      management_set_state (management,
      management_set_state (management,
 Lines 1289-1295   do_deferred_options (struct context *c, Link Here 
#ifdef ENABLE_OCC
#ifdef ENABLE_OCC
  if (found & OPT_P_EXPLICIT_NOTIFY)
  if (found & OPT_P_EXPLICIT_NOTIFY)
    {
    {
      if (c->options.ce.proto != PROTO_UDPv4 && c->options.explicit_exit_notification)
      if (!proto_is_udp(c->options.ce.proto) && c->options.explicit_exit_notification)
	{
	{
	  msg (D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp");
	  msg (D_PUSH, "OPTIONS IMPORT: --explicit-exit-notify can only be used with --proto udp");
	  c->options.explicit_exit_notification = 0;
	  c->options.explicit_exit_notification = 0;
 Lines 1384-1395   #endif Link Here 
  switch (c->options.ce.proto)
  switch (c->options.ce.proto)
    {
    {
    case PROTO_UDPv4:
    case PROTO_UDPv4:
#ifdef USE_PF_INET6
    case PROTO_UDPv6:
#endif
      if (proxy)
      if (proxy)
	sec = c->options.ce.connect_retry_seconds;
	sec = c->options.ce.connect_retry_seconds;
      break;
      break;
#ifdef USE_PF_INET6
    case PROTO_TCPv6_SERVER:
#endif
    case PROTO_TCPv4_SERVER:
    case PROTO_TCPv4_SERVER:
      sec = 1;
      sec = 1;
      break;
      break;
#ifdef USE_PF_INET6
    case PROTO_TCPv6_CLIENT:
#endif
    case PROTO_TCPv4_CLIENT:
    case PROTO_TCPv4_CLIENT:
      sec = c->options.ce.connect_retry_seconds;
      sec = c->options.ce.connect_retry_seconds;
      break;
      break;
 Lines 2504-2510   do_setup_fast_io (struct context *c) Link Here 
#ifdef WIN32
#ifdef WIN32
      msg (M_INFO, "NOTE: --fast-io is disabled since we are running on Windows");
      msg (M_INFO, "NOTE: --fast-io is disabled since we are running on Windows");
#else
#else
      if (c->options.ce.proto != PROTO_UDPv4)
      if (!proto_is_udp(c->options.ce.proto))
	msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP");
	msg (M_INFO, "NOTE: --fast-io is disabled since we are not using UDP");
      else
      else
	{
	{
 Lines 2764-2770   init_instance (struct context *c, const Link Here 
  /* link_socket_mode allows CM_CHILD_TCP
  /* link_socket_mode allows CM_CHILD_TCP
     instances to inherit acceptable fds
     instances to inherit acceptable fds
     from a top-level parent */
     from a top-level parent */
#ifdef USE_PF_INET6
  if (c->options.ce.proto == PROTO_TCPv4_SERVER || c->options.ce.proto == PROTO_TCPv6_SERVER)
#else
  if (c->options.ce.proto == PROTO_TCPv4_SERVER)
  if (c->options.ce.proto == PROTO_TCPv4_SERVER)
#endif
    {
    {
      if (c->mode == CM_TOP)
      if (c->mode == CM_TOP)
	link_socket_mode = LS_MODE_TCP_LISTEN;
	link_socket_mode = LS_MODE_TCP_LISTEN;
 Lines 3047-3063   inherit_context_child (struct context *d Link Here 
{
{
  CLEAR (*dest);
  CLEAR (*dest);
  switch (src->options.ce.proto)
  dest->mode = proto_is_dgram(src->options.ce.proto)? CM_CHILD_UDP : CM_CHILD_TCP;
    {
    case PROTO_UDPv4:
      dest->mode = CM_CHILD_UDP;
      break;
    case PROTO_TCPv4_SERVER:
      dest->mode = CM_CHILD_TCP;
      break;
    default:
      ASSERT (0);
    }
  dest->gc = gc_new ();
  dest->gc = gc_new ();
 Lines 3163-3169    Link Here 
  dest->c2.es_owned = false;
  dest->c2.es_owned = false;
  dest->c2.event_set = NULL;
  dest->c2.event_set = NULL;
  if (src->options.ce.proto == PROTO_UDPv4)
  if (proto_is_dgram(src->options.ce.proto))
    do_event_set_init (dest, false);
    do_event_set_init (dest, false);
}
}
(-) a/manage.c (-5 / +5 lines)
 Lines 1669-1677   man_settings_init (struct man_settings * Link Here 
      /*
      /*
       * Initialize socket address
       * Initialize socket address
       */
       */
      ms->local.sa.sin_family = AF_INET;
      ms->local.addr.in4.sin_family = AF_INET;
      ms->local.sa.sin_addr.s_addr = 0;
      ms->local.addr.in4.sin_addr.s_addr = 0;
      ms->local.sa.sin_port = htons (port);
      ms->local.addr.in4.sin_port = htons (port);
      /*
      /*
       * Run management over tunnel, or
       * Run management over tunnel, or
 Lines 1683-1689   man_settings_init (struct man_settings * Link Here 
	}
	}
      else
      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);
	    (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
	}
	}
      
      
 Lines 2022-2028   management_post_tunnel_open (struct mana Link Here 
      && man->connection.state == MS_INITIAL)
      && man->connection.state == MS_INITIAL)
    {
    {
      /* listen on our local TUN/TAP IP address */
      /* 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);
      man_connection_init (man);
    }
    }
(-) a/mroute.c (-4 / +56 lines)
 Lines 226-250   bool mroute_extract_openvpn_sockaddr (st Link Here 
				      const struct openvpn_sockaddr *osaddr,
				      const struct openvpn_sockaddr *osaddr,
				      bool use_port)
				      bool use_port)
{
{
  if (osaddr->sa.sin_family == AF_INET)
  switch (osaddr->addr.sa.sa_family) 
  {
    case AF_INET:
    {
    {
      if (use_port)
      if (use_port)
	{
	{
	  addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
	  addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
	  addr->netbits = 0;
	  addr->netbits = 0;
	  addr->len = 6;
	  addr->len = 6;
	  memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
	  memcpy (addr->addr, &osaddr->addr.in4.sin_addr.s_addr, 4);
	  memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2);
	  memcpy (addr->addr + 4, &osaddr->addr.in4.sin_port, 2);
	}
	}
      else
      else
	{
	{
	  addr->type = MR_ADDR_IPV4;
	  addr->type = MR_ADDR_IPV4;
	  addr->netbits = 0;
	  addr->netbits = 0;
	  addr->len = 4;
	  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;
      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;
  return false;
}
}
 Lines 337-343   mroute_addr_print (const struct mroute_a Link Here 
	  }
	  }
	  break;
	  break;
	case MR_ADDR_IPV6:
	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"); 
	  buf_printf (&out, "IPV6"); 
#endif
	  break;
	  break;
	default:
	default:
	  buf_printf (&out, "UNKNOWN"); 
	  buf_printf (&out, "UNKNOWN"); 
(-) a/mtcp.c (+1 lines)
 Lines 153-158   multi_tcp_instance_specific_init (struct Link Here 
  ASSERT (mi->context.c2.link_socket);
  ASSERT (mi->context.c2.link_socket);
  ASSERT (mi->context.c2.link_socket->info.lsa);
  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->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))
  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");
      msg (D_MULTI_ERRORS, "MULTI TCP: TCP client address is undefined");
(-) a/multi.c (-15 / +10 lines)
 Lines 1053-1060   multi_learn_in_addr_t (struct multi_cont Link Here 
  struct mroute_addr addr;
  struct mroute_addr addr;
  CLEAR (remote_si);
  CLEAR (remote_si);
  remote_si.sa.sin_family = AF_INET;
  remote_si.addr.in4.sin_family = AF_INET;
  remote_si.sa.sin_addr.s_addr = htonl (a);
  remote_si.addr.in4.sin_addr.s_addr = htonl (a);
  ASSERT (mroute_extract_openvpn_sockaddr (&addr, &remote_si, false));
  ASSERT (mroute_extract_openvpn_sockaddr (&addr, &remote_si, false));
  if (netbits >= 0)
  if (netbits >= 0)
 Lines 2464-2472   management_callback_kill_by_addr (void * Link Here 
  int count = 0;
  int count = 0;
  CLEAR (saddr);
  CLEAR (saddr);
  saddr.sa.sin_family = AF_INET;
  saddr.addr.in4.sin_family = AF_INET;
  saddr.sa.sin_addr.s_addr = htonl (addr);
  saddr.addr.in4.sin_addr.s_addr = htonl (addr);
  saddr.sa.sin_port = htons (port);
  saddr.addr.in4.sin_port = htons (port);
  if (mroute_extract_openvpn_sockaddr (&maddr, &saddr, true))
  if (mroute_extract_openvpn_sockaddr (&maddr, &saddr, true))
    {
    {
      hash_iterator_init (m->iter, &hi, true);
      hash_iterator_init (m->iter, &hi, true);
 Lines 2614-2631   tunnel_server (struct context *top) Link Here 
{
{
  ASSERT (top->options.mode == MODE_SERVER);
  ASSERT (top->options.mode == MODE_SERVER);
  switch (top->options.ce.proto) {
  if (proto_is_dgram(top->options.ce.proto))
  case PROTO_UDPv4:
    tunnel_server_udp(top);
    tunnel_server_udp (top);
  else
    break;
    tunnel_server_tcp(top);
  case PROTO_TCPv4_SERVER:
    tunnel_server_tcp (top);
    break;
  default:
    ASSERT (0);
  }
}
}
#else
#else
static void dummy(void) {}
static void dummy(void) {}
#endif /* P2MP_SERVER */
#endif /* P2MP_SERVER */
(-) a/occ.c (-1 / +1 lines)
 Lines 369-375   process_received_occ_msg (struct context Link Here 
	       c->c2.max_send_size_remote,
	       c->c2.max_send_size_remote,
	       c->c2.max_recv_size_local);
	       c->c2.max_recv_size_local);
	  if (!c->options.fragment
	  if (!c->options.fragment
	      && c->options.ce.proto == PROTO_UDPv4
	      && (proto_is_dgram(c->options.ce.proto))
	      && c->c2.max_send_size_local > TUN_MTU_MIN
	      && 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_remote < c->c2.max_send_size_local
		  || c->c2.max_recv_size_local < c->c2.max_send_size_remote))
		  || c->c2.max_recv_size_local < c->c2.max_send_size_remote))
(-) a/ps.c (-3 / +3 lines)
 Lines 332-340   sock_addr_set (struct openvpn_sockaddr * Link Here 
	       const int port)
	       const int port)
{
{
  CLEAR (*osaddr);
  CLEAR (*osaddr);
  osaddr->sa.sin_family = AF_INET;
  osaddr->addr.in4.sin_family = AF_INET;
  osaddr->sa.sin_addr.s_addr = htonl (addr);
  osaddr->addr.in4.sin_addr.s_addr = htonl (addr);
  osaddr->sa.sin_port = htons (port);
  osaddr->addr.in4.sin_port = htons (port);
}
}
static inline void
static inline void
(-) a/socket.h (-31 / +202 lines)
 Lines 70-76   #define ntohps(x) ntohs(x) Link Here 
struct openvpn_sockaddr
struct openvpn_sockaddr
{
{
  /*int dummy;*/ /* add offset to force a bug if sa not explicitly dereferenced */
  /*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 */
/* actual address of remote, based on source address of received packets */
 Lines 79-85   { Link Here 
  /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */
  /*int dummy;*/ /* add offset to force a bug if dest not explicitly dereferenced */
  struct openvpn_sockaddr dest;
  struct openvpn_sockaddr dest;
#if ENABLE_IP_PKTINFO
#if ENABLE_IP_PKTINFO
  struct in_pktinfo pi;
  union {
    struct in_pktinfo in4;
#ifdef USE_PF_INET6
    struct in6_pktinfo in6;
#endif
  } pi;
#endif
#endif
};
};
 Lines 403-408   socket_descriptor_t create_socket_tcp (v Link Here 
socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
				      struct link_socket_actual *act,
				      struct link_socket_actual *act,
				      const bool nowait);
				      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
 * DNS resolution
 Lines 428-450   in_addr_t getaddr (unsigned int flags, Link Here 
 * Transport protocol naming and other details.
 * Transport protocol naming and other details.
 */
 */
#define PROTO_UDPv4        0
#if 0 /* PRE UDPv6/TCPv6 code */
#define PROTO_TCPv4_SERVER 1
#define PROTO_NONE         0 /* catch for uninitialized */
#define PROTO_TCPv4_CLIENT 2
#define PROTO_UDPv4        1
#define PROTO_TCPv4        3
#define PROTO_TCPv4_SERVER 2
#define PROTO_N            4
#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);
int ascii2proto (const char* proto_name);
const char *proto2ascii (int proto, bool display_form);
const char *proto2ascii (int proto, bool display_form);
const char *proto2ascii_all (struct gc_arena *gc);
const char *proto2ascii_all (struct gc_arena *gc);
int proto_remote (int proto, bool remote);
int proto_remote (int proto, bool remote);
const char *addr_family_name(int af);
/*
/*
 * Overhead added to packets by various protocols.
 * Overhead added to packets by various protocols.
 */
 */
#define IPv4_UDP_HEADER_SIZE              28
#define IPv4_UDP_HEADER_SIZE              28
#define IPv4_TCP_HEADER_SIZE              40
#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[];
extern const int proto_overhead[];
 Lines 468-474   legal_ipv4_port (int port) Link Here 
static inline bool
static inline bool
link_socket_proto_connection_oriented (int proto)
link_socket_proto_connection_oriented (int proto)
{
{
  return proto == PROTO_TCPv4_SERVER || proto == PROTO_TCPv4_CLIENT;
  return !proto_is_dgram(proto);
}
}
static inline bool
static inline bool
 Lines 483-489   link_socket_connection_oriented (const s Link Here 
static inline bool
static inline bool
addr_defined (const struct openvpn_sockaddr *addr)
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
static inline bool
 Lines 495-514   link_socket_actual_defined (const struct Link Here 
static inline bool
static inline bool
addr_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
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
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
static inline bool
addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
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
  switch(a1->addr.sa.sa_family) {
    && a1->sa.sin_port == a2->sa.sin_port;
    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
static inline bool
 Lines 521-526   addr_match_proto (const struct openvpn_s Link Here 
    : addr_port_match (a1, a2);
    : 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
static inline bool
link_socket_actual_match (const struct link_socket_actual *a1, const struct link_socket_actual *a2)
link_socket_actual_match (const struct link_socket_actual *a1, const struct link_socket_actual *a2)
{
{
 Lines 577-590   link_socket_verify_incoming_addr (struct Link Here 
{
{
  if (buf->len > 0)
  if (buf->len > 0)
    {
    {
      if (from_addr->dest.sa.sin_family != AF_INET)
      switch (from_addr->dest.addr.sa.sa_family) {
	return false;
#ifdef USE_PF_INET6
      if (!link_socket_actual_defined (from_addr))
	case AF_INET6:
	return false;
#endif
      if (info->remote_float || !addr_defined (&info->lsa->remote))
	case AF_INET:
	return true;
	  if (!link_socket_actual_defined (from_addr))
      if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto))
	    return false;
	return true;
	  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;
  return false;
}
}
 Lines 690-696   link_socket_read (struct link_socket *so Link Here 
		  int maxsize,
		  int maxsize,
		  struct link_socket_actual *from)
		  struct link_socket_actual *from)
{
{
  if (sock->info.proto == PROTO_UDPv4)
  if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */
    {
    {
      int res;
      int res;
 Lines 701-710   #else Link Here 
#endif
#endif
      return res;
      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 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);
      return link_socket_read_tcp (sock, buf);
    }
    }
  else
  else
 Lines 759-771   #if ENABLE_IP_PKTINFO Link Here 
					   struct buffer *buf,
					   struct buffer *buf,
					   struct link_socket_actual *to);
					   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);
    return link_socket_write_udp_posix_sendmsg (sock, buf, to);
  else
  else
#endif
#endif
    return sendto (sock->sd, BPTR (buf), BLEN (buf), 0,
    return sendto (sock->sd, BPTR (buf), BLEN (buf), 0,
		   (struct sockaddr *) &to->dest.sa,
		   (struct sockaddr *) &to->dest.addr.sa,
		   (socklen_t) sizeof (to->dest.sa));
		   (socklen_t) af_addr_size(to->dest.addr.sa.sa_family));
}
}
static inline int
static inline int
 Lines 796-806   link_socket_write (struct link_socket *s Link Here 
		   struct buffer *buf,
		   struct buffer *buf,
		   struct link_socket_actual *to)
		   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);
      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);
      return link_socket_write_tcp (sock, buf, to);
    }
    }
(-) a/socks.c (-9 / +9 lines)
 Lines 174-182   recv_socks_reply (socket_descriptor_t sd Link Here 
  if (addr != NULL)
  if (addr != NULL)
    {
    {
      addr->sa.sin_family = AF_INET;
      addr->addr.in4.sin_family = AF_INET;
      addr->sa.sin_addr.s_addr = htonl (INADDR_ANY);
      addr->addr.in4.sin_addr.s_addr = htonl (INADDR_ANY);
      addr->sa.sin_port = htons (0);
      addr->addr.in4.sin_port = htons (0);
    }
    }
  while (len < 4 + alen + 2)
  while (len < 4 + alen + 2)
 Lines 263-270   recv_socks_reply (socket_descriptor_t sd Link Here 
  /* ATYP == 1 (IP V4 address) */
  /* ATYP == 1 (IP V4 address) */
  if (atyp == '\x01' && addr != NULL)
  if (atyp == '\x01' && addr != NULL)
    {
    {
      memcpy (&addr->sa.sin_addr, buf + 4, sizeof (addr->sa.sin_addr));
      memcpy (&addr->addr.in4.sin_addr, buf + 4, sizeof (addr->addr.in4.sin_addr));
      memcpy (&addr->sa.sin_port, buf + 8, sizeof (addr->sa.sin_port));
      memcpy (&addr->addr.in4.sin_port, buf + 8, sizeof (addr->addr.in4.sin_port));
    }
    }
 Lines 382-389   socks_process_incoming_udp (struct buffe Link Here 
  if (atyp != 1)		/* ATYP == 1 (IP V4) */
  if (atyp != 1)		/* ATYP == 1 (IP V4) */
    goto error;
    goto error;
  buf_read (buf, &from->dest.sa.sin_addr, sizeof (from->dest.sa.sin_addr));
  buf_read (buf, &from->dest.addr.in4.sin_addr, sizeof (from->dest.addr.in4.sin_addr));
  buf_read (buf, &from->dest.sa.sin_port, sizeof (from->dest.sa.sin_port));
  buf_read (buf, &from->dest.addr.in4.sin_port, sizeof (from->dest.addr.in4.sin_port));
  return;
  return;
 Lines 415-422   socks_process_outgoing_udp (struct buffe Link Here 
  buf_write_u16 (&head, 0);	/* RSV = 0 */
  buf_write_u16 (&head, 0);	/* RSV = 0 */
  buf_write_u8 (&head, 0);	/* FRAG = 0 */
  buf_write_u8 (&head, 0);	/* FRAG = 0 */
  buf_write_u8 (&head, '\x01'); /* ATYP = 1 (IP V4) */
  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.addr.in4.sin_addr, sizeof (to->dest.addr.in4.sin_addr));
  buf_write (&head, &to->dest.sa.sin_port, sizeof (to->dest.sa.sin_port));
  buf_write (&head, &to->dest.addr.in4.sin_port, sizeof (to->dest.addr.in4.sin_port));
  return 10;
  return 10;
}
}
(-) a/socket.c (-208 / +613 lines)
 Lines 36-45    Link Here 
#include "memdbg.h"
#include "memdbg.h"
const int proto_overhead[] = { /* indexed by PROTO_x */
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,
  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
};
};
/*
/*
 Lines 299-318    Link Here 
	       struct openvpn_sockaddr *addr,
	       struct openvpn_sockaddr *addr,
	       bool *changed)
	       bool *changed)
{
{
  if (host && addr)
  switch(addr->addr.sa.sa_family) {
    {
    case AF_INET:
      const in_addr_t new_addr = getaddr (
      if (host && addr)
					  GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE,
      {
					  host,
	const in_addr_t new_addr = getaddr (
					  1,
	    GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE,
					  NULL,
	    host,
					  NULL);
	    1,
      if (new_addr && addr->sa.sin_addr.s_addr != new_addr)
	    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;
	  *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
static int
 Lines 505-510    Link Here 
  return sd;
  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
static void
create_socket (struct link_socket *sock)
create_socket (struct link_socket *sock)
{
{
 Lines 523-528    Link Here 
    {
    {
      sock->sd = create_socket_tcp ();
      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
  else
    {
    {
      ASSERT (0);
      ASSERT (0);
 Lines 560-566    Link Here 
		  struct link_socket_actual *act,
		  struct link_socket_actual *act,
		  const bool nowait)
		  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;
  socket_descriptor_t new_sd = SOCKET_UNDEFINED;
  CLEAR (*act);
  CLEAR (*act);
 Lines 568-574    Link Here 
#ifdef HAVE_GETPEERNAME
#ifdef HAVE_GETPEERNAME
  if (nowait)
  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))
      if (!socket_defined (new_sd))
	msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: getpeername() failed");
	msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: getpeername() failed");
 Lines 581-587    Link Here 
#endif
#endif
  else
  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 */
#if 0 /* For debugging only, test the effect of accept() failures */
 Lines 597-603    Link Here 
    {
    {
      msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: accept(%d) failed", sd);
      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);
      msg (D_LINK_ERRORS, "TCP: Received strange incoming connection with unknown address length=%d", remote_len);
      openvpn_close_socket (new_sd);
      openvpn_close_socket (new_sd);
 Lines 698-704    Link Here 
{
{
  struct gc_arena gc = gc_new ();
  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 ();
      const int errnum = openvpn_errno_socket ();
      msg (M_FATAL, "%s: Socket bind failed on local address %s: %s",
      msg (M_FATAL, "%s: Socket bind failed on local address %s: %s",
 Lines 719-725    Link Here 
#ifdef CONNECT_NONBLOCK
#ifdef CONNECT_NONBLOCK
  set_nonblock (sd);
  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)
  if (status)
    status = openvpn_errno_socket ();
    status = openvpn_errno_socket ();
  if (status == EINPROGRESS)
  if (status == EINPROGRESS)
 Lines 854-870    Link Here 
      if (*signal_received)
      if (*signal_received)
	goto done;
	goto done;
      *sd = create_socket_tcp ();
      switch(remote->addr.sa.sa_family) {
      if (bind_local)
        case AF_INET:
        socket_bind (*sd, local, "TCP Client");
          *sd = create_socket_tcp ();
      update_remote (remote_dynamic, remote, remote_changed);
          if (bind_local)
    }
            socket_bind (*sd, local, "TCP Client");
          update_remote (remote_dynamic, remote, remote_changed);
          break;
  #ifdef USE_PF_INET6
        case AF_INET6:
          *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", 
  msg (M_INFO, "TCP connection established with %s",
       print_sockaddr (remote, &gc));
       print_sockaddr (remote, &gc));
 done:
  done:
  gc_free (&gc);
    gc_free (&gc);
}
}
/* For stream protocols, allocate a buffer to build up packet.
/* For stream protocols, allocate a buffer to build up packet.
 Lines 918-934    Link Here 
  /* resolve local address if undefined */
  /* resolve local address if undefined */
  if (!addr_defined (&sock->info.lsa->local))
  if (!addr_defined (&sock->info.lsa->local))
    {
  {
      sock->info.lsa->local.sa.sin_family = AF_INET;
    /* may return AF_{INET|INET6} guessed from local_host */
      sock->info.lsa->local.sa.sin_addr.s_addr =
    switch(addr_guess_family(sock->info.proto, sock->local_host)) {
	(sock->local_host ? getaddr (GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL,
      case AF_INET:
				     sock->local_host,
	sock->info.lsa->local.addr.in4.sin_family = AF_INET;
				     0,
	sock->info.lsa->local.addr.in4.sin_addr.s_addr =
				     NULL,
	  (sock->local_host ? getaddr (GETADDR_RESOLVE | GETADDR_WARN_ON_SIGNAL | GETADDR_FATAL,
				     NULL)
				       sock->local_host,
	 : htonl (INADDR_ANY));
				       0,
      sock->info.lsa->local.sa.sin_port = htons (sock->local_port);
				       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 */
  /* bind to local address/port */
  if (sock->bind_local)
  if (sock->bind_local)
 Lines 955-1055    Link Here 
    {
    {
      /* resolve remote address if undefined */
      /* resolve remote address if undefined */
      if (!addr_defined (&sock->info.lsa->remote))
      if (!addr_defined (&sock->info.lsa->remote))
	{
      {
	  sock->info.lsa->remote.sa.sin_family = AF_INET;
        switch(addr_guess_family(sock->info.proto, sock->remote_host))
	  sock->info.lsa->remote.sa.sin_addr.s_addr = 0;
        {
        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)
	  if (sock->remote_host)
	    {
          {
	      unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE;
            unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE;
	      int retry = 0;
            int retry = 0;
	      bool status = false;
            bool status = false;
	      if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
            if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE)
		{
              {
		  if (phase == 2)
                if (phase == 2)
		    flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
                  flags |= (GETADDR_TRY_ONCE | GETADDR_FATAL);
		  retry = 0;
                retry = 0;
		}
              }
	      else if (phase == 1)
              else if (phase == 1)
		{
                {
		  if (sock->resolve_retry_seconds)
                  if (sock->resolve_retry_seconds)
		    {
                    {
		      retry = 0;
                      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
		  else
		    {
                    {
		      ASSERT (0);
	               flags |= (GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY);
		    }
	               retry = 0;
		}
	            }
	      else
	          }
		{
	          else if (phase == 2)
		  ASSERT (0);
	          {
		}
	            if (sock->resolve_retry_seconds)
	            {
	      sock->info.lsa->remote.sa.sin_addr.s_addr = getaddr (
	              flags |= GETADDR_FATAL;
		    flags,
	              retry = sock->resolve_retry_seconds;
		    sock->remote_host,
	            }
		    retry,
	            else
		    &status,
	            {
		    signal_received);
	              ASSERT (0);
	      
	            }
	      dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d",
	          }
		   flags,
	          else
		   phase,
	          {
		   retry,
	            ASSERT (0);
		   signal_received ? *signal_received : -1,
	          }
		   status);
	          sock->info.lsa->remote.addr.in4.sin_addr.s_addr = getaddr (
	      if (signal_received)
	              flags,
		{
	              sock->remote_host,
		  if (*signal_received)
	              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)
		      *signal_received = SIGUSR1;
		    goto done;
		    goto done;
		}
		  }
	      if (!status)
	        }
		{
		  if (signal_received)
		    *signal_received = SIGUSR1;
		  goto done;
		}
	    }
	  sock->info.lsa->remote.sa.sin_port = htons (sock->remote_port);
          sock->info.lsa->remote.addr.in4.sin_port = htons (sock->remote_port);
	}
          break;
  
  
  #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? */
      /* should we re-use previous active remote address? */
      if (link_socket_actual_defined (&sock->info.lsa->actual))
      if (link_socket_actual_defined (&sock->info.lsa->actual))
	{
      {
	  msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s",
        msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s",
	       print_link_socket_actual (&sock->info.lsa->actual, &gc));
          print_link_socket_actual (&sock->info.lsa->actual, &gc));
	  if (remote_dynamic)
        if (remote_dynamic)
	    *remote_dynamic = NULL;
        *remote_dynamic = NULL;
	}
      }
      else
      else
	{
      {
	  CLEAR (sock->info.lsa->actual);
        CLEAR (sock->info.lsa->actual);
	  sock->info.lsa->actual.dest = sock->info.lsa->remote;
        sock->info.lsa->actual.dest = sock->info.lsa->remote;
	}
      }
      /* remember that we finished */
      /* remember that we finished */
      sock->did_resolve_remote = true;
      sock->did_resolve_remote = true;
    }
    }
 done:
  done:
  gc_free (&gc);
   gc_free (&gc);
}
}
struct link_socket *
struct link_socket *
 Lines 1268-1274    Link Here 
	goto done;
	goto done;
      /* TCP client/server */
      /* 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)
	  switch (sock->mode)
	    {
	    {
 Lines 1303-1309    Link Here 
	      ASSERT (0);
	      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
#ifdef GENERAL_PROXY_SUPPORT
 Lines 1388-1395    Link Here 
	  sock->remote_port = sock->proxy_dest_port;
	  sock->remote_port = sock->proxy_dest_port;
	  sock->did_resolve_remote = false;
	  sock->did_resolve_remote = false;
	  sock->info.lsa->actual.dest.sa.sin_addr.s_addr = 0;
	  addr_zero_host(&sock->info.lsa->actual.dest);
	  sock->info.lsa->remote.sa.sin_addr.s_addr = 0;
	  addr_zero_host(&sock->info.lsa->remote);
	  resolve_remote (sock, 1, NULL, signal_received);
	  resolve_remote (sock, 1, NULL, signal_received);
 Lines 1404-1410    Link Here 
      if (remote_changed)
      if (remote_changed)
	{
	{
	  msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment");
	  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);
	}
	}
    }
    }
 Lines 1593-1605    Link Here 
{
{
  struct gc_arena gc = gc_new ();
  struct gc_arena gc = gc_new ();
  msg (D_LINK_ERRORS,
  switch(from_addr->dest.addr.sa.sa_family)
       "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),
    case AF_INET:
       (int)from_addr->dest.sa.sin_family,
#ifdef USE_PF_INET6
       print_sockaddr (&info->lsa->remote, &gc));
    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;
  buf->len = 0;
  gc_free (&gc);
  gc_free (&gc);
}
}
 Lines 1614-1623    Link Here 
{
{
  const struct link_socket_addr *lsa = info->lsa;
  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))
  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))
  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
  else
    return 0;
    return 0;
}
}
 Lines 1844-1871    Link Here 
		   const unsigned int flags,
		   const unsigned int flags,
		   struct gc_arena *gc)
		   struct gc_arena *gc)
{
{
  if (addr)
   struct buffer out;
    {
   bool addr_is_defined;
      struct buffer out = alloc_buf_gc (64, gc);
   if (!addr) {
      const int port = ntohs (addr->sa.sin_port);
     return "[NULL]";
   }
      mutex_lock_static (L_INET_NTOA);
   addr_is_defined =  addr_defined (addr);
      if (!(flags & PS_DONT_SHOW_ADDR))
   switch(addr->addr.sa.sa_family) {
	buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sa.sin_addr) : "[undef]"));
     case AF_INET:
      mutex_unlock_static (L_INET_NTOA);
       {
       const int port= ntohs (addr->addr.in4.sin_port);
      if (((flags & PS_SHOW_PORT) || (addr_defined (addr) && (flags & PS_SHOW_PORT_IF_DEFINED)))
       out = alloc_buf_gc (128, gc);
	  && port)
       buf_puts (&out, "[AF_INET]");
	{
       mutex_lock_static (L_INET_NTOA);
	  if (separator)
       buf_puts (&out, (addr_is_defined ? inet_ntoa (addr->addr.in4.sin_addr) : "[undef]"));
	    buf_printf (&out, "%s", separator);
       mutex_unlock_static (L_INET_NTOA);
	  buf_printf (&out, "%d", port);
       if (((flags & PS_SHOW_PORT) || (addr_is_defined && (flags & PS_SHOW_PORT_IF_DEFINED)))
	}
          && port)
      return BSTR (&out);
       {
    }
         if (separator)
  else
	   buf_printf (&out, "%s", separator);
    return "[NULL]";
	 buf_printf (&out, "%d", port);
       }
       }
       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 *
const char *
 Lines 1885-1896    Link Here 
      struct buffer out = alloc_buf_gc (128, gc);
      struct buffer out = alloc_buf_gc (128, gc);
      buf_printf (&out, "%s", print_sockaddr_ex (&act->dest, separator, flags, gc));
      buf_printf (&out, "%s", print_sockaddr_ex (&act->dest, separator, flags, gc));
#if ENABLE_IP_PKTINFO
#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;
	  struct openvpn_sockaddr sa;
	  CLEAR (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));
	  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
#endif
      return BSTR (&out);
      return BSTR (&out);
 Lines 1926-1946    Link Here 
setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const bool flags)
setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct openvpn_sockaddr *addr, const bool flags)
{
{
  char name_buf[256];
  char name_buf[256];
  char buf[128];
  if (flags & SA_IP_PORT)
  switch(addr->addr.sa.sa_family) {
    openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix);
    case AF_INET:
  else
      if (flags & SA_IP_PORT)
    openvpn_snprintf (name_buf, sizeof (name_buf), "%s", name_prefix);
	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);
      mutex_lock_static (L_INET_NTOA);
  setenv_str (es, name_buf, inet_ntoa (addr->sa.sin_addr));
      setenv_str (es, name_buf, inet_ntoa (addr->addr.in4.sin_addr));
  mutex_unlock_static (L_INET_NTOA);
      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);
      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
void
 Lines 1950-1956    Link Here 
    {
    {
      struct openvpn_sockaddr si;
      struct openvpn_sockaddr si;
      CLEAR (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);
      setenv_sockaddr (es, name_prefix, &si, flags);
    }
    }
}
}
 Lines 1971-1986    Link Here 
struct proto_names {
struct proto_names {
  const char *short_form;
  const char *short_form;
  const char *display_form;
  const char *display_form;
  bool	is_dgram;
  bool	is_net;
  sa_family_t proto_af;
};
};
/* Indexed by PROTO_x */
/* Indexed by PROTO_x */
static const struct proto_names proto_names[] = {
static const struct proto_names proto_names[PROTO_N] = {
  {"udp",        "UDPv4"},
  {"proto-uninitialized",        "proto-NONE",0,0, AF_UNSPEC},
  {"tcp-server", "TCPv4_SERVER"},
  {"udp",        "UDPv4",1,1, AF_INET},
  {"tcp-client", "TCPv4_CLIENT"},
  {"tcp-server", "TCPv4_SERVER",0,1, AF_INET},
  {"tcp",        "TCPv4"}
  {"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
int
ascii2proto (const char* proto_name)
ascii2proto (const char* proto_name)
{
{
 Lines 2020-2025    Link Here 
  return BSTR (&out);
  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
 * Given a local proto, return local proto
 * if !remote, or compatible remote proto
 * if !remote, or compatible remote proto
 Lines 2034-2043    Link Here 
  ASSERT (proto >= 0 && proto < PROTO_N);
  ASSERT (proto >= 0 && proto < PROTO_N);
  if (remote)
  if (remote)
    {
    {
      if (proto == PROTO_TCPv4_SERVER)
      switch (proto)
	return PROTO_TCPv4_CLIENT;
      {
      if (proto == PROTO_TCPv4_CLIENT)
	case PROTO_TCPv4_SERVER: return PROTO_TCPv4_CLIENT;
	return PROTO_TCPv4_SERVER;
	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;
  return proto;
}
}
 Lines 2096-2105    Link Here 
#if ENABLE_IP_PKTINFO
#if ENABLE_IP_PKTINFO
#pragma pack(1) /* needed to keep structure size consistent for 32 vs. 64-bit architectures */
#pragma pack(1) /* needed to keep structure size consistent for 32 vs. 64-bit architectures */
struct openvpn_pktinfo
struct openvpn_in4_pktinfo
{
  struct cmsghdr cmsghdr;
  struct in_pktinfo pi;
};
#ifdef USE_PF_INET6
struct openvpn_in6_pktinfo
{
{
  struct cmsghdr cmsghdr;
  struct cmsghdr cmsghdr;
  struct in_pktinfo in_pktinfo;
  struct in6_pktinfo pi6;
};
#endif
union openvpn_pktinfo {
      struct openvpn_in4_pktinfo cmsgpi;
#ifdef USE_PF_INET6
      struct openvpn_in6_pktinfo cmsgpi6;
#endif
};
};
#pragma pack()
#pragma pack()
 Lines 2110-2124    Link Here 
				    struct link_socket_actual *from)
				    struct link_socket_actual *from)
{
{
  struct iovec iov;
  struct iovec iov;
  struct openvpn_pktinfo opi;
  union openvpn_pktinfo opi;
  struct msghdr mesg;
  struct msghdr mesg;
  socklen_t fromlen = sizeof (from->dest.sa);
  socklen_t fromlen = sizeof (from->dest.addr);
  iov.iov_base = BPTR (buf);
  iov.iov_base = BPTR (buf);
  iov.iov_len = maxsize;
  iov.iov_len = maxsize;
  mesg.msg_iov = &iov;
  mesg.msg_iov = &iov;
  mesg.msg_iovlen = 1;
  mesg.msg_iovlen = 1;
  mesg.msg_name = &from->dest.sa;
  mesg.msg_name = &from->dest.addr;
  mesg.msg_namelen = fromlen;
  mesg.msg_namelen = fromlen;
  mesg.msg_control = &opi;
  mesg.msg_control = &opi;
  mesg.msg_controllen = sizeof (opi);
  mesg.msg_controllen = sizeof (opi);
 Lines 2135-2143    Link Here 
	  && cmsg->cmsg_len >= sizeof (opi))
	  && cmsg->cmsg_len >= sizeof (opi))
	{
	{
	  struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
	  struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
	  from->pi.ipi_ifindex = pkti->ipi_ifindex;
	  from->pi.in4.ipi_ifindex = pkti->ipi_ifindex;
	  from->pi.ipi_spec_dst = pkti->ipi_spec_dst;
	  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;
  return fromlen;
}
}
 Lines 2149-2166    Link Here 
			    int maxsize,
			    int maxsize,
			    struct link_socket_actual *from)
			    struct link_socket_actual *from)
{
{
  socklen_t fromlen = sizeof (from->dest.sa);
  socklen_t fromlen = sizeof (from->dest.addr);
  from->dest.sa.sin_addr.s_addr = 0;
  socklen_t expectedlen = af_addr_size(proto_sa_family(sock->info.proto));
  addr_zero_host(&from->dest);
  ASSERT (buf_safe (buf, maxsize));
  ASSERT (buf_safe (buf, maxsize));
#if ENABLE_IP_PKTINFO
#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);
    fromlen = link_socket_read_udp_posix_recvmsg (sock, buf, maxsize, from);
  else
  else
#endif
#endif
    buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,
    buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,
			 (struct sockaddr *) &from->dest.sa, &fromlen);
			 &from->dest.addr.sa, &fromlen);
  if (fromlen != sizeof (from->dest.sa))
  if (buf->len >= 0 && expectedlen && fromlen != expectedlen)
    bad_address_length (fromlen, sizeof (from->dest.sa));
    bad_address_length (fromlen, expectedlen);
  return buf->len;
  return buf->len;
}
}
 Lines 2197-2222    Link Here 
  struct iovec iov;
  struct iovec iov;
  struct msghdr mesg;
  struct msghdr mesg;
  struct cmsghdr *cmsg;
  struct cmsghdr *cmsg;
  struct in_pktinfo *pkti;
  struct openvpn_pktinfo opi;
  iov.iov_base = BPTR (buf);
  iov.iov_base = BPTR (buf);
  iov.iov_len = BLEN (buf);
  iov.iov_len = BLEN (buf);
  mesg.msg_iov = &iov;
  mesg.msg_iov = &iov;
  mesg.msg_iovlen = 1;
  mesg.msg_iovlen = 1;
  mesg.msg_name = &to->dest.sa;
  switch (sock->info.lsa->remote.addr.sa.sa_family)
  mesg.msg_namelen = sizeof (to->dest.sa);
  {
  mesg.msg_control = &opi;
    case AF_INET: {
  mesg.msg_controllen = sizeof (opi);
	  struct openvpn_in4_pktinfo opi;
  mesg.msg_flags = 0;
	  struct in_pktinfo *pkti;
  cmsg = CMSG_FIRSTHDR (&mesg);
	  mesg.msg_name = &to->dest.addr.sa;
  cmsg->cmsg_len = sizeof (opi);
	  mesg.msg_namelen = sizeof (struct sockaddr_in);
  cmsg->cmsg_level = SOL_IP;
	  mesg.msg_control = &opi;
  cmsg->cmsg_type = IP_PKTINFO;
	  mesg.msg_controllen = sizeof (opi);
  pkti = (struct in_pktinfo *) CMSG_DATA (cmsg);
	  mesg.msg_flags = 0;
  pkti->ipi_ifindex = to->pi.ipi_ifindex;
	  cmsg = CMSG_FIRSTHDR (&mesg);
  pkti->ipi_spec_dst = to->pi.ipi_spec_dst;
	  cmsg->cmsg_len = sizeof (opi);
  pkti->ipi_addr.s_addr = 0;
	  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);
  return sendmsg (sock->sd, &mesg, 0);
}
}
 Lines 2360-2366    Link Here 
	{
	{
	  /* set destination address for UDP writes */
	  /* set destination address for UDP writes */
	  sock->writes.addr_defined = true;
	  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);
	  sock->writes.addrlen = sizeof (sock->writes.addr);
	  status = WSASendTo(
	  status = WSASendTo(
 Lines 2516-2525    Link Here 
	{
	{
	  if (io->addrlen != sizeof (io->addr))
	  if (io->addrlen != sizeof (io->addr))
	    bad_address_length (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
      else
	CLEAR (from->dest.sa);
	CLEAR (from->dest.addr.sa);
    }
    }
  
  
  if (buf)
  if (buf)
(-) a/options.c (-15 / +35 lines)
 Lines 73-78    Link Here 
#ifdef ENABLE_PKCS11
#ifdef ENABLE_PKCS11
  " [PKCS11]"
  " [PKCS11]"
#endif
#endif
#ifdef ENABLE_IP_PKTINFO
  " [MH]"
#endif
#ifdef USE_PF_INET6
  " [PF_INET6]"
#endif
  " built on " __DATE__
  " built on " __DATE__
;
;
 Lines 93-98    Link Here 
  "--mode m        : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
  "--mode m        : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n"
  "--proto p       : Use protocol p for communicating with peer.\n"
  "--proto p       : Use protocol p for communicating with peer.\n"
  "                  p = udp (default), tcp-server, or tcp-client\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"
  "--connect-retry n : For --proto tcp-client, number of seconds to wait\n"
  "                    between connection retries (default=%d).\n"
  "                    between connection retries (default=%d).\n"
  "--connect-timeout n : For --proto tcp-client, connection timeout (in seconds).\n"
  "--connect-timeout n : For --proto tcp-client, connection timeout (in seconds).\n"
 Lines 1488-1497    Link Here 
   * Sanity check on TCP mode options
   * Sanity check on TCP mode options
   */
   */
  if (ce->connect_retry_defined && ce->proto != PROTO_TCPv4_CLIENT)
  if (ce->connect_retry_defined && ce->proto != PROTO_TCPv4_CLIENT && ce->proto != PROTO_TCPv6_CLIENT)
    msg (M_USAGE, "--connect-retry doesn't make sense unless also used with --proto tcp-client");
    msg (M_USAGE, "--connect-retry doesn't make sense unless also used with --proto tcp-client");
  if (ce->connect_timeout_defined && ce->proto != PROTO_TCPv4_CLIENT)
  if (ce->connect_timeout_defined && ce->proto != PROTO_TCPv4_CLIENT && ce->proto != PROTO_TCPv6_CLIENT)
    msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with --proto tcp-client");
    msg (M_USAGE, "--connect-timeout doesn't make sense unless also used with --proto tcp-client");
  /*
  /*
 Lines 1501-1507    Link Here 
    msg (M_USAGE, "only one of --tun-mtu or --link-mtu may be defined (note that --ifconfig implies --link-mtu %d)", LINK_MTU_DEFAULT);
    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
#ifdef ENABLE_OCC
  if (ce->proto != PROTO_UDPv4 && options->mtu_test)
  if (!proto_is_udp(ce->proto) && options->mtu_test)
    msg (M_USAGE, "--mtu-test only makes sense with --proto udp");
    msg (M_USAGE, "--mtu-test only makes sense with --proto udp");
#endif
#endif
 Lines 1514-1520    Link Here 
   * Sanity check on --local, --remote, and --ifconfig
   * Sanity check on --local, --remote, and --ifconfig
   */
   */
  if (string_defined_equal (ce->local, ce->remote)
  if (proto_is_net(ce->proto)
      && string_defined_equal (ce->local, ce->remote)
      && ce->local_port == ce->remote_port)
      && ce->local_port == ce->remote_port)
    msg (M_USAGE, "--remote and --local addresses are the same");
    msg (M_USAGE, "--remote and --local addresses are the same");
  
  
 Lines 1575-1590    Link Here 
   */
   */
#ifdef ENABLE_FRAGMENT
#ifdef ENABLE_FRAGMENT
  if (ce->proto != PROTO_UDPv4 && options->fragment)
  if (!proto_is_udp(ce->proto) && options->fragment)
    msg (M_USAGE, "--fragment can only be used with --proto udp");
    msg (M_USAGE, "--fragment can only be used with --proto udp");
#endif
#endif
#ifdef ENABLE_OCC
#ifdef ENABLE_OCC
  if (ce->proto != PROTO_UDPv4 && options->explicit_exit_notification)
  if (!proto_is_udp(ce->proto) && options->explicit_exit_notification)
    msg (M_USAGE, "--explicit-exit-notify can only be used with --proto udp");
    msg (M_USAGE, "--explicit-exit-notify can only be used with --proto udp");
#endif
#endif
  if (!ce->remote && ce->proto == PROTO_TCPv4_CLIENT)
  if (!ce->remote && (ce->proto == PROTO_TCPv4_CLIENT||ce->proto == PROTO_TCPv6_CLIENT))
    msg (M_USAGE, "--remote MUST be used in TCP Client mode");
    msg (M_USAGE, "--remote MUST be used in TCP Client mode");
#ifdef ENABLE_HTTP_PROXY
#ifdef ENABLE_HTTP_PROXY
 Lines 1602-1608    Link Here 
    msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode");
    msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode");
#endif
#endif
  if (ce->proto == PROTO_TCPv4_SERVER && connection_list_defined (options))
  if ((ce->proto == PROTO_TCPv4_SERVER||ce->proto == PROTO_TCPv6_SERVER)
         && connection_list_defined (options))
    msg (M_USAGE, "TCP server mode allows at most one --remote address");
    msg (M_USAGE, "TCP server mode allows at most one --remote address");
#if P2MP_SERVER
#if P2MP_SERVER
 Lines 1616-1622    Link Here 
	msg (M_USAGE, "--mode server only works with --dev tun or --dev tap");
	msg (M_USAGE, "--mode server only works with --dev tun or --dev tap");
      if (options->pull)
      if (options->pull)
	msg (M_USAGE, "--pull cannot be used with --mode server");
	msg (M_USAGE, "--pull cannot be used with --mode server");
      if (!(ce->proto == PROTO_UDPv4 || ce->proto == PROTO_TCPv4_SERVER))
      if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCPv4_SERVER || ce->proto == PROTO_TCPv6_SERVER))
	msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server");
	msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server");
#if PORT_SHARE
#if PORT_SHARE
      if ((options->port_share_host || options->port_share_port) && ce->proto != PROTO_TCPv4_SERVER)
      if ((options->port_share_host || options->port_share_port) && ce->proto != PROTO_TCPv4_SERVER)
 Lines 1648-1656    Link Here 
	msg (M_USAGE, "--inetd cannot be used with --mode server");
	msg (M_USAGE, "--inetd cannot be used with --mode server");
      if (options->ipchange)
      if (options->ipchange)
	msg (M_USAGE, "--ipchange cannot be used with --mode server (use --client-connect instead)");
	msg (M_USAGE, "--ipchange cannot be used with --mode server (use --client-connect instead)");
      if (!(ce->proto == PROTO_UDPv4 || ce->proto == PROTO_TCPv4_SERVER))
      if (!(proto_is_dgram(ce->proto) || ce->proto == PROTO_TCPv4_SERVER || ce->proto == PROTO_TCPv6_SERVER ))
	msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server");
        msg (M_USAGE, "--mode server currently only supports --proto udp or --proto tcp-server (also udp6/tcp6)");
      if (ce->proto != PROTO_UDPv4 && (options->cf_max || options->cf_per))
      if (!proto_is_udp(ce->proto) && (options->cf_max || options->cf_per))
	msg (M_USAGE, "--connect-freq only works with --mode server --proto udp.  Try --max-clients instead.");
	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)
      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");
	msg (M_USAGE, "The third parameter to --ifconfig-pool (netmask) is only valid in --dev tap mode");
 Lines 1730-1736    Link Here 
  /*
  /*
   * Check consistency of replay options
   * Check consistency of replay options
   */
   */
  if ((ce->proto != PROTO_UDPv4)
  if ((!proto_is_udp(ce->proto))
      && (options->replay_window != defaults.replay_window
      && (options->replay_window != defaults.replay_window
	  || options->replay_time != defaults.replay_time))
	  || options->replay_time != defaults.replay_time))
    msg (M_USAGE, "--replay-window only makes sense with --proto udp");
    msg (M_USAGE, "--replay-window only makes sense with --proto udp");
 Lines 1892-1897    Link Here 
    {
    {
      if (ce->proto == PROTO_TCPv4)
      if (ce->proto == PROTO_TCPv4)
	ce->proto = PROTO_TCPv4_SERVER;
	ce->proto = PROTO_TCPv4_SERVER;
#ifdef USE_PF_INET6
      else if (ce->proto == PROTO_TCPv6)
        ce->proto = PROTO_TCPv6_SERVER;
#endif
    }
    }
#endif
#endif
#if P2MP
#if P2MP
 Lines 1899-1908    Link Here 
    {
    {
      if (ce->proto == PROTO_TCPv4)
      if (ce->proto == PROTO_TCPv4)
	ce->proto = PROTO_TCPv4_CLIENT;
	ce->proto = PROTO_TCPv4_CLIENT;
    }
#ifdef USE_PF_INET6
      else if (ce->proto == PROTO_TCPv6)
        ce->proto = PROTO_TCPv6_CLIENT;
#endif
}
#endif
#endif
  if (ce->proto == PROTO_TCPv4_CLIENT && !ce->local && !ce->local_port_defined && !ce->bind_defined)
  if ((ce->proto == PROTO_TCPv4_CLIENT||ce->proto == PROTO_TCPv6_CLIENT) && !ce->local && !ce->local_port_defined && !ce->bind_defined)
    ce->bind_local = false;
    ce->bind_local = false;
#ifdef ENABLE_SOCKS
#ifdef ENABLE_SOCKS