@@ -666,6 +666,111 @@ pub fn test_af_alg_aead() {
666
666
assert_eq ! ( decrypted[ ( assoc_size as usize ) ..( payload_len + ( assoc_size as usize ) ) ] , payload[ ( assoc_size as usize ) ..payload_len + ( assoc_size as usize ) ] ) ;
667
667
}
668
668
669
+ // Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`.
670
+ // This creates a (udp) socket bound to localhost, then sends a message to
671
+ // itself but uses Ipv4PacketInfo to force the source address to be localhost.
672
+ //
673
+ // This would be a more interesting test if we could assume that the test host
674
+ // has more than one IP address (since we could select a different address to
675
+ // test from).
676
+ #[ cfg( any( target_os = "linux" ,
677
+ target_os = "macos" ,
678
+ target_os = "netbsd" ) ) ]
679
+ #[ test]
680
+ pub fn test_sendmsg_ipv4packetinfo ( ) {
681
+ use nix:: sys:: uio:: IoVec ;
682
+ use nix:: sys:: socket:: { socket, sendmsg, bind,
683
+ AddressFamily , SockType , SockFlag , SockAddr ,
684
+ ControlMessage , MsgFlags } ;
685
+
686
+ let sock = socket ( AddressFamily :: Inet ,
687
+ SockType :: Datagram ,
688
+ SockFlag :: empty ( ) ,
689
+ None )
690
+ . expect ( "socket failed" ) ;
691
+
692
+ let std_sa = SocketAddr :: from_str ( "127.0.0.1:4000" ) . unwrap ( ) ;
693
+ let inet_addr = InetAddr :: from_std ( & std_sa) ;
694
+ let sock_addr = SockAddr :: new_inet ( inet_addr) ;
695
+
696
+ bind ( sock, & sock_addr) . expect ( "bind failed" ) ;
697
+
698
+ let slice = [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
699
+ let iov = [ IoVec :: from_slice ( & slice) ] ;
700
+
701
+ if let InetAddr :: V4 ( sin) = inet_addr {
702
+ let pi = libc:: in_pktinfo {
703
+ ipi_ifindex : 0 , /* Unspecified interface */
704
+ ipi_addr : libc:: in_addr { s_addr : 0 } ,
705
+ ipi_spec_dst : sin. sin_addr ,
706
+ } ;
707
+
708
+ let cmsg = [ ControlMessage :: Ipv4PacketInfo ( & pi) ] ;
709
+
710
+ sendmsg ( sock, & iov, & cmsg, MsgFlags :: empty ( ) , Some ( & sock_addr) )
711
+ . expect ( "sendmsg" ) ;
712
+ } else {
713
+ panic ! ( "No IPv4 addresses available for testing?" ) ;
714
+ }
715
+ }
716
+
717
+ // Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
718
+ // This creates a (udp) socket bound to ip6-localhost, then sends a message to
719
+ // itself but uses Ipv6PacketInfo to force the source address to be
720
+ // ip6-localhost.
721
+ //
722
+ // This would be a more interesting test if we could assume that the test host
723
+ // has more than one IP address (since we could select a different address to
724
+ // test from).
725
+ #[ cfg( any( target_os = "linux" ,
726
+ target_os = "macos" ,
727
+ target_os = "netbsd" ,
728
+ target_os = "freebsd" ) ) ]
729
+ #[ test]
730
+ pub fn test_sendmsg_ipv6packetinfo ( ) {
731
+ use nix:: Error ;
732
+ use nix:: errno:: Errno ;
733
+ use nix:: sys:: uio:: IoVec ;
734
+ use nix:: sys:: socket:: { socket, sendmsg, bind,
735
+ AddressFamily , SockType , SockFlag , SockAddr ,
736
+ ControlMessage , MsgFlags } ;
737
+
738
+ let sock = socket ( AddressFamily :: Inet6 ,
739
+ SockType :: Datagram ,
740
+ SockFlag :: empty ( ) ,
741
+ None )
742
+ . expect ( "socket failed" ) ;
743
+
744
+ let std_sa = SocketAddr :: from_str ( "[::1]:6000" ) . unwrap ( ) ;
745
+ let inet_addr = InetAddr :: from_std ( & std_sa) ;
746
+ let sock_addr = SockAddr :: new_inet ( inet_addr) ;
747
+
748
+ match bind ( sock, & sock_addr) {
749
+ Err ( Error :: Sys ( Errno :: EADDRNOTAVAIL ) ) => {
750
+ println ! ( "IPv6 not available, skipping test." ) ;
751
+ return ;
752
+ } ,
753
+ _ => ( ) ,
754
+ }
755
+
756
+ let slice = [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
757
+ let iov = [ IoVec :: from_slice ( & slice) ] ;
758
+
759
+ if let InetAddr :: V6 ( sin) = inet_addr {
760
+ let pi = libc:: in6_pktinfo {
761
+ ipi6_ifindex : 0 , /* Unspecified interface */
762
+ ipi6_addr : sin. sin6_addr ,
763
+ } ;
764
+
765
+ let cmsg = [ ControlMessage :: Ipv6PacketInfo ( & pi) ] ;
766
+
767
+ sendmsg ( sock, & iov, & cmsg, MsgFlags :: empty ( ) , Some ( & sock_addr) )
768
+ . expect ( "sendmsg" ) ;
769
+ } else {
770
+ println ! ( "No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo" ) ;
771
+ }
772
+ }
773
+
669
774
/// Tests that passing multiple fds using a single `ControlMessage` works.
670
775
// Disable the test on emulated platforms due to a bug in QEMU versions <
671
776
// 2.12.0. https://bugs.launchpad.net/qemu/+bug/1701808
0 commit comments