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 #[cfg_attr(docsrs, doc(cfg(all())))]
49 IFF_NOTRAILERS;
50 #[cfg(any(target_os = "dragonfly"))]
52 #[cfg_attr(docsrs, doc(cfg(all())))]
53 IFF_SMART;
54 #[cfg(any(target_os = "android",
57 target_os = "dragonfly",
58 target_os = "freebsd",
59 target_os = "fuchsia",
60 target_os = "illumos",
61 target_os = "ios",
62 target_os = "linux",
63 target_os = "macos",
64 target_os = "netbsd",
65 target_os = "openbsd",
66 target_os = "solaris"))]
67 #[cfg_attr(docsrs, doc(cfg(all())))]
68 IFF_RUNNING;
69 IFF_NOARP;
72 IFF_PROMISC;
75 IFF_ALLMULTI;
78 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
81 #[cfg_attr(docsrs, doc(cfg(all())))]
82 IFF_MASTER;
83 #[cfg(any(target_os = "freebsd",
85 target_os = "macos",
86 target_os = "netbsd",
87 target_os = "openbsd",
88 target_os = "ios"))]
89 #[cfg_attr(docsrs, doc(cfg(all())))]
90 IFF_OACTIVE;
91 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
93 #[cfg_attr(docsrs, doc(cfg(all())))]
94 IFF_INTELLIGENT;
95 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
98 #[cfg_attr(docsrs, doc(cfg(all())))]
99 IFF_SLAVE;
100 #[cfg(any(target_os = "dragonfly",
102 target_os = "freebsd",
103 target_os = "macos",
104 target_os = "netbsd",
105 target_os = "openbsd",
106 target_os = "osx"))]
107 #[cfg_attr(docsrs, doc(cfg(all())))]
108 IFF_SIMPLEX;
109 IFF_MULTICAST;
112 #[cfg(any(target_os = "dragonfly",
114 target_os = "freebsd",
115 target_os = "macos",
116 target_os = "netbsd",
117 target_os = "openbsd",
118 target_os = "ios"))]
119 #[cfg_attr(docsrs, doc(cfg(all())))]
120 IFF_LINK0;
121 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
123 #[cfg_attr(docsrs, doc(cfg(all())))]
124 IFF_MULTI_BCAST;
125 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
128 #[cfg_attr(docsrs, doc(cfg(all())))]
129 IFF_PORTSEL;
130 #[cfg(any(target_os = "dragonfly",
132 target_os = "freebsd",
133 target_os = "macos",
134 target_os = "netbsd",
135 target_os = "openbsd",
136 target_os = "ios"))]
137 #[cfg_attr(docsrs, doc(cfg(all())))]
138 IFF_LINK1;
139 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
141 #[cfg_attr(docsrs, doc(cfg(all())))]
142 IFF_UNNUMBERED;
143 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
146 #[cfg_attr(docsrs, doc(cfg(all())))]
147 IFF_AUTOMEDIA;
148 #[cfg(any(target_os = "dragonfly",
150 target_os = "freebsd",
151 target_os = "macos",
152 target_os = "netbsd",
153 target_os = "openbsd",
154 target_os = "ios"))]
155 #[cfg_attr(docsrs, doc(cfg(all())))]
156 IFF_LINK2;
157 #[cfg(any(target_os = "dragonfly",
159 target_os = "freebsd",
160 target_os = "macos",
161 target_os = "ios"))]
162 #[cfg_attr(docsrs, doc(cfg(all())))]
163 IFF_ALTPHYS;
164 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
166 #[cfg_attr(docsrs, doc(cfg(all())))]
167 IFF_DHCPRUNNING;
168 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
171 #[cfg_attr(docsrs, doc(cfg(all())))]
172 IFF_DYNAMIC;
173 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
175 #[cfg_attr(docsrs, doc(cfg(all())))]
176 IFF_PRIVATE;
177 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
179 #[cfg_attr(docsrs, doc(cfg(all())))]
180 IFF_LOWER_UP;
181 #[cfg(any(target_os = "dragonfly"))]
183 #[cfg_attr(docsrs, doc(cfg(all())))]
184 IFF_POLLING_COMPAT;
185 #[cfg(any(target_os = "freebsd"))]
187 #[cfg_attr(docsrs, doc(cfg(all())))]
188 IFF_CANTCONFIG;
189 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
191 #[cfg_attr(docsrs, doc(cfg(all())))]
192 IFF_NOXMIT;
193 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
195 #[cfg_attr(docsrs, doc(cfg(all())))]
196 IFF_DORMANT;
197 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
199 #[cfg_attr(docsrs, doc(cfg(all())))]
200 IFF_PPROMISC;
201 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
203 #[cfg_attr(docsrs, doc(cfg(all())))]
204 IFF_NOLOCAL;
205 #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
207 #[cfg_attr(docsrs, doc(cfg(all())))]
208 IFF_ECHO;
209 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
211 #[cfg_attr(docsrs, doc(cfg(all())))]
212 IFF_MONITOR;
213 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
215 #[cfg_attr(docsrs, doc(cfg(all())))]
216 IFF_DEPRECATED;
217 #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
219 #[cfg_attr(docsrs, doc(cfg(all())))]
220 IFF_STATICARP;
221 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
223 #[cfg_attr(docsrs, doc(cfg(all())))]
224 IFF_ADDRCONF;
225 #[cfg(any(target_os = "dragonfly"))]
227 #[cfg_attr(docsrs, doc(cfg(all())))]
228 IFF_NPOLLING;
229 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
231 #[cfg_attr(docsrs, doc(cfg(all())))]
232 IFF_ROUTER;
233 #[cfg(any(target_os = "dragonfly"))]
235 #[cfg_attr(docsrs, doc(cfg(all())))]
236 IFF_IDIRECT;
237 #[cfg(any(target_os = "freebsd"))]
239 #[cfg_attr(docsrs, doc(cfg(all())))]
240 IFF_DYING;
241 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
243 #[cfg_attr(docsrs, doc(cfg(all())))]
244 IFF_NONUD;
245 #[cfg(any(target_os = "freebsd"))]
247 #[cfg_attr(docsrs, doc(cfg(all())))]
248 IFF_RENAMING;
249 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
251 #[cfg_attr(docsrs, doc(cfg(all())))]
252 IFF_ANYCAST;
253 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
255 #[cfg_attr(docsrs, doc(cfg(all())))]
256 IFF_NORTEXCH;
257 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
259 #[cfg_attr(docsrs, doc(cfg(all())))]
260 IFF_NO_PI as libc::c_int;
261 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
263 #[cfg_attr(docsrs, doc(cfg(all())))]
264 IFF_TUN as libc::c_int;
265 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
267 #[cfg_attr(docsrs, doc(cfg(all())))]
268 IFF_TAP as libc::c_int;
269 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
271 #[cfg_attr(docsrs, doc(cfg(all())))]
272 IFF_IPV4;
273 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
275 #[cfg_attr(docsrs, doc(cfg(all())))]
276 IFF_IPV6;
277 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
279 #[cfg_attr(docsrs, doc(cfg(all())))]
280 IFF_NOFAILOVER;
281 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
283 #[cfg_attr(docsrs, doc(cfg(all())))]
284 IFF_FAILED;
285 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
287 #[cfg_attr(docsrs, doc(cfg(all())))]
288 IFF_STANDBY;
289 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
291 #[cfg_attr(docsrs, doc(cfg(all())))]
292 IFF_INACTIVE;
293 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
295 #[cfg_attr(docsrs, doc(cfg(all())))]
296 IFF_OFFLINE;
297 #[cfg(target_os = "solaris")]
298 #[cfg_attr(docsrs, doc(cfg(all())))]
299 IFF_COS_ENABLED;
300 #[cfg(target_os = "solaris")]
302 #[cfg_attr(docsrs, doc(cfg(all())))]
303 IFF_PREFERRED;
304 #[cfg(target_os = "solaris")]
306 #[cfg_attr(docsrs, doc(cfg(all())))]
307 IFF_TEMPORARY;
308 #[cfg(target_os = "solaris")]
310 #[cfg_attr(docsrs, doc(cfg(all())))]
311 IFF_FIXEDMTU;
312 #[cfg(target_os = "solaris")]
314 #[cfg_attr(docsrs, doc(cfg(all())))]
315 IFF_VIRTUAL;
316 #[cfg(target_os = "solaris")]
318 #[cfg_attr(docsrs, doc(cfg(all())))]
319 IFF_DUPLICATE;
320 #[cfg(target_os = "solaris")]
322 #[cfg_attr(docsrs, doc(cfg(all())))]
323 IFF_IPMP;
324 }
325);
326
327#[cfg(any(
328 target_os = "dragonfly",
329 target_os = "freebsd",
330 target_os = "fuchsia",
331 target_os = "ios",
332 target_os = "linux",
333 target_os = "macos",
334 target_os = "netbsd",
335 target_os = "openbsd",
336))]
337#[cfg_attr(docsrs, doc(cfg(all())))]
338mod if_nameindex {
339 use super::*;
340
341 use std::ffi::CStr;
342 use std::fmt;
343 use std::marker::PhantomData;
344 use std::ptr::NonNull;
345
346 #[allow(missing_copy_implementations)]
349 #[repr(transparent)]
350 pub struct Interface(libc::if_nameindex);
351
352 impl Interface {
353 pub fn index(&self) -> c_uint {
355 self.0.if_index
356 }
357
358 pub fn name(&self) -> &CStr {
360 unsafe { CStr::from_ptr(self.0.if_name) }
361 }
362 }
363
364 impl fmt::Debug for Interface {
365 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366 f.debug_struct("Interface")
367 .field("index", &self.index())
368 .field("name", &self.name())
369 .finish()
370 }
371 }
372
373 pub struct Interfaces {
375 ptr: NonNull<libc::if_nameindex>,
376 }
377
378 impl Interfaces {
379 #[inline]
381 pub fn iter(&self) -> InterfacesIter<'_> {
382 self.into_iter()
383 }
384
385 pub fn to_slice(&self) -> &[Interface] {
389 let ifs = self.ptr.as_ptr() as *const Interface;
390 let len = self.iter().count();
391 unsafe { std::slice::from_raw_parts(ifs, len) }
392 }
393 }
394
395 impl Drop for Interfaces {
396 fn drop(&mut self) {
397 unsafe { libc::if_freenameindex(self.ptr.as_ptr()) };
398 }
399 }
400
401 impl fmt::Debug for Interfaces {
402 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
403 self.to_slice().fmt(f)
404 }
405 }
406
407 impl<'a> IntoIterator for &'a Interfaces {
408 type IntoIter = InterfacesIter<'a>;
409 type Item = &'a Interface;
410 #[inline]
411 fn into_iter(self) -> Self::IntoIter {
412 InterfacesIter {
413 ptr: self.ptr.as_ptr(),
414 _marker: PhantomData,
415 }
416 }
417 }
418
419 #[derive(Debug)]
421 pub struct InterfacesIter<'a> {
422 ptr: *const libc::if_nameindex,
423 _marker: PhantomData<&'a Interfaces>,
424 }
425
426 impl<'a> Iterator for InterfacesIter<'a> {
427 type Item = &'a Interface;
428 #[inline]
429 fn next(&mut self) -> Option<Self::Item> {
430 unsafe {
431 if (*self.ptr).if_index == 0 {
432 None
433 } else {
434 let ret = &*(self.ptr as *const Interface);
435 self.ptr = self.ptr.add(1);
436 Some(ret)
437 }
438 }
439 }
440 }
441
442 pub fn if_nameindex() -> Result<Interfaces> {
451 unsafe {
452 let ifs = libc::if_nameindex();
453 let ptr = NonNull::new(ifs).ok_or_else(Error::last)?;
454 Ok(Interfaces { ptr })
455 }
456 }
457}
458#[cfg(any(
459 target_os = "dragonfly",
460 target_os = "freebsd",
461 target_os = "fuchsia",
462 target_os = "ios",
463 target_os = "linux",
464 target_os = "macos",
465 target_os = "netbsd",
466 target_os = "openbsd",
467))]
468pub use if_nameindex::*;