blob: 3f93ffbc9876bd28bcf2621a10d0cb9f396c2df3 [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>
Daniel Willmann8b3390e2008-12-28 00:31:09 +00007 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
Harald Weltef3efc592009-07-27 20:11:35 +020031#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
Harald Welte7e310b12009-03-30 20:56:32 +000035#include <openbsc/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000036#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000037#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000041#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000042#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000043#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000044#include <openbsc/db.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Weltef3efc592009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000049
Daniel Willmann471712b2008-12-29 01:54:02 +000050#define GSM411_ALLOC_SIZE 1024
51#define GSM411_ALLOC_HEADROOM 128
52
Harald Weltecb8f4432009-08-09 14:59:02 +020053#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
54
Harald Welte2cf161b2009-06-20 22:36:41 +020055static void *tall_gsms_ctx;
56
Harald Weltef3efc592009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte76042182009-08-08 16:03:15 +020059struct gsm_sms *sms_alloc(void)
60{
61 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
62}
63
64void sms_free(struct gsm_sms *sms)
65{
66 /* drop references to subscriber structure */
67 if (sms->sender)
68 subscr_put(sms->sender);
69 if (sms->receiver)
70 subscr_put(sms->receiver);
71
72 talloc_free(sms);
73}
74
Holger Freythera553d092009-01-04 20:16:25 +000075struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000076{
Harald Welte966636f2009-06-26 19:39:35 +020077 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
78 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +000079}
80
Harald Welte87f5d632009-07-04 17:39:00 +020081static int gsm411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000082{
83 if (msg->lchan)
84 msg->trx = msg->lchan->ts->trx;
85
86 msg->l3h = msg->data;
87
Harald Welte76042182009-08-08 16:03:15 +020088 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
89
Harald Weltecb8f4432009-08-09 14:59:02 +020090 return rsl_data_request(msg, UM_SAPI_SMS);
Daniel Willmann471712b2008-12-29 01:54:02 +000091}
92
Harald Welte41985612009-08-10 00:24:32 +020093/* SMC TC1* is expired */
94static void cp_timer_expired(void *data)
95{
96 struct gsm_trans *trans = data;
97
98 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
99 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
100 trans_free(trans);
101}
102
Harald Welte87f5d632009-07-04 17:39:00 +0200103/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200104static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
105 u_int8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +0200106{
107 struct gsm48_hdr *gh;
108
109 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
110 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +0200111 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200112 gh->msg_type = msg_type;
113
Harald Weltef3efc592009-07-27 20:11:35 +0200114 /* assign the outgoing lchan */
115 msg->lchan = trans->lchan;
116
117 /* mobile originating */
118 switch (gh->msg_type) {
119 case GSM411_MT_CP_DATA:
120 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Weltecb8f4432009-08-09 14:59:02 +0200121 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200122 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte41985612009-08-10 00:24:32 +0200123 trans->sms.cp_timer.data = trans;
124 trans->sms.cp_timer.cb = cp_timer_expired;
125 /* 5.3.2.1: Set Timer TC1A */
126 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Weltef3efc592009-07-27 20:11:35 +0200127 break;
128 }
129
Harald Welte87f5d632009-07-04 17:39:00 +0200130 return gsm411_sendmsg(msg);
131}
132
133/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200134static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
135 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte87f5d632009-07-04 17:39:00 +0200136{
137 struct gsm411_rp_hdr *rp;
Harald Welte0d544e72009-08-10 00:22:19 +0200138 u_int8_t len = msg->len;
Harald Welte87f5d632009-07-04 17:39:00 +0200139
140 /* GSM 04.11 RP-DATA header */
141 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Welte0d544e72009-08-10 00:22:19 +0200142 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200143 rp->msg_type = rp_msg_type;
144 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
145
Harald Weltef3efc592009-07-27 20:11:35 +0200146 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200147}
148
Harald Welte76042182009-08-08 16:03:15 +0200149static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000150{
151 u_int8_t vp;
152 unsigned long minutes;
153
Harald Welte76042182009-08-08 16:03:15 +0200154 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000155 case GSM340_TP_VPF_RELATIVE:
156 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200157 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000158 if (vp <= 143)
159 minutes = vp + 1 * 5;
160 else if (vp <= 167)
161 minutes = 12*60 + (vp-143) * 30;
162 else if (vp <= 196)
163 minutes = vp-166 * 60 * 24;
164 else
165 minutes = vp-192 * 60 * 24 * 7;
166 break;
167 case GSM340_TP_VPF_ABSOLUTE:
168 /* Chapter 9.2.3.12.2 */
169 /* FIXME: like service center time stamp */
170 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
171 break;
172 case GSM340_TP_VPF_ENHANCED:
173 /* Chapter 9.2.3.12.3 */
174 /* FIXME: implementation */
175 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
176 break;
177 }
178 return minutes;
179}
180
181/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
182enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
183{
184 u_int8_t cgbits = dcs >> 4;
185 enum sms_alphabet alpha = DCS_NONE;
186
187 if ((cgbits & 0xc) == 0) {
188 if (cgbits & 2)
189 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
190
191 switch (dcs & 3) {
192 case 0:
193 alpha = DCS_7BIT_DEFAULT;
194 break;
195 case 1:
196 alpha = DCS_8BIT_DATA;
197 break;
198 case 2:
199 alpha = DCS_UCS2;
200 break;
201 }
202 } else if (cgbits == 0xc || cgbits == 0xd)
203 alpha = DCS_7BIT_DEFAULT;
204 else if (cgbits == 0xe)
205 alpha = DCS_UCS2;
206 else if (cgbits == 0xf) {
207 if (dcs & 4)
208 alpha = DCS_8BIT_DATA;
209 else
210 alpha = DCS_7BIT_DEFAULT;
211 }
212
213 return alpha;
214}
215
Harald Welte76042182009-08-08 16:03:15 +0200216static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000217{
218 if (db_sms_store(gsms) != 0) {
219 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200220 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000221 }
Harald Welte76042182009-08-08 16:03:15 +0200222 /* dispatch a signal to tell higher level about it */
223 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000224 return 0;
225}
226
Harald Welte76042182009-08-08 16:03:15 +0200227/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
228static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
229 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200230{
Harald Welte76042182009-08-08 16:03:15 +0200231 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200232
Harald Welte76042182009-08-08 16:03:15 +0200233 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
234
235 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
236
237 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
238 oa[0] = strlen(subscr->extension) & 0xff;
239
240 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200241}
242
243static u_int8_t bcdify(u_int8_t value)
244{
245 u_int8_t ret;
246
Harald Welte76042182009-08-08 16:03:15 +0200247 ret = value / 10;
248 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200249
250 return ret;
251}
252
253/* Generate 03.40 TP-SCTS */
254static void gsm340_gen_scts(u_int8_t *scts, time_t time)
255{
256 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200257
258 *scts++ = bcdify(tm->tm_year % 100);
259 *scts++ = bcdify(tm->tm_mon);
260 *scts++ = bcdify(tm->tm_mday);
261 *scts++ = bcdify(tm->tm_hour);
262 *scts++ = bcdify(tm->tm_min);
263 *scts++ = bcdify(tm->tm_sec);
264 *scts++ = 0; /* FIXME: timezone */
265}
266
Harald Welte76042182009-08-08 16:03:15 +0200267/* generate a msgb containing a TPDU derived from struct gsm_sms,
268 * returns total size of TPDU */
269static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200270{
Harald Weltef3efc592009-07-27 20:11:35 +0200271 u_int8_t *smsp;
272 u_int8_t oa[12]; /* max len per 03.40 */
273 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200274 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200275
276 /* generate first octet with masked bits */
277 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200278 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200279 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200280 /* TP-MMS (more messages to send) */
281 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200282 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200283 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200284 if (sms->status_rep_req)
285 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200286 /* TP-UDHI (indicating TP-UD contains a header) */
287 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200288 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200289#if 0
290 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200291 if (sms->
292 *smsp |= 0x80;
293#endif
294
295 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200296 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200297 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200298 memcpy(smsp, oa, oa_len);
299
300 /* generate TP-PID */
301 smsp = msgb_put(msg, 1);
302 *smsp = sms->protocol_id;
303
304 /* generate TP-DCS */
305 smsp = msgb_put(msg, 1);
306 *smsp = sms->data_coding_scheme;
307
308 /* generate TP-SCTS */
309 smsp = msgb_put(msg, 7);
310 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200311
Harald Weltef3efc592009-07-27 20:11:35 +0200312 /* generate TP-UDL */
313 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200314 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200315
316 /* generate TP-UD */
Harald Welte76042182009-08-08 16:03:15 +0200317 smsp = msgb_put(msg, sms->user_data_len);
318 memcpy(smsp, sms->user_data, sms->user_data_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200319
Harald Welte76042182009-08-08 16:03:15 +0200320 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200321}
322
Harald Welteb9c758b2009-07-05 14:02:46 +0200323/* process an incoming TPDU (called from RP-DATA)
324 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000325static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000326{
Harald Welte9176bd42009-07-23 18:46:00 +0200327 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000328 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000329 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200330 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
331 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000332 u_int8_t da_len_bytes;
333 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
334 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000335
Harald Welte76042182009-08-08 16:03:15 +0200336 gsms = sms_alloc();
337 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200338 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000339
340 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200341 sms_mti = *smsp & 0x03;
342 sms_mms = !!(*smsp & 0x04);
343 sms_vpf = (*smsp & 0x18) >> 3;
344 gsms->status_rep_req = (*smsp & 0x20);
345 gsms->ud_hdr_ind = (*smsp & 0x40);
346 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000347
348 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200349 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000350
Harald Welte7e310b12009-03-30 20:56:32 +0000351 /* length in bytes of the destination address */
352 da_len_bytes = 2 + *smsp/2 + *smsp%2;
353 if (da_len_bytes > 12) {
354 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200355 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000356 goto out;
357 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800358 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000359 memcpy(address_lv, smsp, da_len_bytes);
360 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800361 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000362 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200363 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000364 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000365
Harald Welte76042182009-08-08 16:03:15 +0200366 gsms->protocol_id = *smsp++;
367 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000368
Harald Welte76042182009-08-08 16:03:15 +0200369 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000370
Harald Welte76042182009-08-08 16:03:15 +0200371 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000372 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200373 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000374 break;
375 case GSM340_TP_VPF_ABSOLUTE:
376 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200377 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000378 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000379 break;
380 default:
381 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200382 sms_vpf);
383 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000384 }
Harald Welte76042182009-08-08 16:03:15 +0200385 gsms->user_data_len = *smsp++;
386 if (gsms->user_data_len) {
387 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000388
Harald Welte76042182009-08-08 16:03:15 +0200389 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000390 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200391 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000392 break;
393 case DCS_8BIT_DATA:
394 case DCS_UCS2:
395 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000396 break;
397 }
398 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000399
Harald Welte7e310b12009-03-30 20:56:32 +0000400 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
401 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200402 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
403 gsms->protocol_id, gsms->data_coding_scheme,
404 gsms->dest_addr, gsms->user_data_len,
405 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
406 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000407
Harald Welte76042182009-08-08 16:03:15 +0200408 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000409
Harald Welte76042182009-08-08 16:03:15 +0200410 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200411
Harald Welte76042182009-08-08 16:03:15 +0200412 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200413
Harald Welte7e310b12009-03-30 20:56:32 +0000414 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200415 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000416 if (!gsms->receiver) {
417 rc = 1; /* cause 1: unknown subscriber */
418 goto out;
419 }
420
Harald Welte76042182009-08-08 16:03:15 +0200421 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000422 case GSM340_SMS_SUBMIT_MS2SC:
423 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200424 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000425 break;
426 case GSM340_SMS_COMMAND_MS2SC:
427 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200428 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200429 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000430 break;
431 default:
Harald Welte76042182009-08-08 16:03:15 +0200432 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200433 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000434 break;
435 }
436
Harald Welteb9c758b2009-07-05 14:02:46 +0200437 if (!rc && !gsms->receiver)
438 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
439
Harald Welte7e310b12009-03-30 20:56:32 +0000440out:
Harald Welte76042182009-08-08 16:03:15 +0200441 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000442
Harald Welte7e310b12009-03-30 20:56:32 +0000443 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000444}
445
Harald Weltef3efc592009-07-27 20:11:35 +0200446static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000447{
448 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000449
Daniel Willmann471712b2008-12-29 01:54:02 +0000450 DEBUGP(DSMS, "TX: SMS RP ACK\n");
451
Harald Weltef3efc592009-07-27 20:11:35 +0200452 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000453}
454
Harald Weltef3efc592009-07-27 20:11:35 +0200455static int gsm411_send_rp_error(struct gsm_trans *trans,
456 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000457{
458 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000459
Harald Welte7e310b12009-03-30 20:56:32 +0000460 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000461
Harald Welte7e310b12009-03-30 20:56:32 +0000462 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000463
Harald Weltef3efc592009-07-27 20:11:35 +0200464 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000465}
466
Harald Welte7e310b12009-03-30 20:56:32 +0000467/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200468static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
469 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000470 u_int8_t src_len, u_int8_t *src,
471 u_int8_t dst_len, u_int8_t *dst,
472 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000473{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000474 int rc = 0;
475
Harald Welte7e310b12009-03-30 20:56:32 +0000476 if (src_len && src)
477 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
478
479 if (!dst_len || !dst || !tpdu_len || !tpdu) {
480 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200481 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200482 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000483 return -EIO;
484 }
485 msg->smsh = tpdu;
486
487 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000488
489 rc = gsm340_rx_tpdu(msg);
490 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200491 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000492 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200493 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000494 else
495 return rc;
496}
497
498/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200499static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
500 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000501{
502 u_int8_t src_len, dst_len, rpud_len;
503 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
504
505 /* in the MO case, this should always be zero length */
506 src_len = rph->data[0];
507 if (src_len)
508 src = &rph->data[1];
509
510 dst_len = rph->data[1+src_len];
511 if (dst_len)
512 dst = &rph->data[1+src_len+1];
513
514 rpud_len = rph->data[1+src_len+1+dst_len];
515 if (rpud_len)
516 rp_ud = &rph->data[1+src_len+1+dst_len+1];
517
Harald Welteb9c758b2009-07-05 14:02:46 +0200518 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
519 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200520 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000521 rpud_len, rp_ud);
522}
523
Harald Weltecb8f4432009-08-09 14:59:02 +0200524/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200525static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
526 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200527{
Harald Welte76042182009-08-08 16:03:15 +0200528 struct gsm_sms *sms = trans->sms.sms;
529
Harald Welteb9c758b2009-07-05 14:02:46 +0200530 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
531 * successfully received a SMS. We can now safely mark it as
532 * transmitted */
533
Harald Weltecb8f4432009-08-09 14:59:02 +0200534 if (!trans->sms.is_mt) {
535 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
536 return gsm411_send_rp_error(trans, rph->msg_ref,
537 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
538 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200539
Harald Welte76042182009-08-08 16:03:15 +0200540 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200541 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
542 return gsm411_send_rp_error(trans, rph->msg_ref,
543 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200544 }
545
546 /* mark this SMS as sent in database */
547 db_sms_mark_sent(sms);
548
549 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
550
551 sms_free(sms);
552 trans->sms.sms = NULL;
553
Harald Weltecf6a3812009-08-09 19:07:41 +0200554 /* do not free the transaction here, this is done by sending CP-ACK */
555
556 /* check for more messages for this subscriber */
557 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
558 if (sms)
559 gsm411_send_sms_lchan(msg->lchan, sms);
560 else
561 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200562
563 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200564}
565
Harald Weltef3efc592009-07-27 20:11:35 +0200566static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
567 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200568{
Harald Welte76042182009-08-08 16:03:15 +0200569 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200570 u_int8_t cause_len = rph->data[0];
571 u_int8_t cause = rph->data[1];
572
Harald Welteb9c758b2009-07-05 14:02:46 +0200573 /* Error in response to MT RP_DATA, i.e. the MS did not
574 * successfully receive the SMS. We need to investigate
575 * the cause and take action depending on it */
576
Harald Weltef3efc592009-07-27 20:11:35 +0200577 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
578
Harald Weltecb8f4432009-08-09 14:59:02 +0200579 if (!trans->sms.is_mt) {
580 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
581 return gsm411_send_rp_error(trans, rph->msg_ref,
582 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
583 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200584
Harald Welte76042182009-08-08 16:03:15 +0200585 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200586 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
587 return gsm411_send_rp_error(trans, rph->msg_ref,
588 GSM411_RP_CAUSE_PROTOCOL_ERR);
589 }
590
591 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
592 /* MS has not enough memory to store the message. We need
593 * to store this in our database and wati for a SMMA message */
594 /* FIXME */
595 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200596 }
597
598 sms_free(sms);
599 trans->sms.sms = NULL;
600
Harald Weltecb8f4432009-08-09 14:59:02 +0200601 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200602
Harald Weltef3efc592009-07-27 20:11:35 +0200603 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200604}
605
Harald Weltef3efc592009-07-27 20:11:35 +0200606static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
607 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200608{
Harald Weltecf6a3812009-08-09 19:07:41 +0200609 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200610 int rc;
611
Harald Weltecf6a3812009-08-09 19:07:41 +0200612 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
613 trans->sms.rp_state = GSM411_RPS_IDLE;
614
Harald Welteb9c758b2009-07-05 14:02:46 +0200615 /* MS tells us that it has memory for more SMS, we need
616 * to check if we have any pending messages for it and then
617 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200618 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200619
Harald Weltecf6a3812009-08-09 19:07:41 +0200620 /* check for more messages for this subscriber */
621 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
622 if (sms)
623 gsm411_send_sms_lchan(msg->lchan, sms);
624 else
625 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200626
627 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200628}
629
Harald Weltef3efc592009-07-27 20:11:35 +0200630static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
631 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000632{
Daniel Willmann471712b2008-12-29 01:54:02 +0000633 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000634 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000635 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000636
637 switch (msg_type) {
638 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200639 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
640 /* start TR2N and enter 'wait to send RP-ACK state' */
641 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
642 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000643 break;
644 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200645 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
646 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200647 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000648 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200649 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
650 /* start TR2N and enter 'wait to send RP-ACK state' */
651 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
652 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
653 break;
654 case GSM411_MT_RP_ERROR_MO:
655 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000656 break;
657 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000658 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200659 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
660 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000661 break;
662 }
663
664 return rc;
665}
666
Harald Weltef3efc592009-07-27 20:11:35 +0200667/* send CP-ACK to given transaction */
668static int gsm411_tx_cp_ack(struct gsm_trans *trans)
669{
670 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200671 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200672
Harald Weltecf6a3812009-08-09 19:07:41 +0200673 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
674
675 if (trans->sms.is_mt) {
676 /* If this is a MT SMS DELIVER, we can clear transaction here */
677 trans->sms.cp_state = GSM411_CPS_IDLE;
678 trans_free(trans);
679 }
Harald Weltef3efc592009-07-27 20:11:35 +0200680}
681
682static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
683{
684 struct msgb *msg = gsm411_msgb_alloc();
685 u_int8_t *causep;
686
Harald Welte76042182009-08-08 16:03:15 +0200687 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200688 *causep = cause;
689
690 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
691}
692
693/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000694int gsm0411_rcv_sms(struct msgb *msg)
695{
696 struct gsm48_hdr *gh = msgb_l3(msg);
697 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200698 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
699 struct gsm_lchan *lchan = msg->lchan;
700 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000701 int rc = 0;
702
Harald Weltef3efc592009-07-27 20:11:35 +0200703 if (!lchan->subscr)
704 return -EIO;
705 /* FIXME: send some error message */
706
707 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
708 transaction_id);
709 if (!trans) {
710 DEBUGP(DSMS, "Unknown transaction ID %x, "
711 "creating new trans\n", transaction_id);
712 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
713 transaction_id, new_callref++);
714 if (!trans) {
715 DEBUGP(DSMS, "No memory for trans\n");
716 /* FIXME: send some error message */
717 return -ENOMEM;
718 }
719 trans->sms.cp_state = GSM411_CPS_IDLE;
720 trans->sms.rp_state = GSM411_RPS_IDLE;
721 trans->sms.is_mt = 0;
722
723 trans->lchan = lchan;
724 use_lchan(lchan);
725 }
726
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000727 switch(msg_type) {
728 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200729 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200730 /* 5.2.3.1.3: MO state exists when SMC has received
731 * CP-DATA, including sending of the assoc. CP-ACK */
732 /* 5.2.3.2.4: MT state exists when SMC has received
733 * CP-DATA, including sending of the assoc. CP-ACK */
734 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200735
736 rc = gsm411_rx_cp_data(msg, gh, trans);
737 /* Send CP-ACK or CP-ERORR in response */
738 if (rc < 0) {
739 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
740 } else
741 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000742 break;
743 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200744 /* previous CP-DATA in this transaction was confirmed */
745 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200746 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
747 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
748 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200749 /* Stop TC1* after CP-ACK has been received */
750 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200751
Harald Weltef3efc592009-07-27 20:11:35 +0200752 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200753 /* FIXME: we have sont one CP-DATA, which was now
754 * acknowledged. Check if we want to transfer more,
755 * i.e. multi-part message */
756 trans->sms.cp_state = GSM411_CPS_IDLE;
757 trans_free(trans);
758 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000759 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000760 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200761 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
Harald Welte41985612009-08-10 00:24:32 +0200762 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200763 trans->sms.cp_state = GSM411_CPS_IDLE;
764 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000765 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000766 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200767 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
768 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200769 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200770 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000771 break;
772 }
773
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000774 return rc;
775}
776
Harald Welte8c2e36e2008-12-30 15:00:14 +0000777#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000778/* Test TPDU - ALL YOUR */
779static u_int8_t tpdu_test[] = {
780 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
781 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
782 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
783 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000784};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000785#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000786
Harald Weltecf6a3812009-08-09 19:07:41 +0200787/* Take a SMS in gsm_sms structure and send it through an already
788 * existing lchan. We also assume that the caller ensured this lchan already
789 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200790int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000791{
792 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200793 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200794 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200795 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200796 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200797 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000798
Harald Weltecf6a3812009-08-09 19:07:41 +0200799 transaction_id = 4; /* FIXME: we always use 4 for now */
800
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000801 msg->lchan = lchan;
802
Harald Welte76042182009-08-08 16:03:15 +0200803 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200804
Harald Welte76042182009-08-08 16:03:15 +0200805 /* FIXME: allocate transaction with message reference */
806 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
807 transaction_id, new_callref++);
808 if (!trans) {
809 DEBUGP(DSMS, "No memory for trans\n");
810 /* FIXME: send some error message */
811 return -ENOMEM;
812 }
813 trans->sms.cp_state = GSM411_CPS_IDLE;
814 trans->sms.rp_state = GSM411_RPS_IDLE;
815 trans->sms.is_mt = 1;
816 trans->sms.sms = sms;
817
818 trans->lchan = lchan;
819 use_lchan(lchan);
820
821 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000822 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200823 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200824 data[1] = 0x91; /* type of number: international, ISDN */
825 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000826 data[3] = 0x77;
827 data[4] = 0x58;
828 data[5] = 0x10;
829 data[6] = 0x06;
830 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200831
832 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000833 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200834 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000835
Harald Welte76042182009-08-08 16:03:15 +0200836 /* obtain a pointer for the rp_ud_len, so we can fill it later */
837 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000838
Harald Welte76042182009-08-08 16:03:15 +0200839#if 1
840 /* generate the 03.40 TPDU */
841 rc = gsm340_gen_tpdu(msg, sms);
842 if (rc < 0) {
843 msgb_free(msg);
844 return rc;
845 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000846
Harald Welte76042182009-08-08 16:03:15 +0200847 *rp_ud_len = rc;
848#else
849 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000850 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200851 *rp_ud_len = sizeof(tpdu_test);
852#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000853
Harald Welte76042182009-08-08 16:03:15 +0200854 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000855
Harald Weltef3efc592009-07-27 20:11:35 +0200856 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
857 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000858}
Harald Weltef3efc592009-07-27 20:11:35 +0200859
Harald Weltecf6a3812009-08-09 19:07:41 +0200860/* RLL SAPI3 establish callback. Now we have a RLL connection and
861 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200862static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
863 void *_sms, enum bsc_rllr_ind type)
864{
865 struct gsm_sms *sms = _sms;
866
867 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
868 lchan, link_id, sms, type);
869
870 switch (type) {
871 case BSC_RLLR_IND_EST_CONF:
872 gsm411_send_sms_lchan(lchan, sms);
873 break;
874 case BSC_RLLR_IND_REL_IND:
875 case BSC_RLLR_IND_ERR_IND:
876 case BSC_RLLR_IND_TIMEOUT:
877 sms_free(sms);
878 break;
879 }
880}
881
Harald Weltecf6a3812009-08-09 19:07:41 +0200882/* paging callback. Here we get called if paging a subscriber has
883 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200884static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
885 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200886{
Harald Welte76042182009-08-08 16:03:15 +0200887 struct gsm_lchan *lchan = _lchan;
888 struct gsm_sms *sms = _sms;
889 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200890
Harald Welte76042182009-08-08 16:03:15 +0200891 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
892 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
893
894 if (hooknum != GSM_HOOK_RR_PAGING)
895 return -EINVAL;
896
897 switch (event) {
898 case GSM_PAGING_SUCCEEDED:
899 /* Paging aborted without lchan ?!? */
900 if (!lchan) {
901 sms_free(sms);
902 rc = -EIO;
903 break;
904 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200905 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200906 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200907 break;
908 case GSM_PAGING_EXPIRED:
909 sms_free(sms);
910 rc = -ETIMEDOUT;
911 break;
912 default:
913 rc = -EINVAL;
914 break;
915 }
916
917 return rc;
918}
919
Harald Weltecf6a3812009-08-09 19:07:41 +0200920/* high-level function to send a SMS to a given subscriber. The function
921 * will take care of paging the subscriber, establishing the RLL SAPI3
922 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200923int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
924 struct gsm_sms *sms)
925{
Harald Weltecf6a3812009-08-09 19:07:41 +0200926 struct gsm_lchan *lchan;
927
Harald Welte76042182009-08-08 16:03:15 +0200928 /* check if we already have an open lchan to the subscriber.
929 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200930 lchan = lchan_for_subscr(subscr);
931 if (lchan)
932 return rll_establish(lchan, UM_SAPI_SMS,
933 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200934
935 /* if not, we have to start paging */
936 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
937 paging_cb_send_sms, sms);
938
939 return 0;
940}
Harald Welte3366a942009-07-28 00:44:49 +0200941
Harald Weltecf6a3812009-08-09 19:07:41 +0200942static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
943 void *handler_data, void *signal_data)
944{
945 struct gsm_subscriber *subscr;
946 struct gsm_lchan *lchan;
947 struct gsm_sms *sms;
948
949 switch (signal) {
950 case S_SUBSCR_ATTACHED:
951 /* A subscriber has attached. Check if there are
952 * any pending SMS for him to be delivered */
953 subscr = signal_data;
954 lchan = lchan_for_subscr(subscr);
955 if (!lchan)
956 break;
957 sms = db_sms_get_unsent_for_subscr(subscr);
958 if (!sms)
959 break;
960 /* Establish a SAPI3 RLL connection for SMS */
961 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
962 break;
963 default:
964 break;
965 }
966 return 0;
967}
968
Harald Welte7bfc2672009-07-28 00:41:45 +0200969static __attribute__((constructor)) void on_dso_load_sms(void)
970{
Harald Welte7bfc2672009-07-28 00:41:45 +0200971 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200972
973 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200974}