from the file specified by --ca regardless if the pkcs12 file
contains a CA cert or not (Mathias Sundman).
* Merged --capath patch (Thomas Noel).
-* NOTE TO PACKAGE MAINTAINERS: Moved "plugin"
- directory to "plugins". This is
- to work around a strange problem with the
- "make dist" target in the automake-generated
- makefile, where the target tries to do a
- rather bogus "gcc -g -O2 -I. plugin.c -o plugin".
+* Merged --multihome patch.
+* NOTE TO PACKAGE MAINTAINERS: Moved "plugin" directory to "plugins".
+ This is to work around a strange problem with the "make dist"
+ target in the automake-generated makefile, where the target tries to
+ do a rather bogus "gcc -g -O2 -I. plugin.c -o plugin".
2005.10.13 -- Version 2.1-beta2
[FRAGMENT="yes"]
)
+AC_ARG_ENABLE(multihome,
+ [ --disable-multihome Disable multi-homed UDP server support (--multihome)],
+ [MULTIHOME="$enableval"],
+ [MULTIHOME="yes"]
+)
+
AC_ARG_ENABLE(debug,
[ --disable-debug Disable debugging support (disable gremlin and verb 7+ messages)],
[DEBUG="$enableval"],
[AC_DEFINE(HAVE_CMSGHDR, 1, [struct cmsghdr needed for extended socket error support])],
[],
[#include "syshead.h"])
+AC_CHECK_TYPE(
+ [struct in_pktinfo],
+ [AC_DEFINE(HAVE_IN_PKTINFO, 1, [struct in_pktinfo needed for IP_PKTINFO support])],
+ [],
+ [#include "syshead.h"])
AC_CHECK_SIZEOF(unsigned int)
AC_CHECK_SIZEOF(unsigned long)
getpass strerror syslog openlog mlockall getgrnam setgid dnl
setgroups stat flock readv writev setsockopt getsockopt dnl
setsid chdir gettimeofday putenv getpeername unlink dnl
- poll chsize ftruncate)
+ poll chsize ftruncate sendmsg recvmsg)
AC_CACHE_SAVE
dnl Required library functions
AC_DEFINE(ENABLE_HTTP_PROXY, 1, [Enable HTTP proxy support])
fi
+dnl compile --multihome option
+if test "$MULTIHOME" = "yes"; then
+ AC_DEFINE(ENABLE_MULTIHOME, 1, [Enable multi-homed UDP server capability])
+fi
+
dnl enable debugging
if test "$DEBUG" = "yes"; then
AC_DEFINE(ENABLE_DEBUG, 1, [Enable debugging support])
static inline void
socks_preprocess_outgoing_link (struct context *c,
- struct sockaddr_in **to_addr,
+ struct link_socket_actual **to_addr,
int *size_delta)
{
if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDPv4)
{
- *size_delta += socks_process_outgoing_udp (&c->c2.to_link, &c->c2.to_link_addr);
+ *size_delta += socks_process_outgoing_udp (&c->c2.to_link, c->c2.to_link_addr);
*to_addr = &c->c2.link_socket->socks_relay;
}
}
c->c2.buf = c->c2.buffers->read_link_buf;
ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM_ADJ (&c->c2.frame, FRAME_HEADROOM_MARKER_READ_LINK)));
- status = link_socket_read (c->c2.link_socket, &c->c2.buf, MAX_RW_SIZE_LINK (&c->c2.frame), &c->c2.from);
+ status = link_socket_read (c->c2.link_socket,
+ &c->c2.buf,
+ MAX_RW_SIZE_LINK (&c->c2.frame),
+ &c->c2.from);
if (socket_connection_reset (c->c2.link_socket, status))
{
msg (D_LINK_RW, "%s READ [%d] from %s: %s",
proto2ascii (lsi->proto, true),
BLEN (&c->c2.buf),
- print_sockaddr (&c->c2.from, &gc),
+ print_link_socket_actual (&c->c2.from, &gc),
PROTO_DUMP (&c->c2.buf, &gc));
/*
* packet to remote over the TCP/UDP port.
*/
int size = 0;
- ASSERT (addr_defined (&c->c2.to_link_addr));
+ ASSERT (link_socket_actual_defined (c->c2.to_link_addr));
#ifdef ENABLE_DEBUG
/* In gremlin-test mode, we may choose to drop this packet */
msg (D_LINK_RW, "%s WRITE [%d] to %s: %s",
proto2ascii (c->c2.link_socket->info.proto, true),
BLEN (&c->c2.to_link),
- print_sockaddr (&c->c2.to_link_addr, &gc),
+ print_link_socket_actual (c->c2.to_link_addr, &gc),
PROTO_DUMP (&c->c2.to_link, &gc));
/* Packet send complexified by possible Socks5 usage */
{
- struct sockaddr_in *to_addr = &c->c2.to_link_addr;
+ struct link_socket_actual *to_addr = c->c2.to_link_addr;
#ifdef ENABLE_SOCKS
int size_delta = 0;
#endif
socks_preprocess_outgoing_link (c, &to_addr, &size_delta);
#endif
/* Send packet */
- size = link_socket_write (c->c2.link_socket, &c->c2.to_link, to_addr);
+ size = link_socket_write (c->c2.link_socket,
+ &c->c2.to_link,
+ to_addr);
#ifdef ENABLE_SOCKS
/* Undo effect of prepend */
if (size != BLEN (&c->c2.to_link))
msg (D_LINK_ERRORS,
"TCP/UDP packet was truncated/expanded on write to %s (tried=%d,actual=%d)",
- print_sockaddr (&c->c2.to_link_addr, &gc),
+ print_link_socket_actual (c->c2.to_link_addr, &gc),
BLEN (&c->c2.to_link),
size);
}
{
if (c->c2.to_link.len > 0)
msg (D_LINK_ERRORS, "TCP/UDP packet too large on write to %s (tried=%d,max=%d)",
- print_sockaddr (&c->c2.to_link_addr, &gc),
+ print_link_socket_actual (c->c2.to_link_addr, &gc),
c->c2.to_link.len,
EXPANDED_SIZE (&c->c2.frame));
}
man_accept (struct management *man)
{
struct gc_arena gc = gc_new ();
+ struct link_socket_actual act;
/*
* Accept the TCP client.
*/
- man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &man->connection.remote, false);
+ man->connection.sd_cli = socket_do_accept (man->connection.sd_top, &act, false);
if (socket_defined (man->connection.sd_cli))
{
+ man->connection.remote = act.dest;
+
if (socket_defined (man->connection.sd_top))
{
#ifdef WIN32
/*
* Initialize socket address
*/
- ms->local.sin_family = AF_INET;
- ms->local.sin_addr.s_addr = 0;
- ms->local.sin_port = htons (port);
+ ms->local.sa.sin_family = AF_INET;
+ ms->local.sa.sin_addr.s_addr = 0;
+ ms->local.sa.sin_port = htons (port);
/*
* Run management over tunnel, or
}
else
{
- ms->local.sin_addr.s_addr = getaddr
+ ms->local.sa.sin_addr.s_addr = getaddr
(GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
}
&& man->connection.state == MS_INITIAL)
{
/* listen on our local TUN/TAP IP address */
- man->settings.local.sin_addr.s_addr = htonl (tun_local_ip);
+ man->settings.local.sa.sin_addr.s_addr = htonl (tun_local_ip);
man_connection_init (man);
}
struct man_settings {
bool defined;
- struct sockaddr_in local;
+ struct openvpn_sockaddr local;
bool up_query_passwords;
bool management_over_tunnel;
struct user_pass up;
socket_descriptor_t sd_top;
socket_descriptor_t sd_cli;
- struct sockaddr_in remote;
+ struct openvpn_sockaddr remote;
#ifdef WIN32
struct net_event_win32 ne32;
}
/*
- * Translate a struct sockaddr_in (saddr)
+ * Translate a struct openvpn_sockaddr (osaddr)
* to a struct mroute_addr (addr).
*/
-bool
-mroute_extract_sockaddr_in (struct mroute_addr *addr, const struct sockaddr_in *saddr, bool use_port)
+bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
+ const struct openvpn_sockaddr *osaddr,
+ bool use_port)
{
- if (saddr->sin_family == AF_INET)
+ if (osaddr->sa.sin_family == AF_INET)
{
if (use_port)
{
addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
addr->netbits = 0;
addr->len = 6;
- memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
- memcpy (addr->addr + 4, &saddr->sin_port, 2);
+ memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
+ memcpy (addr->addr + 4, &osaddr->sa.sin_port, 2);
}
else
{
addr->type = MR_ADDR_IPV4;
addr->netbits = 0;
addr->len = 4;
- memcpy (addr->addr, &saddr->sin_addr.s_addr, 4);
+ memcpy (addr->addr, &osaddr->sa.sin_addr.s_addr, 4);
}
return true;
}
struct buffer *buf,
int tunnel_type);
-bool mroute_extract_sockaddr_in (struct mroute_addr *addr,
- const struct sockaddr_in *saddr,
- bool use_port);
+struct openvpn_sockaddr;
+
+bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
+ const struct openvpn_sockaddr *osaddr,
+ bool use_port);
bool mroute_learnable_address (const struct mroute_addr *addr);
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);
- if (!mroute_extract_sockaddr_in (&mi->real, &mi->context.c2.link_socket->info.lsa->actual, 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");
return false;
struct multi_instance *mi = NULL;
struct hash *hash = m->hash;
- if (mroute_extract_sockaddr_in (&real, &m->top.c2.from, true))
+ if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
{
struct hash_element *he;
const uint32_t hv = hash_value (hash, &real);
in_addr_t a,
int netbits) /* -1 if host route, otherwise # of network bits in address */
{
- struct sockaddr_in remote_si;
+ struct openvpn_sockaddr remote_si;
struct mroute_addr addr;
CLEAR (remote_si);
- remote_si.sin_family = AF_INET;
- remote_si.sin_addr.s_addr = htonl (a);
- ASSERT (mroute_extract_sockaddr_in (&addr, &remote_si, false));
+ remote_si.sa.sin_family = AF_INET;
+ remote_si.sa.sin_addr.s_addr = htonl (a);
+ ASSERT (mroute_extract_openvpn_sockaddr (&addr, &remote_si, false));
if (netbits >= 0)
{
struct multi_context *m = (struct multi_context *) arg;
struct hash_iterator hi;
struct hash_element *he;
- struct sockaddr_in saddr;
+ struct openvpn_sockaddr saddr;
struct mroute_addr maddr;
int count = 0;
CLEAR (saddr);
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = htonl (addr);
- saddr.sin_port = htons (port);
- if (mroute_extract_sockaddr_in (&maddr, &saddr, true))
+ saddr.sa.sin_family = AF_INET;
+ saddr.sa.sin_addr.s_addr = htonl (addr);
+ saddr.sa.sin_port = htons (port);
+ if (mroute_extract_openvpn_sockaddr (&maddr, &saddr, true))
{
hash_iterator_init (m->iter, &hi, true);
while ((he = hash_iterator_next (&hi)))
struct link_socket_info *link_socket_info;
const struct link_socket *accept_from; /* possibly do accept() on a parent link_socket */
- struct sockaddr_in to_link_addr; /* IP address of remote */
- struct sockaddr_in from; /* address of incoming datagram */
+ struct link_socket_actual *to_link_addr; /* IP address of remote */
+ struct link_socket_actual from; /* address of incoming datagram */
/* MTU frame parameters */
struct frame frame;
"--ping-timer-rem: Run the --ping-exit/--ping-restart timer only if we have a\n"
" remote address.\n"
"--ping n : Ping remote once every n seconds over TCP/UDP port.\n"
+#if ENABLE_IP_PKTINFO
+ "--multihome : Configure a multi-homed UDP server.\n"
+#endif
"--fast-io : (experimental) Optimize TUN/TAP/UDP writes.\n"
"--remap-usr1 s : On SIGUSR1 signals, remap signal (s='SIGHUP' or 'SIGTERM').\n"
"--persist-tun : Keep tun/tap device open across SIGUSR1 or --ping-restart.\n"
VERIFY_PERMISSION (OPT_P_GENERAL);
options->mlock = true;
}
+#if ENABLE_IP_PKTINFO
+ else if (streq (p[0], "multihome"))
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ options->sockflags |= SF_USE_IP_PKTINFO;
+ }
+#endif
else if (streq (p[0], "verb") && p[1])
{
++i;
&& event_timeout_trigger (&c->c2.ping_rec_interval,
&c->c2.timeval,
(!c->options.ping_timer_remote
- || addr_defined (&c->c1.link_socket_addr.actual))
+ || link_socket_actual_defined (&c->c1.link_socket_addr.actual))
? ETT_DEFAULT : 15))
check_ping_restart_dowork (c);
}
static void
update_remote (const char* host,
- struct sockaddr_in *addr,
+ struct openvpn_sockaddr *addr,
bool *changed)
{
if (host && addr)
1,
NULL,
NULL);
- if (new_addr && addr->sin_addr.s_addr != new_addr)
+ if (new_addr && addr->sa.sin_addr.s_addr != new_addr)
{
- addr->sin_addr.s_addr = new_addr;
+ addr->sa.sin_addr.s_addr = new_addr;
*changed = true;
}
}
}
static socket_descriptor_t
-create_socket_udp (void)
+create_socket_udp (const unsigned int flags)
{
socket_descriptor_t sd;
if ((sd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
msg (M_SOCKERR, "UDP: Cannot create UDP socket");
+#if ENABLE_IP_PKTINFO
+ else if (flags & SF_USE_IP_PKTINFO)
+ {
+ int pad = 1;
+ setsockopt (sd, SOL_IP, IP_PKTINFO, (void*)&pad, sizeof(pad));
+ }
+#endif
return sd;
}
/* create socket */
if (sock->info.proto == PROTO_UDPv4)
{
- sock->sd = create_socket_udp ();
+ sock->sd = create_socket_udp (sock->sockflags);
#ifdef ENABLE_SOCKS
if (sock->socks_proxy)
static void
socket_do_listen (socket_descriptor_t sd,
- const struct sockaddr_in *local,
+ const struct openvpn_sockaddr *local,
bool do_listen,
bool do_set_nonblock)
{
socket_descriptor_t
socket_do_accept (socket_descriptor_t sd,
- struct sockaddr_in *remote,
+ struct link_socket_actual *act,
const bool nowait)
{
- socklen_t remote_len = sizeof (*remote);
+ socklen_t remote_len = sizeof (act->dest.sa);
socket_descriptor_t new_sd = SOCKET_UNDEFINED;
+ CLEAR (*act);
+
#ifdef HAVE_GETPEERNAME
if (nowait)
{
- new_sd = getpeername (sd, (struct sockaddr *) remote, &remote_len);
+ new_sd = getpeername (sd, (struct sockaddr *) &act->dest.sa, &remote_len);
if (!socket_defined (new_sd))
msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: getpeername() failed");
#endif
else
{
- new_sd = accept (sd, (struct sockaddr *) remote, &remote_len);
+ new_sd = accept (sd, (struct sockaddr *) &act->dest.sa, &remote_len);
}
if (!socket_defined (new_sd))
{
msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: accept(%d) failed", sd);
}
- else if (remote_len != sizeof (*remote))
+ else if (remote_len != sizeof (act->dest.sa))
{
msg (D_LINK_ERRORS, "TCP: Received strange incoming connection with unknown address length=%d", remote_len);
openvpn_close_socket (new_sd);
}
static void
-tcp_connection_established (const struct sockaddr_in *remote)
+tcp_connection_established (const struct link_socket_actual *act)
{
struct gc_arena gc = gc_new ();
msg (M_INFO, "TCP connection established with %s",
- print_sockaddr (remote, &gc));
+ print_link_socket_actual (act, &gc));
gc_free (&gc);
}
static int
socket_listen_accept (socket_descriptor_t sd,
- struct sockaddr_in *remote,
+ struct link_socket_actual *act,
const char *remote_dynamic,
bool *remote_changed,
- const struct sockaddr_in *local,
+ const struct openvpn_sockaddr *local,
bool do_listen,
bool nowait,
volatile int *signal_received)
{
struct gc_arena gc = gc_new ();
- struct sockaddr_in remote_verify = *remote;
+ //struct openvpn_sockaddr *remote = &act->dest;
+ struct openvpn_sockaddr remote_verify = act->dest;
int new_sd = SOCKET_UNDEFINED;
+ CLEAR (*act);
socket_do_listen (sd, local, do_listen, true);
while (true)
continue;
}
- new_sd = socket_do_accept (sd, remote, nowait);
+ new_sd = socket_do_accept (sd, act, nowait);
if (socket_defined (new_sd))
{
update_remote (remote_dynamic, &remote_verify, remote_changed);
if (addr_defined (&remote_verify)
- && !addr_match (&remote_verify, remote))
+ && !addr_match (&remote_verify, &act->dest))
{
msg (M_WARN,
"TCP NOTE: Rejected connection attempt from %s due to --remote setting",
- print_sockaddr (remote, &gc));
+ print_link_socket_actual (act, &gc));
if (openvpn_close_socket (new_sd))
msg (M_SOCKERR, "TCP: close socket failed (new_sd)");
}
if (!nowait && openvpn_close_socket (sd))
msg (M_SOCKERR, "TCP: close socket failed (sd)");
- tcp_connection_established (remote);
+ tcp_connection_established (act);
gc_free (&gc);
return new_sd;
static void
socket_connect (socket_descriptor_t *sd,
- struct sockaddr_in *remote,
+ struct openvpn_sockaddr *remote,
struct remote_list *remote_list,
const char *remote_dynamic,
bool *remote_changed,
print_sockaddr (remote, &gc));
while (true)
{
- const int status = connect (*sd, (struct sockaddr *) remote,
- sizeof (*remote));
+ const int status = connect (*sd, (struct sockaddr *) &remote->sa,
+ sizeof (remote->sa));
get_signal (signal_received);
if (*signal_received)
{
remote_list_next (remote_list);
remote_dynamic = remote_list_host (remote_list);
- remote->sin_port = htons (remote_list_port (remote_list));
+ remote->sa.sin_port = htons (remote_list_port (remote_list));
*remote_changed = true;
}
/* resolve local address if undefined */
if (!addr_defined (&sock->info.lsa->local))
{
- sock->info.lsa->local.sin_family = AF_INET;
- sock->info.lsa->local.sin_addr.s_addr =
+ 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.sin_port = htons (sock->local_port);
+ sock->info.lsa->local.sa.sin_port = htons (sock->local_port);
}
/* bind to local address/port */
if (sock->bind_local)
{
- if (bind (sock->sd, (struct sockaddr *) &sock->info.lsa->local,
- sizeof (sock->info.lsa->local)))
+ if (bind (sock->sd, (struct sockaddr *) &sock->info.lsa->local.sa,
+ sizeof (sock->info.lsa->local.sa)))
{
const int errnum = openvpn_errno_socket ();
msg (M_FATAL, "TCP/UDP: Socket bind failed on local address %s: %s",
/* resolve remote address if undefined */
if (!addr_defined (&sock->info.lsa->remote))
{
- sock->info.lsa->remote.sin_family = AF_INET;
- sock->info.lsa->remote.sin_addr.s_addr = 0;
+ sock->info.lsa->remote.sa.sin_family = AF_INET;
+ sock->info.lsa->remote.sa.sin_addr.s_addr = 0;
if (sock->remote_host)
{
ASSERT (0);
}
- sock->info.lsa->remote.sin_addr.s_addr = getaddr (
+ sock->info.lsa->remote.sa.sin_addr.s_addr = getaddr (
flags,
sock->remote_host,
retry,
}
}
- sock->info.lsa->remote.sin_port = htons (sock->remote_port);
+ sock->info.lsa->remote.sa.sin_port = htons (sock->remote_port);
}
/* should we re-use previous active remote address? */
- if (addr_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",
- print_sockaddr (&sock->info.lsa->actual, &gc));
+ print_link_socket_actual (&sock->info.lsa->actual, &gc));
if (remote_dynamic)
*remote_dynamic = NULL;
}
else
- sock->info.lsa->actual = sock->info.lsa->remote;
+ {
+ CLEAR (sock->info.lsa->actual);
+ sock->info.lsa->actual.dest = sock->info.lsa->remote;
+ }
/* remember that we finished */
sock->did_resolve_remote = true;
else if (sock->info.proto == PROTO_TCPv4_CLIENT)
{
socket_connect (&sock->sd,
- &sock->info.lsa->actual,
+ &sock->info.lsa->actual.dest,
sock->remote_list,
remote_dynamic,
&remote_changed,
else if (sock->info.proto == PROTO_UDPv4 && sock->socks_proxy)
{
socket_connect (&sock->ctrl_sd,
- &sock->info.lsa->actual,
+ &sock->info.lsa->actual.dest,
NULL,
remote_dynamic,
&remote_changed,
establish_socks_proxy_udpassoc (sock->socks_proxy,
sock->ctrl_sd,
- sock->sd, &sock->socks_relay,
+ sock->sd,
+ &sock->socks_relay.dest,
signal_received);
if (*signal_received)
sock->remote_host = sock->proxy_dest_host;
sock->remote_port = sock->proxy_dest_port;
sock->did_resolve_remote = false;
- sock->info.lsa->actual.sin_addr.s_addr = 0;
- sock->info.lsa->remote.sin_addr.s_addr = 0;
+
+ sock->info.lsa->actual.dest.sa.sin_addr.s_addr = 0;
+ sock->info.lsa->remote.sa.sin_addr.s_addr = 0;
resolve_remote (sock, 1, NULL, signal_received);
if (remote_changed)
{
msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment");
- sock->info.lsa->remote.sin_addr.s_addr = sock->info.lsa->actual.sin_addr.s_addr;
+ sock->info.lsa->remote.sa.sin_addr.s_addr = sock->info.lsa->actual.dest.sa.sin_addr.s_addr;
}
}
msg (M_INFO, "%s link local%s: %s",
proto2ascii (sock->info.proto, true),
(sock->bind_local ? " (bound)" : ""),
- print_sockaddr_ex (&sock->info.lsa->local, sock->bind_local, ":", &gc));
+ print_sockaddr_ex (&sock->info.lsa->local, ":", sock->bind_local ? PS_SHOW_PORT : 0, &gc));
/* print active remote address */
msg (M_INFO, "%s link remote: %s",
proto2ascii (sock->info.proto, true),
- print_sockaddr_ex (&sock->info.lsa->actual, addr_defined (&sock->info.lsa->actual), ":", &gc));
+ print_link_socket_actual_ex (&sock->info.lsa->actual,
+ ":",
+ PS_SHOW_PORT_IF_DEFINED,
+ &gc));
done:
gc_free (&gc);
void
setenv_trusted (struct env_set *es, const struct link_socket_info *info)
{
- setenv_sockaddr (es, "trusted", &info->lsa->actual, SA_IP_PORT);
+ setenv_link_socket_actual (es, "trusted", &info->lsa->actual, SA_IP_PORT);
}
void
link_socket_connection_initiated (const struct buffer *buf,
struct link_socket_info *info,
- const struct sockaddr_in *addr,
+ const struct link_socket_actual *act,
const char *common_name,
struct env_set *es)
{
struct gc_arena gc = gc_new ();
- info->lsa->actual = *addr; /* Note: skip this line for --force-dest */
+ info->lsa->actual = *act; /* Note: skip this line for --force-dest */
setenv_trusted (es, info);
info->connection_established = true;
struct buffer out = alloc_buf_gc (256, &gc);
if (common_name)
buf_printf (&out, "[%s] ", common_name);
- buf_printf (&out, "Peer Connection Initiated with %s", print_sockaddr (&info->lsa->actual, &gc));
+ buf_printf (&out, "Peer Connection Initiated with %s", print_link_socket_actual (&info->lsa->actual, &gc));
msg (M_INFO, "%s", BSTR (&out));
}
/* Process --ipchange plugin */
if (plugin_defined (info->plugins, OPENVPN_PLUGIN_IPCHANGE))
{
- const char *addr_ascii = print_sockaddr_ex (&info->lsa->actual, true, " ", &gc);
+ const char *addr_ascii = print_sockaddr_ex (&info->lsa->actual.dest, " ", PS_SHOW_PORT, &gc);
if (plugin_call (info->plugins, OPENVPN_PLUGIN_IPCHANGE, addr_ascii, NULL, es))
msg (M_WARN, "WARNING: ipchange plugin call failed");
}
setenv_str (es, "script_type", "ipchange");
buf_printf (&out, "%s %s",
info->ipchange_command,
- print_sockaddr_ex (&info->lsa->actual, true, " ", &gc));
+ print_sockaddr_ex (&info->lsa->actual.dest, " ", PS_SHOW_PORT, &gc));
system_check (BSTR (&out), es, S_SCRIPT, "ip-change command failed");
}
void
link_socket_bad_incoming_addr (struct buffer *buf,
const struct link_socket_info *info,
- const struct sockaddr_in *from_addr)
+ const struct link_socket_actual *from_addr)
{
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_sockaddr (from_addr, &gc),
- (int)from_addr->sin_family,
+ print_link_socket_actual (from_addr, &gc),
+ (int)from_addr->dest.sa.sin_family,
print_sockaddr (&info->lsa->remote, &gc));
buf->len = 0;
{
const struct link_socket_addr *lsa = info->lsa;
- if (addr_defined (&lsa->actual))
- return ntohl (lsa->actual.sin_addr.s_addr);
+ if (link_socket_actual_defined (&lsa->actual))
+ return ntohl (lsa->actual.dest.sa.sin_addr.s_addr);
else if (addr_defined (&lsa->remote))
- return ntohl (lsa->remote.sin_addr.s_addr);
+ return ntohl (lsa->remote.sa.sin_addr.s_addr);
else
return 0;
}
*/
const char *
-print_sockaddr (const struct sockaddr_in *addr, struct gc_arena *gc)
+print_sockaddr (const struct openvpn_sockaddr *addr, struct gc_arena *gc)
{
- return print_sockaddr_ex(addr, true, ":", gc);
+ return print_sockaddr_ex (addr, ":", PS_SHOW_PORT, gc);
}
const char *
-print_sockaddr_ex (const struct sockaddr_in *addr, bool do_port, const char* separator, struct gc_arena *gc)
+print_sockaddr_ex (const struct openvpn_sockaddr *addr,
+ const char* separator,
+ const unsigned int flags,
+ struct gc_arena *gc)
{
- struct buffer out = alloc_buf_gc (64, gc);
- const int port = ntohs (addr->sin_port);
+ if (addr)
+ {
+ struct buffer out = alloc_buf_gc (64, gc);
+ const int port = ntohs (addr->sa.sin_port);
- mutex_lock_static (L_INET_NTOA);
- buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sin_addr) : "[undef]"));
- mutex_unlock_static (L_INET_NTOA);
+ mutex_lock_static (L_INET_NTOA);
+ buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sa.sin_addr) : "[undef]"));
+ mutex_unlock_static (L_INET_NTOA);
- if (do_port && port)
- {
- if (separator)
- buf_printf (&out, "%s", separator);
+ if (((flags & PS_SHOW_PORT) || (addr_defined (addr) && (flags & PS_SHOW_PORT_IF_DEFINED)))
+ && port)
+ {
+ if (separator)
+ buf_printf (&out, "%s", separator);
- buf_printf (&out, "%d", port);
+ buf_printf (&out, "%d", port);
+ }
+ return BSTR (&out);
}
- return BSTR (&out);
+ else
+ return "[NULL]";
+}
+
+const char *
+print_link_socket_actual (const struct link_socket_actual *act, struct gc_arena *gc)
+{
+ return print_link_socket_actual_ex (act, ":", PS_SHOW_PORT|PS_SHOW_PKTINFO, gc);
+}
+
+const char *
+print_link_socket_actual_ex (const struct link_socket_actual *act,
+ const char *separator,
+ const unsigned int flags,
+ struct gc_arena *gc)
+{
+ if (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)
+ {
+ struct openvpn_sockaddr sa;
+ CLEAR (sa);
+ sa.sa.sin_addr = act->pi.ipi_spec_dst;
+ buf_printf (&out, " (via %s)", print_sockaddr_ex (&sa, separator, 0, gc));
+ }
+#endif
+ return BSTR (&out);
+ }
+ else
+ return "[NULL]";
}
/*
/* set environmental variables for ip/port in *addr */
void
-setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct sockaddr_in *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];
openvpn_snprintf (name_buf, sizeof (name_buf), "%s", name_prefix);
mutex_lock_static (L_INET_NTOA);
- setenv_str (es, name_buf, inet_ntoa (addr->sin_addr));
+ setenv_str (es, name_buf, inet_ntoa (addr->sa.sin_addr));
mutex_unlock_static (L_INET_NTOA);
- if ((flags & SA_IP_PORT) && addr->sin_port)
+ 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->sin_port));
+ setenv_int (es, name_buf, ntohs (addr->sa.sin_port));
}
}
{
if (addr || !(flags & SA_SET_IF_NONZERO))
{
- struct sockaddr_in si;
+ struct openvpn_sockaddr si;
CLEAR (si);
- si.sin_addr.s_addr = htonl (addr);
+ si.sa.sin_addr.s_addr = htonl (addr);
setenv_sockaddr (es, name_prefix, &si, flags);
}
}
+void
+setenv_link_socket_actual (struct env_set *es,
+ const char *name_prefix,
+ const struct link_socket_actual *act,
+ const bool flags)
+{
+ setenv_sockaddr (es, name_prefix, &act->dest, flags);
+}
+
/*
* Convert protocol names between index and ascii form.
*/
#ifndef WIN32
+#if ENABLE_IP_PKTINFO
+
+struct openvpn_pktinfo
+{
+ struct cmsghdr cmsghdr;
+ struct in_pktinfo in_pktinfo;
+};
+
+static socklen_t
+link_socket_read_udp_posix_recvmsg (struct link_socket *sock,
+ struct buffer *buf,
+ int maxsize,
+ struct link_socket_actual *from)
+{
+ struct iovec iov;
+ struct openvpn_pktinfo opi;
+ struct msghdr mesg;
+ socklen_t fromlen = sizeof (from->dest.sa);
+
+ 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_namelen = fromlen;
+ mesg.msg_control = &opi;
+ mesg.msg_controllen = sizeof (opi);
+ buf->len = recvmsg (sock->sd, &mesg, 0);
+ if (buf->len >= 0)
+ {
+ struct cmsghdr *cmsg;
+ fromlen = mesg.msg_namelen;
+ cmsg = CMSG_FIRSTHDR (&mesg);
+ if (cmsg != NULL
+ && CMSG_NXTHDR (&mesg, cmsg) == NULL
+ && cmsg->cmsg_level == SOL_IP
+ && cmsg->cmsg_type == IP_PKTINFO
+ && 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;
+ }
+ }
+ return fromlen;
+}
+#endif
+
int
link_socket_read_udp_posix (struct link_socket *sock,
struct buffer *buf,
int maxsize,
- struct sockaddr_in *from)
+ struct link_socket_actual *from)
{
- socklen_t fromlen = sizeof (*from);
- CLEAR (*from);
+ socklen_t fromlen = sizeof (from->dest.sa);
+ from->dest.sa.sin_addr.s_addr = 0;
ASSERT (buf_safe (buf, maxsize));
- buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,
- (struct sockaddr *) from, &fromlen);
- if (fromlen != sizeof (*from))
- bad_address_length (fromlen, sizeof (*from));
+#if ENABLE_IP_PKTINFO
+ if (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));
return buf->len;
}
int
link_socket_write_tcp (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
packet_size_type len = BLEN (buf);
dmsg (D_STREAM_DEBUG, "STREAM: WRITE %d offset=%d", (int)len, buf->offset);
#endif
}
+#if ENABLE_IP_PKTINFO
+
+int
+link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *to)
+{
+ 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;
+ return sendmsg (sock->sd, &mesg, 0);
+}
+
+#endif
+
/*
* Win32 overlapped socket I/O functions.
*/
}
int
-socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct sockaddr_in *to)
+socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct link_socket_actual *to)
{
if (sock->writes.iostate == IOSTATE_INITIAL)
{
{
/* set destination address for UDP writes */
sock->writes.addr_defined = true;
- sock->writes.addr = *to;
+ sock->writes.addr = to->dest.sa;
sock->writes.addrlen = sizeof (sock->writes.addr);
status = WSASendTo(
}
int
-socket_finalize (
- SOCKET s,
+socket_finalize (SOCKET s,
struct overlapped_io *io,
struct buffer *buf,
- struct sockaddr_in *from)
+ struct link_socket_actual *from)
{
int ret = -1;
BOOL status;
{
if (io->addrlen != sizeof (io->addr))
bad_address_length (io->addrlen, sizeof (io->addr));
- *from = io->addr;
+ from->dest.sa = io->addr;
}
else
- CLEAR (*from);
+ CLEAR (from->dest.sa);
}
if (buf)
/* convert a packet_size_type from network to host order */
#define ntohps(x) ntohs(x)
+/* OpenVPN sockaddr struct */
+struct openvpn_sockaddr
+{
+ int dummy; // JYFIXME
+ struct sockaddr_in sa;
+};
+
+/* actual address of remote, based on source address of received packets */
+struct link_socket_actual
+{
+ int dummy; // JYFIXME
+ struct openvpn_sockaddr dest;
+#if ENABLE_IP_PKTINFO
+ struct in_pktinfo pi;
+#endif
+};
+
/* IP addresses which are persistant across SIGUSR1s */
struct link_socket_addr
{
- struct sockaddr_in local;
- struct sockaddr_in remote; /* initial remote */
- struct sockaddr_in actual; /* remote may change due to --float */
+ struct openvpn_sockaddr local;
+ struct openvpn_sockaddr remote; /* initial remote */
+ struct link_socket_actual actual; /* reply to this address */
};
struct link_socket_info
bool did_resolve_remote;
-# define SF_TCP_NODELAY (1<<0)
+# define SF_USE_IP_PKTINFO (1<<0)
+# define SF_TCP_NODELAY (1<<1)
unsigned int sockflags;
/* for stream sockets */
#ifdef ENABLE_SOCKS
/* Socks proxy */
struct socks_proxy_info *socks_proxy;
- struct sockaddr_in socks_relay; /* Socks UDP relay address */
+ struct link_socket_actual socks_relay; /* Socks UDP relay address */
#endif
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_SOCKS)
int socket_send_queue (struct link_socket *sock,
struct buffer *buf,
- const struct sockaddr_in *to);
+ const struct link_socket_actual *to);
int socket_finalize (
SOCKET s,
struct overlapped_io *io,
struct buffer *buf,
- struct sockaddr_in *from);
+ struct link_socket_actual *from);
#else
const struct frame *frame,
volatile int *signal_received);
-void link_socket_post_fork (const struct link_socket *sock,
- const struct sockaddr_in *remote);
-
void socket_adjust_frame_parameters (struct frame *frame, int proto);
void frame_adjust_path_mtu (struct frame *frame, int pmtu, int proto);
void link_socket_close (struct link_socket *sock);
-const char *print_sockaddr_ex (const struct sockaddr_in *addr,
- bool do_port,
+#define PS_SHOW_PORT_IF_DEFINED (1<<0)
+#define PS_SHOW_PORT (1<<1)
+#define PS_SHOW_PKTINFO (1<<2)
+
+const char *print_sockaddr_ex (const struct openvpn_sockaddr *addr,
const char* separator,
+ const unsigned int flags,
struct gc_arena *gc);
-const char *print_sockaddr (const struct sockaddr_in *addr,
+
+const char *print_sockaddr (const struct openvpn_sockaddr *addr,
struct gc_arena *gc);
+const char *print_link_socket_actual_ex (const struct link_socket_actual *act,
+ const char* separator,
+ const unsigned int flags,
+ struct gc_arena *gc);
+
+const char *print_link_socket_actual (const struct link_socket_actual *act,
+ struct gc_arena *gc);
+
+
#define IA_EMPTY_IF_UNDEF (1<<0)
#define IA_NET_ORDER (1<<1)
const char *print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc);
#define SA_SET_IF_NONZERO (1<<1)
void setenv_sockaddr (struct env_set *es,
const char *name_prefix,
- const struct sockaddr_in *addr,
+ const struct openvpn_sockaddr *addr,
const bool flags);
void setenv_in_addr_t (struct env_set *es,
in_addr_t addr,
const bool flags);
+void setenv_link_socket_actual (struct env_set *es,
+ const char *name_prefix,
+ const struct link_socket_actual *act,
+ const bool flags);
+
void bad_address_length (int actual, int expected);
in_addr_t link_socket_current_remote (const struct link_socket_info *info);
void link_socket_connection_initiated (const struct buffer *buf,
struct link_socket_info *info,
- const struct sockaddr_in *addr,
+ const struct link_socket_actual *addr,
const char *common_name,
struct env_set *es);
void link_socket_bad_incoming_addr (struct buffer *buf,
const struct link_socket_info *info,
- const struct sockaddr_in *from_addr);
+ const struct link_socket_actual *from_addr);
void link_socket_bad_outgoing_addr (void);
socket_descriptor_t create_socket_tcp (void);
socket_descriptor_t socket_do_accept (socket_descriptor_t sd,
- struct sockaddr_in *remote,
+ struct link_socket_actual *act,
const bool nowait);
/*
}
static inline bool
-addr_defined (const struct sockaddr_in *addr)
+addr_defined (const struct openvpn_sockaddr *addr)
{
- return addr->sin_addr.s_addr != 0;
+ return addr->sa.sin_addr.s_addr != 0;
}
static inline bool
-addr_match (const struct sockaddr_in *a1, const struct sockaddr_in *a2)
+link_socket_actual_defined (const struct link_socket_actual *act)
{
- return a1->sin_addr.s_addr == a2->sin_addr.s_addr;
+ return act && addr_defined (&act->dest);
+}
+
+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;
}
static inline in_addr_t
-addr_host (const struct sockaddr_in *s)
+addr_host (const struct openvpn_sockaddr *s)
{
- return ntohl (s->sin_addr.s_addr);
+ return ntohl (s->sa.sin_addr.s_addr);
}
static inline bool
-addr_port_match (const struct sockaddr_in *a1, const struct sockaddr_in *a2)
+addr_port_match (const struct openvpn_sockaddr *a1, const struct openvpn_sockaddr *a2)
{
- return a1->sin_addr.s_addr == a2->sin_addr.s_addr
- && a1->sin_port == a2->sin_port;
+ return a1->sa.sin_addr.s_addr == a2->sa.sin_addr.s_addr
+ && a1->sa.sin_port == a2->sa.sin_port;
}
static inline bool
-addr_match_proto (const struct sockaddr_in *a1,
- const struct sockaddr_in *a2,
+addr_match_proto (const struct openvpn_sockaddr *a1,
+ const struct openvpn_sockaddr *a2,
const int proto)
{
return link_socket_proto_connection_oriented (proto)
: addr_port_match (a1, a2);
}
+static inline bool
+link_socket_actual_match (const struct link_socket_actual *a1, const struct link_socket_actual *a2)
+{
+ return addr_port_match (&a1->dest, &a2->dest);
+}
+
static inline bool
socket_connection_reset (const struct link_socket *sock, int status)
{
static inline bool
link_socket_verify_incoming_addr (struct buffer *buf,
const struct link_socket_info *info,
- const struct sockaddr_in *from_addr)
+ const struct link_socket_actual *from_addr)
{
if (buf->len > 0)
{
- if (from_addr->sin_family != AF_INET)
+ if (from_addr->dest.sa.sin_family != AF_INET)
return false;
- if (!addr_defined (from_addr))
+ 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, &info->lsa->remote, info->proto))
+ if (addr_match_proto (&from_addr->dest, &info->lsa->remote, info->proto))
return true;
}
return false;
static inline void
link_socket_get_outgoing_addr (struct buffer *buf,
const struct link_socket_info *info,
- struct sockaddr_in *addr)
+ struct link_socket_actual **act)
{
if (buf->len > 0)
{
struct link_socket_addr *lsa = info->lsa;
- if (addr_defined (&lsa->actual))
- {
- addr->sin_family = lsa->actual.sin_family;
- addr->sin_addr.s_addr = lsa->actual.sin_addr.s_addr;
- addr->sin_port = lsa->actual.sin_port;
- }
+ if (link_socket_actual_defined (&lsa->actual))
+ *act = &lsa->actual;
else
{
link_socket_bad_outgoing_addr ();
buf->len = 0;
+ *act = NULL;
}
}
}
static inline void
link_socket_set_outgoing_addr (const struct buffer *buf,
struct link_socket_info *info,
- const struct sockaddr_in *addr,
+ const struct link_socket_actual *act,
const char *common_name,
struct env_set *es)
{
if (
/* new or changed address? */
(!info->connection_established
- || !addr_match_proto (addr, &lsa->actual, info->proto))
+ || !addr_match_proto (&act->dest, &lsa->actual.dest, info->proto))
/* address undef or address == remote or --float */
&& (info->remote_float
|| !addr_defined (&lsa->remote)
- || addr_match_proto (addr, &lsa->remote, info->proto))
+ || addr_match_proto (&act->dest, &lsa->remote, info->proto))
)
{
- link_socket_connection_initiated (buf, info, addr, common_name, es);
+ link_socket_connection_initiated (buf, info, act, common_name, es);
}
}
}
static inline int
link_socket_read_udp_win32 (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *from)
+ struct link_socket_actual *from)
{
return socket_finalize (sock->sd, &sock->reads, buf, from);
}
int link_socket_read_udp_posix (struct link_socket *sock,
struct buffer *buf,
int maxsize,
- struct sockaddr_in *from);
+ struct link_socket_actual *from);
#endif
link_socket_read (struct link_socket *sock,
struct buffer *buf,
int maxsize,
- struct sockaddr_in *from)
+ struct link_socket_actual *from)
{
if (sock->info.proto == PROTO_UDPv4)
{
else if (sock->info.proto == PROTO_TCPv4_SERVER || sock->info.proto == PROTO_TCPv4_CLIENT)
{
/* from address was returned by accept */
- *from = sock->info.lsa->actual;
+ from->dest.sa = sock->info.lsa->actual.dest.sa;
return link_socket_read_tcp (sock, buf);
}
else
int link_socket_write_tcp (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to);
+ struct link_socket_actual *to);
#ifdef WIN32
static inline int
link_socket_write_win32 (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
int err = 0;
int status = 0;
static inline int
link_socket_write_udp_posix (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
- return sendto (sock->sd, BPTR (buf), BLEN (buf), 0,
- (struct sockaddr *) to,
- (socklen_t) sizeof (*to));
+#if ENABLE_IP_PKTINFO
+ int link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
+ struct buffer *buf,
+ struct link_socket_actual *to);
+
+ if (sock->sockflags & SF_USE_IP_PKTINFO)
+ 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));
}
static inline int
link_socket_write_tcp_posix (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
return send (sock->sd, BPTR (buf), BLEN (buf), MSG_NOSIGNAL);
}
static inline int
link_socket_write_udp (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
#ifdef WIN32
return link_socket_write_win32 (sock, buf, to);
static inline int
link_socket_write (struct link_socket *sock,
struct buffer *buf,
- struct sockaddr_in *to)
+ struct link_socket_actual *to)
{
if (sock->info.proto == PROTO_UDPv4)
{
}
static bool
-recv_socks_reply (socket_descriptor_t sd, struct sockaddr_in *addr,
+recv_socks_reply (socket_descriptor_t sd,
+ struct openvpn_sockaddr *addr,
volatile int *signal_received)
{
char atyp = '\0';
if (addr != NULL)
{
- addr->sin_family = AF_INET;
- addr->sin_addr.s_addr = htonl (INADDR_ANY);
- addr->sin_port = htons (0);
+ addr->sa.sin_family = AF_INET;
+ addr->sa.sin_addr.s_addr = htonl (INADDR_ANY);
+ addr->sa.sin_port = htons (0);
}
while (len < 4 + alen + 2)
/* ATYP == 1 (IP V4 address) */
if (atyp == '\x01' && addr != NULL)
{
- memcpy (&addr->sin_addr, buf + 4, sizeof (addr->sin_addr));
- memcpy (&addr->sin_port, buf + 8, sizeof (addr->sin_port));
+ memcpy (&addr->sa.sin_addr, buf + 4, sizeof (addr->sa.sin_addr));
+ memcpy (&addr->sa.sin_port, buf + 8, sizeof (addr->sa.sin_port));
}
establish_socks_proxy_udpassoc (struct socks_proxy_info *p,
socket_descriptor_t ctrl_sd, /* already open to proxy */
socket_descriptor_t udp_sd,
- struct sockaddr_in *relay_addr,
+ struct openvpn_sockaddr *relay_addr,
volatile int *signal_received)
{
if (!socks_handshake (ctrl_sd, signal_received))
*/
void
socks_process_incoming_udp (struct buffer *buf,
- struct sockaddr_in *from)
+ struct link_socket_actual *from)
{
int atyp;
if (atyp != 1) /* ATYP == 1 (IP V4) */
goto error;
- buf_read (buf, &from->sin_addr, sizeof (from->sin_addr));
- buf_read (buf, &from->sin_port, sizeof (from->sin_port));
+ 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));
return;
*/
int
socks_process_outgoing_udp (struct buffer *buf,
- struct sockaddr_in *to)
+ const struct link_socket_actual *to)
{
/*
* Get a 10 byte subset buffer prepended to 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->sin_addr, sizeof (to->sin_addr));
- buf_write (&head, &to->sin_port, sizeof (to->sin_port));
+ 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));
return 10;
}
#include "buffer.h"
+struct openvpn_sockaddr;
+struct link_socket_actual;
+
struct socks_proxy_info {
bool defined;
bool retry;
void establish_socks_proxy_udpassoc (struct socks_proxy_info *p,
socket_descriptor_t ctrl_sd, /* already open to proxy */
socket_descriptor_t udp_sd,
- struct sockaddr_in *relay_addr,
+ struct openvpn_sockaddr *relay_addr,
volatile int *signal_received);
void socks_process_incoming_udp (struct buffer *buf,
- struct sockaddr_in *from);
+ struct link_socket_actual *from);
int socks_process_outgoing_udp (struct buffer *buf,
- struct sockaddr_in *to);
+ const struct link_socket_actual *to);
#endif
#endif
static void
setenv_untrusted (struct tls_session *session)
{
- setenv_sockaddr (session->opt->es, "untrusted", &session->untrusted_sockaddr, SA_IP_PORT);
+ setenv_link_socket_actual (session->opt->es, "untrusted", &session->untrusted_addr, SA_IP_PORT);
}
static void
write_control_auth (struct tls_session *session,
struct key_state *ks,
struct buffer *buf,
- struct sockaddr_in *to_link_addr,
+ struct link_socket_actual **to_link_addr,
int opcode,
int max_ack,
bool prepend_ack)
uint8_t *header;
struct buffer null = clear_buf ();
- ASSERT (addr_defined (&ks->remote_addr));
+ ASSERT (link_socket_actual_defined (&ks->remote_addr));
ASSERT (reliable_ack_write
(ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack));
ASSERT (session_id_write_prepend (&session->session_id, buf));
openvpn_encrypt (buf, null, &session->tls_auth, NULL);
ASSERT (swap_hmac (buf, &session->tls_auth, false));
}
- *to_link_addr = ks->remote_addr;
+ *to_link_addr = &ks->remote_addr;
}
/*
static bool
read_control_auth (struct buffer *buf,
const struct crypto_options *co,
- const struct sockaddr_in *from)
+ const struct link_socket_actual *from)
{
struct gc_arena gc = gc_new ();
{
msg (D_TLS_ERRORS,
"TLS Error: cannot locate HMAC in incoming packet from %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
gc_free (&gc);
return false;
}
{
msg (D_TLS_ERRORS,
"TLS Error: incoming packet authentication failed from %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
gc_free (&gc);
return false;
}
tls_process (struct tls_multi *multi,
struct tls_session *session,
struct buffer *to_link,
- struct sockaddr_in *to_link_addr,
+ struct link_socket_actual **to_link_addr,
struct link_socket_info *to_link_socket_info,
interval_t *wakeup)
{
bool
tls_multi_process (struct tls_multi *multi,
struct buffer *to_link,
- struct sockaddr_in *to_link_addr,
+ struct link_socket_actual **to_link_addr,
struct link_socket_info *to_link_socket_info,
interval_t *wakeup)
{
/* set initial remote address */
if (i == TM_ACTIVE && ks->state == S_INITIAL &&
- addr_defined (&to_link_socket_info->lsa->actual))
+ link_socket_actual_defined (&to_link_socket_info->lsa->actual))
ks->remote_addr = to_link_socket_info->lsa->actual;
dmsg (D_TLS_DEBUG,
state_name (ks->state),
session_id_print (&session->session_id, &gc),
session_id_print (&ks->session_id_remote, &gc),
- print_sockaddr (&ks->remote_addr, &gc));
+ print_link_socket_actual (&ks->remote_addr, &gc));
- if (ks->state >= S_INITIAL && addr_defined (&ks->remote_addr))
+ if (ks->state >= S_INITIAL && link_socket_actual_defined (&ks->remote_addr))
{
+ struct link_socket_actual *tla = NULL;
+
update_time ();
- if (tls_process (multi, session, to_link, to_link_addr,
+ if (tls_process (multi, session, to_link, &tla,
to_link_socket_info, wakeup))
active = true;
+ /*
+ * If tls_process produced an outgoing packet,
+ * return the link_socket_actual object (which
+ * contains the outgoing address).
+ */
+ if (tla)
+ {
+ multi->to_link_addr = *tla;
+ *to_link_addr = &multi->to_link_addr;
+ }
+
/*
* If tls_process hits an error:
* (1) If the session has an unexpired lame duck key, preserve it.
bool
tls_pre_decrypt (struct tls_multi *multi,
- struct sockaddr_in *from,
+ const struct link_socket_actual *from,
struct buffer *buf,
struct crypto_options *opt)
{
if (DECRYPT_KEY_ENABLED (multi, ks)
&& key_id == ks->key_id
&& ks->authenticated
- && addr_port_match(from, &ks->remote_addr))
+ && link_socket_actual_match (from, &ks->remote_addr))
{
/* return appropriate data channel decrypt key in opt */
opt->key_ctx_bi = &ks->key;
ks->n_bytes += buf->len;
dmsg (D_TLS_DEBUG,
"TLS: data channel, key_id=%d, IP=%s",
- key_id, print_sockaddr (from, &gc));
+ key_id, print_link_socket_actual (from, &gc));
gc_free (&gc);
return ret;
}
key_id,
ks->key_id,
ks->authenticated,
- addr_port_match (from, &ks->remote_addr));
+ link_socket_actual_match (from, &ks->remote_addr));
}
#endif
}
msg (D_TLS_ERRORS,
"TLS Error: local/remote TLS keys are out of sync: %s [%d]",
- print_sockaddr (from, &gc), key_id);
+ print_link_socket_actual (from, &gc), key_id);
goto error;
}
else /* control channel packet */
{
msg (D_TLS_ERRORS,
"TLS Error: unknown opcode received from %s op=%d",
- print_sockaddr (from, &gc), op);
+ print_link_socket_actual (from, &gc), op);
goto error;
}
{
msg (D_TLS_ERRORS,
"TLS Error: client->client or server->server connection attempted from %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
}
* Authenticate Packet
*/
dmsg (D_TLS_DEBUG, "TLS: control channel, op=%s, IP=%s",
- packet_opcode_name (op), print_sockaddr (from, &gc));
+ packet_opcode_name (op), print_link_socket_actual (from, &gc));
/* get remote session-id */
{
{
msg (D_TLS_ERRORS,
"TLS Error: session-id not found in packet from %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
}
state_name (ks->state),
session_id_print (&session->session_id, &gc),
session_id_print (&sid, &gc),
- print_sockaddr (from, &gc),
+ print_link_socket_actual (from, &gc),
session_id_print (&ks->session_id_remote, &gc),
- print_sockaddr (&ks->remote_addr, &gc));
+ print_link_socket_actual (&ks->remote_addr, &gc));
if (session_id_equal (&ks->session_id_remote, &sid))
/* found a match */
{
msg (D_TLS_ERRORS,
"TLS Error: Cannot accept new session request from %s due to --single-session [1]",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
msg (D_TLS_DEBUG_LOW,
"TLS: Initial packet from %s, sid=%s",
- print_sockaddr (from, &gc),
+ print_link_socket_actual (from, &gc),
session_id_print (&sid, &gc));
do_burst = true;
new_link = true;
i = TM_ACTIVE;
- session->untrusted_sockaddr = *from;
+ session->untrusted_addr = *from;
}
}
{
msg (D_TLS_ERRORS,
"TLS Error: Cannot accept new session request from %s due to --single-session [2]",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
*/
msg (D_TLS_DEBUG_LOW,
"TLS: new session incoming connection from %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
new_link = true;
i = TM_UNTRUSTED;
- session->untrusted_sockaddr = *from;
+ session->untrusted_addr = *from;
}
else
{
{
msg (D_TLS_ERRORS,
"TLS Error: Unroutable control packet received from %s (si=%d op=%s)",
- print_sockaddr (from, &gc),
+ print_link_socket_actual (from, &gc),
i,
packet_opcode_name (op));
goto error;
/*
* Verify remote IP address
*/
- if (!new_link && !addr_port_match (&ks->remote_addr, from))
+ if (!new_link && !link_socket_actual_match (&ks->remote_addr, from))
{
msg (D_TLS_ERRORS, "TLS Error: Received control packet from unexpected IP addr: %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
ks->remote_addr = *from;
++multi->n_sessions;
}
- else if (!addr_port_match (&ks->remote_addr, from))
+ else if (!link_socket_actual_match (&ks->remote_addr, from))
{
msg (D_TLS_ERRORS,
"TLS Error: Existing session control channel packet from unknown IP address: %s",
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
*/
bool
tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
- const struct sockaddr_in *from,
+ const struct link_socket_actual *from,
const struct buffer *buf)
+
{
struct gc_arena gc = gc_new ();
bool ret = false;
*/
dmsg (D_TLS_STATE_ERRORS,
"TLS State Error: No TLS state for client %s, opcode=%d",
- print_sockaddr (from, &gc),
+ print_link_socket_actual (from, &gc),
op);
goto error;
}
dmsg (D_TLS_STATE_ERRORS,
"TLS State Error: Unknown key ID (%d) received from %s -- 0 was expected",
key_id,
- print_sockaddr (from, &gc));
+ print_link_socket_actual (from, &gc));
goto error;
}
dmsg (D_TLS_STATE_ERRORS,
"TLS State Error: Large packet (size %d) received from %s -- a packet no larger than %d bytes was expected",
buf->len,
- print_sockaddr (from, &gc),
+ print_link_socket_actual (from, &gc),
EXPANDED_SIZE_DYNAMIC (&tas->frame));
goto error;
}
time_t must_die; /* this object is destroyed at this time */
int initial_opcode; /* our initial P_ opcode */
- struct session_id session_id_remote; /* peer's random session ID */
- struct sockaddr_in remote_addr; /* peer's IP addr */
+ struct session_id session_id_remote; /* peer's random session ID */
+ struct link_socket_actual remote_addr; /* peer's IP addr */
struct packet_id packet_id; /* for data channel, to prevent replay attacks */
struct key_ctx_bi key; /* data channel keys for encrypt/decrypt/hmac */
bool verified; /* true if peer certificate was verified against CA */
/* not-yet-authenticated incoming client */
- struct sockaddr_in untrusted_sockaddr;
+ struct link_socket_actual untrusted_addr;
struct key_state key[KS_SIZE];
};
*/
struct key_state *save_ks; /* temporary pointer used between pre/post routines */
+ /*
+ * Used to return outgoing address from
+ * tls_multi_process.
+ */
+ struct link_socket_actual to_link_addr;
+
/*
* Number of sessions negotiated thus far.
*/
bool tls_multi_process (struct tls_multi *multi,
struct buffer *to_link,
- struct sockaddr_in *to_link_addr,
+ struct link_socket_actual **to_link_addr,
struct link_socket_info *to_link_socket_info,
interval_t *wakeup);
void tls_multi_free (struct tls_multi *multi, bool clear);
bool tls_pre_decrypt (struct tls_multi *multi,
- struct sockaddr_in *from,
+ const struct link_socket_actual *from,
struct buffer *buf,
struct crypto_options *opt);
bool tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
- const struct sockaddr_in *from,
+ const struct link_socket_actual *from,
const struct buffer *buf);
void tls_pre_encrypt (struct tls_multi *multi,
#define EXTENDED_SOCKET_ERROR_CAPABILITY 0
#endif
+/*
+ * Does this platform support linux-style IP_PKTINFO?
+ */
+#if defined(ENABLE_MULTIHOME) && defined(HAVE_IN_PKTINFO) && defined(IP_PKTINFO) && defined(HAVE_MSGHDR) && defined(HAVE_CMSGHDR) && defined(HAVE_IOVEC) && defined(CMSG_FIRSTHDR) && defined(CMSG_NXTHDR) && defined(HAVE_RECVMSG) && defined(HAVE_SENDMSG)
+#define ENABLE_IP_PKTINFO 1
+#else
+#define ENABLE_IP_PKTINFO 0
+#endif
+
/*
* Disable ESEC
*/