aboutsummaryrefslogtreecommitdiff
path: root/src/RawSocket.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/RawSocket.zig')
-rw-r--r--src/RawSocket.zig48
1 files changed, 42 insertions, 6 deletions
diff --git a/src/RawSocket.zig b/src/RawSocket.zig
index 71b4e1c..9561dcf 100644
--- a/src/RawSocket.zig
+++ b/src/RawSocket.zig
@@ -1,3 +1,19 @@
+// Copyright 2026 Robby Zambito
+//
+// This file is part of zaprus.
+//
+// Zaprus is free software: you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your option) any later
+// version.
+//
+// Zaprus is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// Zaprus. If not, see <https://www.gnu.org/licenses/>.
+
const RawSocket = @This();
const is_debug = builtin.mode == .Debug;
@@ -16,7 +32,12 @@ const Ifconf = extern struct {
},
};
-pub fn init() !RawSocket {
+pub fn init() error{
+ SocketError,
+ NicError,
+ NoInterfaceFound,
+ BindError,
+}!RawSocket {
const socket: i32 = std.math.cast(i32, std.os.linux.socket(std.os.linux.AF.PACKET, std.os.linux.SOCK.RAW, 0)) orelse return error.SocketError;
if (socket < 0) return error.SocketError;
@@ -117,7 +138,7 @@ pub fn receive(self: RawSocket, buf: []u8) ![]u8 {
return buf[0..len];
}
-pub fn attachSaprusPortFilter(self: RawSocket, port: u16) !void {
+pub fn attachSaprusPortFilter(self: RawSocket, incoming_src_port: ?u16, incoming_dest_port: u16) !void {
const BPF = std.os.linux.BPF;
// BPF instruction structure for classic BPF
const SockFilter = extern struct {
@@ -133,11 +154,26 @@ pub fn attachSaprusPortFilter(self: RawSocket, port: u16) !void {
};
// Build the filter program
- const filter = [_]SockFilter{
+ const filter = if (incoming_src_port) |inc_src| &[_]SockFilter{
// Load 2 bytes at offset 46 (absolute)
.{ .code = BPF.LD | BPF.H | BPF.ABS, .jt = 0, .jf = 0, .k = 46 },
+ // Jump if equal to port (skip 1 if true, skip 0 if false)
+ .{ .code = BPF.JMP | BPF.JEQ | BPF.K, .jt = 1, .jf = 0, .k = @as(u32, inc_src) },
+ // Return 0x0 (fail)
+ .{ .code = BPF.RET | BPF.K, .jt = 0, .jf = 0, .k = 0x0 },
+ // Load 2 bytes at offset 48 (absolute)
+ .{ .code = BPF.LD | BPF.H | BPF.ABS, .jt = 0, .jf = 0, .k = 48 },
+ // Jump if equal to port (skip 0 if true, skip 1 if false)
+ .{ .code = BPF.JMP | BPF.JEQ | BPF.K, .jt = 0, .jf = 1, .k = @as(u32, incoming_dest_port) },
+ // Return 0xffff (pass)
+ .{ .code = BPF.RET | BPF.K, .jt = 0, .jf = 0, .k = 0xffff },
+ // Return 0x0 (fail)
+ .{ .code = BPF.RET | BPF.K, .jt = 0, .jf = 0, .k = 0x0 },
+ } else &[_]SockFilter{
+ // Load 2 bytes at offset 48 (absolute)
+ .{ .code = BPF.LD | BPF.H | BPF.ABS, .jt = 0, .jf = 0, .k = 48 },
// Jump if equal to port (skip 0 if true, skip 1 if false)
- .{ .code = BPF.JMP | BPF.JEQ | BPF.K, .jt = 0, .jf = 1, .k = @as(u32, port) },
+ .{ .code = BPF.JMP | BPF.JEQ | BPF.K, .jt = 0, .jf = 1, .k = @as(u32, incoming_dest_port) },
// Return 0xffff (pass)
.{ .code = BPF.RET | BPF.K, .jt = 0, .jf = 0, .k = 0xffff },
// Return 0x0 (fail)
@@ -145,8 +181,8 @@ pub fn attachSaprusPortFilter(self: RawSocket, port: u16) !void {
};
const fprog = SockFprog{
- .len = filter.len,
- .filter = &filter,
+ .len = @intCast(filter.len),
+ .filter = filter.ptr,
};
// Attach filter to socket using setsockopt