blob: 41639b3a2a27437c45ad9e8cbf59db3975c5920c [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Harald Welte7e310b12009-03-30 20:56:32 +00006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther75172122012-11-10 18:11:22 +01007 * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freyther85531cc2010-10-06 20:37:09 +08008 * (C) 2010 by On-Waves
Andreas Eversbergf7396ea2011-10-28 04:07:07 +02009 * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000010 *
11 * All Rights Reserved
12 *
13 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * it under the terms of the GNU Affero General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
Daniel Willmann8b3390e2008-12-28 00:31:09 +000016 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010021 * GNU Affero General Public License for more details.
Daniel Willmann8b3390e2008-12-28 00:31:09 +000022 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010023 * You should have received a copy of the GNU Affero General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Daniel Willmann8b3390e2008-12-28 00:31:09 +000025 *
26 */
27
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <errno.h>
Harald Weltef3efc592009-07-27 20:11:35 +020033#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000034#include <netinet/in.h>
35
Harald Welte9c3dc902012-04-08 16:59:24 +020036#include "bscconfig.h"
37
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010038#include <osmocom/core/msgb.h>
Holger Hans Peter Freyther75172122012-11-10 18:11:22 +010039#include <osmocom/core/talloc.h>
40
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010041#include <osmocom/gsm/tlv.h>
Holger Hans Peter Freyther75172122012-11-10 18:11:22 +010042#include <osmocom/gsm/gsm_utils.h>
Holger Hans Peter Freyther366c3312012-11-10 18:24:54 +010043#include <osmocom/gsm/gsm0411_utils.h>
Holger Hans Peter Freyther75172122012-11-10 18:11:22 +010044
Daniel Willmann8b3390e2008-12-28 00:31:09 +000045#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000046#include <openbsc/gsm_data.h>
Nico Goldef11af072010-09-15 19:49:55 +020047#include <openbsc/db.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000048#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000049#include <openbsc/gsm_04_11.h>
50#include <openbsc/gsm_04_08.h>
51#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000052#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000053#include <openbsc/db.h>
Harald Weltef3efc592009-07-27 20:11:35 +020054#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020055#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020056#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020057#include <openbsc/chan_alloc.h>
Holger Hans Peter Freythercbac76e2010-05-23 21:05:18 +080058#include <openbsc/bsc_api.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000059
Harald Weltee07b6a72012-11-23 19:02:37 +010060#ifdef BUILD_SMPP
61#include "smpp_smsc.h"
62extern int smpp_try_deliver(struct gsm_sms *sms);
63#endif
64
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020065void *tall_gsms_ctx;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020066static uint32_t new_callref = 0x40000001;
Harald Weltef3efc592009-07-27 20:11:35 +020067
Harald Welte (local)c89a5112009-08-14 10:42:43 +020068static const struct value_string rp_cause_strs[] = {
69 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
70 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
71 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
72 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
73 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
74 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
75 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
76 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
77 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
78 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
79 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
80 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
81 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
82 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
83 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
84 /* valid only for MT */
85 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
86 /* valid for both directions */
87 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
88 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
89 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
90 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
91 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
92 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
93 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
94 { 0, NULL }
95};
96
Holger Hans Peter Freyther0fbb3ec2010-06-16 14:19:31 +080097
Harald Welte76042182009-08-08 16:03:15 +020098struct gsm_sms *sms_alloc(void)
99{
100 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
101}
102
103void sms_free(struct gsm_sms *sms)
104{
105 /* drop references to subscriber structure */
106 if (sms->sender)
107 subscr_put(sms->sender);
108 if (sms->receiver)
109 subscr_put(sms->receiver);
Harald Welte6c7680d2012-11-16 22:15:22 +0100110#ifdef BUILD_SMPP
Harald Weltee94db492012-11-08 20:11:05 +0100111 if (sms->smpp.esme)
112 smpp_esme_put(sms->smpp.esme);
Harald Welte6c7680d2012-11-16 22:15:22 +0100113#endif
Harald Welte76042182009-08-08 16:03:15 +0200114
115 talloc_free(sms);
116}
117
Holger Hans Peter Freythercdfcbee2011-01-10 15:34:09 +0100118struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text)
Holger Hans Peter Freytherc4644912011-01-10 15:21:34 +0100119{
120 struct gsm_sms *sms = sms_alloc();
121
122 if (!sms)
123 return NULL;
124
125 sms->receiver = subscr_get(receiver);
126 strncpy(sms->text, text, sizeof(sms->text)-1);
127
128 /* FIXME: don't use ID 1 static */
129 sms->sender = subscr_get_by_id(receiver->net, 1);
Harald Weltec0de14d2012-11-23 23:35:01 +0100130 strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1);
Holger Hans Peter Freytherc4644912011-01-10 15:21:34 +0100131 sms->reply_path_req = 0;
132 sms->status_rep_req = 0;
133 sms->ud_hdr_ind = 0;
134 sms->protocol_id = 0; /* implicit */
Holger Hans Peter Freythercdfcbee2011-01-10 15:34:09 +0100135 sms->data_coding_scheme = dcs;
Harald Weltec0de14d2012-11-23 23:35:01 +0100136 strncpy(sms->dst.addr, receiver->extension, sizeof(sms->dst.addr)-1);
Holger Hans Peter Freytherc4644912011-01-10 15:21:34 +0100137 /* Generate user_data */
138 sms->user_data_len = gsm_7bit_encode(sms->user_data, sms->text);
139
140 return sms;
141}
142
143
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100144static void send_signal(int sig_no,
145 struct gsm_trans *trans,
146 struct gsm_sms *sms,
147 int paging_result)
148{
149 struct sms_signal_data sig;
150 sig.trans = trans;
151 sig.sms = sms;
152 sig.paging_result = paging_result;
Pablo Neira Ayusobbc5b992011-05-06 12:12:31 +0200153 osmo_signal_dispatch(SS_SMS, sig_no, &sig);
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100154}
155
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200156static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t link_id)
Daniel Willmann471712b2008-12-29 01:54:02 +0000157{
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100158 DEBUGP(DLSMS, "GSM4.11 TX %s\n", osmo_hexdump(msg->data, msg->len));
Holger Hans Peter Freytherec32b582010-03-23 07:40:46 +0100159 msg->l3h = msg->data;
Holger Hans Peter Freyther8d380dc2010-11-10 10:16:02 +0100160 return gsm0808_submit_dtap(conn, msg, link_id, 1);
Daniel Willmann471712b2008-12-29 01:54:02 +0000161}
162
Harald Welte87f5d632009-07-04 17:39:00 +0200163/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200164static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200165 uint8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +0200166{
167 struct gsm48_hdr *gh;
168
169 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
170 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +0200171 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200172 gh->msg_type = msg_type;
173
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200174 DEBUGP(DLSMS, "sending CP message (trans=%x)\n", trans->transaction_id);
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200175
Holger Hans Peter Freytherec32b582010-03-23 07:40:46 +0100176 return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id);
Harald Welte87f5d632009-07-04 17:39:00 +0200177}
178
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200179/* mm_send: receive MMCCSMS sap message from SMC */
180static int gsm411_mm_send(struct gsm411_smc_inst *inst, int msg_type,
181 struct msgb *msg, int cp_msg_type)
182{
183 struct gsm_trans *trans =
184 container_of(inst, struct gsm_trans, sms.smc_inst);
185 int rc = 0;
186
187 switch (msg_type) {
188 case GSM411_MMSMS_EST_REQ:
189 /* recycle msg */
190 rc = gsm411_smc_recv(inst, GSM411_MMSMS_EST_CNF, msg, 0);
191 msgb_free(msg); /* upper layer does not free msg */
192 break;
193 case GSM411_MMSMS_DATA_REQ:
194 rc = gsm411_cp_sendmsg(msg, trans, cp_msg_type);
195 break;
196 case GSM411_MMSMS_REL_REQ:
197 msgb_free(msg);
198 trans_free(trans);
199 break;
200 default:
201 msgb_free(msg);
202 rc = -EINVAL;
203 }
204
205 return rc;
206}
207
Harald Welte87f5d632009-07-04 17:39:00 +0200208/* Prefix msg with a RP-DATA header and send as CP-DATA */
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200209static int gsm411_rp_sendmsg(struct gsm411_smc_inst *inst, struct msgb *msg,
210 uint8_t rp_msg_type, uint8_t rp_msg_ref,
211 int mnsms_msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +0200212{
213 struct gsm411_rp_hdr *rp;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200214 uint8_t len = msg->len;
Harald Welte87f5d632009-07-04 17:39:00 +0200215
216 /* GSM 04.11 RP-DATA header */
217 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Welte0d544e72009-08-10 00:22:19 +0200218 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200219 rp->msg_type = rp_msg_type;
220 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
221
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200222 return gsm411_smc_send(inst, mnsms_msg_type, msg);
Harald Welte87f5d632009-07-04 17:39:00 +0200223}
224
Harald Welte76042182009-08-08 16:03:15 +0200225static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000226{
227 if (db_sms_store(gsms) != 0) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100228 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200229 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000230 }
Harald Welte76042182009-08-08 16:03:15 +0200231 /* dispatch a signal to tell higher level about it */
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100232 send_signal(S_SMS_SUBMITTED, NULL, gsms, 0);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200233
Harald Welte7e310b12009-03-30 20:56:32 +0000234 return 0;
235}
236
Harald Welte76042182009-08-08 16:03:15 +0200237/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
Holger Hans Peter Freyther366c3312012-11-10 18:24:54 +0100238static int gsm340_gen_oa_sub(uint8_t *oa, unsigned int oa_len,
Harald Weltec0de14d2012-11-23 23:35:01 +0100239 const struct gsm_sms_addr *src)
Harald Weltef3efc592009-07-27 20:11:35 +0200240{
Holger Hans Peter Freyther366c3312012-11-10 18:24:54 +0100241 /* network specific, private numbering plan */
Harald Weltec0de14d2012-11-23 23:35:01 +0100242 return gsm340_gen_oa(oa, oa_len, src->ton, src->npi, src->addr);
Harald Weltef3efc592009-07-27 20:11:35 +0200243}
244
Harald Welte76042182009-08-08 16:03:15 +0200245/* generate a msgb containing a TPDU derived from struct gsm_sms,
246 * returns total size of TPDU */
247static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200248{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200249 uint8_t *smsp;
250 uint8_t oa[12]; /* max len per 03.40 */
251 uint8_t oa_len = 0;
252 uint8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200253 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200254
255 /* generate first octet with masked bits */
256 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200257 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200258 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200259 /* TP-MMS (more messages to send) */
260 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200261 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200262 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200263 if (sms->status_rep_req)
264 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200265 /* TP-UDHI (indicating TP-UD contains a header) */
266 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200267 *smsp |= 0x40;
Harald Weltec0de14d2012-11-23 23:35:01 +0100268
Harald Weltef3efc592009-07-27 20:11:35 +0200269 /* generate originator address */
Harald Weltec0de14d2012-11-23 23:35:01 +0100270 oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
Harald Weltef3efc592009-07-27 20:11:35 +0200271 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200272 memcpy(smsp, oa, oa_len);
273
274 /* generate TP-PID */
275 smsp = msgb_put(msg, 1);
276 *smsp = sms->protocol_id;
277
278 /* generate TP-DCS */
279 smsp = msgb_put(msg, 1);
280 *smsp = sms->data_coding_scheme;
281
282 /* generate TP-SCTS */
283 smsp = msgb_put(msg, 7);
284 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200285
Harald Weltef3efc592009-07-27 20:11:35 +0200286 /* generate TP-UDL */
287 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200288 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200289
290 /* generate TP-UD */
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200291 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
292 case DCS_7BIT_DEFAULT:
Daniel Willmann9aef1452009-08-13 03:39:07 +0200293 octet_len = sms->user_data_len*7/8;
294 if (sms->user_data_len*7%8 != 0)
295 octet_len++;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200296 /* Warning, user_data_len indicates the amount of septets
297 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200298 smsp = msgb_put(msg, octet_len);
299 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200300 break;
301 case DCS_UCS2:
302 case DCS_8BIT_DATA:
303 smsp = msgb_put(msg, sms->user_data_len);
304 memcpy(smsp, sms->user_data, sms->user_data_len);
305 break;
306 default:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100307 LOGP(DLSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
Harald Welted0cf7ba2009-12-24 15:08:18 +0100308 sms->data_coding_scheme);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200309 break;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200310 }
Harald Weltef3efc592009-07-27 20:11:35 +0200311
Harald Welte76042182009-08-08 16:03:15 +0200312 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200313}
314
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200315/* process an incoming TPDU (called from RP-DATA)
316 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Holger Hans Peter Freyther18b63f42010-03-23 07:52:17 +0100317static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000318{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200319 uint8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000320 struct gsm_sms *gsms;
Harald Welte258c7132011-07-16 13:34:52 +0200321 unsigned int sms_alphabet;
322 uint8_t sms_mti, sms_mms, sms_vpf, sms_rp;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200323 uint8_t *sms_vp;
324 uint8_t da_len_bytes;
325 uint8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
Harald Welte7e310b12009-03-30 20:56:32 +0000326 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000327
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200328 osmo_counter_inc(conn->bts->network->stats.sms.submitted);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100329
Harald Welte76042182009-08-08 16:03:15 +0200330 gsms = sms_alloc();
331 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200332 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000333
334 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200335 sms_mti = *smsp & 0x03;
336 sms_mms = !!(*smsp & 0x04);
337 sms_vpf = (*smsp & 0x18) >> 3;
338 gsms->status_rep_req = (*smsp & 0x20);
339 gsms->ud_hdr_ind = (*smsp & 0x40);
340 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000341
342 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200343 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000344
Harald Welte7e310b12009-03-30 20:56:32 +0000345 /* length in bytes of the destination address */
346 da_len_bytes = 2 + *smsp/2 + *smsp%2;
347 if (da_len_bytes > 12) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100348 LOGP(DLSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200349 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000350 goto out;
Harald Weltee07b6a72012-11-23 19:02:37 +0100351 } else if (da_len_bytes < 4) {
352 LOGP(DLSMS, LOGL_ERROR, "Destination Address < 4 bytes ?!?\n");
353 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
354 goto out;
Harald Welte7e310b12009-03-30 20:56:32 +0000355 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800356 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000357 memcpy(address_lv, smsp, da_len_bytes);
358 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800359 address_lv[0] = da_len_bytes - 1;
Harald Weltee07b6a72012-11-23 19:02:37 +0100360
Harald Weltec0de14d2012-11-23 23:35:01 +0100361 gsms->dst.ton = (address_lv[1] >> 4) & 7;
362 gsms->dst.npi = address_lv[1] & 0xF;
Harald Welte7e310b12009-03-30 20:56:32 +0000363 /* convert to real number */
Harald Weltec0de14d2012-11-23 23:35:01 +0100364 gsm48_decode_bcd_number(gsms->dst.addr,
365 sizeof(gsms->dst.addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000366 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000367
Harald Welte76042182009-08-08 16:03:15 +0200368 gsms->protocol_id = *smsp++;
369 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000370
Harald Welte76042182009-08-08 16:03:15 +0200371 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Holger Hans Peter Freyther8e78fa72010-06-14 16:13:16 +0800372 if (sms_alphabet == 0xffffffff) {
373 sms_free(gsms);
Harald Weltee98c6352010-06-09 15:29:13 +0200374 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Holger Hans Peter Freyther8e78fa72010-06-14 16:13:16 +0800375 }
Harald Welte7e310b12009-03-30 20:56:32 +0000376
Harald Welte76042182009-08-08 16:03:15 +0200377 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000378 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200379 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000380 break;
381 case GSM340_TP_VPF_ABSOLUTE:
382 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200383 sms_vp = smsp;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100384 /* the additional functionality indicator... */
Steffen Neubauerac0c13c2009-12-05 12:44:41 +0100385 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
386 smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000387 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000388 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200389 case GSM340_TP_VPF_NONE:
390 sms_vp = 0;
391 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000392 default:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100393 LOGP(DLSMS, LOGL_NOTICE,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100394 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte76042182009-08-08 16:03:15 +0200395 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000396 }
Harald Welte76042182009-08-08 16:03:15 +0200397 gsms->user_data_len = *smsp++;
398 if (gsms->user_data_len) {
399 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000400
Harald Welte76042182009-08-08 16:03:15 +0200401 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000402 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200403 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000404 break;
405 case DCS_8BIT_DATA:
406 case DCS_UCS2:
407 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000408 break;
409 }
410 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000411
Holger Hans Peter Freyther4f834092010-06-16 14:16:47 +0800412 gsms->sender = subscr_get(conn->subscr);
Harald Welted0cf7ba2009-12-24 15:08:18 +0100413
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100414 LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
Harald Welted0cf7ba2009-12-24 15:08:18 +0100415 "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
416 "UserDataLength: 0x%02x, UserData: \"%s\"\n",
417 subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
Harald Weltec0de14d2012-11-23 23:35:01 +0100418 gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100419 gsms->user_data_len,
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +0200420 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +0200421 osmo_hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000422
Harald Welte76042182009-08-08 16:03:15 +0200423 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200424
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100425 /* FIXME: This looks very wrong */
426 send_signal(0, NULL, gsms, 0);
Harald Welteb9c758b2009-07-05 14:02:46 +0200427
Harald Welte7e310b12009-03-30 20:56:32 +0000428 /* determine gsms->receiver based on dialled number */
Harald Weltec0de14d2012-11-23 23:35:01 +0100429 gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000430 if (!gsms->receiver) {
Harald Weltee07b6a72012-11-23 19:02:37 +0100431#ifdef BUILD_SMPP
432 rc = smpp_try_deliver(gsms);
433 if (rc == 1) {
434 rc = 1; /* cause 1: unknown subscriber */
435 osmo_counter_inc(conn->bts->network->stats.sms.no_receiver);
436 } else if (rc < 0) {
437 rc = 21; /* cause 21: short message transfer rejected */
438 /* FIXME: handle the error somehow? */
439 }
440#else
Harald Welte7e310b12009-03-30 20:56:32 +0000441 rc = 1; /* cause 1: unknown subscriber */
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200442 osmo_counter_inc(conn->bts->network->stats.sms.no_receiver);
Harald Weltee07b6a72012-11-23 19:02:37 +0100443#endif
Harald Welte7e310b12009-03-30 20:56:32 +0000444 goto out;
445 }
446
Harald Welte76042182009-08-08 16:03:15 +0200447 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000448 case GSM340_SMS_SUBMIT_MS2SC:
449 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200450 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000451 break;
452 case GSM340_SMS_COMMAND_MS2SC:
453 case GSM340_SMS_DELIVER_REP_MS2SC:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100454 LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200455 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000456 break;
457 default:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100458 LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200459 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000460 break;
461 }
462
Harald Welteb9c758b2009-07-05 14:02:46 +0200463 if (!rc && !gsms->receiver)
464 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
465
Harald Welte7e310b12009-03-30 20:56:32 +0000466out:
Harald Welte76042182009-08-08 16:03:15 +0200467 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000468
Harald Welte7e310b12009-03-30 20:56:32 +0000469 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000470}
471
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200472static int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000473{
474 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000475
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100476 DEBUGP(DLSMS, "TX: SMS RP ACK\n");
Daniel Willmann471712b2008-12-29 01:54:02 +0000477
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200478 return gsm411_rp_sendmsg(&trans->sms.smc_inst, msg, GSM411_MT_RP_ACK_MT,
479 msg_ref, GSM411_MNSMS_DATA_REQ);
Daniel Willmann471712b2008-12-29 01:54:02 +0000480}
481
Harald Weltef3efc592009-07-27 20:11:35 +0200482static int gsm411_send_rp_error(struct gsm_trans *trans,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200483 uint8_t msg_ref, uint8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000484{
485 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000486
Harald Welte7e310b12009-03-30 20:56:32 +0000487 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000488
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100489 LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200490 get_value_string(rp_cause_strs, cause));
Daniel Willmann471712b2008-12-29 01:54:02 +0000491
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200492 return gsm411_rp_sendmsg(&trans->sms.smc_inst, msg,
493 GSM411_MT_RP_ERROR_MT, msg_ref, GSM411_MNSMS_DATA_REQ);
Daniel Willmann471712b2008-12-29 01:54:02 +0000494}
495
Harald Welte7e310b12009-03-30 20:56:32 +0000496/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200497static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
498 struct gsm411_rp_hdr *rph,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200499 uint8_t src_len, uint8_t *src,
500 uint8_t dst_len, uint8_t *dst,
501 uint8_t tpdu_len, uint8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000502{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000503 int rc = 0;
504
Harald Welte7e310b12009-03-30 20:56:32 +0000505 if (src_len && src)
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100506 LOGP(DLSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000507
508 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100509 LOGP(DLSMS, LOGL_ERROR,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100510 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200511 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200512 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000513 return -EIO;
514 }
Harald Weltee9dd9b02010-04-30 14:27:05 +0200515 msg->l4h = tpdu;
Harald Welte7e310b12009-03-30 20:56:32 +0000516
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100517 DEBUGP(DLSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000518
Holger Hans Peter Freyther18b63f42010-03-23 07:52:17 +0100519 rc = gsm340_rx_tpdu(trans->conn, msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000520 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200521 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000522 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200523 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000524 else
525 return rc;
526}
527
528/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200529static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
530 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000531{
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200532 uint8_t src_len, dst_len, rpud_len;
533 uint8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
Harald Welte7e310b12009-03-30 20:56:32 +0000534
535 /* in the MO case, this should always be zero length */
536 src_len = rph->data[0];
537 if (src_len)
538 src = &rph->data[1];
539
540 dst_len = rph->data[1+src_len];
541 if (dst_len)
542 dst = &rph->data[1+src_len+1];
543
544 rpud_len = rph->data[1+src_len+1+dst_len];
545 if (rpud_len)
546 rp_ud = &rph->data[1+src_len+1+dst_len+1];
547
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100548 DEBUGP(DLSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
Harald Welteb9c758b2009-07-05 14:02:46 +0200549 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200550 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000551 rpud_len, rp_ud);
552}
553
Harald Weltecb8f4432009-08-09 14:59:02 +0200554/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200555static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
556 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200557{
Harald Welte76042182009-08-08 16:03:15 +0200558 struct gsm_sms *sms = trans->sms.sms;
559
Harald Welteb9c758b2009-07-05 14:02:46 +0200560 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
561 * successfully received a SMS. We can now safely mark it as
562 * transmitted */
563
Harald Weltecb8f4432009-08-09 14:59:02 +0200564 if (!trans->sms.is_mt) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100565 LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200566 return gsm411_send_rp_error(trans, rph->msg_ref,
567 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
568 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200569
Harald Welte76042182009-08-08 16:03:15 +0200570 if (!sms) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100571 LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200572 return gsm411_send_rp_error(trans, rph->msg_ref,
573 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200574 }
575
576 /* mark this SMS as sent in database */
577 db_sms_mark_sent(sms);
578
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100579 send_signal(S_SMS_DELIVERED, trans, sms, 0);
Harald Welte76042182009-08-08 16:03:15 +0200580
581 sms_free(sms);
582 trans->sms.sms = NULL;
583
Harald Weltecf6a3812009-08-09 19:07:41 +0200584 /* check for more messages for this subscriber */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100585 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltecf6a3812009-08-09 19:07:41 +0200586 if (sms)
Holger Hans Peter Freyther0fbb3ec2010-06-16 14:19:31 +0800587 gsm411_send_sms(trans->conn, sms);
Sylvain Munautd6c35f62009-12-24 13:33:51 +0100588
589 /* free the transaction here */
590 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200591 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200592}
593
Harald Weltef3efc592009-07-27 20:11:35 +0200594static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
595 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200596{
Holger Hans Peter Freyther18b63f42010-03-23 07:52:17 +0100597 struct gsm_network *net = trans->conn->bts->network;
Harald Welte76042182009-08-08 16:03:15 +0200598 struct gsm_sms *sms = trans->sms.sms;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200599 uint8_t cause_len = rph->data[0];
600 uint8_t cause = rph->data[1];
Harald Weltef3efc592009-07-27 20:11:35 +0200601
Harald Welteb9c758b2009-07-05 14:02:46 +0200602 /* Error in response to MT RP_DATA, i.e. the MS did not
603 * successfully receive the SMS. We need to investigate
604 * the cause and take action depending on it */
605
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100606 LOGP(DLSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Holger Hans Peter Freytherd4c16b12010-03-23 07:56:22 +0100607 subscr_name(trans->conn->subscr), cause_len, cause,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100608 get_value_string(rp_cause_strs, cause));
Harald Weltef3efc592009-07-27 20:11:35 +0200609
Harald Weltecb8f4432009-08-09 14:59:02 +0200610 if (!trans->sms.is_mt) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100611 LOGP(DLSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200612#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200613 return gsm411_send_rp_error(trans, rph->msg_ref,
614 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200615#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200616 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200617
Harald Welte76042182009-08-08 16:03:15 +0200618 if (!sms) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100619 LOGP(DLSMS, LOGL_ERROR,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100620 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200621 return -EINVAL;
622#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200623 return gsm411_send_rp_error(trans, rph->msg_ref,
624 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200625#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200626 }
627
628 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
629 /* MS has not enough memory to store the message. We need
Holger Hans Peter Freytherdd715bd2010-12-23 22:23:15 +0100630 * to store this in our database and wait for a SMMA message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200631 /* FIXME */
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100632 send_signal(S_SMS_MEM_EXCEEDED, trans, sms, 0);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200633 osmo_counter_inc(net->stats.sms.rp_err_mem);
Holger Hans Peter Freyther0eb76662010-12-24 09:47:04 +0100634 } else {
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100635 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200636 osmo_counter_inc(net->stats.sms.rp_err_other);
Holger Hans Peter Freyther0eb76662010-12-24 09:47:04 +0100637 }
Harald Welte76042182009-08-08 16:03:15 +0200638
639 sms_free(sms);
640 trans->sms.sms = NULL;
641
Harald Weltef3efc592009-07-27 20:11:35 +0200642 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200643}
644
Harald Weltef3efc592009-07-27 20:11:35 +0200645static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
646 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200647{
Harald Weltecf6a3812009-08-09 19:07:41 +0200648 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200649 int rc;
650
Harald Weltecf6a3812009-08-09 19:07:41 +0200651 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
652 trans->sms.rp_state = GSM411_RPS_IDLE;
653
Harald Welteb9c758b2009-07-05 14:02:46 +0200654 /* MS tells us that it has memory for more SMS, we need
655 * to check if we have any pending messages for it and then
656 * transfer those */
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100657 send_signal(S_SMS_SMMA, trans, NULL, 0);
Harald Weltef3efc592009-07-27 20:11:35 +0200658
Harald Weltecf6a3812009-08-09 19:07:41 +0200659 /* check for more messages for this subscriber */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100660 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltecf6a3812009-08-09 19:07:41 +0200661 if (sms)
Holger Hans Peter Freyther0fbb3ec2010-06-16 14:19:31 +0800662 gsm411_send_sms(trans->conn, sms);
Harald Weltef3efc592009-07-27 20:11:35 +0200663
664 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200665}
666
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200667/* receive CP DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200668static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
669 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000670{
Daniel Willmann471712b2008-12-29 01:54:02 +0000671 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200672 uint8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000673 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000674
675 switch (msg_type) {
676 case GSM411_MT_RP_DATA_MO:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100677 DEBUGP(DLSMS, "RX SMS RP-DATA (MO)\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200678 /* start TR2N and enter 'wait to send RP-ACK state' */
679 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
680 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000681 break;
682 case GSM411_MT_RP_ACK_MO:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100683 DEBUGP(DLSMS,"RX SMS RP-ACK (MO)\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200684 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200685 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000686 case GSM411_MT_RP_SMMA_MO:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100687 DEBUGP(DLSMS, "RX SMS RP-SMMA\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200688 /* start TR2N and enter 'wait to send RP-ACK state' */
689 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
690 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
691 break;
692 case GSM411_MT_RP_ERROR_MO:
693 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000694 break;
695 default:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100696 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200697 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
698 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000699 break;
700 }
701
702 return rc;
703}
704
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200705/* receive MNCCSMS sap message from SMC
706 * NOTE: Message is freed by sender
707 */
708static int gsm411_mn_recv(struct gsm411_smc_inst *inst, int msg_type,
709 struct msgb *msg)
Harald Weltef3efc592009-07-27 20:11:35 +0200710{
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200711 struct gsm_trans *trans =
712 container_of(inst, struct gsm_trans, sms.smc_inst);
713 struct gsm48_hdr *gh = msgb_l3(msg);
714 int rc = 0;
Harald Weltef3efc592009-07-27 20:11:35 +0200715
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200716 switch (msg_type) {
717 case GSM411_MNSMS_EST_IND:
718 case GSM411_MNSMS_DATA_IND:
719 DEBUGP(DLSMS, "MNSMS-DATA/EST-IND\n");
720 rc = gsm411_rx_cp_data(msg, gh, trans);
721 break;
722 case GSM411_MNSMS_ERROR_IND:
723 if (gh)
724 DEBUGP(DLSMS, "MNSMS-ERROR-IND, cause %d (%s)\n",
725 gh->data[0],
726 get_value_string(gsm411_cp_cause_strs,
727 gh->data[0]));
728 else
729 DEBUGP(DLSMS, "MNSMS-ERROR-IND, no cause\n");
730 break;
731 default:
732 rc = -EINVAL;
Harald Weltecf6a3812009-08-09 19:07:41 +0200733 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200734
735 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200736}
737
Harald Weltef3efc592009-07-27 20:11:35 +0200738/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Holger Hans Peter Freyther57c4dec2010-06-16 14:24:55 +0800739int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800740 struct msgb *msg)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000741{
742 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200743 uint8_t msg_type = gh->msg_type;
744 uint8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
Harald Weltef3efc592009-07-27 20:11:35 +0200745 struct gsm_trans *trans;
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200746 int new_trans = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000747 int rc = 0;
748
Holger Hans Peter Freyther57c4dec2010-06-16 14:24:55 +0800749 if (!conn->subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200750 return -EIO;
751 /* FIXME: send some error message */
752
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200753 DEBUGP(DLSMS, "receiving data (trans_id=%x)\n", transaction_id);
Holger Hans Peter Freyther57c4dec2010-06-16 14:24:55 +0800754 trans = trans_find_by_id(conn->subscr, GSM48_PDISC_SMS,
Harald Weltef3efc592009-07-27 20:11:35 +0200755 transaction_id);
756 if (!trans) {
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200757 DEBUGP(DLSMS, " -> (new transaction)\n");
Holger Hans Peter Freyther57c4dec2010-06-16 14:24:55 +0800758 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Weltef3efc592009-07-27 20:11:35 +0200759 transaction_id, new_callref++);
760 if (!trans) {
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200761 DEBUGP(DLSMS, " -> No memory for trans\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200762 /* FIXME: send some error message */
763 return -ENOMEM;
764 }
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200765 gsm411_smc_init(&trans->sms.smc_inst, 0, 1,
766 gsm411_mn_recv, gsm411_mm_send);
Harald Weltef3efc592009-07-27 20:11:35 +0200767 trans->sms.rp_state = GSM411_RPS_IDLE;
Holger Hans Peter Freyther97643312010-06-17 16:41:25 +0800768 trans->sms.link_id = UM_SAPI_SMS;
Harald Weltef3efc592009-07-27 20:11:35 +0200769
Holger Hans Peter Freyther57c4dec2010-06-16 14:24:55 +0800770 trans->conn = conn;
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200771
772 new_trans = 1;
Harald Weltef3efc592009-07-27 20:11:35 +0200773 }
774
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200775 /* 5.4: For MO, if a CP-DATA is received for a new
776 * transaction, equals reception of an implicit
777 * last CP-ACK for previous transaction */
778 if (trans->sms.smc_inst.cp_state == GSM411_CPS_IDLE
779 && msg_type == GSM411_MT_CP_DATA) {
780 int i;
781 struct gsm_trans *ptrans;
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100782
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200783 /* Scan through all remote initiated transactions */
784 for (i=8; i<15; i++) {
785 if (i == transaction_id)
786 continue;
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100787
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200788 ptrans = trans_find_by_id(conn->subscr,
789 GSM48_PDISC_SMS, i);
790 if (!ptrans)
791 continue;
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100792
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200793 DEBUGP(DLSMS, "Implicit CP-ACK for trans_id=%x\n", i);
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100794
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200795 /* Finish it for good */
796 trans_free(ptrans);
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100797 }
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000798 }
799
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200800 gsm411_smc_recv(&trans->sms.smc_inst,
801 (new_trans) ? GSM411_MMSMS_EST_IND : GSM411_MMSMS_DATA_IND,
802 msg, msg_type);
803
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000804 return rc;
805}
806
Harald Weltecf6a3812009-08-09 19:07:41 +0200807/* Take a SMS in gsm_sms structure and send it through an already
808 * existing lchan. We also assume that the caller ensured this lchan already
809 * has a SAPI3 RLL connection! */
Holger Hans Peter Freyther11b28f92010-12-24 13:48:27 +0100810int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000811{
812 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200813 struct gsm_trans *trans;
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200814 uint8_t *data, *rp_ud_len;
815 uint8_t msg_ref = 42;
Sylvain Munautc4052cf2009-12-24 13:27:36 +0100816 int transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200817 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000818
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200819 transaction_id =
820 trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
Harald Welte49839212009-12-22 13:45:58 +0100821 if (transaction_id == -1) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100822 LOGP(DLSMS, LOGL_ERROR, "No available transaction ids\n");
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100823 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
Holger Hans Peter Freyther8e78fa72010-06-14 16:13:16 +0800824 sms_free(sms);
Harald Welte49839212009-12-22 13:45:58 +0100825 return -EBUSY;
826 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200827
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100828 DEBUGP(DLSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200829
Harald Welte76042182009-08-08 16:03:15 +0200830 /* FIXME: allocate transaction with message reference */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100831 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welte76042182009-08-08 16:03:15 +0200832 transaction_id, new_callref++);
833 if (!trans) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100834 LOGP(DLSMS, LOGL_ERROR, "No memory for trans\n");
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100835 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
Holger Hans Peter Freyther8e78fa72010-06-14 16:13:16 +0800836 sms_free(sms);
Harald Welte76042182009-08-08 16:03:15 +0200837 /* FIXME: send some error message */
838 return -ENOMEM;
839 }
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200840 gsm411_smc_init(&trans->sms.smc_inst, sms->id, 1,
841 gsm411_mn_recv, gsm411_mm_send);
Harald Welte76042182009-08-08 16:03:15 +0200842 trans->sms.rp_state = GSM411_RPS_IDLE;
Harald Welte76042182009-08-08 16:03:15 +0200843 trans->sms.sms = sms;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200844 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +0200845
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100846 trans->conn = conn;
Harald Welte76042182009-08-08 16:03:15 +0200847
848 /* Hardcode SMSC Originating Address for now */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200849 data = (uint8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200850 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200851 data[1] = 0x91; /* type of number: international, ISDN */
852 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000853 data[3] = 0x77;
854 data[4] = 0x58;
855 data[5] = 0x10;
856 data[6] = 0x06;
857 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200858
859 /* Hardcoded Destination Address */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200860 data = (uint8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200861 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000862
Harald Welte76042182009-08-08 16:03:15 +0200863 /* obtain a pointer for the rp_ud_len, so we can fill it later */
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200864 rp_ud_len = (uint8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000865
Harald Welte76042182009-08-08 16:03:15 +0200866 /* generate the 03.40 TPDU */
867 rc = gsm340_gen_tpdu(msg, sms);
868 if (rc < 0) {
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100869 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Holger Hans Peter Freyther8e78fa72010-06-14 16:13:16 +0800870 sms_free(sms);
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200871 trans->sms.sms = NULL;
872 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200873 msgb_free(msg);
874 return rc;
875 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000876
Harald Welte76042182009-08-08 16:03:15 +0200877 *rp_ud_len = rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000878
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100879 DEBUGP(DLSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000880
Pablo Neira Ayusodfb342c2011-05-06 12:13:10 +0200881 osmo_counter_inc(conn->bts->network->stats.sms.delivered);
Nico Golde1e5ed4e2010-09-16 17:50:29 +0200882 db_sms_inc_deliver_attempts(trans->sms.sms);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100883
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200884 return gsm411_rp_sendmsg(&trans->sms.smc_inst, msg,
885 GSM411_MT_RP_DATA_MT, msg_ref, GSM411_MNSMS_EST_REQ);
Harald Weltef3efc592009-07-27 20:11:35 +0200886 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000887}
Harald Weltef3efc592009-07-27 20:11:35 +0200888
Harald Weltecf6a3812009-08-09 19:07:41 +0200889/* paging callback. Here we get called if paging a subscriber has
890 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200891static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +0800892 struct msgb *msg, void *_conn, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200893{
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +0800894 struct gsm_subscriber_connection *conn = _conn;
Harald Welte76042182009-08-08 16:03:15 +0200895 struct gsm_sms *sms = _sms;
Holger Hans Peter Freyther4cd51582010-06-14 16:03:03 +0800896 int rc = 0;
Harald Weltef3efc592009-07-27 20:11:35 +0200897
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100898 DEBUGP(DLSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
Holger Hans Peter Freyther52ffb922010-12-29 14:02:34 +0100899 "conn=%p, sms=%p/id: %llu)\n", hooknum, event, msg, conn, sms, sms->id);
Harald Welte76042182009-08-08 16:03:15 +0200900
901 if (hooknum != GSM_HOOK_RR_PAGING)
902 return -EINVAL;
903
904 switch (event) {
905 case GSM_PAGING_SUCCEEDED:
Holger Hans Peter Freyther86481c22010-06-17 15:05:57 +0800906 gsm411_send_sms(conn, sms);
Harald Welte76042182009-08-08 16:03:15 +0200907 break;
908 case GSM_PAGING_EXPIRED:
Holger Hans Peter Freytherca5702a2010-06-10 18:20:54 +0800909 case GSM_PAGING_OOM:
Holger Hans Peter Freytherd3baf412010-12-23 18:19:17 +0100910 case GSM_PAGING_BUSY:
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100911 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event);
Harald Welte76042182009-08-08 16:03:15 +0200912 sms_free(sms);
913 rc = -ETIMEDOUT;
914 break;
Holger Hans Peter Freyther52ffb922010-12-29 14:02:34 +0100915 default:
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100916 LOGP(DLSMS, LOGL_ERROR, "Unhandled paging event: %d\n", event);
Harald Welte76042182009-08-08 16:03:15 +0200917 }
918
919 return rc;
920}
921
Harald Weltecf6a3812009-08-09 19:07:41 +0200922/* high-level function to send a SMS to a given subscriber. The function
923 * will take care of paging the subscriber, establishing the RLL SAPI3
924 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200925int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
926 struct gsm_sms *sms)
927{
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +0800928 struct gsm_subscriber_connection *conn;
Harald Weltecf6a3812009-08-09 19:07:41 +0200929
Harald Welte76042182009-08-08 16:03:15 +0200930 /* check if we already have an open lchan to the subscriber.
931 * if yes, send the SMS this way */
Holger Hans Peter Freytherb2be1952010-06-16 13:23:55 +0800932 conn = connection_for_subscr(subscr);
933 if (conn) {
Holger Hans Peter Freyther0fbb3ec2010-06-16 14:19:31 +0800934 return gsm411_send_sms(conn, sms);
Holger Hans Peter Freytherecd99332010-06-15 12:53:08 +0800935 }
Harald Welte76042182009-08-08 16:03:15 +0200936
937 /* if not, we have to start paging */
Holger Hans Peter Freyther7afac582010-06-10 18:21:25 +0800938 subscr_get_channel(subscr, RSL_CHANNEED_SDCCH, paging_cb_send_sms, sms);
Harald Welte76042182009-08-08 16:03:15 +0200939 return 0;
940}
Harald Welte3366a942009-07-28 00:44:49 +0200941
Harald Welte (local)86b17172009-08-14 14:52:17 +0200942void _gsm411_sms_trans_free(struct gsm_trans *trans)
943{
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200944 /* cleanup SMS instance */
945 gsm411_smc_clear(&trans->sms.smc_inst);
946 trans->sms.smc_inst.mn_recv = NULL;
947 trans->sms.smc_inst.mm_send = NULL;
948
Holger Hans Peter Freythercea722b2010-06-15 12:29:37 +0800949 if (trans->sms.sms) {
Holger Hans Peter Freythereff409492012-11-10 19:46:58 +0100950 LOGP(DLSMS, LOGL_ERROR, "Transaction contains SMS.\n");
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100951 send_signal(S_SMS_UNKNOWN_ERROR, trans, trans->sms.sms, 0);
Holger Hans Peter Freythercea722b2010-06-15 12:29:37 +0800952 sms_free(trans->sms.sms);
953 trans->sms.sms = NULL;
954 }
Harald Welte (local)86b17172009-08-14 14:52:17 +0200955}
956
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +0800957void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn)
958{
Holger Hans Peter Freyther79eff7e2010-12-27 23:25:53 +0100959 struct gsm_network *net;
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +0800960 struct gsm_trans *trans, *tmp;
961
Holger Hans Peter Freyther79eff7e2010-12-27 23:25:53 +0100962 net = conn->bts->network;
963
964 llist_for_each_entry_safe(trans, tmp, &net->trans_list, entry)
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +0800965 if (trans->conn == conn) {
966 struct gsm_sms *sms = trans->sms.sms;
967 if (!sms) {
Andreas Eversbergf7396ea2011-10-28 04:07:07 +0200968 LOGP(DLSMS, LOGL_ERROR, "SAPI Reject but no "
969 "SMS.\n");
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +0800970 continue;
971 }
972
Holger Hans Peter Freyther04144c12010-12-24 10:15:55 +0100973 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Holger Hans Peter Freyther6a3d7652010-06-15 12:03:10 +0800974 sms_free(sms);
975 trans->sms.sms = NULL;
976 trans_free(trans);
977 }
978}
979