FreeCalypso > hg > freecalypso-tools
diff rvinterf/libprint/gpf_tst.c @ 939:4d2e6a2dd1a1
libprint: implement libg23 replacement
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 24 May 2023 06:29:13 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rvinterf/libprint/gpf_tst.c Wed May 24 06:29:13 2023 +0000 @@ -0,0 +1,283 @@ +/* + * This libprint module (one public function plus many internal subfunctions) + * implements printing/formatting of GPF TST interface packets, which can be + * traces, sysprims, protocol stack primitives or unrecognized packet format. + */ + +#include <sys/types.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +static int +basic_checks(rxpkt, rxpkt_len) + u_char *rxpkt; + unsigned rxpkt_len; +{ + int i, c; + + if (rxpkt_len < 17) + return(0); + /* check version bits in the header byte */ + if ((rxpkt[1] & 0xC0) != 0x80) + return(0); + /* check the length */ + c = rxpkt[2] | rxpkt[3] << 8; + if (c + 4 != rxpkt_len) + return(0); + /* ensure that the "from" and "to" are printable ASCII */ + for (i = 8; i < 16; i++) { + c = rxpkt[i]; + if (c < ' ' || c > '~') + return(0); + } + /* basic checks pass */ + return(1); +} + +static int +psprim_extra_checks(rxpkt, rxpkt_len) + u_char *rxpkt; + unsigned rxpkt_len; +{ + int i, c; + + if (rxpkt_len < 24) + return(0); + /* "original rcvr" field needs to be printable ASCII */ + for (i = 16; i < 20; i++) { + c = rxpkt[i]; + if (c < ' ' || c > '~') + return(0); + } + /* checks pass */ + return(1); +} + +static void +print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + char headline[80]; + + sprintf(headline, "%sGPF unrecognized packet format", extra_prefix); + outfunc_head(headline); + packet_hex_dump(rxpkt, rxpkt_len, outfunc_cont); +} + +static void +print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + char headline[80]; + + sprintf(headline, "%sGPF packet, failed malloc in formatting", + extra_prefix); + outfunc_head(headline); + packet_hex_dump(rxpkt, rxpkt_len, outfunc_cont); +} + +static int +entity_name_well_formed(p) + char *p; +{ + int i, len; + + if (!isupper(p[0])) + return(0); + for (i = 0; i < 4; i++) + if (!isalnum(p[i])) + break; + len = i; + for (; i < 4; i++) + if (p[i] != ' ') + return(0); + return(len); +} + +static void +print_entity_name(raw, outp) + char *raw, **outp; +{ + int len; + + len = entity_name_well_formed(raw); + if (len) { + sprintf(*outp, "%.*s", len, raw); + *outp += len; + } else { + sprintf(*outp, "\"%.4s\"", raw); + *outp += 6; + } +} + +static void +print_common_hdr(rxpkt, outp, typestr, extra_prefix) + u_char *rxpkt; + char **outp, *typestr, *extra_prefix; +{ + sprintf(*outp, "%sGPF %s id=%02X ts=%02X%02X%02X%02X ", extra_prefix, + typestr, rxpkt[1], rxpkt[7], rxpkt[6], rxpkt[5], rxpkt[4]); + *outp = index(*outp, '\0'); + print_entity_name(rxpkt + 8, outp); + *(*outp)++ = '-'; + *(*outp)++ = '>'; + print_entity_name(rxpkt + 12, outp); + *(*outp)++ = ' '; +} + +static void +format_text(rxpkt, rxpkt_len, start_off, outp) + u_char *rxpkt; + unsigned rxpkt_len, start_off; + char *outp; +{ + *outp++ = '\"'; + safe_print_trace(rxpkt + start_off, rxpkt_len - start_off, outp); + outp = index(outp, '\0'); + *outp++ = '\"'; + *outp = '\0'; +} + +static void +format_compressed_trace(rxpkt, rxpkt_len, start_off, outp) + u_char *rxpkt; + unsigned rxpkt_len, start_off; + char *outp; +{ + int i; + + i = start_off + 1; + sprintf(outp, "%d", rxpkt[i+1] << 8 | rxpkt[i]); + outp = index(outp, '\0'); + i += 4; + for (; i < rxpkt_len; i++) { + sprintf(outp, " %02X", rxpkt[i]); + outp += 3; + } + *outp = '\0'; +} + +static void +format_trace(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + char *outbuf, *outp; + int i; + + outbuf = malloc(rxpkt_len * 4 + strlen(extra_prefix) + 1); + if (!outbuf) { + print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + return; + } + outp = outbuf; + print_common_hdr(rxpkt, &outp, "trace", extra_prefix); + i = 16; + if (rxpkt[i] < 0x20) { + sprintf(outp, "tc=%02X ", rxpkt[i]); + outp += 6; + i++; + } + if (rxpkt_len - i >= 5 && rxpkt[i] == '%' && + !rxpkt[i+3] && !rxpkt[i+4]) + format_compressed_trace(rxpkt, rxpkt_len, i, outp); + else + format_text(rxpkt, rxpkt_len, i, outp); + outfunc_head(outbuf); + free(outbuf); +} + +static void +format_sysprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + char *outbuf, *outp; + + outbuf = malloc(rxpkt_len * 4 + strlen(extra_prefix) + 1); + if (!outbuf) { + print_malloc_fail(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + return; + } + outp = outbuf; + print_common_hdr(rxpkt, &outp, "sysprim", extra_prefix); + format_text(rxpkt, rxpkt_len, 16, outp); + outfunc_head(outbuf); + free(outbuf); +} + +static void +format_psprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + char headline[80]; + char *outp = headline; + + print_common_hdr(rxpkt, &outp, "PSprim", extra_prefix); + /* original destination */ + *outp++ = '('; + print_entity_name(rxpkt + 16, &outp); + *outp++ = ')'; + /* opcode and data length */ + sprintf(outp, " %02X%02X%02X%02X len=%u", + rxpkt[23], rxpkt[22], rxpkt[21], rxpkt[20], rxpkt_len - 24); + outfunc_head(headline); + packet_hex_dump(rxpkt + 24, rxpkt_len - 24, outfunc_cont); +} + +void +format_gpf_packet(rxpkt, rxpkt_len, extra_prefix, outfunc_head, outfunc_cont) + u_char *rxpkt; + unsigned rxpkt_len; + char *extra_prefix; + void (*outfunc_head)(), (*outfunc_cont)(); +{ + if (!basic_checks(rxpkt, rxpkt_len)) { + print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + return; + } + /* dispatch by type */ + switch (rxpkt[1] & 0x30) { + case 0x10: + /* PS primitive */ + if (psprim_extra_checks(rxpkt, rxpkt_len)) + format_psprim(rxpkt, rxpkt_len, extra_prefix, + outfunc_head, outfunc_cont); + else + print_malformed(rxpkt, rxpkt_len, extra_prefix, + outfunc_head, outfunc_cont); + return; + case 0x20: + /* trace */ + format_trace(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + return; + case 0x30: + /* system primitive */ + format_sysprim(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + return; + default: + print_malformed(rxpkt, rxpkt_len, extra_prefix, outfunc_head, + outfunc_cont); + } +}