diff mtctest/setup.c @ 5:e7b192a5dee5

mtctest: initial import from old ThemWi
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 09 Jun 2024 00:58:38 +0000
parents
children 33d8b3177540
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mtctest/setup.c	Sun Jun 09 00:58:38 2024 +0000
@@ -0,0 +1,243 @@
+/*
+ * In this module we compose the MNCC_SETUP_REQ message
+ * initiating our test MT call.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "../include/mncc.h"
+#include "../include/gsm48_const.h"
+#include "../include/number_db_v2.h"
+#include "../libnumdb2/lookup_func.h"
+
+struct gsm_mncc setup_msg;
+
+static void
+set_called_number(arg)
+	char *arg;
+{
+	int rc, ndig;
+	char short_num[5], long_num[12];
+	struct short_number_rec *snum;
+
+	if (!strncmp(arg, "imsi:", 5)) {
+		rc = grok_imsi_user_arg(arg, setup_msg.imsi);
+		if (rc < 0) {
+			fprintf(stderr,
+			"error: call-by-IMSI destination \"%s\" is invalid\n",
+				arg);
+			exit(1);
+		}
+		return;
+	}
+	if (arg[0] == '+') {
+		if (arg[1] != '1') {
+			fprintf(stderr,
+	"error: plus-format call destination number must begin with 1\n");
+			exit(1);
+		}
+		if (grok_number_string(arg+1, 1) != 11) {
+bad_plus1:		fprintf(stderr,
+			"error: malformed +1 call destination number\n");
+			exit(1);
+		}
+		dehyphen_number_string(arg+1, setup_msg.called.number);
+		if (!is_nanp_valid_prefix(setup_msg.called.number+1))
+			goto bad_plus1;
+		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
+		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
+		setup_msg.fields |= MNCC_F_CALLED;
+		return;
+	}
+	ndig = grok_number_string(arg, 1);
+	switch (ndig) {
+	case 4:
+		dehyphen_number_string(arg, short_num);
+		if (read_number_db() < 0) {
+			fprintf(stderr, "error reading number database\n");
+			exit(1);
+		}
+		snum = numdb_lookup_short(short_num);
+		if (!snum) {
+			fprintf(stderr,
+				"error: short dial number %s is not valid\n",
+				short_num);
+			exit(1);
+		}
+		switch (snum->short_num_type) {
+		case SHORT_NUM_TYPE_ABBREV:
+			setup_msg.called.type = GSM48_TON_INTERNATIONAL;
+			setup_msg.called.plan = GSM48_NPI_ISDN_E164;
+			sprintf(setup_msg.called.number, "1%03u%03u%04u",
+				snum->fullnum_prefix[0],
+				snum->fullnum_prefix[1], snum->short_num);
+			break;
+		case SHORT_NUM_TYPE_ITN:
+			setup_msg.called.type = GSM48_TON_NET_SPEC;
+			setup_msg.called.plan = GSM48_NPI_PRIVATE;
+			strcpy(setup_msg.called.number, short_num);
+			break;
+		default:
+			fprintf(stderr,
+			"error: short dial number %s is not abbrev or ITN\n",
+				short_num);
+			exit(1);
+		}
+		setup_msg.fields |= MNCC_F_CALLED;
+		return;
+	case 10:
+		dehyphen_number_string(arg, long_num);
+		if (!is_nanp_valid_prefix(long_num))
+			break;
+		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
+		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
+		setup_msg.called.number[0] = '1';
+		strcpy(setup_msg.called.number+1, long_num);
+		setup_msg.fields |= MNCC_F_CALLED;
+		return;
+	case 11:
+		dehyphen_number_string(arg, long_num);
+		if (long_num[0] != '1')
+			break;
+		if (!is_nanp_valid_prefix(long_num+1))
+			break;
+		setup_msg.called.type = GSM48_TON_INTERNATIONAL;
+		setup_msg.called.plan = GSM48_NPI_ISDN_E164;
+		strcpy(setup_msg.called.number, long_num);
+		setup_msg.fields |= MNCC_F_CALLED;
+		return;
+	}
+	fprintf(stderr, "error: call destination number \"%s\" is invalid\n",
+		arg);
+	exit(1);
+}
+
+static void
+set_calling_number(arg)
+	char *arg;
+{
+	unsigned ndig;
+	int c;
+
+	if (!strcmp(arg, "unavail")) {
+		setup_msg.calling.present = GSM48_PRES_UNAVAIL;
+		return;
+	}
+	if (!strcmp(arg, "blocked")) {
+		setup_msg.calling.present = GSM48_PRES_RESTR;
+		return;
+	}
+	if (*arg == '+') {
+		setup_msg.calling.type = GSM48_TON_INTERNATIONAL;
+		arg++;
+	}
+	for (ndig = 0; *arg; ) {
+		c = *arg++;
+		if (c == ',')
+			break;
+		if (c == '-')
+			continue;
+		if (!is_valid_ext_digit(c)) {
+			fprintf(stderr,
+	"error: calling number argument contains invalid digit \'%c\'\n",
+				c);
+			exit(1);
+		}
+		if (ndig >= 32) {
+			fprintf(stderr,
+				"error: calling number argument is too long\n");
+			exit(1);
+		}
+		setup_msg.calling.number[ndig] = c;
+		ndig++;
+	}
+	if (!ndig) {
+		fprintf(stderr,
+			"error: calling number argument has no digits\n");
+		exit(1);
+	}
+	setup_msg.calling.plan = GSM48_NPI_ISDN_E164;
+	for (;;) {
+		while (*arg == ',')
+			arg++;
+		if (!*arg)
+			return;
+		if (!strncmp(arg, "ton=", 4)) {
+			arg += 4;
+			if (arg[0] >= '0' && arg[0] <= '7' && !isdigit(arg[1])){
+				setup_msg.calling.type = *arg - '0';
+				arg++;
+			} else {
+				fprintf(stderr,
+		"error: calling number argument contains invalid ton= part\n");
+				exit(1);
+			}
+		} else if (!strncmp(arg, "npi=", 4)) {
+			arg += 4;
+			if (arg[0] >= '0' && arg[0] <= '9' && !isdigit(arg[1])){
+				setup_msg.calling.plan = *arg - '0';
+				arg++;
+			} else if (arg[0] == '1' && arg[1] >= '0' &&
+				   arg[1] <= '5' && !isdigit(arg[2])) {
+				setup_msg.calling.plan = atoi(arg);
+				arg += 2;
+			} else {
+				fprintf(stderr,
+		"error: calling number argument contains invalid npi= part\n");
+				exit(1);
+			}
+		} else if (!strncmp(arg, "restr", 5)) {
+			arg += 5;
+			setup_msg.calling.present = GSM48_PRES_RESTR;
+		} else if (!strncmp(arg, "vp", 2)) {
+			arg += 2;
+			setup_msg.calling.screen = GSM48_SCRN_USER_PASS;
+		} else if (!strncmp(arg, "vf", 2)) {
+			arg += 2;
+			setup_msg.calling.screen = GSM48_SCRN_USER_FAIL;
+		} else if (!strncmp(arg, "net", 3)) {
+			arg += 3;
+			setup_msg.calling.screen = GSM48_SCRN_NETWORK;
+		} else {
+inv_qual:		fprintf(stderr,
+		"error: calling number argument contains invalid qualifier\n");
+			exit(1);
+		}
+		if (!*arg)
+			return;
+		if (*arg != ',')
+			goto inv_qual;
+	}
+}
+
+void
+init_setup_msg(from, to)
+	char *from, *to;
+{
+	setup_msg.msg_type = MNCC_SETUP_REQ;
+	setup_msg.callref = 1;
+	set_called_number(to);
+	if (from) {
+		set_calling_number(from);
+		setup_msg.fields |= MNCC_F_CALLING;
+	}
+}
+
+void
+send_setup_msg()
+{
+	if (setup_msg.imsi[0])
+		printf("Calling IMSI %s\n", setup_msg.imsi);
+	else
+		printf("Calling %s%s\n",
+			setup_msg.called.type == GSM48_TON_INTERNATIONAL ? "+"
+									 : "",
+			setup_msg.called.number);
+	send_mncc_to_gsm(&setup_msg, sizeof(struct gsm_mncc));
+}