meh / rust-tun

TUN device creation and handling.
340 stars 133 forks source link

The synchronous `write` does not work #67

Open xmh0511 opened 10 months ago

xmh0511 commented 10 months ago
use packet::{builder::Builder, icmp, ip, Packet};
use std::io::{Read, Write};
use std::net::Ipv4Addr;

fn main() {
    let mut config = tun::Configuration::default();

    config
        .address((10, 0, 0, 1))
        .netmask((255, 255, 255, 0))
        .up();

    #[cfg(target_os = "linux")]
    config.platform(|config| {
        config.packet_information(true);
    });

    let mut dev = tun::create(&config).unwrap();
    let mut buf = [0; 4096];

    loop {
        println!("prepare to read");
        let amount = dev.read(&mut buf).unwrap();
        //println!("{:?}", &buf[0..amount]);
        let read_buf = &buf[4..amount];

        match ip::Packet::new(read_buf) {
            Ok(ip::Packet::V4(pkt)) => match icmp::Packet::new(pkt.payload()) {
                Ok(icmp) => match icmp.echo() {
                    Ok(icmp) => {
                        println!("packet comming!!!! src: {}, dest: {}",pkt.source(),pkt.destination());
                        let reply = ip::v4::Builder::default()
                            .id(0x42)
                            .unwrap()
                            .ttl(64)
                            .unwrap()
                            .source(pkt.destination())
                            .unwrap()
                            .destination(pkt.source())
                            .unwrap()
                            .icmp()
                            .unwrap()
                            .echo()
                            .unwrap()
                            .reply()
                            .unwrap()
                            .identifier(icmp.identifier())
                            .unwrap()
                            .sequence(icmp.sequence())
                            .unwrap()
                            .payload(icmp.payload())
                            .unwrap()
                            .build()
                            .unwrap();
                        let r = dev.write(&reply[..]).unwrap();
                        dev.flush().unwrap();
                        println!("write {r}");
                    }
                    _ => {}
                },
                _ => {}
            },
            Err(err) => println!("Received an invalid packet: {:?}", err),
            _ => {}
        }
    }
}

This code is exactly the same as that of https://github.com/meh/rust-tun/blob/master/examples/ping-tun.rs except that the code uses synchronous version API. When running command ping 10.0.0.2, the program can read packet, however, when trying to reply to the ICMP packet, dev.write does not work. I'm not sure what wrong is here.

xmh0511 commented 10 months ago

The resolution is, that the response data should be headed by [0, 0, 0, 2].