Implemented BroadcastAddress option, RenewalTime option and RebindingTime option. Ran cargo fmt

This commit is contained in:
Xnoe 2022-10-30 14:50:59 +00:00
parent 855b09e580
commit 27b8836f74
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
3 changed files with 263 additions and 131 deletions

View File

@ -1,5 +1,5 @@
pub mod rtnetlink;
pub mod rawsocket; pub mod rawsocket;
pub mod rtnetlink;
use eui48::MacAddress; use eui48::MacAddress;
use rand::prelude::*; use rand::prelude::*;
@ -58,7 +58,7 @@ enum DHCPTransactionState {
WaitingAfterDiscover, WaitingAfterDiscover,
Request, Request,
WaitAfterRequest, WaitAfterRequest,
Renew Renew,
} }
fn pick_weighted<T>(list: &Vec<T>) -> Option<&T> { fn pick_weighted<T>(list: &Vec<T>) -> Option<&T> {
@ -66,18 +66,14 @@ fn pick_weighted<T>(list: &Vec<T>) -> Option<&T> {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let mut prob = rng.gen_range(0f64..=1f64); let mut prob = rng.gen_range(0f64..=1f64);
println!("start prob={}", prob);
for (idx, elem) in list.iter().enumerate() { for (idx, elem) in list.iter().enumerate() {
let weight = 1f64 / (2 as usize).pow(idx as u32 + (len != idx + 1) as u32) as f64; let weight = 1f64 / (2 as usize).pow(idx as u32 + (len != idx + 1) as u32) as f64;
prob -= weight; prob -= weight;
println!("len={} idx={}: weight={}, prob={}", len, idx, weight, prob);
if prob <= 0.0 { if prob <= 0.0 {
return Some(elem); return Some(elem);
} }
} }
// fallback in case of float rounding errors i suppose // fallback in case of float rounding errors i suppose
@ -85,7 +81,9 @@ fn pick_weighted<T>(list: &Vec<T>) -> Option<&T> {
} }
fn dhcp_client(name: String, index: i32, mac: [u8; 6]) { fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
unsafe { libc::sleep(5); } unsafe {
libc::sleep(5);
}
let mut name = name; let mut name = name;
let mut socket_nl = rtnetlink::create_netlink_socket(false).unwrap(); let mut socket_nl = rtnetlink::create_netlink_socket(false).unwrap();
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
@ -120,14 +118,16 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
DHCPOption::End, DHCPOption::End,
], ],
) )
.as_bytes() .as_bytes(),
) { ) {
Ok(_) => break, Ok(_) => break,
Err(libc::ENETDOWN) => { Err(libc::ENETDOWN) => unsafe {
unsafe {
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::ifinfomsg} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::ifinfomsg,
}
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
@ -142,7 +142,10 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::ifinfomsg} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::ifinfomsg,
}
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
@ -160,15 +163,24 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
panic!("Wrong message!"); panic!("Wrong message!");
} }
let mut n = (*nlmsghdr).nlmsg_len - std::mem::size_of::<libc::nlmsghdr>() as u32 - std::mem::size_of::<rtnetlink::ifinfomsg>() as u32; let mut n = (*nlmsghdr).nlmsg_len
let mut rtattr = (&buffer as *const _ as *const u8).offset(std::mem::size_of::<libc::nlmsghdr>() as isize + std::mem::size_of::<rtnetlink::ifinfomsg>() as isize) as *const rtnetlink::rtattr; - std::mem::size_of::<libc::nlmsghdr>() as u32
- std::mem::size_of::<rtnetlink::ifinfomsg>() as u32;
let mut rtattr = (&buffer as *const _ as *const u8).offset(
std::mem::size_of::<libc::nlmsghdr>() as isize
+ std::mem::size_of::<rtnetlink::ifinfomsg>() as isize,
)
as *const rtnetlink::rtattr;
while rtnetlink::rta_ok(rtattr, &mut n) { while rtnetlink::rta_ok(rtattr, &mut n) {
match (*rtattr).rta_type { match (*rtattr).rta_type {
libc::IFLA_IFNAME => { libc::IFLA_IFNAME => {
name = zascii(&std::ptr::read(rtnetlink::rta_data(rtattr) as *const _ as *const [libc::c_char; libc::IFNAMSIZ])); name = zascii(&std::ptr::read(
rtnetlink::rta_data(rtattr) as *const _
as *const [libc::c_char; libc::IFNAMSIZ],
));
} }
_ => () _ => (),
} }
rtattr = rtnetlink::rta_next(rtattr, &mut n); rtattr = rtnetlink::rta_next(rtattr, &mut n);
@ -176,9 +188,8 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
} }
libc::sleep(10); libc::sleep(10);
} },
} Err(_) => panic!("Failed to send on {}", name),
Err(_) => panic!("Failed to send on {}", name)
} }
} }
dhcp_state = DHCPTransactionState::WaitingAfterDiscover; dhcp_state = DHCPTransactionState::WaitingAfterDiscover;
@ -246,7 +257,8 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
DHCPTransactionState::Request => { DHCPTransactionState::Request => {
println!("Sent DHCPRequest on {}", name); println!("Sent DHCPRequest on {}", name);
socket.send( socket
.send(
create_dhcp_packet( create_dhcp_packet(
xid, xid,
client_mac, client_mac,
@ -260,8 +272,9 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
DHCPOption::End, DHCPOption::End,
], ],
) )
.as_bytes() .as_bytes(),
).unwrap(); )
.unwrap();
dhcp_state = DHCPTransactionState::WaitAfterRequest; dhcp_state = DHCPTransactionState::WaitAfterRequest;
} }
@ -308,10 +321,14 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
} }
let mut sleep_time = 0; let mut sleep_time = 0;
let mut subnet_mask = Ipv4Addr::new(0,0,0,0); let mut subnet_mask = Ipv4Addr::new(0, 0, 0, 0);
let mut router = Vec::new(); let mut router = Vec::new();
let mut dns = Vec::new(); let mut dns = Vec::new();
let mut classless_static_routes = Vec::new(); let mut classless_static_routes = Vec::new();
let mut broadcast = None;
let mut renew_time = None;
let mut rebind_time = None;
for option in options { for option in options {
println!("Received: {:?}", option); println!("Received: {:?}", option);
@ -323,6 +340,10 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
DHCPOption::DomainNameServer(v) => dns = v, DHCPOption::DomainNameServer(v) => dns = v,
DHCPOption::ClasslessStaticRoute(v) => classless_static_routes = v, DHCPOption::ClasslessStaticRoute(v) => classless_static_routes = v,
DHCPOption::RenewalTime(t) => renew_time = Some(t),
DHCPOption::RebindingTime(t) => rebind_time = Some(t),
DHCPOption::BroadcastAddress(a) => broadcast = Some(a),
_ => (), _ => (),
} }
} }
@ -330,38 +351,73 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
unsafe { unsafe {
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::ifaddrmsg, c: rtnetlink::rtattr, d: [u8; 4], e: rtnetlink::rtattr, f: [u8; 4], g: rtnetlink::rtattr, h: rtnetlink::ifa_cacheinfo} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::ifaddrmsg,
c: rtnetlink::rtattr,
d: [u8; 4],
e: rtnetlink::rtattr,
f: [u8; 4],
g: rtnetlink::rtattr,
h: rtnetlink::ifa_cacheinfo,
}
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
request.a.nlmsg_type = libc::RTM_NEWADDR; request.a.nlmsg_type = libc::RTM_NEWADDR;
request.a.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_CREATE | libc::NLM_F_REPLACE) as u16; request.a.nlmsg_flags =
(libc::NLM_F_REQUEST | libc::NLM_F_CREATE | libc::NLM_F_REPLACE)
as u16;
request.b.ifa_family = libc::AF_INET as u8; request.b.ifa_family = libc::AF_INET as u8;
request.b.ifa_index = index; request.b.ifa_index = index;
request.b.ifa_prefixlen = u32::from(subnet_mask).leading_ones() as u8; request.b.ifa_prefixlen = u32::from(subnet_mask).leading_ones() as u8;
request.c.rta_type = libc::IFA_LOCAL; request.c.rta_type = libc::IFA_LOCAL;
request.c.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.c.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
request.d = client_addr.unwrap().octets(); request.d = client_addr.unwrap().octets();
request.e.rta_type = libc::IFA_BROADCAST; request.e.rta_type = libc::IFA_BROADCAST;
request.e.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.e.rta_len =
request.f = ((u32::from(client_addr.unwrap()) & u32::from(subnet_mask)) | (!u32::from(subnet_mask))).to_be_bytes(); std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
if let Some(broadcast) = broadcast {
request.f = broadcast.octets();
} else {
request.f = ((u32::from(client_addr.unwrap())
& u32::from(subnet_mask))
| (!u32::from(subnet_mask)))
.to_be_bytes();
}
request.g.rta_type = libc::IFA_CACHEINFO; request.g.rta_type = libc::IFA_CACHEINFO;
request.g.rta_len = std::mem::size_of::<(rtnetlink::rtattr, rtnetlink::ifa_cacheinfo)>() as u16; request.g.rta_len = std::mem::size_of::<(
request.h.ifa_preferred = (sleep_time as f32 * 0.5) as u32; rtnetlink::rtattr,
request.h.ifa_valid = (sleep_time as f32 * 0.875) as u32; rtnetlink::ifa_cacheinfo,
)>() as u16;
request.h.ifa_preferred =
renew_time.unwrap_or((sleep_time as f32 * 0.5) as u32);
request.h.ifa_valid =
rebind_time.unwrap_or((sleep_time as f32 * 0.875) as u32);
socket_nl.send(rtnetlink::to_slice(&request)).unwrap(); socket_nl.send(rtnetlink::to_slice(&request)).unwrap();
} }
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::rtmsg, c: rtnetlink::rtattr, d: [u8; 4], e: rtnetlink::rtattr, f: libc::c_int, g: rtnetlink::rtattr, h: rtnetlink::rta_cacheinfo} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::rtmsg,
c: rtnetlink::rtattr,
d: [u8; 4],
e: rtnetlink::rtattr,
f: libc::c_int,
g: rtnetlink::rtattr,
h: rtnetlink::rta_cacheinfo,
}
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
request.a.nlmsg_type = libc::RTM_NEWROUTE; request.a.nlmsg_type = libc::RTM_NEWROUTE;
request.a.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16; request.a.nlmsg_flags =
(libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16;
request.b.rtm_family = libc::AF_INET as u8; request.b.rtm_family = libc::AF_INET as u8;
request.b.rtm_table = libc::RT_TABLE_MAIN; request.b.rtm_table = libc::RT_TABLE_MAIN;
request.b.rtm_type = libc::RTN_UNICAST; request.b.rtm_type = libc::RTN_UNICAST;
@ -369,27 +425,43 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
request.b.rtm_scope = libc::RT_SCOPE_LINK; request.b.rtm_scope = libc::RT_SCOPE_LINK;
request.b.rtm_dst_len = u32::from(subnet_mask).leading_ones() as u8; request.b.rtm_dst_len = u32::from(subnet_mask).leading_ones() as u8;
request.c.rta_type = libc::RTA_DST; request.c.rta_type = libc::RTA_DST;
request.c.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.c.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
request.d = client_addr.unwrap().octets(); request.d = client_addr.unwrap().octets();
request.e.rta_type = libc::RTA_OIF; request.e.rta_type = libc::RTA_OIF;
request.e.rta_len = std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16; request.e.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16;
request.f = index; request.f = index;
request.g.rta_type = libc::RTA_CACHEINFO; request.g.rta_type = libc::RTA_CACHEINFO;
request.g.rta_len = std::mem::size_of::<(rtnetlink::rtattr, rtnetlink::rta_cacheinfo)>() as u16; request.g.rta_len = std::mem::size_of::<(
request.h.rta_expires = (sleep_time as f32 * 0.875) as u32; rtnetlink::rtattr,
rtnetlink::rta_cacheinfo,
)>() as u16;
request.h.rta_expires =
rebind_time.unwrap_or((sleep_time as f32 * 0.875) as u32);
socket_nl.send(rtnetlink::to_slice(&request)).unwrap(); socket_nl.send(rtnetlink::to_slice(&request)).unwrap();
} }
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::rtmsg, c: rtnetlink::rtattr, d: [u8; 4], e: rtnetlink::rtattr, f: libc::c_int, g: rtnetlink::rtattr, h: rtnetlink::rta_cacheinfo} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::rtmsg,
c: rtnetlink::rtattr,
d: [u8; 4],
e: rtnetlink::rtattr,
f: libc::c_int,
g: rtnetlink::rtattr,
h: rtnetlink::rta_cacheinfo,
}
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
request.a.nlmsg_type = libc::RTM_NEWROUTE; request.a.nlmsg_type = libc::RTM_NEWROUTE;
request.a.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16; request.a.nlmsg_flags =
(libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16;
request.b.rtm_family = libc::AF_INET as u8; request.b.rtm_family = libc::AF_INET as u8;
request.b.rtm_table = libc::RT_TABLE_MAIN; request.b.rtm_table = libc::RT_TABLE_MAIN;
request.b.rtm_type = libc::RTN_UNICAST; request.b.rtm_type = libc::RTN_UNICAST;
@ -397,28 +469,44 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
request.b.rtm_scope = libc::RT_SCOPE_UNIVERSE; request.b.rtm_scope = libc::RT_SCOPE_UNIVERSE;
request.b.rtm_dst_len = 0; request.b.rtm_dst_len = 0;
request.c.rta_type = libc::RTA_GATEWAY; request.c.rta_type = libc::RTA_GATEWAY;
request.c.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.c.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
request.d = pick_weighted(&router).unwrap().octets(); request.d = pick_weighted(&router).unwrap().octets();
request.e.rta_type = libc::RTA_OIF; request.e.rta_type = libc::RTA_OIF;
request.e.rta_len = std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16; request.e.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16;
request.f = index; request.f = index;
request.g.rta_type = libc::RTA_CACHEINFO; request.g.rta_type = libc::RTA_CACHEINFO;
request.g.rta_len = std::mem::size_of::<(rtnetlink::rtattr, rtnetlink::rta_cacheinfo)>() as u16; request.g.rta_len = std::mem::size_of::<(
request.h.rta_expires = (sleep_time as f32 * 0.875) as u32; rtnetlink::rtattr,
rtnetlink::rta_cacheinfo,
)>() as u16;
request.h.rta_expires =
rebind_time.unwrap_or((sleep_time as f32 * 0.875) as u32);
socket_nl.send(rtnetlink::to_slice(&request)).unwrap(); socket_nl.send(rtnetlink::to_slice(&request)).unwrap();
} }
{ {
#[repr(packed)] #[repr(packed)]
struct Request {a: libc::nlmsghdr, b: rtnetlink::rtmsg, c: rtnetlink::rtattr, d: [u8; 4], e: rtnetlink::rtattr, f: [u8; 4], g: rtnetlink::rtattr, h: libc::c_int} struct Request {
a: libc::nlmsghdr,
b: rtnetlink::rtmsg,
c: rtnetlink::rtattr,
d: [u8; 4],
e: rtnetlink::rtattr,
f: [u8; 4],
g: rtnetlink::rtattr,
h: libc::c_int,
}
for (prefix, prefix_len, router) in classless_static_routes { for (prefix, prefix_len, router) in classless_static_routes {
let mut request = std::mem::zeroed::<Request>(); let mut request = std::mem::zeroed::<Request>();
request.a.nlmsg_len = std::mem::size_of::<Request>() as u32; request.a.nlmsg_len = std::mem::size_of::<Request>() as u32;
request.a.nlmsg_type = libc::RTM_NEWROUTE; request.a.nlmsg_type = libc::RTM_NEWROUTE;
request.a.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16; request.a.nlmsg_flags =
(libc::NLM_F_REQUEST | libc::NLM_F_CREATE) as u16;
request.b.rtm_family = libc::AF_INET as u8; request.b.rtm_family = libc::AF_INET as u8;
request.b.rtm_table = libc::RT_TABLE_MAIN; request.b.rtm_table = libc::RT_TABLE_MAIN;
request.b.rtm_type = libc::RTN_UNICAST; request.b.rtm_type = libc::RTN_UNICAST;
@ -426,29 +514,44 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
request.b.rtm_scope = libc::RT_SCOPE_UNIVERSE; request.b.rtm_scope = libc::RT_SCOPE_UNIVERSE;
request.b.rtm_dst_len = prefix_len; request.b.rtm_dst_len = prefix_len;
request.c.rta_type = libc::RTA_DST; request.c.rta_type = libc::RTA_DST;
request.c.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.c.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
request.d = prefix.octets(); request.d = prefix.octets();
request.e.rta_type = libc::RTA_GATEWAY; request.e.rta_type = libc::RTA_GATEWAY;
request.e.rta_len = std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16; request.e.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, [u8; 4])>() as u16;
request.f = router.octets(); request.f = router.octets();
request.g.rta_type = libc::RTA_OIF; request.g.rta_type = libc::RTA_OIF;
request.g.rta_len = std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16; request.g.rta_len =
std::mem::size_of::<(rtnetlink::rtattr, libc::c_int)>() as u16;
request.h = index; request.h = index;
socket_nl.send(rtnetlink::to_slice(&request)).unwrap(); socket_nl.send(rtnetlink::to_slice(&request)).unwrap();
} }
} }
let mut f = std::fs::OpenOptions::new().write(true).truncate(true).open("/etc/resolv.conf").unwrap(); let mut f = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open("/etc/resolv.conf")
.unwrap();
for server in dns { for server in dns {
f.write_all(("nameserver ".to_string() + &server.to_string() + "\n").as_bytes()).unwrap(); f.write_all(
("nameserver ".to_string() + &server.to_string() + "\n").as_bytes(),
)
.unwrap();
} }
f.flush().unwrap(); f.flush().unwrap();
} }
println!("Sleeping for {} for lease time to elapse.", (sleep_time as f32 * 0.5) as u32); println!(
std::thread::sleep(core::time::Duration::new((sleep_time as f32 * 0.5) as u64, 0)); "Sleeping for {} for lease time to elapse.",
renew_time.unwrap_or((sleep_time as f32 * 0.5) as u32)
);
std::thread::sleep(core::time::Duration::new(
renew_time.unwrap_or((sleep_time as f32 * 0.5) as u32) as u64,
0,
));
dhcp_state = DHCPTransactionState::Renew dhcp_state = DHCPTransactionState::Renew
} }
@ -466,7 +569,7 @@ fn dhcp_client(name: String, index: i32, mac: [u8; 6]) {
DHCPOption::End, DHCPOption::End,
], ],
) )
.as_bytes() .as_bytes(),
); );
dhcp_state = DHCPTransactionState::WaitAfterRequest; dhcp_state = DHCPTransactionState::WaitAfterRequest;
} }

View File

@ -8,7 +8,7 @@ pub struct RawSocket {
socket: libc::c_int, socket: libc::c_int,
src_addr: libc::sockaddr_ll, src_addr: libc::sockaddr_ll,
dest_addr: libc::sockaddr_ll, dest_addr: libc::sockaddr_ll,
if_index: i32 if_index: i32,
} }
pub fn create_raw_socket(index: i32, mac: [u8; 6]) -> Result<RawSocket, &'static str> { pub fn create_raw_socket(index: i32, mac: [u8; 6]) -> Result<RawSocket, &'static str> {
@ -42,15 +42,34 @@ pub fn create_raw_socket(index: i32, mac: [u8; 6]) -> Result<RawSocket, &'static
let mut timeval = std::mem::zeroed::<libc::timeval>(); let mut timeval = std::mem::zeroed::<libc::timeval>();
timeval.tv_sec = 30; timeval.tv_sec = 30;
if libc::setsockopt(socket, libc::SOL_SOCKET, libc::SO_RCVTIMEO, &timeval as *const _ as *const libc::c_void, std::mem::size_of::<libc::timeval>() as u32) == -1 { if libc::setsockopt(
socket,
libc::SOL_SOCKET,
libc::SO_RCVTIMEO,
&timeval as *const _ as *const libc::c_void,
std::mem::size_of::<libc::timeval>() as u32,
) == -1
{
return Err("Failed to set SO_RCVTIMEO"); return Err("Failed to set SO_RCVTIMEO");
} }
if libc::setsockopt(socket, libc::SOL_SOCKET, libc::SO_BROADCAST, &(1 as u32) as *const _ as *const libc::c_void, std::mem::size_of::<u32>() as u32) == -1 { if libc::setsockopt(
return Err("Failed to set SO_BROADCAST") socket,
libc::SOL_SOCKET,
libc::SO_BROADCAST,
&(1 as u32) as *const _ as *const libc::c_void,
std::mem::size_of::<u32>() as u32,
) == -1
{
return Err("Failed to set SO_BROADCAST");
} }
if libc::bind(socket, &src_addr as *const _ as *const libc::sockaddr, std::mem::size_of::<libc::sockaddr_ll>() as u32) == -1 { if libc::bind(
socket,
&src_addr as *const _ as *const libc::sockaddr,
std::mem::size_of::<libc::sockaddr_ll>() as u32,
) == -1
{
return Err("Failed to bind to socket"); return Err("Failed to bind to socket");
} }
} }
@ -59,7 +78,7 @@ pub fn create_raw_socket(index: i32, mac: [u8; 6]) -> Result<RawSocket, &'static
socket: socket, socket: socket,
src_addr: src_addr, src_addr: src_addr,
dest_addr: dest_addr, dest_addr: dest_addr,
if_index: index if_index: index,
}) })
} }
@ -100,10 +119,16 @@ impl RawSocket {
if n < 0 { if n < 0 {
match unsafe { *libc::__errno_location() } { match unsafe { *libc::__errno_location() } {
libc::EAGAIN => return Ok((0, [0, 0, 0, 0, 0, 0])), libc::EAGAIN => return Ok((0, [0, 0, 0, 0, 0, 0])),
err => return Err(err) err => return Err(err),
} }
} else { } else {
return Ok((n, unsafe { std::ptr::read(msg.msg_name as *mut _ as *mut libc::sockaddr_ll) }.sll_addr[..6].try_into().unwrap())); return Ok((
n,
unsafe { std::ptr::read(msg.msg_name as *mut _ as *mut libc::sockaddr_ll) }
.sll_addr[..6]
.try_into()
.unwrap(),
));
} }
} }

View File

@ -155,7 +155,7 @@ unsafe fn ifla_rta(r: *const ifinfomsg) -> *const rtattr {
pub struct Socket { pub struct Socket {
socket: libc::c_int, socket: libc::c_int,
src_addr: libc::sockaddr_nl, src_addr: libc::sockaddr_nl,
dest_addr: libc::sockaddr_nl dest_addr: libc::sockaddr_nl,
} }
pub fn create_netlink_socket(subscribed: bool) -> Result<Socket, &'static str> { pub fn create_netlink_socket(subscribed: bool) -> Result<Socket, &'static str> {
@ -177,7 +177,12 @@ pub fn create_netlink_socket(subscribed: bool) -> Result<Socket, &'static str> {
return Err("Failed to create socket"); return Err("Failed to create socket");
} }
if libc::bind(socket, &src_addr as *const _ as *const libc::sockaddr, std::mem::size_of::<libc::sockaddr_nl>() as u32) == -1 { if libc::bind(
socket,
&src_addr as *const _ as *const libc::sockaddr,
std::mem::size_of::<libc::sockaddr_nl>() as u32,
) == -1
{
return Err("Failed to bind to socket"); return Err("Failed to bind to socket");
} }
} }
@ -185,7 +190,7 @@ pub fn create_netlink_socket(subscribed: bool) -> Result<Socket, &'static str> {
Ok(Socket { Ok(Socket {
socket: socket, socket: socket,
src_addr: src_addr, src_addr: src_addr,
dest_addr: dest_addr dest_addr: dest_addr,
}) })
} }
@ -239,10 +244,7 @@ pub struct InterfaceIterator {
} }
pub unsafe fn to_slice<T: Sized>(p: &T) -> &[u8] { pub unsafe fn to_slice<T: Sized>(p: &T) -> &[u8] {
std::slice::from_raw_parts( std::slice::from_raw_parts((p as *const T) as *const u8, std::mem::size_of::<T>())
(p as *const T) as *const u8,
std::mem::size_of::<T>(),
)
} }
pub fn new_interface_iterator() -> Result<InterfaceIterator, &'static str> { pub fn new_interface_iterator() -> Result<InterfaceIterator, &'static str> {
@ -254,7 +256,9 @@ pub fn new_interface_iterator() -> Result<InterfaceIterator, &'static str> {
request.0.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_DUMP) as u16; request.0.nlmsg_flags = (libc::NLM_F_REQUEST | libc::NLM_F_DUMP) as u16;
request.1.ifi_family = libc::AF_NETLINK as u8; request.1.ifi_family = libc::AF_NETLINK as u8;
socket.send(unsafe {to_slice(&request)}).expect("Failed to send interface request!"); socket
.send(unsafe { to_slice(&request) })
.expect("Failed to send interface request!");
Ok(InterfaceIterator { Ok(InterfaceIterator {
socket: socket, socket: socket,