@@ -1745,6 +1745,174 @@ pub fn test_recvif() {
1745
1745
}
1746
1746
}
1747
1747
1748
+ #[ cfg( any( target_os = "android" , target_os = "freebsd" , target_os = "linux" ) ) ]
1749
+ #[ test]
1750
+ pub fn test_recvif_ipv4 ( ) {
1751
+ use nix:: sys:: socket:: sockopt:: { Ipv4RecvOrigDstAddr } ;
1752
+ use nix:: sys:: socket:: { bind, SockFlag , SockType , SockaddrIn } ;
1753
+ use nix:: sys:: socket:: { getsockname, setsockopt, socket} ;
1754
+ use nix:: sys:: socket:: { recvmsg, sendmsg, ControlMessageOwned , MsgFlags } ;
1755
+ use std:: io:: { IoSlice , IoSliceMut } ;
1756
+
1757
+ let lo_ifaddr = loopback_address ( AddressFamily :: Inet ) ;
1758
+ let ( _lo_name, lo) = match lo_ifaddr {
1759
+ Some ( ifaddr) => (
1760
+ ifaddr. interface_name ,
1761
+ ifaddr. address . expect ( "Expect IPv4 address on interface" ) ,
1762
+ ) ,
1763
+ None => return ,
1764
+ } ;
1765
+ let receive = socket (
1766
+ AddressFamily :: Inet ,
1767
+ SockType :: Datagram ,
1768
+ SockFlag :: empty ( ) ,
1769
+ None ,
1770
+ )
1771
+ . expect ( "receive socket failed" ) ;
1772
+ bind ( receive, & lo) . expect ( "bind failed" ) ;
1773
+ let sa: SockaddrIn = getsockname ( receive) . expect ( "getsockname failed" ) ;
1774
+ setsockopt ( receive, Ipv4RecvOrigDstAddr , & true )
1775
+ . expect ( "setsockopt IP_RECVORIGDSTADDR failed" ) ;
1776
+
1777
+ {
1778
+ let slice = [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
1779
+ let iov = [ IoSlice :: new ( & slice) ] ;
1780
+
1781
+ let send = socket (
1782
+ AddressFamily :: Inet ,
1783
+ SockType :: Datagram ,
1784
+ SockFlag :: empty ( ) ,
1785
+ None ,
1786
+ )
1787
+ . expect ( "send socket failed" ) ;
1788
+ sendmsg ( send, & iov, & [ ] , MsgFlags :: empty ( ) , Some ( & sa) )
1789
+ . expect ( "sendmsg failed" ) ;
1790
+ }
1791
+
1792
+ {
1793
+ let mut buf = [ 0u8 ; 8 ] ;
1794
+ let mut iovec = [ IoSliceMut :: new ( & mut buf) ] ;
1795
+ let mut space = cmsg_space ! ( libc:: in_addr, [ u8 ; 0 ] ) ;
1796
+ let msg = recvmsg :: < ( ) > (
1797
+ receive,
1798
+ & mut iovec,
1799
+ Some ( & mut space) ,
1800
+ MsgFlags :: empty ( ) ,
1801
+ )
1802
+ . expect ( "recvmsg failed" ) ;
1803
+ assert ! ( !msg
1804
+ . flags
1805
+ . intersects( MsgFlags :: MSG_TRUNC | MsgFlags :: MSG_CTRUNC ) ) ;
1806
+ assert_eq ! ( msg. cmsgs( ) . count( ) , 1 , "expected 1 cmsgs" ) ;
1807
+
1808
+ let mut rx_recvorigdstaddr = false ;
1809
+ for cmsg in msg. cmsgs ( ) {
1810
+ match cmsg {
1811
+ ControlMessageOwned :: Ipv4RecvOrigDstAddr ( addr) => {
1812
+ rx_recvorigdstaddr = true ;
1813
+ if let Some ( sin) = lo. as_sockaddr_in ( ) {
1814
+ assert_eq ! ( sin. as_ref( ) . sin_addr. s_addr,
1815
+ addr. s_addr,
1816
+ "unexpected destination address (expected {}, got {})" ,
1817
+ sin. as_ref( ) . sin_addr. s_addr,
1818
+ addr. s_addr) ;
1819
+ } else {
1820
+ panic ! ( "unexpected Sockaddr" ) ;
1821
+ }
1822
+ }
1823
+ _ => panic ! ( "unexpected additional control msg" ) ,
1824
+ }
1825
+ }
1826
+ assert ! ( rx_recvorigdstaddr) ;
1827
+ assert_eq ! ( msg. bytes, 8 ) ;
1828
+ assert_eq ! ( * iovec[ 0 ] , [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ) ;
1829
+ }
1830
+ }
1831
+
1832
+ #[ cfg( any( target_os = "android" , target_os = "freebsd" , target_os = "linux" ) ) ]
1833
+ #[ test]
1834
+ pub fn test_recvif_ipv6 ( ) {
1835
+ use nix:: sys:: socket:: sockopt:: { Ipv6RecvOrigDstAddr } ;
1836
+ use nix:: sys:: socket:: { bind, SockFlag , SockType , SockaddrIn6 } ;
1837
+ use nix:: sys:: socket:: { getsockname, setsockopt, socket} ;
1838
+ use nix:: sys:: socket:: { recvmsg, sendmsg, ControlMessageOwned , MsgFlags } ;
1839
+ use std:: io:: { IoSlice , IoSliceMut } ;
1840
+
1841
+ let lo_ifaddr = loopback_address ( AddressFamily :: Inet6 ) ;
1842
+ let ( _lo_name, lo) = match lo_ifaddr {
1843
+ Some ( ifaddr) => (
1844
+ ifaddr. interface_name ,
1845
+ ifaddr. address . expect ( "Expect IPv6 address on interface" ) ,
1846
+ ) ,
1847
+ None => return ,
1848
+ } ;
1849
+ let receive = socket (
1850
+ AddressFamily :: Inet6 ,
1851
+ SockType :: Datagram ,
1852
+ SockFlag :: empty ( ) ,
1853
+ None ,
1854
+ )
1855
+ . expect ( "receive socket failed" ) ;
1856
+ bind ( receive, & lo) . expect ( "bind failed" ) ;
1857
+ let sa: SockaddrIn6 = getsockname ( receive) . expect ( "getsockname failed" ) ;
1858
+ setsockopt ( receive, Ipv6RecvOrigDstAddr , & true )
1859
+ . expect ( "setsockopt IP_RECVORIGDSTADDR failed" ) ;
1860
+
1861
+ {
1862
+ let slice = [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ;
1863
+ let iov = [ IoSlice :: new ( & slice) ] ;
1864
+
1865
+ let send = socket (
1866
+ AddressFamily :: Inet6 ,
1867
+ SockType :: Datagram ,
1868
+ SockFlag :: empty ( ) ,
1869
+ None ,
1870
+ )
1871
+ . expect ( "send socket failed" ) ;
1872
+ sendmsg ( send, & iov, & [ ] , MsgFlags :: empty ( ) , Some ( & sa) )
1873
+ . expect ( "sendmsg failed" ) ;
1874
+ }
1875
+
1876
+ {
1877
+ let mut buf = [ 0u8 ; 8 ] ;
1878
+ let mut iovec = [ IoSliceMut :: new ( & mut buf) ] ;
1879
+ let mut space = cmsg_space ! ( libc:: in6_addr, [ u8 ; 0 ] ) ;
1880
+ let msg = recvmsg :: < ( ) > (
1881
+ receive,
1882
+ & mut iovec,
1883
+ Some ( & mut space) ,
1884
+ MsgFlags :: empty ( ) ,
1885
+ )
1886
+ . expect ( "recvmsg failed" ) ;
1887
+ assert ! ( !msg
1888
+ . flags
1889
+ . intersects( MsgFlags :: MSG_TRUNC | MsgFlags :: MSG_CTRUNC ) ) ;
1890
+ assert_eq ! ( msg. cmsgs( ) . count( ) , 1 , "expected 1 cmsgs" ) ;
1891
+
1892
+ let mut rx_recvorigdstaddr = false ;
1893
+ for cmsg in msg. cmsgs ( ) {
1894
+ match cmsg {
1895
+ ControlMessageOwned :: Ipv6RecvOrigDstAddr ( addr) => {
1896
+ rx_recvorigdstaddr = true ;
1897
+ if let Some ( sin) = lo. as_sockaddr_in6 ( ) {
1898
+ assert_eq ! ( sin. as_ref( ) . sin6_addr. s6_addr,
1899
+ addr. s6_addr,
1900
+ "unexpected destination address (expected {:?}, got {:?})" ,
1901
+ sin. as_ref( ) . sin6_addr. s6_addr,
1902
+ addr. s6_addr) ;
1903
+ } else {
1904
+ panic ! ( "unexpected Sockaddr" ) ;
1905
+ }
1906
+ }
1907
+ _ => panic ! ( "unexpected additional control msg" ) ,
1908
+ }
1909
+ }
1910
+ assert ! ( rx_recvorigdstaddr) ;
1911
+ assert_eq ! ( msg. bytes, 8 ) ;
1912
+ assert_eq ! ( * iovec[ 0 ] , [ 1u8 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] ) ;
1913
+ }
1914
+ }
1915
+
1748
1916
#[ cfg( any(
1749
1917
target_os = "android" ,
1750
1918
target_os = "freebsd" ,
0 commit comments