summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/host/layer23/include/osmocom/bb/common/osmocom_data.h2
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/Makefile.am2
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h3
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/mncc.h3
-rw-r--r--src/host/layer23/src/mobile/Makefile.am2
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c22
-rw-r--r--src/host/layer23/src/mobile/gsm48_cc.c45
-rw-r--r--src/host/layer23/src/mobile/main.c16
-rw-r--r--src/host/layer23/src/mobile/mnccms.c58
9 files changed, 116 insertions, 37 deletions
diff --git a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
index 6ad89cd3..8f150078 100644
--- a/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
+++ b/src/host/layer23/include/osmocom/bb/common/osmocom_data.h
@@ -18,6 +18,7 @@ struct osmocom_ms;
#include <osmocom/bb/mobile/gsm322.h>
#include <osmocom/bb/mobile/gsm48_mm.h>
#include <osmocom/bb/mobile/gsm48_cc.h>
+#include <osmocom/bb/mobile/mncc_sock.h>
#include <osmocom/bb/common/sim.h>
#include <osmocom/bb/common/l1ctl.h>
@@ -31,6 +32,7 @@ struct osmol1_entity {
struct osmomncc_entity {
int (*mncc_recv)(struct osmocom_ms *ms, int msg_type, void *arg);
+ struct mncc_sock_state *sock_state;
uint32_t ref;
};
diff --git a/src/host/layer23/include/osmocom/bb/mobile/Makefile.am b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
index 951e4d19..65b7ce76 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
+++ b/src/host/layer23/include/osmocom/bb/mobile/Makefile.am
@@ -1,2 +1,2 @@
noinst_HEADERS = gsm322.h gsm48_cc.h gsm48_mm.h gsm48_rr.h mncc.h settings.h \
- subscriber.h support.h transaction.h vty.h
+ subscriber.h support.h transaction.h vty.h mncc_sock.h
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
index 8cdd1c4f..282ffe5b 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
@@ -11,7 +11,8 @@ int gsm48_cc_init(struct osmocom_ms *ms);
int gsm48_cc_exit(struct osmocom_ms *ms);
int gsm48_rcv_cc(struct osmocom_ms *ms, struct msgb *msg);
int mncc_dequeue(struct osmocom_ms *ms);
-int mncc_send(struct osmocom_ms *ms, int msg_type, void *arg);
+int mncc_tx_to_cc(void *inst, int msg_type, void *arg);
+int mncc_clear_trans(void *inst, uint8_t protocol);
#endif /* _GSM48_CC_H */
diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc.h b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
index a2b48cf7..1d7f7794 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/mncc.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
@@ -109,9 +109,6 @@ struct gsm_call {
#define GSM_TCHF_FRAME 0x0300
#define GSM_TCHF_FRAME_EFR 0x0301
-#define MS_NEW 0x0400
-#define MS_DELETE 0x0401
-
#define GSM_MAX_FACILITY 128
#define GSM_MAX_SSVERSION 128
#define GSM_MAX_USERUSER 128
diff --git a/src/host/layer23/src/mobile/Makefile.am b/src/host/layer23/src/mobile/Makefile.am
index e5cf76a7..4cff9efd 100644
--- a/src/host/layer23/src/mobile/Makefile.am
+++ b/src/host/layer23/src/mobile/Makefile.am
@@ -5,7 +5,7 @@ LDADD = ../common/liblayer23.a $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOG
noinst_LIBRARIES = libmobile.a
libmobile_a_SOURCES = gsm322.c gsm48_cc.c gsm48_mm.c gsm48_rr.c \
mnccms.c settings.c subscriber.c support.c \
- transaction.c vty_interface.c voice.c
+ transaction.c vty_interface.c voice.c mncc_sock.c
bin_PROGRAMS = mobile
diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c
index 8b3b5524..ada94809 100644
--- a/src/host/layer23/src/mobile/app_mobile.c
+++ b/src/host/layer23/src/mobile/app_mobile.c
@@ -233,16 +233,13 @@ struct osmocom_ms *mobile_new(char *name)
ms->shutdown = 2; /* being down */
if (mncc_recv_app) {
- struct msgb *msg;
+ char name[32];
- msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
- if (msg) {
- struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data;
+ sprintf(name, "/tmp/ms_mncc_%s", ms->name);
- mncc->msg_type = MS_NEW;
- mncc_recv_app(ms, mncc->msg_type, mncc);
- }
ms->mncc_entity.mncc_recv = mncc_recv_app;
+ ms->mncc_entity.sock_state = mncc_sock_init(ms, name, l23_ctx);
+
} else if (ms->settings.ch_cap == GSM_CAP_SDCCH)
ms->mncc_entity.mncc_recv = mncc_recv_dummy;
else
@@ -266,15 +263,8 @@ int mobile_delete(struct osmocom_ms *ms, int force)
}
if (mncc_recv_app) {
- struct msgb *msg;
-
- msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
- if (msg) {
- struct gsm_mncc *mncc = (struct gsm_mncc *)msg->data;
-
- mncc->msg_type = MS_DELETE;
- mncc_recv_app(ms, mncc->msg_type, mncc);
- }
+ mncc_sock_exit(ms->mncc_entity.sock_state);
+ ms->mncc_entity.sock_state = NULL;
}
return 0;
diff --git a/src/host/layer23/src/mobile/gsm48_cc.c b/src/host/layer23/src/mobile/gsm48_cc.c
index 07ee2d9b..2e978197 100644
--- a/src/host/layer23/src/mobile/gsm48_cc.c
+++ b/src/host/layer23/src/mobile/gsm48_cc.c
@@ -76,9 +76,10 @@ int gsm48_cc_exit(struct osmocom_ms *ms)
LOGP(DCC, LOGL_INFO, "exit Call Control processes for %s\n", ms->name);
llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) {
- if (trans->protocol == GSM48_PDISC_CC)
+ if (trans->protocol == GSM48_PDISC_CC) {
LOGP(DCC, LOGL_NOTICE, "Free pendig CC-transaction.\n");
trans_free(trans);
+ }
}
while ((msg = msgb_dequeue(&cc->mncc_upqueue)))
@@ -1916,12 +1917,29 @@ static struct downstate {
#define DOWNSLLEN \
(sizeof(downstatelist) / sizeof(struct downstate))
-int mncc_send(struct osmocom_ms *ms, int msg_type, void *arg)
+int mncc_tx_to_cc(void *inst, int msg_type, void *arg)
{
+ struct osmocom_ms *ms = (struct osmocom_ms *) inst;
struct gsm_mncc *data = arg;
struct gsm_trans *trans;
int i, rc;
+ if (!ms->started || ms->shutdown) {
+ LOGP(DCC, LOGL_NOTICE, "Phone is down!\n");
+ if (ms->mncc_entity.mncc_recv && msg_type != MNCC_REL_REQ) {
+ struct gsm_mncc rel;
+
+ memset(&rel, 0, sizeof(rel));
+ rel.callref = data->callref;
+ mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
+ GSM48_CC_CAUSE_DEST_OOO);
+ ms->mncc_entity.mncc_recv(ms, MNCC_REL_IND, &rel);
+ }
+ return -EBUSY;
+ }
+
+ data->msg_type = msg_type;
+
/* Find callref */
trans = trans_find_by_callref(ms, data->callref);
@@ -2179,3 +2197,26 @@ int gsm48_rcv_cc(struct osmocom_ms *ms, struct msgb *msg)
return rc;
}
+int mncc_clear_trans(void *inst, uint8_t protocol)
+{
+ struct osmocom_ms *ms = (struct osmocom_ms *) inst;
+ struct gsm_mncc rel;
+ struct gsm_trans *trans, *trans2;
+
+ memset(&rel, 0, sizeof(struct gsm_mncc));
+
+ /* safe, in case the release process will destroy transaction node */
+ llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) {
+ if (trans->protocol == protocol) {
+ LOGP(DCC, LOGL_NOTICE, "Release CC-transaction.\n");
+ rel.callref = trans->callref;
+ mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
+ GSM48_CC_CAUSE_TEMP_FAILURE);
+ mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel);
+ }
+ }
+
+ return 0;
+
+}
+
diff --git a/src/host/layer23/src/mobile/main.c b/src/host/layer23/src/mobile/main.c
index ed961c57..5739bfde 100644
--- a/src/host/layer23/src/mobile/main.c
+++ b/src/host/layer23/src/mobile/main.c
@@ -54,6 +54,9 @@ struct gsmtap_inst *gsmtap_inst = NULL;
unsigned short vty_port = 4247;
int debug_set = 0;
char *config_dir = NULL;
+int use_mncc_sock = 0;
+
+int mncc_recv_socket(struct osmocom_ms *ms, int msg_type, void *arg);
int mobile_delete(struct osmocom_ms *ms, int force);
int mobile_signal_cb(unsigned int subsys, unsigned int signal,
@@ -83,6 +86,8 @@ static void print_help()
printf(" -v --vty-port The VTY port number to telnet to. "
"(default %u)\n", vty_port);
printf(" -d --debug Change debug flags.\n");
+ printf(" -m --mncc-sock Disable built-in MNCC handler and "
+ "offer socket\n");
}
static void handle_options(int argc, char **argv)
@@ -94,10 +99,11 @@ static void handle_options(int argc, char **argv)
{"gsmtap-ip", 1, 0, 'i'},
{"vty-port", 1, 0, 'v'},
{"debug", 1, 0, 'd'},
+ {"mncc-sock", 0, 0, 'm'},
{0, 0, 0, 0},
};
- c = getopt_long(argc, argv, "hi:v:d:",
+ c = getopt_long(argc, argv, "hi:v:d:m",
long_options, &option_index);
if (c == -1)
break;
@@ -118,6 +124,9 @@ static void handle_options(int argc, char **argv)
log_parse_category_mask(stderr_target, optarg);
debug_set = 1;
break;
+ case 'm':
+ use_mncc_sock = 1;
+ break;
default:
break;
}
@@ -187,7 +196,10 @@ int main(int argc, char **argv)
config_dir = talloc_strdup(l23_ctx, config_file);
config_dir = dirname(config_dir);
- rc = l23_app_init(NULL, config_file, vty_port);
+ if (use_mncc_sock)
+ rc = l23_app_init(mncc_recv_socket, config_file, vty_port);
+ else
+ rc = l23_app_init(NULL, config_file, vty_port);
if (rc)
exit(rc);
diff --git a/src/host/layer23/src/mobile/mnccms.c b/src/host/layer23/src/mobile/mnccms.c
index 8d3abe68..c6db1abb 100644
--- a/src/host/layer23/src/mobile/mnccms.c
+++ b/src/host/layer23/src/mobile/mnccms.c
@@ -216,7 +216,43 @@ int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg)
mncc_set_cause(&rel, GSM48_CAUSE_LOC_USER,
GSM48_CC_CAUSE_INCOMPAT_DEST);
- return mncc_send(ms, MNCC_REL_REQ, &rel);
+ return mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel);
+}
+
+/*
+ * MNCCms call application via socket
+ */
+int mncc_recv_socket(struct osmocom_ms *ms, int msg_type, void *arg)
+{
+ struct mncc_sock_state *state = ms->mncc_entity.sock_state;
+ struct gsm_mncc *mncc = arg;
+ struct msgb *msg;
+ unsigned char *data;
+
+ if (!state) {
+ if (msg_type != MNCC_REL_IND && msg_type != MNCC_REL_CNF) {
+ struct gsm_mncc rel;
+
+ /* reject */
+ memset(&rel, 0, sizeof(struct gsm_mncc));
+ rel.callref = mncc->callref;
+ mncc_set_cause(&rel, GSM48_CAUSE_LOC_USER,
+ GSM48_CC_CAUSE_TEMP_FAILURE);
+ return mncc_tx_to_cc(ms, MNCC_REL_REQ, &rel);
+ }
+ return 0;
+ }
+
+ mncc->msg_type = msg_type;
+
+ msg = msgb_alloc(sizeof(struct gsm_mncc), "MNCC");
+ if (!msg)
+ return -ENOMEM;
+
+ data = msgb_put(msg, sizeof(struct gsm_mncc));
+ memcpy(data, mncc, sizeof(struct gsm_mncc));
+
+ return mncc_sock_from_cc(state, msg);
}
/*
@@ -244,7 +280,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = data->callref;
mncc_set_cause(&mncc, GSM48_CAUSE_LOC_USER, cause);
- return mncc_send(ms, MNCC_REL_REQ, &mncc);
+ return mncc_tx_to_cc(ms, MNCC_REL_REQ, &mncc);
}
/* setup without call */
@@ -439,7 +475,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
mncc.fields |= MNCC_F_CCCAP;
mncc.cccap.dtmf = 1;
}
- mncc_send(ms, MNCC_CALL_CONF_REQ, &mncc);
+ mncc_tx_to_cc(ms, MNCC_CALL_CONF_REQ, &mncc);
if (first_call)
LOGP(DMNCC, LOGL_INFO, "Ring!\n");
else {
@@ -449,7 +485,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
call->ring = 1;
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = call->callref;
- mncc_send(ms, MNCC_ALERT_REQ, &mncc);
+ mncc_tx_to_cc(ms, MNCC_ALERT_REQ, &mncc);
if (ms->settings.auto_answer) {
LOGP(DMNCC, LOGL_INFO, "Auto-answering call\n");
mncc_answer(ms);
@@ -558,7 +594,7 @@ int mncc_call(struct osmocom_ms *ms, char *number)
}
}
- return mncc_send(ms, MNCC_SETUP_REQ, &setup);
+ return mncc_tx_to_cc(ms, MNCC_SETUP_REQ, &setup);
}
int mncc_hangup(struct osmocom_ms *ms)
@@ -583,7 +619,7 @@ int mncc_hangup(struct osmocom_ms *ms)
disc.callref = found->callref;
mncc_set_cause(&disc, GSM48_CAUSE_LOC_USER,
GSM48_CC_CAUSE_NORM_CALL_CLEAR);
- return mncc_send(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ,
+ return mncc_tx_to_cc(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ,
&disc);
}
@@ -616,7 +652,7 @@ int mncc_answer(struct osmocom_ms *ms)
memset(&rsp, 0, sizeof(struct gsm_mncc));
rsp.callref = alerting->callref;
- return mncc_send(ms, MNCC_SETUP_RSP, &rsp);
+ return mncc_tx_to_cc(ms, MNCC_SETUP_RSP, &rsp);
}
int mncc_hold(struct osmocom_ms *ms)
@@ -639,7 +675,7 @@ int mncc_hold(struct osmocom_ms *ms)
memset(&hold, 0, sizeof(struct gsm_mncc));
hold.callref = found->callref;
- return mncc_send(ms, MNCC_HOLD_REQ, &hold);
+ return mncc_tx_to_cc(ms, MNCC_HOLD_REQ, &hold);
}
int mncc_retrieve(struct osmocom_ms *ms, int number)
@@ -687,7 +723,7 @@ int mncc_retrieve(struct osmocom_ms *ms, int number)
memset(&retr, 0, sizeof(struct gsm_mncc));
retr.callref = call->callref;
- return mncc_send(ms, MNCC_RETRIEVE_REQ, &retr);
+ return mncc_tx_to_cc(ms, MNCC_RETRIEVE_REQ, &retr);
}
/*
@@ -714,7 +750,7 @@ static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc)
call->dtmf_state = DTMF_ST_START;
LOGP(DMNCC, LOGL_INFO, "start DTMF (keypad %c)\n",
dtmf.keypad);
- return mncc_send(ms, MNCC_START_DTMF_REQ, &dtmf);
+ return mncc_tx_to_cc(ms, MNCC_START_DTMF_REQ, &dtmf);
case DTMF_ST_START:
if (mncc->msg_type != MNCC_START_DTMF_RSP) {
LOGP(DMNCC, LOGL_INFO, "DTMF was rejected\n");
@@ -729,7 +765,7 @@ static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc)
dtmf.callref = call->callref;
call->dtmf_state = DTMF_ST_STOP;
LOGP(DMNCC, LOGL_INFO, "stop DTMF\n");
- return mncc_send(ms, MNCC_STOP_DTMF_REQ, &dtmf);
+ return mncc_tx_to_cc(ms, MNCC_STOP_DTMF_REQ, &dtmf);
case DTMF_ST_STOP:
start_dtmf_timer(call, 120);
call->dtmf_state = DTMF_ST_SPACE;