diff rvinterf/libg23/fmtdispatch.c @ 0:e7502631a0f9

initial import from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 11 Jun 2016 00:13:35 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rvinterf/libg23/fmtdispatch.c	Sat Jun 11 00:13:35 2016 +0000
@@ -0,0 +1,144 @@
+/*
+ * This libg23 module exports the format_g23_packet() function, which
+ * validates the packet, then dispatches it to format_g23_trace(),
+ * format_g23_sysprim() or format_g23_psprim() as appropriate, or
+ * prints it in raw hex if malformed.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+
+static int
+basic_checks(rxpkt, rxpkt_len)
+	u_char *rxpkt;
+{
+	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;
+{
+	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_unknown_bin(rxpkt, rxpkt_len, outbuf)
+	u_char *rxpkt;
+	char *outbuf;
+{
+	int i;
+	char *dp;
+
+	dp = outbuf;
+	strcpy(dp, "GPF UNK:");
+	dp += 8;
+	for (i = 1; i < rxpkt_len; i++) {
+		sprintf(dp, " %02X", rxpkt[i]);
+		dp += 3;
+	}
+	*dp = '\0';
+}
+
+static void
+print_old_ascii(rxpkt, rxpkt_len, outbuf)
+	u_char *rxpkt;
+	char *outbuf;
+{
+	char *dp;
+	int txtlen = rxpkt_len - 1;
+
+	dp = outbuf;
+	strcpy(dp, "GPF ASC: ");
+	dp += 9;
+	bcopy(rxpkt + 1, dp, txtlen);
+	dp += txtlen;
+	*dp = '\0';
+}
+
+static int
+is_old_ascii(rxpkt, rxpkt_len)
+	u_char *rxpkt;
+{
+	int i, c;
+
+	for (i = 1; i < rxpkt_len; i++) {
+		c = rxpkt[i];
+		if (c < ' ' || c > '~')
+			return(0);
+	}
+	return(1);
+}
+
+static void
+print_malformed(rxpkt, rxpkt_len, outbuf)
+	u_char *rxpkt;
+	char *outbuf;
+{
+	if (is_old_ascii(rxpkt, rxpkt_len))
+		print_old_ascii(rxpkt, rxpkt_len, outbuf);
+	else
+		print_unknown_bin(rxpkt, rxpkt_len, outbuf);
+}
+
+void
+format_g23_packet(rxpkt, rxpkt_len, outbuf)
+	u_char *rxpkt;
+	char *outbuf;
+{
+	if (!basic_checks(rxpkt, rxpkt_len)) {
+		print_malformed(rxpkt, rxpkt_len, outbuf);
+		return;
+	}
+	/* dispatch by type */
+	switch (rxpkt[1] & 0x30) {
+	case 0x10:
+		/* PS primitive */
+		if (psprim_extra_checks(rxpkt, rxpkt_len))
+			format_g23_psprim(rxpkt, rxpkt_len, outbuf);
+		else
+			print_malformed(rxpkt, rxpkt_len, outbuf);
+		return;
+	case 0x20:
+		/* trace */
+		format_g23_trace(rxpkt, rxpkt_len, outbuf);
+		return;
+	case 0x30:
+		/* system primitive */
+		format_g23_sysprim(rxpkt, rxpkt_len, outbuf);
+		return;
+	default:
+		print_malformed(rxpkt, rxpkt_len, outbuf);
+	}
+}