@@ -33,6 +33,7 @@ TEST_FILES = \
# end of TEST_FILES
TEST_PROGS := \
+ test-bind-addr.sh \
test-bind.sh \
test-chachapoly.sh \
test-close-socket-tcp.sh \
@@ -214,12 +214,13 @@ ovpn_add_peer() {
local server_ns="ovpn_peer0"
M_ID=${labels[OVPN_SYMMETRIC_ID]}
local dev=${2:-"any"}
+ local laddr=${3:-"any"}
if [ "${OVPN_PROTO}" == "UDP" ]; then
if [ ${1} -eq 0 ]; then
ip netns exec "${server_ns}" "${OVPN_CLI}" \
- new_multi_peer tun0 "${dev}" 1 "${M_ID}" \
- "${OVPN_UDP_PEERS_FILE}"
+ new_multi_peer tun0 "${dev}" "${laddr}" 1 \
+ "${M_ID}" "${OVPN_UDP_PEERS_FILE}"
for p in $(seq 1 ${OVPN_NUM_PEERS}); do
ip netns exec "${server_ns}" ${OVPN_CLI} \
@@ -244,7 +245,7 @@ ovpn_add_peer() {
${OVPN_UDP_PEERS_FILE})
ip netns exec "${peer_ns}" "${OVPN_CLI}" new_peer \
tun"${1}" "${dev}" "${PEER_ID}" "${TX_ID}" \
- "${LPORT}" "${RADDR}" "${RPORT}"
+ "${laddr}" "${LPORT}" "${RADDR}" "${RPORT}"
ip netns exec "${peer_ns}" ${OVPN_CLI} new_key tun${1} \
${PEER_ID} 1 0 ${OVPN_ALG} 1 data64.key
fi
@@ -105,7 +105,7 @@ struct ovpn_ctx {
sa_family_t sa_family;
unsigned long peer_id, tx_id;
- unsigned long lport;
+ const char *laddr, *lport;
union {
struct sockaddr_in in4;
@@ -471,59 +471,29 @@ static int ovpn_parse_key_direction(const char *dir, struct ovpn_ctx *ctx)
return 0;
}
-static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int proto)
+static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int type)
{
- struct sockaddr_storage local_sock = { 0 };
- struct sockaddr_in6 *in6;
- struct sockaddr_in *in;
- int ret, s, sock_type;
- size_t sock_len;
-
- if (proto == IPPROTO_UDP)
- sock_type = SOCK_DGRAM;
- else if (proto == IPPROTO_TCP)
- sock_type = SOCK_STREAM;
- else
- return -EINVAL;
+ int ret, s;
- s = socket(family, sock_type, 0);
+ s = socket(family, type, 0);
if (s < 0) {
perror("cannot create socket");
return -1;
}
- switch (family) {
- case AF_INET:
- in = (struct sockaddr_in *)&local_sock;
- in->sin_family = family;
- in->sin_port = htons(ctx->lport);
- in->sin_addr.s_addr = htonl(INADDR_ANY);
- sock_len = sizeof(*in);
- break;
- case AF_INET6:
- in6 = (struct sockaddr_in6 *)&local_sock;
- in6->sin6_family = family;
- in6->sin6_port = htons(ctx->lport);
- in6->sin6_addr = in6addr_any;
- sock_len = sizeof(*in6);
- break;
- default:
- return -1;
- }
-
int opt = 1;
ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (ret < 0) {
perror("setsockopt for SO_REUSEADDR");
- return ret;
+ goto close;
}
ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
if (ret < 0) {
perror("setsockopt for SO_REUSEPORT");
- return ret;
+ goto close;
}
if (ctx->mark != 0) {
@@ -531,16 +501,17 @@ static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int proto)
sizeof(ctx->mark));
if (ret < 0) {
perror("setsockopt for SO_MARK");
- return ret;
+ goto close;
}
}
if (family == AF_INET6) {
opt = 0;
- if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
- sizeof(opt))) {
+ ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
+ sizeof(opt));
+ if (ret < 0) {
perror("failed to set IPV6_V6ONLY");
- return -1;
+ goto close;
}
}
@@ -548,45 +519,87 @@ static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int proto)
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ctx->bind_dev,
strlen(ctx->bind_dev) + 1) != 0) {
perror("setsockopt for SO_BINDTODEVICE");
- return -1;
+ goto close;
}
}
- ret = bind(s, (struct sockaddr *)&local_sock, sock_len);
- if (ret < 0) {
- perror("cannot bind socket");
- goto err_socket;
+ return s;
+close:
+ close(s);
+ return ret;
+}
+
+static int ovpn_setup_socket(struct ovpn_ctx *ctx, sa_family_t family,
+ int socktype)
+{
+ struct addrinfo *list_ai, *curr_ai;
+ struct addrinfo hints;
+ int ret, socket;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV |
+ (socktype == SOCK_STREAM ? 0 : AI_V4MAPPED) |
+ (ctx->laddr ? 0 : AI_PASSIVE);
+ hints.ai_family = family;
+ hints.ai_socktype = socktype;
+ ret = getaddrinfo(ctx->laddr, ctx->lport, &hints, &list_ai);
+ if (ret) {
+ fprintf(stderr,
+ "laddr %s, lport %s, getaddrinfo on local address: %s\n",
+ ctx->laddr, ctx->lport, gai_strerror(ret));
+ return ret;
}
- ctx->socket = s;
- ctx->sa_family = family;
- return 0;
+ for (curr_ai = list_ai; curr_ai; curr_ai = curr_ai->ai_next) {
+ socket = ovpn_socket(ctx, family, socktype);
+ if (socket < 0)
+ continue;
-err_socket:
- close(s);
- return -1;
+ ret = bind(socket, curr_ai->ai_addr, curr_ai->ai_addrlen);
+ if (ret == 0)
+ break;
+
+ close(socket);
+ }
+
+ freeaddrinfo(list_ai);
+
+ if (ret < 0) {
+ perror("cannot setup socket\n");
+ return ret;
+ }
+
+ return socket;
}
static int ovpn_udp_socket(struct ovpn_ctx *ctx, sa_family_t family)
{
- return ovpn_socket(ctx, family, IPPROTO_UDP);
+ int socket = ovpn_setup_socket(ctx, family, SOCK_DGRAM);
+
+ if (socket < 0)
+ return socket;
+
+ ctx->sa_family = family;
+ ctx->socket = socket;
+ return 0;
}
static int ovpn_listen(struct ovpn_ctx *ctx, sa_family_t family)
{
- int ret;
+ int ret, socket = ovpn_setup_socket(ctx, family, SOCK_STREAM);
- ret = ovpn_socket(ctx, family, IPPROTO_TCP);
- if (ret < 0)
- return ret;
+ if (socket < 0)
+ return socket;
- ret = listen(ctx->socket, 10);
+ ret = listen(socket, 10);
if (ret < 0) {
perror("listen");
- close(ctx->socket);
+ close(socket);
return -1;
}
+ ctx->sa_family = family;
+ ctx->socket = socket;
return 0;
}
@@ -621,18 +634,13 @@ static int ovpn_accept(struct ovpn_ctx *ctx)
return ret;
}
-static int ovpn_connect(struct ovpn_ctx *ovpn)
+static int ovpn_connect(struct ovpn_ctx *ctx)
{
+ const sa_family_t family = ctx->remote.in4.sin_family;
socklen_t socklen;
- int s, ret;
+ int ret, socket;
- s = socket(ovpn->remote.in4.sin_family, SOCK_STREAM, 0);
- if (s < 0) {
- perror("cannot create socket");
- return -1;
- }
-
- switch (ovpn->remote.in4.sin_family) {
+ switch (family) {
case AF_INET:
socklen = sizeof(struct sockaddr_in);
break;
@@ -643,20 +651,22 @@ static int ovpn_connect(struct ovpn_ctx *ovpn)
return -EOPNOTSUPP;
}
- ret = connect(s, (struct sockaddr *)&ovpn->remote, socklen);
+ socket = ovpn_setup_socket(ctx, family, SOCK_STREAM);
+ if (socket < 0)
+ return socket;
+
+ ret = connect(socket, (struct sockaddr *)&ctx->remote, socklen);
if (ret < 0) {
perror("connect");
- goto err;
+ close(socket);
+ return ret;
}
fprintf(stderr, "connected\n");
- ovpn->socket = s;
-
+ ctx->sa_family = family;
+ ctx->socket = socket;
return 0;
-err:
- close(s);
- return ret;
}
static int ovpn_new_peer(struct ovpn_ctx *ovpn, bool is_tcp)
@@ -1712,7 +1722,7 @@ static void usage(const char *cmd)
"\tkey_file: file containing the symmetric key for encryption\n");
fprintf(stderr,
- "* new_peer <iface> <dev> <peer_id> <tx_id> <lport> <raddr> <rport> [vpnaddr]: add new peer\n");
+ "* new_peer <iface> <dev> <peer_id> <tx_id> <laddr> <lport> <raddr> <rport> [vpnaddr]: add new peer\n");
fprintf(stderr, "\tiface: ovpn interface name\n");
fprintf(stderr,
"\tdev: transport interface name to bind to, supports 'any'\n");
@@ -1720,16 +1730,20 @@ static void usage(const char *cmd)
"\tpeer_id: peer ID found in data packets received from this peer\n");
fprintf(stderr,
"\ttx_id: peer ID to be used when sending to this peer, 'none' for symmetric peer ID\n");
+ fprintf(stderr,
+ "\tladdr: local UDP address to bind to, supports 'any'\n");
fprintf(stderr, "\tlport: local UDP port to bind to\n");
fprintf(stderr, "\traddr: peer IP address\n");
fprintf(stderr, "\trport: peer UDP port\n");
fprintf(stderr, "\tvpnaddr: peer VPN IP\n");
fprintf(stderr,
- "* new_multi_peer <iface> <dev> <lport> <id_type> <peers_file> [mark]: add multiple peers as listed in the file\n");
+ "* new_multi_peer <iface> <dev> <laddr> <lport> <id_type> <peers_file> [mark]: add multiple peers as listed in the file\n");
fprintf(stderr, "\tiface: ovpn interface name\n");
fprintf(stderr,
"\tdev: transport interface name to bind to, supports 'any'\n");
+ fprintf(stderr,
+ "\tladdr: local UDP address to bind to, supports 'any'\n");
fprintf(stderr, "\tlport: local UDP port to bind to\n");
fprintf(stderr, "\tid_type:\n");
fprintf(stderr,
@@ -2224,11 +2238,8 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
if (argc < 6)
return -EINVAL;
- ovpn->lport = strtoul(argv[3], NULL, 10);
- if (errno == ERANGE || ovpn->lport > 65535) {
- fprintf(stderr, "lport value out of range\n");
- return -1;
- }
+ ovpn->laddr = NULL;
+ ovpn->lport = argv[3];
if (strcmp(argv[4], "SYMM") == 0) {
ovpn->asymm_id = false;
@@ -2252,6 +2263,9 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
ovpn->sa_family = AF_INET;
ovpn->asymm_id = strcmp(argv[4], "none");
+ ovpn->laddr = NULL;
+ ovpn->lport = "1";
+
ret = ovpn_parse_new_peer(ovpn, argv[3], argv[4], argv[5],
argv[6], NULL);
if (ret < 0) {
@@ -2271,52 +2285,46 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
}
break;
case CMD_NEW_PEER:
- if (argc < 9)
+ if (argc < 10)
return -EINVAL;
ovpn->bind_dev = strcmp(argv[3], "any") == 0 ? NULL : argv[3];
ovpn->asymm_id = strcmp(argv[5], "none");
- ovpn->lport = strtoul(argv[6], NULL, 10);
- if (errno == ERANGE || ovpn->lport > 65535) {
- fprintf(stderr, "lport value out of range\n");
- return -1;
- }
+ ovpn->laddr = strcmp(argv[6], "any") == 0 ? NULL : argv[6];
+ ovpn->lport = argv[7];
- const char *vpnip = (argc > 9) ? argv[9] : NULL;
+ const char *vpnip = (argc > 10) ? argv[10] : NULL;
- ret = ovpn_parse_new_peer(ovpn, argv[4], argv[5], argv[7],
- argv[8], vpnip);
+ ret = ovpn_parse_new_peer(ovpn, argv[4], argv[5], argv[8],
+ argv[9], vpnip);
if (ret < 0)
return -1;
break;
case CMD_NEW_MULTI_PEER:
- if (argc < 7)
+ if (argc < 8)
return -EINVAL;
ovpn->bind_dev = strcmp(argv[3], "any") == 0 ? NULL : argv[3];
- ovpn->lport = strtoul(argv[4], NULL, 10);
- if (errno == ERANGE || ovpn->lport > 65535) {
- fprintf(stderr, "lport value out of range\n");
- return -1;
- }
+ ovpn->laddr = strcmp(argv[4], "any") == 0 ? NULL : argv[4];
+ ovpn->lport = argv[5];
- if (!strcmp(argv[5], "SYMM")) {
+ if (!strcmp(argv[6], "SYMM")) {
ovpn->asymm_id = false;
- } else if (!strcmp(argv[5], "ASYMM")) {
+ } else if (!strcmp(argv[6], "ASYMM")) {
ovpn->asymm_id = true;
} else {
- fprintf(stderr, "Cannot parse id type: %s\n", argv[5]);
+ fprintf(stderr, "Cannot parse id type: %s\n", argv[6]);
return -1;
}
- ovpn->peers_file = argv[6];
+ ovpn->peers_file = argv[7];
ovpn->mark = 0;
- if (argc > 7) {
- ovpn->mark = strtoul(argv[7], NULL, 10);
+ if (argc > 8) {
+ ovpn->mark = strtoul(argv[8], NULL, 10);
if (errno == ERANGE || ovpn->mark > UINT32_MAX) {
fprintf(stderr, "mark value out of range\n");
return -1;
new file mode 100755
@@ -0,0 +1,10 @@
+#!/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>
+
+BIND_TYPE="ADDR"
+
+source test-bind.sh
@@ -10,6 +10,7 @@
set -eE
OVPN_PROTO=UDP
+BIND_TYPE=${BIND_TYPE:-"DEV"}
source ./common.sh
@@ -62,8 +63,9 @@ ovpn_bind_prepare_network() {
ovpn_cmd_ok "bring up peer2 second underlay link" \
ip -n ovpn_peer2 link set veth2 up
- # Some test cases intentionally bind peer1 to a device that does not
- # match the route-selected underlay, so allow asymmetric underlay paths.
+ # Some test cases intentionally bind peer1 to a device or address that
+ # does not match the route-selected underlay, so allow asymmetric
+ # underlay paths.
ovpn_cmd_ok "disable peer1 global rp_filter" \
ip netns exec ovpn_peer1 sysctl -w \
net.ipv4.conf.all.rp_filter=0
@@ -110,8 +112,10 @@ ovpn_bind_prepare_network() {
ovpn_bind_configure_peers() {
local dev1="$1"
local dev2="$2"
- local raddr4_peer1="$3"
- local raddr4_peer2="$4"
+ local laddr4_peer1="$3"
+ local laddr4_peer2="$4"
+ local raddr4_peer1="$5"
+ local raddr4_peer2="$6"
ip netns exec ovpn_peer1 "${OVPN_CLI}" del_peer tun1 1 \
>/dev/null 2>&1 || true
@@ -121,15 +125,16 @@ ovpn_bind_configure_peers() {
# Close any active userspace socket before installing a new peer pair.
killall "$(basename "${OVPN_CLI}")" 2>/dev/null || true
- ovpn_cmd_ok "create peer1 bound peer on ${dev1}" \
+ ovpn_cmd_ok "create peer1 bound peer" \
ip netns exec ovpn_peer1 "${OVPN_CLI}" new_peer tun1 \
- "${dev1}" 1 10 1 "${raddr4_peer1}" 1
+ "${dev1}" 1 10 "${laddr4_peer1}" 1 "${raddr4_peer1}" 1
ovpn_cmd_ok "install peer1 key" \
ip netns exec ovpn_peer1 "${OVPN_CLI}" new_key tun1 1 1 0 \
"${OVPN_ALG}" 0 data64.key
- ovpn_cmd_ok "create peer2 bound peer on ${dev2}" \
+ ovpn_cmd_ok "create peer2 bound peer" \
ip netns exec ovpn_peer2 "${OVPN_CLI}" new_peer tun2 \
- "${dev2}" 10 1 1 "${raddr4_peer2}" 1
+ "${dev2}" 10 1 "${laddr4_peer2}" 1 \
+ "${raddr4_peer2}" 1
ovpn_cmd_ok "install peer2 key" \
ip netns exec ovpn_peer2 "${OVPN_CLI}" new_key tun2 10 1 0 \
"${OVPN_ALG}" 1 data64.key
@@ -153,7 +158,7 @@ ovpn_bind_start_capture() {
OVPN_BIND_TCPDUMP_PIDS+=("${pid}")
}
-ovpn_bind_run_positive_case() {
+ovpn_bind_run_dev_positive_case() {
local dev1="$1"
local dev2="$2"
local raddr4_peer1="$3"
@@ -165,8 +170,8 @@ ovpn_bind_run_positive_case() {
local header2="0x4800000a"
local ping_start_delay="0.3"
- ovpn_bind_configure_peers "${dev1}" "${dev2}" "${raddr4_peer1}" \
- "${raddr4_peer2}"
+ ovpn_bind_configure_peers "${dev1}" "${dev2}" any any \
+ "${raddr4_peer1}" "${raddr4_peer2}"
filter="$(printf '(%s) or (%s)' \
"$(ovpn_build_capture_filter "${header1}" "${raddr4_peer1}")" \
"$(ovpn_build_capture_filter "${header2}" "${raddr4_peer2}")")"
@@ -192,7 +197,7 @@ ovpn_bind_run_positive_case() {
OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
}
-ovpn_bind_run_sender_negative_case() {
+ovpn_bind_run_dev_sender_negative_case() {
local dev1="$1"
local raddr4_peer1="$2"
local raddr4_peer2="$3"
@@ -201,7 +206,7 @@ ovpn_bind_run_sender_negative_case() {
local header="0x4800000a"
local ping_start_delay="0.3"
- ovpn_bind_configure_peers "${dev1}" any "${raddr4_peer1}" \
+ ovpn_bind_configure_peers "${dev1}" any any any "${raddr4_peer1}" \
"${raddr4_peer2}"
filter="$(ovpn_build_capture_filter "${header}" "${raddr4_peer1}")"
@@ -217,7 +222,7 @@ ovpn_bind_run_sender_negative_case() {
OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
}
-ovpn_bind_run_receiver_negative_case() {
+ovpn_bind_run_dev_receiver_negative_case() {
local dev2="$1"
local raddr4_peer1="$2"
local raddr4_peer2="$3"
@@ -226,7 +231,7 @@ ovpn_bind_run_receiver_negative_case() {
local header="0x4800000a"
local ping_start_delay="0.3"
- ovpn_bind_configure_peers any "${dev2}" "${raddr4_peer1}" \
+ ovpn_bind_configure_peers any "${dev2}" any any "${raddr4_peer1}" \
"${raddr4_peer2}"
filter="$(ovpn_build_capture_filter "${header}" "${raddr4_peer1}")"
@@ -242,40 +247,138 @@ ovpn_bind_run_receiver_negative_case() {
OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
}
+ovpn_bind_run_addr_positive_case() {
+ local laddr4_peer1="$1"
+ local raddr4_peer1="$2"
+ local raddr4_peer2="$3"
+ local expected_dev="$4"
+ local unexpected_dev="$5"
+ local filter
+ local header="0x4800000a"
+ local ping_start_delay="0.3"
+
+ ovpn_bind_configure_peers any any "${laddr4_peer1}" any \
+ "${raddr4_peer1}" "${raddr4_peer2}"
+ filter="$(printf '(%s) and src host %s' \
+ "$(ovpn_build_capture_filter "${header}" "${raddr4_peer1}")" \
+ "${laddr4_peer1}")"
+
+ # The route-selected device must carry peer1 data packets with the
+ # explicitly bound local address as outer source address.
+ ovpn_bind_start_capture "${expected_dev}" 1 "${filter}"
+
+ # The other underlay device must not carry peer1 data packets with the
+ # explicitly bound local address.
+ ovpn_bind_start_capture "${unexpected_dev}" 1 "${filter}"
+
+ sleep "${ping_start_delay}"
+ ovpn_cmd_ok "send tunnel traffic from peer1 to peer2" \
+ ip netns exec ovpn_peer1 ping -qfc 10 -w 3 5.5.5.2
+ ovpn_cmd_ok "capture bound source on ${expected_dev}" \
+ wait "${OVPN_BIND_TCPDUMP_PIDS[0]}"
+ OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
+
+ ovpn_cmd_fail "capture bound source on ${unexpected_dev}" \
+ wait "${OVPN_BIND_TCPDUMP_PIDS[0]}"
+ OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
+}
+
+ovpn_bind_run_addr_receiver_positive_case() {
+ local laddr4_peer2="$1"
+ local raddr4_peer1="$2"
+ local raddr4_peer2="$3"
+ local expected_dev="$4"
+ local unexpected_dev="$5"
+ local filter
+ local header="0x4800000a"
+ local ping_start_delay="0.3"
+
+ ovpn_bind_configure_peers any any any "${laddr4_peer2}" \
+ "${raddr4_peer1}" "${raddr4_peer2}"
+ filter="$(printf '(%s) and dst host %s' \
+ "$(ovpn_build_capture_filter "${header}" "${raddr4_peer1}")" \
+ "${raddr4_peer1}")"
+
+ # The destination-matching underlay device must carry peer1 data
+ # packets to the address peer2 is bound to.
+ ovpn_bind_start_capture "${expected_dev}" 1 "${filter}"
+
+ # The other underlay device must not carry those packets.
+ ovpn_bind_start_capture "${unexpected_dev}" 1 "${filter}"
+
+ sleep "${ping_start_delay}"
+ ovpn_cmd_ok "send tunnel traffic from peer1 to peer2" \
+ ip netns exec ovpn_peer1 ping -qfc 10 -w 3 5.5.5.2
+ ovpn_cmd_ok "capture bound destination on ${expected_dev}" \
+ wait "${OVPN_BIND_TCPDUMP_PIDS[0]}"
+ OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
+
+ ovpn_cmd_fail "capture bound destination on ${unexpected_dev}" \
+ wait "${OVPN_BIND_TCPDUMP_PIDS[0]}"
+ OVPN_BIND_TCPDUMP_PIDS=("${OVPN_BIND_TCPDUMP_PIDS[@]:1}")
+}
+
+ovpn_bind_run_dev_tests() {
+ ktap_set_plan 9
+
+ ovpn_run_stage "setup network topology" ovpn_bind_prepare_network
+ ovpn_run_stage "peer1 bind_dev=veth1 routes over veth1" \
+ ovpn_bind_run_dev_positive_case \
+ veth1 any 10.10.10.2 10.10.10.1 veth1 veth2
+ ovpn_run_stage "peer1 bind_dev=veth2 routes over veth2" \
+ ovpn_bind_run_dev_positive_case \
+ veth2 any 20.20.20.2 20.20.20.1 veth2 veth1
+ ovpn_run_stage "peer2 bind_dev=veth1 replies over veth1" \
+ ovpn_bind_run_dev_positive_case \
+ any veth1 10.10.10.2 10.10.10.1 veth1 veth2
+ ovpn_run_stage "peer2 bind_dev=veth2 replies over veth2" \
+ ovpn_bind_run_dev_positive_case \
+ any veth2 20.20.20.2 20.20.20.1 veth2 veth1
+ ovpn_run_stage "peer1 bind_dev=veth1 blocks veth2 egress" \
+ ovpn_bind_run_dev_sender_negative_case \
+ veth1 20.20.20.2 20.20.20.1 veth2
+ ovpn_run_stage "peer1 bind_dev=veth2 blocks veth1 egress" \
+ ovpn_bind_run_dev_sender_negative_case \
+ veth2 10.10.10.2 10.10.10.1 veth1
+ ovpn_run_stage "peer2 bind_dev=veth1 rejects veth2 ingress" \
+ ovpn_bind_run_dev_receiver_negative_case \
+ veth1 20.20.20.2 20.20.20.1 veth2
+ ovpn_run_stage "peer2 bind_dev=veth2 rejects veth1 ingress" \
+ ovpn_bind_run_dev_receiver_negative_case \
+ veth2 10.10.10.2 10.10.10.1 veth1
+}
+
+ovpn_bind_run_addr_tests() {
+ ktap_set_plan 5
+
+ ovpn_run_stage "setup network topology" ovpn_bind_prepare_network
+ ovpn_run_stage "peer1 bind_addr=10.10.10.1 sends from 10.10.10.1 \
+ via veth2" ovpn_bind_run_addr_positive_case \
+ 10.10.10.1 20.20.20.2 10.10.10.1 veth2 veth1
+ ovpn_run_stage "peer1 bind_addr=20.20.20.1 sends from 20.20.20.1 \
+ via veth1" ovpn_bind_run_addr_positive_case \
+ 20.20.20.1 10.10.10.2 20.20.20.1 veth1 veth2
+ ovpn_run_stage "peer2 bind_addr=10.10.10.2 accepts dst 10.10.10.2 \
+ via veth1" ovpn_bind_run_addr_receiver_positive_case \
+ 10.10.10.2 10.10.10.2 10.10.10.1 veth1 veth2
+ ovpn_run_stage "peer2 bind_addr=20.20.20.2 accepts dst 20.20.20.2 \
+ via veth2" ovpn_bind_run_addr_receiver_positive_case \
+ 20.20.20.2 20.20.20.2 20.20.20.1 veth2 veth1
+}
+
trap ovpn_test_exit EXIT
trap ovpn_stage_err ERR
ktap_print_header
-ktap_set_plan 9
ovpn_cleanup
modprobe -q ovpn || true
-ovpn_run_stage "setup network topology" ovpn_bind_prepare_network
-ovpn_run_stage "peer1 bind_dev=veth1 routes over veth1" \
- ovpn_bind_run_positive_case \
- veth1 any 10.10.10.2 10.10.10.1 veth1 veth2
-ovpn_run_stage "peer1 bind_dev=veth2 routes over veth2" \
- ovpn_bind_run_positive_case \
- veth2 any 20.20.20.2 20.20.20.1 veth2 veth1
-ovpn_run_stage "peer2 bind_dev=veth1 replies over veth1" \
- ovpn_bind_run_positive_case \
- any veth1 10.10.10.2 10.10.10.1 veth1 veth2
-ovpn_run_stage "peer2 bind_dev=veth2 replies over veth2" \
- ovpn_bind_run_positive_case \
- any veth2 20.20.20.2 20.20.20.1 veth2 veth1
-ovpn_run_stage "peer1 bind_dev=veth1 blocks veth2 egress" \
- ovpn_bind_run_sender_negative_case \
- veth1 20.20.20.2 20.20.20.1 veth2
-ovpn_run_stage "peer1 bind_dev=veth2 blocks veth1 egress" \
- ovpn_bind_run_sender_negative_case \
- veth2 10.10.10.2 10.10.10.1 veth1
-ovpn_run_stage "peer2 bind_dev=veth1 rejects veth2 ingress" \
- ovpn_bind_run_receiver_negative_case \
- veth1 20.20.20.2 20.20.20.1 veth2
-ovpn_run_stage "peer2 bind_dev=veth2 rejects veth1 ingress" \
- ovpn_bind_run_receiver_negative_case \
- veth2 10.10.10.2 10.10.10.1 veth1
+if [ "${BIND_TYPE}" = "ADDR" ]; then
+ ovpn_bind_run_addr_tests
+else
+ ovpn_bind_run_dev_tests
+fi
ovpn_test_finished=1
ktap_finished
@@ -39,7 +39,7 @@ ovpn_mark_prepare_network() {
ovpn_cmd_ok "create server-side multi-peer with fwmark" \
ip netns exec ovpn_peer0 "${OVPN_CLI}" new_multi_peer tun0 \
- any 1 ASYMM "${OVPN_UDP_PEERS_FILE}" "${MARK}"
+ any any 1 ASYMM "${OVPN_UDP_PEERS_FILE}" "${MARK}"
for p in $(seq 1 3); do
ovpn_cmd_ok "install server key for peer ${p}" \
ip netns exec ovpn_peer0 "${OVPN_CLI}" new_key tun0 \