blob: 246847bf2903fd2049dd45b52f1d1221f5cbb5a7 [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>
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020049#include <openbsc/chan_alloc.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000050
Daniel Willmann471712b2008-12-29 01:54:02 +000051#define GSM411_ALLOC_SIZE 1024
52#define GSM411_ALLOC_HEADROOM 128
53
Harald Weltecb8f4432009-08-09 14:59:02 +020054#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
55
Harald Welte2cf161b2009-06-20 22:36:41 +020056static void *tall_gsms_ctx;
57
Harald Weltef3efc592009-07-27 20:11:35 +020058static u_int32_t new_callref = 0x40000001;
59
Harald Welte76042182009-08-08 16:03:15 +020060struct gsm_sms *sms_alloc(void)
61{
62 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
63}
64
65void sms_free(struct gsm_sms *sms)
66{
67 /* drop references to subscriber structure */
68 if (sms->sender)
69 subscr_put(sms->sender);
70 if (sms->receiver)
71 subscr_put(sms->receiver);
72
73 talloc_free(sms);
74}
75
Holger Freythera553d092009-01-04 20:16:25 +000076struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000077{
Harald Welte966636f2009-06-26 19:39:35 +020078 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
79 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +000080}
81
Harald Welte87f5d632009-07-04 17:39:00 +020082static int gsm411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000083{
84 if (msg->lchan)
85 msg->trx = msg->lchan->ts->trx;
86
87 msg->l3h = msg->data;
88
Harald Welte76042182009-08-08 16:03:15 +020089 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
90
Harald Weltecb8f4432009-08-09 14:59:02 +020091 return rsl_data_request(msg, UM_SAPI_SMS);
Daniel Willmann471712b2008-12-29 01:54:02 +000092}
93
Harald Welte41985612009-08-10 00:24:32 +020094/* SMC TC1* is expired */
95static void cp_timer_expired(void *data)
96{
97 struct gsm_trans *trans = data;
98
99 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
100 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
101 trans_free(trans);
102}
103
Harald Welte87f5d632009-07-04 17:39:00 +0200104/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200105static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
106 u_int8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +0200107{
108 struct gsm48_hdr *gh;
109
110 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
111 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +0200112 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200113 gh->msg_type = msg_type;
114
Harald Weltef3efc592009-07-27 20:11:35 +0200115 /* assign the outgoing lchan */
116 msg->lchan = trans->lchan;
117
118 /* mobile originating */
119 switch (gh->msg_type) {
120 case GSM411_MT_CP_DATA:
121 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Weltecb8f4432009-08-09 14:59:02 +0200122 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200123 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte41985612009-08-10 00:24:32 +0200124 trans->sms.cp_timer.data = trans;
125 trans->sms.cp_timer.cb = cp_timer_expired;
126 /* 5.3.2.1: Set Timer TC1A */
127 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Weltef3efc592009-07-27 20:11:35 +0200128 break;
129 }
130
Harald Welte87f5d632009-07-04 17:39:00 +0200131 return gsm411_sendmsg(msg);
132}
133
134/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200135static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
136 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte87f5d632009-07-04 17:39:00 +0200137{
138 struct gsm411_rp_hdr *rp;
Harald Welte0d544e72009-08-10 00:22:19 +0200139 u_int8_t len = msg->len;
Harald Welte87f5d632009-07-04 17:39:00 +0200140
141 /* GSM 04.11 RP-DATA header */
142 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Welte0d544e72009-08-10 00:22:19 +0200143 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200144 rp->msg_type = rp_msg_type;
145 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
146
Harald Weltef3efc592009-07-27 20:11:35 +0200147 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200148}
149
Harald Welte76042182009-08-08 16:03:15 +0200150static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000151{
152 u_int8_t vp;
153 unsigned long minutes;
154
Harald Welte76042182009-08-08 16:03:15 +0200155 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000156 case GSM340_TP_VPF_RELATIVE:
157 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200158 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000159 if (vp <= 143)
160 minutes = vp + 1 * 5;
161 else if (vp <= 167)
162 minutes = 12*60 + (vp-143) * 30;
163 else if (vp <= 196)
164 minutes = vp-166 * 60 * 24;
165 else
166 minutes = vp-192 * 60 * 24 * 7;
167 break;
168 case GSM340_TP_VPF_ABSOLUTE:
169 /* Chapter 9.2.3.12.2 */
170 /* FIXME: like service center time stamp */
171 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
172 break;
173 case GSM340_TP_VPF_ENHANCED:
174 /* Chapter 9.2.3.12.3 */
175 /* FIXME: implementation */
176 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
177 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200178 case GSM340_TP_VPF_NONE:
179 /* Default validity: two days */
180 minutes = 24 * 60 * 2;
181 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000182 }
183 return minutes;
184}
185
186/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
187enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
188{
189 u_int8_t cgbits = dcs >> 4;
190 enum sms_alphabet alpha = DCS_NONE;
191
192 if ((cgbits & 0xc) == 0) {
193 if (cgbits & 2)
194 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
195
196 switch (dcs & 3) {
197 case 0:
198 alpha = DCS_7BIT_DEFAULT;
199 break;
200 case 1:
201 alpha = DCS_8BIT_DATA;
202 break;
203 case 2:
204 alpha = DCS_UCS2;
205 break;
206 }
207 } else if (cgbits == 0xc || cgbits == 0xd)
208 alpha = DCS_7BIT_DEFAULT;
209 else if (cgbits == 0xe)
210 alpha = DCS_UCS2;
211 else if (cgbits == 0xf) {
212 if (dcs & 4)
213 alpha = DCS_8BIT_DATA;
214 else
215 alpha = DCS_7BIT_DEFAULT;
216 }
217
218 return alpha;
219}
220
Harald Welte76042182009-08-08 16:03:15 +0200221static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000222{
223 if (db_sms_store(gsms) != 0) {
224 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200225 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000226 }
Harald Welte76042182009-08-08 16:03:15 +0200227 /* dispatch a signal to tell higher level about it */
228 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000229 return 0;
230}
231
Harald Welte76042182009-08-08 16:03:15 +0200232/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
233static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
234 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200235{
Harald Welte76042182009-08-08 16:03:15 +0200236 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200237
Harald Welte76042182009-08-08 16:03:15 +0200238 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
239
240 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
241
242 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
243 oa[0] = strlen(subscr->extension) & 0xff;
244
245 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200246}
247
248static u_int8_t bcdify(u_int8_t value)
249{
250 u_int8_t ret;
251
Harald Welte76042182009-08-08 16:03:15 +0200252 ret = value / 10;
253 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200254
255 return ret;
256}
257
258/* Generate 03.40 TP-SCTS */
259static void gsm340_gen_scts(u_int8_t *scts, time_t time)
260{
261 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200262
263 *scts++ = bcdify(tm->tm_year % 100);
264 *scts++ = bcdify(tm->tm_mon);
265 *scts++ = bcdify(tm->tm_mday);
266 *scts++ = bcdify(tm->tm_hour);
267 *scts++ = bcdify(tm->tm_min);
268 *scts++ = bcdify(tm->tm_sec);
269 *scts++ = 0; /* FIXME: timezone */
270}
271
Harald Welte76042182009-08-08 16:03:15 +0200272/* generate a msgb containing a TPDU derived from struct gsm_sms,
273 * returns total size of TPDU */
274static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200275{
Harald Weltef3efc592009-07-27 20:11:35 +0200276 u_int8_t *smsp;
277 u_int8_t oa[12]; /* max len per 03.40 */
278 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200279 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200280
281 /* generate first octet with masked bits */
282 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200283 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200284 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200285 /* TP-MMS (more messages to send) */
286 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200287 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200288 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200289 if (sms->status_rep_req)
290 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200291 /* TP-UDHI (indicating TP-UD contains a header) */
292 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200293 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200294#if 0
295 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200296 if (sms->
297 *smsp |= 0x80;
298#endif
299
300 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200301 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200302 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200303 memcpy(smsp, oa, oa_len);
304
305 /* generate TP-PID */
306 smsp = msgb_put(msg, 1);
307 *smsp = sms->protocol_id;
308
309 /* generate TP-DCS */
310 smsp = msgb_put(msg, 1);
311 *smsp = sms->data_coding_scheme;
312
313 /* generate TP-SCTS */
314 smsp = msgb_put(msg, 7);
315 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200316
Harald Weltef3efc592009-07-27 20:11:35 +0200317 /* generate TP-UDL */
318 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200319 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200320
321 /* generate TP-UD */
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200322 /* FIXME: Handle DSC of UCS2 or 8/bit default */
323 if (gsm338_get_sms_alphabet(sms->data_coding_scheme) == DCS_7BIT_DEFAULT) {
324 /* Warning, user_data_len indicates the amount of septets
325 * (characters), we need amount of octets occupied */
326 smsp = msgb_put(msg, ceil(sms->user_data_len*7/8.0));
327 memcpy(smsp, sms->user_data, ceil(sms->user_data_len*7/8.0));
328 }
Harald Weltef3efc592009-07-27 20:11:35 +0200329
Harald Welte76042182009-08-08 16:03:15 +0200330 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200331}
332
Harald Welteb9c758b2009-07-05 14:02:46 +0200333/* process an incoming TPDU (called from RP-DATA)
334 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000335static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000336{
Harald Welte9176bd42009-07-23 18:46:00 +0200337 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000338 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000339 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200340 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
341 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000342 u_int8_t da_len_bytes;
343 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
344 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000345
Harald Welte76042182009-08-08 16:03:15 +0200346 gsms = sms_alloc();
347 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200348 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000349
350 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200351 sms_mti = *smsp & 0x03;
352 sms_mms = !!(*smsp & 0x04);
353 sms_vpf = (*smsp & 0x18) >> 3;
354 gsms->status_rep_req = (*smsp & 0x20);
355 gsms->ud_hdr_ind = (*smsp & 0x40);
356 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000357
358 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200359 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000360
Harald Welte7e310b12009-03-30 20:56:32 +0000361 /* length in bytes of the destination address */
362 da_len_bytes = 2 + *smsp/2 + *smsp%2;
363 if (da_len_bytes > 12) {
364 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200365 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000366 goto out;
367 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800368 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000369 memcpy(address_lv, smsp, da_len_bytes);
370 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800371 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000372 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200373 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000374 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000375
Harald Welte76042182009-08-08 16:03:15 +0200376 gsms->protocol_id = *smsp++;
377 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000378
Harald Welte76042182009-08-08 16:03:15 +0200379 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000380
Harald Welte76042182009-08-08 16:03:15 +0200381 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000382 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200383 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000384 break;
385 case GSM340_TP_VPF_ABSOLUTE:
386 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200387 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000388 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000389 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200390 case GSM340_TP_VPF_NONE:
391 sms_vp = 0;
392 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000393 default:
394 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200395 sms_vpf);
396 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000397 }
Harald Welte76042182009-08-08 16:03:15 +0200398 gsms->user_data_len = *smsp++;
399 if (gsms->user_data_len) {
400 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000401
Harald Welte76042182009-08-08 16:03:15 +0200402 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000403 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200404 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000405 break;
406 case DCS_8BIT_DATA:
407 case DCS_UCS2:
408 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000409 break;
410 }
411 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000412
Harald Welte7e310b12009-03-30 20:56:32 +0000413 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
414 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200415 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
416 gsms->protocol_id, gsms->data_coding_scheme,
417 gsms->dest_addr, gsms->user_data_len,
418 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
419 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000420
Harald Welte76042182009-08-08 16:03:15 +0200421 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000422
Harald Welte76042182009-08-08 16:03:15 +0200423 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200424
Harald Welte76042182009-08-08 16:03:15 +0200425 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200426
Harald Welte7e310b12009-03-30 20:56:32 +0000427 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200428 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000429 if (!gsms->receiver) {
430 rc = 1; /* cause 1: unknown subscriber */
431 goto out;
432 }
433
Harald Welte76042182009-08-08 16:03:15 +0200434 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000435 case GSM340_SMS_SUBMIT_MS2SC:
436 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200437 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000438 break;
439 case GSM340_SMS_COMMAND_MS2SC:
440 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200441 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200442 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000443 break;
444 default:
Harald Welte76042182009-08-08 16:03:15 +0200445 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200446 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000447 break;
448 }
449
Harald Welteb9c758b2009-07-05 14:02:46 +0200450 if (!rc && !gsms->receiver)
451 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
452
Harald Welte7e310b12009-03-30 20:56:32 +0000453out:
Harald Welte76042182009-08-08 16:03:15 +0200454 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000455
Harald Welte7e310b12009-03-30 20:56:32 +0000456 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000457}
458
Harald Weltef3efc592009-07-27 20:11:35 +0200459static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000460{
461 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000462
Daniel Willmann471712b2008-12-29 01:54:02 +0000463 DEBUGP(DSMS, "TX: SMS RP ACK\n");
464
Harald Weltef3efc592009-07-27 20:11:35 +0200465 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000466}
467
Harald Weltef3efc592009-07-27 20:11:35 +0200468static int gsm411_send_rp_error(struct gsm_trans *trans,
469 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000470{
471 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000472
Harald Welte7e310b12009-03-30 20:56:32 +0000473 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000474
Harald Welte7e310b12009-03-30 20:56:32 +0000475 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000476
Harald Weltef3efc592009-07-27 20:11:35 +0200477 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000478}
479
Harald Welte7e310b12009-03-30 20:56:32 +0000480/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200481static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
482 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000483 u_int8_t src_len, u_int8_t *src,
484 u_int8_t dst_len, u_int8_t *dst,
485 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000486{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000487 int rc = 0;
488
Harald Welte7e310b12009-03-30 20:56:32 +0000489 if (src_len && src)
490 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
491
492 if (!dst_len || !dst || !tpdu_len || !tpdu) {
493 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200494 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200495 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000496 return -EIO;
497 }
498 msg->smsh = tpdu;
499
500 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000501
502 rc = gsm340_rx_tpdu(msg);
503 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200504 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000505 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200506 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000507 else
508 return rc;
509}
510
511/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200512static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
513 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000514{
515 u_int8_t src_len, dst_len, rpud_len;
516 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
517
518 /* in the MO case, this should always be zero length */
519 src_len = rph->data[0];
520 if (src_len)
521 src = &rph->data[1];
522
523 dst_len = rph->data[1+src_len];
524 if (dst_len)
525 dst = &rph->data[1+src_len+1];
526
527 rpud_len = rph->data[1+src_len+1+dst_len];
528 if (rpud_len)
529 rp_ud = &rph->data[1+src_len+1+dst_len+1];
530
Harald Welteb9c758b2009-07-05 14:02:46 +0200531 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
532 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200533 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000534 rpud_len, rp_ud);
535}
536
Harald Weltecb8f4432009-08-09 14:59:02 +0200537/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200538static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
539 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200540{
Harald Welte76042182009-08-08 16:03:15 +0200541 struct gsm_sms *sms = trans->sms.sms;
542
Harald Welteb9c758b2009-07-05 14:02:46 +0200543 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
544 * successfully received a SMS. We can now safely mark it as
545 * transmitted */
546
Harald Weltecb8f4432009-08-09 14:59:02 +0200547 if (!trans->sms.is_mt) {
548 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
549 return gsm411_send_rp_error(trans, rph->msg_ref,
550 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
551 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200552
Harald Welte76042182009-08-08 16:03:15 +0200553 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200554 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
555 return gsm411_send_rp_error(trans, rph->msg_ref,
556 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200557 }
558
559 /* mark this SMS as sent in database */
560 db_sms_mark_sent(sms);
561
562 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
563
564 sms_free(sms);
565 trans->sms.sms = NULL;
566
Harald Weltecf6a3812009-08-09 19:07:41 +0200567 /* do not free the transaction here, this is done by sending CP-ACK */
568
569 /* check for more messages for this subscriber */
570 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
571 if (sms)
572 gsm411_send_sms_lchan(msg->lchan, sms);
573 else
574 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200575
576 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200577}
578
Harald Weltef3efc592009-07-27 20:11:35 +0200579static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
580 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200581{
Harald Welte76042182009-08-08 16:03:15 +0200582 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200583 u_int8_t cause_len = rph->data[0];
584 u_int8_t cause = rph->data[1];
585
Harald Welteb9c758b2009-07-05 14:02:46 +0200586 /* Error in response to MT RP_DATA, i.e. the MS did not
587 * successfully receive the SMS. We need to investigate
588 * the cause and take action depending on it */
589
Harald Weltef3efc592009-07-27 20:11:35 +0200590 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
591
Harald Weltecb8f4432009-08-09 14:59:02 +0200592 if (!trans->sms.is_mt) {
593 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
594 return gsm411_send_rp_error(trans, rph->msg_ref,
595 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
596 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200597
Harald Welte76042182009-08-08 16:03:15 +0200598 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200599 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
600 return gsm411_send_rp_error(trans, rph->msg_ref,
601 GSM411_RP_CAUSE_PROTOCOL_ERR);
602 }
603
604 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
605 /* MS has not enough memory to store the message. We need
606 * to store this in our database and wati for a SMMA message */
607 /* FIXME */
608 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200609 }
610
611 sms_free(sms);
612 trans->sms.sms = NULL;
613
Harald Weltecb8f4432009-08-09 14:59:02 +0200614 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200615
Harald Weltef3efc592009-07-27 20:11:35 +0200616 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200617}
618
Harald Weltef3efc592009-07-27 20:11:35 +0200619static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
620 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200621{
Harald Weltecf6a3812009-08-09 19:07:41 +0200622 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200623 int rc;
624
Harald Weltecf6a3812009-08-09 19:07:41 +0200625 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
626 trans->sms.rp_state = GSM411_RPS_IDLE;
627
Harald Welteb9c758b2009-07-05 14:02:46 +0200628 /* MS tells us that it has memory for more SMS, we need
629 * to check if we have any pending messages for it and then
630 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200631 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200632
Harald Weltecf6a3812009-08-09 19:07:41 +0200633 /* check for more messages for this subscriber */
634 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
635 if (sms)
636 gsm411_send_sms_lchan(msg->lchan, sms);
637 else
638 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200639
640 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200641}
642
Harald Weltef3efc592009-07-27 20:11:35 +0200643static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
644 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000645{
Daniel Willmann471712b2008-12-29 01:54:02 +0000646 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000647 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000648 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000649
650 switch (msg_type) {
651 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200652 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
653 /* start TR2N and enter 'wait to send RP-ACK state' */
654 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
655 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000656 break;
657 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200658 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
659 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200660 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000661 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200662 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
663 /* start TR2N and enter 'wait to send RP-ACK state' */
664 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
665 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
666 break;
667 case GSM411_MT_RP_ERROR_MO:
668 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000669 break;
670 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000671 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200672 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
673 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000674 break;
675 }
676
677 return rc;
678}
679
Harald Weltef3efc592009-07-27 20:11:35 +0200680/* send CP-ACK to given transaction */
681static int gsm411_tx_cp_ack(struct gsm_trans *trans)
682{
683 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200684 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200685
Harald Weltecf6a3812009-08-09 19:07:41 +0200686 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
687
688 if (trans->sms.is_mt) {
689 /* If this is a MT SMS DELIVER, we can clear transaction here */
690 trans->sms.cp_state = GSM411_CPS_IDLE;
691 trans_free(trans);
692 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200693
694 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200695}
696
697static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
698{
699 struct msgb *msg = gsm411_msgb_alloc();
700 u_int8_t *causep;
701
Harald Welte76042182009-08-08 16:03:15 +0200702 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200703 *causep = cause;
704
705 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
706}
707
708/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000709int gsm0411_rcv_sms(struct msgb *msg)
710{
711 struct gsm48_hdr *gh = msgb_l3(msg);
712 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200713 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
714 struct gsm_lchan *lchan = msg->lchan;
715 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000716 int rc = 0;
717
Harald Weltef3efc592009-07-27 20:11:35 +0200718 if (!lchan->subscr)
719 return -EIO;
720 /* FIXME: send some error message */
721
722 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
723 transaction_id);
724 if (!trans) {
725 DEBUGP(DSMS, "Unknown transaction ID %x, "
726 "creating new trans\n", transaction_id);
727 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
728 transaction_id, new_callref++);
729 if (!trans) {
730 DEBUGP(DSMS, "No memory for trans\n");
731 /* FIXME: send some error message */
732 return -ENOMEM;
733 }
734 trans->sms.cp_state = GSM411_CPS_IDLE;
735 trans->sms.rp_state = GSM411_RPS_IDLE;
736 trans->sms.is_mt = 0;
737
738 trans->lchan = lchan;
739 use_lchan(lchan);
740 }
741
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000742 switch(msg_type) {
743 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200744 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200745 /* 5.2.3.1.3: MO state exists when SMC has received
746 * CP-DATA, including sending of the assoc. CP-ACK */
747 /* 5.2.3.2.4: MT state exists when SMC has received
748 * CP-DATA, including sending of the assoc. CP-ACK */
749 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200750
751 rc = gsm411_rx_cp_data(msg, gh, trans);
752 /* Send CP-ACK or CP-ERORR in response */
753 if (rc < 0) {
754 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
755 } else
756 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000757 break;
758 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200759 /* previous CP-DATA in this transaction was confirmed */
760 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200761 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
762 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
763 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200764 /* Stop TC1* after CP-ACK has been received */
765 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200766
Harald Weltef3efc592009-07-27 20:11:35 +0200767 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200768 /* FIXME: we have sont one CP-DATA, which was now
769 * acknowledged. Check if we want to transfer more,
770 * i.e. multi-part message */
771 trans->sms.cp_state = GSM411_CPS_IDLE;
772 trans_free(trans);
773 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000774 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000775 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200776 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
Harald Welte41985612009-08-10 00:24:32 +0200777 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200778 trans->sms.cp_state = GSM411_CPS_IDLE;
779 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000780 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000781 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200782 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
783 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200784 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200785 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000786 break;
787 }
788
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000789 return rc;
790}
791
Harald Welte8c2e36e2008-12-30 15:00:14 +0000792#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000793/* Test TPDU - ALL YOUR */
794static u_int8_t tpdu_test[] = {
795 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
796 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
797 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
798 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000799};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000800#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000801
Harald Weltecf6a3812009-08-09 19:07:41 +0200802/* Take a SMS in gsm_sms structure and send it through an already
803 * existing lchan. We also assume that the caller ensured this lchan already
804 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200805int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000806{
807 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200808 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200809 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200810 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200811 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200812 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000813
Harald Weltecf6a3812009-08-09 19:07:41 +0200814 transaction_id = 4; /* FIXME: we always use 4 for now */
815
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000816 msg->lchan = lchan;
817
Harald Welte76042182009-08-08 16:03:15 +0200818 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200819
Harald Welte76042182009-08-08 16:03:15 +0200820 /* FIXME: allocate transaction with message reference */
821 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
822 transaction_id, new_callref++);
823 if (!trans) {
824 DEBUGP(DSMS, "No memory for trans\n");
825 /* FIXME: send some error message */
826 return -ENOMEM;
827 }
828 trans->sms.cp_state = GSM411_CPS_IDLE;
829 trans->sms.rp_state = GSM411_RPS_IDLE;
830 trans->sms.is_mt = 1;
831 trans->sms.sms = sms;
832
833 trans->lchan = lchan;
834 use_lchan(lchan);
835
836 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000837 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200838 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200839 data[1] = 0x91; /* type of number: international, ISDN */
840 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000841 data[3] = 0x77;
842 data[4] = 0x58;
843 data[5] = 0x10;
844 data[6] = 0x06;
845 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200846
847 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000848 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200849 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000850
Harald Welte76042182009-08-08 16:03:15 +0200851 /* obtain a pointer for the rp_ud_len, so we can fill it later */
852 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000853
Harald Welte76042182009-08-08 16:03:15 +0200854#if 1
855 /* generate the 03.40 TPDU */
856 rc = gsm340_gen_tpdu(msg, sms);
857 if (rc < 0) {
858 msgb_free(msg);
859 return rc;
860 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000861
Harald Welte76042182009-08-08 16:03:15 +0200862 *rp_ud_len = rc;
863#else
864 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000865 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200866 *rp_ud_len = sizeof(tpdu_test);
867#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000868
Harald Welte76042182009-08-08 16:03:15 +0200869 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000870
Harald Weltef3efc592009-07-27 20:11:35 +0200871 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
872 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000873}
Harald Weltef3efc592009-07-27 20:11:35 +0200874
Harald Weltecf6a3812009-08-09 19:07:41 +0200875/* RLL SAPI3 establish callback. Now we have a RLL connection and
876 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200877static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
878 void *_sms, enum bsc_rllr_ind type)
879{
880 struct gsm_sms *sms = _sms;
881
882 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
883 lchan, link_id, sms, type);
884
885 switch (type) {
886 case BSC_RLLR_IND_EST_CONF:
887 gsm411_send_sms_lchan(lchan, sms);
888 break;
889 case BSC_RLLR_IND_REL_IND:
890 case BSC_RLLR_IND_ERR_IND:
891 case BSC_RLLR_IND_TIMEOUT:
892 sms_free(sms);
893 break;
894 }
895}
896
Harald Weltecf6a3812009-08-09 19:07:41 +0200897/* paging callback. Here we get called if paging a subscriber has
898 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200899static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
900 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200901{
Harald Welte76042182009-08-08 16:03:15 +0200902 struct gsm_lchan *lchan = _lchan;
903 struct gsm_sms *sms = _sms;
904 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200905
Harald Welte76042182009-08-08 16:03:15 +0200906 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
907 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
908
909 if (hooknum != GSM_HOOK_RR_PAGING)
910 return -EINVAL;
911
912 switch (event) {
913 case GSM_PAGING_SUCCEEDED:
914 /* Paging aborted without lchan ?!? */
915 if (!lchan) {
916 sms_free(sms);
917 rc = -EIO;
918 break;
919 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200920 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200921 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200922 break;
923 case GSM_PAGING_EXPIRED:
924 sms_free(sms);
925 rc = -ETIMEDOUT;
926 break;
927 default:
928 rc = -EINVAL;
929 break;
930 }
931
932 return rc;
933}
934
Harald Weltecf6a3812009-08-09 19:07:41 +0200935/* high-level function to send a SMS to a given subscriber. The function
936 * will take care of paging the subscriber, establishing the RLL SAPI3
937 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200938int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
939 struct gsm_sms *sms)
940{
Harald Weltecf6a3812009-08-09 19:07:41 +0200941 struct gsm_lchan *lchan;
942
Harald Welte76042182009-08-08 16:03:15 +0200943 /* check if we already have an open lchan to the subscriber.
944 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200945 lchan = lchan_for_subscr(subscr);
946 if (lchan)
947 return rll_establish(lchan, UM_SAPI_SMS,
948 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200949
950 /* if not, we have to start paging */
951 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
952 paging_cb_send_sms, sms);
953
954 return 0;
955}
Harald Welte3366a942009-07-28 00:44:49 +0200956
Harald Weltecf6a3812009-08-09 19:07:41 +0200957static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
958 void *handler_data, void *signal_data)
959{
960 struct gsm_subscriber *subscr;
961 struct gsm_lchan *lchan;
962 struct gsm_sms *sms;
963
Jan Luebbe336f8ec2009-08-12 15:18:52 +0200964 u_int32_t token;
965
Harald Weltecf6a3812009-08-09 19:07:41 +0200966 switch (signal) {
967 case S_SUBSCR_ATTACHED:
968 /* A subscriber has attached. Check if there are
969 * any pending SMS for him to be delivered */
970 subscr = signal_data;
971 lchan = lchan_for_subscr(subscr);
972 if (!lchan)
973 break;
974 sms = db_sms_get_unsent_for_subscr(subscr);
975 if (!sms)
976 break;
977 /* Establish a SAPI3 RLL connection for SMS */
978 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
979 break;
980 default:
981 break;
982 }
983 return 0;
984}
985
Harald Welte7bfc2672009-07-28 00:41:45 +0200986static __attribute__((constructor)) void on_dso_load_sms(void)
987{
Harald Welte7bfc2672009-07-28 00:41:45 +0200988 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200989
990 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200991}