blob: 41639b3a2a27437c45ad9e8cbf59db3975c5920c [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* 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>
6 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Holger Hans Peter Freyther5b33c732012-11-10 18:11:22 +01007 * (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
Holger Hans Peter Freyther51808442010-10-06 20:37:09 +08008 * (C) 2010 by On-Waves
Andreas Eversberg12c52b72011-10-28 04:07:07 +02009 * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
Harald Welte59b04682009-06-10 05:40:52 +080010 *
11 * All Rights Reserved
12 *
13 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-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
Harald Welte59b04682009-06-10 05:40:52 +080016 * (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 Welte0e3e88e2011-01-01 15:25:50 +010021 * GNU Affero General Public License for more details.
Harald Welte59b04682009-06-10 05:40:52 +080022 *
Harald Welte0e3e88e2011-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/>.
Harald Welte59b04682009-06-10 05:40:52 +080025 *
26 */
27
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <errno.h>
Harald Welteb78996d2009-07-27 20:11:35 +020033#include <time.h>
Harald Welte59b04682009-06-10 05:40:52 +080034#include <netinet/in.h>
35
Harald Welteeaf4a522012-04-08 16:59:24 +020036#include "bscconfig.h"
37
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010038#include <osmocom/core/msgb.h>
Holger Hans Peter Freyther5b33c732012-11-10 18:11:22 +010039#include <osmocom/core/talloc.h>
40
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010041#include <osmocom/gsm/tlv.h>
Holger Hans Peter Freyther5b33c732012-11-10 18:11:22 +010042#include <osmocom/gsm/gsm_utils.h>
Holger Hans Peter Freytherdc767972012-11-10 18:24:54 +010043#include <osmocom/gsm/gsm0411_utils.h>
Holger Hans Peter Freyther5b33c732012-11-10 18:11:22 +010044
Harald Welte59b04682009-06-10 05:40:52 +080045#include <openbsc/debug.h>
46#include <openbsc/gsm_data.h>
Nico Golde47c8f822010-09-15 19:49:55 +020047#include <openbsc/db.h>
Harald Welte59b04682009-06-10 05:40:52 +080048#include <openbsc/gsm_subscriber.h>
49#include <openbsc/gsm_04_11.h>
50#include <openbsc/gsm_04_08.h>
Harald Welte59b04682009-06-10 05:40:52 +080051#include <openbsc/abis_rsl.h>
52#include <openbsc/signal.h>
53#include <openbsc/db.h>
Harald Welteb78996d2009-07-27 20:11:35 +020054#include <openbsc/transaction.h>
Harald Welte68b7df22009-08-08 16:03:15 +020055#include <openbsc/paging.h>
Harald Welte09421d32009-08-09 14:59:02 +020056#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther735cd9e2009-08-10 07:54:02 +020057#include <openbsc/chan_alloc.h>
Holger Hans Peter Freyther8b820fe2010-05-23 21:05:18 +080058#include <openbsc/bsc_api.h>
Harald Welte59b04682009-06-10 05:40:52 +080059
Harald Welte691ce332012-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)8751ee92009-08-15 02:30:58 +020065void *tall_gsms_ctx;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +020066static uint32_t new_callref = 0x40000001;
Harald Welteb78996d2009-07-27 20:11:35 +020067
Harald Welte (local)cb4715c2009-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 Freythere5dfd492010-06-16 14:19:31 +080097
Harald Welte68b7df22009-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 Welte3ae5ec72012-11-16 22:15:22 +0100110#ifdef BUILD_SMPP
Harald Weltebf6d98e2012-11-08 20:11:05 +0100111 if (sms->smpp.esme)
112 smpp_esme_put(sms->smpp.esme);
Harald Welte3ae5ec72012-11-16 22:15:22 +0100113#endif
Harald Welte68b7df22009-08-08 16:03:15 +0200114
115 talloc_free(sms);
116}
117
Holger Hans Peter Freyther3fb6bf92011-01-10 15:34:09 +0100118struct gsm_sms *sms_from_text(struct gsm_subscriber *receiver, int dcs, const char *text)
Holger Hans Peter Freyther805d3692011-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 Weltefde49162012-11-23 23:35:01 +0100130 strncpy(sms->src.addr, sms->sender->extension, sizeof(sms->src.addr)-1);
Holger Hans Peter Freyther805d3692011-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 Freyther3fb6bf92011-01-10 15:34:09 +0100135 sms->data_coding_scheme = dcs;
Harald Weltefde49162012-11-23 23:35:01 +0100136 strncpy(sms->dst.addr, receiver->extension, sizeof(sms->dst.addr)-1);
Holger Hans Peter Freyther805d3692011-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 Freythered3c2042010-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 Ayusoef717c62011-05-06 12:12:31 +0200153 osmo_signal_dispatch(SS_SMS, sig_no, &sig);
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100154}
155
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200156static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800157{
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100158 DEBUGP(DLSMS, "GSM4.11 TX %s\n", osmo_hexdump(msg->data, msg->len));
Holger Hans Peter Freyther7cdff242010-03-23 07:40:46 +0100159 msg->l3h = msg->data;
Holger Hans Peter Freyther6bfcad82010-11-10 10:16:02 +0100160 return gsm0808_submit_dtap(conn, msg, link_id, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800161}
162
Harald Welte7e2f57d2009-07-04 17:39:00 +0200163/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200164static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200165 uint8_t msg_type)
Harald Welte7e2f57d2009-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 Welteb78996d2009-07-27 20:11:35 +0200171 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200172 gh->msg_type = msg_type;
173
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200174 DEBUGP(DLSMS, "sending CP message (trans=%x)\n", trans->transaction_id);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200175
Holger Hans Peter Freyther7cdff242010-03-23 07:40:46 +0100176 return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200177}
178
Andreas Eversberg12c52b72011-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 Welte7e2f57d2009-07-04 17:39:00 +0200208/* Prefix msg with a RP-DATA header and send as CP-DATA */
Andreas Eversberg12c52b72011-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 Welte7e2f57d2009-07-04 17:39:00 +0200212{
213 struct gsm411_rp_hdr *rp;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200214 uint8_t len = msg->len;
Harald Welte7e2f57d2009-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 Weltef2e680b2009-08-10 00:22:19 +0200218 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200219 rp->msg_type = rp_msg_type;
220 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
221
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200222 return gsm411_smc_send(inst, mnsms_msg_type, msg);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200223}
224
Harald Welte68b7df22009-08-08 16:03:15 +0200225static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800226{
227 if (db_sms_store(gsms) != 0) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100228 LOGP(DLSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200229 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800230 }
Harald Welte68b7df22009-08-08 16:03:15 +0200231 /* dispatch a signal to tell higher level about it */
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100232 send_signal(S_SMS_SUBMITTED, NULL, gsms, 0);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200233
Harald Welte59b04682009-06-10 05:40:52 +0800234 return 0;
235}
236
Harald Welte68b7df22009-08-08 16:03:15 +0200237/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
Holger Hans Peter Freytherdc767972012-11-10 18:24:54 +0100238static int gsm340_gen_oa_sub(uint8_t *oa, unsigned int oa_len,
Harald Weltefde49162012-11-23 23:35:01 +0100239 const struct gsm_sms_addr *src)
Harald Welteb78996d2009-07-27 20:11:35 +0200240{
Holger Hans Peter Freytherdc767972012-11-10 18:24:54 +0100241 /* network specific, private numbering plan */
Harald Weltefde49162012-11-23 23:35:01 +0100242 return gsm340_gen_oa(oa, oa_len, src->ton, src->npi, src->addr);
Harald Welteb78996d2009-07-27 20:11:35 +0200243}
244
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200248{
Holger Hans Peter Freyther7eb8a9a2011-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 Welte68b7df22009-08-08 16:03:15 +0200253 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200254
255 /* generate first octet with masked bits */
256 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200257 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200258 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200259 /* TP-MMS (more messages to send) */
260 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200261 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200262 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200263 if (sms->status_rep_req)
264 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200265 /* TP-UDHI (indicating TP-UD contains a header) */
266 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200267 *smsp |= 0x40;
Harald Weltefde49162012-11-23 23:35:01 +0100268
Harald Welteb78996d2009-07-27 20:11:35 +0200269 /* generate originator address */
Harald Weltefde49162012-11-23 23:35:01 +0100270 oa_len = gsm340_gen_oa_sub(oa, sizeof(oa), &sms->src);
Harald Welteb78996d2009-07-27 20:11:35 +0200271 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-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 Welte68b7df22009-08-08 16:03:15 +0200285
Harald Welteb78996d2009-07-27 20:11:35 +0200286 /* generate TP-UDL */
287 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200288 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200289
290 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200291 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
292 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-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 Willmann8f31ed92009-08-12 21:17:06 +0200296 /* Warning, user_data_len indicates the amount of septets
297 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200298 smsp = msgb_put(msg, octet_len);
299 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-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 Freytherd0a34ed2012-11-10 19:46:58 +0100307 LOGP(DLSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
Harald Welteced9a912009-12-24 15:08:18 +0100308 sms->data_coding_scheme);
Daniel Willmann8d786602009-08-15 03:01:46 +0200309 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200310 }
Harald Welteb78996d2009-07-27 20:11:35 +0200311
Harald Welte68b7df22009-08-08 16:03:15 +0200312 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200313}
314
Holger Hans Peter Freyther71135142010-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 Freythere9781842010-03-23 07:52:17 +0100317static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +0800318{
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200319 uint8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800320 struct gsm_sms *gsms;
Harald Welte2ece4192011-07-16 13:34:52 +0200321 unsigned int sms_alphabet;
322 uint8_t sms_mti, sms_mms, sms_vpf, sms_rp;
Holger Hans Peter Freyther7eb8a9a2011-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 Welte59b04682009-06-10 05:40:52 +0800326 int rc = 0;
327
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200328 osmo_counter_inc(conn->bts->network->stats.sms.submitted);
Harald Welte3edc5a92009-12-22 00:41:05 +0100329
Harald Welte68b7df22009-08-08 16:03:15 +0200330 gsms = sms_alloc();
331 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200332 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800333
334 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800341
342 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200343 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800344
345 /* 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 Freytherd0a34ed2012-11-10 19:46:58 +0100348 LOGP(DLSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200349 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800350 goto out;
Harald Welte691ce332012-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 Welte59b04682009-06-10 05:40:52 +0800355 }
Harald Welte3794e152009-06-12 02:42:11 +0800356 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800357 memcpy(address_lv, smsp, da_len_bytes);
358 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800359 address_lv[0] = da_len_bytes - 1;
Harald Welte691ce332012-11-23 19:02:37 +0100360
Harald Weltefde49162012-11-23 23:35:01 +0100361 gsms->dst.ton = (address_lv[1] >> 4) & 7;
362 gsms->dst.npi = address_lv[1] & 0xF;
Harald Welte59b04682009-06-10 05:40:52 +0800363 /* convert to real number */
Harald Weltefde49162012-11-23 23:35:01 +0100364 gsm48_decode_bcd_number(gsms->dst.addr,
365 sizeof(gsms->dst.addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800366 smsp += da_len_bytes;
367
Harald Welte68b7df22009-08-08 16:03:15 +0200368 gsms->protocol_id = *smsp++;
369 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800370
Harald Welte68b7df22009-08-08 16:03:15 +0200371 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Holger Hans Peter Freyther87a39ff2010-06-14 16:13:16 +0800372 if (sms_alphabet == 0xffffffff) {
373 sms_free(gsms);
Harald Weltefb3a2322010-06-09 15:29:13 +0200374 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Holger Hans Peter Freyther87a39ff2010-06-14 16:13:16 +0800375 }
Harald Welte59b04682009-06-10 05:40:52 +0800376
Harald Welte68b7df22009-08-08 16:03:15 +0200377 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800378 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200379 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800380 break;
381 case GSM340_TP_VPF_ABSOLUTE:
382 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200383 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100384 /* the additional functionality indicator... */
Steffen Neubauerdd488d12009-12-05 12:44:41 +0100385 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
386 smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800387 smsp += 7;
388 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200389 case GSM340_TP_VPF_NONE:
390 sms_vp = 0;
391 break;
Harald Welte59b04682009-06-10 05:40:52 +0800392 default:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100393 LOGP(DLSMS, LOGL_NOTICE,
Harald Welteced9a912009-12-24 15:08:18 +0100394 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte68b7df22009-08-08 16:03:15 +0200395 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800396 }
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800400
Harald Welte68b7df22009-08-08 16:03:15 +0200401 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800402 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200403 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800404 break;
405 case DCS_8BIT_DATA:
406 case DCS_UCS2:
407 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800408 break;
409 }
410 }
411
Holger Hans Peter Freyther60c282d2010-06-16 14:16:47 +0800412 gsms->sender = subscr_get(conn->subscr);
Harald Welteced9a912009-12-24 15:08:18 +0100413
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100414 LOGP(DLSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
Harald Welteced9a912009-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 Weltefde49162012-11-23 23:35:01 +0100418 gsms->protocol_id, gsms->data_coding_scheme, gsms->dst.addr,
Harald Welteced9a912009-12-24 15:08:18 +0100419 gsms->user_data_len,
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200420 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
Pablo Neira Ayusob1d5a692011-05-07 12:12:48 +0200421 osmo_hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800422
Harald Welte68b7df22009-08-08 16:03:15 +0200423 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200424
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100425 /* FIXME: This looks very wrong */
426 send_signal(0, NULL, gsms, 0);
Harald Welte156c5e62009-07-05 14:02:46 +0200427
Harald Welte59b04682009-06-10 05:40:52 +0800428 /* determine gsms->receiver based on dialled number */
Harald Weltefde49162012-11-23 23:35:01 +0100429 gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dst.addr);
Harald Welte59b04682009-06-10 05:40:52 +0800430 if (!gsms->receiver) {
Harald Welte691ce332012-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 Welte59b04682009-06-10 05:40:52 +0800441 rc = 1; /* cause 1: unknown subscriber */
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200442 osmo_counter_inc(conn->bts->network->stats.sms.no_receiver);
Harald Welte691ce332012-11-23 19:02:37 +0100443#endif
Harald Welte59b04682009-06-10 05:40:52 +0800444 goto out;
445 }
446
Harald Welte68b7df22009-08-08 16:03:15 +0200447 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800448 case GSM340_SMS_SUBMIT_MS2SC:
449 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200450 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800451 break;
452 case GSM340_SMS_COMMAND_MS2SC:
453 case GSM340_SMS_DELIVER_REP_MS2SC:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100454 LOGP(DLSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200455 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800456 break;
457 default:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100458 LOGP(DLSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200459 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800460 break;
461 }
462
Harald Welte156c5e62009-07-05 14:02:46 +0200463 if (!rc && !gsms->receiver)
464 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
465
Harald Welte59b04682009-06-10 05:40:52 +0800466out:
Harald Welte68b7df22009-08-08 16:03:15 +0200467 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800468
469 return rc;
470}
471
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200472static int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800473{
474 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800475
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100476 DEBUGP(DLSMS, "TX: SMS RP ACK\n");
Harald Welte59b04682009-06-10 05:40:52 +0800477
Andreas Eversberg12c52b72011-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);
Harald Welte59b04682009-06-10 05:40:52 +0800480}
481
Harald Welteb78996d2009-07-27 20:11:35 +0200482static int gsm411_send_rp_error(struct gsm_trans *trans,
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200483 uint8_t msg_ref, uint8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800484{
485 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800486
Harald Welte59b04682009-06-10 05:40:52 +0800487 msgb_tv_put(msg, 1, cause);
488
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100489 LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200490 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800491
Andreas Eversberg12c52b72011-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);
Harald Welte59b04682009-06-10 05:40:52 +0800494}
495
496/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-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 Freyther7eb8a9a2011-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)
Harald Welte59b04682009-06-10 05:40:52 +0800502{
Harald Welte59b04682009-06-10 05:40:52 +0800503 int rc = 0;
504
505 if (src_len && src)
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100506 LOGP(DLSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte59b04682009-06-10 05:40:52 +0800507
508 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100509 LOGP(DLSMS, LOGL_ERROR,
Harald Welteced9a912009-12-24 15:08:18 +0100510 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200511 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200512 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800513 return -EIO;
514 }
Harald Welte2c5706d2010-04-30 14:27:05 +0200515 msg->l4h = tpdu;
Harald Welte59b04682009-06-10 05:40:52 +0800516
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100517 DEBUGP(DLSMS, "DST(%u,%s)\n", dst_len, osmo_hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800518
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100519 rc = gsm340_rx_tpdu(trans->conn, msg);
Harald Welte59b04682009-06-10 05:40:52 +0800520 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200521 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800522 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200523 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800524 else
525 return rc;
526}
527
528/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800531{
Holger Hans Peter Freyther7eb8a9a2011-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 Welte59b04682009-06-10 05:40:52 +0800534
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 Freytherd0a34ed2012-11-10 19:46:58 +0100548 DEBUGP(DLSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
Harald Welte156c5e62009-07-05 14:02:46 +0200549 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200550 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800551 rpud_len, rp_ud);
552}
553
Harald Welte09421d32009-08-09 14:59:02 +0200554/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200557{
Harald Welte68b7df22009-08-08 16:03:15 +0200558 struct gsm_sms *sms = trans->sms.sms;
559
Harald Welte156c5e62009-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 Welte09421d32009-08-09 14:59:02 +0200564 if (!trans->sms.is_mt) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100565 LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200566 return gsm411_send_rp_error(trans, rph->msg_ref,
567 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
568 }
Harald Weltedd62b162009-07-09 23:52:59 +0200569
Harald Welte68b7df22009-08-08 16:03:15 +0200570 if (!sms) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100571 LOGP(DLSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200572 return gsm411_send_rp_error(trans, rph->msg_ref,
573 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-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 Freythered3c2042010-12-24 10:15:55 +0100579 send_signal(S_SMS_DELIVERED, trans, sms, 0);
Harald Welte68b7df22009-08-08 16:03:15 +0200580
581 sms_free(sms);
582 trans->sms.sms = NULL;
583
Harald Weltefc01b242009-08-09 19:07:41 +0200584 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100585 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltefc01b242009-08-09 19:07:41 +0200586 if (sms)
Holger Hans Peter Freythere5dfd492010-06-16 14:19:31 +0800587 gsm411_send_sms(trans->conn, sms);
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100588
589 /* free the transaction here */
590 trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200591 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200592}
593
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200596{
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100597 struct gsm_network *net = trans->conn->bts->network;
Harald Welte68b7df22009-08-08 16:03:15 +0200598 struct gsm_sms *sms = trans->sms.sms;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200599 uint8_t cause_len = rph->data[0];
600 uint8_t cause = rph->data[1];
Harald Welteb78996d2009-07-27 20:11:35 +0200601
Harald Welte156c5e62009-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 Freytherd0a34ed2012-11-10 19:46:58 +0100606 LOGP(DLSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Holger Hans Peter Freytherde896e52010-03-23 07:56:22 +0100607 subscr_name(trans->conn->subscr), cause_len, cause,
Harald Welteced9a912009-12-24 15:08:18 +0100608 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200609
Harald Welte09421d32009-08-09 14:59:02 +0200610 if (!trans->sms.is_mt) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100611 LOGP(DLSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200612#if 0
Harald Welte09421d32009-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)ced09ed2009-08-17 09:39:55 +0200615#endif
Harald Welte09421d32009-08-09 14:59:02 +0200616 }
Harald Weltedd62b162009-07-09 23:52:59 +0200617
Harald Welte68b7df22009-08-08 16:03:15 +0200618 if (!sms) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100619 LOGP(DLSMS, LOGL_ERROR,
Harald Welteced9a912009-12-24 15:08:18 +0100620 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200621 return -EINVAL;
622#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200623 return gsm411_send_rp_error(trans, rph->msg_ref,
624 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200625#endif
Harald Welte09421d32009-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 Freytherf2904692010-12-23 22:23:15 +0100630 * to store this in our database and wait for a SMMA message */
Harald Welte09421d32009-08-09 14:59:02 +0200631 /* FIXME */
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100632 send_signal(S_SMS_MEM_EXCEEDED, trans, sms, 0);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200633 osmo_counter_inc(net->stats.sms.rp_err_mem);
Holger Hans Peter Freyther6c7cf7e2010-12-24 09:47:04 +0100634 } else {
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100635 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200636 osmo_counter_inc(net->stats.sms.rp_err_other);
Holger Hans Peter Freyther6c7cf7e2010-12-24 09:47:04 +0100637 }
Harald Welte68b7df22009-08-08 16:03:15 +0200638
639 sms_free(sms);
640 trans->sms.sms = NULL;
641
Harald Welteb78996d2009-07-27 20:11:35 +0200642 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200643}
644
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200647{
Harald Weltefc01b242009-08-09 19:07:41 +0200648 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200649 int rc;
650
Harald Weltefc01b242009-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 Welte156c5e62009-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 Freythered3c2042010-12-24 10:15:55 +0100657 send_signal(S_SMS_SMMA, trans, NULL, 0);
Harald Welteb78996d2009-07-27 20:11:35 +0200658
Harald Weltefc01b242009-08-09 19:07:41 +0200659 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100660 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltefc01b242009-08-09 19:07:41 +0200661 if (sms)
Holger Hans Peter Freythere5dfd492010-06-16 14:19:31 +0800662 gsm411_send_sms(trans->conn, sms);
Harald Welteb78996d2009-07-27 20:11:35 +0200663
664 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200665}
666
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200667/* receive CP DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200668static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
669 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800670{
671 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200672 uint8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte59b04682009-06-10 05:40:52 +0800673 int rc = 0;
674
675 switch (msg_type) {
676 case GSM411_MT_RP_DATA_MO:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100677 DEBUGP(DLSMS, "RX SMS RP-DATA (MO)\n");
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800681 break;
682 case GSM411_MT_RP_ACK_MO:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100683 DEBUGP(DLSMS,"RX SMS RP-ACK (MO)\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200684 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200685 break;
Harald Welte59b04682009-06-10 05:40:52 +0800686 case GSM411_MT_RP_SMMA_MO:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100687 DEBUGP(DLSMS, "RX SMS RP-SMMA\n");
Harald Welteb78996d2009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800694 break;
695 default:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100696 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200697 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
698 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800699 break;
700 }
701
702 return rc;
703}
704
Andreas Eversberg12c52b72011-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 Welteb78996d2009-07-27 20:11:35 +0200710{
Andreas Eversberg12c52b72011-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 Welteb78996d2009-07-27 20:11:35 +0200715
Andreas Eversberg12c52b72011-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 Weltefc01b242009-08-09 19:07:41 +0200733 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200734
735 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200736}
737
Harald Welteb78996d2009-07-27 20:11:35 +0200738/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Holger Hans Peter Freyther112f7b72010-06-16 14:24:55 +0800739int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
Holger Hans Peter Freytherb9795792010-06-17 16:41:25 +0800740 struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +0800741{
742 struct gsm48_hdr *gh = msgb_l3(msg);
Holger Hans Peter Freyther7eb8a9a2011-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 Welteb78996d2009-07-27 20:11:35 +0200745 struct gsm_trans *trans;
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200746 int new_trans = 0;
Harald Welte59b04682009-06-10 05:40:52 +0800747 int rc = 0;
748
Holger Hans Peter Freyther112f7b72010-06-16 14:24:55 +0800749 if (!conn->subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200750 return -EIO;
751 /* FIXME: send some error message */
752
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200753 DEBUGP(DLSMS, "receiving data (trans_id=%x)\n", transaction_id);
Holger Hans Peter Freyther112f7b72010-06-16 14:24:55 +0800754 trans = trans_find_by_id(conn->subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200755 transaction_id);
756 if (!trans) {
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200757 DEBUGP(DLSMS, " -> (new transaction)\n");
Holger Hans Peter Freyther112f7b72010-06-16 14:24:55 +0800758 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200759 transaction_id, new_callref++);
760 if (!trans) {
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200761 DEBUGP(DLSMS, " -> No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200762 /* FIXME: send some error message */
763 return -ENOMEM;
764 }
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200765 gsm411_smc_init(&trans->sms.smc_inst, 0, 1,
766 gsm411_mn_recv, gsm411_mm_send);
Harald Welteb78996d2009-07-27 20:11:35 +0200767 trans->sms.rp_state = GSM411_RPS_IDLE;
Holger Hans Peter Freytherb9795792010-06-17 16:41:25 +0800768 trans->sms.link_id = UM_SAPI_SMS;
Harald Welteb78996d2009-07-27 20:11:35 +0200769
Holger Hans Peter Freyther112f7b72010-06-16 14:24:55 +0800770 trans->conn = conn;
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200771
772 new_trans = 1;
Harald Welteb78996d2009-07-27 20:11:35 +0200773 }
774
Andreas Eversberg12c52b72011-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 Munauta5914da2009-12-24 16:47:08 +0100782
Andreas Eversberg12c52b72011-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 Munauta5914da2009-12-24 16:47:08 +0100787
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200788 ptrans = trans_find_by_id(conn->subscr,
789 GSM48_PDISC_SMS, i);
790 if (!ptrans)
791 continue;
Sylvain Munauta5914da2009-12-24 16:47:08 +0100792
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200793 DEBUGP(DLSMS, "Implicit CP-ACK for trans_id=%x\n", i);
Sylvain Munauta5914da2009-12-24 16:47:08 +0100794
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200795 /* Finish it for good */
796 trans_free(ptrans);
Sylvain Munauta5914da2009-12-24 16:47:08 +0100797 }
Harald Welte59b04682009-06-10 05:40:52 +0800798 }
799
Andreas Eversberg12c52b72011-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
Harald Welte59b04682009-06-10 05:40:52 +0800804 return rc;
805}
806
Harald Weltefc01b242009-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 Freyther575d2e12010-12-24 13:48:27 +0100810int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800811{
812 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200813 struct gsm_trans *trans;
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200814 uint8_t *data, *rp_ud_len;
815 uint8_t msg_ref = 42;
Sylvain Munaute65af1b2009-12-24 13:27:36 +0100816 int transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +0200817 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800818
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200819 transaction_id =
820 trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
Harald Welte6e55abf2009-12-22 13:45:58 +0100821 if (transaction_id == -1) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100822 LOGP(DLSMS, LOGL_ERROR, "No available transaction ids\n");
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100823 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
Holger Hans Peter Freyther87a39ff2010-06-14 16:13:16 +0800824 sms_free(sms);
Harald Welte6e55abf2009-12-22 13:45:58 +0100825 return -EBUSY;
826 }
Harald Weltefc01b242009-08-09 19:07:41 +0200827
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100828 DEBUGP(DLSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200829
Harald Welte68b7df22009-08-08 16:03:15 +0200830 /* FIXME: allocate transaction with message reference */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100831 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welte68b7df22009-08-08 16:03:15 +0200832 transaction_id, new_callref++);
833 if (!trans) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100834 LOGP(DLSMS, LOGL_ERROR, "No memory for trans\n");
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100835 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, 0);
Holger Hans Peter Freyther87a39ff2010-06-14 16:13:16 +0800836 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +0200837 /* FIXME: send some error message */
838 return -ENOMEM;
839 }
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200840 gsm411_smc_init(&trans->sms.smc_inst, sms->id, 1,
841 gsm411_mn_recv, gsm411_mm_send);
Harald Welte68b7df22009-08-08 16:03:15 +0200842 trans->sms.rp_state = GSM411_RPS_IDLE;
Harald Welte68b7df22009-08-08 16:03:15 +0200843 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200844 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +0200845
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100846 trans->conn = conn;
Harald Welte68b7df22009-08-08 16:03:15 +0200847
848 /* Hardcode SMSC Originating Address for now */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200849 data = (uint8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200850 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200851 data[1] = 0x91; /* type of number: international, ISDN */
852 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800853 data[3] = 0x77;
854 data[4] = 0x58;
855 data[5] = 0x10;
856 data[6] = 0x06;
857 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200858
859 /* Hardcoded Destination Address */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200860 data = (uint8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200861 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800862
Harald Welte68b7df22009-08-08 16:03:15 +0200863 /* obtain a pointer for the rp_ud_len, so we can fill it later */
Holger Hans Peter Freyther7eb8a9a2011-04-18 17:04:00 +0200864 rp_ud_len = (uint8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800865
Harald Welte68b7df22009-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 Freythered3c2042010-12-24 10:15:55 +0100869 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Holger Hans Peter Freyther87a39ff2010-06-14 16:13:16 +0800870 sms_free(sms);
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200871 trans->sms.sms = NULL;
872 trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200873 msgb_free(msg);
874 return rc;
875 }
Harald Welte59b04682009-06-10 05:40:52 +0800876
Harald Welte68b7df22009-08-08 16:03:15 +0200877 *rp_ud_len = rc;
Harald Welte59b04682009-06-10 05:40:52 +0800878
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100879 DEBUGP(DLSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +0800880
Pablo Neira Ayuso1c450742011-05-06 12:13:10 +0200881 osmo_counter_inc(conn->bts->network->stats.sms.delivered);
Nico Goldeacee9502010-09-16 17:50:29 +0200882 db_sms_inc_deliver_attempts(trans->sms.sms);
Harald Welte3edc5a92009-12-22 00:41:05 +0100883
Andreas Eversberg12c52b72011-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 Welteb78996d2009-07-27 20:11:35 +0200886 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800887}
Harald Welteb78996d2009-07-27 20:11:35 +0200888
Harald Weltefc01b242009-08-09 19:07:41 +0200889/* paging callback. Here we get called if paging a subscriber has
890 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +0200891static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
Holger Hans Peter Freytherd3aaf662010-06-17 15:05:57 +0800892 struct msgb *msg, void *_conn, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200893{
Holger Hans Peter Freytherd3aaf662010-06-17 15:05:57 +0800894 struct gsm_subscriber_connection *conn = _conn;
Harald Welte68b7df22009-08-08 16:03:15 +0200895 struct gsm_sms *sms = _sms;
Holger Hans Peter Freyther1a4d6992010-06-14 16:03:03 +0800896 int rc = 0;
Harald Welteb78996d2009-07-27 20:11:35 +0200897
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100898 DEBUGP(DLSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
Holger Hans Peter Freytherc4c9e4d2010-12-29 14:02:34 +0100899 "conn=%p, sms=%p/id: %llu)\n", hooknum, event, msg, conn, sms, sms->id);
Harald Welte68b7df22009-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 Freytherd3aaf662010-06-17 15:05:57 +0800906 gsm411_send_sms(conn, sms);
Harald Welte68b7df22009-08-08 16:03:15 +0200907 break;
908 case GSM_PAGING_EXPIRED:
Holger Hans Peter Freyther54d5dd52010-06-10 18:20:54 +0800909 case GSM_PAGING_OOM:
Holger Hans Peter Freytherab2a9332010-12-23 18:19:17 +0100910 case GSM_PAGING_BUSY:
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100911 send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, event);
Harald Welte68b7df22009-08-08 16:03:15 +0200912 sms_free(sms);
913 rc = -ETIMEDOUT;
914 break;
Holger Hans Peter Freytherc4c9e4d2010-12-29 14:02:34 +0100915 default:
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100916 LOGP(DLSMS, LOGL_ERROR, "Unhandled paging event: %d\n", event);
Harald Welte68b7df22009-08-08 16:03:15 +0200917 }
918
919 return rc;
920}
921
Harald Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +0200925int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
926 struct gsm_sms *sms)
927{
Holger Hans Peter Freyther2f4af772010-06-16 13:23:55 +0800928 struct gsm_subscriber_connection *conn;
Harald Weltefc01b242009-08-09 19:07:41 +0200929
Harald Welte68b7df22009-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 Freyther2f4af772010-06-16 13:23:55 +0800932 conn = connection_for_subscr(subscr);
933 if (conn) {
Holger Hans Peter Freythere5dfd492010-06-16 14:19:31 +0800934 return gsm411_send_sms(conn, sms);
Holger Hans Peter Freyther43fae0a2010-06-15 12:53:08 +0800935 }
Harald Welte68b7df22009-08-08 16:03:15 +0200936
937 /* if not, we have to start paging */
Holger Hans Peter Freyther99c10312010-06-10 18:21:25 +0800938 subscr_get_channel(subscr, RSL_CHANNEED_SDCCH, paging_cb_send_sms, sms);
Harald Welte68b7df22009-08-08 16:03:15 +0200939 return 0;
940}
Harald Welte5b359d82009-07-28 00:44:49 +0200941
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200942void _gsm411_sms_trans_free(struct gsm_trans *trans)
943{
Andreas Eversberg12c52b72011-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 Freyther3ed097d2010-06-15 12:29:37 +0800949 if (trans->sms.sms) {
Holger Hans Peter Freytherd0a34ed2012-11-10 19:46:58 +0100950 LOGP(DLSMS, LOGL_ERROR, "Transaction contains SMS.\n");
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100951 send_signal(S_SMS_UNKNOWN_ERROR, trans, trans->sms.sms, 0);
Holger Hans Peter Freyther3ed097d2010-06-15 12:29:37 +0800952 sms_free(trans->sms.sms);
953 trans->sms.sms = NULL;
954 }
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200955}
956
Holger Hans Peter Freyther9f619d02010-06-15 12:03:10 +0800957void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn)
958{
Holger Hans Peter Freyther97d454e2010-12-27 23:25:53 +0100959 struct gsm_network *net;
Holger Hans Peter Freyther9f619d02010-06-15 12:03:10 +0800960 struct gsm_trans *trans, *tmp;
961
Holger Hans Peter Freyther97d454e2010-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 Freyther9f619d02010-06-15 12:03:10 +0800965 if (trans->conn == conn) {
966 struct gsm_sms *sms = trans->sms.sms;
967 if (!sms) {
Andreas Eversberg12c52b72011-10-28 04:07:07 +0200968 LOGP(DLSMS, LOGL_ERROR, "SAPI Reject but no "
969 "SMS.\n");
Holger Hans Peter Freyther9f619d02010-06-15 12:03:10 +0800970 continue;
971 }
972
Holger Hans Peter Freythered3c2042010-12-24 10:15:55 +0100973 send_signal(S_SMS_UNKNOWN_ERROR, trans, sms, 0);
Holger Hans Peter Freyther9f619d02010-06-15 12:03:10 +0800974 sms_free(sms);
975 trans->sms.sms = NULL;
976 trans_free(trans);
977 }
978}
979