UDP头计算

问题描述 投票:0回答:1

我需要为固定长度的数据包编写一个无循环版本的 UDP 标头计算。我的数据包始终具有 13 字节的有效负载。我为其编写了以下测试程序,但由于某种原因我无法从阅读 UDP 校验和规范中得到正确的答案。有什么想法问题出在哪里吗?

use etherparse::PacketBuilder;

const SRC_IP: usize = 12;
const DST_IP: usize = 16;

const UDP_START: usize = 20;
const SRC_PORT: usize = 0;
const DST_PORT: usize = 2;
const LEN: usize = 4;
const CHECK: usize = 6;

const IP_HEADER_LEN: u32 = 20;
const UDP_HEADER_LEN: u32 = 8;
const PAYLOAD_LEN: u32 = 13;

const PAYLOAD_START: usize = IP_HEADER_LEN as usize + UDP_HEADER_LEN as usize;

fn my_checksum(packet: [u8; (IP_HEADER_LEN + UDP_HEADER_LEN + PAYLOAD_LEN) as usize]) -> [u8; 2] {
    let mut sum: u32 = UDP_HEADER_LEN + PAYLOAD_LEN + 17; // 17 = UDP protocol number
                                                          // Source IP
    sum += (packet[SRC_IP] as u32) << 8 | (packet[SRC_IP + 1] as u32);
    sum += (packet[SRC_IP + 2] as u32) << 8 | (packet[SRC_IP + 3] as u32);
    // Destination IP
    sum += (packet[DST_IP] as u32) << 8 | (packet[DST_IP + 1] as u32);
    sum += (packet[DST_IP + 2] as u32) << 8 | (packet[DST_IP + 3] as u32);
    // Source PORT
    sum += (packet[UDP_START + SRC_PORT] as u32) << 8 | packet[UDP_START + SRC_PORT + 1] as u32;
    // Destination PORT
    sum += (packet[UDP_START + DST_PORT] as u32) << 8 | packet[UDP_START + DST_PORT + 1] as u32;
    // Payload
    sum += (packet[PAYLOAD_START + 0] as u32) << 8 | packet[PAYLOAD_START + 1] as u32;
    sum += (packet[PAYLOAD_START + 2] as u32) << 8 | packet[PAYLOAD_START + 3] as u32;
    sum += (packet[PAYLOAD_START + 4] as u32) << 8 | packet[PAYLOAD_START + 5] as u32;
    sum += (packet[PAYLOAD_START + 6] as u32) << 8 | packet[PAYLOAD_START + 7] as u32;
    sum += (packet[PAYLOAD_START + 8] as u32) << 8 | packet[PAYLOAD_START + 9] as u32;
    sum += (packet[PAYLOAD_START + 10] as u32) << 8 | packet[PAYLOAD_START + 11] as u32;
    sum += (packet[PAYLOAD_START + 12] as u32) << 8;

    // We need at most 2 rounds for overflow clearing for a packet less than 64 bytes.
    sum = (sum & 0xffff) + (sum >> 16);
    sum = (sum & 0xffff) + (sum >> 16);

    let sum = !(sum as u16);
    sum.to_be_bytes()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_packet() {
        // Build packet using etherparse
        let builder = PacketBuilder::ipv4([192, 168, 1, 1], [192, 168, 1, 2], 20).udp(10000, 5000);
        let payload = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];

        let mut result = Vec::<u8>::with_capacity(builder.size(payload.len()));
        builder.write(&mut result, &payload).unwrap();

        println!("{:?}", result);
        assert_eq!(
            [result[UDP_START + CHECK], result[UDP_START + CHECK + 1]],
            my_checksum(result.try_into().unwrap())
        );
    }
}
rust udp
1个回答
0
投票

问题是长度同时存在于伪标头和 UDP 标头中,因此需要按照问题评论中的建议添加两次。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.