Я создаю устройство Tap, используя интерфейс Tun/Tap, открыв/dev/net/tun . Однако, когда я пытаюсь получить MAC -адрес, используя siocgifhwaddr ioctl call, я получаю неправильный MAC -адрес. Если я сделаю один и тот же звонок еще один или два раза, я в конечном итоге получу «правильный» MAC -адрес, и он придержится этот Mac. Пример вывода из моей программы показан ниже, а также код, используемый для установки/получения свойств интерфейса TAP. Есть ли правильный способ получить Mac устройства, который я не использую? Есть ли способ узнать, когда я получил «правильный»? или быть уведомленным при его изменении?ip link set dev up
[*] get_tap_address
# produced in a tight loop where we read 1 frame from the tap device
# then get the mac address again using get_tap_address
[2025-09-08T03:13:17Z DEBUG teecee] Created new tap device: TapDevice { name: "teecee0", address: ea:dd:cc:40:d1:00 }
[2025-09-08T03:13:17Z DEBUG teecee] Got new frame:
{
dst_mac: 33:33:00:00:00:16,
src_mac: 0e:58:b2:b1:61:35,
ethertype: 0x0086DD,
}
[2025-09-08T03:13:17Z DEBUG teecee] New tap mac: 0e:58:b2:b1:61:35
[2025-09-08T03:13:17Z DEBUG teecee] Got new frame:
{
dst_mac: 33:33:00:00:00:16,
src_mac: 0e:58:b2:b1:61:35,
ethertype: 0x0086DD,
}
[2025-09-08T03:13:17Z DEBUG teecee] New tap mac: 0e:58:b2:b1:61:35
< /code>
fn set_tap_with_name(fd: libc::c_int, name: &CStr) -> Result {
let mut ifreq = Self::ifreq_with_params(
name.to_bytes(),
(libc::IFF_TAP | libc::IFF_NO_PI) as _
);
unsafe {
if libc::ioctl(fd, libc::TUNSETIFF, &mut ifreq as *mut _) < 0 {
return Err(TapError::IoctlSet(std::io::Error::last_os_error()));
}
};
let name_bytes = ifreq.ifr_name.iter()
.map_while(|c| {
if *c != 0 {
Some(*c as u8)
}
else {
None
}
})
.collect::();
String::from_utf8(name_bytes).map_err(TapError::NameUtf8)
}
fn get_tap_address(fd: libc::c_int, name: &String) -> Result {
let mut ifreq = Self::ifreq_with_params(name.as_bytes(), 0);
unsafe {
if libc::ioctl(fd, libc::SIOCGIFHWADDR, &mut ifreq as *mut _) < 0 {
return Err(TapError::IoctlAddrGet(std::io::Error::last_os_error()));
}
};
let hw_addr = unsafe {
let addr = &ifreq.ifr_ifru.ifru_hwaddr.sa_data[..MacAddr::LEN];
std::slice::from_raw_parts(addr.as_ptr() as _, addr.len())
};
let mut addr = MacAddr::new_zeroed();
addr.as_mut_bytes().copy_from_slice(hw_addr);
Ok(addr)
}
fn ifreq_with_params(name: &[u8], flags: i16) -> libc::ifreq {
const MAX_NAME_LEN: usize = 16;
assert!(name.len() < MAX_NAME_LEN);
let name = unsafe {
std::slice::from_raw_parts(name.as_ptr() as _, name.len())
};
let mut ifreq: libc::ifreq;
unsafe {
ifreq = std::mem::zeroed();
ifreq.ifr_name[..name.len()].copy_from_slice(name);
ifreq.ifr_ifru.ifru_flags = flags;
}
ifreq
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ac-address