From 8bc93d7ffbc127e0b095c7274a68eb0c175f93ae Mon Sep 17 00:00:00 2001 From: james Date: Sat, 15 Oct 2005 08:44:02 +0000 Subject: svn merge -r 618:619 $SO/patches/openvpn-2-0_rc16-mh/openvpn Merged --multihome patch + aggregated sockflags. Pre-2.1_beta3 git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@622 e7ae566f-a301-0410-adde-c780ea21d3b5 --- ChangeLog | 11 +- configure.ac | 18 +++- forward.c | 25 +++-- manage.c | 15 +-- manage.h | 4 +- mroute.c | 15 +-- mroute.h | 8 +- mtcp.c | 2 +- mudp.c | 2 +- multi.c | 18 ++-- openvpn.h | 4 +- options.c | 10 ++ ping-inline.h | 2 +- socket.c | 337 ++++++++++++++++++++++++++++++++++++++++++---------------- socket.h | 164 ++++++++++++++++++---------- socks.c | 27 ++--- socks.h | 9 +- ssl.c | 92 +++++++++------- ssl.h | 18 ++-- syshead.h | 9 ++ 20 files changed, 533 insertions(+), 257 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5bbdca1..04c8567 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,12 +11,11 @@ $Id$ 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 diff --git a/configure.ac b/configure.ac index 9faae97..844778f 100644 --- a/configure.ac +++ b/configure.ac @@ -95,6 +95,12 @@ AC_ARG_ENABLE(fragment, [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"], @@ -342,6 +348,11 @@ AC_CHECK_TYPE( [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) @@ -367,7 +378,7 @@ AC_CHECK_FUNCS(daemon chroot getpwnam setuid nice system getpid dup dup2 dnl 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 @@ -605,6 +616,11 @@ if test "$HTTP_PROXY" = "yes"; then 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]) diff --git a/forward.c b/forward.c index e1023ef..11d6d28 100644 --- a/forward.c +++ b/forward.c @@ -571,12 +571,12 @@ socks_postprocess_incoming_link (struct context *c) 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; } } @@ -616,7 +616,10 @@ read_incoming_link (struct context *c) 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)) { @@ -687,7 +690,7 @@ process_incoming_link (struct context *c) 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)); /* @@ -985,7 +988,7 @@ process_outgoing_link (struct context *c) * 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 */ @@ -1020,12 +1023,12 @@ process_outgoing_link (struct context *c) 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 @@ -1035,7 +1038,9 @@ process_outgoing_link (struct context *c) 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 */ @@ -1059,7 +1064,7 @@ process_outgoing_link (struct context *c) 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); } @@ -1068,7 +1073,7 @@ process_outgoing_link (struct context *c) { 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)); } diff --git a/manage.c b/manage.c index f76ec7a..2d1bcbb 100644 --- a/manage.c +++ b/manage.c @@ -770,13 +770,16 @@ static void 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 @@ -1145,9 +1148,9 @@ man_settings_init (struct man_settings *ms, /* * 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 @@ -1159,7 +1162,7 @@ man_settings_init (struct man_settings *ms, } 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); } @@ -1406,7 +1409,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.sin_addr.s_addr = htonl (tun_local_ip); + man->settings.local.sa.sin_addr.s_addr = htonl (tun_local_ip); man_connection_init (man); } diff --git a/manage.h b/manage.h index 8015226..5d059fa 100644 --- a/manage.h +++ b/manage.h @@ -188,7 +188,7 @@ struct man_persist { 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; @@ -215,7 +215,7 @@ struct man_connection { 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; diff --git a/mroute.c b/mroute.c index 0a7bcf6..a7d1215 100644 --- a/mroute.c +++ b/mroute.c @@ -168,28 +168,29 @@ mroute_extract_addr_from_packet (struct mroute_addr *src, } /* - * 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; } diff --git a/mroute.h b/mroute.h index 87e952c..fb7bee7 100644 --- a/mroute.h +++ b/mroute.h @@ -94,9 +94,11 @@ unsigned int mroute_extract_addr_from_packet (struct mroute_addr *src, 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); diff --git a/mtcp.c b/mtcp.c index a71801f..6ec9974 100644 --- a/mtcp.c +++ b/mtcp.c @@ -159,7 +159,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); - 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; diff --git a/mudp.c b/mudp.c index 750dc8f..fa2ae17 100644 --- a/mudp.c +++ b/mudp.c @@ -51,7 +51,7 @@ multi_get_create_instance_udp (struct multi_context *m) 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); diff --git a/multi.c b/multi.c index 7bccfed..a42c561 100644 --- a/multi.c +++ b/multi.c @@ -982,13 +982,13 @@ multi_learn_in_addr_t (struct multi_context *m, 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) { @@ -2180,15 +2180,15 @@ management_callback_kill_by_addr (void *arg, const in_addr_t addr, const int por 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))) diff --git a/openvpn.h b/openvpn.h index 5c93c8d..78bb67b 100644 --- a/openvpn.h +++ b/openvpn.h @@ -205,8 +205,8 @@ struct context_2 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; diff --git a/options.c b/options.c index 0895674..c9ed15d 100644 --- a/options.c +++ b/options.c @@ -175,6 +175,9 @@ static const char usage_message[] = "--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" @@ -3281,6 +3284,13 @@ add_option (struct options *options, 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; diff --git a/ping-inline.h b/ping-inline.h index bf7fd81..14463de 100644 --- a/ping-inline.h +++ b/ping-inline.h @@ -37,7 +37,7 @@ check_ping_restart (struct context *c) && 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); } diff --git a/socket.c b/socket.c index c7172ac..35d38a1 100644 --- a/socket.c +++ b/socket.c @@ -236,7 +236,7 @@ openvpn_inet_aton (const char *dotted_quad, struct in_addr *addr) static void update_remote (const char* host, - struct sockaddr_in *addr, + struct openvpn_sockaddr *addr, bool *changed) { if (host && addr) @@ -247,9 +247,9 @@ update_remote (const char* host, 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; } } @@ -492,12 +492,19 @@ create_socket_tcp (void) } 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; } @@ -507,7 +514,7 @@ create_socket (struct link_socket *sock) /* 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) @@ -531,7 +538,7 @@ create_socket (struct link_socket *sock) 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) { @@ -553,16 +560,18 @@ socket_do_listen (socket_descriptor_t sd, 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"); @@ -575,14 +584,14 @@ socket_do_accept (socket_descriptor_t sd, #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); @@ -592,28 +601,30 @@ socket_do_accept (socket_descriptor_t 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) @@ -645,17 +656,17 @@ socket_listen_accept (socket_descriptor_t sd, 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)"); } @@ -668,7 +679,7 @@ socket_listen_accept (socket_descriptor_t 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; @@ -676,7 +687,7 @@ socket_listen_accept (socket_descriptor_t 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, @@ -689,8 +700,8 @@ socket_connect (socket_descriptor_t *sd, 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) @@ -711,7 +722,7 @@ socket_connect (socket_descriptor_t *sd, { 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; } @@ -771,22 +782,22 @@ resolve_bind_local (struct link_socket *sock) /* 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", @@ -810,8 +821,8 @@ resolve_remote (struct link_socket *sock, /* 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) { @@ -856,7 +867,7 @@ resolve_remote (struct link_socket *sock, 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, @@ -883,19 +894,22 @@ resolve_remote (struct link_socket *sock, } } - 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; @@ -1162,7 +1176,7 @@ link_socket_init_phase2 (struct link_socket *sock, 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, @@ -1200,7 +1214,7 @@ link_socket_init_phase2 (struct link_socket *sock, 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, @@ -1212,7 +1226,8 @@ link_socket_init_phase2 (struct link_socket *sock, 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) @@ -1221,8 +1236,9 @@ link_socket_init_phase2 (struct link_socket *sock, 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); @@ -1237,7 +1253,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.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; } } @@ -1274,12 +1290,15 @@ link_socket_init_phase2 (struct link_socket *sock, 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); @@ -1344,19 +1363,19 @@ socket_adjust_frame_parameters (struct frame *frame, int proto) 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; @@ -1365,7 +1384,7 @@ link_socket_connection_initiated (const struct buffer *buf, 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)); } @@ -1375,7 +1394,7 @@ link_socket_connection_initiated (const struct buffer *buf, /* 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"); } @@ -1387,7 +1406,7 @@ link_socket_connection_initiated (const struct buffer *buf, 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"); } @@ -1397,14 +1416,14 @@ link_socket_connection_initiated (const struct buffer *buf, 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; @@ -1422,10 +1441,10 @@ link_socket_current_remote (const struct link_socket_info *info) { 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; } @@ -1618,29 +1637,69 @@ socket_listen_event_handle (struct link_socket *s) */ 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]"; } /* @@ -1667,7 +1726,7 @@ print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena *gc) /* 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]; @@ -1677,13 +1736,13 @@ setenv_sockaddr (struct env_set *es, const char *name_prefix, const struct socka 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)); } } @@ -1692,13 +1751,22 @@ setenv_in_addr_t (struct env_set *es, const char *name_prefix, in_addr_t addr, c { 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. */ @@ -1828,19 +1896,72 @@ link_socket_read_tcp (struct link_socket *sock, #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; } @@ -1853,7 +1974,7 @@ link_socket_read_udp_posix (struct link_socket *sock, 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); @@ -1867,6 +1988,41 @@ link_socket_write_tcp (struct link_socket *sock, #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. */ @@ -1981,7 +2137,7 @@ socket_recv_queue (struct link_socket *sock, int maxsize) } 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) { @@ -2005,7 +2161,7 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct so { /* 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( @@ -2081,11 +2237,10 @@ socket_send_queue (struct link_socket *sock, struct buffer *buf, const struct so } 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; @@ -2162,10 +2317,10 @@ socket_finalize ( { 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) diff --git a/socket.h b/socket.h index 4efcfcf..b73f763 100644 --- a/socket.h +++ b/socket.h @@ -77,12 +77,29 @@ typedef uint16_t packet_size_type; /* 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 @@ -180,7 +197,8 @@ struct link_socket 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 */ @@ -196,7 +214,7 @@ struct link_socket #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) @@ -232,13 +250,13 @@ int socket_recv_queue (struct link_socket *sock, int maxsize); 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 @@ -286,23 +304,34 @@ void link_socket_init_phase2 (struct link_socket *sock, 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); @@ -311,7 +340,7 @@ const char *print_in_addr_t (in_addr_t addr, unsigned int flags, struct gc_arena #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, @@ -319,19 +348,24 @@ 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); @@ -355,7 +389,7 @@ int openvpn_inet_aton (const char *dotted_quad, struct in_addr *addr); 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); /* @@ -447,33 +481,39 @@ link_socket_connection_oriented (const struct link_socket *sock) } 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) @@ -481,6 +521,12 @@ addr_match_proto (const struct sockaddr_in *a1, : 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) { @@ -504,17 +550,17 @@ 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; @@ -523,21 +569,18 @@ link_socket_verify_incoming_addr (struct buffer *buf, 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; } } } @@ -545,7 +588,7 @@ link_socket_get_outgoing_addr (struct buffer *buf, 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) { @@ -555,14 +598,14 @@ link_socket_set_outgoing_addr (const struct buffer *buf, 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); } } } @@ -599,7 +642,7 @@ int link_socket_read_tcp (struct link_socket *sock, 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); } @@ -609,7 +652,7 @@ link_socket_read_udp_win32 (struct link_socket *sock, 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 @@ -618,7 +661,7 @@ static inline int 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) { @@ -634,7 +677,7 @@ link_socket_read (struct link_socket *sock, 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 @@ -650,14 +693,14 @@ link_socket_read (struct link_socket *sock, 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; @@ -682,17 +725,26 @@ link_socket_write_win32 (struct link_socket *sock, 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); } @@ -702,7 +754,7 @@ link_socket_write_tcp_posix (struct link_socket *sock, 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); @@ -715,7 +767,7 @@ link_socket_write_udp (struct link_socket *sock, 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) { diff --git a/socks.c b/socks.c index 22bdfa4..66cf209 100644 --- a/socks.c +++ b/socks.c @@ -148,7 +148,8 @@ socks_handshake (socket_descriptor_t sd, volatile int *signal_received) } 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'; @@ -159,9 +160,9 @@ recv_socks_reply (socket_descriptor_t sd, struct sockaddr_in *addr, 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) @@ -248,8 +249,8 @@ recv_socks_reply (socket_descriptor_t sd, struct sockaddr_in *addr, /* 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)); } @@ -310,7 +311,7 @@ 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) { if (!socks_handshake (ctrl_sd, signal_received)) @@ -352,7 +353,7 @@ establish_socks_proxy_udpassoc (struct socks_proxy_info *p, */ void socks_process_incoming_udp (struct buffer *buf, - struct sockaddr_in *from) + struct link_socket_actual *from) { int atyp; @@ -367,8 +368,8 @@ socks_process_incoming_udp (struct buffer *buf, 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; @@ -385,7 +386,7 @@ socks_process_incoming_udp (struct buffer *buf, */ 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 -- @@ -400,8 +401,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->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; } diff --git a/socks.h b/socks.h index 12958b8..3d3f067 100644 --- a/socks.h +++ b/socks.h @@ -34,6 +34,9 @@ #include "buffer.h" +struct openvpn_sockaddr; +struct link_socket_actual; + struct socks_proxy_info { bool defined; bool retry; @@ -58,14 +61,14 @@ void establish_socks_proxy_passthru (struct socks_proxy_info *p, 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 diff --git a/ssl.c b/ssl.c index 60516a8..2d65d82 100644 --- a/ssl.c +++ b/ssl.c @@ -374,7 +374,7 @@ extract_x509_field (const char *x509, const char *field_name, char *out, int siz 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 @@ -1860,7 +1860,7 @@ 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) @@ -1868,7 +1868,7 @@ write_control_auth (struct tls_session *session, 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)); @@ -1880,7 +1880,7 @@ write_control_auth (struct tls_session *session, 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; } /* @@ -1889,7 +1889,7 @@ write_control_auth (struct tls_session *session, 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 (); @@ -1902,7 +1902,7 @@ read_control_auth (struct buffer *buf, { 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; } @@ -1914,7 +1914,7 @@ read_control_auth (struct buffer *buf, { 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; } @@ -2803,7 +2803,7 @@ static bool 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) { @@ -3197,7 +3197,7 @@ error: 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) { @@ -3223,7 +3223,7 @@ tls_multi_process (struct tls_multi *multi, /* 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, @@ -3232,16 +3232,29 @@ tls_multi_process (struct tls_multi *multi, 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. @@ -3361,7 +3374,7 @@ tls_multi_process (struct tls_multi *multi, 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) { @@ -3403,7 +3416,7 @@ tls_pre_decrypt (struct tls_multi *multi, 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; @@ -3416,7 +3429,7 @@ tls_pre_decrypt (struct tls_multi *multi, 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; } @@ -3429,14 +3442,14 @@ tls_pre_decrypt (struct tls_multi *multi, 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 */ @@ -3450,7 +3463,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; } @@ -3465,7 +3478,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; } } @@ -3474,7 +3487,7 @@ tls_pre_decrypt (struct tls_multi *multi, * 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 */ { @@ -3484,7 +3497,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; } } @@ -3501,9 +3514,9 @@ tls_pre_decrypt (struct tls_multi *multi, 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 */ @@ -3548,7 +3561,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; } @@ -3564,13 +3577,13 @@ tls_pre_decrypt (struct tls_multi *multi, 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; } } @@ -3590,7 +3603,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; } @@ -3613,11 +3626,11 @@ tls_pre_decrypt (struct tls_multi *multi, */ 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 { @@ -3631,7 +3644,7 @@ tls_pre_decrypt (struct tls_multi *multi, { 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; @@ -3640,10 +3653,10 @@ tls_pre_decrypt (struct tls_multi *multi, /* * 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; } @@ -3705,11 +3718,11 @@ tls_pre_decrypt (struct tls_multi *multi, 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; } @@ -3807,8 +3820,9 @@ tls_pre_decrypt (struct tls_multi *multi, */ 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; @@ -3835,7 +3849,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, */ 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; } @@ -3845,7 +3859,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, 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; } @@ -3854,7 +3868,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, 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; } diff --git a/ssl.h b/ssl.h index 77c2e73..0e41690 100644 --- a/ssl.h +++ b/ssl.h @@ -344,8 +344,8 @@ struct key_state 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 */ @@ -488,7 +488,7 @@ struct tls_session 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]; }; @@ -534,6 +534,12 @@ struct tls_multi */ 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. */ @@ -590,19 +596,19 @@ void tls_multi_init_set_options(struct tls_multi* multi, 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, diff --git a/syshead.h b/syshead.h index e354ef4..a786e65 100644 --- a/syshead.h +++ b/syshead.h @@ -309,6 +309,15 @@ #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 */ -- cgit v1.2.3