0213-資料鏈路層協議

波尔發表於2024-08-09

環境

  • Time 2022-11-20
  • WSL-Ubuntu 22.04
  • Rust 1.65.0
  • pnet 0.31.0

前言

說明

參考:https://docs.rs/pnet_datalink/0.31.0/pnet_datalink/linux
RFC894:https://www.rfc-editor.org/rfc/pdfrfc/rfc894.txt.pdf
《TCP/IP詳解 卷1:協議》:http://www.52im.net/topic-tcpipvol1.html

目標

RFC894 介紹了資料鏈路層的一些情況。其中乙太網幀的前 6 個位元組是目的主機的 MAC 地址。
後面跟著的是源主機 MAC 地址,再後面兩位是乙太網幀的型別,需要使用 0800 標記,表示 IPv4。

接收資料

use pnet_datalink::{linux, Channel};

fn main() {
    let interfaces = linux::interfaces();

    let dummy: Vec<_> = interfaces
        .into_iter()
        .filter(|e| e.name == "mydummy")
        .collect();

    let config = linux::Config::default();
    let channel = linux::channel(&dummy[0], config);
    let (mut _sender, mut reader) = match channel {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        _ => panic!("Not a valid channel returned"),
    };

    let bytes = reader.next().unwrap();
    println!("reader: {:?}", bytes);
}

傳送資料

use pnet_datalink::{linux, Channel};

fn main() {
    let interfaces = linux::interfaces();

    let dummy: Vec<_> = interfaces
        .into_iter()
        .filter(|e| e.name == "mydummy")
        .collect();

    let config = linux::Config::default();
    let channel = linux::channel(&dummy[0], config);
    let (mut sender, mut _reader) = match channel {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        _ => panic!("Not a valid channel returned"),
    };

    let mac = dummy[0].mac.unwrap();
    // 目的 MAC + 源 MAC + 型別 = 14 位元組
    let mut buffer = [0; 14];
    buffer[0] = mac.0;
    buffer[1] = mac.1;
    buffer[2] = mac.2;
    buffer[3] = mac.3;
    buffer[4] = mac.4;
    buffer[5] = mac.5;

    // 源
    buffer[6] = mac.0;
    buffer[7] = mac.1;
    buffer[8] = mac.2;
    buffer[9] = mac.3;
    buffer[10] = mac.4;
    buffer[11] = mac.5;

    // 型別
    buffer[12] = 8;
    sender.send_to(&buffer, None).unwrap().unwrap();
}

tcpdump 的顯示

21:27:41.811646 36:e0:f1:2a:e8:45 (oui Unknown) > 36:e0:f1:2a:e8:45 (oui Unknown), ethertype IPv4 (0x0800), length 14:  [|ip]

IP 命令顯示

其中的 link/ether 表示 MAC 地址,在程式中將其寫入到了源和目的地址,tcpdump 也看到了。

8: mydummy: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether 36:e0:f1:2a:e8:45 brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
             0       0      0       0       0       0
    TX:  bytes packets errors dropped carrier collsns
           756      14      0       0       0       0

總結

瞭解了資料鏈路層協議型別,除此之外,還有其它的型別,可以透過給的參考連結檢視。

附錄

相關文章