Skip to content

Added if_nametoindex (and necessary module based on Cs net/if.h) #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ pub mod mount;
#[cfg(any(target_os = "linux"))]
pub mod mqueue;

#[cfg(any(target_os = "linux"))]
pub mod net;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;

Expand Down
48 changes: 48 additions & 0 deletions src/net/if_.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Network interface name resolution.
//!
//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
//! or "socan1" into device numbers.

use libc::{c_char, c_uint};
use std::ffi::{CString, NulError};
use std::io;

/// Error that can occur during interface name resolution.
#[derive(Debug)]
pub enum NameToIndexError {
/// Failed to allocate a C-style string to for the syscall
NulError,
IOError(io::Error),
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use nix:Error instead of your own error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into it before implementing my own, but there's the NulError to take care of. I believe it may be worthwhile to add that to nix::Error though? It's documented in https://doc.rust-lang.org/std/ffi/struct.NulError.html.

Alternatives are just returning not found if a NulError occured or, as a last resort, unpacking (I'd like to avoid that).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A fourth option is now in 71c6836: Just returned Error::invalid_argument() if a string containig a null-byte is passed.


impl From<NulError> for NameToIndexError {
fn from(_: NulError) -> NameToIndexError {
NameToIndexError::NulError
}
}

impl From<io::Error> for NameToIndexError {
fn from(e: io::Error) -> NameToIndexError {
NameToIndexError::IOError(e)
}
}

extern {
fn if_nametoindex(ifname: *const c_char) -> c_uint;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, I could've sworn I already replaced it. Fixed in 8972270

}

/// Resolve an interface into a interface number.
pub fn name_to_index(name: &str) -> Result<c_uint, NameToIndexError> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things:

This would look like:

pub fn if_nametoindex<S: ?Sized + NixPath>(target: &P) -> Result<c_uint> {
    let res = try!(name.with_nix_path(|name| { /* rest of body here */ }));

    from_ffi(res)
}

The nix::from_ffi() function handles errno translation for you. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few things:

use the function's name as in C

Fixed in 2cb7878

return a nix::Result<c_uint>, which is equivalent to swapping in nix::Error for the error type

Fixed in 5ef9689

use a NixPath bound for the string argument (the name is bad, and it'll likely change soon, see #221 if you want more info!)

That currently seems a little messy and missing an implementation for &str? Interface names are not Paths and I don't want to require passing in CStrings, because at that point it stops being a Rust-Interface, I think.

The nix::from_ffi() function handles errno translation for you. :-)

If i am reading this right, won't from_ffi() just return () ? At least the compiler seems to agree with me. Additionally, it only works for c_int, but if_nametoindex returns unsigned values.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That currently seems a little messy and missing an implementation for &str? Interface names are not Paths and I don't want to require passing in CStrings, because at that point it stops being a Rust-Interface, I think.

This is a good consideration. I've copied your note over to to #221 where we're discussing string handling in nix.

let name = try!(CString::new(name));

let if_index;
unsafe {
if_index = if_nametoindex(name.as_ptr());
}

if if_index == 0 {
return Err(NameToIndexError::from(io::Error::last_os_error()));
}

Ok(if_index)
}
1 change: 1 addition & 0 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod if_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you add a tiny comment explaining the name is to avoid the keyword issue? (I'm assuming that's why, anyway)