1919use crate :: fd:: AsFd ;
2020use crate :: io;
2121#[ cfg( feature = "alloc" ) ]
22- use alloc:: string:: String ;
22+ use alloc:: { borrow :: ToOwned , string:: String } ;
2323
2424/// `ioctl(fd, SIOCGIFINDEX, ifreq)`—Returns the interface index for a given
2525/// name.
@@ -42,6 +42,8 @@ pub fn name_to_index<Fd: AsFd>(fd: Fd, if_name: &str) -> io::Result<u32> {
4242///
4343/// See the [module-level documentation] for information about `fd` usage.
4444///
45+ /// See also [`index_to_name_inlined`] which does not require `alloc` feature.
46+ ///
4547/// # References
4648/// - [Linux]
4749///
@@ -52,12 +54,84 @@ pub fn name_to_index<Fd: AsFd>(fd: Fd, if_name: &str) -> io::Result<u32> {
5254#[ cfg( feature = "alloc" ) ]
5355#[ cfg_attr( docsrs, doc( cfg( feature = "alloc" ) ) ) ]
5456pub fn index_to_name < Fd : AsFd > ( fd : Fd , index : u32 ) -> io:: Result < String > {
55- crate :: backend:: net:: netdevice:: index_to_name ( fd. as_fd ( ) , index)
57+ let ( len, ifrn_name) = crate :: backend:: net:: netdevice:: index_to_name ( fd. as_fd ( ) , index) ?;
58+
59+ core:: str:: from_utf8 ( & ifrn_name[ ..len] )
60+ . map_err ( |_| io:: Errno :: ILSEQ )
61+ . map ( ToOwned :: to_owned)
62+ }
63+
64+ /// `ioctl(fd, SIOCGIFNAME, ifreq)`—Returns the interface name for a given
65+ /// index.
66+ ///
67+ /// See the [module-level documentation] for information about `fd` usage.
68+ ///
69+ /// # References
70+ /// - [Linux]
71+ ///
72+ /// [module-level documentation]: self
73+ /// [Linux]: https://man7.org/linux/man-pages/man7/netdevice.7.html
74+ #[ inline]
75+ #[ doc( alias = "SIOCGIFNAME" ) ]
76+ pub fn index_to_name_inlined < Fd : AsFd > ( fd : Fd , index : u32 ) -> io:: Result < InlinedName > {
77+ let ( len, ifrn_name) = crate :: backend:: net:: netdevice:: index_to_name ( fd. as_fd ( ) , index) ?;
78+
79+ // Check if the name is valid UTF-8.
80+ core:: str:: from_utf8 ( & ifrn_name[ ..len] )
81+ . map_err ( |_| io:: Errno :: ILSEQ )
82+ . map ( |_| InlinedName {
83+ len,
84+ name : ifrn_name,
85+ } )
86+ }
87+
88+ /// The inlined interface name.
89+ #[ derive( Debug , Copy , Clone , Eq , PartialEq , Hash ) ]
90+ pub struct InlinedName {
91+ len : usize ,
92+ name : [ u8 ; 16 ] ,
93+ }
94+
95+ impl InlinedName {
96+ /// Returns the str representation of the inlined name.
97+ pub fn as_str ( & self ) -> & str {
98+ self . as_ref ( )
99+ }
100+
101+ /// Returns the bytes representation of the inlined name.
102+ pub fn as_bytes ( & self ) -> & [ u8 ] {
103+ self . as_ref ( )
104+ }
105+ }
106+
107+ impl AsRef < [ u8 ] > for InlinedName {
108+ fn as_ref ( & self ) -> & [ u8 ] {
109+ & self . name [ ..self . len ]
110+ }
111+ }
112+
113+ impl AsRef < str > for InlinedName {
114+ fn as_ref ( & self ) -> & str {
115+ // SAFETY: `InlinedName` is constructed with valid UTF-8.
116+ core:: str:: from_utf8 ( & self . name [ ..self . len ] ) . unwrap ( )
117+ }
118+ }
119+
120+ impl core:: borrow:: Borrow < str > for InlinedName {
121+ fn borrow ( & self ) -> & str {
122+ self . as_ref ( )
123+ }
124+ }
125+
126+ impl core:: fmt:: Display for InlinedName {
127+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
128+ self . as_str ( ) . fmt ( f)
129+ }
56130}
57131
58132#[ cfg( test) ]
59133mod tests {
60- use crate :: backend :: net :: netdevice :: { index_to_name, name_to_index} ;
134+ use super :: { index_to_name, index_to_name_inlined , name_to_index} ;
61135 use crate :: fd:: AsFd ;
62136 use crate :: net:: { AddressFamily , SocketFlags , SocketType } ;
63137
@@ -81,6 +155,31 @@ mod tests {
81155 assert_eq ! ( Ok ( loopback_index) , name_to_index( fd. as_fd( ) , "lo" ) ) ;
82156 }
83157
158+ #[ test]
159+ fn test_index_to_name_inlined ( ) {
160+ let fd = crate :: net:: socket_with (
161+ AddressFamily :: INET ,
162+ SocketType :: DGRAM ,
163+ SocketFlags :: CLOEXEC ,
164+ None ,
165+ )
166+ . unwrap ( ) ;
167+
168+ let loopback_index = std:: fs:: read_to_string ( "/sys/class/net/lo/ifindex" )
169+ . unwrap ( )
170+ . as_str ( )
171+ . split_at ( 1 )
172+ . 0
173+ . parse :: < u32 > ( )
174+ . unwrap ( ) ;
175+ assert_eq ! (
176+ "lo" ,
177+ index_to_name_inlined( fd. as_fd( ) , loopback_index)
178+ . unwrap( )
179+ . as_str( ) ,
180+ ) ;
181+ }
182+
84183 #[ test]
85184 #[ cfg( feature = "alloc" ) ]
86185 fn test_index_to_name ( ) {
0 commit comments