@@ -131,14 +131,14 @@ fn test_so_listen_q_limit() {
131131#[ test]
132132fn test_so_tcp_maxseg ( ) {
133133 use nix:: sys:: socket:: {
134- accept, bind, connect, listen, Backlog , SockaddrIn ,
134+ accept, bind, connect, getsockname , listen, Backlog , SockaddrIn ,
135135 } ;
136136 use nix:: unistd:: write;
137137 use std:: net:: SocketAddrV4 ;
138138 use std:: str:: FromStr ;
139139
140- let std_sa = SocketAddrV4 :: from_str ( "127.0.0.1:4003 " ) . unwrap ( ) ;
141- let sock_addr = SockaddrIn :: from ( std_sa) ;
140+ let std_sa = SocketAddrV4 :: from_str ( "127.0.0.1:0 " ) . unwrap ( ) ;
141+ let mut sock_addr = SockaddrIn :: from ( std_sa) ;
142142
143143 let rsock = socket (
144144 AddressFamily :: Inet ,
@@ -148,6 +148,7 @@ fn test_so_tcp_maxseg() {
148148 )
149149 . unwrap ( ) ;
150150 bind ( rsock. as_raw_fd ( ) , & sock_addr) . unwrap ( ) ;
151+ sock_addr = getsockname ( rsock. as_raw_fd ( ) ) . unwrap ( ) ;
151152 listen ( & rsock, Backlog :: new ( 10 ) . unwrap ( ) ) . unwrap ( ) ;
152153 let initial = getsockopt ( & rsock, sockopt:: TcpMaxSeg ) . unwrap ( ) ;
153154 // Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
@@ -305,7 +306,7 @@ fn test_get_mtu() {
305306 use std:: net:: SocketAddrV4 ;
306307 use std:: str:: FromStr ;
307308
308- let std_sa = SocketAddrV4 :: from_str ( "127.0.0.1:4001 " ) . unwrap ( ) ;
309+ let std_sa = SocketAddrV4 :: from_str ( "127.0.0.1:0 " ) . unwrap ( ) ;
309310 let std_sb = SocketAddrV4 :: from_str ( "127.0.0.1:4002" ) . unwrap ( ) ;
310311
311312 let usock = socket (
@@ -615,7 +616,7 @@ fn test_ts_clock_monotonic() {
615616
616617#[ test]
617618#[ cfg( linux_android) ]
618- // Disable the test under emulation because it failsi with ENOPROTOOPT in CI
619+ // Disable the test under emulation because it fails with ENOPROTOOPT in CI
619620// on cross target. Lack of QEMU support is suspected.
620621#[ cfg_attr( qemu, ignore) ]
621622fn test_ip_bind_address_no_port ( ) {
@@ -735,3 +736,95 @@ fn can_get_listen_on_tcp_socket() {
735736 let s_listening2 = getsockopt ( & s, sockopt:: AcceptConn ) . unwrap ( ) ;
736737 assert ! ( s_listening2) ;
737738}
739+
740+ #[ cfg( target_os = "linux" ) ]
741+ // Some architectures running under cross don't support `setsockopt(SOL_TCP, TCP_ULP)`
742+ // because the cross image is based on Ubuntu 16.04 which predates TCP ULP support
743+ // (it was added in kernel v4.13 released in 2017). For these architectures,
744+ // the `setsockopt(SOL_TCP, TCP_ULP, "tls", sizeof("tls"))` call succeeds
745+ // but the subsequent `setsockopt(SOL_TLS, TLS_TX, ...)` call fails with `ENOPROTOOPT`.
746+ // It's as if the first `setsockopt` call enabled some other option, not `TCP_ULP`.
747+ // For example, `strace` says:
748+ //
749+ // [pid 813] setsockopt(4, SOL_TCP, 0x1f /* TCP_??? */, [7564404], 4) = 0
750+ //
751+ // It's not clear why `setsockopt(SOL_TCP, TCP_ULP)` succeeds if the container image libc doesn't support it,
752+ // but in any case we can't run the test on such an architecture, so skip it.
753+ #[ cfg_attr( qemu, ignore) ]
754+ #[ test]
755+ fn test_ktls ( ) {
756+ use nix:: sys:: socket:: {
757+ accept, bind, connect, getsockname, listen, Backlog , SockaddrIn ,
758+ } ;
759+ use std:: net:: SocketAddrV4 ;
760+ use std:: str:: FromStr ;
761+
762+ let std_sa = SocketAddrV4 :: from_str ( "127.0.0.1:0" ) . unwrap ( ) ;
763+ let mut sock_addr = SockaddrIn :: from ( std_sa) ;
764+
765+ let rsock = socket (
766+ AddressFamily :: Inet ,
767+ SockType :: Stream ,
768+ SockFlag :: empty ( ) ,
769+ SockProtocol :: Tcp ,
770+ )
771+ . unwrap ( ) ;
772+ bind ( rsock. as_raw_fd ( ) , & sock_addr) . unwrap ( ) ;
773+ sock_addr = getsockname ( rsock. as_raw_fd ( ) ) . unwrap ( ) ;
774+ listen ( & rsock, Backlog :: new ( 10 ) . unwrap ( ) ) . unwrap ( ) ;
775+
776+ let ssock = socket (
777+ AddressFamily :: Inet ,
778+ SockType :: Stream ,
779+ SockFlag :: empty ( ) ,
780+ SockProtocol :: Tcp ,
781+ )
782+ . unwrap ( ) ;
783+ connect ( ssock. as_raw_fd ( ) , & sock_addr) . unwrap ( ) ;
784+
785+ let _rsess = accept ( rsock. as_raw_fd ( ) ) . unwrap ( ) ;
786+
787+ match setsockopt ( & ssock, sockopt:: TcpUlp :: default ( ) , b"tls" ) {
788+ Ok ( ( ) ) => ( ) ,
789+
790+ // TLS ULP is not enabled, so we can't test kTLS.
791+ Err ( nix:: Error :: ENOENT ) => skip ! ( "TLS ULP is not enabled" ) ,
792+
793+ Err ( err) => panic ! ( "{err:?}" ) ,
794+ }
795+
796+ // In real life we would do a TLS handshake and extract the protocol version and secrets.
797+ // For this test we just make some up.
798+
799+ let tx = sockopt:: TlsCryptoInfo :: Aes128Gcm ( libc:: tls12_crypto_info_aes_gcm_128 {
800+ info : libc:: tls_crypto_info {
801+ version : libc:: TLS_1_2_VERSION ,
802+ cipher_type : libc:: TLS_CIPHER_AES_GCM_128 ,
803+ } ,
804+ iv : * b"\x04 \x05 \x06 \x07 \x08 \x09 \x0a \x0b " ,
805+ key : * b"\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1a \x1b \x1c \x1d \x1e \x1f " ,
806+ salt : * b"\x00 \x01 \x02 \x03 " ,
807+ rec_seq : * b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ,
808+ } ) ;
809+ setsockopt ( & ssock, sockopt:: TcpTlsTx , & tx)
810+ . expect ( "setting TLS_TX after enabling TLS ULP should succeed" ) ;
811+
812+ let rx = sockopt:: TlsCryptoInfo :: Aes128Gcm ( libc:: tls12_crypto_info_aes_gcm_128 {
813+ info : libc:: tls_crypto_info {
814+ version : libc:: TLS_1_2_VERSION ,
815+ cipher_type : libc:: TLS_CIPHER_AES_GCM_128 ,
816+ } ,
817+ iv : * b"\xf4 \xf5 \xf6 \xf7 \xf8 \xf9 \xfa \xfb " ,
818+ key : * b"\xe0 \xe1 \xe2 \xe3 \xe4 \xe5 \xe6 \xe7 \xe8 \xe9 \xea \xeb \xec \xed \xee \xef " ,
819+ salt : * b"\xf0 \xf1 \xf2 \xf3 " ,
820+ rec_seq : * b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 " ,
821+ } ) ;
822+ match setsockopt ( & ssock, sockopt:: TcpTlsRx , & rx) {
823+ Ok ( ( ) ) => ( ) ,
824+ Err ( nix:: Error :: ENOPROTOOPT ) => {
825+ // TLS_TX was added in v4.13 and TLS_RX in v4.17, so we appear to be between that range.
826+ // It's good enough that TLS_TX worked, so let the test succeed.
827+ }
828+ Err ( err) => panic ! ( "{err:?}" ) ,
829+ }
830+ }
0 commit comments