mirror of
https://git.robbyzambito.me/zaprus
synced 2026-02-04 00:14:52 +00:00
Calculate IPv4 checksum header
This was causing an issue because virtual networks were dropping packets without this being set
This commit is contained in:
@@ -49,9 +49,45 @@ pub const EthIpUdp = packed struct(u336) { // 42 bytes * 8 bits = 336
|
||||
|
||||
pub fn setPayloadLen(self: *@This(), len: usize) void {
|
||||
self.ip.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8) + (@bitSizeOf(@TypeOf(self.ip)) / 8));
|
||||
|
||||
// Zero the checksum field before calculation
|
||||
self.ip.header_checksum = 0;
|
||||
|
||||
// Serialize IP header to big-endian bytes
|
||||
var ip_bytes: [@bitSizeOf(@TypeOf(self.ip)) / 8]u8 = undefined;
|
||||
var w: Writer = .fixed(&ip_bytes);
|
||||
w.writeStruct(self.ip, .big) catch unreachable;
|
||||
|
||||
// Calculate checksum over serialized bytes
|
||||
self.ip.header_checksum = onesComplement16(&ip_bytes);
|
||||
|
||||
self.udp.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8));
|
||||
}
|
||||
};
|
||||
|
||||
fn onesComplement16(data: []const u8) u16 {
|
||||
var sum: u32 = 0;
|
||||
|
||||
// Process pairs of bytes as 16-bit words
|
||||
var i: usize = 0;
|
||||
while (i + 1 < data.len) : (i += 2) {
|
||||
const word: u16 = (@as(u16, data[i]) << 8) | data[i + 1];
|
||||
sum += word;
|
||||
}
|
||||
|
||||
// Handle odd byte if present
|
||||
if (data.len % 2 == 1) {
|
||||
sum += @as(u32, data[data.len - 1]) << 8;
|
||||
}
|
||||
|
||||
// Fold 32-bit sum to 16 bits
|
||||
while (sum >> 16 != 0) {
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
}
|
||||
|
||||
// Return ones' complement
|
||||
return ~@as(u16, @truncate(sum));
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const Writer = std.Io.Writer;
|
||||
|
||||
Reference in New Issue
Block a user