this repo has no description

read qname

altagos.dev 2d806558 b7753e96

verified
+101 -3
+101 -3
src/root.zig
··· 45 45 } 46 46 47 47 /// Get a range of bytes 48 - pub fn get_range(self: *const BytePacketBuffer, start: usize, len: usize) ReadError![]const u8 { 48 + pub fn getRange(self: *const BytePacketBuffer, start: usize, len: usize) ReadError![]const u8 { 49 49 if (start + len >= comptime self.buf.len) return ReadError.EndOfBuffer; 50 50 return self.buf[start .. start + len]; 51 51 } ··· 55 55 /// The tricky part: Reading domain names, taking labels into consideration. 56 56 /// Will take something like [3]www[6]google[3]com and append 57 57 /// www.google.com to outstr. 58 - pub fn read_qname(self: *BytePacketBuffer, outstr: []u8) ReadError!void { 58 + pub fn readQname(self: *BytePacketBuffer, outstr: []u8) ReadError!void { 59 59 // We might encounter jumps, therefore we need to keep thrack of our position locally 60 60 var pos = self.pos; 61 61 var out_pos: usize = 0; ··· 115 115 116 116 if (!jumped) self.seek(1); 117 117 } 118 + 119 + /// Read a qname 120 + /// 121 + /// The tricky part: Reading domain names, taking labels into consideration. 122 + /// Will take something like [3]www[6]google[3]com and append 123 + /// www.google.com to outstr. 124 + pub fn readQnameAlloc(self: *BytePacketBuffer, alloc: std.mem.Allocator) ![]u8 { 125 + var buffer: std.ArrayList(u8) = .init(alloc); 126 + 127 + // We might encounter jumps, therefore we need to keep thrack of our position locally 128 + var pos = self.pos; 129 + 130 + // track whether or nor we've jumped 131 + var jumped = false; 132 + const max_jumps: usize = 5; 133 + var jumps_performed: usize = 0; 134 + 135 + var delim: ?[]const u8 = null; 136 + while (true) { 137 + if (jumps_performed > max_jumps) return ReadError.JumpLimitExceeded; 138 + 139 + // Each label starts with a length byte 140 + const len = try self.get(pos); 141 + 142 + // If len has the two most signigicant bit set, it represents a jump to some other 143 + // offset in the packet: 144 + if ((len & 0xC0) == 0xC0) { 145 + // Update the buffer position to a point past the current label 146 + if (!jumped) self.seek(2); 147 + 148 + // Read another byte, calculate offset and performe the jump by updating our 149 + // local position variable 150 + const b2 = @as(u16, try self.get(pos + 1)); 151 + const offset = ((@as(u16, len) ^ 0xC0) << 8) | b2; 152 + pos = @as(usize, offset); 153 + 154 + // Indicate that a jump was performed 155 + jumped = true; 156 + jumps_performed += 1; 157 + 158 + continue; 159 + } else { 160 + // Move a single byte forward to move path the length 161 + self.pos += 1; 162 + pos += 1; 163 + 164 + // Domain names are terminated by an empty label of length 0, so if the length 165 + // is zero we're done 166 + if (len == 0) break; 167 + 168 + if (delim) |del| { 169 + try buffer.appendSlice(del); 170 + } 171 + 172 + try buffer.appendSlice(try self.getRange(pos, len)); 173 + 174 + delim = "."; 175 + 176 + pos += len; 177 + } 178 + } 179 + 180 + if (!jumped) self.seek(1); 181 + 182 + return buffer.toOwnedSlice(); 183 + } 118 184 }; 119 185 120 186 test "BytePacketBuffer.read" { ··· 182 248 const outstr = try allocator.alloc(u8, expected.len); 183 249 defer allocator.free(outstr); 184 250 185 - try buf.read_qname(outstr); 251 + try buf.readQname(outstr); 186 252 187 253 try testing.expectEqualStrings(expected, outstr); 188 254 } 255 + 256 + test "BytePacketBuffer.read_qname_alloc google.com" { 257 + const testing = std.testing; 258 + const allocator = testing.allocator; 259 + 260 + const input = [_]u8{ 261 + 0x06, // [6] 262 + 0x67, // g 263 + 0x6f, // o 264 + 0x6f, // o 265 + 0x67, // g 266 + 0x6c, // l 267 + 0x65, // e 268 + 0x03, // [3] 269 + 0x63, // c 270 + 0x6f, // o 271 + 0x6d, // m 272 + 0x00, // [0] 273 + }; 274 + const expected = "google.com"; 275 + 276 + var buf = BytePacketBuffer{}; 277 + for (input, 0..) |char, idx| { 278 + buf.buf[idx] = char; 279 + } 280 + 281 + const outstr = try buf.readQnameAlloc(allocator); 282 + defer allocator.free(outstr); 283 + 284 + try testing.expectEqualStrings(expected, outstr); 285 + } 286 +