计算Rust中的UDP校验和?

发布于 2025-01-26 03:07:34 字数 2059 浏览 3 评论 0原文

我正在尝试手动构建数据包,并且难以计算正确的UDP校验和。有人可以告诉我我在以下代码中做错了什么?传递的数据包是将与UDP校验和0x0000的占位符一起发送的完整数据包,但我总结了psoudoheader,UDP标头和UDP有效载荷,但是根据Wireshark,我的UDP校验和不正确。 (我的:0x9f4c vs Wireshark:0x2b7b)

fn udp_checksum (packet: &Vec<u8>) -> [u8; 2] {
    let mut idx = 0;
    let mut idx_end = 2;
    let mut payload = &packet[42..];
    let payload_len = payload.len();
    if payload_len % 2 != 0 {
        payload.to_vec().push(0);
    }
    let source_ip_1 = BigEndian::read_u16(&packet[26..28]); //source ip 1 of 2
    let source_ip_2 = BigEndian::read_u16(&packet[28..30]); //source ip 2 of 2
    let dest_ip_1 = BigEndian::read_u16(&packet[30..32]); //dest ip 1 of 2
    let dest_ip_2 = BigEndian::read_u16(&packet[32..34]); //dest ip 2 of 2
    let udp_len = BigEndian::read_u16(&packet[38..40]);
    let source_port = BigEndian::read_u16(&packet[34..36]);
    let dest_port = BigEndian::read_u16(&packet[36..38]);

    let mut header_sum = UDP_PROTO as u32 + source_ip_1 as u32 + source_ip_2 as u32 + dest_ip_1 as u32 + dest_ip_2 as u32 + udp_len as u32 + source_port as u32 + dest_port as u32 + udp_len as u32;
    // println!("Payload Len: {:?}", &payload.len());
    // println!("Payload: {:?}", &payload);
    // println!("First Payload Slice: {:?}", &payload[idx..idx_end]);
    // println!("First BE U32: {:?}", BigEndian::read_u16(&payload[idx..idx_end]) as u32);

    while idx < &payload.len() - 2 {
        header_sum += BigEndian::read_u16(&payload[idx..idx_end]) as u32;
        println!("Header Sum: {:0x?}", &header_sum);
        idx += 2;
        idx_end += 2;
    }

    while header_sum > 0xffff {
        header_sum -= 0xffff;
        header_sum += 1;
    }

    let udp_csum = 0xffff - (header_sum as u16);

    let csum_one: u8 = header_sum as u8;
    let csum_two: u8 = (header_sum >> 8) as u8;
    println!("Calculated CSUM: {:?}", udp_csum);
    println!("Checksum: {:0x}{:0x}", csum_one, csum_two);
    return [csum_one, csum_two];
}```

I am trying to manually build packets and am having trouble calculating a correct UDP checksum. Can someone tell me what I am doing wrong in the below code? The packet being passed in is the complete packet to be sent with a placeholder for the UDP Checksum currently of 0x0000, but I sum the psuedoheader, udp header, and udp payload, but according to wireshark my UDP checksums are incorrect. (Mine: 0x9f4c vs Wireshark: 0x2b7b for example)

fn udp_checksum (packet: &Vec<u8>) -> [u8; 2] {
    let mut idx = 0;
    let mut idx_end = 2;
    let mut payload = &packet[42..];
    let payload_len = payload.len();
    if payload_len % 2 != 0 {
        payload.to_vec().push(0);
    }
    let source_ip_1 = BigEndian::read_u16(&packet[26..28]); //source ip 1 of 2
    let source_ip_2 = BigEndian::read_u16(&packet[28..30]); //source ip 2 of 2
    let dest_ip_1 = BigEndian::read_u16(&packet[30..32]); //dest ip 1 of 2
    let dest_ip_2 = BigEndian::read_u16(&packet[32..34]); //dest ip 2 of 2
    let udp_len = BigEndian::read_u16(&packet[38..40]);
    let source_port = BigEndian::read_u16(&packet[34..36]);
    let dest_port = BigEndian::read_u16(&packet[36..38]);

    let mut header_sum = UDP_PROTO as u32 + source_ip_1 as u32 + source_ip_2 as u32 + dest_ip_1 as u32 + dest_ip_2 as u32 + udp_len as u32 + source_port as u32 + dest_port as u32 + udp_len as u32;
    // println!("Payload Len: {:?}", &payload.len());
    // println!("Payload: {:?}", &payload);
    // println!("First Payload Slice: {:?}", &payload[idx..idx_end]);
    // println!("First BE U32: {:?}", BigEndian::read_u16(&payload[idx..idx_end]) as u32);

    while idx < &payload.len() - 2 {
        header_sum += BigEndian::read_u16(&payload[idx..idx_end]) as u32;
        println!("Header Sum: {:0x?}", &header_sum);
        idx += 2;
        idx_end += 2;
    }

    while header_sum > 0xffff {
        header_sum -= 0xffff;
        header_sum += 1;
    }

    let udp_csum = 0xffff - (header_sum as u16);

    let csum_one: u8 = header_sum as u8;
    let csum_two: u8 = (header_sum >> 8) as u8;
    println!("Calculated CSUM: {:?}", udp_csum);
    println!("Checksum: {:0x}{:0x}", csum_one, csum_two);
    return [csum_one, csum_two];
}```

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

魔法唧唧 2025-02-02 03:07:34

这可能只是解决问题的部分解决方案。

有效载荷.to_vec()创建一个新的向量。
扩展它对有效载荷没有影响。

制作有效载荷可变可在必要时可以在扩展向量上工作。

这是一个最小的例子。

fn main() {
    let v1 = vec![9, 1, 2, 3];
    let mut v2 = Vec::new(); // empty for now
    let mut sl = &v1[1..]; // could be reassigned to v2
    println!("before v1: {:?}", v1);
    println!("before v2: {:?}", v2);
    println!("before sl: {:?}", sl);
    if sl.len() % 2 != 0 {
        v2 = sl.to_vec();
        v2.push(0);
        sl = &v2[..];
    }
    println!("after v1: {:?}", v1);
    println!("after v2: {:?}", v2);
    println!("after sl: {:?}", sl);
}
/*
before v1: [9, 1, 2, 3]
before v2: []
before sl: [1, 2, 3]
after v1: [9, 1, 2, 3]
after v2: [1, 2, 3, 0]
after sl: [1, 2, 3, 0]
*/

避免副本的另一个解决方案是较早停止一个字节(如果pareload.len()是奇怪的),然后处理剩余的字节。

It's maybe only a partial solution to the problem.

payload.to_vec() creates a new vector.
Extending it has no influence on payload.

Making payload mutable will enable working on the extended vector if necessary.

Here is a minimal example.

fn main() {
    let v1 = vec![9, 1, 2, 3];
    let mut v2 = Vec::new(); // empty for now
    let mut sl = &v1[1..]; // could be reassigned to v2
    println!("before v1: {:?}", v1);
    println!("before v2: {:?}", v2);
    println!("before sl: {:?}", sl);
    if sl.len() % 2 != 0 {
        v2 = sl.to_vec();
        v2.push(0);
        sl = &v2[..];
    }
    println!("after v1: {:?}", v1);
    println!("after v2: {:?}", v2);
    println!("after sl: {:?}", sl);
}
/*
before v1: [9, 1, 2, 3]
before v2: []
before sl: [1, 2, 3]
after v1: [9, 1, 2, 3]
after v2: [1, 2, 3, 0]
after sl: [1, 2, 3, 0]
*/

Another solution, avoiding the copy, would be to stop one byte earlier (if payload.len() is odd) the loop, then deal with the remaining byte.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文