summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/net/ovpn/Makefile1
-rw-r--r--tools/testing/selftests/net/ovpn/ovpn-cli.c23
-rwxr-xr-xtools/testing/selftests/net/ovpn/test-mark.sh96
3 files changed, 119 insertions, 1 deletions
diff --git a/tools/testing/selftests/net/ovpn/Makefile b/tools/testing/selftests/net/ovpn/Makefile
index ce9f79c4f892..169f0464ac3a 100644
--- a/tools/testing/selftests/net/ovpn/Makefile
+++ b/tools/testing/selftests/net/ovpn/Makefile
@@ -38,6 +38,7 @@ TEST_PROGS := \
test-close-socket.sh \
test-float.sh \
test-large-mtu.sh \
+ test-mark.sh \
test-symmetric-id-float.sh \
test-symmetric-id-tcp.sh \
test-symmetric-id.sh \
diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c
index 085446471397..d40953375c86 100644
--- a/tools/testing/selftests/net/ovpn/ovpn-cli.c
+++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c
@@ -6,6 +6,7 @@
* Author: Antonio Quartulli <antonio@openvpn.net>
*/
+#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>
#include <stdbool.h>
@@ -133,6 +134,7 @@ struct ovpn_ctx {
enum ovpn_key_slot key_slot;
int key_id;
+ uint32_t mark;
bool asymm_id;
const char *peers_file;
@@ -523,6 +525,15 @@ static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int proto)
return ret;
}
+ if (ctx->mark != 0) {
+ ret = setsockopt(s, SOL_SOCKET, SO_MARK, (void *)&ctx->mark,
+ sizeof(ctx->mark));
+ if (ret < 0) {
+ perror("setsockopt for SO_MARK");
+ return ret;
+ }
+ }
+
if (family == AF_INET6) {
opt = 0;
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
@@ -1704,7 +1715,7 @@ static void usage(const char *cmd)
fprintf(stderr, "\tvpnaddr: peer VPN IP\n");
fprintf(stderr,
- "* new_multi_peer <iface> <lport> <id_type> <peers_file>: add multiple peers as listed in the file\n");
+ "* new_multi_peer <iface> <lport> <id_type> <peers_file> [mark]: add multiple peers as listed in the file\n");
fprintf(stderr, "\tiface: ovpn interface name\n");
fprintf(stderr, "\tlport: local UDP port to bind to\n");
fprintf(stderr, "\tid_type:\n");
@@ -1716,6 +1727,7 @@ static void usage(const char *cmd)
"\tpeers_file: text file containing one peer per line. Line format:\n");
fprintf(stderr,
"\t\t<peer_id> <tx_id> <raddr> <rport> <laddr> <lport> <vpnaddr>\n");
+ fprintf(stderr, "\tmark: socket FW mark value\n");
fprintf(stderr,
"* set_peer <iface> <peer_id> <keepalive_interval> <keepalive_timeout>: set peer attributes\n");
@@ -2284,6 +2296,15 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
}
ovpn->peers_file = argv[5];
+
+ ovpn->mark = 0;
+ if (argc > 6) {
+ ovpn->mark = strtoul(argv[6], NULL, 10);
+ if (errno == ERANGE || ovpn->mark > UINT32_MAX) {
+ fprintf(stderr, "mark value out of range\n");
+ return -1;
+ }
+ }
break;
case CMD_SET_PEER:
if (argc < 6)
diff --git a/tools/testing/selftests/net/ovpn/test-mark.sh b/tools/testing/selftests/net/ovpn/test-mark.sh
new file mode 100755
index 000000000000..8534428ed3eb
--- /dev/null
+++ b/tools/testing/selftests/net/ovpn/test-mark.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2020-2025 OpenVPN, Inc.
+#
+# Author: Ralf Lici <ralf@mandelbit.com>
+# Antonio Quartulli <antonio@openvpn.net>
+
+#set -x
+set -e
+
+MARK=1056
+
+source ./common.sh
+
+cleanup
+
+modprobe -q ovpn || true
+
+for p in $(seq 0 "${NUM_PEERS}"); do
+ create_ns "${p}"
+done
+
+for p in $(seq 0 3); do
+ setup_ns "${p}" 5.5.5.$((p + 1))/24
+done
+
+# add peer0 with mark
+ip netns exec peer0 "${OVPN_CLI}" new_multi_peer tun0 1 ASYMM \
+ "${UDP_PEERS_FILE}" \
+ ${MARK}
+for p in $(seq 1 3); do
+ ip netns exec peer0 "${OVPN_CLI}" new_key tun0 "${p}" 1 0 "${ALG}" 0 \
+ data64.key
+done
+
+for p in $(seq 1 3); do
+ add_peer "${p}"
+done
+
+for p in $(seq 1 3); do
+ ip netns exec peer0 "${OVPN_CLI}" set_peer tun0 "${p}" 60 120
+ ip netns exec peer"${p}" "${OVPN_CLI}" set_peer tun"${p}" \
+ $((p + 9)) 60 120
+done
+
+sleep 1
+
+for p in $(seq 1 3); do
+ ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((p + 1))
+done
+
+echo "Adding an nftables drop rule based on mark value ${MARK}"
+ip netns exec peer0 nft flush ruleset
+ip netns exec peer0 nft 'add table inet filter'
+ip netns exec peer0 nft 'add chain inet filter output {
+ type filter hook output priority 0;
+ policy accept;
+}'
+ip netns exec peer0 nft add rule inet filter output \
+ meta mark == ${MARK} \
+ counter drop
+
+DROP_COUNTER=$(ip netns exec peer0 nft list chain inet filter output \
+ | sed -n 's/.*packets \([0-9]*\).*/\1/p')
+sleep 1
+
+# ping should fail
+for p in $(seq 1 3); do
+ PING_OUTPUT=$(ip netns exec peer0 ping \
+ -qfc 500 -w 1 5.5.5.$((p + 1)) 2>&1) && exit 1
+ echo "${PING_OUTPUT}"
+ LOST_PACKETS=$(echo "$PING_OUTPUT" \
+ | awk '/packets transmitted/ { print $1 }')
+ # increment the drop counter by the amount of lost packets
+ DROP_COUNTER=$((DROP_COUNTER + LOST_PACKETS))
+done
+
+# check if the final nft counter matches our counter
+TOTAL_COUNT=$(ip netns exec peer0 nft list chain inet filter output \
+ | sed -n 's/.*packets \([0-9]*\).*/\1/p')
+if [ "${DROP_COUNTER}" -ne "${TOTAL_COUNT}" ]; then
+ echo "Expected ${TOTAL_COUNT} drops, got ${DROP_COUNTER}"
+ exit 1
+fi
+
+echo "Removing the drop rule"
+ip netns exec peer0 nft flush ruleset
+sleep 1
+
+for p in $(seq 1 3); do
+ ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((p + 1))
+done
+
+cleanup
+
+modprobe -r ovpn || true