mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-06-11 09:50:26 -04:00
* rebased openvpn-2.1_rc1b.jjo.20061206.d.patch
* passes {udp,tcp}x{v4,v6} loopback tests
* passes {udp,tcp}x{v6} remote tests
This commit is contained in:
parent
badba714db
commit
8335caf929
13 changed files with 855 additions and 189 deletions
13
buffer.c
13
buffer.c
|
|
@ -214,6 +214,19 @@ buf_printf (struct buffer *buf, const char *format, ...)
|
|||
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,
|
||||
* that don't guarantee null termination for size > 0.
|
||||
|
|
|
|||
16
configure.ac
16
configure.ac
|
|
@ -146,6 +146,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"],
|
||||
|
|
@ -566,6 +572,16 @@ LDFLAGS="$LDFLAGS -Wl,--fatal-warnings"
|
|||
AC_CHECK_FUNC(epoll_create, AC_DEFINE(HAVE_EPOLL_CREATE, 1, [epoll_create function is defined]))
|
||||
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
|
||||
|
|
|
|||
36
init.c
36
init.c
|
|
@ -96,7 +96,7 @@ update_options_ce_post (struct options *options)
|
|||
*/
|
||||
if (options->pull
|
||||
&& options->ping_rec_timeout_action == PING_UNDEF
|
||||
&& options->ce.proto == PROTO_UDPv4)
|
||||
&& proto_is_dgram(options->ce.proto))
|
||||
{
|
||||
options->ping_rec_timeout = PRE_PULL_INITIAL_PING_RESTART;
|
||||
options->ping_rec_timeout_action = PING_RESTART;
|
||||
|
|
@ -1150,7 +1150,7 @@ initialization_sequence_completed (struct context *c, const unsigned int flags)
|
|||
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,
|
||||
|
|
@ -1569,7 +1569,7 @@ do_deferred_options (struct context *c, const unsigned int found)
|
|||
#ifdef ENABLE_OCC
|
||||
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");
|
||||
c->options.explicit_exit_notification = 0;
|
||||
|
|
@ -1664,13 +1664,22 @@ socket_restart_pause (struct context *c)
|
|||
switch (c->options.ce.proto)
|
||||
{
|
||||
case PROTO_UDPv4:
|
||||
#ifdef USE_PF_INET6
|
||||
case PROTO_UDPv6:
|
||||
#endif
|
||||
if (proxy)
|
||||
sec = c->options.ce.connect_retry_seconds;
|
||||
break;
|
||||
case PROTO_TCPv4_SERVER:
|
||||
#ifdef USE_PF_INET6
|
||||
case PROTO_TCPv6_SERVER:
|
||||
#endif
|
||||
sec = 1;
|
||||
break;
|
||||
case PROTO_TCPv4_CLIENT:
|
||||
#ifdef USE_PF_INET6
|
||||
case PROTO_TCPv6_CLIENT:
|
||||
#endif
|
||||
sec = c->options.ce.connect_retry_seconds;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2810,7 +2819,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.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");
|
||||
else
|
||||
{
|
||||
|
|
@ -3086,7 +3095,11 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
|
|||
/* link_socket_mode allows CM_CHILD_TCP
|
||||
instances to inherit acceptable fds
|
||||
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)
|
||||
#endif
|
||||
{
|
||||
if (c->mode == CM_TOP)
|
||||
link_socket_mode = LS_MODE_TCP_LISTEN;
|
||||
|
|
@ -3361,17 +3374,8 @@ inherit_context_child (struct context *dest,
|
|||
{
|
||||
CLEAR (*dest);
|
||||
|
||||
switch (src->options.ce.proto)
|
||||
{
|
||||
case PROTO_UDPv4:
|
||||
dest->mode = CM_CHILD_UDP;
|
||||
break;
|
||||
case PROTO_TCPv4_SERVER:
|
||||
dest->mode = CM_CHILD_TCP;
|
||||
break;
|
||||
default:
|
||||
ASSERT (0);
|
||||
}
|
||||
/* proto_is_dgram will ASSERT(0) if proto is invalid */
|
||||
dest->mode = proto_is_dgram(src->options.ce.proto)? CM_CHILD_UDP : CM_CHILD_TCP;
|
||||
|
||||
dest->gc = gc_new ();
|
||||
|
||||
|
|
@ -3477,7 +3481,7 @@ inherit_context_top (struct context *dest,
|
|||
dest->c2.es_owned = false;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
10
manage.c
10
manage.c
|
|
@ -1999,9 +1999,9 @@ man_settings_init (struct man_settings *ms,
|
|||
/*
|
||||
* 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
|
||||
|
|
@ -2013,7 +2013,7 @@ man_settings_init (struct man_settings *ms,
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2472,7 +2472,7 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i
|
|||
&& 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
60
mroute.c
60
mroute.c
|
|
@ -226,25 +226,47 @@ bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -337,7 +359,37 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
|
|||
}
|
||||
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");
|
||||
|
|
|
|||
1
mtcp.c
1
mtcp.c
|
|
@ -150,6 +150,7 @@ multi_tcp_instance_specific_init (struct multi_context *m, struct multi_instance
|
|||
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");
|
||||
|
|
|
|||
17
multi.c
17
multi.c
|
|
@ -1058,8 +1058,8 @@ multi_learn_in_addr_t (struct multi_context *m,
|
|||
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)
|
||||
|
|
@ -2496,9 +2496,9 @@ management_callback_kill_by_addr (void *arg, const in_addr_t addr, const int por
|
|||
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);
|
||||
|
|
@ -2675,6 +2675,12 @@ tunnel_server (struct context *top)
|
|||
{
|
||||
ASSERT (top->options.mode == MODE_SERVER);
|
||||
|
||||
#ifdef USE_PF_INET6
|
||||
if (proto_is_dgram(top->options.ce.proto))
|
||||
tunnel_server_udp(top);
|
||||
else
|
||||
tunnel_server_tcp(top);
|
||||
#else
|
||||
switch (top->options.ce.proto) {
|
||||
case PROTO_UDPv4:
|
||||
tunnel_server_udp (top);
|
||||
|
|
@ -2685,6 +2691,7 @@ tunnel_server (struct context *top)
|
|||
default:
|
||||
ASSERT (0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
2
occ.c
2
occ.c
|
|
@ -369,7 +369,7 @@ process_received_occ_msg (struct context *c)
|
|||
c->c2.max_send_size_remote,
|
||||
c->c2.max_recv_size_local);
|
||||
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_recv_size_remote < c->c2.max_send_size_local
|
||||
|| c->c2.max_recv_size_local < c->c2.max_send_size_remote))
|
||||
|
|
|
|||
41
options.c
41
options.c
|
|
@ -79,6 +79,11 @@ const char title_string[] =
|
|||
#endif
|
||||
#ifdef ENABLE_EUREPHIA
|
||||
" [eurephia]"
|
||||
#ifdef ENABLE_IP_PKTINFO
|
||||
" [MH]"
|
||||
#endif
|
||||
#ifdef USE_PF_INET6
|
||||
" [PF_INET6]"
|
||||
#endif
|
||||
" built on " __DATE__
|
||||
;
|
||||
|
|
@ -102,6 +107,9 @@ static const char usage_message[] =
|
|||
"--proto p : Use protocol p for communicating with peer.\n"
|
||||
" p = udp (default), tcp-server, or tcp-client\n"
|
||||
"--proto-force p : only consider protocol p in list of connection profiles.\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"
|
||||
|
|
@ -1695,10 +1703,10 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
* 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");
|
||||
|
||||
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");
|
||||
|
||||
/*
|
||||
|
|
@ -1708,7 +1716,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
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 (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");
|
||||
#endif
|
||||
|
||||
|
|
@ -1721,7 +1729,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
* 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)
|
||||
msg (M_USAGE, "--remote and --local addresses are the same");
|
||||
|
||||
|
|
@ -1786,16 +1795,16 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
*/
|
||||
|
||||
#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");
|
||||
#endif
|
||||
|
||||
#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");
|
||||
#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");
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
|
@ -1813,7 +1822,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
msg (M_USAGE, "--socks-proxy can not be used in TCP Server mode");
|
||||
#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");
|
||||
|
||||
#if P2MP_SERVER
|
||||
|
|
@ -1827,10 +1837,11 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
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 (!(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");
|
||||
#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 && ce->proto != PROTO_TCPv6_SERVER))
|
||||
msg (M_USAGE, "--port-share only works in TCP server mode (--proto tcp-server)");
|
||||
#endif
|
||||
if (!options->tls_server)
|
||||
|
|
@ -1859,9 +1870,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
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 (!(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");
|
||||
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.");
|
||||
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");
|
||||
|
|
@ -1954,7 +1965,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
|
|||
/*
|
||||
* Check consistency of replay options
|
||||
*/
|
||||
if ((ce->proto != PROTO_UDPv4)
|
||||
if ((!proto_is_udp(ce->proto))
|
||||
&& (options->replay_window != defaults.replay_window
|
||||
|| options->replay_time != defaults.replay_time))
|
||||
msg (M_USAGE, "--replay-window only makes sense with --proto udp");
|
||||
|
|
@ -2127,6 +2138,10 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce)
|
|||
{
|
||||
if (ce->proto == PROTO_TCPv4)
|
||||
ce->proto = PROTO_TCPv4_CLIENT;
|
||||
#ifdef USE_PF_INET6
|
||||
else if (ce->proto == PROTO_TCPv6)
|
||||
ce->proto = PROTO_TCPv6_CLIENT;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
6
ps.c
6
ps.c
|
|
@ -320,9 +320,9 @@ sock_addr_set (struct openvpn_sockaddr *osaddr,
|
|||
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
|
||||
|
|
|
|||
591
socket.c
591
socket.c
|
|
@ -36,10 +36,16 @@
|
|||
#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
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -410,6 +416,8 @@ update_remote (const char* host,
|
|||
bool *changed,
|
||||
const unsigned int sockflags)
|
||||
{
|
||||
switch(addr->addr.sa.sa_family) {
|
||||
case AF_INET:
|
||||
if (host && addr)
|
||||
{
|
||||
const in_addr_t new_addr = getaddr (
|
||||
|
|
@ -418,12 +426,39 @@ update_remote (const char* host,
|
|||
1,
|
||||
NULL,
|
||||
NULL);
|
||||
if (new_addr && addr->sa.sin_addr.s_addr != new_addr)
|
||||
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: /* TODO(jjo): should adapt getaddr() + sf2gaf() 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
|
||||
|
|
@ -616,6 +651,44 @@ create_socket_udp (const unsigned int flags)
|
|||
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)
|
||||
{
|
||||
|
|
@ -634,6 +707,17 @@ create_socket (struct link_socket *sock)
|
|||
{
|
||||
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);
|
||||
|
|
@ -671,7 +755,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);
|
||||
|
|
@ -679,7 +768,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");
|
||||
|
|
@ -692,7 +781,7 @@ socket_do_accept (socket_descriptor_t sd,
|
|||
#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 */
|
||||
|
|
@ -708,7 +797,8 @@ socket_do_accept (socket_descriptor_t 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);
|
||||
openvpn_close_socket (new_sd);
|
||||
|
|
@ -809,7 +899,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",
|
||||
|
|
@ -830,7 +920,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)
|
||||
|
|
@ -1030,17 +1120,44 @@ resolve_bind_local (struct link_socket *sock)
|
|||
|
||||
/* 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)
|
||||
|
|
@ -1068,8 +1185,11 @@ resolve_remote (struct link_socket *sock,
|
|||
/* 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)
|
||||
{
|
||||
|
|
@ -1112,7 +1232,7 @@ resolve_remote (struct link_socket *sock,
|
|||
ASSERT (0);
|
||||
}
|
||||
|
||||
sock->info.lsa->remote.sa.sin_addr.s_addr = getaddr (
|
||||
sock->info.lsa->remote.addr.in4.sin_addr.s_addr = getaddr (
|
||||
flags,
|
||||
sock->remote_host,
|
||||
retry,
|
||||
|
|
@ -1139,7 +1259,29 @@ resolve_remote (struct link_socket *sock,
|
|||
}
|
||||
}
|
||||
|
||||
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: /* TODO(jjo): 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? */
|
||||
|
|
@ -1384,7 +1526,11 @@ link_socket_init_phase2 (struct link_socket *sock,
|
|||
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)
|
||||
{
|
||||
|
|
@ -1419,7 +1565,11 @@ link_socket_init_phase2 (struct link_socket *sock,
|
|||
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
|
||||
|
|
@ -1506,8 +1656,8 @@ link_socket_init_phase2 (struct link_socket *sock,
|
|||
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);
|
||||
|
||||
|
|
@ -1522,7 +1672,7 @@ link_socket_init_phase2 (struct link_socket *sock,
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1708,13 +1858,20 @@ link_socket_bad_incoming_addr (struct buffer *buf,
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1729,10 +1886,25 @@ link_socket_current_remote (const struct link_socket_info *info)
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -1959,26 +2131,58 @@ print_sockaddr_ex (const struct openvpn_sockaddr *addr,
|
|||
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);
|
||||
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_DONT_SHOW_ADDR))
|
||||
buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sa.sin_addr) : "[undef]"));
|
||||
|
||||
if (((flags & PS_SHOW_PORT) || (addr_defined (addr) && (flags & PS_SHOW_PORT_IF_DEFINED)))
|
||||
&& port)
|
||||
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 *
|
||||
|
|
@ -1998,12 +2202,38 @@ print_link_socket_actual_ex (const struct link_socket_actual *act,
|
|||
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);
|
||||
|
|
@ -2037,19 +2267,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);
|
||||
|
||||
setenv_str (es, name_buf, inet_ntoa (addr->sa.sin_addr));
|
||||
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
|
||||
|
|
@ -2059,7 +2307,8 @@ setenv_in_addr_t (struct env_set *es, const char *name_prefix, in_addr_t addr, c
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -2080,16 +2329,63 @@ setenv_link_socket_actual (struct env_set *es,
|
|||
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)
|
||||
{
|
||||
|
|
@ -2129,6 +2425,38 @@ 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_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";
|
||||
}
|
||||
return "AF_UNSPEC";
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a local proto, return local proto
|
||||
* if !remote, or compatible remote proto
|
||||
|
|
@ -2143,10 +2471,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;
|
||||
}
|
||||
|
|
@ -2205,10 +2538,24 @@ link_socket_read_tcp (struct link_socket *sock,
|
|||
#if ENABLE_IP_PKTINFO
|
||||
|
||||
#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 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
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
|
|
@ -2219,15 +2566,15 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock,
|
|||
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);
|
||||
|
|
@ -2244,9 +2591,21 @@ link_socket_read_udp_posix_recvmsg (struct link_socket *sock,
|
|||
&& 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;
|
||||
}
|
||||
|
|
@ -2258,18 +2617,20 @@ link_socket_read_udp_posix (struct link_socket *sock,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2306,26 +2667,52 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
@ -2469,7 +2856,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct li
|
|||
{
|
||||
/* 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(
|
||||
|
|
@ -2625,10 +3012,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)
|
||||
|
|
|
|||
233
socket.h
233
socket.h
|
|
@ -70,7 +70,13 @@ typedef uint16_t packet_size_type;
|
|||
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 */
|
||||
|
|
@ -79,7 +85,12 @@ struct link_socket_actual
|
|||
/*int dummy;*/ /* 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
|
||||
};
|
||||
|
||||
|
|
@ -410,6 +421,14 @@ socket_descriptor_t create_socket_tcp (void);
|
|||
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);
|
||||
|
||||
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
|
||||
|
|
@ -472,23 +491,49 @@ in_addr_t getaddr_multi (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[];
|
||||
|
||||
|
|
@ -518,7 +563,7 @@ is_proto_tcp(const int p)
|
|||
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
|
||||
|
|
@ -533,7 +578,30 @@ link_socket_connection_oriented (const struct link_socket *sock)
|
|||
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
|
||||
|
|
@ -545,20 +613,50 @@ link_socket_actual_defined (const struct link_socket_actual *act)
|
|||
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
|
||||
|
|
@ -571,6 +669,74 @@ addr_match_proto (const struct openvpn_sockaddr *a1,
|
|||
: 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)
|
||||
{
|
||||
|
|
@ -627,14 +793,18 @@ link_socket_verify_incoming_addr (struct buffer *buf,
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -740,7 +910,7 @@ link_socket_read (struct link_socket *sock,
|
|||
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;
|
||||
|
||||
|
|
@ -751,10 +921,10 @@ link_socket_read (struct link_socket *sock,
|
|||
#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
|
||||
|
|
@ -809,13 +979,14 @@ link_socket_write_udp_posix (struct link_socket *sock,
|
|||
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
|
||||
|
|
@ -846,11 +1017,11 @@ link_socket_write (struct link_socket *sock,
|
|||
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);
|
||||
}
|
||||
|
|
|
|||
18
socks.c
18
socks.c
|
|
@ -299,9 +299,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)
|
||||
|
|
@ -388,8 +388,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));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -507,8 +507,8 @@ socks_process_incoming_udp (struct buffer *buf,
|
|||
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;
|
||||
|
||||
|
|
@ -540,8 +540,8 @@ socks_process_outgoing_udp (struct buffer *buf,
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue