nx_printer_query.nx source
↩ module page · 222 lines · 9990 B
1// nx_printer_query.nx -- LIVE driver: query a real IPP printer and print the honest truth.
2// Composes R0 codec + R1 health + R2 transport against the operator's Brother at 192.168.8.127:631.
3// READ-ONLY (Get-Printer-Attributes) -> never-brick. license_tier: ORIGINAL
4
5import "nx_syscalls.nx"
6import "nx_ipp_codec.nx"
7import "nx_printer_health.nx"
8import "nx_ipp_transport.nx"
9import "nx_printer_security.nx"
10import "nx_printer_waste.nx"
11import "nx_printer_conform.nx"
12const K_MAGIC_131072: i64 = 131072
13
14func p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
15func pn(v: i64) -> i64 {
16 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
17 var m: i64 = v
18 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
19 let t: *u8 = sys_mmap(24); var k: i64 = 0
20 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
21 let b: *u8 = sys_mmap(24); var i: i64 = 0
22 while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
23 sys_write(1, b, k); return 0
24}
25func phex16(v: i64) -> i64 {
26 let hx: *u8 = "0123456789abcdef"
27 var sh: i64 = 12
28 while sh >= 0 { let nib: i64 = (v >> sh) & 0xf; sys_write(1, ((hx as i64) + nib) as *u8, 1); sh = sh - 4 }
29 return 0
30}
31
32func state_label(s: i64) -> *u8 {
33 if s == NX_IPP_PSTATE_IDLE { return "idle" as *u8 }
34 if s == NX_IPP_PSTATE_PROCESSING { return "processing" as *u8 }
35 if s == NX_IPP_PSTATE_STOPPED { return "STOPPED" as *u8 }
36 return "unknown" as *u8
37}
38func sev_label(s: i64) -> *u8 {
39 if s == NX_SEV_NONE { return "none" as *u8 }
40 if s == NX_SEV_REPORT { return "report" as *u8 }
41 if s == NX_SEV_WARNING { return "WARNING" as *u8 }
42 if s == NX_SEV_ERROR { return "ERROR" as *u8 }
43 return "?" as *u8
44}
45func verdict_label(v: i64) -> *u8 {
46 if v == NX_PR_CAN_PRINT { return "READY -- can print now" as *u8 }
47 if v == NX_PR_DEGRADED { return "DEGRADED -- will print, but needs attention" as *u8 }
48 if v == NX_PR_BLOCKED { return "BLOCKED -- will NOT print until a human acts" as *u8 }
49 return "UNKNOWN -- could not determine (NOT a silent 'ready')" as *u8
50}
51func psec_label(v: i64) -> *u8 {
52 if v == NX_PSEC_SECURE { return "SECURE" as *u8 }
53 if v == NX_PSEC_WEAK { return "WEAK -- downgrade/partial protection" as *u8 }
54 if v == NX_PSEC_EXPOSED { return "EXPOSED -- wide open" as *u8 }
55 return "UNKNOWN -- printer reported no security attributes" as *u8
56}
57func yn(flags: i64, bit: i64) -> i64 {
58 if (flags & bit) != 0 { p("YES") } else { p("no") }
59 return 0
60}
61func sup_label(v: i64) -> *u8 {
62 if v == NX_SUP_OK { return "OK" as *u8 }
63 if v == NX_SUP_LOW { return "LOW" as *u8 }
64 if v == NX_SUP_EMPTY { return "EMPTY" as *u8 }
65 return "UNKNOWN" as *u8
66}
67func dup_label(v: i64) -> *u8 {
68 if v == NX_DUP_OK { return "duplex default -- not wasting paper" as *u8 }
69 if v == NX_DUP_WASTE { return "WASTE -- duplex supported but defaults to ONE-SIDED" as *u8 }
70 if v == NX_DUP_UNSUPPORTED { return "no duplex hardware" as *u8 }
71 return "unknown (sides not reported)" as *u8
72}
73
74// find a string-valued attribute and print it, or "(not reported)"
75func print_attr_str(body: *u8, n: i64, name: *u8) -> i64 {
76 let sc: *i64 = sys_mmap(64) as *i64
77 let p_tag: *i64 = sc
78 let p_voff: *i64 = ((sc as i64) + 8) as *i64
79 let p_vlen: *i64 = ((sc as i64) + 16) as *i64
80 let r: i64 = nx_ipp_find(body, n, name, p_tag, p_voff, p_vlen)
81 if r != NX_IPP_OK { p("(not reported)"); return 0 }
82 sys_write(1, ((body as i64) + p_voff[0]) as *u8, p_vlen[0])
83 return 0
84}
85
86// walk and print every printer-state-reasons value with its severity (the bit Brother hides)
87func print_reasons(body: *u8, n: i64, pstate: i64) -> i64 {
88 if n < 8 { return 0 }
89 var off: i64 = 8
90 var in_reasons: i64 = 0
91 var keep: i64 = 1
92 while keep == 1 {
93 if off >= n { keep = 0 }
94 else {
95 let tag: i64 = body[off] as i64
96 if tag == NX_IPP_TAG_END { keep = 0 }
97 else {
98 if tag <= 0x0f { off = off + 1; in_reasons = 0 }
99 else {
100 if (off + 3) > n { keep = 0 }
101 else {
102 let nlen: i64 = nx_ipp_get_u16(body, off + 1)
103 let name_off: i64 = off + 3
104 if (name_off + nlen + 2) > n { keep = 0 }
105 else {
106 let vlen_off: i64 = name_off + nlen
107 let vlen: i64 = nx_ipp_get_u16(body, vlen_off)
108 let val_off: i64 = vlen_off + 2
109 if (val_off + vlen) > n { keep = 0 }
110 else {
111 if nlen > 0 {
112 if nx_ipp_name_eq(body, name_off, "printer-state-reasons", 21) == 1 { in_reasons = 1 }
113 else { in_reasons = 0 }
114 }
115 if in_reasons == 1 {
116 let sev: i64 = nx_ph_reason_severity(body, val_off, vlen, pstate)
117 p(" - "); sys_write(1, ((body as i64) + val_off) as *u8, vlen)
118 p(" ["); p(sev_label(sev)); p("]\n")
119 }
120 off = val_off + vlen
121 }
122 }
123 }
124 }
125 }
126 }
127 }
128 return 0
129}
130
131func main() -> i64 {
132 p("=== NISHI SOVEREIGN PRINTER STATUS (IPP / any-vendor, READ-ONLY) ===\n")
133 let a: i64 = 192
134 let b: i64 = 168
135 let c: i64 = 8
136 let d: i64 = 127
137 p("target ipp://"); pn(a); p("."); pn(b); p("."); pn(c); p("."); pn(d); p(":631\n")
138
139 let resp: *u8 = sys_mmap(K_MAGIC_131072)
140 let body: *u8 = sys_mmap(K_MAGIC_131072)
141 let out2: *i64 = sys_mmap(16) as *i64
142
143 var path: *u8 = "/ipp/print"
144 var v: i64 = nx_ipt_query_printer(a, b, c, d, 631, path, resp, K_MAGIC_131072, body, K_MAGIC_131072, 5, out2)
145 var ok: i64 = 0
146 if v == NX_IPT_OK { if out2[0] == 200 { ok = 1 } }
147 if ok == 0 {
148 p(" (/ipp/print -> "); p(nx_ipt_verdict_name(v)); p(" http="); pn(out2[0]); p("; retry /ipp/port1)\n")
149 path = "/ipp/port1"
150 v = nx_ipt_query_printer(a, b, c, d, 631, path, resp, K_MAGIC_131072, body, K_MAGIC_131072, 5, out2)
151 if v == NX_IPT_OK { if out2[0] == 200 { ok = 1 } }
152 }
153
154 p("path="); p(path); p(" transport="); p(nx_ipt_verdict_name(v))
155 p(" http_status="); pn(out2[0]); p(" ipp_body_bytes="); pn(out2[1]); p("\n")
156 if v != NX_IPT_OK {
157 p("RESULT: no clean IPP response -- reported, not silently swallowed.\n")
158 sys_exit(1); return 1
159 }
160
161 let n: i64 = out2[1]
162 p("ipp_status=0x"); phex16(nx_ipp_status(body)); p("\n")
163 p("printer : "); print_attr_str(body, n, "printer-make-and-model"); p("\n")
164 p("location : "); print_attr_str(body, n, "printer-location"); p("\n")
165
166 let sc: *i64 = sys_mmap(64) as *i64
167 let o_state: *i64 = sys_mmap(16) as *i64
168 let o_sev: *i64 = sys_mmap(16) as *i64
169 let o_cnt: *i64 = sys_mmap(16) as *i64
170 let o_acc: *i64 = sys_mmap(16) as *i64
171 let verdict: i64 = nx_printer_diagnose(body, n, sc, o_state, o_sev, o_cnt, o_acc)
172
173 p("state : "); p(state_label(o_state[0])); p(" ("); pn(o_state[0]); p(")\n")
174 p("accepting: "); pn(o_acc[0]); p(" (1=yes 0=no -1=not reported)\n")
175 p("reasons : "); pn(o_cnt[0]); p("\n")
176 print_reasons(body, n, o_state[0])
177 p("\n>>> CAN IT PRINT RIGHT NOW? "); p(verdict_label(verdict)); p("\n")
178
179 // --- SECURITY POSTURE (the #1 measurable exceed axis) ---
180 let secfl: *i64 = sys_mmap(16) as *i64
181 let secv: i64 = nx_printer_security(body, n, sc, secfl)
182 p("\n--- SECURITY ---\n")
183 p("posture : "); p(psec_label(secv)); p("\n")
184 p(" cleartext(no TLS): "); yn(secfl[0], PSEC_F_CLEARTEXT); p("\n")
185 p(" no authentication: "); yn(secfl[0], PSEC_F_NOAUTH); p("\n")
186 p(" TLS available : "); yn(secfl[0], PSEC_F_TLS); p("\n")
187 p(" auth available : "); yn(secfl[0], PSEC_F_AUTH); p("\n")
188 if secv == NX_PSEC_EXPOSED {
189 p(" ! WIDE OPEN: anyone on this network can READ your jobs AND submit jobs.\n")
190 p(" ! same exposure class as CUPS CVE-2024-47176 (cleartext :631 + no auth).\n")
191 }
192
193 // --- SUPPLIES & WASTE (the "wasteful as shit" axis) ---
194 let w_cnt: *i64 = sys_mmap(16) as *i64
195 let w_pct: *i64 = sys_mmap(16) as *i64
196 let w_dup: *i64 = sys_mmap(16) as *i64
197 let w_sc: *i64 = sys_mmap(64) as *i64
198 let supv: i64 = nx_printer_waste(body, n, w_sc, w_cnt, w_pct, w_dup)
199 p("\n--- SUPPLIES & WASTE ---\n")
200 p("supplies : "); pn(w_cnt[0]); p("\n")
201 p("lowest level : ")
202 if w_pct[0] < 0 { p("unknown") } else { pn(w_pct[0]); p("%") }
203 p(" status="); p(sup_label(supv)); p("\n")
204 p("paper (duplex) : "); p(dup_label(w_dup[0])); p("\n")
205 if w_dup[0] == NX_DUP_WASTE {
206 p(" -> fix: submit jobs with sides=two-sided-long-edge to halve paper use.\n")
207 }
208
209 // --- CONFORMANCE (capability gaps the vendor UI hides) ---
210 let conf_gaps: i64 = nx_conf_gaps(body, n, sc)
211 p("\n--- CONFORMANCE ---\n")
212 if conf_gaps < 0 { p("gaps : UNKNOWN (malformed)\n") }
213 else {
214 p("actionable gaps : "); pn(nx_conf_gap_count(conf_gaps)); p("\n")
215 if (conf_gaps & NX_CONF_GAP_IPP_OLD) != 0 { p(" - only old IPP (no 2.0): missing IPP Everywhere features\n") }
216 if (conf_gaps & NX_CONF_GAP_NO_PDF) != 0 { p(" - no PDF: the client must rasterize (URF/PWG)\n") }
217 if (conf_gaps & NX_CONF_GAP_DUPLEX_WASTE) != 0 { p(" - duplex-capable but defaults one-sided: silent paper waste\n") }
218 if (conf_gaps & NX_CONF_GAP_NO_COLOR) != 0 { p(" - monochrome (color-supported = false)\n") }
219 if conf_gaps == 0 { p(" (none -- modern, well-configured)\n") }
220 }
221 sys_exit(0); return 0
222}