mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
dco: backport OS-independent part of peer float support
This is a backport of commitcb8a0f6f57, which introduces float support for DCO linux, Windows, and the OS-independent parts. DCO linux/windows in 2.6 has no float support kernel-side, so this ignores all OS dependent parts, backporting just enough to add FreeBSD support in the next patch. One notable difference in the backport is that 2.6 has no multi-socket support, so all the "link_sockets[0]" occurances need to be changed back to "link_socket". See https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=289303 for all the epic details... Change-Id: Ib748e726eb84dcbe8a48b297d165dec80c0e578d Signed-off-by: Ralf Lici <ralf@mandelbit.com> Signed-off-by: Gert Doering <gert@greenie.muc.de> Acked-by: Ralf Lici <ralf@mandelbit.com> (cherry picked from commitcb8a0f6f57) Message-Id: <20250908081124.17933-1-gert@greenie.muc.de> URL: https://sourceforge.net/p/openvpn/mailman/message/59230454/ Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
8af210e49a
commit
b0b123b3a7
3 changed files with 73 additions and 0 deletions
|
|
@ -1234,6 +1234,41 @@ process_incoming_link(struct context *c)
|
|||
perf_pop();
|
||||
}
|
||||
|
||||
void
|
||||
extract_dco_float_peer_addr(const sa_family_t socket_family,
|
||||
struct openvpn_sockaddr *out_osaddr,
|
||||
const struct sockaddr *float_sa)
|
||||
{
|
||||
if (float_sa->sa_family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *float4 = (struct sockaddr_in *)float_sa;
|
||||
/* DCO treats IPv4-mapped IPv6 addresses as pure IPv4. However, on a
|
||||
* dual-stack socket, we need to preserve the mapping otherwise openvpn
|
||||
* will not be able to find the peer by its transport address.
|
||||
*/
|
||||
if (socket_family == AF_INET6)
|
||||
{
|
||||
out_osaddr->addr.in6.sin6_family = AF_INET6;
|
||||
out_osaddr->addr.in6.sin6_port = float4->sin_port;
|
||||
|
||||
memset(&out_osaddr->addr.in6.sin6_addr.s6_addr, 0, 10);
|
||||
out_osaddr->addr.in6.sin6_addr.s6_addr[10] = 0xff;
|
||||
out_osaddr->addr.in6.sin6_addr.s6_addr[11] = 0xff;
|
||||
memcpy(&out_osaddr->addr.in6.sin6_addr.s6_addr[12],
|
||||
&float4->sin_addr.s_addr, sizeof(in_addr_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&out_osaddr->addr.in4, float4, sizeof(struct sockaddr_in));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in6 *float6 = (struct sockaddr_in6 *)float_sa;
|
||||
memcpy(&out_osaddr->addr.in6, float6, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
process_incoming_dco(struct context *c)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -188,6 +188,21 @@ bool process_incoming_link_part1(struct context *c, struct link_socket_info *lsi
|
|||
*/
|
||||
void process_incoming_link_part2(struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf);
|
||||
|
||||
/**
|
||||
* Transfers \c float_sa data extracted from an incoming DCO
|
||||
* PEER_FLOAT_NTF to \c out_osaddr for later processing.
|
||||
*
|
||||
* @param socket_family - The address family of the socket
|
||||
* @param out_osaddr - openvpn_sockaddr struct that will be filled the new
|
||||
* address data
|
||||
* @param float_sa - The sockaddr struct containing the data received from the
|
||||
* DCO notification
|
||||
*/
|
||||
void
|
||||
extract_dco_float_peer_addr(sa_family_t socket_family,
|
||||
struct openvpn_sockaddr *out_osaddr,
|
||||
const struct sockaddr *float_sa);
|
||||
|
||||
/**
|
||||
* Write a packet to the external network interface.
|
||||
* @ingroup external_multiplexer
|
||||
|
|
|
|||
|
|
@ -3169,6 +3169,18 @@ multi_process_float(struct multi_context *m, struct multi_instance *mi)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* It doesn't make sense to let a peer float to the address it already
|
||||
* has, so we disallow it. This can happen if a DCO netlink notification
|
||||
* gets lost and we miss a floating step.
|
||||
*/
|
||||
if (m1->peer_id == m2->peer_id)
|
||||
{
|
||||
msg(M_WARN, "disallowing peer %" PRIu32 " (%s) from floating to "
|
||||
"its own address (%s)",
|
||||
m1->peer_id, tls_common_name(mi->context.c2.tls_multi, false),
|
||||
mroute_addr_print(&mi->real, &gc));
|
||||
goto done;
|
||||
}
|
||||
msg(D_MULTI_MEDIUM, "closing instance %s", multi_instance_string(ex_mi, false, &gc));
|
||||
multi_close_instance(m, ex_mi, false);
|
||||
}
|
||||
|
|
@ -3301,6 +3313,17 @@ multi_process_incoming_dco(struct multi_context *m)
|
|||
{
|
||||
process_incoming_del_peer(m, mi, dco);
|
||||
}
|
||||
#if 0
|
||||
else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER)
|
||||
{
|
||||
ASSERT(mi->context.c2.link_socket);
|
||||
extract_dco_float_peer_addr(mi->context.c2.link_socket->info.af,
|
||||
&m->top.c2.from.dest,
|
||||
(struct sockaddr *)&dco->dco_float_peer_ss);
|
||||
multi_process_float(m, mi);
|
||||
CLEAR(dco->dco_float_peer_ss);
|
||||
}
|
||||
#endif /* if defined(TARGET_LINUX) || defined(TARGET_WIN32) */
|
||||
else if (dco->dco_message_type == OVPN_CMD_SWAP_KEYS)
|
||||
{
|
||||
tls_session_soft_reset(mi->context.c2.tls_multi);
|
||||
|
|
|
|||
Loading…
Reference in a new issue