diff options
Diffstat (limited to 'tools/testing/selftests/net')
| -rw-r--r-- | tools/testing/selftests/net/Makefile | 1 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/fcnal-test.sh | 57 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/fib_nexthops.sh | 63 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/fib_tests.sh | 59 | ||||
| -rw-r--r-- | tools/testing/selftests/net/forwarding/forwarding.config.sample | 2 | ||||
| -rwxr-xr-x | tools/testing/selftests/net/icmp_redirect.sh | 2 | ||||
| -rw-r--r-- | tools/testing/selftests/net/tls.c | 557 | ||||
| -rw-r--r-- | tools/testing/selftests/net/toeplitz.c | 2 | 
8 files changed, 586 insertions, 157 deletions
| diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 7615f29831eb..9897fa9ab953 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -34,6 +34,7 @@ TEST_PROGS += srv6_end_dt46_l3vpn_test.sh  TEST_PROGS += srv6_end_dt4_l3vpn_test.sh  TEST_PROGS += srv6_end_dt6_l3vpn_test.sh  TEST_PROGS += vrf_strict_mode_test.sh +TEST_PROGS += arp_ndisc_evict_nocarrier.sh  TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh  TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh  TEST_GEN_FILES =  socket nettest diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh index 3313566ce906..ad2982b72e02 100755 --- a/tools/testing/selftests/net/fcnal-test.sh +++ b/tools/testing/selftests/net/fcnal-test.sh @@ -455,6 +455,22 @@ cleanup()  	ip netns del ${NSC} >/dev/null 2>&1  } +cleanup_vrf_dup() +{ +	ip link del ${NSA_DEV2} >/dev/null 2>&1 +	ip netns pids ${NSC} | xargs kill 2>/dev/null +	ip netns del ${NSC} >/dev/null 2>&1 +} + +setup_vrf_dup() +{ +	# some VRF tests use ns-C which has the same config as +	# ns-B but for a device NOT in the VRF +	create_ns ${NSC} "-" "-" +	connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ +		   ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64 +} +  setup()  {  	local with_vrf=${1} @@ -484,12 +500,6 @@ setup()  		ip -netns ${NSB} ro add ${VRF_IP}/32 via ${NSA_IP} dev ${NSB_DEV}  		ip -netns ${NSB} -6 ro add ${VRF_IP6}/128 via ${NSA_IP6} dev ${NSB_DEV} - -		# some VRF tests use ns-C which has the same config as -		# ns-B but for a device NOT in the VRF -		create_ns ${NSC} "-" "-" -		connect_ns ${NSA} ${NSA_DEV2} ${NSA_IP}/24 ${NSA_IP6}/64 \ -			   ${NSC} ${NSC_DEV} ${NSB_IP}/24 ${NSB_IP6}/64  	else  		ip -netns ${NSA} ro add ${NSB_LO_IP}/32 via ${NSB_IP} dev ${NSA_DEV}  		ip -netns ${NSA} ro add ${NSB_LO_IP6}/128 via ${NSB_IP6} dev ${NSA_DEV} @@ -1240,7 +1250,9 @@ ipv4_tcp_vrf()  	log_test_addr ${a} $? 1 "Global server, local connection"  	# run MD5 tests +	setup_vrf_dup  	ipv4_tcp_md5 +	cleanup_vrf_dup  	#  	# enable VRF global server @@ -1798,8 +1810,9 @@ ipv4_addr_bind_vrf()  	for a in ${NSA_IP} ${VRF_IP}  	do  		log_start +		show_hint "Socket not bound to VRF, but address is in VRF"  		run_cmd nettest -s -R -P icmp -l ${a} -b -		log_test_addr ${a} $? 0 "Raw socket bind to local address" +		log_test_addr ${a} $? 1 "Raw socket bind to local address"  		log_start  		run_cmd nettest -s -R -P icmp -l ${a} -I ${NSA_DEV} -b @@ -2191,7 +2204,7 @@ ipv6_ping_vrf()  		log_start  		show_hint "Fails since VRF device does not support linklocal or multicast"  		run_cmd ${ping6} -c1 -w1 ${a} -		log_test_addr ${a} $? 2 "ping out, VRF bind" +		log_test_addr ${a} $? 1 "ping out, VRF bind"  	done  	for a in ${NSB_IP6} ${NSB_LO_IP6} ${NSB_LINKIP6}%${NSA_DEV} ${MCAST}%${NSA_DEV} @@ -2719,7 +2732,9 @@ ipv6_tcp_vrf()  	log_test_addr ${a} $? 1 "Global server, local connection"  	# run MD5 tests +	setup_vrf_dup  	ipv6_tcp_md5 +	cleanup_vrf_dup  	#  	# enable VRF global server @@ -3414,11 +3429,14 @@ ipv6_addr_bind_novrf()  	run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b  	log_test_addr ${a} $? 0 "TCP socket bind to local address after device bind" +	# Sadly, the kernel allows binding a socket to a device and then +	# binding to an address not on the device. So this test passes +	# when it really should not  	a=${NSA_LO_IP6}  	log_start -	show_hint "Should fail with 'Cannot assign requested address'" +	show_hint "Tecnically should fail since address is not on device but kernel allows"  	run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b -	log_test_addr ${a} $? 1 "TCP socket bind to out of scope local address" +	log_test_addr ${a} $? 0 "TCP socket bind to out of scope local address"  }  ipv6_addr_bind_vrf() @@ -3459,10 +3477,15 @@ ipv6_addr_bind_vrf()  	run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b  	log_test_addr ${a} $? 0 "TCP socket bind to local address with device bind" +	# Sadly, the kernel allows binding a socket to a device and then +	# binding to an address not on the device. The only restriction +	# is that the address is valid in the L3 domain. So this test +	# passes when it really should not  	a=${VRF_IP6}  	log_start +	show_hint "Tecnically should fail since address is not on device but kernel allows"  	run_cmd nettest -6 -s -l ${a} -I ${NSA_DEV} -t1 -b -	log_test_addr ${a} $? 1 "TCP socket bind to VRF address with device bind" +	log_test_addr ${a} $? 0 "TCP socket bind to VRF address with device bind"  	a=${NSA_LO_IP6}  	log_start @@ -4002,8 +4025,8 @@ EOF  ################################################################################  # main -TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_addr_bind ipv4_runtime ipv4_netfilter" -TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_addr_bind ipv6_runtime ipv6_netfilter" +TESTS_IPV4="ipv4_ping ipv4_tcp ipv4_udp ipv4_bind ipv4_runtime ipv4_netfilter" +TESTS_IPV6="ipv6_ping ipv6_tcp ipv6_udp ipv6_bind ipv6_runtime ipv6_netfilter"  TESTS_OTHER="use_cases"  PAUSE_ON_FAIL=no @@ -4077,3 +4100,11 @@ cleanup 2>/dev/null  printf "\nTests passed: %3d\n" ${nsuccess}  printf "Tests failed: %3d\n"   ${nfail} + +if [ $nfail -ne 0 ]; then +	exit 1 # KSFT_FAIL +elif [ $nsuccess -eq 0 ]; then +	exit $ksft_skip +fi + +exit 0 # KSFT_PASS diff --git a/tools/testing/selftests/net/fib_nexthops.sh b/tools/testing/selftests/net/fib_nexthops.sh index b5a69ad191b0..d444ee6aa3cb 100755 --- a/tools/testing/selftests/net/fib_nexthops.sh +++ b/tools/testing/selftests/net/fib_nexthops.sh @@ -629,6 +629,66 @@ ipv6_fcnal()  	log_test $? 0 "Nexthops removed on admin down"  } +ipv6_grp_refs() +{ +	if [ ! -x "$(command -v mausezahn)" ]; then +		echo "SKIP: Could not run test; need mausezahn tool" +		return +	fi + +	run_cmd "$IP link set dev veth1 up" +	run_cmd "$IP link add veth1.10 link veth1 up type vlan id 10" +	run_cmd "$IP link add veth1.20 link veth1 up type vlan id 20" +	run_cmd "$IP -6 addr add 2001:db8:91::1/64 dev veth1.10" +	run_cmd "$IP -6 addr add 2001:db8:92::1/64 dev veth1.20" +	run_cmd "$IP -6 neigh add 2001:db8:91::2 lladdr 00:11:22:33:44:55 dev veth1.10" +	run_cmd "$IP -6 neigh add 2001:db8:92::2 lladdr 00:11:22:33:44:55 dev veth1.20" +	run_cmd "$IP nexthop add id 100 via 2001:db8:91::2 dev veth1.10" +	run_cmd "$IP nexthop add id 101 via 2001:db8:92::2 dev veth1.20" +	run_cmd "$IP nexthop add id 102 group 100" +	run_cmd "$IP route add 2001:db8:101::1/128 nhid 102" + +	# create per-cpu dsts through nh 100 +	run_cmd "ip netns exec me mausezahn -6 veth1.10 -B 2001:db8:101::1 -A 2001:db8:91::1 -c 5 -t tcp "dp=1-1023, flags=syn" >/dev/null 2>&1" + +	# remove nh 100 from the group to delete the route potentially leaving +	# a stale per-cpu dst which holds a reference to the nexthop's net +	# device and to the IPv6 route +	run_cmd "$IP nexthop replace id 102 group 101" +	run_cmd "$IP route del 2001:db8:101::1/128" + +	# add both nexthops to the group so a reference is taken on them +	run_cmd "$IP nexthop replace id 102 group 100/101" + +	# if the bug described in commit "net: nexthop: release IPv6 per-cpu +	# dsts when replacing a nexthop group" exists at this point we have +	# an unlinked IPv6 route (but not freed due to stale dst) with a +	# reference over the group so we delete the group which will again +	# only unlink it due to the route reference +	run_cmd "$IP nexthop del id 102" + +	# delete the nexthop with stale dst, since we have an unlinked +	# group with a ref to it and an unlinked IPv6 route with ref to the +	# group, the nh will only be unlinked and not freed so the stale dst +	# remains forever and we get a net device refcount imbalance +	run_cmd "$IP nexthop del id 100" + +	# if a reference was lost this command will hang because the net device +	# cannot be removed +	timeout -s KILL 5 ip netns exec me ip link del veth1.10 >/dev/null 2>&1 + +	# we can't cleanup if the command is hung trying to delete the netdev +	if [ $? -eq 137 ]; then +		return 1 +	fi + +	# cleanup +	run_cmd "$IP link del veth1.20" +	run_cmd "$IP nexthop flush" + +	return 0 +} +  ipv6_grp_fcnal()  {  	local rc @@ -734,6 +794,9 @@ ipv6_grp_fcnal()  	run_cmd "$IP nexthop add id 108 group 31/24"  	log_test $? 2 "Nexthop group can not have a blackhole and another nexthop" + +	ipv6_grp_refs +	log_test $? 0 "Nexthop group replace refcounts"  }  ipv6_res_grp_fcnal() diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index 5abe92d55b69..996af1ae3d3d 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -444,24 +444,63 @@ fib_rp_filter_test()  	setup  	set -e +	ip netns add ns2 +	ip netns set ns2 auto + +	ip -netns ns2 link set dev lo up + +	$IP link add name veth1 type veth peer name veth2 +	$IP link set dev veth2 netns ns2 +	$IP address add 192.0.2.1/24 dev veth1 +	ip -netns ns2 address add 192.0.2.1/24 dev veth2 +	$IP link set dev veth1 up +	ip -netns ns2 link set dev veth2 up +  	$IP link set dev lo address 52:54:00:6a:c7:5e -	$IP link set dummy0 address 52:54:00:6a:c7:5e -	$IP link add dummy1 type dummy -	$IP link set dummy1 address 52:54:00:6a:c7:5e -	$IP link set dev dummy1 up +	$IP link set dev veth1 address 52:54:00:6a:c7:5e +	ip -netns ns2 link set dev lo address 52:54:00:6a:c7:5e +	ip -netns ns2 link set dev veth2 address 52:54:00:6a:c7:5e + +	# 1. (ns2) redirect lo's egress to veth2's egress +	ip netns exec ns2 tc qdisc add dev lo parent root handle 1: fq_codel +	ip netns exec ns2 tc filter add dev lo parent 1: protocol arp basic \ +		action mirred egress redirect dev veth2 +	ip netns exec ns2 tc filter add dev lo parent 1: protocol ip basic \ +		action mirred egress redirect dev veth2 + +	# 2. (ns1) redirect veth1's ingress to lo's ingress +	$NS_EXEC tc qdisc add dev veth1 ingress +	$NS_EXEC tc filter add dev veth1 ingress protocol arp basic \ +		action mirred ingress redirect dev lo +	$NS_EXEC tc filter add dev veth1 ingress protocol ip basic \ +		action mirred ingress redirect dev lo + +	# 3. (ns1) redirect lo's egress to veth1's egress +	$NS_EXEC tc qdisc add dev lo parent root handle 1: fq_codel +	$NS_EXEC tc filter add dev lo parent 1: protocol arp basic \ +		action mirred egress redirect dev veth1 +	$NS_EXEC tc filter add dev lo parent 1: protocol ip basic \ +		action mirred egress redirect dev veth1 + +	# 4. (ns2) redirect veth2's ingress to lo's ingress +	ip netns exec ns2 tc qdisc add dev veth2 ingress +	ip netns exec ns2 tc filter add dev veth2 ingress protocol arp basic \ +		action mirred ingress redirect dev lo +	ip netns exec ns2 tc filter add dev veth2 ingress protocol ip basic \ +		action mirred ingress redirect dev lo +  	$NS_EXEC sysctl -qw net.ipv4.conf.all.rp_filter=1  	$NS_EXEC sysctl -qw net.ipv4.conf.all.accept_local=1  	$NS_EXEC sysctl -qw net.ipv4.conf.all.route_localnet=1 - -	$NS_EXEC tc qd add dev dummy1 parent root handle 1: fq_codel -	$NS_EXEC tc filter add dev dummy1 parent 1: protocol arp basic action mirred egress redirect dev lo -	$NS_EXEC tc filter add dev dummy1 parent 1: protocol ip basic action mirred egress redirect dev lo +	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.rp_filter=1 +	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.accept_local=1 +	ip netns exec ns2 sysctl -qw net.ipv4.conf.all.route_localnet=1  	set +e -	run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 198.51.100.1" +	run_cmd "ip netns exec ns2 ping -w1 -c1 192.0.2.1"  	log_test $? 0 "rp_filter passes local packets" -	run_cmd "ip netns exec ns1 ping -I dummy1 -w1 -c1 127.0.0.1" +	run_cmd "ip netns exec ns2 ping -w1 -c1 127.0.0.1"  	log_test $? 0 "rp_filter passes loopback packets"  	cleanup diff --git a/tools/testing/selftests/net/forwarding/forwarding.config.sample b/tools/testing/selftests/net/forwarding/forwarding.config.sample index bf17e485684f..b0980a2efa31 100644 --- a/tools/testing/selftests/net/forwarding/forwarding.config.sample +++ b/tools/testing/selftests/net/forwarding/forwarding.config.sample @@ -13,6 +13,8 @@ NETIFS[p5]=veth4  NETIFS[p6]=veth5  NETIFS[p7]=veth6  NETIFS[p8]=veth7 +NETIFS[p9]=veth8 +NETIFS[p10]=veth9  # Port that does not have a cable connected.  NETIF_NO_CABLE=eth8 diff --git a/tools/testing/selftests/net/icmp_redirect.sh b/tools/testing/selftests/net/icmp_redirect.sh index ecbf57f264ed..7b9d6e31b8e7 100755 --- a/tools/testing/selftests/net/icmp_redirect.sh +++ b/tools/testing/selftests/net/icmp_redirect.sh @@ -311,7 +311,7 @@ check_exception()  		ip -netns h1 ro get ${H1_VRF_ARG} ${H2_N2_IP} | \  		grep -E -v 'mtu|redirected' | grep -q "cache"  	fi -	log_test $? 0 "IPv4: ${desc}" +	log_test $? 0 "IPv4: ${desc}" 0  	# No PMTU info for test "redirect" and "mtu exception plus redirect"  	if [ "$with_redirect" = "yes" ] && [ "$desc" != "redirect exception plus mtu" ]; then diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index e61fc4c32ba2..6e468e0f42f7 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -31,6 +31,8 @@ struct tls_crypto_info_keys {  		struct tls12_crypto_info_chacha20_poly1305 chacha20;  		struct tls12_crypto_info_sm4_gcm sm4gcm;  		struct tls12_crypto_info_sm4_ccm sm4ccm; +		struct tls12_crypto_info_aes_ccm_128 aesccm128; +		struct tls12_crypto_info_aes_gcm_256 aesgcm256;  	};  	size_t len;  }; @@ -61,6 +63,16 @@ static void tls_crypto_info_init(uint16_t tls_version, uint16_t cipher_type,  		tls12->sm4ccm.info.version = tls_version;  		tls12->sm4ccm.info.cipher_type = cipher_type;  		break; +	case TLS_CIPHER_AES_CCM_128: +		tls12->len = sizeof(struct tls12_crypto_info_aes_ccm_128); +		tls12->aesccm128.info.version = tls_version; +		tls12->aesccm128.info.cipher_type = cipher_type; +		break; +	case TLS_CIPHER_AES_GCM_256: +		tls12->len = sizeof(struct tls12_crypto_info_aes_gcm_256); +		tls12->aesgcm256.info.version = tls_version; +		tls12->aesgcm256.info.cipher_type = cipher_type; +		break;  	default:  		break;  	} @@ -78,26 +90,21 @@ static void memrnd(void *s, size_t n)  		*byte++ = rand();  } -FIXTURE(tls_basic) -{ -	int fd, cfd; -	bool notls; -}; - -FIXTURE_SETUP(tls_basic) +static void ulp_sock_pair(struct __test_metadata *_metadata, +			  int *fd, int *cfd, bool *notls)  {  	struct sockaddr_in addr;  	socklen_t len;  	int sfd, ret; -	self->notls = false; +	*notls = false;  	len = sizeof(addr);  	addr.sin_family = AF_INET;  	addr.sin_addr.s_addr = htonl(INADDR_ANY);  	addr.sin_port = 0; -	self->fd = socket(AF_INET, SOCK_STREAM, 0); +	*fd = socket(AF_INET, SOCK_STREAM, 0);  	sfd = socket(AF_INET, SOCK_STREAM, 0);  	ret = bind(sfd, &addr, sizeof(addr)); @@ -108,26 +115,96 @@ FIXTURE_SETUP(tls_basic)  	ret = getsockname(sfd, &addr, &len);  	ASSERT_EQ(ret, 0); -	ret = connect(self->fd, &addr, sizeof(addr)); +	ret = connect(*fd, &addr, sizeof(addr));  	ASSERT_EQ(ret, 0); -	self->cfd = accept(sfd, &addr, &len); -	ASSERT_GE(self->cfd, 0); +	*cfd = accept(sfd, &addr, &len); +	ASSERT_GE(*cfd, 0);  	close(sfd); -	ret = setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")); +	ret = setsockopt(*fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));  	if (ret != 0) {  		ASSERT_EQ(errno, ENOENT); -		self->notls = true; +		*notls = true;  		printf("Failure setting TCP_ULP, testing without tls\n");  		return;  	} -	ret = setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")); +	ret = setsockopt(*cfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls"));  	ASSERT_EQ(ret, 0);  } +/* Produce a basic cmsg */ +static int tls_send_cmsg(int fd, unsigned char record_type, +			 void *data, size_t len, int flags) +{ +	char cbuf[CMSG_SPACE(sizeof(char))]; +	int cmsg_len = sizeof(char); +	struct cmsghdr *cmsg; +	struct msghdr msg; +	struct iovec vec; + +	vec.iov_base = data; +	vec.iov_len = len; +	memset(&msg, 0, sizeof(struct msghdr)); +	msg.msg_iov = &vec; +	msg.msg_iovlen = 1; +	msg.msg_control = cbuf; +	msg.msg_controllen = sizeof(cbuf); +	cmsg = CMSG_FIRSTHDR(&msg); +	cmsg->cmsg_level = SOL_TLS; +	/* test sending non-record types. */ +	cmsg->cmsg_type = TLS_SET_RECORD_TYPE; +	cmsg->cmsg_len = CMSG_LEN(cmsg_len); +	*CMSG_DATA(cmsg) = record_type; +	msg.msg_controllen = cmsg->cmsg_len; + +	return sendmsg(fd, &msg, flags); +} + +static int tls_recv_cmsg(struct __test_metadata *_metadata, +			 int fd, unsigned char record_type, +			 void *data, size_t len, int flags) +{ +	char cbuf[CMSG_SPACE(sizeof(char))]; +	struct cmsghdr *cmsg; +	unsigned char ctype; +	struct msghdr msg; +	struct iovec vec; +	int n; + +	vec.iov_base = data; +	vec.iov_len = len; +	memset(&msg, 0, sizeof(struct msghdr)); +	msg.msg_iov = &vec; +	msg.msg_iovlen = 1; +	msg.msg_control = cbuf; +	msg.msg_controllen = sizeof(cbuf); + +	n = recvmsg(fd, &msg, flags); + +	cmsg = CMSG_FIRSTHDR(&msg); +	EXPECT_NE(cmsg, NULL); +	EXPECT_EQ(cmsg->cmsg_level, SOL_TLS); +	EXPECT_EQ(cmsg->cmsg_type, TLS_GET_RECORD_TYPE); +	ctype = *((unsigned char *)CMSG_DATA(cmsg)); +	EXPECT_EQ(ctype, record_type); + +	return n; +} + +FIXTURE(tls_basic) +{ +	int fd, cfd; +	bool notls; +}; + +FIXTURE_SETUP(tls_basic) +{ +	ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); +} +  FIXTURE_TEARDOWN(tls_basic)  {  	close(self->fd); @@ -196,63 +273,48 @@ FIXTURE_VARIANT_ADD(tls, 13_sm4_ccm)  	.cipher_type = TLS_CIPHER_SM4_CCM,  }; +FIXTURE_VARIANT_ADD(tls, 12_aes_ccm) +{ +	.tls_version = TLS_1_2_VERSION, +	.cipher_type = TLS_CIPHER_AES_CCM_128, +}; + +FIXTURE_VARIANT_ADD(tls, 13_aes_ccm) +{ +	.tls_version = TLS_1_3_VERSION, +	.cipher_type = TLS_CIPHER_AES_CCM_128, +}; + +FIXTURE_VARIANT_ADD(tls, 12_aes_gcm_256) +{ +	.tls_version = TLS_1_2_VERSION, +	.cipher_type = TLS_CIPHER_AES_GCM_256, +}; + +FIXTURE_VARIANT_ADD(tls, 13_aes_gcm_256) +{ +	.tls_version = TLS_1_3_VERSION, +	.cipher_type = TLS_CIPHER_AES_GCM_256, +}; +  FIXTURE_SETUP(tls)  {  	struct tls_crypto_info_keys tls12; -	struct sockaddr_in addr; -	socklen_t len; -	int sfd, ret; - -	self->notls = false; -	len = sizeof(addr); +	int ret;  	tls_crypto_info_init(variant->tls_version, variant->cipher_type,  			     &tls12); -	addr.sin_family = AF_INET; -	addr.sin_addr.s_addr = htonl(INADDR_ANY); -	addr.sin_port = 0; - -	self->fd = socket(AF_INET, SOCK_STREAM, 0); -	sfd = socket(AF_INET, SOCK_STREAM, 0); +	ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); -	ret = bind(sfd, &addr, sizeof(addr)); -	ASSERT_EQ(ret, 0); -	ret = listen(sfd, 10); -	ASSERT_EQ(ret, 0); +	if (self->notls) +		return; -	ret = getsockname(sfd, &addr, &len); +	ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len);  	ASSERT_EQ(ret, 0); -	ret = connect(self->fd, &addr, sizeof(addr)); +	ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len);  	ASSERT_EQ(ret, 0); - -	ret = setsockopt(self->fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")); -	if (ret != 0) { -		self->notls = true; -		printf("Failure setting TCP_ULP, testing without tls\n"); -	} - -	if (!self->notls) { -		ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, -				 tls12.len); -		ASSERT_EQ(ret, 0); -	} - -	self->cfd = accept(sfd, &addr, &len); -	ASSERT_GE(self->cfd, 0); - -	if (!self->notls) { -		ret = setsockopt(self->cfd, IPPROTO_TCP, TCP_ULP, "tls", -				 sizeof("tls")); -		ASSERT_EQ(ret, 0); - -		ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, -				 tls12.len); -		ASSERT_EQ(ret, 0); -	} - -	close(sfd);  }  FIXTURE_TEARDOWN(tls) @@ -613,6 +675,95 @@ TEST_F(tls, splice_to_pipe)  	EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);  } +TEST_F(tls, splice_cmsg_to_pipe) +{ +	char *test_str = "test_read"; +	char record_type = 100; +	int send_len = 10; +	char buf[10]; +	int p[2]; + +	ASSERT_GE(pipe(p), 0); +	EXPECT_EQ(tls_send_cmsg(self->fd, 100, test_str, send_len, 0), 10); +	EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, send_len, 0), -1); +	EXPECT_EQ(errno, EINVAL); +	EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); +	EXPECT_EQ(errno, EIO); +	EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, record_type, +				buf, sizeof(buf), MSG_WAITALL), +		  send_len); +	EXPECT_EQ(memcmp(test_str, buf, send_len), 0); +} + +TEST_F(tls, splice_dec_cmsg_to_pipe) +{ +	char *test_str = "test_read"; +	char record_type = 100; +	int send_len = 10; +	char buf[10]; +	int p[2]; + +	ASSERT_GE(pipe(p), 0); +	EXPECT_EQ(tls_send_cmsg(self->fd, 100, test_str, send_len, 0), 10); +	EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); +	EXPECT_EQ(errno, EIO); +	EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, send_len, 0), -1); +	EXPECT_EQ(errno, EINVAL); +	EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, record_type, +				buf, sizeof(buf), MSG_WAITALL), +		  send_len); +	EXPECT_EQ(memcmp(test_str, buf, send_len), 0); +} + +TEST_F(tls, recv_and_splice) +{ +	int send_len = TLS_PAYLOAD_MAX_LEN; +	char mem_send[TLS_PAYLOAD_MAX_LEN]; +	char mem_recv[TLS_PAYLOAD_MAX_LEN]; +	int half = send_len / 2; +	int p[2]; + +	ASSERT_GE(pipe(p), 0); +	EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len); +	/* Recv hald of the record, splice the other half */ +	EXPECT_EQ(recv(self->cfd, mem_recv, half, MSG_WAITALL), half); +	EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, half, SPLICE_F_NONBLOCK), +		  half); +	EXPECT_EQ(read(p[0], &mem_recv[half], half), half); +	EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); +} + +TEST_F(tls, peek_and_splice) +{ +	int send_len = TLS_PAYLOAD_MAX_LEN; +	char mem_send[TLS_PAYLOAD_MAX_LEN]; +	char mem_recv[TLS_PAYLOAD_MAX_LEN]; +	int chunk = TLS_PAYLOAD_MAX_LEN / 4; +	int n, i, p[2]; + +	memrnd(mem_send, sizeof(mem_send)); + +	ASSERT_GE(pipe(p), 0); +	for (i = 0; i < 4; i++) +		EXPECT_EQ(send(self->fd, &mem_send[chunk * i], chunk, 0), +			  chunk); + +	EXPECT_EQ(recv(self->cfd, mem_recv, chunk * 5 / 2, +		       MSG_WAITALL | MSG_PEEK), +		  chunk * 5 / 2); +	EXPECT_EQ(memcmp(mem_send, mem_recv, chunk * 5 / 2), 0); + +	n = 0; +	while (n < send_len) { +		i = splice(self->cfd, NULL, p[1], NULL, send_len - n, 0); +		EXPECT_GT(i, 0); +		n += i; +	} +	EXPECT_EQ(n, send_len); +	EXPECT_EQ(read(p[0], mem_recv, send_len), send_len); +	EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0); +} +  TEST_F(tls, recvmsg_single)  {  	char const *test_str = "test_recvmsg_single"; @@ -1193,60 +1344,30 @@ TEST_F(tls, mutliproc_sendpage_writers)  TEST_F(tls, control_msg)  { -	if (self->notls) -		return; - -	char cbuf[CMSG_SPACE(sizeof(char))]; -	char const *test_str = "test_read"; -	int cmsg_len = sizeof(char); +	char *test_str = "test_read";  	char record_type = 100; -	struct cmsghdr *cmsg; -	struct msghdr msg;  	int send_len = 10; -	struct iovec vec;  	char buf[10]; -	vec.iov_base = (char *)test_str; -	vec.iov_len = 10; -	memset(&msg, 0, sizeof(struct msghdr)); -	msg.msg_iov = &vec; -	msg.msg_iovlen = 1; -	msg.msg_control = cbuf; -	msg.msg_controllen = sizeof(cbuf); -	cmsg = CMSG_FIRSTHDR(&msg); -	cmsg->cmsg_level = SOL_TLS; -	/* test sending non-record types. */ -	cmsg->cmsg_type = TLS_SET_RECORD_TYPE; -	cmsg->cmsg_len = CMSG_LEN(cmsg_len); -	*CMSG_DATA(cmsg) = record_type; -	msg.msg_controllen = cmsg->cmsg_len; +	if (self->notls) +		SKIP(return, "no TLS support"); -	EXPECT_EQ(sendmsg(self->fd, &msg, 0), send_len); +	EXPECT_EQ(tls_send_cmsg(self->fd, record_type, test_str, send_len, 0), +		  send_len);  	/* Should fail because we didn't provide a control message */  	EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1); -	vec.iov_base = buf; -	EXPECT_EQ(recvmsg(self->cfd, &msg, MSG_WAITALL | MSG_PEEK), send_len); - -	cmsg = CMSG_FIRSTHDR(&msg); -	EXPECT_NE(cmsg, NULL); -	EXPECT_EQ(cmsg->cmsg_level, SOL_TLS); -	EXPECT_EQ(cmsg->cmsg_type, TLS_GET_RECORD_TYPE); -	record_type = *((unsigned char *)CMSG_DATA(cmsg)); -	EXPECT_EQ(record_type, 100); +	EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, record_type, +				buf, sizeof(buf), MSG_WAITALL | MSG_PEEK), +		  send_len);  	EXPECT_EQ(memcmp(buf, test_str, send_len), 0);  	/* Recv the message again without MSG_PEEK */ -	record_type = 0;  	memset(buf, 0, sizeof(buf)); -	EXPECT_EQ(recvmsg(self->cfd, &msg, MSG_WAITALL), send_len); -	cmsg = CMSG_FIRSTHDR(&msg); -	EXPECT_NE(cmsg, NULL); -	EXPECT_EQ(cmsg->cmsg_level, SOL_TLS); -	EXPECT_EQ(cmsg->cmsg_type, TLS_GET_RECORD_TYPE); -	record_type = *((unsigned char *)CMSG_DATA(cmsg)); -	EXPECT_EQ(record_type, 100); +	EXPECT_EQ(tls_recv_cmsg(_metadata, self->cfd, record_type, +				buf, sizeof(buf), MSG_WAITALL), +		  send_len);  	EXPECT_EQ(memcmp(buf, test_str, send_len), 0);  } @@ -1301,6 +1422,160 @@ TEST_F(tls, shutdown_reuse)  	EXPECT_EQ(errno, EISCONN);  } +FIXTURE(tls_err) +{ +	int fd, cfd; +	int fd2, cfd2; +	bool notls; +}; + +FIXTURE_VARIANT(tls_err) +{ +	uint16_t tls_version; +}; + +FIXTURE_VARIANT_ADD(tls_err, 12_aes_gcm) +{ +	.tls_version = TLS_1_2_VERSION, +}; + +FIXTURE_VARIANT_ADD(tls_err, 13_aes_gcm) +{ +	.tls_version = TLS_1_3_VERSION, +}; + +FIXTURE_SETUP(tls_err) +{ +	struct tls_crypto_info_keys tls12; +	int ret; + +	tls_crypto_info_init(variant->tls_version, TLS_CIPHER_AES_GCM_128, +			     &tls12); + +	ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls); +	ulp_sock_pair(_metadata, &self->fd2, &self->cfd2, &self->notls); +	if (self->notls) +		return; + +	ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len); +	ASSERT_EQ(ret, 0); + +	ret = setsockopt(self->cfd2, SOL_TLS, TLS_RX, &tls12, tls12.len); +	ASSERT_EQ(ret, 0); +} + +FIXTURE_TEARDOWN(tls_err) +{ +	close(self->fd); +	close(self->cfd); +	close(self->fd2); +	close(self->cfd2); +} + +TEST_F(tls_err, bad_rec) +{ +	char buf[64]; + +	if (self->notls) +		SKIP(return, "no TLS support"); + +	memset(buf, 0x55, sizeof(buf)); +	EXPECT_EQ(send(self->fd2, buf, sizeof(buf), 0), sizeof(buf)); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EMSGSIZE); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), MSG_DONTWAIT), -1); +	EXPECT_EQ(errno, EAGAIN); +} + +TEST_F(tls_err, bad_auth) +{ +	char buf[128]; +	int n; + +	if (self->notls) +		SKIP(return, "no TLS support"); + +	memrnd(buf, sizeof(buf) / 2); +	EXPECT_EQ(send(self->fd, buf, sizeof(buf) / 2, 0), sizeof(buf) / 2); +	n = recv(self->cfd, buf, sizeof(buf), 0); +	EXPECT_GT(n, sizeof(buf) / 2); + +	buf[n - 1]++; + +	EXPECT_EQ(send(self->fd2, buf, n, 0), n); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +} + +TEST_F(tls_err, bad_in_large_read) +{ +	char txt[3][64]; +	char cip[3][128]; +	char buf[3 * 128]; +	int i, n; + +	if (self->notls) +		SKIP(return, "no TLS support"); + +	/* Put 3 records in the sockets */ +	for (i = 0; i < 3; i++) { +		memrnd(txt[i], sizeof(txt[i])); +		EXPECT_EQ(send(self->fd, txt[i], sizeof(txt[i]), 0), +			  sizeof(txt[i])); +		n = recv(self->cfd, cip[i], sizeof(cip[i]), 0); +		EXPECT_GT(n, sizeof(txt[i])); +		/* Break the third message */ +		if (i == 2) +			cip[2][n - 1]++; +		EXPECT_EQ(send(self->fd2, cip[i], n, 0), n); +	} + +	/* We should be able to receive the first two messages */ +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), sizeof(txt[0]) * 2); +	EXPECT_EQ(memcmp(buf, txt[0], sizeof(txt[0])), 0); +	EXPECT_EQ(memcmp(buf + sizeof(txt[0]), txt[1], sizeof(txt[1])), 0); +	/* Third mesasge is bad */ +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +} + +TEST_F(tls_err, bad_cmsg) +{ +	char *test_str = "test_read"; +	int send_len = 10; +	char cip[128]; +	char buf[128]; +	char txt[64]; +	int n; + +	if (self->notls) +		SKIP(return, "no TLS support"); + +	/* Queue up one data record */ +	memrnd(txt, sizeof(txt)); +	EXPECT_EQ(send(self->fd, txt, sizeof(txt), 0), sizeof(txt)); +	n = recv(self->cfd, cip, sizeof(cip), 0); +	EXPECT_GT(n, sizeof(txt)); +	EXPECT_EQ(send(self->fd2, cip, n, 0), n); + +	EXPECT_EQ(tls_send_cmsg(self->fd, 100, test_str, send_len, 0), 10); +	n = recv(self->cfd, cip, sizeof(cip), 0); +	cip[n - 1]++; /* Break it */ +	EXPECT_GT(n, send_len); +	EXPECT_EQ(send(self->fd2, cip, n, 0), n); + +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), sizeof(txt)); +	EXPECT_EQ(memcmp(buf, txt, sizeof(txt)), 0); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +	EXPECT_EQ(recv(self->cfd2, buf, sizeof(buf), 0), -1); +	EXPECT_EQ(errno, EBADMSG); +} +  TEST(non_established) {  	struct tls12_crypto_info_aes_gcm_256 tls12;  	struct sockaddr_in addr; @@ -1355,64 +1630,82 @@ TEST(non_established) {  TEST(keysizes) {  	struct tls12_crypto_info_aes_gcm_256 tls12; -	struct sockaddr_in addr; -	int sfd, ret, fd, cfd; -	socklen_t len; +	int ret, fd, cfd;  	bool notls; -	notls = false; -	len = sizeof(addr); -  	memset(&tls12, 0, sizeof(tls12));  	tls12.info.version = TLS_1_2_VERSION;  	tls12.info.cipher_type = TLS_CIPHER_AES_GCM_256; -	addr.sin_family = AF_INET; -	addr.sin_addr.s_addr = htonl(INADDR_ANY); -	addr.sin_port = 0; +	ulp_sock_pair(_metadata, &fd, &cfd, ¬ls); -	fd = socket(AF_INET, SOCK_STREAM, 0); -	sfd = socket(AF_INET, SOCK_STREAM, 0); +	if (!notls) { +		ret = setsockopt(fd, SOL_TLS, TLS_TX, &tls12, +				 sizeof(tls12)); +		EXPECT_EQ(ret, 0); + +		ret = setsockopt(cfd, SOL_TLS, TLS_RX, &tls12, +				 sizeof(tls12)); +		EXPECT_EQ(ret, 0); +	} + +	close(fd); +	close(cfd); +} + +TEST(tls_v6ops) { +	struct tls_crypto_info_keys tls12; +	struct sockaddr_in6 addr, addr2; +	int sfd, ret, fd; +	socklen_t len, len2; + +	tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12); + +	addr.sin6_family = AF_INET6; +	addr.sin6_addr = in6addr_any; +	addr.sin6_port = 0; + +	fd = socket(AF_INET6, SOCK_STREAM, 0); +	sfd = socket(AF_INET6, SOCK_STREAM, 0);  	ret = bind(sfd, &addr, sizeof(addr));  	ASSERT_EQ(ret, 0);  	ret = listen(sfd, 10);  	ASSERT_EQ(ret, 0); +	len = sizeof(addr);  	ret = getsockname(sfd, &addr, &len);  	ASSERT_EQ(ret, 0);  	ret = connect(fd, &addr, sizeof(addr));  	ASSERT_EQ(ret, 0); +	len = sizeof(addr); +	ret = getsockname(fd, &addr, &len); +	ASSERT_EQ(ret, 0); +  	ret = setsockopt(fd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")); -	if (ret != 0) { -		notls = true; -		printf("Failure setting TCP_ULP, testing without tls\n"); +	if (ret) { +		ASSERT_EQ(errno, ENOENT); +		SKIP(return, "no TLS support");  	} +	ASSERT_EQ(ret, 0); -	if (!notls) { -		ret = setsockopt(fd, SOL_TLS, TLS_TX, &tls12, -				 sizeof(tls12)); -		EXPECT_EQ(ret, 0); -	} +	ret = setsockopt(fd, SOL_TLS, TLS_TX, &tls12, tls12.len); +	ASSERT_EQ(ret, 0); -	cfd = accept(sfd, &addr, &len); -	ASSERT_GE(cfd, 0); +	ret = setsockopt(fd, SOL_TLS, TLS_RX, &tls12, tls12.len); +	ASSERT_EQ(ret, 0); -	if (!notls) { -		ret = setsockopt(cfd, IPPROTO_TCP, TCP_ULP, "tls", -				 sizeof("tls")); -		EXPECT_EQ(ret, 0); +	len2 = sizeof(addr2); +	ret = getsockname(fd, &addr2, &len2); +	ASSERT_EQ(ret, 0); -		ret = setsockopt(cfd, SOL_TLS, TLS_RX, &tls12, -				 sizeof(tls12)); -		EXPECT_EQ(ret, 0); -	} +	EXPECT_EQ(len2, len); +	EXPECT_EQ(memcmp(&addr, &addr2, len), 0); -	close(sfd);  	close(fd); -	close(cfd); +	close(sfd);  }  TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/net/toeplitz.c b/tools/testing/selftests/net/toeplitz.c index 710ac956bdb3..c5489341cfb8 100644 --- a/tools/testing/selftests/net/toeplitz.c +++ b/tools/testing/selftests/net/toeplitz.c @@ -498,7 +498,7 @@ static void parse_opts(int argc, char **argv)  	bool have_toeplitz = false;  	int index, c; -	while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:u:v", long_options, &index)) != -1) { +	while ((c = getopt_long(argc, argv, "46C:d:i:k:r:stT:uv", long_options, &index)) != -1) {  		switch (c) {  		case '4':  			cfg_family = AF_INET; |