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
12 .with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
13
14 if if_index == 0 {
15 Err(Error::last())
16 } else {
17 Ok(if_index)
18 }
19}
20
21libc_bitflags!(
22 pub struct InterfaceFlags: libc::c_int {
24 IFF_UP;
27 IFF_BROADCAST;
30 #[cfg(not(target_os = "haiku"))]
33 IFF_DEBUG;
34 IFF_LOOPBACK;
37 IFF_POINTOPOINT;
40 #[cfg(any(target_os = "android",
43 target_os = "fuchsia",
44 target_os = "ios",
45 target_os = "linux",
46 target_os = "macos",
47 target_os = "netbsd",
48 target_os = "illumos",
49 target_os = "solaris"))]
50 #[cfg_attr(docsrs, doc(cfg(all())))]
51 IFF_NOTRAILERS;
52 #[cfg(any(target_os = "dragonfly"))]
54 #[cfg_attr(docsrs, doc(cfg(all())))]
55 IFF_SMART;
56 #[cfg(any(target_os = "android",
59 target_os = "dragonfly",
60 target_os = "freebsd",
61 target_os = "fuchsia",
62 target_os = "illumos",
63 target_os = "ios",
64 target_os = "linux",
65 target_os = "macos",
66 target_os = "netbsd",
67 target_os = "openbsd",
68 target_os = "solaris"))]
69 #[cfg_attr(docsrs, doc(cfg(all())))]
70 IFF_RUNNING;
71 IFF_NOARP;
74 IFF_PROMISC;
77 IFF_ALLMULTI;
80 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
83 #[cfg_attr(docsrs, doc(cfg(all())))]
84 IFF_MASTER;
85 #[cfg(any(target_os = "freebsd",
87 target_os = "macos",
88 target_os = "netbsd",
89 target_os = "openbsd",
90 target_os = "ios"))]
91 #[cfg_attr(docsrs, doc(cfg(all())))]
92 IFF_OACTIVE;
93 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
95 #[cfg_attr(docsrs, doc(cfg(all())))]
96 IFF_INTELLIGENT;
97 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
100 #[cfg_attr(docsrs, doc(cfg(all())))]
101 IFF_SLAVE;
102 #[cfg(any(target_os = "dragonfly",
104 target_os = "freebsd",
105 target_os = "macos",
106 target_os = "netbsd",
107 target_os = "openbsd"))]
108 #[cfg_attr(docsrs, doc(cfg(all())))]
109 IFF_SIMPLEX;
110 IFF_MULTICAST;
113 #[cfg(any(target_os = "dragonfly",
115 target_os = "freebsd",
116 target_os = "macos",
117 target_os = "netbsd",
118 target_os = "openbsd",
119 target_os = "ios"))]
120 #[cfg_attr(docsrs, doc(cfg(all())))]
121 IFF_LINK0;
122 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
124 #[cfg_attr(docsrs, doc(cfg(all())))]
125 IFF_MULTI_BCAST;
126 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
129 #[cfg_attr(docsrs, doc(cfg(all())))]
130 IFF_PORTSEL;
131 #[cfg(any(target_os = "dragonfly",
133 target_os = "freebsd",
134 target_os = "macos",
135 target_os = "netbsd",
136 target_os = "openbsd",
137 target_os = "ios"))]
138 #[cfg_attr(docsrs, doc(cfg(all())))]
139 IFF_LINK1;
140 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
142 #[cfg_attr(docsrs, doc(cfg(all())))]
143 IFF_UNNUMBERED;
144 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
147 #[cfg_attr(docsrs, doc(cfg(all())))]
148 IFF_AUTOMEDIA;
149 #[cfg(any(target_os = "dragonfly",
151 target_os = "freebsd",
152 target_os = "macos",
153 target_os = "netbsd",
154 target_os = "openbsd",
155 target_os = "ios"))]
156 #[cfg_attr(docsrs, doc(cfg(all())))]
157 IFF_LINK2;
158 #[cfg(any(target_os = "dragonfly",
160 target_os = "freebsd",
161 target_os = "macos",
162 target_os = "ios"))]
163 #[cfg_attr(docsrs, doc(cfg(all())))]
164 IFF_ALTPHYS;
165 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
167 #[cfg_attr(docsrs, doc(cfg(all())))]
168 IFF_DHCPRUNNING;
169 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
172 #[cfg_attr(docsrs, doc(cfg(all())))]
173 IFF_DYNAMIC;
174 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
176 #[cfg_attr(docsrs, doc(cfg(all())))]
177 IFF_PRIVATE;
178 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
180 #[cfg_attr(docsrs, doc(cfg(all())))]
181 IFF_LOWER_UP;
182 #[cfg(any(target_os = "dragonfly"))]
184 #[cfg_attr(docsrs, doc(cfg(all())))]
185 IFF_POLLING_COMPAT;
186 #[cfg(any(target_os = "freebsd"))]
188 #[cfg_attr(docsrs, doc(cfg(all())))]
189 IFF_CANTCONFIG;
190 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
192 #[cfg_attr(docsrs, doc(cfg(all())))]
193 IFF_NOXMIT;
194 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
196 #[cfg_attr(docsrs, doc(cfg(all())))]
197 IFF_DORMANT;
198 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
200 #[cfg_attr(docsrs, doc(cfg(all())))]
201 IFF_PPROMISC;
202 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
204 #[cfg_attr(docsrs, doc(cfg(all())))]
205 IFF_NOLOCAL;
206 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
208 #[cfg_attr(docsrs, doc(cfg(all())))]
209 IFF_ECHO;
210 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
212 #[cfg_attr(docsrs, doc(cfg(all())))]
213 IFF_MONITOR;
214 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
216 #[cfg_attr(docsrs, doc(cfg(all())))]
217 IFF_DEPRECATED;
218 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
220 #[cfg_attr(docsrs, doc(cfg(all())))]
221 IFF_STATICARP;
222 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
224 #[cfg_attr(docsrs, doc(cfg(all())))]
225 IFF_ADDRCONF;
226 #[cfg(any(target_os = "dragonfly"))]
228 #[cfg_attr(docsrs, doc(cfg(all())))]
229 IFF_NPOLLING;
230 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
232 #[cfg_attr(docsrs, doc(cfg(all())))]
233 IFF_ROUTER;
234 #[cfg(any(target_os = "dragonfly"))]
236 #[cfg_attr(docsrs, doc(cfg(all())))]
237 IFF_IDIRECT;
238 #[cfg(any(target_os = "freebsd"))]
240 #[cfg_attr(docsrs, doc(cfg(all())))]
241 IFF_DYING;
242 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
244 #[cfg_attr(docsrs, doc(cfg(all())))]
245 IFF_NONUD;
246 #[cfg(any(target_os = "freebsd"))]
248 #[cfg_attr(docsrs, doc(cfg(all())))]
249 IFF_RENAMING;
250 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
252 #[cfg_attr(docsrs, doc(cfg(all())))]
253 IFF_ANYCAST;
254 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
256 #[cfg_attr(docsrs, doc(cfg(all())))]
257 IFF_NORTEXCH;
258 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
260 #[cfg_attr(docsrs, doc(cfg(all())))]
261 IFF_NO_PI as libc::c_int;
262 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
264 #[cfg_attr(docsrs, doc(cfg(all())))]
265 IFF_TUN as libc::c_int;
266 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
268 #[cfg_attr(docsrs, doc(cfg(all())))]
269 IFF_TAP as libc::c_int;
270 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
272 #[cfg_attr(docsrs, doc(cfg(all())))]
273 IFF_IPV4;
274 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
276 #[cfg_attr(docsrs, doc(cfg(all())))]
277 IFF_IPV6;
278 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
280 #[cfg_attr(docsrs, doc(cfg(all())))]
281 IFF_NOFAILOVER;
282 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
284 #[cfg_attr(docsrs, doc(cfg(all())))]
285 IFF_FAILED;
286 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
288 #[cfg_attr(docsrs, doc(cfg(all())))]
289 IFF_STANDBY;
290 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
292 #[cfg_attr(docsrs, doc(cfg(all())))]
293 IFF_INACTIVE;
294 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
296 #[cfg_attr(docsrs, doc(cfg(all())))]
297 IFF_OFFLINE;
298 #[cfg(target_os = "solaris")]
299 #[cfg_attr(docsrs, doc(cfg(all())))]
300 IFF_COS_ENABLED;
301 #[cfg(target_os = "solaris")]
303 #[cfg_attr(docsrs, doc(cfg(all())))]
304 IFF_PREFERRED;
305 #[cfg(target_os = "solaris")]
307 #[cfg_attr(docsrs, doc(cfg(all())))]
308 IFF_TEMPORARY;
309 #[cfg(target_os = "solaris")]
311 #[cfg_attr(docsrs, doc(cfg(all())))]
312 IFF_FIXEDMTU;
313 #[cfg(target_os = "solaris")]
315 #[cfg_attr(docsrs, doc(cfg(all())))]
316 IFF_VIRTUAL;
317 #[cfg(target_os = "solaris")]
319 #[cfg_attr(docsrs, doc(cfg(all())))]
320 IFF_DUPLICATE;
321 #[cfg(target_os = "solaris")]
323 #[cfg_attr(docsrs, doc(cfg(all())))]
324 IFF_IPMP;
325 }
326);
327
328#[cfg(any(
329 target_os = "dragonfly",
330 target_os = "freebsd",
331 target_os = "fuchsia",
332 target_os = "ios",
333 target_os = "linux",
334 target_os = "macos",
335 target_os = "netbsd",
336 target_os = "openbsd",
337))]
338#[cfg_attr(docsrs, doc(cfg(all())))]
339mod if_nameindex {
340 use super::*;
341
342 use std::ffi::CStr;
343 use std::fmt;
344 use std::marker::PhantomData;
345 use std::ptr::NonNull;
346
347 #[allow(missing_copy_implementations)]
350 #[repr(transparent)]
351 pub struct Interface(libc::if_nameindex);
352
353 impl Interface {
354 pub fn index(&self) -> c_uint {
356 self.0.if_index
357 }
358
359 pub fn name(&self) -> &CStr {
361 unsafe { CStr::from_ptr(self.0.if_name) }
362 }
363 }
364
365 impl fmt::Debug for Interface {
366 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
367 f.debug_struct("Interface")
368 .field("index", &self.index())
369 .field("name", &self.name())
370 .finish()
371 }
372 }
373
374 pub struct Interfaces {
376 ptr: NonNull<libc::if_nameindex>,
377 }
378
379 impl Interfaces {
380 #[inline]
382 pub fn iter(&self) -> InterfacesIter<'_> {
383 self.into_iter()
384 }
385
386 pub fn to_slice(&self) -> &[Interface] {
390 let ifs = self.ptr.as_ptr() as *const Interface;
391 let len = self.iter().count();
392 unsafe { std::slice::from_raw_parts(ifs, len) }
393 }
394 }
395
396 impl Drop for Interfaces {
397 fn drop(&mut self) {
398 unsafe { libc::if_freenameindex(self.ptr.as_ptr()) };
399 }
400 }
401
402 impl fmt::Debug for Interfaces {
403 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
404 self.to_slice().fmt(f)
405 }
406 }
407
408 impl<'a> IntoIterator for &'a Interfaces {
409 type IntoIter = InterfacesIter<'a>;
410 type Item = &'a Interface;
411 #[inline]
412 fn into_iter(self) -> Self::IntoIter {
413 InterfacesIter {
414 ptr: self.ptr.as_ptr(),
415 _marker: PhantomData,
416 }
417 }
418 }
419
420 #[derive(Debug)]
422 pub struct InterfacesIter<'a> {
423 ptr: *const libc::if_nameindex,
424 _marker: PhantomData<&'a Interfaces>,
425 }
426
427 impl<'a> Iterator for InterfacesIter<'a> {
428 type Item = &'a Interface;
429 #[inline]
430 fn next(&mut self) -> Option<Self::Item> {
431 unsafe {
432 if (*self.ptr).if_index == 0 {
433 None
434 } else {
435 let ret = &*(self.ptr as *const Interface);
436 self.ptr = self.ptr.add(1);
437 Some(ret)
438 }
439 }
440 }
441 }
442
443 pub fn if_nameindex() -> Result<Interfaces> {
452 unsafe {
453 let ifs = libc::if_nameindex();
454 let ptr = NonNull::new(ifs).ok_or_else(Error::last)?;
455 Ok(Interfaces { ptr })
456 }
457 }
458}
459#[cfg(any(
460 target_os = "dragonfly",
461 target_os = "freebsd",
462 target_os = "fuchsia",
463 target_os = "ios",
464 target_os = "linux",
465 target_os = "macos",
466 target_os = "netbsd",
467 target_os = "openbsd",
468))]
469pub use if_nameindex::*;