FreeCalypso > hg > themwi-system-sw
view mtctest/setup.c @ 267:81958b35f74d
NANP validation: allow made-up area codes of N9X form
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 13 Nov 2023 15:28:09 -0800 |
parents | 74dae755f85a |
children |
line wrap: on
line source
/* * 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)); }