1use crate::{Error, NixPath, Result};
7use libc::c_uint;
8
9pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
11 let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
12
13 if if_index == 0 {
14 Err(Error::last())
15 } else {
16 Ok(if_index)
17 }
18}
19
20libc_bitflags!(
21 pub struct InterfaceFlags: libc::c_int {
23 IFF_UP;
26 IFF_BROADCAST;
29 IFF_DEBUG;
32 IFF_LOOPBACK;
35 IFF_POINTOPOINT;
38 #[cfg(any(target_os = "android",
41 target_os = "fuchsia",
42 target_os = "ios",
43 target_os = "linux",
44 target_os = "macos",
45 target_os = "netbsd",
46 target_os = "illumos",
47 target_os = "solaris"))]
48 IFF_NOTRAILERS;
49 #[cfg(any(target_os = "dragonfly"))]
51 IFF_SMART;
52 #[cfg(any(target_os = "android",
55 target_os = "dragonfly",
56 target_os = "freebsd",
57 target_os = "fuchsia",
58 target_os = "illumos",
59 target_os = "ios",
60 target_os = "linux",
61 target_os = "macos",
62 target_os = "netbsd",
63 target_os = "openbsd",
64 target_os = "solaris"))]
65 IFF_RUNNING;
66 IFF_NOARP;
69 IFF_PROMISC;
72 IFF_ALLMULTI;
75 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
78 IFF_MASTER;
79 #[cfg(any(target_os = "freebsd",
81 target_os = "macos",
82 target_os = "netbsd",
83 target_os = "openbsd",
84 target_os = "ios"))]
85 IFF_OACTIVE;
86 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
88 IFF_INTELLIGENT;
89 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
92 IFF_SLAVE;
93 #[cfg(any(target_os = "dragonfly",
95 target_os = "freebsd",
96 target_os = "macos",
97 target_os = "netbsd",
98 target_os = "openbsd",
99 target_os = "osx"))]
100 IFF_SIMPLEX;
101 IFF_MULTICAST;
104 #[cfg(any(target_os = "dragonfly",
106 target_os = "freebsd",
107 target_os = "macos",
108 target_os = "netbsd",
109 target_os = "openbsd",
110 target_os = "ios"))]
111 IFF_LINK0;
112 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
114 IFF_MULTI_BCAST;
115 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
118 IFF_PORTSEL;
119 #[cfg(any(target_os = "dragonfly",
121 target_os = "freebsd",
122 target_os = "macos",
123 target_os = "netbsd",
124 target_os = "openbsd",
125 target_os = "ios"))]
126 IFF_LINK1;
127 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
129 IFF_UNNUMBERED;
130 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
133 IFF_AUTOMEDIA;
134 #[cfg(any(target_os = "dragonfly",
136 target_os = "freebsd",
137 target_os = "macos",
138 target_os = "netbsd",
139 target_os = "openbsd",
140 target_os = "ios"))]
141 IFF_LINK2;
142 #[cfg(any(target_os = "dragonfly",
144 target_os = "freebsd",
145 target_os = "macos",
146 target_os = "ios"))]
147 IFF_ALTPHYS;
148 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
150 IFF_DHCPRUNNING;
151 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
154 IFF_DYNAMIC;
155 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
157 IFF_PRIVATE;
158 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
160 IFF_LOWER_UP;
161 #[cfg(any(target_os = "dragonfly"))]
163 IFF_POLLING_COMPAT;
164 #[cfg(any(target_os = "freebsd"))]
166 IFF_CANTCONFIG;
167 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
169 IFF_NOXMIT;
170 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
172 IFF_DORMANT;
173 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
175 IFF_PPROMISC;
176 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
178 IFF_NOLOCAL;
179 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
181 IFF_ECHO;
182 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
184 IFF_MONITOR;
185 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
187 IFF_DEPRECATED;
188 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
190 IFF_STATICARP;
191 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
193 IFF_ADDRCONF;
194 #[cfg(any(target_os = "dragonfly"))]
196 IFF_NPOLLING;
197 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
199 IFF_ROUTER;
200 #[cfg(any(target_os = "dragonfly"))]
202 IFF_IDIRECT;
203 #[cfg(any(target_os = "freebsd"))]
205 IFF_DYING;
206 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
208 IFF_NONUD;
209 #[cfg(any(target_os = "freebsd"))]
211 IFF_RENAMING;
212 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
214 IFF_ANYCAST;
215 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
217 IFF_NORTEXCH;
218 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
220 IFF_NO_PI as libc::c_int;
221 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
223 IFF_TUN as libc::c_int;
224 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
226 IFF_TAP as libc::c_int;
227 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
229 IFF_IPV4;
230 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
232 IFF_IPV6;
233 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
235 IFF_NOFAILOVER;
236 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
238 IFF_FAILED;
239 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
241 IFF_STANDBY;
242 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
244 IFF_INACTIVE;
245 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
247 IFF_OFFLINE;
248 #[cfg(target_os = "solaris")]
249 IFF_COS_ENABLED;
250 #[cfg(target_os = "solaris")]
252 IFF_PREFERRED;
253 #[cfg(target_os = "solaris")]
255 IFF_TEMPORARY;
256 #[cfg(target_os = "solaris")]
258 IFF_FIXEDMTU;
259 #[cfg(target_os = "solaris")]
261 IFF_VIRTUAL;
262 #[cfg(target_os = "solaris")]
264 IFF_DUPLICATE;
265 #[cfg(target_os = "solaris")]
267 IFF_IPMP;
268 }
269);
270
271#[cfg(any(
272 target_os = "dragonfly",
273 target_os = "freebsd",
274 target_os = "fuchsia",
275 target_os = "ios",
276 target_os = "linux",
277 target_os = "macos",
278 target_os = "netbsd",
279 target_os = "openbsd",
280))]
281mod if_nameindex {
282 use super::*;
283
284 use std::ffi::CStr;
285 use std::fmt;
286 use std::marker::PhantomData;
287 use std::ptr::NonNull;
288
289 #[allow(missing_copy_implementations)]
292 #[repr(transparent)]
293 pub struct Interface(libc::if_nameindex);
294
295 impl Interface {
296 pub fn index(&self) -> c_uint {
298 self.0.if_index
299 }
300
301 pub fn name(&self) -> &CStr {
303 unsafe { CStr::from_ptr(self.0.if_name) }
304 }
305 }
306
307 impl fmt::Debug for Interface {
308 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
309 f.debug_struct("Interface")
310 .field("index", &self.index())
311 .field("name", &self.name())
312 .finish()
313 }
314 }
315
316 pub struct Interfaces {
318 ptr: NonNull<libc::if_nameindex>,
319 }
320
321 impl Interfaces {
322 #[inline]
324 pub fn iter(&self) -> InterfacesIter<'_> {
325 self.into_iter()
326 }
327
328 pub fn to_slice(&self) -> &[Interface] {
332 let ifs = self.ptr.as_ptr() as *const Interface;
333 let len = self.iter().count();
334 unsafe { std::slice::from_raw_parts(ifs, len) }
335 }
336 }
337
338 impl Drop for Interfaces {
339 fn drop(&mut self) {
340 unsafe { libc::if_freenameindex(self.ptr.as_ptr()) };
341 }
342 }
343
344 impl fmt::Debug for Interfaces {
345 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
346 self.to_slice().fmt(f)
347 }
348 }
349
350 impl<'a> IntoIterator for &'a Interfaces {
351 type IntoIter = InterfacesIter<'a>;
352 type Item = &'a Interface;
353 #[inline]
354 fn into_iter(self) -> Self::IntoIter {
355 InterfacesIter {
356 ptr: self.ptr.as_ptr(),
357 _marker: PhantomData,
358 }
359 }
360 }
361
362 #[derive(Debug)]
364 pub struct InterfacesIter<'a> {
365 ptr: *const libc::if_nameindex,
366 _marker: PhantomData<&'a Interfaces>,
367 }
368
369 impl<'a> Iterator for InterfacesIter<'a> {
370 type Item = &'a Interface;
371 #[inline]
372 fn next(&mut self) -> Option<Self::Item> {
373 unsafe {
374 if (*self.ptr).if_index == 0 {
375 None
376 } else {
377 let ret = &*(self.ptr as *const Interface);
378 self.ptr = self.ptr.add(1);
379 Some(ret)
380 }
381 }
382 }
383 }
384
385 pub fn if_nameindex() -> Result<Interfaces> {
394 unsafe {
395 let ifs = libc::if_nameindex();
396 let ptr = NonNull::new(ifs).ok_or_else(Error::last)?;
397 Ok(Interfaces { ptr })
398 }
399 }
400}
401#[cfg(any(
402 target_os = "dragonfly",
403 target_os = "freebsd",
404 target_os = "fuchsia",
405 target_os = "ios",
406 target_os = "linux",
407 target_os = "macos",
408 target_os = "netbsd",
409 target_os = "openbsd",
410))]
411pub use if_nameindex::*;