changeset 12:7543aa173634

proto-smsc-sendmt program written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 27 Aug 2023 16:36:28 -0800
parents 44148d13283c
children 2c35aad69fea
files .hgignore smsc-sendmt/Makefile smsc-sendmt/hexdecode.c smsc-sendmt/imsi_entry.c smsc-sendmt/main.c smsc-sendmt/read_pdu.c smsc-sendmt/smsc_addr.c
diffstat 7 files changed, 247 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Aug 27 13:39:51 2023 -0800
+++ b/.hgignore	Sun Aug 27 16:36:28 2023 -0800
@@ -5,3 +5,5 @@
 ^euse-demo/osmo-euse-demo$
 
 ^smsc-daemon/proto-smsc-daemon$
+
+^smsc-sendmt/proto-smsc-sendmt$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsc-sendmt/Makefile	Sun Aug 27 16:36:28 2023 -0800
@@ -0,0 +1,13 @@
+CC=	gcc
+CFLAGS=	-O2 -pthread -I/opt/osmocni2/include -I/usr/include/samba-4.0
+PROG=	proto-smsc-sendmt
+OBJS=	hexdecode.o imsi_entry.o main.o read_pdu.o smsc_addr.o
+OSMOLIB=-L/opt/osmocni2/lib -Wl,-rpath,/opt/osmocni2/lib -losmogsm -losmocore
+
+all:	${PROG}
+
+${PROG}:	${OBJS}
+	${CC} -o $@ ${OBJS} ${OSMOLIB}
+
+clean:
+	rm -f *.o ${PROG}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsc-sendmt/hexdecode.c	Sun Aug 27 16:36:28 2023 -0800
@@ -0,0 +1,34 @@
+/*
+ * This library module implements decoding of long hex strings,
+ * such as SMS PDUs.
+ */
+
+#include <ctype.h>
+#include <stdint.h>
+
+int decode_hex_line(const char *inbuf, uint8_t *outbuf, unsigned outmax)
+{
+	const char *inp = inbuf;
+	uint8_t *outp = outbuf;
+	unsigned outcnt = 0;
+	int c, d[2], i;
+
+	while (*inp) {
+		if (!isxdigit(inp[0]) || !isxdigit(inp[1]))
+			return(-1);
+		if (outcnt >= outmax)
+			break;
+		for (i = 0; i < 2; i++) {
+			c = *inp++;
+			if (isdigit(c))
+				d[i] = c - '0';
+			else if (isupper(c))
+				d[i] = c - 'A' + 10;
+			else
+				d[i] = c - 'a' + 10;
+		}
+		*outp++ = (d[0] << 4) | d[1];
+		outcnt++;
+	}
+	return outcnt;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsc-sendmt/imsi_entry.c	Sun Aug 27 16:36:28 2023 -0800
@@ -0,0 +1,53 @@
+/*
+ * The library function implemented in this module supports IMSI entry
+ * at UI level, either in the standard form (long string of digits)
+ * or in the shorthand notation introduced in fc-sim-tools.
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+int grok_imsi_user_arg(const char *arg, char *dest)
+{
+	const char *cp;
+	char *dp;
+	int n, tail_len, remain;
+
+	if (!isdigit(*arg))
+		return(-1);
+	cp = arg;
+	dp = dest;
+	n = 0;
+	while (isdigit(*cp)) {
+		if (n >= 15)
+			return(-1);
+		*dp++ = *cp++;
+		n++;
+	}
+	if (!*cp) {
+		if (n < 6)
+			return(-1);
+		*dp = '\0';
+		return(0);
+	}
+	if (*cp != '-')
+		return(-1);
+	cp++;
+	tail_len = strlen(cp);
+	if (!tail_len)
+		return(-1);
+	remain = 15 - n;
+	if (remain < tail_len + 1)
+		return(-1);
+	while (remain > tail_len) {
+		*dp++ = '0';
+		remain--;
+	}
+	while (*cp) {
+		if (!isdigit(*cp))
+			return(-1);
+		*dp++ = *cp++;
+	}
+	*dp = '\0';
+	return(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsc-sendmt/main.c	Sun Aug 27 16:36:28 2023 -0800
@@ -0,0 +1,87 @@
+/*
+ * This C module is the main for proto-smsc-sendmt, a command line utility
+ * that constructs an MT-forwardSM.req GSUP message and shoots it over to
+ * proto-smsc-daemon for feeding to OsmoHLR.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/socket.h>
+
+#include <osmocom/gsm/gsup.h>
+
+extern void parse_smsc_addr_arg(const char *arg);
+extern void encode_smsc_addr(struct osmo_gsup_message *gmsg);
+extern int grok_imsi_user_arg(const char *arg, char *dest);
+extern void read_pdu_from_stdin(void);
+
+extern uint8_t tpdu_buf[];
+extern unsigned tpdu_len;
+
+static const uint8_t sm_rp_mr = 0xFF;
+
+int main(int argc, char **argv)
+{
+	struct osmo_gsup_message gmsg;
+	struct msgb *msgb;
+	int rc, sock;
+
+	if (argc != 4) {
+		fprintf(stderr, "usage: %s smsc-addr imsi socket-path\n",
+			argv[0]);
+		exit(1);
+	}
+	parse_smsc_addr_arg(argv[1]);
+	memset(&gmsg, 0, sizeof(gmsg));
+	rc = grok_imsi_user_arg(argv[2], gmsg.imsi);
+	if (rc < 0) {
+		fprintf(stderr, "error: invalid IMSI argument\n");
+		exit(1);
+	}
+	read_pdu_from_stdin();
+
+	/* fill out the rest of GSUP msg */
+	gmsg.message_type = OSMO_GSUP_MSGT_MT_FORWARD_SM_REQUEST;
+	gmsg.message_class = OSMO_GSUP_MESSAGE_CLASS_SMS;
+	gmsg.sm_rp_mr = &sm_rp_mr;
+	gmsg.sm_rp_da_type = OSMO_GSUP_SMS_SM_RP_ODA_NULL;
+	gmsg.sm_rp_oa_type = OSMO_GSUP_SMS_SM_RP_ODA_SMSC_ADDR;
+	encode_smsc_addr(&gmsg);
+	gmsg.sm_rp_ui = tpdu_buf;
+	gmsg.sm_rp_ui_len = tpdu_len;
+
+	/* pack it into an msgb */
+	msgb = msgb_alloc_headroom(4000, 64, "sendmt");
+	if (!msgb) {
+		fprintf(stderr, "error: unable to allocate msgb\n");
+		exit(1);
+	}
+	rc = osmo_gsup_encode(msgb, &gmsg);
+	if (rc < 0) {
+		fprintf(stderr, "error: osmo_gsup_encode() failed\n");
+		exit(1);
+	}
+
+	/* send it off via UNIX socket */
+	sock = osmo_sock_unix_init(SOCK_DGRAM, 0, argv[3], OSMO_SOCK_F_CONNECT);
+	if (sock < 0) {
+		fprintf(stderr, "error connecting to %s\n", argv[3]);
+		exit(1);
+	}
+	rc = send(sock, msgb->data, msgb->len, 0);
+	if (rc < 0) {
+		perror("sending dgram on socket");
+		exit(1);
+	}
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsc-sendmt/read_pdu.c	Sun Aug 27 16:36:28 2023 -0800
@@ -0,0 +1,38 @@
+/*
+ * This module implements the reading of hex-encoded SMS-DELIVER TPDU
+ * from stdin.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int decode_hex_line(const char *inbuf, uint8_t *outbuf, unsigned outmax);
+
+uint8_t tpdu_buf[176];
+unsigned tpdu_len;
+
+void read_pdu_from_stdin(void)
+{
+	char linebuf[512], *nl;
+	int rc;
+
+	if (!fgets(linebuf, sizeof(linebuf), stdin)) {
+		fprintf(stderr, "error: empty stdin is not acceptable\n");
+		exit(1);
+	}
+	nl = strchr(linebuf, '\n');
+	if (!nl) {
+		fprintf(stderr,
+			"error: stdin line is too long or unterminated\n");
+		exit(1);
+	}
+	*nl = '\0';
+	rc = decode_hex_line(linebuf, tpdu_buf, sizeof(tpdu_buf));
+	if (rc <= 0) {
+		fprintf(stderr, "error: stdin line is not a valid hex PDU\n");
+		exit(1);
+	}
+	tpdu_len = rc;
+}
--- a/smsc-sendmt/smsc_addr.c	Sun Aug 27 13:39:51 2023 -0800
+++ b/smsc-sendmt/smsc_addr.c	Sun Aug 27 16:36:28 2023 -0800
@@ -1,21 +1,25 @@
 /*
- * This C module is being stashed here temporarily until we figure out
- * where this function ultimately needs to go.  The parsing of the SMSC
- * address is being moved out of proto-smsc-daemon to proto-smsc-sendmt,
- * but we haven't started putting together the latter program yet.
+ * This module handles the parsing and GSUP encoding of our SMSC address,
+ * which we need to send to the MSC and ultimately to the MS as SM-RP-OA.
  */
 
 #include <ctype.h>
 #include <string.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 
-char smsc_addr_num[21];		/* maximum of 20 digits per GSM 04.11 */
-uint8_t smsc_addr_ton_npi;
+#include <osmocom/gsm/gsm48_ie.h>
+#include <osmocom/gsm/gsup.h>
 
-void parse_smsc_addr_arg(char *arg)
+static char smsc_addr_num[21];	/* maximum of 20 digits per GSM 04.11 */
+static uint8_t smsc_addr_ton_npi;
+static uint8_t smsc_addr_bcd[12];
+
+void parse_smsc_addr_arg(const char *arg)
 {
-	char *cp, *dp, *endp;
+	const char *cp;
+	char *dp, *endp;
 	unsigned ndig;
 
 	cp = arg;
@@ -49,3 +53,11 @@
 	if (*endp)
 		goto invalid;
 }
+
+void encode_smsc_addr(struct osmo_gsup_message *gmsg)
+{
+	gsm48_encode_bcd_number(smsc_addr_bcd, 11, 1, smsc_addr_num);
+	smsc_addr_bcd[1] = smsc_addr_ton_npi;
+	gmsg->sm_rp_oa = smsc_addr_bcd + 1;
+	gmsg->sm_rp_oa_len = smsc_addr_bcd[0];
+}