Rust网络接口信息获取库get_if_addrs-sys的使用,高效获取和管理系统网络接口地址信息
Rust网络接口信息获取库get_if_addrs-sys的使用,高效获取和管理系统网络接口地址信息
安装方法
在项目目录中运行以下Cargo命令:
cargo add get_if_addrs-sys
或者在Cargo.toml中添加以下行:
get_if_addrs-sys = "0.1.1"
基本使用示例
以下是使用get_if_addrs-sys库获取网络接口信息的完整示例代码:
extern crate libc;
extern crate get_if_addrs_sys;
use std::mem;
use std::ptr;
fn main() {
unsafe {
// 获取接口列表
let mut interfaces: *mut get_if_addrs_sys::ifaddrs = ptr::null_mut();
if get_if_addrs_sys::getifaddrs(&mut interfaces) != 0 {
panic!("Failed to get network interfaces");
}
// 遍历接口列表
let mut current = interfaces;
while !current.is_null() {
let ifa = *current;
let name = String::from_utf8_lossy(std::ffi::CStr::from_ptr(ifa.ifa_name).to_bytes());
println!("Interface: {}", name);
// 检查地址类型
if !ifa.ifa_addr.is_null() {
let sa_family = (*ifa.ifa_addr).sa_family as i32;
match sa_family {
libc::AF_INET => {
let sockaddr: *mut libc::sockaddr_in = ifa.ifa_addr as *mut _;
let addr = (*sockaddr).sin_addr.s_addr;
println!(" IPv4 Address: {}.{}.{}.{}",
(addr & 0xff) as u8,
((addr >> 8) & 0xff) as u8,
((addr >> 16) & 0xff) as u8,
((addr >> 24) & 0xff) as u8);
},
libc::AF_INET6 => {
let sockaddr: *mut libc::sockaddr_in6 = ifa.ifa_addr as *mut _;
let addr = (*sockaddr).sin6_addr.s6_addr;
println!(" IPv6 Address: {:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5], addr[6], addr[7],
addr[8], addr[9], addr[10], addr[11],
addr[12], addr[13], addr[14], addr[15]);
},
_ => println!(" Unknown address family: {}", sa_family),
}
}
current = ifa.ifa_next;
}
// 释放接口列表
get_if_addrs-sys::freeifaddrs(interfaces);
}
}
代码说明
- 首先调用
getifaddrs
函数获取网络接口列表 - 遍历返回的接口链表,打印每个接口的名称
- 根据地址族类型(AF_INET/AF_INET6)解析IP地址
- 最后调用
freeifaddrs
释放分配的内存
注意事项
- 这是一个底层系统接口的Rust绑定,使用时需要注意内存安全
- 示例中使用了unsafe代码块,因为直接调用C函数
- 需要处理可能的错误情况,如获取接口失败等
完整示例代码
以下是一个更完整的示例,包含了错误处理和更详细的网络接口信息输出:
extern crate libc;
extern crate get_if_addrs_sys;
use std::ffi::CStr;
use std::ptr;
use std::process;
fn main() {
unsafe {
// 获取网络接口列表
let mut ifaddr: *mut get_if_addrs_sys::ifaddrs = ptr::null_mut();
// 检查getifaddrs调用是否成功
if get_if_addrs_sys::getifaddrs(&mut ifaddr) == -1 {
eprintln!("错误: 无法获取网络接口列表");
process::exit(1);
}
// 遍历接口链表
let mut current = ifaddr;
while !current.is_null() {
let ifa = *current;
// 获取接口名称
let name = CStr::from_ptr(ifa.ifa_name).to_string_lossy();
println!("接口名称: {}", name);
// 检查是否有地址信息
if !ifa.ifa_addr.is_null() {
let sa_family = (*ifa.ifa_addr).sa_family as i32;
match sa_family {
libc::AF_INET => {
// IPv4地址处理
let sockaddr = ifa.ifa_addr as *mut libc::sockaddr_in;
let addr = (*sockaddr).sin_addr.s_addr;
println!(" 类型: IPv4");
println!(" 地址: {}.{}.{}.{}",
(addr & 0xff) as u8,
((addr >> 8) & 0xff) as u8,
((addr >> 16) & 0xff) as u8,
((addr >> 24) & 0xff) as u8);
},
libc::AF_INET6 => {
// IPv6地址处理
let sockaddr = ifa.ifa_addr as *mut libc::sockaddr_in6;
let addr = (*sockaddr).sin6_addr.s6_addr;
println!(" 类型: IPv6");
println!(" 地址: {:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}:{:02x}{:02x}",
addr[0], addr[1], addr[2], addr[3],
addr[4], addr[5], addr[6], addr[7],
addr[8], addr[9], addr[10], addr[11],
addr[12], addr[13], addr[14], addr[15]);
},
libc::AF_PACKET => {
// 链路层地址处理
println!(" 类型: 链路层(如以太网)");
},
_ => {
println!(" 未知地址类型: {}", sa_family);
}
}
}
// 检查是否有网络掩码
if !ifa.ifa_netmask.is_null() {
println!(" 有网络掩码信息");
}
// 检查是否有广播地址
if (ifa.ifa_flags & libc::IFF_BROADCAST as u32) != 0 && !ifa.ifa_ifu.is_null() {
println!(" 有广播地址信息");
}
// 移动到下一个接口
current = ifa.ifa_next;
println!("----------------------------------------");
}
// 释放接口列表内存
get_if_addrs_sys::freeifaddrs(ifaddr);
}
}
这个完整示例增加了以下功能:
- 更详细的错误处理
- 显示网络掩码和广播地址信息
- 支持更多地址类型(如链路层)
- 更清晰的输出格式
- 处理了更多网络接口标志
1 回复