aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2009-12-29 11:49:12 +0100
committerHarald Welte <laforge@netfilter.org>2010-01-01 10:59:20 +0100
commit510087752e46489b7ea61d72b3ab39540ce0d908 (patch)
tree08b0f8203147f4691a22ccfdc33198c274eb625a
parent83579ca8ff706cd2d5ed27a10fa90129bdd943f4 (diff)
introduce and implement silent_call_reroute() and silent_call_rx()
Thise two functions are interfacing with the 04.08 layer 3 to determine if a particular message should be handled inside the OpenBSC layer 3, or if it should be handled in the silent call handler.
-rw-r--r--openbsc/include/openbsc/silent_call.h2
-rw-r--r--openbsc/src/gsm_04_08.c4
-rw-r--r--openbsc/src/silent_call.c44
3 files changed, 50 insertions, 0 deletions
diff --git a/openbsc/include/openbsc/silent_call.h b/openbsc/include/openbsc/silent_call.h
index 53ed4e248..b5bc5c035 100644
--- a/openbsc/include/openbsc/silent_call.h
+++ b/openbsc/include/openbsc/silent_call.h
@@ -3,5 +3,7 @@
extern int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data);
extern int gsm_silent_call_stop(struct gsm_subscriber *subscr);
+extern int silent_call_rx(struct msgb *msg);
+extern int silent_call_reroute(struct msgb *msg);
#endif /* _SILENT_CALL_H */
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index 6eeddbf90..cd66d255f 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -50,6 +50,7 @@
#include <openbsc/talloc.h>
#include <openbsc/transaction.h>
#include <openbsc/ussd.h>
+#include <openbsc/silent_call.h>
#define GSM_MAX_FACILITY 128
#define GSM_MAX_SSVERSION 128
@@ -3500,6 +3501,9 @@ int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id)
struct gsm48_hdr *gh = msgb_l3(msg);
u_int8_t pdisc = gh->proto_discr & 0x0f;
int rc = 0;
+
+ if (silent_call_reroute(msg))
+ return silent_call_rx(msg);
switch (pdisc) {
case GSM48_PDISC_CC:
diff --git a/openbsc/src/silent_call.c b/openbsc/src/silent_call.c
index 500d1873d..2679db7a9 100644
--- a/openbsc/src/silent_call.c
+++ b/openbsc/src/silent_call.c
@@ -34,6 +34,7 @@
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
+/* paging of the requested subscriber has completed */
static int paging_cb_silent(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *_lchan, void *_data)
{
@@ -70,6 +71,48 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
return rc;
}
+/* receive a layer 3 message from a silent call */
+int silent_call_rx(struct msgb *msg)
+{
+ /* FIXME: do something like sending it through a UDP port */
+ return 0;
+}
+
+struct msg_match {
+ u_int8_t pdisc;
+ u_int8_t msg_type;
+};
+
+/* list of messages that are handled inside OpenBSC, even in a silent call */
+static const struct msg_match silent_call_accept[] = {
+ { GSM48_PDISC_MM, GSM48_MT_MM_LOC_UPD_REQUEST },
+ { GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_REQ },
+};
+
+/* decide if we need to reroute a message as part of a silent call */
+int silent_call_reroute(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ u_int8_t pdisc = gh->proto_discr & 0x0f;
+ int i;
+
+ /* if we're not part of a silent call, never reroute */
+ if (!msg->lchan->silent_call)
+ return 0;
+
+ /* check if we are a special message that is handled in openbsc */
+ for (i = 0; i < ARRAY_SIZE(silent_call_accept); i++) {
+ if (silent_call_accept[i].pdisc == pdisc &&
+ silent_call_accept[i].msg_type == gh->msg_type)
+ return 0;
+ }
+
+ /* otherwise, reroute */
+ return 1;
+}
+
+
+/* initiate a silent call with a given subscriber */
int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data)
{
int rc;
@@ -79,6 +122,7 @@ int gsm_silent_call_start(struct gsm_subscriber *subscr, void *data)
return rc;
}
+/* end a silent call with a given subscriber */
int gsm_silent_call_stop(struct gsm_subscriber *subscr)
{
struct gsm_lchan *lchan;