aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gsm_04_11.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/gsm_04_11.c')
-rw-r--r--openbsc/src/gsm_04_11.c137
1 files changed, 90 insertions, 47 deletions
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 579bb55d1..881c3755a 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -31,18 +31,18 @@
#include <time.h>
#include <netinet/in.h>
-#include <openbsc/msgb.h>
-#include <openbsc/tlv.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h>
#include <openbsc/gsm_04_11.h>
#include <openbsc/gsm_04_08.h>
-#include <openbsc/gsm_utils.h>
+#include <osmocore/gsm_utils.h>
#include <openbsc/abis_rsl.h>
#include <openbsc/signal.h>
#include <openbsc/db.h>
-#include <openbsc/talloc.h>
+#include <osmocore/talloc.h>
#include <openbsc/transaction.h>
#include <openbsc/paging.h>
#include <openbsc/bsc_rll.h>
@@ -215,7 +215,8 @@ static u_int8_t unbcdify(u_int8_t value)
u_int8_t ret;
if ((value & 0x0F) > 9 || (value >> 4) > 9)
- DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
+ LOGP(DSMS, LOGL_ERROR,
+ "unbcdify got too big nibble: 0x%02X\n", value);
ret = (value&0x0F)*10;
ret += value>>4;
@@ -311,7 +312,8 @@ static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
unsigned long minutes;
vp = *(sms_vp);
if (vp == 0) {
- DEBUGP(DSMS, "reserved relative_integer validity period\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "reserved relative_integer validity period\n");
return gsm340_vp_default();
}
minutes = vp/60;
@@ -356,7 +358,8 @@ static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
default:
/* The GSM spec says that the SC should reject any
unsupported and/or undefined values. FIXME */
- DEBUGP(DSMS, "Reserved enhanced validity period format\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "Reserved enhanced validity period format\n");
return gsm340_vp_default();
}
case GSM340_TP_VPF_NONE:
@@ -373,7 +376,8 @@ enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
if ((cgbits & 0xc) == 0) {
if (cgbits & 2)
- DEBUGP(DSMS, "Compressed SMS not supported yet\n");
+ LOGP(DSMS, LOGL_NOTICE,
+ "Compressed SMS not supported yet\n");
switch ((dcs >> 2)&0x03) {
case 0:
@@ -403,7 +407,7 @@ enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
{
if (db_sms_store(gsms) != 0) {
- DEBUGP(DSMS, "Failed to store SMS in Database\n");
+ LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
/* dispatch a signal to tell higher level about it */
@@ -422,7 +426,7 @@ static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
oa[1] = 0xb9; /* networks-specific number, private numbering plan */
- len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
+ len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, subscr->extension);
/* GSM 03.40 tells us the length is in 'useful semi-octets' */
oa[0] = strlen(subscr->extension) & 0xff;
@@ -497,7 +501,8 @@ static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
memcpy(smsp, sms->user_data, sms->user_data_len);
break;
default:
- DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
+ LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
+ sms->data_coding_scheme);
break;
}
@@ -517,7 +522,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
int rc = 0;
- bts->network->stats.sms.submitted++;
+ counter_inc(bts->network->stats.sms.submitted);
gsms = sms_alloc();
if (!gsms)
@@ -537,7 +542,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
/* length in bytes of the destination address */
da_len_bytes = 2 + *smsp/2 + *smsp%2;
if (da_len_bytes > 12) {
- DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
goto out;
}
@@ -546,7 +551,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
/* mangle first byte to reflect length in bytes, not digits */
address_lv[0] = da_len_bytes - 1;
/* convert to real number */
- decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
+ gsm48_decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
smsp += da_len_bytes;
gsms->protocol_id = *smsp++;
@@ -570,8 +575,8 @@ static int gsm340_rx_tpdu(struct msgb *msg)
sms_vp = 0;
break;
default:
- DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
- sms_vpf);
+ LOGP(DSMS, LOGL_NOTICE,
+ "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
}
gsms->user_data_len = *smsp++;
@@ -589,16 +594,17 @@ static int gsm340_rx_tpdu(struct msgb *msg)
}
}
- DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
- "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
- "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
- gsms->protocol_id, gsms->data_coding_scheme,
- gsms->dest_addr, gsms->user_data_len,
+ gsms->sender = subscr_get(msg->lchan->subscr);
+
+ LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
+ "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
+ "UserDataLength: 0x%02x, UserData: \"%s\"\n",
+ subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
+ gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
+ gsms->user_data_len,
sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
hexdump(gsms->user_data, gsms->user_data_len));
- gsms->sender = subscr_get(msg->lchan->subscr);
-
gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
dispatch_signal(SS_SMS, 0, gsms);
@@ -607,7 +613,7 @@ static int gsm340_rx_tpdu(struct msgb *msg)
gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
if (!gsms->receiver) {
rc = 1; /* cause 1: unknown subscriber */
- bts->network->stats.sms.no_receiver++;
+ counter_inc(bts->network->stats.sms.no_receiver);
goto out;
}
@@ -618,11 +624,11 @@ static int gsm340_rx_tpdu(struct msgb *msg)
break;
case GSM340_SMS_COMMAND_MS2SC:
case GSM340_SMS_DELIVER_REP_MS2SC:
- DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
+ LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
default:
- DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
+ LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
rc = GSM411_RP_CAUSE_IE_NOTEXIST;
break;
}
@@ -652,7 +658,7 @@ static int gsm411_send_rp_error(struct gsm_trans *trans,
msgb_tv_put(msg, 1, cause);
- DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
+ LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
get_value_string(rp_cause_strs, cause));
return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
@@ -668,10 +674,11 @@ static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
int rc = 0;
if (src_len && src)
- DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
if (!dst_len || !dst || !tpdu_len || !tpdu) {
- DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "RP-DATA (MO) without DST or TPDU ?!?\n");
gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_INV_MAND_INF);
return -EIO;
@@ -726,13 +733,13 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
* transmitted */
if (!trans->sms.is_mt) {
- DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_MSG_INCOMP_STATE);
}
if (!sms) {
- DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_PROTOCOL_ERR);
}
@@ -745,14 +752,16 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
sms_free(sms);
trans->sms.sms = NULL;
- /* free the transaction here */
- trans_free(trans);
-
/* check for more messages for this subscriber */
sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
if (sms)
gsm411_send_sms_lchan(msg->lchan, sms);
- else
+
+ /* free the transaction here */
+ trans_free(trans);
+
+ /* release channel if done */
+ if (!sms)
rsl_release_request(msg->lchan, trans->sms.link_id);
return 0;
@@ -761,6 +770,7 @@ static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
struct gsm411_rp_hdr *rph)
{
+ struct gsm_network *net = trans->lchan->ts->trx->bts->network;
struct gsm_sms *sms = trans->sms.sms;
u_int8_t cause_len = rph->data[0];
u_int8_t cause = rph->data[1];
@@ -769,11 +779,12 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
* successfully receive the SMS. We need to investigate
* the cause and take action depending on it */
- DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
- get_value_string(rp_cause_strs, cause));
+ LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
+ subscr_name(msg->lchan->subscr), cause_len, cause,
+ get_value_string(rp_cause_strs, cause));
if (!trans->sms.is_mt) {
- DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
+ LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
#if 0
return gsm411_send_rp_error(trans, rph->msg_ref,
GSM411_RP_CAUSE_MSG_INCOMP_STATE);
@@ -781,7 +792,8 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
}
if (!sms) {
- DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
+ LOGP(DSMS, LOGL_ERROR,
+ "RX RP-ERR, but no sms in transaction?!?\n");
return -EINVAL;
#if 0
return gsm411_send_rp_error(trans, rph->msg_ref,
@@ -794,9 +806,9 @@ static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
* to store this in our database and wati for a SMMA message */
/* FIXME */
dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
- trans->lchan->ts->trx->bts->network->stats.sms.rp_err_mem++;
+ counter_inc(net->stats.sms.rp_err_mem);
} else
- trans->lchan->ts->trx->bts->network->stats.sms.rp_err_other++;
+ counter_inc(net->stats.sms.rp_err_other);
sms_free(sms);
trans->sms.sms = NULL;
@@ -858,7 +870,7 @@ static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
rc = gsm411_rx_rp_error(msg, trans, rp_data);
break;
default:
- DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
+ LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
break;
@@ -889,7 +901,7 @@ static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
struct msgb *msg = gsm411_msgb_alloc();
u_int8_t *causep;
- DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
+ LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
get_value_string(cp_cause_strs, cause));
causep = msgb_put(msg, 1);
@@ -936,6 +948,33 @@ int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
switch(msg_type) {
case GSM411_MT_CP_DATA:
DEBUGPC(DSMS, "RX SMS CP-DATA\n");
+
+ /* 5.4: For MO, if a CP-DATA is received for a new
+ * transaction, equals reception of an implicit
+ * last CP-ACK for previous transaction */
+ if (trans->sms.cp_state == GSM411_CPS_IDLE) {
+ int i;
+ struct gsm_trans *ptrans;
+
+ /* Scan through all remote initiated transactions */
+ for (i=8; i<15; i++) {
+ if (i == transaction_id)
+ continue;
+
+ ptrans = trans_find_by_id(lchan->subscr,
+ GSM48_PDISC_SMS, i);
+ if (!ptrans)
+ continue;
+
+ DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
+
+ /* Finish it for good */
+ bsc_del_timer(&ptrans->sms.cp_timer);
+ ptrans->sms.cp_state = GSM411_CPS_IDLE;
+ trans_free(ptrans);
+ }
+ }
+
/* 5.2.3.1.3: MO state exists when SMC has received
* CP-DATA, including sending of the assoc. CP-ACK */
/* 5.2.3.2.4: MT state exists when SMC has received
@@ -1008,10 +1047,14 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
struct gsm_trans *trans;
u_int8_t *data, *rp_ud_len;
u_int8_t msg_ref = 42;
- u_int8_t transaction_id;
+ int transaction_id;
int rc;
- transaction_id = 4; /* FIXME: we always use 4 for now */
+ transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
+ if (transaction_id == -1) {
+ LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
+ return -EBUSY;
+ }
msg->lchan = lchan;
@@ -1021,7 +1064,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
transaction_id, new_callref++);
if (!trans) {
- DEBUGP(DSMS, "No memory for trans\n");
+ LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
/* FIXME: send some error message */
return -ENOMEM;
}
@@ -1069,7 +1112,7 @@ int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
DEBUGP(DSMS, "TX: SMS DELIVER\n");
- lchan->ts->trx->bts->network->stats.sms.delivered++;
+ counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered);
return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
/* FIXME: enter 'wait for RP-ACK' state, start TR1N */