This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Review at https://gerrit.osmocom.org/3695
NOT FOR MERGE combined changes from openbsc.git for gerrit checking
Change-Id: Id072aa07793aceca66bd74950bc40dd504982a55
---
M configure.ac
M contrib/jenkins.sh
M doc/examples/osmo-bsc/osmo-bsc.cfg
M include/openbsc/Makefile.am
M include/openbsc/gprs_sgsn.h
M include/openbsc/gprs_utils.h
A include/openbsc/gsm_04_14.h
M include/openbsc/gsm_data.h
M include/openbsc/gsm_data_shared.h
M include/openbsc/osmux.h
M src/gprs/gb_proxy.c
M src/gprs/gb_proxy_main.c
M src/gprs/gb_proxy_patch.c
M src/gprs/gb_proxy_peer.c
M src/gprs/gb_proxy_vty.c
M src/gprs/gprs_sgsn.c
M src/gprs/gprs_subscriber.c
M src/gprs/gprs_utils.c
M src/gprs/gtphub.c
M src/gprs/gtphub_main.c
M src/gprs/sgsn_cdr.c
M src/gprs/sgsn_libgtp.c
M src/gprs/sgsn_main.c
M src/gprs/sgsn_vty.c
M src/libbsc/abis_nm.c
M src/libbsc/abis_rsl.c
M src/libbsc/bsc_api.c
M src/libbsc/bsc_init.c
M src/libbsc/bsc_vty.c
M src/libbsc/handover_logic.c
M src/libbsc/net_init.c
M src/libcommon-cs/common_cs.c
M src/libcommon/gsm_data.c
M src/libcommon/gsm_data_shared.c
M src/libmgcp/mgcp_osmux.c
M src/libmgcp/mgcp_protocol.c
M src/libmsc/Makefile.am
M src/libmsc/db.c
M src/libmsc/gsm_04_08.c
M src/libmsc/gsm_04_11.c
A src/libmsc/gsm_04_14.c
M src/libmsc/smpp_openbsc.c
M src/libmsc/smpp_smsc.c
M src/libmsc/smpp_smsc.h
M src/libmsc/transaction.c
M src/libmsc/vty_interface_layer3.c
M src/osmo-bsc/osmo_bsc_main.c
M src/osmo-msc/msc_main.c
M src/utils/smpp_mirror.c
M tests/channel/channel_test.c
M tests/channel/channel_test.ok
M tests/db/db_test.err
M tests/gprs/gprs_test.c
M tests/gsm0408/gsm0408_test.c
M tests/gtphub/Makefile.am
M tests/sgsn/sgsn_test.c
56 files changed, 1,087 insertions(+), 405 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-msc refs/changes/95/3695/1
diff --git a/configure.ac b/configure.ac
index f184e78..871f7e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,7 +66,7 @@
AC_ARG_ENABLE([smpp], [AS_HELP_STRING([--enable-smpp], [Build the SMPP interface])],
[osmo_ac_build_smpp="$enableval"],[osmo_ac_build_smpp="no"])
if test "$osmo_ac_build_smpp" = "yes" ; then
- PKG_CHECK_MODULES(LIBSMPP34, libsmpp34 >= 1.10)
+ PKG_CHECK_MODULES(LIBSMPP34, libsmpp34 >= 1.12)
AC_DEFINE(BUILD_SMPP, 1, [Define if we want to build SMPP])
fi
AM_CONDITIONAL(BUILD_SMPP, test "x$osmo_ac_build_smpp" = "xyes")
diff --git a/contrib/jenkins.sh b/contrib/jenkins.sh
index b4074e4..7734965 100755
--- a/contrib/jenkins.sh
+++ b/contrib/jenkins.sh
@@ -1,4 +1,11 @@
#!/usr/bin/env bash
+# jenkins build helper script for openbsc. This is how we build on jenkins.osmocom.org
+
+if ! [ -x "$(command -v osmo-build-dep.sh)" ]; then
+ echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
+ exit 2
+fi
+
set -ex
diff --git a/doc/examples/osmo-bsc/osmo-bsc.cfg b/doc/examples/osmo-bsc/osmo-bsc.cfg
index b974b76..534605a 100644
--- a/doc/examples/osmo-bsc/osmo-bsc.cfg
+++ b/doc/examples/osmo-bsc/osmo-bsc.cfg
@@ -28,18 +28,6 @@
handover power budget interval 6
handover power budget hysteresis 3
handover maximum distance 9999
- timer t3101 10
- timer t3103 0
- timer t3105 0
- timer t3107 0
- timer t3109 0
- timer t3111 0
- timer t3113 60
- timer t3115 0
- timer t3117 0
- timer t3119 0
- timer t3122 0
- timer t3141 0
bts 0
type nanobts
band DCS1800
diff --git a/include/openbsc/Makefile.am b/include/openbsc/Makefile.am
index 2558d7c..995f02d 100644
--- a/include/openbsc/Makefile.am
+++ b/include/openbsc/Makefile.am
@@ -37,6 +37,7 @@
gprs_utils.h \
gsm_04_08.h \
gsm_04_11.h \
+ gsm_04_14.h \
gsm_04_80.h \
gsm_data.h \
gsm_data_shared.h \
diff --git a/include/openbsc/gprs_sgsn.h b/include/openbsc/gprs_sgsn.h
index fd86174..4e49c08 100644
--- a/include/openbsc/gprs_sgsn.h
+++ b/include/openbsc/gprs_sgsn.h
@@ -393,6 +393,8 @@
char apn_str[GSM_APN_LENGTH];
uint8_t qos_subscribed[20];
size_t qos_subscribed_len;
+ uint8_t pdp_charg[2];
+ bool has_pdp_charg;
};
struct sgsn_subscriber_data {
@@ -407,6 +409,9 @@
uint8_t hlr[9];
size_t hlr_len;
+
+ uint8_t pdp_charg[2];
+ bool has_pdp_charg;
};
#define SGSN_ERROR_CAUSE_NONE (-1)
diff --git a/include/openbsc/gprs_utils.h b/include/openbsc/gprs_utils.h
index 603605c..574f5c5 100644
--- a/include/openbsc/gprs_utils.h
+++ b/include/openbsc/gprs_utils.h
@@ -30,7 +30,6 @@
struct msgb *gprs_msgb_copy(const struct msgb *msg, const char *name);
int gprs_msgb_resize_area(struct msgb *msg, uint8_t *area,
size_t old_size, size_t new_size);
-char *gprs_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t rest_chars);
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
/* GSM 04.08, 10.5.7.3 GPRS Timer */
diff --git a/include/openbsc/gsm_04_14.h b/include/openbsc/gsm_04_14.h
new file mode 100644
index 0000000..3cdbe04
--- /dev/null
+++ b/include/openbsc/gsm_04_14.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <osmocom/gsm/protocol/gsm_04_14.h>
+
+int gsm0414_tx_close_tch_loop_cmd(struct gsm_subscriber_connection *conn,
+ enum gsm414_tch_loop_mode loop_mode);
+int gsm0414_tx_open_loop_cmd(struct gsm_subscriber_connection *conn);
+int gsm0414_tx_act_emmi_cmd(struct gsm_subscriber_connection *conn);
+int gsm0414_tx_test_interface(struct gsm_subscriber_connection *conn,
+ uint8_t tested_devs);
+int gsm0414_tx_reset_ms_pos_store(struct gsm_subscriber_connection *conn,
+ uint8_t technology);
+
+int gsm0414_rcv_test(struct gsm_subscriber_connection *conn,
+ struct msgb *msg);
diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h
index c307fee..f4de381 100644
--- a/include/openbsc/gsm_data.h
+++ b/include/openbsc/gsm_data.h
@@ -323,10 +323,18 @@
GSM_AUTH_POLICY_REGEXP, /* accept IMSIs matching given regexp */
};
-#define GSM_T3101_DEFAULT 10
-#define GSM_T3105_DEFAULT 40
+#define GSM_T3101_DEFAULT 10 /* s */
+#define GSM_T3103_DEFAULT 5 /* s */
+#define GSM_T3105_DEFAULT 100 /* ms */
+#define GSM_T3107_DEFAULT 5 /* s */
+#define GSM_T3109_DEFAULT 19 /* s, must be 2s + radio_link_timeout*0.48 */
+#define GSM_T3111_DEFAULT 2 /* s */
#define GSM_T3113_DEFAULT 60
+#define GSM_T3115_DEFAULT 10
+#define GSM_T3117_DEFAULT 10
+#define GSM_T3119_DEFAULT 10
#define GSM_T3122_DEFAULT 10
+#define GSM_T3141_DEFAULT 10
struct gsm_tz {
int override; /* if 0, use system's time zone instead. */
@@ -503,6 +511,8 @@
} smpp;
unsigned long validity_minutes;
+ time_t created;
+ bool is_report;
uint8_t reply_path_req;
uint8_t status_rep_req;
uint8_t ud_hdr_ind;
diff --git a/include/openbsc/gsm_data_shared.h b/include/openbsc/gsm_data_shared.h
index 0790807..60da2e5 100644
--- a/include/openbsc/gsm_data_shared.h
+++ b/include/openbsc/gsm_data_shared.h
@@ -899,7 +899,7 @@
};
-struct gsm_bts *gsm_bts_alloc(void *talloc_ctx);
+struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num);
struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num);
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts);
diff --git a/include/openbsc/osmux.h b/include/openbsc/osmux.h
index 0b64a7f..f3ea72a 100644
--- a/include/openbsc/osmux.h
+++ b/include/openbsc/osmux.h
@@ -11,8 +11,7 @@
};
int osmux_init(int role, struct mgcp_config *cfg);
-int osmux_enable_endpoint(struct mgcp_endpoint *endp, int role,
- struct in_addr *addr, uint16_t port);
+int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port);
void osmux_disable_endpoint(struct mgcp_endpoint *endp);
void osmux_allocate_cid(struct mgcp_endpoint *endp);
void osmux_release_cid(struct mgcp_endpoint *endp);
diff --git a/src/gprs/gb_proxy.c b/src/gprs/gb_proxy.c
index d95139f..cd38d23 100644
--- a/src/gprs/gb_proxy.c
+++ b/src/gprs/gb_proxy.c
@@ -1266,8 +1266,7 @@
rc = bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_FEAT, NULL, orig_msg);
break;
default:
- LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type 0x%02x unknown\n",
- pdu_type);
+ LOGP(DGPRS, LOGL_NOTICE, "BSSGP PDU type %s not supported\n", bssgp_pdu_str(pdu_type));
rate_ctr_inc(&cfg->ctrg->
ctr[GBPROX_GLOB_CTR_PROTO_ERR_SGSN]);
rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, orig_msg);
@@ -1370,9 +1369,8 @@
/* from BSS to SGSN */
peer = gbproxy_peer_by_nsei(cfg, nsvc->nsei);
if (!peer) {
- LOGP(DGPRS, LOGL_NOTICE, "signal %u for unknown peer "
- "NSEI=%u/NSVCI=%u\n", signal, nsvc->nsei,
- nsvc->nsvci);
+ LOGP(DGPRS, LOGL_NOTICE, "signal '%s' for unknown peer NSEI=%u/NSVCI=%u\n",
+ get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
return 0;
}
switch (signal) {
@@ -1380,9 +1378,8 @@
case S_NS_BLOCK:
if (!peer->blocked)
break;
- LOGP(DGPRS, LOGL_NOTICE, "Converting NS_RESET from "
- "NSEI=%u/NSVCI=%u into BSSGP_BVC_BLOCK to SGSN\n",
- nsvc->nsei, nsvc->nsvci);
+ LOGP(DGPRS, LOGL_NOTICE, "Converting '%s' from NSEI=%u/NSVCI=%u into BSSGP_BVC_BLOCK to SGSN\n",
+ get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, nsvc->nsei,
peer->bvci, 0);
break;
@@ -1431,6 +1428,10 @@
INIT_LLIST_HEAD(&cfg->bts_peers);
cfg->ctrg = rate_ctr_group_alloc(tall_bsc_ctx, &global_ctrg_desc, 0);
+ if (!cfg->ctrg) {
+ LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n");
+ return -1;
+ }
clock_gettime(CLOCK_REALTIME, &tp);
return 0;
diff --git a/src/gprs/gb_proxy_main.c b/src/gprs/gb_proxy_main.c
index 69a93b6..caff27f 100644
--- a/src/gprs/gb_proxy_main.c
+++ b/src/gprs/gb_proxy_main.c
@@ -98,6 +98,7 @@
switch (signal) {
case SIGINT:
+ case SIGTERM:
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(1);
exit(0);
@@ -232,6 +233,7 @@
msgb_talloc_ctx_init(tall_bsc_ctx, 0);
signal(SIGINT, &signal_handler);
+ signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
diff --git a/src/gprs/gb_proxy_patch.c b/src/gprs/gb_proxy_patch.c
index 7bddc44..210fb2b 100644
--- a/src/gprs/gb_proxy_patch.c
+++ b/src/gprs/gb_proxy_patch.c
@@ -28,6 +28,7 @@
#include <osmocom/gprs/protocol/gsm_08_18.h>
#include <osmocom/core/rate_ctr.h>
+#include <osmocom/gsm/apn.h>
/* patch RA identifier in place */
static void gbproxy_patch_raid(uint8_t *raid_enc, struct gbproxy_peer *peer,
@@ -101,7 +102,7 @@
LOGP(DGPRS, LOGL_DEBUG,
"Patching %s to SGSN: Removing APN '%s'\n",
log_text,
- gprs_apn_to_str(str1, apn, apn_len));
+ osmo_apn_to_str(str1, apn, apn_len));
*new_apn_ie_len = 0;
gprs_msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
@@ -116,8 +117,8 @@
"Patching %s to SGSN: "
"Replacing APN '%s' -> '%s'\n",
log_text,
- gprs_apn_to_str(str1, apn, apn_len),
- gprs_apn_to_str(str2, peer->cfg->core_apn,
+ osmo_apn_to_str(str1, apn, apn_len),
+ osmo_apn_to_str(str2, peer->cfg->core_apn,
peer->cfg->core_apn_size));
*new_apn_ie_len = peer->cfg->core_apn_size + 2;
diff --git a/src/gprs/gb_proxy_peer.c b/src/gprs/gb_proxy_peer.c
index 5365ff0..8909687 100644
--- a/src/gprs/gb_proxy_peer.c
+++ b/src/gprs/gb_proxy_peer.c
@@ -177,6 +177,10 @@
peer->bvci = bvci;
peer->ctrg = rate_ctr_group_alloc(peer, &peer_ctrg_desc, bvci);
+ if (!peer->ctrg) {
+ talloc_free(peer);
+ return NULL;
+ }
peer->cfg = cfg;
llist_add(&peer->list, &cfg->bts_peers);
diff --git a/src/gprs/gb_proxy_vty.c b/src/gprs/gb_proxy_vty.c
index 933b6b0..86d65a8 100644
--- a/src/gprs/gb_proxy_vty.c
+++ b/src/gprs/gb_proxy_vty.c
@@ -29,6 +29,7 @@
#include <openbsc/gsm_04_08.h>
#include <osmocom/gprs/gprs_ns.h>
+#include <osmocom/gsm/apn.h>
#include <openbsc/debug.h>
#include <openbsc/gb_proxy.h>
@@ -107,7 +108,7 @@
if (g_cfg->core_apn_size > 0) {
char str[500] = {0};
vty_out(vty, " core-access-point-name %s%s",
- gprs_apn_to_str(str, g_cfg->core_apn,
+ osmo_apn_to_str(str, g_cfg->core_apn,
g_cfg->core_apn_size),
VTY_NEWLINE);
} else {
diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c
index 18625ae..43eeaaa 100644
--- a/src/gprs/gprs_sgsn.c
+++ b/src/gprs/gprs_sgsn.c
@@ -30,6 +30,7 @@
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+#include <osmocom/gsm/apn.h>
#include <openbsc/gprs_subscriber.h>
#include <openbsc/debug.h>
@@ -129,6 +130,7 @@
void sgsn_rate_ctr_init() {
sgsn->rate_ctrs = rate_ctr_group_alloc(tall_bsc_ctx, &sgsn_ctrg_desc, 0);
+ OSMO_ASSERT(sgsn->rate_ctrs);
}
/* look-up an SGSN MM context based on Iu UE context (struct ue_conn_ctx)*/
@@ -229,6 +231,11 @@
LOGMMCTXP(LOGL_DEBUG, ctx, "Allocated with %s cipher.\n",
get_value_string(gprs_cipher_names, ctx->ciph_algo));
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli);
+ if (!ctx->ctrg) {
+ LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
+ talloc_free(ctx);
+ return NULL;
+ }
INIT_LLIST_HEAD(&ctx->pdp_list);
llist_add(&ctx->list, &sgsn_mm_ctxts);
@@ -253,6 +260,11 @@
ctx->pmm_state = PMM_DETACHED;
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, 0);
+ if (!ctx->ctrg) {
+ LOGMMCTXP(LOGL_ERROR, ctx, "Cannot allocate counter group\n");
+ talloc_free(ctx);
+ return NULL;
+ }
/* Need to get RAID from IU conn */
ctx->ra = ctx->iu.ue_ctx->ra_id;
@@ -380,6 +392,11 @@
pdp->mm = mm;
pdp->nsapi = nsapi;
pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi);
+ if (!pdp->ctrg) {
+ LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
+ talloc_free(pdp);
+ return NULL;
+ }
llist_add(&pdp->list, &mm->pdp_list);
llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
@@ -699,10 +716,21 @@
sgsn_auth_update(mmctx);
}
-static void insert_qos(struct tlv_parsed *tp, struct sgsn_subscriber_pdp_data *pdp)
+static void insert_extra(struct tlv_parsed *tp,
+ struct sgsn_subscriber_data *data,
+ struct sgsn_subscriber_pdp_data *pdp)
{
tp->lv[OSMO_IE_GSM_SUB_QOS].len = pdp->qos_subscribed_len;
tp->lv[OSMO_IE_GSM_SUB_QOS].val = pdp->qos_subscribed;
+
+ /* Prefer PDP charging characteristics of per subscriber one */
+ if (pdp->has_pdp_charg) {
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(pdp->pdp_charg);
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &pdp->pdp_charg[0];
+ } else if (data->has_pdp_charg) {
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].len = sizeof(data->pdp_charg);
+ tp->lv[OSMO_IE_GSM_CHARG_CHAR].val = &data->pdp_charg[0];
+ }
}
/**
@@ -731,7 +759,7 @@
return NULL;
}
- gprs_apn_to_str(req_apn_str,
+ osmo_apn_to_str(req_apn_str,
TLVP_VAL(tp, GSM48_IE_GSM_APN),
TLVP_LEN(tp, GSM48_IE_GSM_APN));
@@ -751,7 +779,7 @@
{
allow_any_apn = 1;
selected_apn_str = "";
- insert_qos(tp, pdp);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
continue;
}
if (!llist_empty(&sgsn_apn_ctxts)) {
@@ -760,7 +788,7 @@
if (apn_ctx == NULL)
continue;
}
- insert_qos(tp, pdp);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
selected_apn_str = pdp->apn_str;
break;
}
@@ -768,13 +796,13 @@
/* Check whether the given APN is granted */
llist_for_each_entry(pdp, &mmctx->subscr->sgsn_data->pdp_list, list) {
if (strcmp(pdp->apn_str, "*") == 0) {
- insert_qos(tp, pdp);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
selected_apn_str = req_apn_str;
allow_any_apn = 1;
continue;
}
if (strcasecmp(pdp->apn_str, req_apn_str) == 0) {
- insert_qos(tp, pdp);
+ insert_extra(tp, mmctx->subscr->sgsn_data, pdp);
selected_apn_str = req_apn_str;
break;
}
diff --git a/src/gprs/gprs_subscriber.c b/src/gprs/gprs_subscriber.c
index 176583b..94297d0 100644
--- a/src/gprs/gprs_subscriber.c
+++ b/src/gprs/gprs_subscriber.c
@@ -22,6 +22,7 @@
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
#include <osmocom/gsm/gsup.h>
+#include <osmocom/gsm/apn.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
#include <openbsc/gprs_subscriber.h>
@@ -325,6 +326,13 @@
}
}
+ if (gsup_msg->pdp_charg_enc && gsup_msg->pdp_charg_enc_len >= sizeof(sdata->pdp_charg)) {
+ memcpy(&sdata->pdp_charg, gsup_msg->pdp_charg_enc, sizeof(sdata->pdp_charg));
+ sdata->has_pdp_charg = 1;
+ } else {
+ sdata->has_pdp_charg = 0;
+ }
+
if (gsup_msg->pdp_info_compl) {
rc = gprs_subscr_pdp_data_clear(subscr);
if (rc > 0)
@@ -364,10 +372,17 @@
OSMO_ASSERT(pdp_data != NULL);
pdp_data->pdp_type = pdp_info->pdp_type;
- gprs_apn_to_str(pdp_data->apn_str,
+ osmo_apn_to_str(pdp_data->apn_str,
pdp_info->apn_enc, pdp_info->apn_enc_len);
memcpy(pdp_data->qos_subscribed, pdp_info->qos_enc, pdp_info->qos_enc_len);
pdp_data->qos_subscribed_len = pdp_info->qos_enc_len;
+
+ if (pdp_info->pdp_charg_enc && pdp_info->pdp_charg_enc_len >= sizeof(pdp_data->pdp_charg)) {
+ memcpy(&pdp_data->pdp_charg, pdp_info->pdp_charg_enc, sizeof(pdp_data->pdp_charg));
+ pdp_data->has_pdp_charg = 1;
+ } else {
+ pdp_data->has_pdp_charg = 0;
+ }
}
}
diff --git a/src/gprs/gprs_utils.c b/src/gprs/gprs_utils.c
index 64ed978..91a09d2 100644
--- a/src/gprs/gprs_utils.c
+++ b/src/gprs/gprs_utils.c
@@ -114,34 +114,6 @@
return 0;
}
-/* TODO: Move these conversion functions to a utils file. */
-/* TODO: consolidate with gprs_apn2str(). */
-/** memmove apn_enc to out_str, replacing the length octets in apn_enc with '.'
- * (omitting the first one) and terminating with a '\0'.
- * out_str needs to have rest_chars amount of bytes or 1 whatever is bigger.
- */
-char * gprs_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t rest_chars)
-{
- char *str = out_str;
-
- while (rest_chars > 0 && apn_enc[0]) {
- size_t label_size = apn_enc[0];
- if (label_size + 1 > rest_chars)
- return NULL;
-
- memmove(str, apn_enc + 1, label_size);
- str += label_size;
- rest_chars -= label_size + 1;
- apn_enc += label_size + 1;
-
- if (rest_chars)
- *(str++) = '.';
- }
- str[0] = '\0';
-
- return out_str;
-}
-
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str)
{
uint8_t *last_len_field;
diff --git a/src/gprs/gtphub.c b/src/gprs/gtphub.c
index 211018b..0a8e375 100644
--- a/src/gprs/gtphub.c
+++ b/src/gprs/gtphub.c
@@ -42,6 +42,8 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stats.h>
+#include <osmocom/gsm/apn.h>
+
static const int GTPH_GC_TICK_SECONDS = 1;
@@ -498,7 +500,7 @@
len = sizeof(apn_buf) - 1;
apn_buf[len] = '\0';
- *apn_str = gprs_apn_to_str(apn_buf, (uint8_t*)apn_buf, len);
+ *apn_str = osmo_apn_to_str(apn_buf, (uint8_t*)apn_buf, len);
if (!(*apn_str)) {
LOG(LOGL_ERROR, "APN IE: present but cannot be decoded: %s\n",
osmo_hexdump((uint8_t*)apn_buf, len));
@@ -2708,6 +2710,10 @@
pp->counters_io = rate_ctr_group_alloc(osmo_gtphub_ctx,
>phub_ctrg_io_desc, 0);
+ if (!pp->counters_io) {
+ talloc_free(pp);
+ return NULL;
+ }
llist_add(&pp->entry, &a->ports);
diff --git a/src/gprs/gtphub_main.c b/src/gprs/gtphub_main.c
index 73a122c..2b87d19 100644
--- a/src/gprs/gtphub_main.c
+++ b/src/gprs/gtphub_main.c
@@ -96,6 +96,7 @@
switch (signal) {
case SIGINT:
+ case SIGTERM:
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(1);
exit(0);
@@ -302,6 +303,7 @@
msgb_talloc_ctx_init(osmo_gtphub_ctx, 0);
signal(SIGINT, &signal_handler);
+ signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
diff --git a/src/gprs/sgsn_cdr.c b/src/gprs/sgsn_cdr.c
index 0910896..16ea9d4 100644
--- a/src/gprs/sgsn_cdr.c
+++ b/src/gprs/sgsn_cdr.c
@@ -22,6 +22,7 @@
#include <openbsc/signal.h>
#include <openbsc/gprs_utils.h>
#include <openbsc/debug.h>
+#include <osmocom/gsm/apn.h>
#include <openbsc/vty.h>
@@ -145,7 +146,7 @@
if (pdp->lib) {
- gprs_apn_to_str(apni, pdp->lib->apn_use.v, pdp->lib->apn_use.l);
+ osmo_apn_to_str(apni, pdp->lib->apn_use.v, pdp->lib->apn_use.l);
inet_ntop(AF_INET, &pdp->lib->hisaddr0.s_addr, ggsn_addr, sizeof(ggsn_addr));
extract_eua(&pdp->lib->eua, eua_addr);
}
diff --git a/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c
index 7595bf8..7ff8ece 100644
--- a/src/gprs/sgsn_libgtp.c
+++ b/src/gprs/sgsn_libgtp.c
@@ -234,6 +234,10 @@
memcpy(pdp->qos_req.v, qos, pdp->qos_req.l);
}
+ /* charging characteristics if present */
+ if (TLVP_LEN(tp, OSMO_IE_GSM_CHARG_CHAR) >= sizeof(pdp->cch_pdp))
+ pdp->cch_pdp = tlvp_val16be(tp, OSMO_IE_GSM_CHARG_CHAR);
+
/* SGSN address for control plane */
pdp->gsnlc.l = sizeof(sgsn->cfg.gtp_listenaddr.sin_addr);
memcpy(pdp->gsnlc.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
@@ -247,18 +251,28 @@
memcpy(pdp->gsnlu.v, &sgsn->cfg.gtp_listenaddr.sin_addr,
sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
- /* Routing Area Identifier with LAC and RAC fixed values, as
- * requested in 29.006 7.3.1 */
+ /* Encode RAT Type according to TS 29.060 7.7.50 */
+ pdp->rattype.l = 1;
+ if (mmctx->ran_type == MM_CTX_T_UTRAN_Iu)
+ pdp->rattype.v[0] = 1;
+ else
+ pdp->rattype.v[0] = 2;
+ pdp->rattype_given = 1;
+
+ /* Include RAI and ULI all the time */
pdp->rai_given = 1;
pdp->rai.l = 6;
+
+ /* Routing Area Identifier with LAC and RAC fixed values, as
+ * requested in 29.006 7.3.1 */
raid = mmctx->ra;
raid.lac = 0xFFFE;
raid.rac = 0xFF;
gsm48_construct_ra(pdp->rai.v, &raid);
- pdp->rattype.l = 1;
- pdp->rattype_given = 1;
-
+ /* Encode User Location Information accordint to TS 29.060 7.7.51 */
+ pdp->userloc_given = 1;
+ pdp->userloc.l = 8;
switch (mmctx->ran_type) {
case MM_CTX_T_GERAN_Gb:
case MM_CTX_T_GERAN_Iu:
@@ -270,8 +284,9 @@
bssgp_create_cell_id(&pdp->userloc.v[1], &mmctx->ra, mmctx->gb.cell_id);
break;
case MM_CTX_T_UTRAN_Iu:
- pdp->rattype.v[0] = 1;
- /* FIXME: Optional User Location Information with SAI */
+ pdp->userloc.v[0] = 1; /* SAI for UTRAN */
+ /* SAI is like CGI but with SAC instead of CID, so we can abuse this function */
+ bssgp_create_cell_id(&pdp->userloc.v[1], &mmctx->ra, mmctx->iu.sac);
break;
}
diff --git a/src/gprs/sgsn_main.c b/src/gprs/sgsn_main.c
index 71cb18c..d5d43ad 100644
--- a/src/gprs/sgsn_main.c
+++ b/src/gprs/sgsn_main.c
@@ -145,6 +145,7 @@
switch (signal) {
case SIGINT:
+ case SIGTERM:
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(1);
exit(0);
@@ -332,6 +333,7 @@
msgb_talloc_ctx_init(tall_bsc_ctx, 0);
signal(SIGINT, &signal_handler);
+ signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
diff --git a/src/gprs/sgsn_vty.c b/src/gprs/sgsn_vty.c
index 888f53a..cf44cc4 100644
--- a/src/gprs/sgsn_vty.c
+++ b/src/gprs/sgsn_vty.c
@@ -28,6 +28,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+#include <osmocom/gsm/apn.h>
#include <openbsc/debug.h>
#include <openbsc/sgsn.h>
@@ -116,7 +117,6 @@
#define GSM48_MAX_APN_LEN 102 /* 10.5.6.1 */
-/* TODO: consolidate with gprs_apn_to_str(). */
/** Copy apn to a static buffer, replacing the length octets in apn_enc with '.'
* and terminating with a '\0'. Return the static buffer.
* len: the length of the encoded APN (which has no terminating zero).
@@ -124,23 +124,10 @@
static char *gprs_apn2str(uint8_t *apn, unsigned int len)
{
static char apnbuf[GSM48_MAX_APN_LEN+1];
- unsigned int i = 0;
if (!apn)
return "";
-
- if (len > sizeof(apnbuf)-1)
- len = sizeof(apnbuf)-1;
-
- memcpy(apnbuf, apn, len);
- apnbuf[len] = '\0';
-
- /* replace the domain name step sizes with dots */
- while (i < len) {
- unsigned int step = apnbuf[i];
- apnbuf[i] = '.';
- i += step+1;
- }
+ osmo_apn_to_str(apnbuf, apn, len);
return apnbuf+1;
}
@@ -468,20 +455,22 @@
const char *imsi = pdp->mm ? pdp->mm->imsi : "(detaching)";
vty_out(vty, "%sPDP Context IMSI: %s, SAPI: %u, NSAPI: %u, TI: %u%s",
pfx, imsi, pdp->sapi, pdp->nsapi, pdp->ti, VTY_NEWLINE);
- vty_out(vty, "%s APN: %s%s", pfx,
- gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
- VTY_NEWLINE);
- vty_out(vty, "%s PDP Address: %s%s", pfx,
- gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
- VTY_NEWLINE);
- vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
- gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
- vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
- gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
- vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
- gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
- vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
- gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
+ if (pdp->lib) {
+ vty_out(vty, "%s APN: %s%s", pfx,
+ gprs_apn2str(pdp->lib->apn_use.v, pdp->lib->apn_use.l),
+ VTY_NEWLINE);
+ vty_out(vty, "%s PDP Address: %s%s", pfx,
+ gprs_pdpaddr2str(pdp->lib->eua.v, pdp->lib->eua.l),
+ VTY_NEWLINE);
+ vty_out(vty, "%s GTP Local Control(%s / TEIC: 0x%08x) ", pfx,
+ gtp_ntoa(&pdp->lib->gsnlc), pdp->lib->teic_own);
+ vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
+ gtp_ntoa(&pdp->lib->gsnlu), pdp->lib->teid_own, VTY_NEWLINE);
+ vty_out(vty, "%s GTP Remote Control(%s / TEIC: 0x%08x) ", pfx,
+ gtp_ntoa(&pdp->lib->gsnrc), pdp->lib->teic_gn);
+ vty_out(vty, "Data(%s / TEID: 0x%08x)%s",
+ gtp_ntoa(&pdp->lib->gsnru), pdp->lib->teid_gn, VTY_NEWLINE);
+ }
vty_out_rate_ctr_group(vty, " ", pdp->ctrg);
}
diff --git a/src/libbsc/abis_nm.c b/src/libbsc/abis_nm.c
index 019d039..cf20d7c 100644
--- a/src/libbsc/abis_nm.c
+++ b/src/libbsc/abis_nm.c
@@ -1590,10 +1590,17 @@
const uint8_t *attr, uint8_t attr_len)
{
struct abis_om_hdr *oh;
- struct msgb *msg = nm_msgb_alloc();
+ struct msgb *msg;
+
+ if (bts->type != GSM_BTS_TYPE_OSMOBTS) {
+ LOGPC(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n",
+ bts->nr, btstype2str(bts->type));
+ return -EINVAL;
+ }
DEBUGP(DNM, "Get Attr (bts=%d)\n", bts->nr);
+ msg = nm_msgb_alloc();
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
fill_om_fom_hdr(oh, attr_len, NM_MT_GET_ATTR, obj_class,
bts_nr, trx_nr, ts_nr);
diff --git a/src/libbsc/abis_rsl.c b/src/libbsc/abis_rsl.c
index 441b386..4f687a0 100644
--- a/src/libbsc/abis_rsl.c
+++ b/src/libbsc/abis_rsl.c
@@ -245,12 +245,14 @@
&& type == RSL_SYSTEM_INFO_13) {
/* Ericsson proprietary encoding of SI13 */
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, RSL_ERIC_SYSTEM_INFO_13);
- msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
+ if (data)
+ msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
msgb_tv_put(msg, RSL_IE_ERIC_BCCH_MAPPING, 0x00);
} else {
/* Normal encoding */
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
- msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
+ if (data)
+ msgb_tlv_put(msg, RSL_IE_FULL_BCCH_INFO, len, data);
}
msg->dst = trx->rsl_link;
@@ -269,7 +271,8 @@
ch->msg_type = RSL_MT_SACCH_FILL;
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
- msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
+ if (data)
+ msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
msg->dst = trx->rsl_link;
@@ -288,7 +291,8 @@
dh->chan_nr = chan_nr;
msgb_tv_put(msg, RSL_IE_SYSINFO_TYPE, type);
- msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
+ if (data)
+ msgb_tl16v_put(msg, RSL_IE_L3_INFO, len, data);
msg->dst = lchan->ts->trx->rsl_link;
@@ -2446,7 +2450,7 @@
dh = (struct abis_rsl_dchan_hdr *) msgb_put(msg, sizeof(*dh));
init_dchan_hdr(dh, msg_type);
dh->c.msg_discr = ABIS_RSL_MDISC_DED_CHAN;
- dh->chan_nr = gsm_pchan2chan_nr(GSM_PCHAN_PDCH, ts->nr, 0);
+ dh->chan_nr = gsm_pchan2chan_nr(GSM_PCHAN_TCH_F, ts->nr, 0);
DEBUGP(DRSL, "%s IPAC PDCH %sACT\n", gsm_ts_name(ts),
act ? "" : "DE");
@@ -2905,10 +2909,6 @@
int rsl_start_t3109(struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
-
- /* Disabled, mostly legacy code */
- if (bts->network->T3109 == 0)
- return -1;
osmo_timer_setup(&lchan->T3109, t3109_expired, lchan);
osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0);
diff --git a/src/libbsc/bsc_api.c b/src/libbsc/bsc_api.c
index c2828e3..c60f818 100644
--- a/src/libbsc/bsc_api.c
+++ b/src/libbsc/bsc_api.c
@@ -607,7 +607,7 @@
break;
case GSM48_MT_RR_STATUS:
LOGP(DRR, LOGL_NOTICE, "%s (cause: %s)\n",
- gsm48_rr_msg_name(GSM48_MT_RR_GPRS_SUSP_REQ),
+ gsm48_rr_msg_name(GSM48_MT_RR_STATUS),
rr_cause_name(gh->data[0]));
break;
case GSM48_MT_RR_MEAS_REP:
diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c
index 64dcd15..78ca2ab 100644
--- a/src/libbsc/bsc_init.c
+++ b/src/libbsc/bsc_init.c
@@ -104,8 +104,11 @@
struct gsm_bts *bts = trx->bts;
int rc, j;
- DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i),
- osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
+ if (si_len) {
+ DEBUGP(DRR, "SI%s: %s\n", get_value_string(osmo_sitype_strs, i),
+ osmo_hexdump(GSM_BTS_SI(bts, i), GSM_MACBLOCK_LEN));
+ } else
+ DEBUGP(DRR, "SI%s: OFF\n", get_value_string(osmo_sitype_strs, i));
switch (i) {
case SYSINFO_TYPE_5:
@@ -113,14 +116,18 @@
case SYSINFO_TYPE_5ter:
case SYSINFO_TYPE_6:
rc = rsl_sacch_filling(trx, osmo_sitype2rsl(i),
- GSM_BTS_SI(bts, i), si_len);
+ si_len ? GSM_BTS_SI(bts, i) : NULL, si_len);
break;
case SYSINFO_TYPE_2quater:
+ if (si_len == 0) {
+ rc = rsl_bcch_info(trx, i, NULL, 0);
+ break;
+ }
for (j = 0; j <= bts->si2q_count; j++)
rc = rsl_bcch_info(trx, i, (const uint8_t *)GSM_BTS_SI2Q(bts, j), GSM_MACBLOCK_LEN);
break;
default:
- rc = rsl_bcch_info(trx, i, GSM_BTS_SI(bts, i), si_len);
+ rc = rsl_bcch_info(trx, i, si_len ? GSM_BTS_SI(bts, i) : NULL, si_len);
break;
}
@@ -139,8 +146,8 @@
ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
bts->si_common.cell_sel_par.neci = bts->network->neci;
- /* Zero, forget the state of the SIs */
- bts->si_valid = 0;
+ /* Zero/forget the state of the dynamically computed SIs, leeping the static ones */
+ bts->si_valid = bts->si_mode_static;
/* First, we determine which of the SI messages we actually need */
@@ -193,9 +200,13 @@
for (n = 0; n < n_si; n++) {
i = gen_si[n];
+ /* if we don't currently have this SI, we send a zero-length
+ * RSL BCCH FILLING / SACCH FILLING * in order to deactivate
+ * the SI, in case it might have previously been active */
if (!GSM_BTS_HAS_SI(bts, i))
- continue;
- rc = rsl_si(trx, i, si_len[i]);
+ rc = rsl_si(trx, i, 0);
+ else
+ rc = rsl_si(trx, i, si_len[i]);
if (rc < 0)
return rc;
}
@@ -350,12 +361,12 @@
generate_cell_chan_list(ca, trx->bts);
/* Request generic BTS-level attributes */
- abis_nm_get_attr(trx->bts, NM_OC_BTS, trx->bts->nr, trx->nr, 0xFF, bts_attr, sizeof(bts_attr));
+ abis_nm_get_attr(trx->bts, NM_OC_BTS, 0xFF, 0xFF, 0xFF, bts_attr, sizeof(bts_attr));
llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
int i;
/* Request TRX-level attributes */
- abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, cur_trx->bts->nr, cur_trx->nr, 0xFF,
+ abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, 0, cur_trx->nr, 0xFF,
trx_attr, sizeof(trx_attr));
for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
generate_ma_for_ts(&cur_trx->ts[i]);
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index 722753a..bd363ae 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -30,6 +30,7 @@
#include <osmocom/vty/misc.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/gsm0502.h>
+#include <osmocom/ctrl/control_if.h>
#include <arpa/inet.h>
@@ -776,6 +777,11 @@
return CMD_SUCCESS;
}
+/* small helper macro for conditional dumping of timer */
+#define VTY_OUT_TIMER(number) \
+ if (gsmnet->T##number != GSM_T##number##_DEFAULT) \
+ vty_out(vty, " timer t"#number" %u%s", gsmnet->T##number, VTY_NEWLINE)
+
static int config_write_net(struct vty *vty)
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
@@ -812,18 +818,18 @@
gsmnet->handover.pwr_hysteresis, VTY_NEWLINE);
vty_out(vty, " handover maximum distance %u%s",
gsmnet->handover.max_distance, VTY_NEWLINE);
- vty_out(vty, " timer t3101 %u%s", gsmnet->T3101, VTY_NEWLINE);
- vty_out(vty, " timer t3103 %u%s", gsmnet->T3103, VTY_NEWLINE);
- vty_out(vty, " timer t3105 %u%s", gsmnet->T3105, VTY_NEWLINE);
- vty_out(vty, " timer t3107 %u%s", gsmnet->T3107, VTY_NEWLINE);
- vty_out(vty, " timer t3109 %u%s", gsmnet->T3109, VTY_NEWLINE);
- vty_out(vty, " timer t3111 %u%s", gsmnet->T3111, VTY_NEWLINE);
- vty_out(vty, " timer t3113 %u%s", gsmnet->T3113, VTY_NEWLINE);
- vty_out(vty, " timer t3115 %u%s", gsmnet->T3115, VTY_NEWLINE);
- vty_out(vty, " timer t3117 %u%s", gsmnet->T3117, VTY_NEWLINE);
- vty_out(vty, " timer t3119 %u%s", gsmnet->T3119, VTY_NEWLINE);
- vty_out(vty, " timer t3122 %u%s", gsmnet->T3122, VTY_NEWLINE);
- vty_out(vty, " timer t3141 %u%s", gsmnet->T3141, VTY_NEWLINE);
+ VTY_OUT_TIMER(3101);
+ VTY_OUT_TIMER(3103);
+ VTY_OUT_TIMER(3105);
+ VTY_OUT_TIMER(3107);
+ VTY_OUT_TIMER(3109);
+ VTY_OUT_TIMER(3111);
+ VTY_OUT_TIMER(3113);
+ VTY_OUT_TIMER(3115);
+ VTY_OUT_TIMER(3117);
+ VTY_OUT_TIMER(3119);
+ VTY_OUT_TIMER(3122);
+ VTY_OUT_TIMER(3141);
vty_out(vty, " dyn_ts_allow_tch_f %d%s",
gsmnet->dyn_ts_allow_tch_f ? 1 : 0, VTY_NEWLINE);
if (gsmnet->tz.override != 0) {
@@ -1534,38 +1540,43 @@
return CMD_SUCCESS;
}
+#define DEFAULT_TIMER(number) GSM_T##number##_DEFAULT
+/* Add another expansion so that DEFAULT_TIMER() becomes its value */
+#define EXPAND_AND_STRINGIFY(x) OSMO_STRINGIFY(x)
+
#define DECLARE_TIMER(number, doc) \
DEFUN(cfg_net_T##number, \
cfg_net_T##number##_cmd, \
- "timer t" #number " <0-65535>", \
+ "timer t" #number " (default|<1-65535>)", \
"Configure GSM Timers\n" \
- doc "Timer Value in seconds\n") \
+ doc " (default: " EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \
+ "Set to default timer value" \
+ " (" EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \
+ "Timer Value in seconds\n") \
{ \
struct gsm_network *gsmnet = gsmnet_from_vty(vty); \
- int value = atoi(argv[0]); \
- \
- if (value < 0 || value > 65535) { \
- vty_out(vty, "Timer value %s out of range.%s", \
- argv[0], VTY_NEWLINE); \
- return CMD_WARNING; \
- } \
+ int value; \
+ if (strcmp(argv[0], "default") == 0) \
+ value = DEFAULT_TIMER(number); \
+ else \
+ value = atoi(argv[0]); \
\
gsmnet->T##number = value; \
return CMD_SUCCESS; \
}
-DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT.\n")
-DECLARE_TIMER(3103, "Set the timeout value for HANDOVER.\n")
-DECLARE_TIMER(3105, "Set the timer for repetition of PHYSICAL INFORMATION.\n")
-DECLARE_TIMER(3107, "Currently not used.\n")
-DECLARE_TIMER(3109, "Set the RSL SACCH deactivation timeout.\n")
-DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel.\n")
-DECLARE_TIMER(3113, "Set the time to try paging a subscriber.\n")
-DECLARE_TIMER(3115, "Currently not used.\n")
-DECLARE_TIMER(3117, "Currently not used.\n")
-DECLARE_TIMER(3119, "Currently not used.\n")
-DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT\n")
-DECLARE_TIMER(3141, "Currently not used.\n")
+DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT")
+DECLARE_TIMER(3103, "Set the timeout value for HANDOVER")
+DECLARE_TIMER(3105, "Set the timer for repetition of PHYSICAL INFORMATION")
+DECLARE_TIMER(3107, "Currently not used")
+DECLARE_TIMER(3109, "Set the RSL SACCH deactivation timeout")
+DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel")
+DECLARE_TIMER(3113, "Set the time to try paging a subscriber")
+DECLARE_TIMER(3115, "Currently not used")
+DECLARE_TIMER(3117, "Currently not used")
+DECLARE_TIMER(3119, "Currently not used")
+DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT")
+DECLARE_TIMER(3141, "Currently not used")
DEFUN_DEPRECATED(cfg_net_dtx,
cfg_net_dtx_cmd,
@@ -3801,6 +3812,38 @@
return CMD_SUCCESS;
}
+DEFUN(bts_resend, bts_resend_cmd,
+ "bts <0-255> resend-system-information",
+ "BTS Specific Commands\n" "BTS Number\n"
+ "Re-generate + re-send BCCH SYSTEM INFORMATION\n")
+{
+ struct gsm_network *gsmnet;
+ struct gsm_bts_trx *trx;
+ struct gsm_bts *bts;
+ unsigned int bts_nr;
+
+ gsmnet = gsmnet_from_vty(vty);
+
+ bts_nr = atoi(argv[0]);
+ if (bts_nr >= gsmnet->num_bts) {
+ vty_out(vty, "BTS number must be between 0 and %d. It was %d.%s",
+ gsmnet->num_bts, bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts = gsm_bts_num(gsmnet, bts_nr);
+ if (!bts) {
+ vty_out(vty, "BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ llist_for_each_entry_reverse(trx, &bts->trx_list, list)
+ gsm_bts_trx_set_system_infos(trx);
+
+ return CMD_SUCCESS;
+}
+
+
DEFUN(smscb_cmd, smscb_cmd_cmd,
"bts <0-255> smscb-command <1-4> HEXSTRING",
"BTS related commands\n" "BTS Number\n"
@@ -4061,6 +4104,20 @@
rsl_ipacc_mdcx(lchan, ntohl(ia.s_addr), port, 0);
return CMD_SUCCESS;
}
+
+DEFUN(ctrl_trap, ctrl_trap_cmd,
+ "ctrl-interface generate-trap TRAP VALUE",
+ "Commands related to the CTRL Interface\n"
+ "Generate a TRAP for test purpose\n"
+ "Identity/Name of the TRAP variable\n"
+ "Value of the TRAP variable\n")
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+
+ ctrl_cmd_send_trap(net->ctrl, argv[0], (char *) argv[1]);
+ return CMD_SUCCESS;
+}
+
extern int bsc_vty_init_extra(void);
int bsc_vty_init(struct gsm_network *network)
@@ -4256,10 +4313,12 @@
install_element(ENABLE_NODE, &drop_bts_cmd);
install_element(ENABLE_NODE, &restart_bts_cmd);
+ install_element(ENABLE_NODE, &bts_resend_cmd);
install_element(ENABLE_NODE, &pdch_act_cmd);
install_element(ENABLE_NODE, &lchan_act_cmd);
install_element(ENABLE_NODE, &lchan_mdcx_cmd);
install_element(ENABLE_NODE, &smscb_cmd_cmd);
+ install_element(ENABLE_NODE, &ctrl_trap_cmd);
abis_nm_vty_init();
abis_om2k_vty_init();
diff --git a/src/libbsc/handover_logic.c b/src/libbsc/handover_logic.c
index c03563f..57d1dcd 100644
--- a/src/libbsc/handover_logic.c
+++ b/src/libbsc/handover_logic.c
@@ -282,6 +282,7 @@
new_lchan->conn->ho_lchan = NULL;
new_lchan->conn->lchan = new_lchan;
+ new_lchan->conn->bts = new_lchan->ts->trx->bts;
ho->old_lchan->conn = NULL;
lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END);
diff --git a/src/libbsc/net_init.c b/src/libbsc/net_init.c
index bc5ed35..9d54319 100644
--- a/src/libbsc/net_init.c
+++ b/src/libbsc/net_init.c
@@ -44,10 +44,17 @@
net->num_bts = 0;
net->reject_cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
net->T3101 = GSM_T3101_DEFAULT;
+ net->T3103 = GSM_T3103_DEFAULT;
net->T3105 = GSM_T3105_DEFAULT;
+ net->T3107 = GSM_T3107_DEFAULT;
+ net->T3109 = GSM_T3109_DEFAULT;
+ net->T3111 = GSM_T3111_DEFAULT;
net->T3113 = GSM_T3113_DEFAULT;
+ net->T3115 = GSM_T3115_DEFAULT;
+ net->T3117 = GSM_T3117_DEFAULT;
+ net->T3119 = GSM_T3119_DEFAULT;
net->T3122 = GSM_T3122_DEFAULT;
- /* FIXME: initialize all other timers! */
+ net->T3141 = GSM_T3141_DEFAULT;
/* default set of handover parameters */
net->handover.win_rxlev_avg = 10;
@@ -61,6 +68,10 @@
/* init statistics */
net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0);
+ if (!net->bsc_ctrs) {
+ talloc_free(net);
+ return NULL;
+ }
gsm_net_update_ctype(net);
diff --git a/src/libcommon-cs/common_cs.c b/src/libcommon-cs/common_cs.c
index 8e19bb2..99206c8 100644
--- a/src/libcommon-cs/common_cs.c
+++ b/src/libcommon-cs/common_cs.c
@@ -68,6 +68,10 @@
/* init statistics */
net->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, 0);
+ if (!net->msc_ctrs) {
+ talloc_free(net);
+ return NULL;
+ }
net->active_calls = osmo_counter_alloc("msc.active_calls");
net->mncc_recv = mncc_recv;
diff --git a/src/libcommon/gsm_data.c b/src/libcommon/gsm_data.c
index b5bf059..7be2240 100644
--- a/src/libcommon/gsm_data.c
+++ b/src/libcommon/gsm_data.c
@@ -254,12 +254,13 @@
if (!model && type != GSM_BTS_TYPE_UNKNOWN)
return NULL;
- bts = gsm_bts_alloc(net);
+ bts = gsm_bts_alloc(net, net->num_bts);
if (!bts)
return NULL;
+ net->num_bts++;
+
bts->network = net;
- bts->nr = net->num_bts++;
bts->type = type;
bts->model = model;
bts->bsic = bsic;
diff --git a/src/libcommon/gsm_data_shared.c b/src/libcommon/gsm_data_shared.c
index 8992636..2696273 100644
--- a/src/libcommon/gsm_data_shared.c
+++ b/src/libcommon/gsm_data_shared.c
@@ -312,7 +312,7 @@
.initial_mcs = 6,
};
-struct gsm_bts *gsm_bts_alloc(void *ctx)
+struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
{
struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
int i;
@@ -320,6 +320,7 @@
if (!bts)
return NULL;
+ bts->nr = bts_num;
bts->num_trx = 0;
INIT_LLIST_HEAD(&bts->trx_list);
bts->ms_max_power = 15; /* dBm */
@@ -643,11 +644,14 @@
switch (pchan) {
case GSM_PCHAN_TCH_F:
- case GSM_PCHAN_PDCH:
case GSM_PCHAN_TCH_F_PDCH:
OSMO_ASSERT(lchan_nr == 0);
cbits = 0x01;
break;
+ case GSM_PCHAN_PDCH:
+ OSMO_ASSERT(lchan_nr == 0);
+ cbits = RSL_CHAN_OSMO_PDCH >> 3;
+ break;
case GSM_PCHAN_TCH_H:
OSMO_ASSERT(lchan_nr < 2);
cbits = 0x02;
diff --git a/src/libmgcp/mgcp_osmux.c b/src/libmgcp/mgcp_osmux.c
index b46a80e..c52984b 100644
--- a/src/libmgcp/mgcp_osmux.c
+++ b/src/libmgcp/mgcp_osmux.c
@@ -340,8 +340,7 @@
if (endp->osmux.state == OSMUX_STATE_ENABLED)
goto out;
- if (osmux_enable_endpoint(endp, OSMUX_ROLE_BSC_NAT,
- &addr->sin_addr, addr->sin_port) < 0 ){
+ if (osmux_enable_endpoint(endp, &addr->sin_addr, addr->sin_port) < 0 ) {
LOGP(DMGCP, LOGL_ERROR,
"Could not enable osmux in endpoint %d\n",
ENDPOINT_NUMBER(endp));
@@ -433,8 +432,7 @@
return 0;
}
-int osmux_enable_endpoint(struct mgcp_endpoint *endp, int role,
- struct in_addr *addr, uint16_t port)
+int osmux_enable_endpoint(struct mgcp_endpoint *endp, struct in_addr *addr, uint16_t port)
{
/* If osmux is enabled, initialize the output handler. This handler is
* used to reconstruct the RTP flow from osmux. The RTP SSRC is
@@ -522,8 +520,7 @@
return 0;
if (endp->osmux.state == OSMUX_STATE_ACTIVATING) {
- if (osmux_enable_endpoint(endp, OSMUX_ROLE_BSC,
- &endp->net_end.addr,
+ if (osmux_enable_endpoint(endp, &endp->net_end.addr,
htons(endp->cfg->osmux_port)) < 0) {
LOGP(DMGCP, LOGL_ERROR,
"Could not activate osmux in endpoint %d\n",
diff --git a/src/libmgcp/mgcp_protocol.c b/src/libmgcp/mgcp_protocol.c
index 78e41f1..96542c5 100644
--- a/src/libmgcp/mgcp_protocol.c
+++ b/src/libmgcp/mgcp_protocol.c
@@ -277,10 +277,12 @@
if (!addr)
addr = mgcp_net_src_addr(endp);
- if (endp->osmux.state == OSMUX_STATE_NEGOTIATING)
+ if (endp->osmux.state == OSMUX_STATE_NEGOTIATING) {
sprintf(osmux_extension, "\nX-Osmux: %u", endp->osmux.cid);
- else
+ endp->osmux.state = OSMUX_STATE_ACTIVATING;
+ } else {
osmux_extension[0] = '\0';
+ }
len = snprintf(sdp_record, sizeof(sdp_record),
"I: %u%s\n\n", endp->ci, osmux_extension);
diff --git a/src/libmsc/Makefile.am b/src/libmsc/Makefile.am
index 16154ff..4726bbe 100644
--- a/src/libmsc/Makefile.am
+++ b/src/libmsc/Makefile.am
@@ -30,6 +30,7 @@
db.c \
gsm_04_08.c \
gsm_04_11.c \
+ gsm_04_14.c \
gsm_04_80.c \
gsm_subscriber.c \
iucs.c \
diff --git a/src/libmsc/db.c b/src/libmsc/db.c
index 28e9782..ae7e287 100644
--- a/src/libmsc/db.c
+++ b/src/libmsc/db.c
@@ -48,7 +48,7 @@
static char *db_dirname = NULL;
static dbi_conn conn;
-#define SCHEMA_REVISION "4"
+#define SCHEMA_REVISION "5"
enum {
SCHEMA_META,
@@ -122,6 +122,8 @@
"valid_until TIMESTAMP, "
"reply_path_req INTEGER NOT NULL, "
"status_rep_req INTEGER NOT NULL, "
+ "is_report INTEGER NOT NULL, "
+ "msg_ref INTEGER NOT NULL, "
"protocol_id INTEGER NOT NULL, "
"data_coding_scheme INTEGER NOT NULL, "
"ud_hdr_ind INTEGER NOT NULL, "
@@ -378,6 +380,152 @@
return -EINVAL;
}
+/* Just like v3, but there is a new message reference field for status reports,
+ * that is set to zero for existing entries since there is no way we can infer
+ * this.
+ */
+static struct gsm_sms *sms_from_result_v4(dbi_result result)
+{
+ struct gsm_sms *sms = sms_alloc();
+ const unsigned char *user_data;
+ const char *text, *addr;
+
+ if (!sms)
+ return NULL;
+
+ sms->id = dbi_result_get_ulonglong(result, "id");
+
+ sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req");
+ sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req");
+ sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind");
+ sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id");
+ sms->data_coding_scheme = dbi_result_get_ulonglong(result,
+ "data_coding_scheme");
+
+ addr = dbi_result_get_string(result, "src_addr");
+ osmo_strlcpy(sms->src.addr, addr, sizeof(sms->src.addr));
+ sms->src.ton = dbi_result_get_ulonglong(result, "src_ton");
+ sms->src.npi = dbi_result_get_ulonglong(result, "src_npi");
+
+ addr = dbi_result_get_string(result, "dest_addr");
+ osmo_strlcpy(sms->dst.addr, addr, sizeof(sms->dst.addr));
+ sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton");
+ sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi");
+
+ sms->user_data_len = dbi_result_get_field_length(result, "user_data");
+ user_data = dbi_result_get_binary(result, "user_data");
+ if (sms->user_data_len > sizeof(sms->user_data))
+ sms->user_data_len = (uint8_t) sizeof(sms->user_data);
+ memcpy(sms->user_data, user_data, sms->user_data_len);
+
+ text = dbi_result_get_string(result, "text");
+ if (text)
+ osmo_strlcpy(sms->text, text, sizeof(sms->text));
+ return sms;
+}
+
+static int update_db_revision_4(void)
+{
+ dbi_result result;
+ struct gsm_sms *sms;
+
+ LOGP(DDB, LOGL_NOTICE, "Going to migrate from revision 4\n");
+
+ result = dbi_conn_query(conn, "BEGIN EXCLUSIVE TRANSACTION");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to begin transaction (upgrade from rev 4)\n");
+ return -EINVAL;
+ }
+ dbi_result_free(result);
+
+ /* Rename old SMS table to be able create a new one */
+ result = dbi_conn_query(conn, "ALTER TABLE SMS RENAME TO SMS_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to rename the old SMS table (upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* Create new SMS table with all the bells and whistles! */
+ result = dbi_conn_query(conn, create_stmts[SCHEMA_SMS]);
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to create a new SMS table (upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* Cycle through old messages and convert them to the new format */
+ result = dbi_conn_query(conn, "SELECT * FROM SMS_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed fetch messages from the old SMS table (upgrade from rev 4).\n");
+ goto rollback;
+ }
+ while (dbi_result_next_row(result)) {
+ sms = sms_from_result_v4(result);
+ if (db_sms_store(sms) != 0) {
+ LOGP(DDB, LOGL_ERROR, "Failed to store message to the new SMS table(upgrade from rev 4).\n");
+ sms_free(sms);
+ dbi_result_free(result);
+ goto rollback;
+ }
+ sms_free(sms);
+ }
+ dbi_result_free(result);
+
+ /* Remove the temporary table */
+ result = dbi_conn_query(conn, "DROP TABLE SMS_4");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to drop the old SMS table (upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ /* We're done. Bump DB Meta revision to 4 */
+ result = dbi_conn_query(conn,
+ "UPDATE Meta "
+ "SET value = '5' "
+ "WHERE key = 'revision'");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to update DB schema revision (upgrade from rev 4).\n");
+ goto rollback;
+ }
+ dbi_result_free(result);
+
+ result = dbi_conn_query(conn, "COMMIT TRANSACTION");
+ if (!result) {
+ LOGP(DDB, LOGL_ERROR,
+ "Failed to commit the transaction (upgrade from rev 4)\n");
+ return -EINVAL;
+ } else {
+ dbi_result_free(result);
+ }
+
+ /* Shrink DB file size by actually wiping out SMS_4 table data */
+ result = dbi_conn_query(conn, "VACUUM");
+ if (!result)
+ LOGP(DDB, LOGL_ERROR,
+ "VACUUM failed. Ignoring it (upgrade from rev 4).\n");
+ else
+ dbi_result_free(result);
+
+ return 0;
+
+rollback:
+ result = dbi_conn_query(conn, "ROLLBACK TRANSACTION");
+ if (!result)
+ LOGP(DDB, LOGL_ERROR,
+ "Rollback failed (upgrade from rev 4).\n");
+ else
+ dbi_result_free(result);
+ return -EINVAL;
+}
+
static int check_db_revision(void)
{
dbi_result result;
@@ -420,6 +568,9 @@
goto error;
case 3:
if (update_db_revision_3())
+ goto error;
+ case 4:
+ if (update_db_revision_4())
goto error;
/* The end of waterfall */
@@ -546,20 +697,23 @@
result = dbi_conn_queryf(conn,
"INSERT INTO SMS "
"(created, valid_until, "
- "reply_path_req, status_rep_req, protocol_id, "
- "data_coding_scheme, ud_hdr_ind, "
+ "reply_path_req, status_rep_req, is_report, "
+ "msg_ref, protocol_id, data_coding_scheme, "
+ "ud_hdr_ind, "
"user_data, text, "
"dest_addr, dest_ton, dest_npi, "
"src_addr, src_ton, src_npi) VALUES "
"(datetime('now'), %u, "
"%u, %u, %u, "
- "%u, %u, "
+ "%u, %u, %u, "
+ "%u, "
"%s, %s, "
"%s, %u, %u, "
"%s, %u, %u)",
validity_timestamp,
- sms->reply_path_req, sms->status_rep_req, sms->protocol_id,
- sms->data_coding_scheme, sms->ud_hdr_ind,
+ sms->reply_path_req, sms->status_rep_req, sms->is_report,
+ sms->msg_ref, sms->protocol_id, sms->data_coding_scheme,
+ sms->ud_hdr_ind,
q_udata, q_text,
q_daddr, sms->dst.ton, sms->dst.npi,
q_saddr, sms->src.ton, sms->src.npi);
@@ -588,13 +742,15 @@
/* FIXME: validity */
/* FIXME: those should all be get_uchar, but sqlite3 is braindead */
+ sms->created = dbi_result_get_datetime(result, "created");
sms->reply_path_req = dbi_result_get_ulonglong(result, "reply_path_req");
sms->status_rep_req = dbi_result_get_ulonglong(result, "status_rep_req");
+ sms->is_report = dbi_result_get_ulonglong(result, "is_report");
+ sms->msg_ref = dbi_result_get_ulonglong(result, "msg_ref");
sms->ud_hdr_ind = dbi_result_get_ulonglong(result, "ud_hdr_ind");
sms->protocol_id = dbi_result_get_ulonglong(result, "protocol_id");
sms->data_coding_scheme = dbi_result_get_ulonglong(result,
"data_coding_scheme");
- /* sms->msg_ref is temporary and not stored in DB */
sms->dst.npi = dbi_result_get_ulonglong(result, "dest_npi");
sms->dst.ton = dbi_result_get_ulonglong(result, "dest_ton");
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index d97bde2..28cba5b 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -43,6 +43,7 @@
#include <openbsc/gsm_04_11.h>
#include <openbsc/gsm_04_08.h>
#include <openbsc/gsm_04_80.h>
+#include <openbsc/gsm_04_14.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/paging.h>
@@ -496,12 +497,19 @@
else {
/* Need to get GSM offset and convert into 15 min units */
/* This probably breaks if gmtoff returns a value not evenly divisible by 15? */
- local_time = localtime(&cur_t);
#ifdef HAVE_TM_GMTOFF_IN_TM
+ local_time = localtime(&cur_t);
tzunits = (local_time->tm_gmtoff/60)/15;
#else
-#warning find a portable way to obtain the timezone offset
- tzunits = 0;
+ /* find timezone offset */
+ time_t utc;
+ double offsetFromUTC;
+ utc = mktime(gmt_time);
+ local_time = localtime(&cur_t);
+ offsetFromUTC = difftime(cur_t, utc);
+ if (local_time->tm_isdst)
+ offsetFromUTC += 3600.0;
+ tzunits = ((int)offsetFromUTC) / 60 / 15;
#endif
if (tzunits < 0) {
tzunits = tzunits/-1;
@@ -3072,6 +3080,9 @@
case GSM48_PDISC_NC_SS:
rc = handle_rcv_ussd(conn, msg);
break;
+ case GSM48_PDISC_TEST:
+ rc = gsm0414_rcv_test(conn, msg);
+ break;
default:
LOGP(DRLL, LOGL_NOTICE, "Unknown "
"GSM 04.08 discriminator 0x%02x\n", pdisc);
diff --git a/src/libmsc/gsm_04_11.c b/src/libmsc/gsm_04_11.c
index bdf2ad7..c5bcce7 100644
--- a/src/libmsc/gsm_04_11.c
+++ b/src/libmsc/gsm_04_11.c
@@ -189,7 +189,7 @@
return gsm411_smc_send(&trans->sms.smc_inst, msg_type, msg);
}
-static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
+static int gsm340_rx_sms_submit(struct gsm_sms *gsms)
{
if (db_sms_store(gsms) != 0) {
LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
@@ -215,9 +215,9 @@
{
uint8_t *smsp;
uint8_t oa[12]; /* max len per 03.40 */
- uint8_t oa_len = 0;
uint8_t octet_len;
unsigned int old_msg_len = msg->len;
+ int oa_len;
/* generate first octet with masked bits */
smsp = msgb_put(msg, 1);
@@ -235,6 +235,9 @@
/* generate originator address */
oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
+ if (oa_len < 0)
+ return -ENOSPC;
+
smsp = msgb_put(msg, oa_len);
memcpy(smsp, oa, oa_len);
@@ -279,8 +282,55 @@
return msg->len - old_msg_len;
}
-int sms_route_mt_sms(struct gsm_subscriber_connection *conn, struct msgb *msg,
- struct gsm_sms *gsms, uint8_t sms_mti, bool *deferred)
+/* As defined by GSM 03.40, Section 9.2.2.3. */
+static int gsm340_gen_sms_status_report_tpdu(struct msgb *msg,
+ struct gsm_sms *sms)
+{
+ unsigned int old_msg_len = msg->len;
+ uint8_t oa[12]; /* max len per 03.40 */
+ uint8_t *smsp;
+ int oa_len;
+
+ /* generate first octet with masked bits */
+ smsp = msgb_put(msg, 1);
+ /* TP-MTI (message type indicator) */
+ *smsp = GSM340_SMS_STATUS_REP_SC2MS;
+ /* TP-MMS (more messages to send) */
+ if (0 /* FIXME */)
+ *smsp |= 0x04;
+ /* TP-MR (message reference) */
+ smsp = msgb_put(msg, 1);
+ *smsp = sms->msg_ref;
+
+ /* generate recipient address */
+ oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
+ if (oa_len < 0)
+ return -ENOSPC;
+
+ smsp = msgb_put(msg, oa_len);
+ memcpy(smsp, oa, oa_len);
+
+ /* generate TP-SCTS (Service centre timestamp) */
+ smsp = msgb_put(msg, 7);
+ gsm340_gen_scts(smsp, sms->created);
+
+ /* generate TP-DT (Discharge time, in TP-SCTS format). */
+ smsp = msgb_put(msg, 7);
+ gsm340_gen_scts(smsp, sms->created);
+
+ /* TP-ST (status) */
+ smsp = msgb_put(msg, 1);
+ /* From GSM 03.40, Section 9.2.3.15, 0x00 means OK. */
+ *smsp = 0x00;
+
+ LOGP(DLSMS, LOGL_INFO, "sending status report for SMS reference %x\n",
+ sms->msg_ref);
+
+ return msg->len - old_msg_len;
+}
+
+static int sms_route_mt_sms(struct gsm_subscriber_connection *conn,
+ struct gsm_sms *gsms)
{
int rc;
@@ -294,8 +344,9 @@
* delivery of the SMS.
*/
if (smpp_first) {
- rc = smpp_try_deliver(gsms, conn, deferred);
+ rc = smpp_try_deliver(gsms, conn);
if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED)
+ /* unknown subscriber, try local */
goto try_local;
if (rc < 0) {
LOGP(DLSMS, LOGL_ERROR, "%s: SMS delivery error: %d.",
@@ -322,7 +373,7 @@
return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
}
- rc = smpp_try_deliver(gsms, conn, deferred);
+ rc = smpp_try_deliver(gsms, conn);
if (rc == GSM411_RP_CAUSE_MO_NUM_UNASSIGNED) {
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
} else if (rc < 0) {
@@ -337,27 +388,7 @@
rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
rate_ctr_inc(&conn->network->msc_ctrs->ctr[MSC_CTR_SMS_NO_RECEIVER]);
#endif
- return rc;
}
-
- switch (sms_mti) {
- case GSM340_SMS_SUBMIT_MS2SC:
- /* MS is submitting a SMS */
- rc = gsm340_rx_sms_submit(msg, gsms);
- break;
- case GSM340_SMS_COMMAND_MS2SC:
- case GSM340_SMS_DELIVER_REP_MS2SC:
- LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
- rc = GSM411_RP_CAUSE_IE_NOTEXIST;
- break;
- default:
- LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
- rc = GSM411_RP_CAUSE_IE_NOTEXIST;
- break;
- }
-
- if (!rc && !gsms->receiver)
- rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
return rc;
}
@@ -366,7 +397,7 @@
/* process an incoming TPDU (called from RP-DATA)
* return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
static int gsm340_rx_tpdu(struct gsm_trans *trans, struct msgb *msg,
- uint32_t gsm411_msg_ref, bool *deferred)
+ uint32_t gsm411_msg_ref)
{
struct gsm_subscriber_connection *conn = trans->conn;
uint8_t *smsp = msgb_sms(msg);
@@ -387,7 +418,7 @@
/* invert those fields where 0 means active/present */
sms_mti = *smsp & 0x03;
sms_vpf = (*smsp & 0x18) >> 3;
- gsms->status_rep_req = (*smsp & 0x20);
+ gsms->status_rep_req = (*smsp & 0x20) >> 5;
gsms->ud_hdr_ind = (*smsp & 0x40);
/*
* Not evaluating MMS (More Messages to Send) because the
@@ -487,10 +518,29 @@
/* FIXME: This looks very wrong */
send_signal(0, NULL, gsms, 0);
- rc = sms_route_mt_sms(conn, msg, gsms, sms_mti, deferred);
+ rc = sms_route_mt_sms(conn, gsms);
+
+ /* This SMS got routed through SMPP or no receiver exists. */
+ if (!gsms->receiver)
+ return rc;
+
+ switch (sms_mti) {
+ case GSM340_SMS_SUBMIT_MS2SC:
+ /* MS is submitting a SMS */
+ rc = gsm340_rx_sms_submit(gsms);
+ break;
+ case GSM340_SMS_COMMAND_MS2SC:
+ case GSM340_SMS_DELIVER_REP_MS2SC:
+ LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
+ break;
+ default:
+ LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
+ rc = GSM411_RP_CAUSE_IE_NOTEXIST;
+ break;
+ }
out:
- if (!deferred)
- sms_free(gsms);
+ sms_free(gsms);
return rc;
}
@@ -543,7 +593,6 @@
uint8_t dst_len, uint8_t *dst,
uint8_t tpdu_len, uint8_t *tpdu)
{
- bool deferred = false;
int rc = 0;
if (src_len && src)
@@ -560,8 +609,8 @@
DEBUGP(DLSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
- rc = gsm340_rx_tpdu(trans, msg, rph->msg_ref, &deferred);
- if (rc == 0 && !deferred)
+ rc = gsm340_rx_tpdu(trans, msg, rph->msg_ref);
+ if (rc == 0)
return gsm411_send_rp_ack(trans, rph->msg_ref);
else if (rc > 0)
return gsm411_send_rp_error(trans, rph->msg_ref, rc);
@@ -595,6 +644,62 @@
rpud_len, rp_ud);
}
+static struct gsm_sms *sms_report_alloc(struct gsm_sms *sms)
+{
+ struct gsm_sms *sms_report;
+ int len;
+
+ sms_report = sms_alloc();
+ OSMO_ASSERT(sms_report);
+
+ sms_report->msg_ref = sms->msg_ref;
+ sms_report->protocol_id = sms->protocol_id;
+ sms_report->data_coding_scheme = GSM338_DCS_1111_8BIT_DATA;
+
+ /* Invert address to send status report back to origin. */
+ sms_report->src = sms->dst;
+ sms_report->dst = sms->src;
+
+ /* As specified by Appendix B. Delivery Receipt Format.
+ * TODO: Many fields in this string are just set with dummy values,
+ * revisit this.
+ */
+ len = snprintf((char *)sms_report->user_data,
+ sizeof(sms_report->user_data),
+ "id:%.08llu sub:000 dlvrd:000 submit date:YYMMDDhhmm done date:YYMMDDhhmm stat:DELIVRD err:000 text:%.20s",
+ sms->id, sms->text);
+ sms_report->user_data_len = len;
+ LOGP(DLSMS, LOGL_NOTICE, "%s\n", sms_report->user_data);
+
+ /* This represents a sms report. */
+ sms_report->is_report = true;
+
+ return sms_report;
+}
+
+static void sms_status_report(struct gsm_sms *gsms,
+ struct gsm_subscriber_connection *conn)
+{
+ struct gsm_sms *sms_report;
+ int rc;
+
+ sms_report = sms_report_alloc(gsms);
+
+ rc = sms_route_mt_sms(conn, sms_report);
+ if (rc < 0) {
+ LOGP(DLSMS, LOGL_ERROR,
+ "Failed to send status report! err=%d\n", rc);
+ }
+
+ /* No route via SMPP, send the GSM 03.40 status-report now. */
+ if (gsms->receiver)
+ gsm340_rx_sms_submit(sms_report);
+
+ LOGP(DLSMS, LOGL_NOTICE, "Status report has been sent\n");
+
+ sms_free(sms_report);
+}
+
/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
@@ -615,6 +720,9 @@
db_sms_mark_delivered(sms);
send_signal(S_SMS_DELIVERED, trans, sms, 0);
+
+ if (sms->status_rep_req)
+ sms_status_report(sms, trans->conn);
sms_free(sms);
trans->sms.sms = NULL;
@@ -940,8 +1048,13 @@
/* obtain a pointer for the rp_ud_len, so we can fill it later */
rp_ud_len = (uint8_t *)msgb_put(msg, 1);
- /* generate the 03.40 SMS-DELIVER TPDU */
- rc = gsm340_gen_sms_deliver_tpdu(msg, sms);
+ if (sms->is_report) {
+ /* generate the 03.40 SMS-STATUS-REPORT TPDU */
+ rc = gsm340_gen_sms_status_report_tpdu(msg, sms);
+ } else {
+ /* generate the 03.40 SMS-DELIVER TPDU */
+ rc = gsm340_gen_sms_deliver_tpdu(msg, sms);
+ }
if (rc < 0) {
send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
sms_free(sms);
diff --git a/src/libmsc/gsm_04_14.c b/src/libmsc/gsm_04_14.c
new file mode 100644
index 0000000..b529f4c
--- /dev/null
+++ b/src/libmsc/gsm_04_14.c
@@ -0,0 +1,133 @@
+/* GSM MS Testing Layer 3 messages
+ * 3GPP TS 44.014 / GSM TS 04.14 */
+
+/* (C) 2017 by Harald Welte <laforge at gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "bscconfig.h"
+
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/gsm_04_08.h>
+#include <openbsc/bsc_api.h>
+#include <openbsc/msc_ifaces.h>
+
+#include <osmocom/gsm/gsm48.h>
+#include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/gsm/protocol/gsm_04_14.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+
+static struct msgb *create_gsm0414_msg(uint8_t msg_type)
+{
+ struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.14");
+ struct gsm48_hdr *gh;
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+ gh->proto_discr = GSM48_PDISC_TEST;
+ gh->msg_type = msg_type;
+ return msg;
+}
+
+static int gsm0414_conn_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg)
+{
+ return msc_tx_dtap(conn, msg);
+}
+
+static int gsm0414_tx_simple(struct gsm_subscriber_connection *conn, uint8_t msg_type)
+{
+ struct msgb *msg = create_gsm0414_msg(msg_type);
+
+ return gsm0414_conn_sendmsg(conn, msg);
+}
+
+
+/* Send a CLOSE_TCH_LOOOP_CMD according to Section 8.1 */
+int gsm0414_tx_close_tch_loop_cmd(struct gsm_subscriber_connection *conn,
+ enum gsm414_tch_loop_mode loop_mode)
+{
+ struct msgb *msg = create_gsm0414_msg(GSM414_MT_CLOSE_TCH_LOOP_CMD);
+ uint8_t subch;
+
+ subch = (loop_mode << 1);
+ msgb_put_u8(msg, subch);
+
+ msg->lchan = conn->lchan;
+ return gsm0414_conn_sendmsg(conn, msg);
+}
+
+/* Send a OPEN_LOOP_CMD according to Section 8.3 */
+int gsm0414_tx_open_loop_cmd(struct gsm_subscriber_connection *conn)
+{
+ return gsm0414_tx_simple(conn, GSM414_MT_OPEN_LOOP_CMD);
+}
+
+/* Send a ACT_EMMI_CMD according to Section 8.8 */
+int gsm0414_tx_act_emmi_cmd(struct gsm_subscriber_connection *conn)
+{
+ return gsm0414_tx_simple(conn, GSM414_MT_ACT_EMMI_CMD);
+}
+
+/* Send a DEACT_EMMI_CMD according to Section 8.10 */
+int gsm0414_tx_deact_emmi_cmd(struct gsm_subscriber_connection *conn)
+{
+ return gsm0414_tx_simple(conn, GSM414_MT_DEACT_EMMI_CMD);
+}
+
+/* Send a TEST_INTERFACE according to Section 8.11 */
+int gsm0414_tx_test_interface(struct gsm_subscriber_connection *conn,
+ uint8_t tested_devs)
+{
+ struct msgb *msg = create_gsm0414_msg(GSM414_MT_TEST_INTERFACE);
+ msgb_put_u8(msg, tested_devs);
+ return gsm0414_conn_sendmsg(conn, msg);
+}
+
+/* Send a RESET_MS_POSITION_STORED according to Section 8.11 */
+int gsm0414_tx_reset_ms_pos_store(struct gsm_subscriber_connection *conn,
+ uint8_t technology)
+{
+ struct msgb *msg = create_gsm0414_msg(GSM414_MT_RESET_MS_POS_STORED);
+ msgb_put_u8(msg, technology);
+ return gsm0414_conn_sendmsg(conn, msg);
+}
+
+
+
+/* Entry point for incoming GSM48_PDISC_TEST received from MS */
+int gsm0414_rcv_test(struct gsm_subscriber_connection *conn,
+ struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+
+ if (msgb_l3len(msg) < sizeof(*gh))
+ return -1;
+
+ LOGP(DMM, LOGL_NOTICE, "%s: Received TEST class message '%s'\n", "FIXME",
+ get_value_string(gsm414_msgt_names, gh->msg_type));
+
+ return 0;
+}
diff --git a/src/libmsc/smpp_openbsc.c b/src/libmsc/smpp_openbsc.c
index 24a4653..431cb4d 100644
--- a/src/libmsc/smpp_openbsc.c
+++ b/src/libmsc/smpp_openbsc.c
@@ -73,27 +73,32 @@
return vsub;
}
-/*! \brief find a TLV with given tag in list of libsmpp34 TLVs */
-static struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag)
+static int smpp34_submit_tlv_msg_payload(const struct tlv_t *t,
+ const struct submit_sm_t *submit,
+ const uint8_t **sms_msg,
+ unsigned int *sms_msg_len)
{
- struct tlv_t *t;
-
- for (t = head; t != NULL; t = t->next) {
- if (t->tag == tag)
- return t;
+ if (submit->sm_length) {
+ LOGP(DLSMS, LOGL_ERROR,
+ "SMPP cannot have payload in TLV _and_ in the header\n");
+ return -1;
}
- return NULL;
+ *sms_msg = t->value.octet;
+ *sms_msg_len = t->length;
+
+ return 0;
}
/*! \brief convert from submit_sm_t to gsm_sms */
static int submit_to_sms(struct gsm_sms **psms, struct gsm_network *net,
const struct submit_sm_t *submit)
{
+ const uint8_t *sms_msg = NULL;
+ unsigned int sms_msg_len = 0;
struct vlr_subscr *dest;
+ uint16_t msg_ref = 0;
struct gsm_sms *sms;
struct tlv_t *t;
- const uint8_t *sms_msg;
- unsigned int sms_msg_len;
int mode;
dest = subscr_by_dst(net, submit->dest_addr_npi,
@@ -106,30 +111,40 @@
return ESME_RINVDSTADR;
}
- t = find_tlv(submit->tlv, TLVID_message_payload);
- if (t) {
- if (submit->sm_length) {
- /* ERROR: we cannot have both! */
- LOGP(DLSMS, LOGL_ERROR, "SMPP Cannot have payload in "
- "TLV _and_ in the header\n");
- vlr_subscr_put(dest);
- return ESME_ROPTPARNOTALLWD;
+ smpp34_tlv_for_each(t, submit->tlv) {
+ switch (t->tag) {
+ case TLVID_message_payload:
+ if (smpp34_submit_tlv_msg_payload(t, submit, &sms_msg,
+ &sms_msg_len) < 0) {
+ vlr_subscr_put(dest);
+ return ESME_ROPTPARNOTALLWD;
+ }
+ break;
+ case TLVID_user_message_reference:
+ msg_ref = t->value.val16;
+ break;
+ default:
+ break;
}
- sms_msg = t->value.octet;
- sms_msg_len = t->length;
- } else if (submit->sm_length > 0 && submit->sm_length < 255) {
- sms_msg = submit->short_message;
- sms_msg_len = submit->sm_length;
- } else {
- LOGP(DLSMS, LOGL_ERROR,
- "SMPP neither message payload nor valid sm_length.\n");
- vlr_subscr_put(dest);
- return ESME_RINVPARLEN;
+ }
+
+ if (!sms_msg) {
+ if (submit->sm_length > 0 && submit->sm_length < 255) {
+ sms_msg = submit->short_message;
+ sms_msg_len = submit->sm_length;
+ } else {
+ LOGP(DLSMS, LOGL_ERROR,
+ "SMPP neither message payload nor valid sm_length.\n");
+ vlr_subscr_put(dest);
+ return ESME_RINVPARLEN;
+ }
}
sms = sms_alloc();
sms->source = SMS_SOURCE_SMPP;
sms->smpp.sequence_nr = submit->sequence_number;
+ sms->status_rep_req = submit->registered_delivery;
+ sms->msg_ref = msg_ref;
/* fill in the destination address */
sms->receiver = dest;
@@ -143,10 +158,13 @@
osmo_strlcpy(sms->src.addr, (char *)submit->source_addr,
sizeof(sms->src.addr));
- if (submit->esm_class & 0x40)
+ if (submit->esm_class == SMPP34_DELIVERY_ACK)
+ sms->is_report = true;
+
+ if (submit->esm_class & SMPP34_UDHI_IND)
sms->ud_hdr_ind = 1;
- if (submit->esm_class & 0x80) {
+ if (submit->esm_class & SMPP34_REPLY_PATH) {
sms->reply_path_req = 1;
#warning Implement reply path
}
@@ -222,7 +240,7 @@
sms->smpp.esme = esme;
sms->protocol_id = submit->protocol_id;
- switch (submit->esm_class & 3) {
+ switch (submit->esm_class & SMPP34_MSG_MODE_MASK) {
case 0: /* default */
case 1: /* datagram */
case 3: /* store-and-forward */
@@ -419,7 +437,7 @@
memset(&tlv, 0, sizeof(tlv));
tlv.tag = tag;
tlv.length = 2;
- tlv.value.val16 = htons(val);
+ tlv.value.val16 = val;
build_tlv(req_tlv, &tlv);
}
@@ -501,7 +519,6 @@
osmo_timer_del(&cmd->response_timer);
llist_del(&cmd->list);
vlr_subscr_put(cmd->vsub);
- sms_free(cmd->sms);
talloc_free(cmd);
}
@@ -518,21 +535,24 @@
struct gsm_subscriber_connection *conn;
struct gsm_trans *trans;
+ if (cmd->is_report)
+ goto out;
+
conn = connection_for_subscr(cmd->vsub);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
- return;
+ goto out;
}
- trans = trans_find_by_id(conn, GSM48_PDISC_SMS,
- cmd->sms->gsm411.transaction_id);
+ trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
if (!trans) {
LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
- cmd->sms->gsm411.transaction_id);
- return;
+ cmd->gsm411_trans_id);
+ goto out;
}
- gsm411_send_rp_ack(trans, cmd->sms->gsm411.msg_ref);
+ gsm411_send_rp_ack(trans, cmd->gsm411_msg_ref);
+out:
smpp_cmd_free(cmd);
}
@@ -542,25 +562,27 @@
struct gsm_trans *trans;
int gsm411_cause;
+ if (cmd->is_report)
+ goto out;
+
conn = connection_for_subscr(cmd->vsub);
if (!conn) {
LOGP(DSMPP, LOGL_ERROR, "No connection to subscriber anymore\n");
- return;
+ goto out;
}
- trans = trans_find_by_id(conn, GSM48_PDISC_SMS,
- cmd->sms->gsm411.transaction_id);
+ trans = trans_find_by_id(conn, GSM48_PDISC_SMS, cmd->gsm411_trans_id);
if (!trans) {
LOGP(DSMPP, LOGL_ERROR, "GSM transaction %u is gone\n",
- cmd->sms->gsm411.transaction_id);
- return;
+ cmd->gsm411_trans_id);
+ goto out;
}
if (smpp_to_gsm411_err(status, &gsm411_cause) < 0)
gsm411_cause = GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
- gsm411_send_rp_error(trans, cmd->sms->gsm411.msg_ref, gsm411_cause);
-
+ gsm411_send_rp_error(trans, cmd->gsm411_msg_ref, gsm411_cause);
+out:
smpp_cmd_free(cmd);
}
@@ -571,7 +593,7 @@
static int smpp_cmd_enqueue(struct osmo_esme *esme,
struct vlr_subscr *vsub, struct gsm_sms *sms,
- uint32_t sequence_number, bool *deferred)
+ uint32_t sequence_number)
{
struct osmo_smpp_cmd *cmd;
@@ -580,7 +602,9 @@
return -1;
cmd->sequence_nr = sequence_number;
- cmd->sms = sms;
+ cmd->is_report = sms->is_report;
+ cmd->gsm411_msg_ref = sms->gsm411.msg_ref;
+ cmd->gsm411_trans_id = sms->gsm411.transaction_id;
cmd->vsub = vlr_subscr_get(vsub);
/* FIXME: No predefined value for this response_timer as specified by
@@ -591,7 +615,6 @@
osmo_timer_setup(&cmd->response_timer, smpp_deliver_sm_cb, cmd);
osmo_timer_schedule(&cmd->response_timer, 5, 0);
llist_add_tail(&cmd->list, &esme->smpp_cmd_list);
- *deferred = true;
return 0;
}
@@ -609,8 +632,7 @@
}
static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
- struct gsm_subscriber_connection *conn,
- bool *deferred)
+ struct gsm_subscriber_connection *conn)
{
struct deliver_sm_t deliver;
int mode, ret;
@@ -641,15 +663,20 @@
memcpy(deliver.destination_addr, sms->dst.addr,
sizeof(deliver.destination_addr));
- deliver.esm_class = 1; /* datagram mode */
+ if (sms->is_report)
+ deliver.esm_class = SMPP34_DELIVERY_RECEIPT;
+ else
+ deliver.esm_class = SMPP34_DATAGRAM_MODE;
+
if (sms->ud_hdr_ind)
- deliver.esm_class |= 0x40;
+ deliver.esm_class |= SMPP34_UDHI_IND;
if (sms->reply_path_req)
- deliver.esm_class |= 0x80;
+ deliver.esm_class |= SMPP34_REPLY_PATH;
deliver.protocol_id = sms->protocol_id;
deliver.priority_flag = 0;
- deliver.registered_delivery = 0;
+ if (sms->status_rep_req)
+ deliver.registered_delivery = SMPP34_DELIVERY_RECEIPT_ON;
/* Figure out SMPP DCS from TP-DCS */
dcs = sms->data_coding_scheme;
@@ -679,8 +706,6 @@
} else {
deliver.sm_length = sms->user_data_len;
memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
- deliver.sm_length = sms->user_data_len;
- memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
}
#if BEFORE_MSCSPLIT
@@ -689,12 +714,15 @@
append_osmo_tlvs(&deliver.tlv, conn->lchan);
#endif
+ append_tlv_u16(&deliver.tlv, TLVID_user_message_reference,
+ sms->msg_ref);
+
ret = smpp_tx_deliver(esme, &deliver);
if (ret < 0)
return ret;
return smpp_cmd_enqueue(esme, conn->vsub, sms,
- deliver.sequence_number, deferred);
+ deliver.sequence_number);
}
static struct smsc *g_smsc;
@@ -705,21 +733,22 @@
}
int smpp_try_deliver(struct gsm_sms *sms,
- struct gsm_subscriber_connection *conn, bool *deferred)
+ struct gsm_subscriber_connection *conn)
{
struct osmo_esme *esme;
struct osmo_smpp_addr dst;
+ int rc;
memset(&dst, 0, sizeof(dst));
dst.ton = sms->dst.ton;
dst.npi = sms->dst.npi;
memcpy(dst.addr, sms->dst.addr, sizeof(dst.addr));
- esme = smpp_route(g_smsc, &dst);
- if (!esme)
- return GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
+ rc = smpp_route(g_smsc, &dst, &esme);
+ if (!rc)
+ rc = deliver_to_esme(esme, sms, conn);
- return deliver_to_esme(esme, sms, conn, deferred);
+ return rc;
}
struct smsc *smsc_from_vty(struct vty *v)
diff --git a/src/libmsc/smpp_smsc.c b/src/libmsc/smpp_smsc.c
index 48a1192..04afc49 100644
--- a/src/libmsc/smpp_smsc.c
+++ b/src/libmsc/smpp_smsc.c
@@ -270,8 +270,7 @@
}
/*! \brief try to find a SMPP route (ESME) for given destination */
-struct osmo_esme *
-smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest)
+int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **pesme)
{
struct osmo_smpp_route *r;
struct osmo_smpp_acl *acl = NULL;
@@ -314,15 +313,20 @@
struct osmo_esme *esme;
DEBUGP(DSMPP, "ACL even has ESME, we can route to it!\n");
esme = acl->esme;
- if (esme->bind_flags & ESME_BIND_RX)
- return esme;
- else
+ if (esme->bind_flags & ESME_BIND_RX) {
+ *pesme = esme;
+ return 0;
+ } else
LOGP(DSMPP, LOGL_NOTICE, "[%s] is matching route, "
"but not bound for Rx, discarding MO SMS\n",
esme->system_id);
}
- return NULL;
+ *pesme = NULL;
+ if (acl)
+ return GSM48_CC_CAUSE_NETWORK_OOO;
+ else
+ return GSM48_CC_CAUSE_UNASSIGNED_NR;
}
@@ -654,6 +658,9 @@
{
deliver->sequence_number = esme_inc_seq_nr(esme);
+ LOGP(DSMPP, LOGL_DEBUG, "[%s] Tx DELIVER-SM (from %s)\n",
+ esme->system_id, deliver->source_addr);
+
return PACK_AND_SEND(esme, deliver);
}
diff --git a/src/libmsc/smpp_smsc.h b/src/libmsc/smpp_smsc.h
index 4bee59b..755e685 100644
--- a/src/libmsc/smpp_smsc.h
+++ b/src/libmsc/smpp_smsc.h
@@ -89,8 +89,10 @@
struct osmo_smpp_cmd {
struct llist_head list;
struct vlr_subscr *vsub;
- struct gsm_sms *sms;
uint32_t sequence_nr;
+ uint32_t gsm411_msg_ref;
+ uint8_t gsm411_trans_id;
+ bool is_report;
struct osmo_timer_list response_timer;
};
@@ -126,8 +128,7 @@
void smpp_esme_get(struct osmo_esme *esme);
void smpp_esme_put(struct osmo_esme *esme);
-struct osmo_esme *
-smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest);
+int smpp_route(const struct smsc *smsc, const struct osmo_smpp_addr *dest, struct osmo_esme **emse);
struct osmo_smpp_acl *smpp_acl_alloc(struct smsc *smsc, const char *sys_id);
struct osmo_smpp_acl *smpp_acl_by_system_id(struct smsc *smsc,
@@ -162,5 +163,5 @@
int smpp_route_smpp_first(struct gsm_sms *sms,
struct gsm_subscriber_connection *conn);
int smpp_try_deliver(struct gsm_sms *sms,
- struct gsm_subscriber_connection *conn, bool *deferred);
+ struct gsm_subscriber_connection *conn);
#endif
diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c
index 7289a8f..28e0914 100644
--- a/src/libmsc/transaction.c
+++ b/src/libmsc/transaction.c
@@ -88,6 +88,13 @@
DEBUGP(DCC, "subscr=%p, net=%p\n", vsub, net);
+ /* a valid subscriber is indispensable */
+ if (vsub == NULL) {
+ LOGP(DCC, LOGL_NOTICE,
+ "unable to alloc transaction, invalid subscriber (NULL)\n");
+ return NULL;
+ }
+
trans = talloc_zero(tall_trans_ctx, struct gsm_trans);
if (!trans)
return NULL;
diff --git a/src/libmsc/vty_interface_layer3.c b/src/libmsc/vty_interface_layer3.c
index d1bf6b3..864597d 100644
--- a/src/libmsc/vty_interface_layer3.c
+++ b/src/libmsc/vty_interface_layer3.c
@@ -46,6 +46,7 @@
#include <openbsc/debug.h>
#include <openbsc/vty.h>
#include <openbsc/gsm_04_80.h>
+#include <openbsc/gsm_04_14.h>
#include <openbsc/chan_alloc.h>
#include <openbsc/sms_queue.h>
#include <openbsc/mncc_int.h>
@@ -473,6 +474,97 @@
return CMD_SUCCESS;
}
+static int loop_by_char(uint8_t ch)
+{
+ switch (ch) {
+ case 'a':
+ return GSM414_LOOP_A;
+ case 'b':
+ return GSM414_LOOP_B;
+ case 'c':
+ return GSM414_LOOP_C;
+ case 'd':
+ return GSM414_LOOP_D;
+ case 'e':
+ return GSM414_LOOP_E;
+ case 'f':
+ return GSM414_LOOP_F;
+ case 'i':
+ return GSM414_LOOP_I;
+ }
+ return -1;
+}
+
+DEFUN(subscriber_mstest_close,
+ subscriber_mstest_close_cmd,
+ "subscriber " SUBSCR_TYPES " ID ms-test close-loop (a|b|c|d|e|f|i)",
+ SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
+ "Close a TCH Loop inside the MS\n"
+ "Loop Type A\n"
+ "Loop Type B\n"
+ "Loop Type C\n"
+ "Loop Type D\n"
+ "Loop Type E\n"
+ "Loop Type F\n"
+ "Loop Type I\n")
+{
+ struct gsm_subscriber_connection *conn;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
+ const char *loop_str;
+ int loop_mode;
+
+ if (!vsub) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ loop_str = argv[2];
+ loop_mode = loop_by_char(loop_str[0]);
+
+ conn = connection_for_subscr(vsub);
+ if (!conn) {
+ vty_out(vty, "%% An active connection is required for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ vlr_subscr_put(vsub);
+ return CMD_WARNING;
+ }
+
+ gsm0414_tx_close_tch_loop_cmd(conn, loop_mode);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(subscriber_mstest_open,
+ subscriber_mstest_open_cmd,
+ "subscriber " SUBSCR_TYPES " ID ms-test open-loop",
+ SUBSCR_HELP "Send a TS 04.14 MS Test Command to subscriber\n"
+ "Open a TCH Loop inside the MS\n")
+{
+ struct gsm_subscriber_connection *conn;
+ struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ struct vlr_subscr *vsub = get_vsub_by_argv(gsmnet, argv[0], argv[1]);
+
+ if (!vsub) {
+ vty_out(vty, "%% No subscriber found for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ conn = connection_for_subscr(vsub);
+ if (!conn) {
+ vty_out(vty, "%% An active connection is required for %s %s%s",
+ argv[0], argv[1], VTY_NEWLINE);
+ vlr_subscr_put(vsub);
+ return CMD_WARNING;
+ }
+
+ gsm0414_tx_open_loop_cmd(conn);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(ena_subscr_expire,
ena_subscr_expire_cmd,
"subscriber " SUBSCR_TYPES " ID expire",
@@ -570,11 +662,11 @@
VTY_NEWLINE);
vty_out(vty, "Handover : %lu attempted, %lu no_channel, %lu timeout, "
"%lu completed, %lu failed%s",
- net->msc_ctrs->ctr[BSC_CTR_HANDOVER_ATTEMPTED].current,
- net->msc_ctrs->ctr[BSC_CTR_HANDOVER_NO_CHANNEL].current,
- net->msc_ctrs->ctr[BSC_CTR_HANDOVER_TIMEOUT].current,
- net->msc_ctrs->ctr[BSC_CTR_HANDOVER_COMPLETED].current,
- net->msc_ctrs->ctr[BSC_CTR_HANDOVER_FAILED].current,
+ net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_ATTEMPTED].current,
+ net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_NO_CHANNEL].current,
+ net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_TIMEOUT].current,
+ net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_COMPLETED].current,
+ net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_FAILED].current,
VTY_NEWLINE);
vty_out(vty, "SMS MO : %lu submitted, %lu no receiver%s",
net->msc_ctrs->ctr[MSC_CTR_SMS_SUBMITTED].current,
@@ -851,6 +943,8 @@
install_element_ve(&subscriber_silent_call_start_cmd);
install_element_ve(&subscriber_silent_call_stop_cmd);
install_element_ve(&subscriber_ussd_notify_cmd);
+ install_element_ve(&subscriber_mstest_close_cmd);
+ install_element_ve(&subscriber_mstest_open_cmd);
install_element_ve(&subscriber_update_cmd);
install_element_ve(&show_stats_cmd);
install_element_ve(&show_smsqueue_cmd);
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index ee094d6..90651b9 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -162,6 +162,7 @@
switch (signal) {
case SIGINT:
+ case SIGTERM:
bsc_shutdown_net(bsc_gsmnet);
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(3);
@@ -280,6 +281,7 @@
}
signal(SIGINT, &signal_handler);
+ signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
diff --git a/src/osmo-msc/msc_main.c b/src/osmo-msc/msc_main.c
index 4166159..723c0e6 100644
--- a/src/osmo-msc/msc_main.c
+++ b/src/osmo-msc/msc_main.c
@@ -140,7 +140,6 @@
printf(" -c --config-file filename The config file to use.\n");
printf(" -s --disable-color\n");
printf(" -l --database db-name The database to use.\n");
- printf(" -a --authorize-everyone Authorize every new subscriber. Dangerous!\n");
printf(" -T --timestamp Prefix every log line with a timestamp.\n");
printf(" -V --version Print the version of OpenBSC.\n");
printf(" -P --rtp-proxy Enable the RTP Proxy code inside OpenBSC.\n");
@@ -163,7 +162,6 @@
{"config-file", 1, 0, 'c'},
{"disable-color", 0, 0, 's'},
{"database", 1, 0, 'l'},
- {"authorize-everyone", 0, 0, 'a'},
{"pcap", 1, 0, 'p'},
{"timestamp", 0, 0, 'T'},
{"version", 0, 0, 'V' },
@@ -268,6 +266,7 @@
switch (signal) {
case SIGINT:
+ case SIGTERM:
msc_network_shutdown(msc_network);
osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
sleep(3);
@@ -474,6 +473,7 @@
osmo_timer_schedule(&db_sync_timer, DB_SYNC_INTERVAL);
signal(SIGINT, &signal_handler);
+ signal(SIGTERM, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);
signal(SIGUSR2, &signal_handler);
diff --git a/src/utils/smpp_mirror.c b/src/utils/smpp_mirror.c
index 95df5f2..c570505 100644
--- a/src/utils/smpp_mirror.c
+++ b/src/utils/smpp_mirror.c
@@ -95,12 +95,23 @@
}
/* FIXME: merge with smpp_smsc.c */
+static struct tlv_t *find_tlv(struct tlv_t *head, uint16_t tag)
+{
+ struct tlv_t *t;
+
+ for (t = head; t != NULL; t = t->next) {
+ if (t->tag == tag)
+ return t;
+ }
+ return NULL;
+}
static int smpp_handle_deliver(struct esme *esme, struct msgb *msg)
{
struct deliver_sm_t deliver;
struct deliver_sm_resp_t deliver_r;
struct submit_sm_t submit;
+ tlv_t *t;
int rc;
memset(&deliver, 0, sizeof(deliver));
@@ -129,7 +140,15 @@
OSMO_MIN(sizeof(submit.source_addr),
sizeof(deliver.destination_addr)));
- submit.esm_class = deliver.esm_class;
+ /* Mirror delivery receipts as a delivery acknowledgements. */
+ if (deliver.esm_class == 0x04) {
+ LOGP(DSMPP, LOGL_DEBUG, "%s\n", deliver.short_message);
+ submit.esm_class = 0x08;
+ } else {
+ submit.esm_class = deliver.esm_class;
+ }
+
+ submit.registered_delivery = deliver.registered_delivery;
submit.protocol_id = deliver.protocol_id;
submit.priority_flag = deliver.priority_flag;
memcpy(submit.schedule_delivery_time, deliver.schedule_delivery_time,
@@ -146,7 +165,18 @@
memcpy(submit.short_message, deliver.short_message,
OSMO_MIN(sizeof(submit.short_message),
sizeof(deliver.short_message)));
- /* FIXME: TLV? */
+
+ /* FIXME: More TLV? */
+ t = find_tlv(deliver.tlv, TLVID_user_message_reference);
+ if (t) {
+ tlv_t tlv;
+
+ memset(&tlv, 0, sizeof(tlv));
+ tlv.tag = TLVID_user_message_reference;
+ tlv.length = 2;
+ tlv.value.val16 = t->value.val16;
+ build_tlv(&submit.tlv, &tlv);
+ }
return PACK_AND_SEND(esme, &submit);
}
diff --git a/tests/channel/channel_test.c b/tests/channel/channel_test.c
index f686969..beae658 100644
--- a/tests/channel/channel_test.c
+++ b/tests/channel/channel_test.c
@@ -31,6 +31,35 @@
#include <openbsc/gsm_subscriber.h>
#include <openbsc/vlr.h>
+void test_bts_debug_print(void)
+{
+ struct gsm_network *network;
+ struct gsm_bts *bts;
+ struct gsm_bts_trx *trx;
+
+ printf("Testing the lchan printing:");
+
+ /* Create a dummy network */
+ network = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
+ if (!network)
+ exit(1);
+ /* Add a BTS with some reasonanbly non-zero id */
+ bts = gsm_bts_alloc(network, 45);
+ /* Add a second TRX to test on multiple TRXs */
+ gsm_bts_trx_alloc(bts);
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ char *name = gsm_lchan_name(&trx->ts[3].lchan[4]);
+
+ if (name)
+ printf(" %s", name);
+ else
+ printf("NULL name");
+ }
+ printf("\n");
+}
+
+
void test_dyn_ts_subslots(void)
{
struct gsm_bts_trx_ts ts;
@@ -66,6 +95,7 @@
osmo_init_logging(&log_info);
test_dyn_ts_subslots();
+ test_bts_debug_print();
return EXIT_SUCCESS;
}
diff --git a/tests/channel/channel_test.ok b/tests/channel/channel_test.ok
index e4d625a..81d6569 100644
--- a/tests/channel/channel_test.ok
+++ b/tests/channel/channel_test.ok
@@ -1 +1,2 @@
Testing subslot numbers for pchan types
+Testing the lchan printing: (bts=45,trx=0,ts=3,ss=4) (bts=45,trx=1,ts=3,ss=4)
diff --git a/tests/db/db_test.err b/tests/db/db_test.err
index fa9a54c..27e5703 100644
--- a/tests/db/db_test.err
+++ b/tests/db/db_test.err
@@ -1,2 +1,3 @@
Going to migrate from revision 3
+[0;mGoing to migrate from revision 4
[0;m
\ No newline at end of file
diff --git a/tests/gprs/gprs_test.c b/tests/gprs/gprs_test.c
index ff77404..aac9bb8 100644
--- a/tests/gprs/gprs_test.c
+++ b/tests/gprs/gprs_test.c
@@ -48,101 +48,6 @@
ASSERT_FALSE(nu_is_retransmission(479, 511)); // wrapped
}
-static void apn_round_trip(const uint8_t *input, size_t len, const char *wanted_output)
-{
- char output[len ? len : 1];
- uint8_t encoded[len + 50];
- char *out_str;
- int enc_len;
-
- /* decode and verify we have what we want */
- out_str = gprs_apn_to_str(output, input, len);
- OSMO_ASSERT(out_str);
- OSMO_ASSERT(out_str == &output[0]);
- OSMO_ASSERT(strlen(out_str) == strlen(wanted_output));
- OSMO_ASSERT(strcmp(out_str, wanted_output) == 0);
-
- /* encode and verify it */
- if (len != 0) {
- enc_len = gprs_str_to_apn(encoded, ARRAY_SIZE(encoded), wanted_output);
- OSMO_ASSERT(enc_len == len);
- OSMO_ASSERT(memcmp(encoded, input, enc_len) == 0);
- } else {
- enc_len = gprs_str_to_apn(encoded, 0, wanted_output);
- OSMO_ASSERT(enc_len == -1);
- }
-}
-
-static void test_gsm_03_03_apn(void)
-{
-
- {
- /* test invalid writes */
- const uint8_t ref[10] = { 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF };
- uint8_t output[10];
- int enc_len;
-
- memcpy(output, ref, ARRAY_SIZE(output));
- enc_len = gprs_str_to_apn(output, 0, "");
- OSMO_ASSERT(enc_len == -1);
- OSMO_ASSERT(memcmp(ref, output, ARRAY_SIZE(ref)) == 0);
-
- memcpy(output, ref, ARRAY_SIZE(output));
- enc_len = gprs_str_to_apn(output, 0, "foo");
- OSMO_ASSERT(enc_len == -1);
- OSMO_ASSERT(memcmp(ref, output, ARRAY_SIZE(ref)) == 0);
-
- memcpy(output, ref, ARRAY_SIZE(output));
- enc_len = gprs_str_to_apn(output, 1, "foo");
- OSMO_ASSERT(enc_len == -1);
- OSMO_ASSERT(memcmp(ref + 1, output + 1, ARRAY_SIZE(ref) - 1) == 0);
-
- memcpy(output, ref, ARRAY_SIZE(output));
- enc_len = gprs_str_to_apn(output, 2, "foo");
- OSMO_ASSERT(enc_len == -1);
- OSMO_ASSERT(memcmp(ref + 2, output + 2, ARRAY_SIZE(ref) - 2) == 0);
-
- memcpy(output, ref, ARRAY_SIZE(output));
- enc_len = gprs_str_to_apn(output, 3, "foo");
- OSMO_ASSERT(enc_len == -1);
- OSMO_ASSERT(memcmp(ref + 3, output + 3, ARRAY_SIZE(ref) - 3) == 0);
- }
-
- {
- /* single empty label */
- uint8_t input[] = { 0x0 };
- const char *output = "";
- apn_round_trip(input, ARRAY_SIZE(input), output);
- }
-
- {
- /* no label */
- uint8_t input[] = { };
- const char *output = "";
- apn_round_trip(input, ARRAY_SIZE(input), output);
- }
-
- {
- /* single label with A */
- uint8_t input[] = { 0x1, 65 };
- const char *output = "A";
- apn_round_trip(input, ARRAY_SIZE(input), output);
- OSMO_ASSERT(gprs_apn_to_str(NULL, input, ARRAY_SIZE(input) - 1) == NULL);
- }
-
- {
- uint8_t input[] = { 0x3, 65, 66, 67, 0x2, 90, 122 };
- const char *output = "ABC.Zz";
- char tmp[strlen(output) + 1];
- apn_round_trip(input, ARRAY_SIZE(input), output);
- OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 1) == NULL);
- OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 2) == NULL);
- OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 4) == NULL);
- OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 5) == NULL);
- OSMO_ASSERT(gprs_apn_to_str(tmp, input, ARRAY_SIZE(input) - 6) == NULL);
- }
-}
-
static void test_gprs_timer_enc_dec(void)
{
int i, u, secs, tmr;
@@ -228,7 +133,6 @@
osmo_init_logging(&info);
test_8_4_2();
- test_gsm_03_03_apn();
test_gprs_timer_enc_dec();
printf("Done.\n");
diff --git a/tests/gsm0408/gsm0408_test.c b/tests/gsm0408/gsm0408_test.c
index 1b326ee..fcdc8f8 100644
--- a/tests/gsm0408/gsm0408_test.c
+++ b/tests/gsm0408/gsm0408_test.c
@@ -153,7 +153,7 @@
if (!network)
exit(1);
- bts = gsm_bts_alloc(network);
+ bts = gsm_bts_alloc(network, 0);
_bts_uarfcn_add(bts, 10564, 319, 0);
_bts_uarfcn_add(bts, 10612, 319, 0);
@@ -168,7 +168,7 @@
if (!network)
exit(1);
- bts = gsm_bts_alloc(network);
+ bts = gsm_bts_alloc(network, 0);
_bts_uarfcn_add(bts, 10564, 318, 0);
_bts_uarfcn_add(bts, 10612, 319, 0);
@@ -188,7 +188,7 @@
if (!network)
exit(1);
- bts = gsm_bts_alloc(network);
+ bts = gsm_bts_alloc(network, 0);
/* first generate invalid SI as no UARFCN added */
gen(bts, __func__);
@@ -216,7 +216,7 @@
if (!network)
exit(1);
- bts = gsm_bts_alloc(network);
+ bts = gsm_bts_alloc(network, 0);
bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
@@ -249,7 +249,7 @@
if (!network)
exit(1);
- bts = gsm_bts_alloc(network);
+ bts = gsm_bts_alloc(network, 0);
bts->si_common.si2quater_neigh_list.arfcn = bts->si_common.data.earfcn_list;
bts->si_common.si2quater_neigh_list.meas_bw = bts->si_common.data.meas_bw_list;
diff --git a/tests/gtphub/Makefile.am b/tests/gtphub/Makefile.am
index 5c834b7..f2a6b88 100644
--- a/tests/gtphub/Makefile.am
+++ b/tests/gtphub/Makefile.am
@@ -8,6 +8,7 @@
-ggdb3 \
$(LIBOSMOCORE_CFLAGS) \
$(LIBOSMOABIS_CFLAGS) \
+ $(LIBOSMOGSM_CFLAGS) \
$(LIBGTP_CFLAGS) \
$(NULL)
@@ -37,6 +38,7 @@
$(top_builddir)/src/gprs/gtphub.o \
$(top_builddir)/src/gprs/gprs_utils.o \
$(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
$(LIBGTP_LIBS) \
-lrt \
$(NULL)
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
index 2f1513a..d66c5dd 100644
--- a/tests/sgsn/sgsn_test.c
+++ b/tests/sgsn/sgsn_test.c
@@ -139,12 +139,12 @@
};
/* override, requires '-Wl,--wrap=gprs_subscr_request_auth_info' */
-int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx);
-int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx) =
+int __real_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand);
+int (*subscr_request_auth_info_cb)(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) =
&__real_gprs_subscr_request_auth_info;
-int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx) {
- return (*subscr_request_auth_info_cb)(mmctx);
+int __wrap_gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand) {
+ return (*subscr_request_auth_info_cb)(mmctx, auts, auts_rand);
};
/* override, requires '-Wl,--wrap=gsup_client_send' */
@@ -1160,7 +1160,7 @@
cleanup_test();
}
-int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx)
+int my_subscr_request_auth_info_real_auth(struct sgsn_mm_ctx *mmctx, const uint8_t *auts, const uint8_t *auts_rand)
{
struct gsm_auth_tuple at = {
.vec.sres = {0x51, 0xe5, 0x51, 0xe5},
--
To view, visit https://gerrit.osmocom.org/3695
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id072aa07793aceca66bd74950bc40dd504982a55
Gerrit-PatchSet: 1
Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>