1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::convert::TryFrom;
use std::net::{IpAddr, SocketAddr};
use std::mem::transmute;
use crate::Message;
use crate::err::Invalid;
use crate::ffi::{AF_INET, AF_INET6, inet_diag_msg, tcp_info};
use crate::sys::Bytes;
#[derive(Debug)]
pub struct Diag<T = tcp_info> {
pub family: u8,
pub src: SocketAddr,
pub dst: SocketAddr,
pub state: u8,
pub info: Option<T>,
}
pub fn diag(msg: &Message<inet_diag_msg>) -> Result<Diag, Invalid> {
let src = addr(msg.idiag_family, &msg.id.idiag_src, msg.id.idiag_sport)?;
let dst = addr(msg.idiag_family, &msg.id.idiag_dst, msg.id.idiag_dport)?;
let info = msg.info();
Ok(Diag {
family: msg.idiag_family,
src: src,
dst: dst,
state: msg.idiag_state,
info: info,
})
}
pub fn diag2<T: Bytes>(msg: Message<inet_diag_msg>) -> Result<Diag<T>, Invalid> {
let src = addr(msg.idiag_family, &msg.id.idiag_src, msg.id.idiag_sport)?;
let dst = addr(msg.idiag_family, &msg.id.idiag_dst, msg.id.idiag_dport)?;
let info = msg.info();
Ok(Diag {
family: msg.idiag_family,
src: src,
dst: dst,
state: msg.idiag_state,
info: info,
})
}
fn addr(family: u8, addr: &[u32; 4], port: u16) -> Result<SocketAddr, Invalid> {
let octets: &[u8; 16] = unsafe { transmute(addr) };
Ok(SocketAddr::new(match family {
AF_INET => IpAddr::from(<[u8; 4]>::try_from(&octets[..4])?),
AF_INET6 => IpAddr::from(<[u8; 16]>::try_from(&octets[..])?),
family => return Err(Invalid::Family(family)),
}, port.to_be()))
}