From: Leonard Crestez <cdleonard@gmail.com>
To: David Ahern <dsahern@kernel.org>,
Eric Dumazet <edumazet@google.com>,
Philip Paeps <philip@trouble.is>
Cc: Dmitry Safonov <0x7f454c46@gmail.com>,
Shuah Khan <shuah@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Herbert Xu <herbert@gondor.apana.org.au>,
Kuniyuki Iwashima <kuniyu@amazon.co.jp>,
Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>,
Jakub Kicinski <kuba@kernel.org>,
Yuchung Cheng <ycheng@google.com>,
Francesco Ruggeri <fruggeri@arista.com>,
Mat Martineau <mathew.j.martineau@linux.intel.com>,
Christoph Paasch <cpaasch@apple.com>,
Ivan Delalande <colona@arista.com>,
Caowangbao <caowangbao@huawei.com>,
Priyaranjan Jha <priyarjha@google.com>,
netdev@vger.kernel.org, linux-crypto@vger.kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v7 21/26] selftests: net/fcnal: Initial tcp_authopt support
Date: Thu, 18 Aug 2022 22:59:55 +0300 [thread overview]
Message-ID: <e6960e67892b264c0f73fcf1b7e5fc6e22988fb9.1660852705.git.cdleonard@gmail.com> (raw)
In-Reply-To: <cover.1660852705.git.cdleonard@gmail.com>
Tests are mostly copied from tcp_md5 with minor changes.
It covers VRF support but only based on binding multiple servers: not
multiple keys bound to different interfaces.
Also add a specific -t tcp_authopt to run only these tests specifically.
Signed-off-by: Leonard Crestez <cdleonard@gmail.com>
---
tools/testing/selftests/net/fcnal-test.sh | 329 +++++++++++++++++++++-
1 file changed, 327 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh
index 03b586760164..6b443aa0d89e 100755
--- a/tools/testing/selftests/net/fcnal-test.sh
+++ b/tools/testing/selftests/net/fcnal-test.sh
@@ -830,10 +830,330 @@ ipv4_ping()
}
################################################################################
# IPv4 TCP
+#
+# TCP Authentication Option Tests
+#
+
+# try to enable tcp_authopt sysctl
+enable_tcp_authopt()
+{
+ if [[ -e /proc/sys/net/ipv4/tcp_authopt ]]; then
+ sysctl -w net.ipv4.tcp_authopt=1
+ fi
+}
+
+# check if tcp_authopt is compiled with a client-side bind test
+has_tcp_authopt()
+{
+ run_cmd_nsb nettest -b -A ${MD5_PW} -r ${NSA_IP}
+}
+
+# Verify /proc/net/tcp_authopt is empty in all namespaces
+check_tcp_authopt_key_leak()
+{
+ local ns cnt
+
+ for ns in $NSA $NSB $NSC; do
+ if ! ip netns list | grep -q $ns; then
+ continue
+ fi
+ cnt=$(ip netns exec "$ns" cat /proc/net/tcp_authopt | wc -l)
+ if [[ $cnt != 1 ]]; then
+ echo "FAIL: leaked tcp_authopt keys in netns $ns"
+ ip netns exec $ns cat /proc/net/tcp_authopt
+ return 1
+ fi
+ done
+}
+
+log_check_tcp_authopt_key_leak()
+{
+ check_tcp_authopt_key_leak
+ log_test $? 0 "TCP-AO: Key leak check"
+}
+
+ipv4_tcp_authopt_novrf()
+{
+ enable_tcp_authopt
+ if ! has_tcp_authopt; then
+ echo "TCP-AO appears to be missing, skip"
+ return 0
+ fi
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: Single address config"
+
+ log_start
+ run_cmd nettest -s &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 2 "AO: Server no config, client uses password"
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: Client uses wrong password"
+ log_check_tcp_authopt_key_leak
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} -m ${NSB_LO_IP} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 2 "AO: Client address does not match address configured on server"
+ log_check_tcp_authopt_key_leak
+
+ # client in prefix
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} -m ${NS_NET} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: Prefix config"
+
+ # client in prefix, wrong password
+ log_start
+ show_hint "Should timeout since client uses wrong password"
+ run_cmd nettest -s -A ${MD5_PW} -m ${NS_NET} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: Prefix config, client uses wrong password"
+ log_check_tcp_authopt_key_leak
+
+ # client outside of prefix
+ log_start
+ show_hint "Should timeout due to MD5 mismatch"
+ run_cmd nettest -s -A ${MD5_PW} -m ${NS_NET} &
+ sleep 1
+ run_cmd_nsb nettest -c ${NSB_LO_IP} -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 2 "AO: Prefix config, client address not in configured prefix"
+ log_check_tcp_authopt_key_leak
+}
+
+ipv6_tcp_authopt_novrf()
+{
+ enable_tcp_authopt
+ if ! has_tcp_authopt; then
+ echo "TCP-AO appears to be missing, skip"
+ return 0
+ fi
+
+ log_start
+ run_cmd nettest -6 -s -A ${MD5_PW} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 0 "AO: Simple correct config"
+
+ log_start
+ run_cmd nettest -6 -s
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 2 "AO: Server no config, client uses password"
+
+ log_start
+ run_cmd nettest -6 -s -A ${MD5_PW} -m ${NSB_IP6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: Client uses wrong password"
+
+ log_start
+ run_cmd nettest -6 -s -A ${MD5_PW} -m ${NSB_LO_IP6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 2 "AO: Client address does not match address configured on server"
+}
+
+ipv4_tcp_authopt_vrf()
+{
+ enable_tcp_authopt
+ if ! has_tcp_authopt; then
+ echo "TCP-AO appears to be missing, skip"
+ return 0
+ fi
+
+ log_start
+ run_cmd nettest -s -I ${VRF} -A ${MD5_PW} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Simple config"
+
+ #
+ # duplicate config between default VRF and a VRF
+ #
+
+ log_start
+ run_cmd nettest -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP} &
+ run_cmd nettest -s -A ${MD5_WRONG_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Servers in default VRF and VRF, client in VRF"
+
+ log_start
+ run_cmd nettest -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP} &
+ run_cmd nettest -s -A ${MD5_WRONG_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsc nettest -r ${NSA_IP} -A ${MD5_WRONG_PW}
+ log_test $? 0 "AO: VRF: Servers in default VRF and VRF, client in default VRF"
+
+ log_start
+ show_hint "Should timeout since client in default VRF uses VRF password"
+ run_cmd nettest -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP} &
+ run_cmd nettest -s -A ${MD5_WRONG_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsc nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 2 "AO: VRF: Servers in default VRF and VRF, conn in default VRF with VRF pw"
+
+ log_start
+ show_hint "Should timeout since client in VRF uses default VRF password"
+ run_cmd nettest -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP} &
+ run_cmd nettest -s -A ${MD5_WRONG_PW} -m ${NSB_IP} &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: VRF: Servers in default VRF and VRF, conn in VRF with default VRF pw"
+
+ test_ipv4_tcp_authopt_vrf__global_server__bind_ifindex0
+}
+
+test_ipv4_tcp_authopt_vrf__global_server__bind_ifindex0()
+{
+ # This particular test needs tcp_l3mdev_accept=1 for Global server to accept VRF connections
+ local old_tcp_l3mdev_accept
+ old_tcp_l3mdev_accept=$(get_sysctl net.ipv4.tcp_l3mdev_accept)
+ set_sysctl net.ipv4.tcp_l3mdev_accept=1
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} --force-bind-key-ifindex &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 2 "AO: VRF: Global server, Key bound to ifindex=0 rejects VRF connection"
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} --force-bind-key-ifindex &
+ sleep 1
+ run_cmd_nsc nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Global server, key bound to ifindex=0 accepts non-VRF connection"
+ log_start
+
+ run_cmd nettest -s -A ${MD5_PW} --no-bind-key-ifindex &
+ sleep 1
+ run_cmd_nsb nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Global server, key not bound to ifindex accepts VRF connection"
+
+ log_start
+ run_cmd nettest -s -A ${MD5_PW} --no-bind-key-ifindex &
+ sleep 1
+ run_cmd_nsc nettest -r ${NSA_IP} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Global server, key not bound to ifindex accepts non-VRF connection"
+
+ # restore value
+ set_sysctl net.ipv4.tcp_l3mdev_accept="$old_tcp_l3mdev_accept"
+}
+
+ipv6_tcp_authopt_vrf()
+{
+ enable_tcp_authopt
+ if ! has_tcp_authopt; then
+ echo "TCP-AO appears to be missing, skip"
+ return 0
+ fi
+
+ log_start
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Simple config"
+
+ #
+ # duplicate config between default VRF and a VRF
+ #
+
+ log_start
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NSB_IP6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Servers in default VRF and VRF, client in VRF"
+
+ log_start
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NSB_IP6} &
+ sleep 1
+ run_cmd_nsc nettest -6 -r ${NSA_IP6} -A ${MD5_WRONG_PW}
+ log_test $? 0 "AO: VRF: Servers in default VRF and VRF, client in default VRF"
+
+ log_start
+ show_hint "Should timeout since client in default VRF uses VRF password"
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NSB_IP6} &
+ sleep 1
+ run_cmd_nsc nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 2 "AO: VRF: Servers in default VRF and VRF, conn in default VRF with VRF pw"
+
+ log_start
+ show_hint "Should timeout since client in VRF uses default VRF password"
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NSB_IP6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NSB_IP6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: VRF: Servers in default VRF and VRF, conn in VRF with default VRF pw"
+
+ log_start
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NS_NET6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NS_NET6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 0 "AO: VRF: Prefix config in default VRF and VRF, conn in VRF"
+
+ log_start
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NS_NET6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NS_NET6} &
+ sleep 1
+ run_cmd_nsc nettest -6 -r ${NSA_IP6} -A ${MD5_WRONG_PW}
+ log_test $? 0 "AO: VRF: Prefix config in default VRF and VRF, conn in default VRF"
+
+ log_start
+ show_hint "Should timeout since client in default VRF uses VRF password"
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NS_NET6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NS_NET6} &
+ sleep 1
+ run_cmd_nsc nettest -6 -r ${NSA_IP6} -A ${MD5_PW}
+ log_test $? 2 "AO: VRF: Prefix config in def VRF and VRF, conn in def VRF with VRF pw"
+
+ log_start
+ show_hint "Should timeout since client in VRF uses default VRF password"
+ run_cmd nettest -6 -s -I ${VRF} -A ${MD5_PW} -m ${NS_NET6} &
+ run_cmd nettest -6 -s -A ${MD5_WRONG_PW} -m ${NS_NET6} &
+ sleep 1
+ run_cmd_nsb nettest -6 -r ${NSA_IP6} -A ${MD5_WRONG_PW}
+ log_test $? 2 "AO: VRF: Prefix config in dev VRF and VRF, conn in VRF with def VRF pw"
+}
+
+only_tcp_authopt()
+{
+ log_section "TCP Authentication Option"
+
+ setup
+ set_sysctl net.ipv4.tcp_l3mdev_accept=0
+ log_subsection "TCP-AO IPv4 no VRF"
+ ipv4_tcp_authopt_novrf
+ log_subsection "TCP-AO IPv6 no VRF"
+ ipv6_tcp_authopt_novrf
+
+ setup "yes"
+ setup_vrf_dup
+ set_sysctl net.ipv4.tcp_l3mdev_accept=0
+ log_subsection "TCP-AO IPv4 VRF"
+ ipv4_tcp_authopt_vrf
+ log_subsection "TCP-AO IPv6 VRF"
+ ipv6_tcp_authopt_vrf
+}
+
#
# MD5 tests without VRF
#
ipv4_tcp_md5_novrf()
{
@@ -1215,10 +1535,11 @@ ipv4_tcp_novrf()
show_hint "Should fail 'Connection refused'"
run_cmd nettest -d ${NSA_DEV} -r ${a}
log_test_addr ${a} $? 1 "No server, device client, local conn"
ipv4_tcp_md5_novrf
+ ipv4_tcp_authopt_novrf
}
ipv4_tcp_vrf()
{
local a
@@ -1267,13 +1588,14 @@ ipv4_tcp_vrf()
run_cmd nettest -s &
sleep 1
run_cmd nettest -r ${a} -d ${NSA_DEV}
log_test_addr ${a} $? 1 "Global server, local connection"
- # run MD5 tests
+ # run MD5+AO tests
setup_vrf_dup
ipv4_tcp_md5
+ ipv6_tcp_md5_vrf
cleanup_vrf_dup
#
# enable VRF global server
#
@@ -2748,10 +3070,11 @@ ipv6_tcp_novrf()
run_cmd nettest -6 -d ${NSA_DEV} -r ${a}
log_test_addr ${a} $? 1 "No server, device client, local conn"
done
ipv6_tcp_md5_novrf
+ ipv6_tcp_authopt_novrf
}
ipv6_tcp_vrf()
{
local a
@@ -2816,13 +3139,14 @@ ipv6_tcp_vrf()
run_cmd nettest -6 -s &
sleep 1
run_cmd nettest -6 -r ${a} -d ${NSA_DEV}
log_test_addr ${a} $? 1 "Global server, local connection"
- # run MD5 tests
+ # run MD5+AO tests
setup_vrf_dup
ipv6_tcp_md5
+ ipv6_tcp_authopt_vrf
cleanup_vrf_dup
#
# enable VRF global server
#
@@ -4191,10 +4515,11 @@ do
ipv6_bind|bind6) ipv6_addr_bind;;
ipv6_runtime) ipv6_runtime;;
ipv6_netfilter) ipv6_netfilter;;
use_cases) use_cases;;
+ tcp_authopt) only_tcp_authopt;;
# setup namespaces and config, but do not run any tests
setup) setup; exit 0;;
vrf_setup) setup "yes"; exit 0;;
esac
--
2.25.1
next prev parent reply other threads:[~2022-08-18 20:04 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-18 19:59 [PATCH v7 00/26] tcp: Initial support for RFC5925 auth option Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 01/26] tcp: authopt: Initial support and key management Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 02/26] docs: Add user documentation for tcp_authopt Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 03/26] tcp: authopt: Add crypto initialization Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 04/26] tcp: Refactor tcp_sig_hash_skb_data for AO Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 05/26] tcp: authopt: Compute packet signatures Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 06/26] tcp: Refactor tcp_inbound_md5_hash into tcp_inbound_sig_hash Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 07/26] tcp: authopt: Hook into tcp core Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 08/26] tcp: authopt: Disable via sysctl by default Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 09/26] tcp: authopt: Implement Sequence Number Extension Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 10/26] tcp: ipv6: Add AO signing for tcp_v6_send_response Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 11/26] tcp: authopt: Add support for signing skb-less replies Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 12/26] tcp: ipv4: Add AO signing for " Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 13/26] tcp: authopt: Add key selection controls Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 14/26] tcp: authopt: Add initial l3index support Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 15/26] tcp: authopt: Add NOSEND/NORECV flags Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 16/26] tcp: authopt: Add prefixlen support Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 17/26] tcp: authopt: Add v4mapped ipv6 address support Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 18/26] tcp: authopt: Add /proc/net/tcp_authopt listing all keys Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 19/26] selftests: nettest: Rename md5_prefix to key_addr_prefix Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 20/26] selftests: nettest: Initial tcp_authopt support Leonard Crestez
2022-08-18 19:59 ` Leonard Crestez [this message]
2022-08-18 19:59 ` [PATCH v7 22/26] tcp: authopt: Try to respect rnextkeyid from SYN on SYNACK Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 23/26] tcp: authopt: tcp_authopt_lookup_send: Add anykey output param Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 24/26] tcp: authopt: Initial support for TCP_AUTHOPT_FLAG_ACTIVE Leonard Crestez
2022-08-18 19:59 ` [PATCH v7 25/26] tcp: authopt: If no keys are valid for send report an error Leonard Crestez
2022-08-18 20:00 ` [PATCH v7 26/26] tcp: authopt: Initial implementation of TCP_REPAIR_AUTHOPT Leonard Crestez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e6960e67892b264c0f73fcf1b7e5fc6e22988fb9.1660852705.git.cdleonard@gmail.com \
--to=cdleonard@gmail.com \
--cc=0x7f454c46@gmail.com \
--cc=caowangbao@huawei.com \
--cc=colona@arista.com \
--cc=cpaasch@apple.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=fruggeri@arista.com \
--cc=herbert@gondor.apana.org.au \
--cc=kuba@kernel.org \
--cc=kuniyu@amazon.co.jp \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=mathew.j.martineau@linux.intel.com \
--cc=netdev@vger.kernel.org \
--cc=philip@trouble.is \
--cc=priyarjha@google.com \
--cc=shuah@kernel.org \
--cc=ycheng@google.com \
--cc=yoshfuji@linux-ipv6.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).