network_search 0.1.0

the tools which is useful for searching networks
pub mod tcp{
    use pnet::packet::{tcp::{MutableTcpPacket, TcpFlags::{ACK, SYN}, TcpPacket,TcpOption,},Packet,ipv4::Ipv4Packet};
    use pnet::datalink::{NetworkInterface,channel,Channel::Ethernet};
    use pnet::packet::ethernet::{EtherTypes, EthernetPacket};
    use pnet::packet::ip::IpNextHeaderProtocols::Tcp;
    use pnet::transport::{transport_channel,TransportChannelType::Layer4};
    use pnet::transport::TransportProtocol::Ipv4;

    use std::sync::mpsc;
    use std::thread::{sleep, spawn};
    use std::net::{IpAddr,Ipv4Addr};
    use std::time::Duration;

    use crate::util::util::get_local_ip;

    pub fn make_tcp_packet(tcp: &mut MutableTcpPacket){
        tcp.set_flags(SYN);
        tcp.set_window(1000); // 0 でもよかったかもしれない
        tcp.set_data_offset(6);
        tcp.set_sequence(20);
        tcp.set_acknowledgement(100);
        tcp.set_options(&[TcpOption::mss(1460)]); // The maximum segment size (MSS)
    }

    pub fn send_recv_packet(tcp: &mut MutableTcpPacket,remote_addr: Ipv4Addr,interface: NetworkInterface)->bool{
        let (mut tx, _) = transport_channel(4096, Layer4(Ipv4(Tcp))).unwrap();
    
        let lp = tcp.get_source().clone();
        let rp = tcp.get_destination().clone();
    
        // スレッド間の通信用チャネル
        let (t, r) = mpsc::channel();
    
        // ターゲットからの応答パケットを受信するスレッドの開始。
        // 受信するとチャネル t に応答パケットのフラグを送信する
        let handle = spawn(move || {
            t.send(match recv(interface, lp,rp, get_local_ip().unwrap().0,remote_addr) {
                Err(e) => {
                    eprintln!("[Error] {:?}", e);
                    0u8
                }
                Ok(flags) => flags,
            })
            .unwrap();
        });
    
    
        sleep(Duration::from_millis(10));
    
        // SYN パケットの送信
        tx.send_to(tcp.to_immutable(), IpAddr::V4(remote_addr)).unwrap();
    
        match r.recv_timeout(Duration::from_millis(1000)) {
            Err(_) => {
                //println!("Timeout");
                return false;
            },
            Ok(f) => {
                handle.join().unwrap();
                //println!("{:?}",f);
                if f == SYN+ACK {
                    return true;
                }else{
                    return false;
                }
            }
        }
    
    
    }

    fn recv(
        interface: NetworkInterface,
        lp: u16,
        rp: u16,
        li: Ipv4Addr,
        ri: Ipv4Addr,
    ) -> Result<u8, ()> {
        let mut flags = 0u8;
    
        // イーサネットフレームを受信するチャネル rx を取得
        if let Ethernet(_, mut rx) = channel(&interface, Default::default()).unwrap() {
            loop {
                // rx からイーサネットフレームを取り出して処理する
                let bytes = rx.next().unwrap();
                let frame = EthernetPacket::new(bytes);
                if frame.is_none() {
                    continue;
                }
                let frame = frame.unwrap();
                if frame.get_ethertype() != EtherTypes::Ipv4 {
                    continue;
                }
                let ipv4 = Ipv4Packet::new(frame.payload());
                if ipv4.is_none() {
                    continue;
                }
                let ipv4 = ipv4.unwrap();
                if ipv4.get_source() != ri || ipv4.get_destination() != li {
                    // IPアドレスが条件を満たさないのでスキップ
                    continue;
                }
                if ipv4.get_next_level_protocol() != Tcp {
                    continue;
                }
                let tcp = TcpPacket::new(ipv4.payload());
                if tcp.is_none() {
                    continue;
                }
                let tcp = tcp.unwrap();
                if tcp.get_source() != rp || tcp.get_destination() != lp {
                    // ポート番号が条件を満たさないのでスキップ
                    continue;
                }
    
                // ここまで到達するのは欲しい TCP セグメントだった時
                flags = tcp.get_flags();
    
                //println!("received");
    
                break; // ループを抜ける
            }
        }
    
        Ok(flags)
    }
}