blob: e1b417a862cf6c5eace24d68706574168170ac06 [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;
Daniel Willmann9aef1452009-08-13 03:39:07 +0200279 u_int8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200280 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200281
282 /* generate first octet with masked bits */
283 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200284 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200285 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200286 /* TP-MMS (more messages to send) */
287 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200288 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200289 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200290 if (sms->status_rep_req)
291 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200292 /* TP-UDHI (indicating TP-UD contains a header) */
293 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200294 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200295#if 0
296 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200297 if (sms->
298 *smsp |= 0x80;
299#endif
300
301 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200302 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200303 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200304 memcpy(smsp, oa, oa_len);
305
306 /* generate TP-PID */
307 smsp = msgb_put(msg, 1);
308 *smsp = sms->protocol_id;
309
310 /* generate TP-DCS */
311 smsp = msgb_put(msg, 1);
312 *smsp = sms->data_coding_scheme;
313
314 /* generate TP-SCTS */
315 smsp = msgb_put(msg, 7);
316 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200317
Harald Weltef3efc592009-07-27 20:11:35 +0200318 /* generate TP-UDL */
319 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200320 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200321
322 /* generate TP-UD */
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200323 /* FIXME: Handle DSC of UCS2 or 8/bit default */
324 if (gsm338_get_sms_alphabet(sms->data_coding_scheme) == DCS_7BIT_DEFAULT) {
Daniel Willmann9aef1452009-08-13 03:39:07 +0200325 octet_len = sms->user_data_len*7/8;
326 if (sms->user_data_len*7%8 != 0)
327 octet_len++;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200328 /* Warning, user_data_len indicates the amount of septets
329 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200330 smsp = msgb_put(msg, octet_len);
331 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200332 }
Harald Weltef3efc592009-07-27 20:11:35 +0200333
Harald Welte76042182009-08-08 16:03:15 +0200334 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200335}
336
Harald Welteb9c758b2009-07-05 14:02:46 +0200337/* process an incoming TPDU (called from RP-DATA)
338 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000339static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000340{
Harald Welte9176bd42009-07-23 18:46:00 +0200341 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000342 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000343 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200344 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
345 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000346 u_int8_t da_len_bytes;
347 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
348 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000349
Harald Welte76042182009-08-08 16:03:15 +0200350 gsms = sms_alloc();
351 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200352 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000353
354 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200355 sms_mti = *smsp & 0x03;
356 sms_mms = !!(*smsp & 0x04);
357 sms_vpf = (*smsp & 0x18) >> 3;
358 gsms->status_rep_req = (*smsp & 0x20);
359 gsms->ud_hdr_ind = (*smsp & 0x40);
360 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000361
362 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200363 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000364
Harald Welte7e310b12009-03-30 20:56:32 +0000365 /* length in bytes of the destination address */
366 da_len_bytes = 2 + *smsp/2 + *smsp%2;
367 if (da_len_bytes > 12) {
368 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200369 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000370 goto out;
371 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800372 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000373 memcpy(address_lv, smsp, da_len_bytes);
374 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800375 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000376 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200377 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000378 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000379
Harald Welte76042182009-08-08 16:03:15 +0200380 gsms->protocol_id = *smsp++;
381 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000382
Harald Welte76042182009-08-08 16:03:15 +0200383 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000384
Harald Welte76042182009-08-08 16:03:15 +0200385 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000386 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200387 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000388 break;
389 case GSM340_TP_VPF_ABSOLUTE:
390 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200391 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000392 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000393 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200394 case GSM340_TP_VPF_NONE:
395 sms_vp = 0;
396 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000397 default:
398 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200399 sms_vpf);
400 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000401 }
Harald Welte76042182009-08-08 16:03:15 +0200402 gsms->user_data_len = *smsp++;
403 if (gsms->user_data_len) {
404 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000405
Harald Welte76042182009-08-08 16:03:15 +0200406 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000407 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200408 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000409 break;
410 case DCS_8BIT_DATA:
411 case DCS_UCS2:
412 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000413 break;
414 }
415 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000416
Harald Welte7e310b12009-03-30 20:56:32 +0000417 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
418 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200419 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
420 gsms->protocol_id, gsms->data_coding_scheme,
421 gsms->dest_addr, gsms->user_data_len,
422 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
423 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000424
Harald Welte76042182009-08-08 16:03:15 +0200425 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000426
Harald Welte76042182009-08-08 16:03:15 +0200427 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200428
Harald Welte76042182009-08-08 16:03:15 +0200429 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200430
Harald Welte7e310b12009-03-30 20:56:32 +0000431 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200432 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000433 if (!gsms->receiver) {
434 rc = 1; /* cause 1: unknown subscriber */
435 goto out;
436 }
437
Harald Welte76042182009-08-08 16:03:15 +0200438 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000439 case GSM340_SMS_SUBMIT_MS2SC:
440 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200441 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000442 break;
443 case GSM340_SMS_COMMAND_MS2SC:
444 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200445 DEBUGP(DSMS, "Unimplemented 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 default:
Harald Welte76042182009-08-08 16:03:15 +0200449 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200450 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000451 break;
452 }
453
Harald Welteb9c758b2009-07-05 14:02:46 +0200454 if (!rc && !gsms->receiver)
455 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
456
Harald Welte7e310b12009-03-30 20:56:32 +0000457out:
Harald Welte76042182009-08-08 16:03:15 +0200458 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000459
Harald Welte7e310b12009-03-30 20:56:32 +0000460 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000461}
462
Harald Weltef3efc592009-07-27 20:11:35 +0200463static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000464{
465 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000466
Daniel Willmann471712b2008-12-29 01:54:02 +0000467 DEBUGP(DSMS, "TX: SMS RP ACK\n");
468
Harald Weltef3efc592009-07-27 20:11:35 +0200469 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000470}
471
Harald Weltef3efc592009-07-27 20:11:35 +0200472static int gsm411_send_rp_error(struct gsm_trans *trans,
473 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000474{
475 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000476
Harald Welte7e310b12009-03-30 20:56:32 +0000477 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000478
Harald Welte7e310b12009-03-30 20:56:32 +0000479 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000480
Harald Weltef3efc592009-07-27 20:11:35 +0200481 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000482}
483
Harald Welte7e310b12009-03-30 20:56:32 +0000484/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200485static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
486 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000487 u_int8_t src_len, u_int8_t *src,
488 u_int8_t dst_len, u_int8_t *dst,
489 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000490{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000491 int rc = 0;
492
Harald Welte7e310b12009-03-30 20:56:32 +0000493 if (src_len && src)
494 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
495
496 if (!dst_len || !dst || !tpdu_len || !tpdu) {
497 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200498 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200499 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000500 return -EIO;
501 }
502 msg->smsh = tpdu;
503
504 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000505
506 rc = gsm340_rx_tpdu(msg);
507 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200508 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000509 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200510 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000511 else
512 return rc;
513}
514
515/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200516static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
517 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000518{
519 u_int8_t src_len, dst_len, rpud_len;
520 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
521
522 /* in the MO case, this should always be zero length */
523 src_len = rph->data[0];
524 if (src_len)
525 src = &rph->data[1];
526
527 dst_len = rph->data[1+src_len];
528 if (dst_len)
529 dst = &rph->data[1+src_len+1];
530
531 rpud_len = rph->data[1+src_len+1+dst_len];
532 if (rpud_len)
533 rp_ud = &rph->data[1+src_len+1+dst_len+1];
534
Harald Welteb9c758b2009-07-05 14:02:46 +0200535 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
536 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200537 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000538 rpud_len, rp_ud);
539}
540
Harald Weltecb8f4432009-08-09 14:59:02 +0200541/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200542static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
543 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200544{
Harald Welte76042182009-08-08 16:03:15 +0200545 struct gsm_sms *sms = trans->sms.sms;
546
Harald Welteb9c758b2009-07-05 14:02:46 +0200547 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
548 * successfully received a SMS. We can now safely mark it as
549 * transmitted */
550
Harald Weltecb8f4432009-08-09 14:59:02 +0200551 if (!trans->sms.is_mt) {
552 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
553 return gsm411_send_rp_error(trans, rph->msg_ref,
554 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
555 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200556
Harald Welte76042182009-08-08 16:03:15 +0200557 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200558 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
559 return gsm411_send_rp_error(trans, rph->msg_ref,
560 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200561 }
562
563 /* mark this SMS as sent in database */
564 db_sms_mark_sent(sms);
565
566 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
567
568 sms_free(sms);
569 trans->sms.sms = NULL;
570
Harald Weltecf6a3812009-08-09 19:07:41 +0200571 /* do not free the transaction here, this is done by sending CP-ACK */
572
573 /* check for more messages for this subscriber */
574 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
575 if (sms)
576 gsm411_send_sms_lchan(msg->lchan, sms);
577 else
578 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200579
580 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200581}
582
Harald Weltef3efc592009-07-27 20:11:35 +0200583static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
584 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200585{
Harald Welte76042182009-08-08 16:03:15 +0200586 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200587 u_int8_t cause_len = rph->data[0];
588 u_int8_t cause = rph->data[1];
589
Harald Welteb9c758b2009-07-05 14:02:46 +0200590 /* Error in response to MT RP_DATA, i.e. the MS did not
591 * successfully receive the SMS. We need to investigate
592 * the cause and take action depending on it */
593
Harald Weltef3efc592009-07-27 20:11:35 +0200594 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
595
Harald Weltecb8f4432009-08-09 14:59:02 +0200596 if (!trans->sms.is_mt) {
597 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
598 return gsm411_send_rp_error(trans, rph->msg_ref,
599 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
600 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200601
Harald Welte76042182009-08-08 16:03:15 +0200602 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200603 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
604 return gsm411_send_rp_error(trans, rph->msg_ref,
605 GSM411_RP_CAUSE_PROTOCOL_ERR);
606 }
607
608 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
609 /* MS has not enough memory to store the message. We need
610 * to store this in our database and wati for a SMMA message */
611 /* FIXME */
612 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200613 }
614
615 sms_free(sms);
616 trans->sms.sms = NULL;
617
Harald Weltecb8f4432009-08-09 14:59:02 +0200618 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200619
Harald Weltef3efc592009-07-27 20:11:35 +0200620 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200621}
622
Harald Weltef3efc592009-07-27 20:11:35 +0200623static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
624 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200625{
Harald Weltecf6a3812009-08-09 19:07:41 +0200626 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200627 int rc;
628
Harald Weltecf6a3812009-08-09 19:07:41 +0200629 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
630 trans->sms.rp_state = GSM411_RPS_IDLE;
631
Harald Welteb9c758b2009-07-05 14:02:46 +0200632 /* MS tells us that it has memory for more SMS, we need
633 * to check if we have any pending messages for it and then
634 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200635 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200636
Harald Weltecf6a3812009-08-09 19:07:41 +0200637 /* check for more messages for this subscriber */
638 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
639 if (sms)
640 gsm411_send_sms_lchan(msg->lchan, sms);
641 else
642 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200643
644 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200645}
646
Harald Weltef3efc592009-07-27 20:11:35 +0200647static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
648 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000649{
Daniel Willmann471712b2008-12-29 01:54:02 +0000650 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000651 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000652 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000653
654 switch (msg_type) {
655 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200656 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
657 /* start TR2N and enter 'wait to send RP-ACK state' */
658 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
659 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000660 break;
661 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200662 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
663 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200664 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000665 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200666 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
667 /* start TR2N and enter 'wait to send RP-ACK state' */
668 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
669 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
670 break;
671 case GSM411_MT_RP_ERROR_MO:
672 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000673 break;
674 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000675 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200676 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
677 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000678 break;
679 }
680
681 return rc;
682}
683
Harald Weltef3efc592009-07-27 20:11:35 +0200684/* send CP-ACK to given transaction */
685static int gsm411_tx_cp_ack(struct gsm_trans *trans)
686{
687 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200688 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200689
Harald Weltecf6a3812009-08-09 19:07:41 +0200690 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
691
692 if (trans->sms.is_mt) {
693 /* If this is a MT SMS DELIVER, we can clear transaction here */
694 trans->sms.cp_state = GSM411_CPS_IDLE;
695 trans_free(trans);
696 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200697
698 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200699}
700
701static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
702{
703 struct msgb *msg = gsm411_msgb_alloc();
704 u_int8_t *causep;
705
Harald Welte76042182009-08-08 16:03:15 +0200706 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200707 *causep = cause;
708
709 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
710}
711
712/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000713int gsm0411_rcv_sms(struct msgb *msg)
714{
715 struct gsm48_hdr *gh = msgb_l3(msg);
716 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200717 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
718 struct gsm_lchan *lchan = msg->lchan;
719 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000720 int rc = 0;
721
Harald Weltef3efc592009-07-27 20:11:35 +0200722 if (!lchan->subscr)
723 return -EIO;
724 /* FIXME: send some error message */
725
726 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
727 transaction_id);
728 if (!trans) {
729 DEBUGP(DSMS, "Unknown transaction ID %x, "
730 "creating new trans\n", transaction_id);
731 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
732 transaction_id, new_callref++);
733 if (!trans) {
734 DEBUGP(DSMS, "No memory for trans\n");
735 /* FIXME: send some error message */
736 return -ENOMEM;
737 }
738 trans->sms.cp_state = GSM411_CPS_IDLE;
739 trans->sms.rp_state = GSM411_RPS_IDLE;
740 trans->sms.is_mt = 0;
741
742 trans->lchan = lchan;
743 use_lchan(lchan);
744 }
745
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000746 switch(msg_type) {
747 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200748 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200749 /* 5.2.3.1.3: MO state exists when SMC has received
750 * CP-DATA, including sending of the assoc. CP-ACK */
751 /* 5.2.3.2.4: MT state exists when SMC has received
752 * CP-DATA, including sending of the assoc. CP-ACK */
753 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200754
755 rc = gsm411_rx_cp_data(msg, gh, trans);
756 /* Send CP-ACK or CP-ERORR in response */
757 if (rc < 0) {
758 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
759 } else
760 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000761 break;
762 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200763 /* previous CP-DATA in this transaction was confirmed */
764 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200765 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
766 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
767 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200768 /* Stop TC1* after CP-ACK has been received */
769 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200770
Harald Weltef3efc592009-07-27 20:11:35 +0200771 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200772 /* FIXME: we have sont one CP-DATA, which was now
773 * acknowledged. Check if we want to transfer more,
774 * i.e. multi-part message */
775 trans->sms.cp_state = GSM411_CPS_IDLE;
776 trans_free(trans);
777 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000778 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000779 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200780 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
Harald Welte41985612009-08-10 00:24:32 +0200781 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200782 trans->sms.cp_state = GSM411_CPS_IDLE;
783 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000784 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000785 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200786 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
787 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200788 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200789 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000790 break;
791 }
792
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000793 return rc;
794}
795
Harald Welte8c2e36e2008-12-30 15:00:14 +0000796#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000797/* Test TPDU - ALL YOUR */
798static u_int8_t tpdu_test[] = {
799 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
800 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
801 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
802 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000803};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000804#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000805
Harald Weltecf6a3812009-08-09 19:07:41 +0200806/* Take a SMS in gsm_sms structure and send it through an already
807 * existing lchan. We also assume that the caller ensured this lchan already
808 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200809int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000810{
811 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200812 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200813 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200814 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200815 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200816 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000817
Harald Weltecf6a3812009-08-09 19:07:41 +0200818 transaction_id = 4; /* FIXME: we always use 4 for now */
819
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000820 msg->lchan = lchan;
821
Harald Welte76042182009-08-08 16:03:15 +0200822 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200823
Harald Welte76042182009-08-08 16:03:15 +0200824 /* FIXME: allocate transaction with message reference */
825 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
826 transaction_id, new_callref++);
827 if (!trans) {
828 DEBUGP(DSMS, "No memory for trans\n");
829 /* FIXME: send some error message */
830 return -ENOMEM;
831 }
832 trans->sms.cp_state = GSM411_CPS_IDLE;
833 trans->sms.rp_state = GSM411_RPS_IDLE;
834 trans->sms.is_mt = 1;
835 trans->sms.sms = sms;
836
837 trans->lchan = lchan;
838 use_lchan(lchan);
839
840 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000841 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200842 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200843 data[1] = 0x91; /* type of number: international, ISDN */
844 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000845 data[3] = 0x77;
846 data[4] = 0x58;
847 data[5] = 0x10;
848 data[6] = 0x06;
849 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200850
851 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000852 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200853 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000854
Harald Welte76042182009-08-08 16:03:15 +0200855 /* obtain a pointer for the rp_ud_len, so we can fill it later */
856 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000857
Harald Welte76042182009-08-08 16:03:15 +0200858#if 1
859 /* generate the 03.40 TPDU */
860 rc = gsm340_gen_tpdu(msg, sms);
861 if (rc < 0) {
862 msgb_free(msg);
863 return rc;
864 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000865
Harald Welte76042182009-08-08 16:03:15 +0200866 *rp_ud_len = rc;
867#else
868 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000869 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200870 *rp_ud_len = sizeof(tpdu_test);
871#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000872
Harald Welte76042182009-08-08 16:03:15 +0200873 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000874
Harald Weltef3efc592009-07-27 20:11:35 +0200875 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
876 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000877}
Harald Weltef3efc592009-07-27 20:11:35 +0200878
Harald Weltecf6a3812009-08-09 19:07:41 +0200879/* RLL SAPI3 establish callback. Now we have a RLL connection and
880 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200881static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
882 void *_sms, enum bsc_rllr_ind type)
883{
884 struct gsm_sms *sms = _sms;
885
886 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
887 lchan, link_id, sms, type);
888
889 switch (type) {
890 case BSC_RLLR_IND_EST_CONF:
891 gsm411_send_sms_lchan(lchan, sms);
892 break;
893 case BSC_RLLR_IND_REL_IND:
894 case BSC_RLLR_IND_ERR_IND:
895 case BSC_RLLR_IND_TIMEOUT:
896 sms_free(sms);
897 break;
898 }
899}
900
Harald Weltecf6a3812009-08-09 19:07:41 +0200901/* paging callback. Here we get called if paging a subscriber has
902 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200903static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
904 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200905{
Harald Welte76042182009-08-08 16:03:15 +0200906 struct gsm_lchan *lchan = _lchan;
907 struct gsm_sms *sms = _sms;
908 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200909
Harald Welte76042182009-08-08 16:03:15 +0200910 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
911 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
912
913 if (hooknum != GSM_HOOK_RR_PAGING)
914 return -EINVAL;
915
916 switch (event) {
917 case GSM_PAGING_SUCCEEDED:
918 /* Paging aborted without lchan ?!? */
919 if (!lchan) {
920 sms_free(sms);
921 rc = -EIO;
922 break;
923 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200924 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200925 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200926 break;
927 case GSM_PAGING_EXPIRED:
928 sms_free(sms);
929 rc = -ETIMEDOUT;
930 break;
931 default:
932 rc = -EINVAL;
933 break;
934 }
935
936 return rc;
937}
938
Harald Weltecf6a3812009-08-09 19:07:41 +0200939/* high-level function to send a SMS to a given subscriber. The function
940 * will take care of paging the subscriber, establishing the RLL SAPI3
941 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200942int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
943 struct gsm_sms *sms)
944{
Harald Weltecf6a3812009-08-09 19:07:41 +0200945 struct gsm_lchan *lchan;
946
Harald Welte76042182009-08-08 16:03:15 +0200947 /* check if we already have an open lchan to the subscriber.
948 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200949 lchan = lchan_for_subscr(subscr);
950 if (lchan)
951 return rll_establish(lchan, UM_SAPI_SMS,
952 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200953
954 /* if not, we have to start paging */
955 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
956 paging_cb_send_sms, sms);
957
958 return 0;
959}
Harald Welte3366a942009-07-28 00:44:49 +0200960
Harald Weltecf6a3812009-08-09 19:07:41 +0200961static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
962 void *handler_data, void *signal_data)
963{
964 struct gsm_subscriber *subscr;
965 struct gsm_lchan *lchan;
966 struct gsm_sms *sms;
967
Jan Luebbe336f8ec2009-08-12 15:18:52 +0200968 u_int32_t token;
969
Harald Weltecf6a3812009-08-09 19:07:41 +0200970 switch (signal) {
971 case S_SUBSCR_ATTACHED:
972 /* A subscriber has attached. Check if there are
973 * any pending SMS for him to be delivered */
974 subscr = signal_data;
975 lchan = lchan_for_subscr(subscr);
976 if (!lchan)
977 break;
978 sms = db_sms_get_unsent_for_subscr(subscr);
979 if (!sms)
980 break;
981 /* Establish a SAPI3 RLL connection for SMS */
982 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
983 break;
984 default:
985 break;
986 }
987 return 0;
988}
989
Harald Welte7bfc2672009-07-28 00:41:45 +0200990static __attribute__((constructor)) void on_dso_load_sms(void)
991{
Harald Welte7bfc2672009-07-28 00:41:45 +0200992 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200993
994 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200995}