nx_connect_gate.nx source
↩ module page · 156 lines · 6758 B
1// nx_connect_gate.nx -- proves nx_connect_bounded actually BOUNDS a connect, and that it is a safe
2// drop-in for the 100 raw sys_connect sites.
3//
4// THE NON-VACUITY TOOTH is T2: it dials 192.0.2.1 (RFC5737 TEST-NET-1, guaranteed unroutable, so the
5// SYN is black-holed rather than refused) with a 2s budget. A RAW sys_connect against that address
6// returns after the kernel's SYN-retry ceiling of ~127 SECONDS. If T2 comes back in ~2s the bound is
7// real; if it comes back in ~127s the primitive is decorative. The gate MEASURES the elapsed time and
8// fails on the number -- it does not take the return code's word for it.
9// expect_exit: 0 license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_connect.nx"
12import "nx_fcntl.nx"
13import "nx_clock.nx"
14import "nx_gate_verdict.nx"
15
16const G_PORT_LIVE: i64 = 19781
17const G_PORT_CLOSED: i64 = 19782
18const G_BUDGET_MS: i64 = 2000
19const G_SLACK_MS: i64 = 5000
20const G_NS_PER_MS: i64 = 1000000
21// A real 2s budget cannot come back in under this. Guards against the bail-out-instantly false pass.
22const G_MIN_MS: i64 = 1500
23
24func g_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
25func g_putn(v: i64) -> i64 {
26 let b: *u8 = sys_mmap(32)
27 if v == 0 { b[0] = 48 as u8; sys_write(1, b, 1); return 0 }
28 var x: i64 = v
29 var neg: i64 = 0
30 if x < 0 { neg = 1; x = 0 - x }
31 var n: i64 = 0
32 while x > 0 { b[n] = ((x - (x / 10) * 10) + 48) as u8; n = n + 1; x = x / 10 }
33 let r: *u8 = sys_mmap(48)
34 var i: i64 = 0
35 if neg == 1 { r[0] = 45 as u8; i = 1 }
36 var k: i64 = 0
37 while k < n { r[i + k] = b[n - 1 - k]; k = k + 1 }
38 sys_write(1, r, i + n)
39 return 0
40}
41
42// sockaddr_in: family(2, LE) port(2, BE) addr(4, BE) pad(8)
43func g_sa(a: i64, b: i64, c: i64, d: i64, port: i64) -> *u8 {
44 let s: *u8 = sys_mmap(32)
45 var i: i64 = 0
46 while i < 16 { s[i] = 0 as u8; i = i + 1 }
47 s[0] = 2 as u8
48 s[1] = 0 as u8
49 s[2] = ((port >> 8) & 255) as u8
50 s[3] = (port & 255) as u8
51 s[4] = a as u8
52 s[5] = b as u8
53 s[6] = c as u8
54 s[7] = d as u8
55 return s
56}
57
58func g_tooth(name: *u8, ok: i64) -> i64 {
59 if ok == 1 { g_puts(" [GREEN] " as *u8) } else { g_puts(" [RED] " as *u8) }
60 g_puts(name); g_puts("\n" as *u8)
61 return ok
62}
63
64func main(argc: i64, argv: *i64) -> i64 {
65 g_puts("=== nx_connect_gate -- bounded connect ===\n" as *u8)
66 var pass: i64 = 0
67 var total: i64 = 0
68
69 // ---- T0: the syscall this whole primitive rests on must actually work ----
70 total = total + 1
71 let pfd0: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
72 let fl0: i64 = nx_fcntl(pfd0, NX_F_GETFL, 0)
73 sys_close(pfd0)
74 g_puts(" fcntl(F_GETFL) = " as *u8); g_putn(fl0); g_puts(" (negative = broken wrapper)\n" as *u8)
75 var t0f: i64 = 0
76 if fl0 >= 0 { t0f = 1 }
77 pass = pass + g_tooth("T0 fcntl wrapper reaches the kernel" as *u8, t0f)
78
79 // ---- T1: a LIVE listener must connect, and fast ----
80 total = total + 1
81 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
82 var t1: i64 = 0
83 if lfd >= 0 {
84 let la: *u8 = g_sa(127, 0, 0, 1, G_PORT_LIVE)
85 if sys_bind(lfd, la, 16) == 0 {
86 if sys_listen(lfd, 16) == 0 {
87 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
88 let r: i64 = nx_connect_bounded(cfd, la, 16, G_BUDGET_MS)
89 if r == 0 { t1 = 1 }
90 sys_close(cfd)
91 }
92 }
93 }
94 pass = pass + g_tooth("T1 live local listener connects" as *u8, t1)
95
96 // ---- T2: THE NON-VACUITY TOOTH. Black-holed address must time out at the BUDGET, not ~127s ----
97 total = total + 1
98 let t0: i64 = nx_clock_monotonic_ns()
99 let bfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
100 let ba: *u8 = g_sa(192, 0, 2, 1, 80)
101 let br: i64 = nx_connect_bounded(bfd, ba, 16, G_BUDGET_MS)
102 let t1n: i64 = nx_clock_monotonic_ns()
103 sys_close(bfd)
104 var el: i64 = 0 - 1
105 if t0 > 0 { if t1n > 0 { el = (t1n - t0) / G_NS_PER_MS } }
106 g_puts(" black-hole dial returned rc=" as *u8); g_putn(br)
107 g_puts(" after " as *u8); g_putn(el); g_puts(" ms (raw connect would be ~127000)\n" as *u8)
108 var t2: i64 = 0
109 // MUST land in a WINDOW. el==0 means the primitive never dialled (the first version of
110 // this gate passed that way); el>=127000 means the bound did nothing.
111 if br != 0 { if el >= G_MIN_MS { if el < G_SLACK_MS { t2 = 1 } } }
112 pass = pass + g_tooth("T2 black-holed connect BOUNDED (non-vacuity)" as *u8, t2)
113
114 // ---- T3: a refusal must come back fast and NOT burn the whole budget ----
115 total = total + 1
116 let t3a: i64 = nx_clock_monotonic_ns()
117 let rfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
118 let ra: *u8 = g_sa(127, 0, 0, 1, G_PORT_CLOSED)
119 let rr: i64 = nx_connect_bounded(rfd, ra, 16, G_BUDGET_MS)
120 let t3b: i64 = nx_clock_monotonic_ns()
121 sys_close(rfd)
122 var rel: i64 = 0 - 1
123 if t3a > 0 { if t3b > 0 { rel = (t3b - t3a) / G_NS_PER_MS } }
124 g_puts(" refused dial returned rc=" as *u8); g_putn(rr)
125 g_puts(" after " as *u8); g_putn(rel); g_puts(" ms\n" as *u8)
126 var t3: i64 = 0
127 if rr != 0 { if rel >= 0 { if rel < G_BUDGET_MS { t3 = 1 } } }
128 pass = pass + g_tooth("T3 refusal distinguished from timeout" as *u8, t3)
129
130 // ---- T4: the fd's flags must come back EXACTLY as handed in ----
131 // If O_NONBLOCK leaked, every later read on a peer socket would return EAGAIN and the caller would
132 // silently read nothing. This is what makes the primitive a drop-in rather than a landmine.
133 total = total + 1
134 let ffd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
135 let before: i64 = nx_fcntl(ffd, NX_F_GETFL, 0)
136 nx_connect_bounded(ffd, ba, 16, 200)
137 let after: i64 = nx_fcntl(ffd, NX_F_GETFL, 0)
138 sys_close(ffd)
139 g_puts(" flags before=" as *u8); g_putn(before)
140 g_puts(" after=" as *u8); g_putn(after); g_puts("\n" as *u8)
141 var t4: i64 = 0
142 if before == after { t4 = 1 }
143 pass = pass + g_tooth("T4 caller's fd flags restored (no O_NONBLOCK leak)" as *u8, t4)
144
145 sys_close(lfd)
146 g_puts("teeth " as *u8); g_putn(pass); g_puts("/" as *u8); g_putn(total); g_puts("\n" as *u8)
147 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
148 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
149 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
150 let ctr__dry: *i64 = gv_ctr()
151 ctr__dry[0] = pass
152 ctr__dry[1] = total
153 let rc__dry: i64 = gv_verdict("CONNECT-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
154 sys_exit(rc__dry)
155 return rc__dry
156}