2022-08-17 09:18:47 +03:00
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
# define _GNU_SOURCE
# include <sched.h>
# include <linux/socket.h>
2023-01-25 23:16:08 +03:00
# include <linux/tls.h>
2022-08-17 09:18:47 +03:00
# include <net/if.h>
# include "test_progs.h"
# include "cgroup_helpers.h"
# include "network_helpers.h"
# include "setget_sockopt.skel.h"
# define CG_NAME " / setget-sockopt-test"
static const char addr4_str [ ] = " 127.0.0.1 " ;
static const char addr6_str [ ] = " ::1 " ;
static struct setget_sockopt * skel ;
static int cg_fd ;
static int create_netns ( void )
{
if ( ! ASSERT_OK ( unshare ( CLONE_NEWNET ) , " create netns " ) )
return - 1 ;
if ( ! ASSERT_OK ( system ( " ip link set dev lo up " ) , " set lo up " ) )
return - 1 ;
if ( ! ASSERT_OK ( system ( " ip link add dev binddevtest1 type veth peer name binddevtest2 " ) ,
" add veth " ) )
return - 1 ;
if ( ! ASSERT_OK ( system ( " ip link set dev binddevtest1 up " ) ,
" bring veth up " ) )
return - 1 ;
return 0 ;
}
static void test_tcp ( int family )
{
struct setget_sockopt__bss * bss = skel - > bss ;
int sfd , cfd ;
memset ( bss , 0 , sizeof ( * bss ) ) ;
sfd = start_server ( family , SOCK_STREAM ,
family = = AF_INET6 ? addr6_str : addr4_str , 0 , 0 ) ;
if ( ! ASSERT_GE ( sfd , 0 , " start_server " ) )
return ;
cfd = connect_to_fd ( sfd , 0 ) ;
if ( ! ASSERT_GE ( cfd , 0 , " connect_to_fd_server " ) ) {
close ( sfd ) ;
return ;
}
close ( sfd ) ;
close ( cfd ) ;
ASSERT_EQ ( bss - > nr_listen , 1 , " nr_listen " ) ;
ASSERT_EQ ( bss - > nr_connect , 1 , " nr_connect " ) ;
ASSERT_EQ ( bss - > nr_active , 1 , " nr_active " ) ;
ASSERT_EQ ( bss - > nr_passive , 1 , " nr_passive " ) ;
ASSERT_EQ ( bss - > nr_socket_post_create , 2 , " nr_socket_post_create " ) ;
ASSERT_EQ ( bss - > nr_binddev , 2 , " nr_bind " ) ;
}
static void test_udp ( int family )
{
struct setget_sockopt__bss * bss = skel - > bss ;
int sfd ;
memset ( bss , 0 , sizeof ( * bss ) ) ;
sfd = start_server ( family , SOCK_DGRAM ,
family = = AF_INET6 ? addr6_str : addr4_str , 0 , 0 ) ;
if ( ! ASSERT_GE ( sfd , 0 , " start_server " ) )
return ;
close ( sfd ) ;
ASSERT_GE ( bss - > nr_socket_post_create , 1 , " nr_socket_post_create " ) ;
ASSERT_EQ ( bss - > nr_binddev , 1 , " nr_bind " ) ;
}
2023-01-25 23:16:08 +03:00
static void test_ktls ( int family )
{
struct tls12_crypto_info_aes_gcm_128 aes128 ;
struct setget_sockopt__bss * bss = skel - > bss ;
int cfd = - 1 , sfd = - 1 , fd = - 1 , ret ;
char buf ;
memset ( bss , 0 , sizeof ( * bss ) ) ;
sfd = start_server ( family , SOCK_STREAM ,
family = = AF_INET6 ? addr6_str : addr4_str , 0 , 0 ) ;
if ( ! ASSERT_GE ( sfd , 0 , " start_server " ) )
return ;
fd = connect_to_fd ( sfd , 0 ) ;
if ( ! ASSERT_GE ( fd , 0 , " connect_to_fd " ) )
goto err_out ;
cfd = accept ( sfd , NULL , 0 ) ;
if ( ! ASSERT_GE ( cfd , 0 , " accept " ) )
goto err_out ;
close ( sfd ) ;
sfd = - 1 ;
/* Setup KTLS */
ret = setsockopt ( fd , IPPROTO_TCP , TCP_ULP , " tls " , sizeof ( " tls " ) ) ;
if ( ! ASSERT_OK ( ret , " setsockopt " ) )
goto err_out ;
ret = setsockopt ( cfd , IPPROTO_TCP , TCP_ULP , " tls " , sizeof ( " tls " ) ) ;
if ( ! ASSERT_OK ( ret , " setsockopt " ) )
goto err_out ;
memset ( & aes128 , 0 , sizeof ( aes128 ) ) ;
aes128 . info . version = TLS_1_2_VERSION ;
aes128 . info . cipher_type = TLS_CIPHER_AES_GCM_128 ;
ret = setsockopt ( fd , SOL_TLS , TLS_TX , & aes128 , sizeof ( aes128 ) ) ;
if ( ! ASSERT_OK ( ret , " setsockopt " ) )
goto err_out ;
ret = setsockopt ( cfd , SOL_TLS , TLS_RX , & aes128 , sizeof ( aes128 ) ) ;
if ( ! ASSERT_OK ( ret , " setsockopt " ) )
goto err_out ;
/* KTLS is enabled */
close ( fd ) ;
/* At this point, the cfd socket is at the CLOSE_WAIT state
* and still run TLS protocol . The test for
* BPF_TCP_CLOSE_WAIT should be run at this point .
*/
ret = read ( cfd , & buf , sizeof ( buf ) ) ;
ASSERT_EQ ( ret , 0 , " read " ) ;
close ( cfd ) ;
ASSERT_EQ ( bss - > nr_listen , 1 , " nr_listen " ) ;
ASSERT_EQ ( bss - > nr_connect , 1 , " nr_connect " ) ;
ASSERT_EQ ( bss - > nr_active , 1 , " nr_active " ) ;
ASSERT_EQ ( bss - > nr_passive , 1 , " nr_passive " ) ;
ASSERT_EQ ( bss - > nr_socket_post_create , 2 , " nr_socket_post_create " ) ;
ASSERT_EQ ( bss - > nr_binddev , 2 , " nr_bind " ) ;
ASSERT_EQ ( bss - > nr_fin_wait1 , 1 , " nr_fin_wait1 " ) ;
return ;
err_out :
close ( fd ) ;
close ( cfd ) ;
close ( sfd ) ;
}
2022-08-17 09:18:47 +03:00
void test_setget_sockopt ( void )
{
cg_fd = test__join_cgroup ( CG_NAME ) ;
if ( cg_fd < 0 )
return ;
if ( create_netns ( ) )
goto done ;
skel = setget_sockopt__open ( ) ;
if ( ! ASSERT_OK_PTR ( skel , " open skel " ) )
goto done ;
strcpy ( skel - > rodata - > veth , " binddevtest1 " ) ;
skel - > rodata - > veth_ifindex = if_nametoindex ( " binddevtest1 " ) ;
if ( ! ASSERT_GT ( skel - > rodata - > veth_ifindex , 0 , " if_nametoindex " ) )
goto done ;
if ( ! ASSERT_OK ( setget_sockopt__load ( skel ) , " load skel " ) )
goto done ;
skel - > links . skops_sockopt =
bpf_program__attach_cgroup ( skel - > progs . skops_sockopt , cg_fd ) ;
if ( ! ASSERT_OK_PTR ( skel - > links . skops_sockopt , " attach cgroup " ) )
goto done ;
skel - > links . socket_post_create =
bpf_program__attach_cgroup ( skel - > progs . socket_post_create , cg_fd ) ;
if ( ! ASSERT_OK_PTR ( skel - > links . socket_post_create , " attach_cgroup " ) )
goto done ;
test_tcp ( AF_INET6 ) ;
test_tcp ( AF_INET ) ;
test_udp ( AF_INET6 ) ;
test_udp ( AF_INET ) ;
2023-01-25 23:16:08 +03:00
test_ktls ( AF_INET6 ) ;
test_ktls ( AF_INET ) ;
2022-08-17 09:18:47 +03:00
done :
setget_sockopt__destroy ( skel ) ;
close ( cg_fd ) ;
}