1use crate::fd::AsFd;
20use crate::io;
21#[cfg(feature = "alloc")]
22use alloc::{borrow::ToOwned, string::String};
23
24#[inline]
35#[doc(alias = "SIOCGIFINDEX")]
36pub fn name_to_index<Fd: AsFd>(fd: Fd, if_name: &str) -> io::Result<u32> {
37 crate::backend::net::netdevice::name_to_index(fd.as_fd(), if_name)
38}
39
40#[inline]
53#[doc(alias = "SIOCGIFNAME")]
54#[cfg(feature = "alloc")]
55#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
56pub fn index_to_name<Fd: AsFd>(fd: Fd, index: u32) -> io::Result<String> {
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#[inline]
75#[doc(alias = "SIOCGIFNAME")]
76pub 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 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#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
90pub struct InlinedName {
91 len: usize,
92 name: [u8; 16],
93}
94
95impl InlinedName {
96 pub fn as_str(&self) -> &str {
98 self.as_ref()
99 }
100
101 pub fn as_bytes(&self) -> &[u8] {
103 self.as_ref()
104 }
105}
106
107impl AsRef<[u8]> for InlinedName {
108 fn as_ref(&self) -> &[u8] {
109 &self.name[..self.len]
110 }
111}
112
113impl AsRef<str> for InlinedName {
114 fn as_ref(&self) -> &str {
115 core::str::from_utf8(&self.name[..self.len]).unwrap()
117 }
118}
119
120impl core::borrow::Borrow<str> for InlinedName {
121 fn borrow(&self) -> &str {
122 self.as_ref()
123 }
124}
125
126impl core::fmt::Display for InlinedName {
127 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
128 self.as_str().fmt(f)
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::{index_to_name, index_to_name_inlined, name_to_index};
135 use crate::fd::AsFd;
136 use crate::net::{AddressFamily, SocketFlags, SocketType};
137
138 #[test]
139 fn test_name_to_index() {
140 let fd = crate::net::socket_with(
141 AddressFamily::INET,
142 SocketType::DGRAM,
143 SocketFlags::CLOEXEC,
144 None,
145 )
146 .unwrap();
147
148 let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
149 .unwrap()
150 .as_str()
151 .split_at(1)
152 .0
153 .parse::<u32>()
154 .unwrap();
155 assert_eq!(Ok(loopback_index), name_to_index(fd.as_fd(), "lo"));
156 }
157
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
183 #[test]
184 #[cfg(feature = "alloc")]
185 fn test_index_to_name() {
186 let fd = crate::net::socket_with(
187 AddressFamily::INET,
188 SocketType::DGRAM,
189 SocketFlags::CLOEXEC,
190 None,
191 )
192 .unwrap();
193
194 let loopback_index = std::fs::read_to_string("/sys/class/net/lo/ifindex")
195 .unwrap()
196 .as_str()
197 .split_at(1)
198 .0
199 .parse::<u32>()
200 .unwrap();
201 assert_eq!(
202 Ok("lo".to_owned()),
203 index_to_name(fd.as_fd(), loopback_index)
204 );
205 }
206}