From: ralf_lici (C. Review) <ge...@op...> - 2025-07-14 09:45:38
|
Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos, flichtenheld, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to review the following change. Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 154 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/1 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..7a5dfc5 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,40 @@ perf_pop(); } +bool +extract_dco_float_peer_addr(const uint32_t peer_id, + 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, we need + * to preserve the mapping, otherwise openvpn will not be able to find + * the peer by its trasnport address. + */ + if (out_osaddr->addr.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&out_osaddr->addr.in6.sin6_addr)) + { + memcpy(&out_osaddr->addr.in6.sin6_addr.s6_addr[12], + &float4->sin_addr.s_addr, sizeof(in_addr_t)); + out_osaddr->addr.in6.sin6_port = float4->sin_port; + } + else + { + memcpy(&out_osaddr->addr.in4, float4, sizeof(struct sockaddr_in)); + } + return true; + } + else if (float_sa->sa_family == AF_INET6) + { + struct sockaddr_in6 *float6 = (struct sockaddr_in6 *)float_sa; + memcpy(&out_osaddr->addr.in6, float6, sizeof(struct sockaddr_in6)); + return true; + } + return false; +} + static void process_incoming_dco(struct context *c) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..32c8113 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,22 @@ 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 peer_id - The id of the floating peer. + * @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 + * + * @return true if \c float_sa has a valid address family, false otherwise + */ +bool +extract_dco_float_peer_addr(uint32_t peer_id, struct openvpn_sockaddr *out_osaddr, + const struct sockaddr *float_sa); + +/** * Write a packet to the external network interface. * @ingroup external_multiplexer * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..2375c48 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,24 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss)) + { + ASSERT(mi->context.c2.link_sockets[0]); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + } + else + { + msg(D_DCO_DEBUG, "Received DCO float message with incorrect " + "address family %hu for peer-id %d", + dco->dco_float_peer_ss.ss_family, peer_id); + } + CLEAR(dco->dco_float_peer_ss); + } +#endif /* if defined(TARGET_LINUX) */ else if (dco->dco_message_type == OVPN_CMD_SWAP_KEYS) { tls_session_soft_reset(mi->context.c2.tls_multi); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-MessageType: newchange |
From: stipa (C. Review) <ge...@op...> - 2025-07-15 14:21:55
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici. stipa has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 1: (1 comment) File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/d4327cbe_dc45f82d : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, Do we really need this "if"? Could we trust the kernel and just assert inside `extract_dco_float_peer_addr` on incorrect AF? -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Comment-Date: Tue, 15 Jul 2025 14:21:46 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment |
From: ordex (C. Review) <ge...@op...> - 2025-07-15 14:23:16
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa. ordex has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 1: Code-Review+2 (2 comments) Patchset: PS1: looks good to me File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/febbeba3_6cfc1fdf : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, > Do we really need this "if"? Could we trust the kernel and just assert inside `extract_dco_float_pee […] no, we can't trust the kernel. when talking to an external component we can't just assume it will always do the right thing. A bug in the kernel code should not crash userspace. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Tue, 15 Jul 2025 14:23:00 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-15 15:36:59
|
Attention is currently required from: flichtenheld, ordex, plaisthos, stipa. ralf_lici has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 1: (1 comment) File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/347abf04_7c9f0c38 : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, > no, we can't trust the kernel. […] This isn’t actually a parsing of the kernel message, but rather a utility function to transpose the content of dco_float_peer_ss into m->top.c2.from.dest. Since dco_float_peer_ss is constructed by parsing the kernel notification, it would never contain an incorrect address family, thanks to a specific check in the Linux parser (ovpn_parse_float_addr()). OTOH, on Windows, we simply receive the sockaddr object from the kernel (if my understanding is correct), though I assume there’s a similar check in dco-win. So this 'if' statement is probably redundant on Linux but might act as the missing userspace check for Windows. But if you'd rather use an assert (since dco_float_peer_ss should never be ill-formed once we reach this point) we could add a check in dco_handle_overlapped_success() (or somewhere else in the dco_win-specific code) just to be safe. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Tue, 15 Jul 2025 15:36:44 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: ordex <an...@ma...> Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
From: stipa (C. Review) <ge...@op...> - 2025-07-16 08:00:57
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici. stipa has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 1: (1 comment) File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/e60039a2_6836322f : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, > This isn’t actually a parsing of the kernel message, but rather a utility function to transpose the […] Yeah I would trust the kernel on Windows and add an assert to dco_handle_overlapped_success(). I think this would make the logic more simple. I could send you the diff and you could squash it into this patch. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Comment-Date: Wed, 16 Jul 2025 08:00:41 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: ordex <an...@ma...> Comment-In-Reply-To: ralf_lici <ra...@ma...> Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
From: stipa (C. Review) <ge...@op...> - 2025-07-16 08:31:54
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici. stipa has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 1: (1 comment) File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/32317b9e_d8a2c183 : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, > Yeah I would trust the kernel on Windows and add an assert to dco_handle_overlapped_success(). […] after discussion on IRC we decided just to remove this "if" and not to add an assert - we'll get a error later in an improbable cause if dco-win returns invalid AF. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 1 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Comment-Date: Wed, 16 Jul 2025 08:31:39 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: ordex <an...@ma...> Comment-In-Reply-To: ralf_lici <ra...@ma...> Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-16 08:56:09
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici. Hello flichtenheld, ordex, plaisthos, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to look at the new patch set (#2). The following approvals got outdated and were removed: Code-Review+2 by ordex Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 142 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/2 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..0b4ceae 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,37 @@ perf_pop(); } +void +extract_dco_float_peer_addr(const uint32_t peer_id, + 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, we need + * to preserve the mapping, otherwise openvpn will not be able to find + * the peer by its trasnport address. + */ + if (out_osaddr->addr.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&out_osaddr->addr.in6.sin6_addr)) + { + memcpy(&out_osaddr->addr.in6.sin6_addr.s6_addr[12], + &float4->sin_addr.s_addr, sizeof(in_addr_t)); + out_osaddr->addr.in6.sin6_port = float4->sin_port; + } + 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..4f3d81e 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 peer_id - The id of the floating peer. + * @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(uint32_t peer_id, struct openvpn_sockaddr *out_osaddr, + const struct sockaddr *float_sa); + +/** * Write a packet to the external network interface. * @ingroup external_multiplexer * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..e5b817d 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,16 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, + (struct sockaddr*)&dco->dco_float_peer_ss); + ASSERT(mi->context.c2.link_sockets[0]); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 2 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-MessageType: newpatchset |
From: ordex (C. Review) <ge...@op...> - 2025-07-16 08:56:41
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici. ordex has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 2 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Comment-Date: Wed, 16 Jul 2025 08:56:31 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-16 08:56:51
|
Attention is currently required from: flichtenheld, plaisthos, stipa. ralf_lici has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 2: (1 comment) File src/openvpn/multi.c: http://gerrit.openvpn.net/c/openvpn/+/1084/comment/ec73084a_1fed51b8 : PS1, Line 3390: if (extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, > after discussion on IRC we decided just to remove this "if" and not to add an assert - we'll get a e […] Done -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 2 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-CC: stipa <lst...@gm...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Wed, 16 Jul 2025 08:56:42 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: ordex <an...@ma...> Comment-In-Reply-To: ralf_lici <ra...@ma...> Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
From: stipa (C. Review) <ge...@op...> - 2025-07-16 08:59:31
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici. stipa has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 2 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Comment-Date: Wed, 16 Jul 2025 08:59:22 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-16 09:42:53
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici, stipa. Hello flichtenheld, ordex, plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to look at the new patch set (#3). The following approvals got outdated and were removed: Code-Review+2 by ordex, Code-Review+2 by stipa Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 142 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/3 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..0b4ceae 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,37 @@ perf_pop(); } +void +extract_dco_float_peer_addr(const uint32_t peer_id, + 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, we need + * to preserve the mapping, otherwise openvpn will not be able to find + * the peer by its trasnport address. + */ + if (out_osaddr->addr.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&out_osaddr->addr.in6.sin6_addr)) + { + memcpy(&out_osaddr->addr.in6.sin6_addr.s6_addr[12], + &float4->sin_addr.s_addr, sizeof(in_addr_t)); + out_osaddr->addr.in6.sin6_port = float4->sin_port; + } + 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..4f3d81e 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 peer_id - The id of the floating peer. + * @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(uint32_t peer_id, struct openvpn_sockaddr *out_osaddr, + const struct sockaddr *float_sa); + +/** * Write a packet to the external network interface. * @ingroup external_multiplexer * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..5030faa 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,16 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + ASSERT(mi->context.c2.link_sockets[0]); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 3 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
From: ordex (C. Review) <ge...@op...> - 2025-07-16 09:44:04
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa. ordex has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 3: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 3 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Wed, 16 Jul 2025 09:43:49 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: Gert D. <ge...@gr...> - 2025-07-16 16:29:31
|
From: Ralf Lici <ra...@ma...> When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> Acked-by: Antonio Quartulli <an...@ma...> --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1084 This mail reflects revision 3 of this Change. Acked-by according to Gerrit (reflected above): Antonio Quartulli <an...@ma...> diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..0b4ceae 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,37 @@ perf_pop(); } +void +extract_dco_float_peer_addr(const uint32_t peer_id, + 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, we need + * to preserve the mapping, otherwise openvpn will not be able to find + * the peer by its trasnport address. + */ + if (out_osaddr->addr.sa.sa_family == AF_INET6 + && IN6_IS_ADDR_V4MAPPED(&out_osaddr->addr.in6.sin6_addr)) + { + memcpy(&out_osaddr->addr.in6.sin6_addr.s6_addr[12], + &float4->sin_addr.s_addr, sizeof(in_addr_t)); + out_osaddr->addr.in6.sin6_port = float4->sin_port; + } + 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..4f3d81e 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 peer_id - The id of the floating peer. + * @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(uint32_t peer_id, struct openvpn_sockaddr *out_osaddr, + const struct sockaddr *float_sa); + +/** * Write a packet to the external network interface. * @ingroup external_multiplexer * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..5030faa 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,16 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + extract_dco_float_peer_addr(peer_id, &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + ASSERT(mi->context.c2.link_sockets[0]); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { |
From: cron2 (C. Review) <ge...@op...> - 2025-07-17 15:54:45
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 3: Code-Review-1 (1 comment) Patchset: PS3: *b00m* so this is the testbed: ununtu 20.04 server with backported float notification patch, commit 31aedd7fb plus this patch. one server instance, with 2 UDP sockets (one udp6/dual-stack, one udp4 only). Client connecting to the UDP4 socket (so v6 mapped is not relevant). Server has --reneg-sec 60, and in between renegotiations the client is made to roam between LAN and WiFi (by unplugging and replugging the LAN cable). It floats quite happily, and then explodes - it's something with timing, float, and server-triggered renegotiation, though I do not really know what sequence of things I need. `peer-id 2` is the floating client, `peer-id 1` is just sticking around. ``` 2025-07-17 17:45:32 us=32787 freebsd-74-amd64/udp6:194.97.140.3:61704 peer-id=1 Control Channel: TLSv1.2, cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384, 2048 bit key 2025-07-17 17:45:32 us=32932 freebsd-74-amd64/udp6:194.97.140.3:61704 peer-id=1 dco_install_key: peer_id=1 keyid=6, currently 1 keys installed 2025-07-17 17:45:32 us=32963 freebsd-74-amd64/udp6:194.97.140.3:61704 peer-id=1 dco_new_key: slot 1, key-id 6, peer-id 1, cipher AES-256-GCM 2025-07-17 17:45:32 us=658862 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 Swapping primary and secondary keys to primary-id=6 secondary-id=5 2025-07-17 17:45:32 us=658933 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 dco_swap_keys: peer-id 2 2025-07-17 17:45:59 us=350653 dco_do_read 2025-07-17 17:45:59 us=350790 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5501, peer-id 2, address: [AF_INET]193.149.48.173:63385 2025-07-17 17:45:59 us=350937 peer 2 (cron2-freebsd-tc-amd64) floated from udp4:193.149.48.172:63385 to [AF_INET6]::ffff:193.149.48.173:63385 (via ::ffff:195.30.8.84%ens160) 2025-07-17 17:46:02 us=32434 cron2-freebsd-tc-amd64/udp6:193.149.48.173:63385 peer-id=2 TLS: soft reset sec=60/59 bytes=0/-1 pkts=0/0 aead_limit_send=0/60129542137 aead_limit_recv=0/60129542137 2025-07-17 17:46:02 us=32639 cron2-freebsd-tc-amd64/udp6:193.149.48.173:63385 peer-id=2 dco_del_key: peer-id 2, slot 1 2025-07-17 17:46:02 us=32911 cron2-freebsd-tc-amd64/udp6:193.149.48.173:63385 peer-id=2 UDPv4 WRITE [54] to [AF_INET6]::ffff:193.149.48.173:63385 (via ::ffff:195.30.8.84%ens160): P_CONTROL_SOFT_RESET_V1 kid=7 [ ] pid=12648 DATA len=40 2025-07-17 17:46:02 us=32981 cron2-freebsd-tc-amd64/udp6:193.149.48.173:63385 peer-id=2 write UDPv4 []: Address family not supported by protocol (fd=7,code=97) 2025-07-17 17:46:02 us=352420 dco_do_read 2025-07-17 17:46:02 us=352549 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5501, peer-id 2, address: [AF_INET]193.149.48.172:63385 2025-07-17 17:46:02 us=352705 peer 2 (cron2-freebsd-tc-amd64) floated from udp6:193.149.48.173:63385 to [AF_INET6]::ffff:193.149.48.172:63385 (via ::ffff:195.30.8.84%ens160) 2025-07-17 17:46:02 us=529069 freebsd-74-amd64/udp6:194.97.140.3:61704 peer-id=1 Swapping primary and secondary keys to primary-id=6 secondary-id=5 2025-07-17 17:46:02 us=529153 freebsd-74-amd64/udp6:194.97.140.3:61704 peer-id=1 dco_swap_keys: peer-id 1 2025-07-17 17:46:04 us=286241 cron2-freebsd-tc-amd64/udp6:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [54] to [AF_INET6]::ffff:193.149.48.172:63385 (via ::ffff:195.30.8.84%ens160): P_CONTROL_SOFT_RESET_V1 kid=7 [ ] pid=12904 DATA len=40 2025-07-17 17:46:04 us=286325 cron2-freebsd-tc-amd64/udp6:193.149.48.172:63385 peer-id=2 write UDPv4 []: Address family not supported by protocol (fd=7,code=97) 2025-07-17 17:46:05 us=364294 dco_get_peer_stats_multi 2025-07-17 17:46:05 us=364768 dco_parse_peer_multi: parsing message... 2025-07-17 17:46:05 us=364822 dco_update_peer_stat: no link RX bytes provided in reply for peer 2 2025-07-17 17:46:05 us=364854 dco_update_peer_stat: no link TX bytes provided in reply for peer 2 2025-07-17 17:46:05 us=364913 dco_update_peer_stat: no VPN RX bytes provided in reply for peer 2 2025-07-17 17:46:05 us=364931 dco_update_peer_stat: no VPN TX bytes provided in reply for peer 2 2025-07-17 17:46:05 us=364994 dco_parse_peer_multi: parsing message... 2025-07-17 17:46:05 us=365028 dco_update_peer_stat / dco_read_bytes: 1648 2025-07-17 17:46:05 us=365057 dco_update_peer_stat / dco_write_bytes: 1440 2025-07-17 17:46:05 us=365103 dco_update_peer_stat / tun_read_bytes: 0 2025-07-17 17:46:05 us=365129 dco_update_peer_stat / tun_write_bytes: 0 2025-07-17 17:46:05 us=365145 dco_parse_peer_multi: parsing message... 2025-07-17 17:46:05 us=365180 dco_update_peer_stat / dco_read_bytes: 53648 2025-07-17 17:46:05 us=365208 dco_update_peer_stat / dco_write_bytes: 53248 2025-07-17 17:46:05 us=365269 dco_update_peer_stat / tun_read_bytes: 43264 2025-07-17 17:46:05 us=365304 dco_update_peer_stat / tun_write_bytes: 43264 2025-07-17 17:46:05 us=366195 dco_do_read 2025-07-17 17:46:05 us=366301 dco_do_read: netlink reports error (-4): Try again 2025-07-17 17:46:08 us=370284 dco_do_read 2025-07-17 17:46:08 us=370355 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5501, peer-id 2, address: [AF_INET]193.149.48.172:63385 2025-07-17 17:46:08 us=370416 closing instance cron2-freebsd-tc-amd64/udp6:193.149.48.172:63385 peer-id=2 2025-07-17 17:46:08 us=370469 dco_get_peer_stats_multi 2025-07-17 17:46:08 us=370666 dco_parse_peer_multi: parsing message... 2025-07-17 17:46:08 us=370811 dco_update_peer_stat / dco_read_bytes: 1648 2025-07-17 17:46:08 us=370856 dco_update_peer_stat / dco_write_bytes: 1440 2025-07-17 17:46:08 us=370887 dco_update_peer_stat / tun_read_bytes: 0 2025-07-17 17:46:08 us=370918 dco_update_peer_stat / tun_write_bytes: 0 2025-07-17 17:46:08 us=371212 dco_parse_peer_multi: parsing message... 2025-07-17 17:46:08 us=371249 dco_parse_peer_multi: cannot store DCO stats for peer 2 2025-07-17 17:46:08 us=371410 register signal: SIGTERM (close_context) 2025-07-17 17:46:08 us=371534 dco_del_peer: peer-id 2 ``` (why does it want to close peer 2? so something went fishy already at this point) ``` Program received signal SIGSEGV, Segmentation fault. 0x00005555555989b3 in multi_process_float (m=m@entry=0x7fffffffbb90, mi=mi@entry=0x555555772a70, sock=0x5555556c7a20) at multi.c:3258 3258 msg(D_MULTI_MEDIUM, "peer %" PRIu32 " (%s) floated from %s to %s", (gdb) where #0 0x00005555555989b3 in multi_process_float (m=m@entry=0x7fffffffbb90, mi=mi@entry=0x555555772a70, sock=0x5555556c7a20) at multi.c:3258 #1 0x0000555555598f53 in multi_process_incoming_dco (m=m@entry=0x7fffffffbb90) at multi.c:3393 #2 0x000055555559d7e0 in multi_io_process_io (m=m@entry=0x7fffffffbb90) at multi_io.c:534 #3 0x000055555559c740 in tunnel_server_loop (multi=0x7fffffffbb90) at multi.c:4287 #4 tunnel_server (top=0x7fffffffd0c0) at multi.c:4339 #5 0x00005555555a1f29 in openvpn_main (argc=5, argv=0x7fffffffe598) at openvpn.c:318 #6 0x00007ffff7d72083 in __libc_start_main (main=0x55555555fb70 <main>, argc=5, argv=0x7fffffffe598, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe588) at ../csu/libc-start.c:308 #7 0x000055555555fbae in _start () at openvpn.c:395 (gdb) list 3253 3254 msg(D_MULTI_MEDIUM, "closing instance %s", multi_instance_string(ex_mi, false, &gc)); 3255 multi_close_instance(m, ex_mi, false); 3256 } 3257 3258 msg(D_MULTI_MEDIUM, "peer %" PRIu32 " (%s) floated from %s to %s", 3259 mi->context.c2.tls_multi->peer_id, 3260 tls_common_name(mi->context.c2.tls_multi, false), 3261 mroute_addr_print(&mi->real, &gc), 3262 print_link_socket_actual(&m->top.c2.from, &gc)); (gdb) print mi->context.c2.tls_multi $1 = (struct tls_multi *) 0x0 ``` the kernel log around that time says ``` Jul 17 17:46:01 ubuntu2004 kernel: [3570425.002983] tun7: peer 2 floated to 193.149.48.173:63385 Jul 17 17:46:01 ubuntu2004 kernel: [3570426.825096] tun7: sending keepalive to peer 1 Jul 17 17:46:01 ubuntu2004 kernel: [3570426.825119] tun7: scheduling keepalive work: now=1752767170 next_run=1752767161 delta=9 Jul 17 17:46:02 ubuntu2004 kernel: [3570427.685495] deleting key slot 1, key_id=5 Jul 17 17:46:02 ubuntu2004 kernel: [3570428.004618] tun7: peer 2 floated to 193.149.48.172:63385 Jul 17 17:46:02 ubuntu2004 kernel: [3570428.182001] key swapped: (old primary) 5 <-> (new primary) 6 Jul 17 17:46:03 ubuntu2004 kernel: [3570429.235584] tun7: ping received from peer 1 Jul 17 17:46:08 ubuntu2004 kernel: [3570431.015784] tun7: peer 2 floated to 193.149.48.173:63385 Jul 17 17:46:08 ubuntu2004 kernel: [3570434.022364] tun7: peer 2 floated to 193.149.48.172:63385 Jul 17 17:46:08 ubuntu2004 kernel: [3570434.024151] tun7: del peer 2 Jul 17 17:46:08 ubuntu2004 kernel: [3570434.024169] tun7: deleting peer with id 2, reason 1 Jul 17 17:46:10 ubuntu2004 kernel: [3570436.040898] tun7: scheduling keepalive work: now=1752767171 next_run=1752767170 delta=1 Jul 17 17:46:11 ubuntu2004 kernel: [3570437.064852] tun7: sending keepalive to peer 1 ``` -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 3 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Thu, 17 Jul 2025 15:54:28 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: cron2 (C. Review) <ge...@op...> - 2025-07-17 16:02:46
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 3: (1 comment) Patchset: PS3: so here's the last successful TLS reneg, one minute earlier ``` 2025-07-17 17:45:02 us=482995 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 TLS: soft reset sec=59/59 bytes=0/-1 pkts=0/0 aead_limit_send=0/60129542137 aead_limit_recv=0/60129542137 2025-07-17 17:45:02 us=483272 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 dco_del_key: peer-id 2, slot 1 2025-07-17 17:45:02 us=483585 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [54] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_SOFT_RESET_V1 kid=6 [ ] pid=10600 DATA len=40 2025-07-17 17:45:02 us=490075 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [66] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_SOFT_RESET_V1 kid=6 [ ] pid=10600 DATA len=52 2025-07-17 17:45:02 us=490260 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [62] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_ACK_V1 kid=6 [ ] DATA len=52 2025-07-17 17:45:02 us=495340 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [355] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=10856 DATA len=341 2025-07-17 17:45:02 us=505576 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [1262] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=11112 DATA len=1248 2025-07-17 17:45:02 us=505746 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [923] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=11368 DATA len=909 2025-07-17 17:45:02 us=510213 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [66] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_ACK_V1 kid=6 [ ] DATA len=56 2025-07-17 17:45:02 us=519114 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [1262] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=11368 DATA len=1248 2025-07-17 17:45:02 us=519243 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [70] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_ACK_V1 kid=6 [ ] DATA len=60 2025-07-17 17:45:02 us=519353 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [1262] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=11624 DATA len=1248 2025-07-17 17:45:02 us=519471 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [74] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_ACK_V1 kid=6 [ ] DATA len=64 2025-07-17 17:45:02 us=519586 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [753] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=11880 DATA len=739 2025-07-17 17:45:02 us=519991 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 VERIFY OK: depth=1, C=US, ST=California, L=Pleasanton, O=OpenVPN community project, CN=OpenVPN community project CA, emailAddress=sa...@op... 2025-07-17 17:45:02 us=520144 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 VERIFY OK: depth=0, C=DE, ST=Bavaria, L=Munich, O=OpenVPN community project, OU=Server Testing, CN=cron2-freebsd-tc-amd64, emailAddress=ge...@gr... 2025-07-17 17:45:02 us=525244 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [121] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=12136 DATA len=107 2025-07-17 17:45:02 us=530446 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [525] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=12136 DATA len=511 2025-07-17 17:45:02 us=530543 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_VER=2.7_alpha2 2025-07-17 17:45:02 us=530583 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_PLAT=mac 2025-07-17 17:45:02 us=530619 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_TCPNL=1 2025-07-17 17:45:02 us=530646 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_MTU=1600 2025-07-17 17:45:02 us=530666 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_NCP=2 2025-07-17 17:45:02 us=530687 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_CIPHERS=AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305 2025-07-17 17:45:02 us=530705 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_PROTO=3998 2025-07-17 17:45:02 us=530726 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_LZ4=1 2025-07-17 17:45:02 us=530755 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_LZ4v2=1 2025-07-17 17:45:02 us=530779 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_LZO=1 2025-07-17 17:45:02 us=530801 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_COMP_STUB=1 2025-07-17 17:45:02 us=530821 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 peer info: IV_COMP_STUBv2=1 2025-07-17 17:45:02 us=530859 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 Note: 'compress migrate' detected remote peer with compression enabled. 2025-07-17 17:45:02 us=531008 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 WRITE [286] to [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_CONTROL_V1 kid=6 [ ] pid=12392 DATA len=272 2025-07-17 17:45:02 us=535798 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 UDPv4 READ [78] from [AF_INET]193.149.48.172:63385 (via [AF_INET]195.30.8.84%ens160): P_ACK_V1 kid=6 [ ] DATA len=68 2025-07-17 17:45:02 us=535906 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 Control Channel: TLSv1.2, cipher TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256, 2048 bit key 2025-07-17 17:45:02 us=536025 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 dco_install_key: peer_id=2 keyid=6, currently 1 keys installed 2025-07-17 17:45:02 us=536058 cron2-freebsd-tc-amd64/udp4:193.149.48.172:63385 peer-id=2 dco_new_key: slot 1, key-id 6, peer-id 2, cipher AES-256-GCM 2025-07-17 17:45:05 us=707606 dco_get_peer_stats_multi 2025-07-17 17:45:05 us=707964 dco_parse_peer_multi: parsing message... 2025-07-17 17:45:05 us=707999 dco_update_peer_stat / dco_read_bytes: 1408 2025-07-17 17:45:05 us=708017 dco_update_peer_stat / dco_write_bytes: 1200 2025-07-17 17:45:05 us=708032 dco_update_peer_stat / tun_read_bytes: 0 2025-07-17 17:45:05 us=708051 dco_update_peer_stat / tun_write_bytes: 0 2025-07-17 17:45:05 us=708071 dco_parse_peer_multi: parsing message... ``` -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 3 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Thu, 17 Jul 2025 16:02:30 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-17 20:10:20
|
Attention is currently required from: cron2, flichtenheld, ordex, plaisthos, ralf_lici, stipa. Hello cron2, flichtenheld, ordex, plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to look at the new patch set (#4). The following approvals got outdated and were removed: Code-Review+2 by ordex, Code-Review-1 by cron2 The change is no longer submittable: Code-Review and checks~ChecksSubmitRule are unsatisfied now. Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 148 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/4 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..18d2325 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,40 @@ perf_pop(); } +void +extract_dco_float_peer_addr(const uint32_t peer_id, + 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_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)); + out_osaddr->addr.in6.sin6_port = float4->sin_port; + } + 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..f835508 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,22 @@ 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 peer_id - The id of the floating peer. + * @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(uint32_t peer_id, 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..8cb8aee 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,18 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(peer_id, + mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 4 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: cron2 <ge...@gr...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-17 21:08:21
|
Attention is currently required from: cron2, flichtenheld, ordex, plaisthos, ralf_lici, stipa. Hello cron2, flichtenheld, ordex, plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to look at the new patch set (#5). Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 150 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/5 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..2ef9c2b0 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,42 @@ perf_pop(); } +void +extract_dco_float_peer_addr(const uint32_t peer_id, + 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..f835508 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,22 @@ 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 peer_id - The id of the floating peer. + * @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(uint32_t peer_id, 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..8cb8aee 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3384,6 +3384,18 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(peer_id, + mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 5 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: cron2 <ge...@gr...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
From: cron2 (C. Review) <ge...@op...> - 2025-07-18 08:40:02
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici, stipa. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 5: (1 comment) Patchset: PS5: So, it segfaulted again - which is a different bug than the AF_INET6 thing (which seems fixed). Not sure how to trigger it yet... I had 2 sockets, and 3 clients this time (something stable on the udp6 socket with peer-id 0 + 1, and the floating client on the udp4 socket with peer-id 2). It got confused again about "something", then tried to delete the peer, and segfaulted at the same place (race condition between userspace already having deleted half the peer info and then kernel sending up a message?) Trying to extract the interesting bits ``` 2025-07-18 10:32:39 us=870590 dco_do_read 2025-07-18 10:32:39 us=870769 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5651, peer-id 2, address: [AF_INET]193.149.48.173:62227 2025-07-18 10:32:39 us=870881 peer 2 (cron2-freebsd-tc-amd64) floated from udp4:193.149.48.172:62227 to [AF_INET]193.149.48.173:62227 2025-07-18 10:32:43 us=883102 dco_do_read 2025-07-18 10:32:43 us=883230 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5651, peer-id 2, address: [AF_INET]193.149.48.172:62227 2025-07-18 10:32:43 us=883293 peer 2 (cron2-freebsd-tc-amd64) floated from udp4:193.149.48.173:62227 to [AF_INET]193.149.48.172:62227 (everything fine) 2025-07-18 10:32:55 us=935486 dco_get_peer_stats_multi 2025-07-18 10:32:55 us=935798 dco_parse_peer_multi: parsing message... 2025-07-18 10:32:55 us=935851 dco_update_peer_stat: no link RX bytes provided in reply for peer 2 2025-07-18 10:32:55 us=935881 dco_update_peer_stat: no link TX bytes provided in reply for peer 2 2025-07-18 10:32:55 us=935900 dco_update_peer_stat: no VPN RX bytes provided in reply for peer 2 2025-07-18 10:32:55 us=935919 dco_update_peer_stat: no VPN TX bytes provided in reply for peer 2 2025-07-18 10:32:55 us=937904 dco_parse_peer_multi: parsing message... 2025-07-18 10:32:55 us=937991 dco_update_peer_stat / dco_read_bytes: 976 2025-07-18 10:32:55 us=938052 dco_update_peer_stat / dco_write_bytes: 440 2025-07-18 10:32:55 us=938098 dco_update_peer_stat / tun_read_bytes: 0 2025-07-18 10:32:55 us=938151 dco_update_peer_stat / tun_write_bytes: 0 2025-07-18 10:32:55 us=938212 dco_parse_peer_multi: parsing message... 2025-07-18 10:32:55 us=938270 dco_update_peer_stat / dco_read_bytes: 400 2025-07-18 10:32:55 us=938322 dco_update_peer_stat / dco_write_bytes: 440 2025-07-18 10:32:55 us=938366 dco_update_peer_stat / tun_read_bytes: 0 2025-07-18 10:32:55 us=938425 dco_update_peer_stat / tun_write_bytes: 0 2025-07-18 10:32:55 us=938483 dco_parse_peer_multi: parsing message... 2025-07-18 10:32:55 us=938535 dco_update_peer_stat / dco_read_bytes: 13840 2025-07-18 10:32:55 us=938579 dco_update_peer_stat / dco_write_bytes: 13440 2025-07-18 10:32:55 us=938638 dco_update_peer_stat / tun_read_bytes: 10920 2025-07-18 10:32:55 us=938695 dco_update_peer_stat / tun_write_bytes: 10920 2025-07-18 10:32:55 us=939599 dco_do_read 2025-07-18 10:32:55 us=939755 dco_do_read: netlink reports error (-4): Try again (this "no RX bytes for peer 2" is what I saw yesterday as well, and the "Try again") 2025-07-18 10:33:00 us=100235 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 TLS: soft reset sec=56/56 bytes=0/-1 pkts=0/0 aead_limit_send=0/60129542137 aead_limit_recv=0/60129542137 2025-07-18 10:33:00 us=100434 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 Sent warning SSL alert: close notify 2025-07-18 10:33:00 us=100719 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 dco_del_key: peer-id 2, slot 1 (this still looks normal, skipping the UDP read/write) 2025-07-18 10:33:00 us=132607 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 VERIFY OK: depth=1, C=US, ST=California, L=Pleasanton, O=OpenVPN community project, CN=OpenVPN community project CA, emailAddress=sa...@op... 2025-07-18 10:33:00 us=132851 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 VERIFY OK: depth=0, C=DE, ST=Bavaria, L=Munich, O=OpenVPN community project, OU=Server Testing, CN=cron2-freebsd-tc-amd64, emailAddress=ge...@gr... 2025-07-18 10:33:00 us=133145 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_VER=2.7_alpha2 2025-07-18 10:33:00 us=133198 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_PLAT=mac 2025-07-18 10:33:00 us=133238 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_TCPNL=1 2025-07-18 10:33:00 us=133283 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_MTU=1600 2025-07-18 10:33:00 us=133315 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_NCP=2 2025-07-18 10:33:00 us=133348 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_CIPHERS=AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305 2025-07-18 10:33:00 us=133385 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_PROTO=3998 2025-07-18 10:33:00 us=133418 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_LZ4=1 2025-07-18 10:33:00 us=133453 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_LZ4v2=1 2025-07-18 10:33:00 us=133487 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_LZO=1 2025-07-18 10:33:00 us=133521 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_COMP_STUB=1 2025-07-18 10:33:00 us=133553 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 peer info: IV_COMP_STUBv2=1 2025-07-18 10:33:00 us=133592 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 Note: 'compress migrate' detected remote peer with compression enabled. 2025-07-18 10:33:00 us=133743 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 UDPv4 WRITE [236] to [AF_INET]193.149.48.172:62227: P_CONTROL_V1 kid=2 [ ] pid=4456 DATA len=222 2025-07-18 10:33:00 us=133834 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 UDPv4 WRITE [287] to [AF_INET]193.149.48.172:62227: P_CONTROL_V1 kid=2 [ ] pid=4712 DATA len=273 2025-07-18 10:33:00 us=137204 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 UDPv4 READ [78] from [AF_INET]193.149.48.172:62227: P_ACK_V1 kid=2 [ ] DATA len=68 2025-07-18 10:33:00 us=140572 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 UDPv4 READ [82] from [AF_INET]193.149.48.172:62227: P_ACK_V1 kid=2 [ ] DATA len=72 2025-07-18 10:33:00 us=140640 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bits RSA, signature: RSA-SHA1, peer temporary key: 253 bits X25519, peer signing digest/type: SHA256 RSASSA-PSS 2025-07-18 10:33:00 us=140720 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 dco_install_key: peer_id=2 keyid=2, currently 1 keys installed 2025-07-18 10:33:00 us=140767 cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 dco_new_key: slot 1, key-id 2, peer-id 2, cipher AES-256-GCM 2025-07-18 10:33:00 us=951542 dco_do_read 2025-07-18 10:33:00 us=951670 ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: 5651, peer-id 2, address: [AF_INET]193.149.48.172:62227 2025-07-18 10:33:00 us=951736 closing instance cron2-freebsd-tc-amd64/udp4:193.149.48.172:62227 peer-id=2 2025-07-18 10:33:00 us=951806 dco_get_peer_stats_multi 2025-07-18 10:33:00 us=952053 dco_parse_peer_multi: parsing message... 2025-07-18 10:33:00 us=952099 dco_update_peer_stat / dco_read_bytes: 976 2025-07-18 10:33:00 us=952135 dco_update_peer_stat / dco_write_bytes: 440 2025-07-18 10:33:00 us=952169 dco_update_peer_stat / tun_read_bytes: 0 2025-07-18 10:33:00 us=952478 dco_update_peer_stat / tun_write_bytes: 0 2025-07-18 10:33:00 us=952541 dco_parse_peer_multi: parsing message... 2025-07-18 10:33:00 us=952580 dco_update_peer_stat / dco_read_bytes: 400 2025-07-18 10:33:00 us=952614 dco_update_peer_stat / dco_write_bytes: 440 2025-07-18 10:33:00 us=952663 dco_update_peer_stat / tun_read_bytes: 0 2025-07-18 10:33:00 us=952707 dco_update_peer_stat / tun_write_bytes: 0 2025-07-18 10:33:00 us=952754 dco_parse_peer_multi: parsing message... 2025-07-18 10:33:00 us=952791 dco_parse_peer_multi: cannot store DCO stats for peer 2 2025-07-18 10:33:00 us=952892 register signal: SIGTERM (close_context) 2025-07-18 10:33:00 us=952943 dco_del_peer: peer-id 2 2025-07-18 10:33:00 us=972424 Sent warning SSL alert: close notify 2025-07-18 10:33:00 us=972698 Sent warning SSL alert: close notify Program received signal SIGSEGV, Segmentation fault. 0x0000555555599ef3 in multi_process_float (m=m@entry=0x7fffffffbcc0, mi=mi@entry=0x5555556a2050, sock=0x55555564dbe0) at multi.c:3258 3258 msg(D_MULTI_MEDIUM, "peer %" PRIu32 " (%s) floated from %s to %s", (gdb) list 3253 3254 msg(D_MULTI_MEDIUM, "closing instance %s", multi_instance_string(ex_mi, false, &gc)); 3255 multi_close_instance(m, ex_mi, false); 3256 } 3257 3258 msg(D_MULTI_MEDIUM, "peer %" PRIu32 " (%s) floated from %s to %s", 3259 mi->context.c2.tls_multi->peer_id, 3260 tls_common_name(mi->context.c2.tls_multi, false), 3261 mroute_addr_print(&mi->real, &gc), 3262 print_link_socket_actual(&m->top.c2.from, &gc)); (gdb) print mi->context.c2.tls_multi $1 = (struct tls_multi *) 0x0 ``` -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 5 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Fri, 18 Jul 2025 08:39:45 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment |
From: ralf_lici (C. Review) <ge...@op...> - 2025-07-18 10:50:54
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici, stipa. Hello cron2, flichtenheld, ordex, plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email to look at the new patch set (#6). Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. It may happen that a netlink notification gets lost, causing us to skip a float step. If the peer then floats back to its previous address, userspace closes the only valid instance while trying to process the float, leading to a segfault. To prevent this, we ignore float attempts to an address already taken by a peer with the same peer ID. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 159 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/6 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..dfc6708 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,41 @@ 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..2818fd1 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..ead3dd0 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3251,6 +3251,18 @@ 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); } @@ -3384,6 +3396,17 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 6 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
From: Gert D. <ge...@gr...> - 2025-07-18 15:04:24
|
From: Ralf Lici <ra...@ma...> When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. It may happen that a netlink notification gets lost, causing us to skip a float step. If the peer then floats back to its previous address, userspace closes the only valid instance while trying to process the float, leading to a segfault. To prevent this, we ignore float attempts to an address already taken by a peer with the same peer ID. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> Acked-by: Gert Doering <ge...@gr...> --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1084 This mail reflects revision 6 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering <ge...@gr...> diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..dfc6708 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,41 @@ 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..2818fd1 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..ead3dd0 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3251,6 +3251,18 @@ 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); } @@ -3384,6 +3396,17 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { |
From: Gert D. <ge...@gr...> - 2025-07-18 15:49:57
|
So, this was quite a bit of work from the already-+2'ed v3 :-) The patch looks larger than it actually is, because it affects the two low level DCO modules implemented plus the "midlayer" having to update the peer address. Each individual change is fairly straightforward. I have stared at the code for quite a bit and everything looks reasonable and works (now). v3 had problems where it would apply the wrong logic to "does this v4 address need to be wrapped into a v6mapped v6 address?", so OpenVPN would end up trying to send v6 packets on a v4-only socket (no good), and also there is a race condition in the DCO message callback leading to lost DCO notification if the timing is just right (they are read by the "give me counters!" callback, which gets confused and just throws the notification away) - leading to "TLS packets get sent to the old address" and (worse) "on floating *back*, OpenVPN kills the current instance and then SIGSEGVs". The DCO notification race will be fixed by Antonio ASAP - it's annoying, but with the fixes in v6, we just log a message that makes clear what must be happened, ignore the second notification, and do not crash. This is really outside *this* patch to fix. I tested this against Linux / float-notification-6.16.0-rc3-cb06c90 (Backport to ubuntu 20.04), with a Mac laptop on Wifi and LAN, plugging and unplugging the LAN cable while an OpenVPN UDP session was active and pings going on in the tunnel. This nicely floats back and forth (and fast, usually 0 or 1 packets lost). Server had --tls-reneg 60, which made it quickly obvious if userland's idea of "what IP address does the client have?" was wrong (thanks to Ralf for that suggestion). What I did not test (because it does not really happen in practice and I couldn't get my current middleboxes to do that) is "client floats from v4 to v6, on a dual-stacked socket" - this should work, but it needs NAT64/NAT46 set up in a particular way which I gave up on. If you are very bored, test this, and show me the float messages :-) (In practice our client decides on 1 proto and 1 server IP, and sticks to that, even if it *could* decide to just go to a different server IP "because it can!" - we might add that one day, like "continuously test latency to all server IPs and use the best path" or so, but that's more a 2.8 feature...) FTR, there is a v3 from Lev on the patch, which is for testing the Windows side. I have recorded that as well, so we have lots of ACKs here :-) Your patch has been applied to the master branch. commit cb8a0f6f5741d102b667d98370ab4d553503d0b5 Author: Ralf Lici Date: Fri Jul 18 14:22:24 2025 +0200 dco: Add support for float notifications Signed-off-by: Ralf Lici <ra...@ma...> Acked-by: Gert Doering <ge...@gr...> Acked-by: Antonio Quartulli <an...@ma...> Acked-by: Lev Stipakov <lst...@gm...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg32210.html Signed-off-by: Gert Doering <ge...@gr...> -- kind regards, Gert Doering |
From: ordex (C. Review) <ge...@op...> - 2025-07-18 15:19:43
|
Attention is currently required from: flichtenheld, plaisthos, ralf_lici, stipa. ordex has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 6: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 6 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Fri, 18 Jul 2025 12:26:51 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: cron2 (C. Review) <ge...@op...> - 2025-07-18 15:23:27
|
Attention is currently required from: flichtenheld, ordex, plaisthos, ralf_lici, stipa. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... Patch Set 6: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 6 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: ordex <an...@ma...> Gerrit-Attention: ralf_lici <ra...@ma...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Fri, 18 Jul 2025 12:22:11 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
From: cron2 (C. Review) <ge...@op...> - 2025-07-18 15:50:19
|
cron2 has uploaded a new patch set (#7) to the change originally created by ralf_lici. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) The following approvals got outdated and were removed: Code-Review+2 by cron2, Code-Review+2 by ordex Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. It may happen that a netlink notification gets lost, causing us to skip a float step. If the peer then floats back to its previous address, userspace closes the only valid instance while trying to process the float, leading to a segfault. To prevent this, we ignore float attempts to an address already taken by a peer with the same peer ID. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> Acked-by: Gert Doering <ge...@gr...> Acked-by: Antonio Quartulli <an...@ma...> Acked-by: Lev Stipakov <lst...@gm...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg32210.html Signed-off-by: Gert Doering <ge...@gr...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 159 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/84/1084/7 diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..dfc6708 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,41 @@ 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..2818fd1 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..ead3dd0 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3251,6 +3251,18 @@ 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); } @@ -3384,6 +3396,17 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 7 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-MessageType: newpatchset |
From: cron2 (C. Review) <ge...@op...> - 2025-07-18 15:50:21
|
cron2 has submitted this change. ( http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email ) Change subject: dco: Add support for float notifications ...................................................................... dco: Add support for float notifications When a peer changes its UDP endpoint, the DCO module emits a notification to userpace. The message is parsed and the relevant information are extracted in order to process the floating operation. Note that we preserve IPv4-mapped IPv6 addresses in userspace when receiving a pure IPv4 address from the module, otherwise openvpn wouldn't be able to retrieve the multi_instance using the transport address hash table lookup. It may happen that a netlink notification gets lost, causing us to skip a float step. If the peer then floats back to its previous address, userspace closes the only valid instance while trying to process the float, leading to a segfault. To prevent this, we ignore float attempts to an address already taken by a peer with the same peer ID. Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Signed-off-by: Ralf Lici <ra...@ma...> Acked-by: Gert Doering <ge...@gr...> Acked-by: Antonio Quartulli <an...@ma...> Acked-by: Lev Stipakov <lst...@gm...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg32210.html Signed-off-by: Gert Doering <ge...@gr...> --- M src/openvpn/dco_linux.c M src/openvpn/dco_linux.h M src/openvpn/dco_win.c M src/openvpn/dco_win.h M src/openvpn/forward.c M src/openvpn/forward.h M src/openvpn/multi.c M src/openvpn/multi.h M src/openvpn/ovpn_dco_linux.h M src/openvpn/ovpn_dco_win.h 10 files changed, 159 insertions(+), 2 deletions(-) diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c index 22a445a..f04ebfe 100644 --- a/src/openvpn/dco_linux.c +++ b/src/openvpn/dco_linux.c @@ -768,6 +768,44 @@ return ret; } +static bool +ovpn_parse_float_addr(struct nlattr **attrs, struct sockaddr *out) +{ + if (!attrs[OVPN_A_PEER_REMOTE_PORT]) + { + msg(D_DCO, "ovpn-dco: no remote port in PEER_FLOAT_NTF message"); + return false; + } + + if (attrs[OVPN_A_PEER_REMOTE_IPV4]) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *)out; + CLEAR(*addr4); + addr4->sin_family = AF_INET; + addr4->sin_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + addr4->sin_addr.s_addr = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV4]); + return true; + } + else if (attrs[OVPN_A_PEER_REMOTE_IPV6] + && nla_len(attrs[OVPN_A_PEER_REMOTE_IPV6]) == sizeof(struct in6_addr)) + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)out; + CLEAR(*addr6); + addr6->sin6_family = AF_INET6; + addr6->sin6_port = nla_get_u16(attrs[OVPN_A_PEER_REMOTE_PORT]); + memcpy(&addr6->sin6_addr, nla_data(attrs[OVPN_A_PEER_REMOTE_IPV6]), + sizeof(addr6->sin6_addr)); + if (attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]) + { + addr6->sin6_scope_id = nla_get_u32(attrs[OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID]); + } + return true; + } + + msg(D_DCO, "ovpn-dco: no valid remote IP address in PEER_FLOAT_NTF message"); + return false; +} + /* This function parses any netlink message sent by ovpn-dco to userspace */ static int ovpn_handle_msg(struct nl_msg *msg, void *arg) @@ -856,6 +894,45 @@ break; } + case OVPN_CMD_PEER_FLOAT_NTF: + { + if (!attrs[OVPN_A_PEER]) + { + msg(D_DCO, "ovpn-dco: no peer in PEER_FLOAT_NTF message"); + return NL_STOP; + } + + struct nlattr *fp_attrs[OVPN_A_PEER_MAX + 1]; + if (nla_parse_nested(fp_attrs, OVPN_A_PEER_MAX, attrs[OVPN_A_PEER], + NULL)) + { + msg(D_DCO, "ovpn-dco: can't parse peer in PEER_FLOAT_NTF messsage"); + return NL_STOP; + } + + if (!fp_attrs[OVPN_A_PEER_ID]) + { + msg(D_DCO, "ovpn-dco: no peer-id in PEER_FLOAT_NTF message"); + return NL_STOP; + } + uint32_t peerid = nla_get_u32(fp_attrs[OVPN_A_PEER_ID]); + + if (!ovpn_parse_float_addr(fp_attrs, (struct sockaddr *)&dco->dco_float_peer_ss)) + { + return NL_STOP; + } + + struct gc_arena gc = gc_new(); + msg(D_DCO_DEBUG, + "ovpn-dco: received CMD_PEER_FLOAT_NTF, ifindex: %u, peer-id %u, address: %s", + ifindex, peerid, print_sockaddr((struct sockaddr *)&dco->dco_float_peer_ss, &gc)); + dco->dco_message_peer_id = (int)peerid; + dco->dco_message_type = OVPN_CMD_PEER_FLOAT_NTF; + + gc_free(&gc); + break; + } + case OVPN_CMD_KEY_SWAP_NTF: { if (!attrs[OVPN_A_KEYCONF]) diff --git a/src/openvpn/dco_linux.h b/src/openvpn/dco_linux.h index 4e441ec..676b8cd 100644 --- a/src/openvpn/dco_linux.h +++ b/src/openvpn/dco_linux.h @@ -34,6 +34,7 @@ /* Defines to avoid mismatching with other platforms */ #define OVPN_CMD_DEL_PEER OVPN_CMD_PEER_DEL_NTF #define OVPN_CMD_SWAP_KEYS OVPN_CMD_KEY_SWAP_NTF +#define OVPN_CMD_FLOAT_PEER OVPN_CMD_PEER_FLOAT_NTF typedef enum ovpn_key_slot dco_key_slot_t; typedef enum ovpn_cipher_alg dco_cipher_t; @@ -75,6 +76,7 @@ int dco_message_peer_id; int dco_message_key_id; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; } dco_context_t; diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c index 2a13658..83db739 100644 --- a/src/openvpn/dco_win.c +++ b/src/openvpn/dco_win.c @@ -663,6 +663,7 @@ dco->dco_message_peer_id = dco->notif_buf.PeerId; dco->dco_message_type = dco->notif_buf.Cmd; dco->dco_del_peer_reason = dco->notif_buf.DelPeerReason; + dco->dco_float_peer_ss = dco->notif_buf.FloatAddress; } else { diff --git a/src/openvpn/dco_win.h b/src/openvpn/dco_win.h index 4513f3f..b9d93fa 100644 --- a/src/openvpn/dco_win.h +++ b/src/openvpn/dco_win.h @@ -52,6 +52,7 @@ int dco_message_peer_id; int dco_message_type; int dco_del_peer_reason; + struct sockaddr_storage dco_float_peer_ss; uint64_t dco_read_bytes; uint64_t dco_write_bytes; diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index a4f260a..dfc6708 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1243,6 +1243,41 @@ 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) { diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h index 318691f..2818fd1 100644 --- a/src/openvpn/forward.h +++ b/src/openvpn/forward.h @@ -196,6 +196,21 @@ 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 * diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index a760e07..ead3dd0 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -3251,6 +3251,18 @@ 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); } @@ -3384,6 +3396,17 @@ { process_incoming_del_peer(m, mi, dco); } +#if defined(TARGET_LINUX) || defined(TARGET_WIN32) + else if (dco->dco_message_type == OVPN_CMD_FLOAT_PEER) + { + ASSERT(mi->context.c2.link_sockets[0]); + extract_dco_float_peer_addr(mi->context.c2.link_sockets[0]->info.af, + &m->top.c2.from.dest, + (struct sockaddr *)&dco->dco_float_peer_ss); + multi_process_float(m, mi, mi->context.c2.link_sockets[0]); + 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); diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index 40f7519..fe9e847 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -322,7 +322,7 @@ /** * Process an incoming DCO message (from kernel space). * - * @param m - The single \c multi_context structur.e + * @param m - The single \c multi_context structure. * * @return * - True, if the message was received correctly. diff --git a/src/openvpn/ovpn_dco_linux.h b/src/openvpn/ovpn_dco_linux.h index 680d152..b3c9ff0 100644 --- a/src/openvpn/ovpn_dco_linux.h +++ b/src/openvpn/ovpn_dco_linux.h @@ -99,6 +99,7 @@ OVPN_CMD_KEY_SWAP, OVPN_CMD_KEY_SWAP_NTF, OVPN_CMD_KEY_DEL, + OVPN_CMD_PEER_FLOAT_NTF, __OVPN_CMD_MAX, OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1) diff --git a/src/openvpn/ovpn_dco_win.h b/src/openvpn/ovpn_dco_win.h index 865bb38..dd6b7ce 100644 --- a/src/openvpn/ovpn_dco_win.h +++ b/src/openvpn/ovpn_dco_win.h @@ -149,7 +149,8 @@ typedef enum { OVPN_CMD_DEL_PEER, - OVPN_CMD_SWAP_KEYS + OVPN_CMD_SWAP_KEYS, + OVPN_CMD_FLOAT_PEER } OVPN_NOTIFY_CMD; typedef enum { @@ -164,6 +165,7 @@ OVPN_NOTIFY_CMD Cmd; int PeerId; OVPN_DEL_PEER_REASON DelPeerReason; + struct sockaddr_storage FloatAddress; } OVPN_NOTIFY_EVENT, * POVPN_NOTIFY_EVENT; typedef struct _OVPN_MP_DEL_PEER { -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/1084?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I33e9272b4196c7634db2fb33a75ae4261660867f Gerrit-Change-Number: 1084 Gerrit-PatchSet: 7 Gerrit-Owner: ralf_lici <ra...@ma...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: ordex <an...@ma...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-MessageType: merged |