Hi,
On 12/04/2022 12:33, Frank Lichtenheld wrote:
Honestly still not sure one would start reviewing the actual code but here
are at least a few minor things I noticed while browsing through it:
Antonio Quartulli <a...@unstable.cc> hat am 11.04.2022 15:35 geschrieben:
Implement the data-channel offloading using the ovpn-dco kernel
module. See README.dco.md for more details.
Signed-off-by: Arne Schwabe <a...@rfc2549.org>
Signed-off-by: Antonio Quartulli <a...@unstable.cc>
---
Changes from v1:
* uncrustified code. Note that uncrustify wanted to change way more
code in our repo, therefore I had to dig into the proposed changes and
pick only those related to this patch. For this reason I may have
missed something.
You also incorporated my review suggestions.
Right - sorry!
[...]
diff --git a/README.dco.md b/README.dco.md
new file mode 100644
index 00000000..e73e0fc2
--- /dev/null
+++ b/README.dco.md
[...}
+DCO and P2P mode
+----------------
+DCO is also available when running OpenVPN in P2P mode without --pull/--client
option.
+The P2P mode is useful for scenarios when the OpenVPN tunnel should not
interfere with
+overall routing and behave more like a "dumb" tunnel like GRE.
+
+However, DCO requires DATA_V2 to be enabled. This requires P2P with NCP
capability, which
+is only available in OpenVPN 2.6 and later.
Changes.rst doesn't mention this change, should it?
how does this sound:
Note that DCO will use DATA_V2 packets in P2P mode, therefore,
this implies that peers must be running 2.6.0+ in order to have P2P-NCP
which brings DATA_V2 packet support.
Should we mention here what "NCP" stands for?
to be honest I barely know what it stands for :-D I just know it is
"cipher negotiation", but the actual definition I think is expected to
be found elsewhere. no?
+OpenVPN prints a diagnostic message for the P2P NCP result when running in P2P
mode:
+
+ P2P mode NCP negotiation result: TLS_export=1, DATA_v2=1, peer-id 9484735,
cipher=AES-256-GCM
+
+Double check that your have `DATA_v2=1` in your output and a supported AEAD
cipher
+(AES-XXX-GCM or CHACHA20POLY1305).
[...]
diff --git a/doc/man-sections/advanced-options.rst
b/doc/man-sections/advanced-options.rst
index 5157c561..6019aefe 100644
--- a/doc/man-sections/advanced-options.rst
+++ b/doc/man-sections/advanced-options.rst
@@ -91,3 +91,16 @@ used when debugging or testing out special usage scenarios.
*(Linux only)* Set the TX queue length on the TUN/TAP interface.
Currently defaults to operating system default.
+--disable-dco
+ Disables the opportunistic use of the data channel offloading if available.
Nitpick: would remove "the" in "the data channel offloading".
right
[...]
diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
index 9e10f64e..7e49d710 100644
--- a/src/openvpn/crypto.c
+++ b/src/openvpn/crypto.c
@@ -845,6 +845,7 @@ init_key_ctx(struct key_ctx *ctx, const struct key *key,
cipher_kt_iv_size(kt->cipher));
warn_insecure_key_type(ciphername);
}
+
Spurious uncrustify change?
removed
if (md_defined(kt->digest))
{
ctx->hmac = hmac_ctx_new();
diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c
new file mode 100644
index 00000000..2f7779f6
--- /dev/null
+++ b/src/openvpn/dco.c
[...]
+/**
+ * Find a usable key that is not the primary (i.e. the secondary key)
+ *
+ * @param multi The TLS struct to retrieve keys from
+ * @param primary The primary key that should be skipped doring the scan
"during"
I almost managed to have Gert in the comment :-D
[...]
+static bool
+dco_check_option_conflict_ce(const struct connection_entry *ce, int msglevel)
+{
+ if (ce->fragment)
+ {
+ msg(msglevel, "Note: --fragment disables data channel offload.");
+ return true;
+ }
+
+ if (ce->http_proxy_options)
+ {
+ msg(msglevel, "Note: --http-proxy disables data channel offload.");
+ return true;
+ }
+
+ if (ce->socks_proxy_server)
+ {
+ msg(msglevel, "Note --socks-proxy disable data channel offload.");
"Note: --socks-proxy disables data channel offload."
right
Missing ':' after "Note" and missing 's' in "disables".
yup, thanks!
+ return true;
+ }
+
+ return false;
+}
[...]
diff --git a/src/openvpn/dco_linux.c b/src/openvpn/dco_linux.c
new file mode 100644
index 00000000..6c670950
--- /dev/null
+++ b/src/openvpn/dco_linux.c
[...]
+/**
+ * @brief resolves the netlink ID for ovpn-dco
+ *
+ * This function queries the kernel via a netlink socket
+ * whether the ovpn-dco netlink namespace is available
+ *
+ * This function can be used to determine if the kernel
+ * support DCO offloading.
"supports"
thanks
+ *
+ * @return ID on success, negative error code on error
+ */
+static int
+resolve_ovpn_netlink_id(int msglevel)
[...]
+/**
+ * Send a preprared netlink message and registers cb as callback if non-null.
+ *
+ * The method will also free nl_msg
+ * @param dco The dco context to use
+ * @param nl_msg the message to use
+ * @param cb An optional callback if the caller expects an answers\
"an answer", also spurious '\'
thanks
+ * @param prefix A prefix to report in the error message to give the user
context
+ * @return status of sending the message
+ */
+static int
+ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, ovpn_nl_cb cb,
+ const char *prefix)
+{
+ dco->status = 1;
+
+ if (cb)
+ {
+ nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, dco);
+ }
+ else
+ {
+ nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, NULL, dco);
+ }
Is there an actual difference to just writing
nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, dco);
without the whole if/else?
yeah, this must be the result of older pruning, which left the
leaves...but they can now be merged :-)
done!
+ nl_send_auto(dco->nl_sock, nl_msg);
+
+ while (dco->status == 1)
+ {
+ ovpn_nl_recvmsgs(dco, prefix);
+ }
+
+ if (dco->status < 0)
+ {
+ msg(M_INFO, "%s: failed to send netlink message: %s (%d)",
+ prefix, strerror(-dco->status), dco->status);
+ }
+
+ return dco->status;
+}
+
+struct sockaddr *
+mapped_v4_to_v6(struct sockaddr *sock, struct gc_arena *gc)
+{
+ struct sockaddr_in6 *sock6 = ((struct sockaddr_in6 *)sock);
+ if (sock->sa_family == AF_INET6
+ && memcmp(&sock6->sin6_addr,
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff", 12)==0)
magic constant?
as Gert pointed out, there is a nice macro for this. using it now.
+ {
+
+ struct sockaddr_in *sock4;
+ ALLOC_OBJ_CLEAR_GC(sock4, struct sockaddr_in, gc);
+ memcpy(&sock4->sin_addr, sock6->sin6_addr.s6_addr +12, 4);
+ sock4->sin_port = sock6->sin6_port;
+ sock4->sin_family = AF_INET;
+ return (struct sockaddr *) sock4;
+ }
+ return sock;
+}
[...]
Regards,
Thanks a lot for the review!
Regards,
--
Frank Lichtenheld
--
Antonio Quartulli
_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel