code wiki / (root) / nx_printer_query.nx

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}