nx_ipfilter.nx source
↩ module page · 42 lines · 2581 B
1// nx_ipfilter.nx -- SOVEREIGN IP blocklist (BitTorrent ip-filter): reject known-bad / anti-P2P-monitor IP
2// ranges before we connect to them (worker) or accept them (seeder). Real privacy while WAN-seeding. Binary
3// blocklist format (ipfilter.bin): 8 bytes/entry = [start u32 LE][end u32 LE], inclusive IPv4 range. Linear
4// scan per check -- home-scale connection rate makes even 100k ranges <1ms + it's done once per peer. Load
5// ONCE (parent), children inherit the array via fork COW. license_tier: ORIGINAL depends: nx_syscalls
6import "nx_syscalls.nx"
7
8// dotted octets -> u32 host order
9func ipf_ip(a: i64, b: i64, c: i64, d: i64) -> i64 { return ((a&0xff)<<24)|((b&0xff)<<16)|((c&0xff)<<8)|(d&0xff) }
10// unpack a LE u32 from buf at off
11func ipf_u32le(buf: *u8, off: i64) -> i64 { return (buf[off] as i64)|((buf[off+1] as i64)<<8)|((buf[off+2] as i64)<<16)|((buf[off+3] as i64)<<24) }
12// pack a LE u32 into buf at off
13func ipf_put_u32le(buf: *u8, off: i64, v: i64) -> i64 { buf[off]=(v&0xff) as u8; buf[off+1]=((v>>8)&0xff) as u8; buf[off+2]=((v>>16)&0xff) as u8; buf[off+3]=((v>>24)&0xff) as u8; return off+4 }
14
15// Load ipfilter.bin into `arr` (i64 array, 2 slots/entry: arr[2i]=start, arr[2i+1]=end). Returns entry count
16// (0 if absent/empty -> filter is a safe no-op, never blocks). maxpairs caps the load.
17func ipf_load(path: *u8, arr: *i64, maxpairs: i64) -> i64 {
18 let fd: i64 = sys_openat_rd(path); if fd<0 { return 0 }
19 let cap: i64 = maxpairs*8 + 16
20 let buf: *u8 = sys_mmap(cap)
21 var tot: i64=0; var r: i64=1
22 while r>0 { if tot>=cap { r=0 } else { r=sys_read(fd, (((buf as i64)+tot) as *u8), cap-tot); if r>0 { tot=tot+r } } }
23 sys_close(fd)
24 let n: i64 = tot/8; var i: i64=0
25 while i<n { if i>=maxpairs { i=n } else { arr[2*i]=ipf_u32le(buf, 8*i); arr[2*i+1]=ipf_u32le(buf, 8*i+4); i=i+1 } }
26 if n>maxpairs { return maxpairs }
27 return n
28}
29// 1 if ip (u32 host order) falls in any blocked range, else 0. Unsigned compare via masking to 32 bits.
30func ipf_blocked(arr: *i64, count: i64, ip: i64) -> i64 {
31 let x: i64 = ip & 0xFFFFFFFF
32 var i: i64=0
33 while i<count { let s: i64=arr[2*i]&0xFFFFFFFF; let e: i64=arr[2*i+1]&0xFFFFFFFF; if x>=s { if x<=e { return 1 } } i=i+1 }
34 return 0
35}
36// convenience: load + check in one call (for callers that don't cache). path default handled by caller.
37func ipf_blocked_ip(path: *u8, ip: i64, maxpairs: i64) -> i64 {
38 let arr: *i64 = sys_mmap(maxpairs*16 + 64) as *i64
39 let c: i64 = ipf_load(path, arr, maxpairs)
40 if c<=0 { return 0 }
41 return ipf_blocked(arr, c, ip)
42}