Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux strace can';无法分析我的netlink消息,但它似乎有效_Linux_Rust_Netlink - Fatal编程技术网

Linux strace can';无法分析我的netlink消息,但它似乎有效

Linux strace can';无法分析我的netlink消息,但它似乎有效,linux,rust,netlink,Linux,Rust,Netlink,我第一次尝试在linux中使用NetLink API。我用铁锈,因为它还没有咬到我的屁股,让我回到C。我认为一个很好的开始是枚举netlink设备,因为已经有一个实用程序可以这样做(ip link)。当我运行Rust代码时,它返回ip link返回的6个设备中的3个设备。因此,我试图检查我正在发送的请求与ip-link正在发送的请求 # Mine $ sudo strace -ff -v -e trace=%network mine 2>&1 |grep sendto send

我第一次尝试在linux中使用NetLink API。我用铁锈,因为它还没有咬到我的屁股,让我回到C。我认为一个很好的开始是枚举netlink设备,因为已经有一个实用程序可以这样做(
ip link
)。当我运行Rust代码时,它返回
ip link
返回的6个设备中的3个设备。因此,我试图检查我正在发送的请求与
ip-link
正在发送的请求

# Mine
$ sudo strace -ff  -v -e trace=%network mine 2>&1  |grep sendto
sendto(3, 
  {
    {nlmsg_len=40, nlmsg_type=0x12 /* NLMSG_??? */, nlmsg_flags=NLM_F_REQUEST|0x300, nlmsg_seq=1620766291, nlmsg_pid=0}, 
    "\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1d\x00\x01\x00\x00\x00"
  },
  40, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 40


$ sudo strace -ff --const-print-style=raw -v -e trace=%network mine 2>&1  |grep sendto                                                                                                            
sendto(3, 
  {
    {nlmsg_len=40, nlmsg_type=0x12, nlmsg_flags=0x301, nlmsg_seq=1620766293, nlmsg_pid=0}, 
    "\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x1d\x00\x01\x00\x00\x00"
  },
  40, 0, {sa_family=0x10, nl_pid=0, nl_groups=00000000}, 12) = 40


# ip link
$ sudo strace -ff  -v -e trace=%network ip link 2>&1  |grep sendto                                            
sendto(3, 
  {
    {nlmsg_len=40, nlmsg_type=RTM_GETLINK, nlmsg_flags=NLM_F_REQUEST|NLM_F_DUMP, nlmsg_seq=1620765818, nlmsg_pid=0}, 
    {ifi_family=AF_PACKET, ifi_type=ARPHRD_NETROM, ifi_index=0, ifi_flags=0, ifi_change=0}, 
    {
      {nla_len=8, nla_type=IFLA_EXT_MASK}, 
      1
    }
  },
  40, 0, NULL, 0) = 40


$ sudo strace -ff --const-print-style=raw -v -e trace=%network ip link 2>&1  |grep sendto
sendto(3, 
  {
    {nlmsg_len=40, nlmsg_type=0x12, nlmsg_flags=0x301, nlmsg_seq=1620765854, nlmsg_pid=0}, 
    {ifi_family=0x11, ifi_type=0, ifi_index=0, ifi_flags=0, ifi_change=0}, 
    {
      {nla_len=8, nla_type=0x1d}, 
      1
    }
  },
  40, 0, NULL, 0) = 40


我能发现的两个区别是:(A)
ip链接
绑定套接字,而Rust库为
sendto提供了一个
dest\u addr
参数。我怀疑这是否相关。(B)
strace
可以解析
ip-link
发送的结构,但似乎无法完全解析我的Rust程序发送的结构
strace
表示两个程序在
struct-nlmsghdr
标题上一致。但是,
strace
不会解析我的程序的
struct-ifinfo-msg
。但是,从字节来看,它似乎是匹配的

我使用的rust库
netlink packet route
似乎与
struct rtattr
没有明显的等价物。在
IFINFOMG
(在rust库中称为
LinkHeader
)旁边,有一个它称为
Nla
的列表。枚举值与其C等价项对齐,如上图所示,常量值也对齐

manrtnetlink
没有提到任何关于
IFLA\u EXT\u MASK
的内容,这可能是
RTM\u GETLINK
rtttr
,我在文档中也没有得到很多关于它的点击

我想下一步是将这两个调用都弹出到
gdb
,看看这两个调用之间是否有任何其他可观察到的差异


产生上述信息的超级丑陋的演示质量锈代码:

use std::io::{Result, Error, ErrorKind};
use netlink_sys::{Socket, protocols::NETLINK_ROUTE, SocketAddr};
use netlink_packet_core::{NetlinkMessage, NetlinkHeader, NLM_F_DUMP, NLM_F_REQUEST};
use netlink_packet_route::{RtnlMessage, LinkMessage, LinkHeader, AF_PACKET, ARPHRD_NETROM};
use netlink_packet_core::NetlinkPayload::InnerMessage;
use netlink_packet_route::RtnlMessage::NewLink;
use netlink_packet_route::link::nlas::Nla;
use std::time::{UNIX_EPOCH, SystemTime};

fn main() -> Result<()> {
    println!("Hello, world!");

    let socket = Socket::new(NETLINK_ROUTE)?;
    let kernel_addr = SocketAddr::new(0, 0);

    let msgid = SystemTime::now().duration_since(UNIX_EPOCH).map_err(|_|{Error::from(ErrorKind::Other)})?.as_secs();
    let nlas: Vec<Nla> = vec![Nla::ExtMask(1)];
    let mut packet = NetlinkMessage {
        header: NetlinkHeader {
            sequence_number: msgid as u32,
            flags: NLM_F_DUMP | NLM_F_REQUEST,
            ..Default::default()
        },
        payload: RtnlMessage::GetLink(LinkMessage {header: LinkHeader {
            interface_family: AF_PACKET as u8,
            link_layer_type: ARPHRD_NETROM,
            ..LinkHeader::default()}, nlas, ..LinkMessage::default()}).into(),
    };
    packet.finalize();

    let mut buf = vec![0; packet.header.length as usize];
    packet.serialize(&mut buf[..]);

    let n_sent = socket.send_to(&buf[..], &kernel_addr, 0).unwrap();
    assert_eq!(n_sent, buf.len());
    let mut buf = vec![0; 4096];
    loop {
        let (n_received, sender_addr) = socket.recv_from(&mut buf[..], 0).unwrap();
        assert_eq!(sender_addr, kernel_addr);
        for i in &mut buf[n_received..] { *i = 0 };
        if n_received == 4096 { return Err(Error::from(ErrorKind::OutOfMemory))}
        if buf[4] == 2 && buf[5] == 0 {
            println!("the kernel responded with an error");
            return Err(Error::from(ErrorKind::ConnectionReset));
        }
        if buf[4] == 3 && buf[5] == 0 {
            println!("Done");
            return Ok(());
        }
        let resp = NetlinkMessage::<RtnlMessage>::deserialize(&buf).expect("Failed to deserialize message");
        match resp.payload {
            InnerMessage(i) => match i {
                NewLink(j) => {
                    let name = j.nlas.iter().find(|nla| { matches!(nla, Nla::IfName(_))});

                    println!("index {:?}: {:?}", j.header.index, name);
                },
                _ => println!("Some other message type")
            },
            _ => println!("Some other message type")
        }

    }
}
使用std::io::{Result,Error,ErrorKind};
使用netlink_sys:{Socket,protocols::netlink_ROUTE,SocketAddr};
使用netlink_数据包_核心:{NetlinkMessage,NetlinkHeader,NLM_F_DUMP,NLM_F_REQUEST};
使用netlink_包_路由:{RtnlMessage,LinkMessage,LinkHeader,AF_包,ARPHRD_NETROM};
使用netlink_数据包_core::NetlinkPayload::InnerMessage;
使用netlink_数据包_路由::RtnlMessage::NewLink;
使用netlink_数据包_路由::link::nlas::Nla;
使用std::time::{UNIX_EPOCH,SystemTime};
fn main()->结果{
println!(“你好,世界!”);
让套接字=套接字::新建(NETLINK_路由)?;
让kernel_addr=SocketAddr::new(0,0);
设msgid=SystemTime::now().duration_-since(UNIX_EPOCH).map_-err(| |{Error::from(ErrorKind::Other)}).as_-secs();
让nlas:Vec=Vec![Nla::ExtMask(1)];
让mut packet=NetlinkMessage{
标题:NetlinkHeader{
序列号:msgid为u32,
标志:NLM_F_DUMP | NLM_F_REQUEST,
…默认值::默认值()
},
有效负载:RtnlMessage::GetLink(LinkMessage{header:LinkHeader{
接口_系列:AF_数据包为u8,
链路层类型:ARPHRD\u NETROM,
…LinkHeader::default()},nlas,…LinkMessage::default()}).into(),
};
packet.finalize();
让mut buf=vec![0;packet.header.length as usize];
packet.serialize(&mutbuf[…]);
设n_sent=socket.send_to(&buf[…],&kernel_addr,0).unwrap();
assert_eq!(n_sent,buf.len());
设mut buf=vec![0;4096];
环路{
let(n_received,sender_addr)=socket.recv_from(&mut buf[…],0).unwrap();
断言(发送方地址、内核地址);
对于i in&mut buf[n_received..]{*i=0};
如果n_received==4096{返回Err(Error::from(ErrorKind::OutOfMemory))}
如果buf[4]==2&&buf[5]==0{
println!(“内核响应错误”);
返回Err(Error::from(ErrorKind::ConnectionReset));
}
如果buf[4]==3&&buf[5]==0{
println!(“完成”);
返回Ok(());
}
let resp=NetlinkMessage:::反序列化(&buf).expect(“反序列化消息失败”);
匹配相应有效载荷{
InnerMessage(i)=>匹配i{
新链接(j)=>{
让name=j.nlas.iter().find(| nla |{matches!(nla,nla::IfName(|));
println!(“索引{:?}:{:?}”,j.header.index,name);
},
_=>println!(“其他消息类型”)
},
_=>println!(“其他消息类型”)
}
}
}

因此,
netlink
将在单个响应数据包中发送多个响应结构。我发现这一点是通过为netlink设置一个监视器接口并对其进行tcpdump来实现的。响应
ip-link
和我的程序返回的总字节数相似,但它们分布在不同数量的数据包上。
recvmsg
调用上使用的缓冲区大小会影响
netlink
打包结果的方式

sudo ip link add  nlmon0 type nlmon
sudo ip link set dev nlmon0 up
sudo tcpdump -i nlmon0 -w /tmp/dump &
ip link
mine
fg
CTRL+C
tshark -r /tmp/dump
我需要弄清楚如何设置这个生锈库来处理这个问题

    1   0.000000              →              Netlink route 56 
    2   0.000073              →              Netlink route 2660 
    3   0.000127              →              Netlink route 2688 
    4   0.000205              →              Netlink route 4060 
    5   0.000258              →              Netlink 36 
    6   3.622386              →              Netlink route 56 
    7   3.622449              →              Netlink route 2660 
    8   3.622512              →              Netlink route 2688 
    9   3.623179              →              Netlink route 2740 
   10   3.623748              →              Netlink route 1336 
   11   3.624273              →              Netlink 36