blob: 9b3f44ec8e30205fe00c7d9786b84a47d8e22f43 [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;
178 }
179 return minutes;
180}
181
182/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
183enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
184{
185 u_int8_t cgbits = dcs >> 4;
186 enum sms_alphabet alpha = DCS_NONE;
187
188 if ((cgbits & 0xc) == 0) {
189 if (cgbits & 2)
190 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
191
192 switch (dcs & 3) {
193 case 0:
194 alpha = DCS_7BIT_DEFAULT;
195 break;
196 case 1:
197 alpha = DCS_8BIT_DATA;
198 break;
199 case 2:
200 alpha = DCS_UCS2;
201 break;
202 }
203 } else if (cgbits == 0xc || cgbits == 0xd)
204 alpha = DCS_7BIT_DEFAULT;
205 else if (cgbits == 0xe)
206 alpha = DCS_UCS2;
207 else if (cgbits == 0xf) {
208 if (dcs & 4)
209 alpha = DCS_8BIT_DATA;
210 else
211 alpha = DCS_7BIT_DEFAULT;
212 }
213
214 return alpha;
215}
216
Harald Welte76042182009-08-08 16:03:15 +0200217static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000218{
219 if (db_sms_store(gsms) != 0) {
220 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200221 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000222 }
Harald Welte76042182009-08-08 16:03:15 +0200223 /* dispatch a signal to tell higher level about it */
224 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000225 return 0;
226}
227
Harald Welte76042182009-08-08 16:03:15 +0200228/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
229static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
230 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200231{
Harald Welte76042182009-08-08 16:03:15 +0200232 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200233
Harald Welte76042182009-08-08 16:03:15 +0200234 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
235
236 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
237
238 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
239 oa[0] = strlen(subscr->extension) & 0xff;
240
241 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200242}
243
244static u_int8_t bcdify(u_int8_t value)
245{
246 u_int8_t ret;
247
Harald Welte76042182009-08-08 16:03:15 +0200248 ret = value / 10;
249 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200250
251 return ret;
252}
253
254/* Generate 03.40 TP-SCTS */
255static void gsm340_gen_scts(u_int8_t *scts, time_t time)
256{
257 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200258
259 *scts++ = bcdify(tm->tm_year % 100);
260 *scts++ = bcdify(tm->tm_mon);
261 *scts++ = bcdify(tm->tm_mday);
262 *scts++ = bcdify(tm->tm_hour);
263 *scts++ = bcdify(tm->tm_min);
264 *scts++ = bcdify(tm->tm_sec);
265 *scts++ = 0; /* FIXME: timezone */
266}
267
Harald Welte76042182009-08-08 16:03:15 +0200268/* generate a msgb containing a TPDU derived from struct gsm_sms,
269 * returns total size of TPDU */
270static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200271{
Harald Weltef3efc592009-07-27 20:11:35 +0200272 u_int8_t *smsp;
273 u_int8_t oa[12]; /* max len per 03.40 */
274 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200275 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200276
277 /* generate first octet with masked bits */
278 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200279 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200280 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200281 /* TP-MMS (more messages to send) */
282 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200283 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200284 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200285 if (sms->status_rep_req)
286 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200287 /* TP-UDHI (indicating TP-UD contains a header) */
288 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200289 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200290#if 0
291 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200292 if (sms->
293 *smsp |= 0x80;
294#endif
295
296 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200297 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200298 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200299 memcpy(smsp, oa, oa_len);
300
301 /* generate TP-PID */
302 smsp = msgb_put(msg, 1);
303 *smsp = sms->protocol_id;
304
305 /* generate TP-DCS */
306 smsp = msgb_put(msg, 1);
307 *smsp = sms->data_coding_scheme;
308
309 /* generate TP-SCTS */
310 smsp = msgb_put(msg, 7);
311 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200312
Harald Weltef3efc592009-07-27 20:11:35 +0200313 /* generate TP-UDL */
314 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200315 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200316
317 /* generate TP-UD */
Harald Welte76042182009-08-08 16:03:15 +0200318 smsp = msgb_put(msg, sms->user_data_len);
319 memcpy(smsp, sms->user_data, sms->user_data_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200320
Harald Welte76042182009-08-08 16:03:15 +0200321 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200322}
323
Harald Welteb9c758b2009-07-05 14:02:46 +0200324/* process an incoming TPDU (called from RP-DATA)
325 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000326static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000327{
Harald Welte9176bd42009-07-23 18:46:00 +0200328 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000329 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000330 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200331 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
332 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000333 u_int8_t da_len_bytes;
334 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
335 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000336
Harald Welte76042182009-08-08 16:03:15 +0200337 gsms = sms_alloc();
338 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200339 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000340
341 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200342 sms_mti = *smsp & 0x03;
343 sms_mms = !!(*smsp & 0x04);
344 sms_vpf = (*smsp & 0x18) >> 3;
345 gsms->status_rep_req = (*smsp & 0x20);
346 gsms->ud_hdr_ind = (*smsp & 0x40);
347 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000348
349 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200350 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000351
Harald Welte7e310b12009-03-30 20:56:32 +0000352 /* length in bytes of the destination address */
353 da_len_bytes = 2 + *smsp/2 + *smsp%2;
354 if (da_len_bytes > 12) {
355 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200356 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000357 goto out;
358 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800359 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000360 memcpy(address_lv, smsp, da_len_bytes);
361 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800362 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000363 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200364 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000365 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000366
Harald Welte76042182009-08-08 16:03:15 +0200367 gsms->protocol_id = *smsp++;
368 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000369
Harald Welte76042182009-08-08 16:03:15 +0200370 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000371
Harald Welte76042182009-08-08 16:03:15 +0200372 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000373 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200374 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000375 break;
376 case GSM340_TP_VPF_ABSOLUTE:
377 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200378 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000379 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000380 break;
381 default:
382 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200383 sms_vpf);
384 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000385 }
Harald Welte76042182009-08-08 16:03:15 +0200386 gsms->user_data_len = *smsp++;
387 if (gsms->user_data_len) {
388 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000389
Harald Welte76042182009-08-08 16:03:15 +0200390 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000391 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200392 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000393 break;
394 case DCS_8BIT_DATA:
395 case DCS_UCS2:
396 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000397 break;
398 }
399 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000400
Harald Welte7e310b12009-03-30 20:56:32 +0000401 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
402 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200403 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
404 gsms->protocol_id, gsms->data_coding_scheme,
405 gsms->dest_addr, gsms->user_data_len,
406 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
407 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000408
Harald Welte76042182009-08-08 16:03:15 +0200409 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000410
Harald Welte76042182009-08-08 16:03:15 +0200411 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200412
Harald Welte76042182009-08-08 16:03:15 +0200413 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200414
Harald Welte7e310b12009-03-30 20:56:32 +0000415 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200416 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000417 if (!gsms->receiver) {
418 rc = 1; /* cause 1: unknown subscriber */
419 goto out;
420 }
421
Harald Welte76042182009-08-08 16:03:15 +0200422 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000423 case GSM340_SMS_SUBMIT_MS2SC:
424 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200425 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000426 break;
427 case GSM340_SMS_COMMAND_MS2SC:
428 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200429 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200430 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000431 break;
432 default:
Harald Welte76042182009-08-08 16:03:15 +0200433 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200434 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000435 break;
436 }
437
Harald Welteb9c758b2009-07-05 14:02:46 +0200438 if (!rc && !gsms->receiver)
439 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
440
Harald Welte7e310b12009-03-30 20:56:32 +0000441out:
Harald Welte76042182009-08-08 16:03:15 +0200442 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000443
Harald Welte7e310b12009-03-30 20:56:32 +0000444 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000445}
446
Harald Weltef3efc592009-07-27 20:11:35 +0200447static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000448{
449 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000450
Daniel Willmann471712b2008-12-29 01:54:02 +0000451 DEBUGP(DSMS, "TX: SMS RP ACK\n");
452
Harald Weltef3efc592009-07-27 20:11:35 +0200453 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000454}
455
Harald Weltef3efc592009-07-27 20:11:35 +0200456static int gsm411_send_rp_error(struct gsm_trans *trans,
457 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000458{
459 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000460
Harald Welte7e310b12009-03-30 20:56:32 +0000461 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000462
Harald Welte7e310b12009-03-30 20:56:32 +0000463 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000464
Harald Weltef3efc592009-07-27 20:11:35 +0200465 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000466}
467
Harald Welte7e310b12009-03-30 20:56:32 +0000468/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200469static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
470 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000471 u_int8_t src_len, u_int8_t *src,
472 u_int8_t dst_len, u_int8_t *dst,
473 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000474{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000475 int rc = 0;
476
Harald Welte7e310b12009-03-30 20:56:32 +0000477 if (src_len && src)
478 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
479
480 if (!dst_len || !dst || !tpdu_len || !tpdu) {
481 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200482 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200483 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000484 return -EIO;
485 }
486 msg->smsh = tpdu;
487
488 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000489
490 rc = gsm340_rx_tpdu(msg);
491 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200492 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000493 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200494 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000495 else
496 return rc;
497}
498
499/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200500static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
501 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000502{
503 u_int8_t src_len, dst_len, rpud_len;
504 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
505
506 /* in the MO case, this should always be zero length */
507 src_len = rph->data[0];
508 if (src_len)
509 src = &rph->data[1];
510
511 dst_len = rph->data[1+src_len];
512 if (dst_len)
513 dst = &rph->data[1+src_len+1];
514
515 rpud_len = rph->data[1+src_len+1+dst_len];
516 if (rpud_len)
517 rp_ud = &rph->data[1+src_len+1+dst_len+1];
518
Harald Welteb9c758b2009-07-05 14:02:46 +0200519 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
520 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200521 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000522 rpud_len, rp_ud);
523}
524
Harald Weltecb8f4432009-08-09 14:59:02 +0200525/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200526static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
527 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200528{
Harald Welte76042182009-08-08 16:03:15 +0200529 struct gsm_sms *sms = trans->sms.sms;
530
Harald Welteb9c758b2009-07-05 14:02:46 +0200531 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
532 * successfully received a SMS. We can now safely mark it as
533 * transmitted */
534
Harald Weltecb8f4432009-08-09 14:59:02 +0200535 if (!trans->sms.is_mt) {
536 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
537 return gsm411_send_rp_error(trans, rph->msg_ref,
538 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
539 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200540
Harald Welte76042182009-08-08 16:03:15 +0200541 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200542 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
543 return gsm411_send_rp_error(trans, rph->msg_ref,
544 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200545 }
546
547 /* mark this SMS as sent in database */
548 db_sms_mark_sent(sms);
549
550 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
551
552 sms_free(sms);
553 trans->sms.sms = NULL;
554
Harald Weltecf6a3812009-08-09 19:07:41 +0200555 /* do not free the transaction here, this is done by sending CP-ACK */
556
557 /* check for more messages for this subscriber */
558 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
559 if (sms)
560 gsm411_send_sms_lchan(msg->lchan, sms);
561 else
562 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200563
564 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200565}
566
Harald Weltef3efc592009-07-27 20:11:35 +0200567static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
568 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200569{
Harald Welte76042182009-08-08 16:03:15 +0200570 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200571 u_int8_t cause_len = rph->data[0];
572 u_int8_t cause = rph->data[1];
573
Harald Welteb9c758b2009-07-05 14:02:46 +0200574 /* Error in response to MT RP_DATA, i.e. the MS did not
575 * successfully receive the SMS. We need to investigate
576 * the cause and take action depending on it */
577
Harald Weltef3efc592009-07-27 20:11:35 +0200578 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
579
Harald Weltecb8f4432009-08-09 14:59:02 +0200580 if (!trans->sms.is_mt) {
581 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
582 return gsm411_send_rp_error(trans, rph->msg_ref,
583 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
584 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200585
Harald Welte76042182009-08-08 16:03:15 +0200586 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200587 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
588 return gsm411_send_rp_error(trans, rph->msg_ref,
589 GSM411_RP_CAUSE_PROTOCOL_ERR);
590 }
591
592 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
593 /* MS has not enough memory to store the message. We need
594 * to store this in our database and wati for a SMMA message */
595 /* FIXME */
596 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200597 }
598
599 sms_free(sms);
600 trans->sms.sms = NULL;
601
Harald Weltecb8f4432009-08-09 14:59:02 +0200602 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200603
Harald Weltef3efc592009-07-27 20:11:35 +0200604 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200605}
606
Harald Weltef3efc592009-07-27 20:11:35 +0200607static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
608 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200609{
Harald Weltecf6a3812009-08-09 19:07:41 +0200610 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200611 int rc;
612
Harald Weltecf6a3812009-08-09 19:07:41 +0200613 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
614 trans->sms.rp_state = GSM411_RPS_IDLE;
615
Harald Welteb9c758b2009-07-05 14:02:46 +0200616 /* MS tells us that it has memory for more SMS, we need
617 * to check if we have any pending messages for it and then
618 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200619 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200620
Harald Weltecf6a3812009-08-09 19:07:41 +0200621 /* check for more messages for this subscriber */
622 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
623 if (sms)
624 gsm411_send_sms_lchan(msg->lchan, sms);
625 else
626 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200627
628 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200629}
630
Harald Weltef3efc592009-07-27 20:11:35 +0200631static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
632 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000633{
Daniel Willmann471712b2008-12-29 01:54:02 +0000634 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000635 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000636 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000637
638 switch (msg_type) {
639 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200640 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
641 /* start TR2N and enter 'wait to send RP-ACK state' */
642 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
643 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000644 break;
645 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200646 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
647 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200648 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000649 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200650 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
651 /* start TR2N and enter 'wait to send RP-ACK state' */
652 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
653 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
654 break;
655 case GSM411_MT_RP_ERROR_MO:
656 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000657 break;
658 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000659 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200660 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
661 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000662 break;
663 }
664
665 return rc;
666}
667
Harald Weltef3efc592009-07-27 20:11:35 +0200668/* send CP-ACK to given transaction */
669static int gsm411_tx_cp_ack(struct gsm_trans *trans)
670{
671 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200672 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200673
Harald Weltecf6a3812009-08-09 19:07:41 +0200674 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
675
676 if (trans->sms.is_mt) {
677 /* If this is a MT SMS DELIVER, we can clear transaction here */
678 trans->sms.cp_state = GSM411_CPS_IDLE;
679 trans_free(trans);
680 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200681
682 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200683}
684
685static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
686{
687 struct msgb *msg = gsm411_msgb_alloc();
688 u_int8_t *causep;
689
Harald Welte76042182009-08-08 16:03:15 +0200690 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200691 *causep = cause;
692
693 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
694}
695
696/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000697int gsm0411_rcv_sms(struct msgb *msg)
698{
699 struct gsm48_hdr *gh = msgb_l3(msg);
700 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200701 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
702 struct gsm_lchan *lchan = msg->lchan;
703 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000704 int rc = 0;
705
Harald Weltef3efc592009-07-27 20:11:35 +0200706 if (!lchan->subscr)
707 return -EIO;
708 /* FIXME: send some error message */
709
710 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
711 transaction_id);
712 if (!trans) {
713 DEBUGP(DSMS, "Unknown transaction ID %x, "
714 "creating new trans\n", transaction_id);
715 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
716 transaction_id, new_callref++);
717 if (!trans) {
718 DEBUGP(DSMS, "No memory for trans\n");
719 /* FIXME: send some error message */
720 return -ENOMEM;
721 }
722 trans->sms.cp_state = GSM411_CPS_IDLE;
723 trans->sms.rp_state = GSM411_RPS_IDLE;
724 trans->sms.is_mt = 0;
725
726 trans->lchan = lchan;
727 use_lchan(lchan);
728 }
729
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000730 switch(msg_type) {
731 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200732 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200733 /* 5.2.3.1.3: MO state exists when SMC has received
734 * CP-DATA, including sending of the assoc. CP-ACK */
735 /* 5.2.3.2.4: MT state exists when SMC has received
736 * CP-DATA, including sending of the assoc. CP-ACK */
737 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200738
739 rc = gsm411_rx_cp_data(msg, gh, trans);
740 /* Send CP-ACK or CP-ERORR in response */
741 if (rc < 0) {
742 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
743 } else
744 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000745 break;
746 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200747 /* previous CP-DATA in this transaction was confirmed */
748 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200749 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
750 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
751 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200752 /* Stop TC1* after CP-ACK has been received */
753 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200754
Harald Weltef3efc592009-07-27 20:11:35 +0200755 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200756 /* FIXME: we have sont one CP-DATA, which was now
757 * acknowledged. Check if we want to transfer more,
758 * i.e. multi-part message */
759 trans->sms.cp_state = GSM411_CPS_IDLE;
760 trans_free(trans);
761 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000762 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000763 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200764 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
Harald Welte41985612009-08-10 00:24:32 +0200765 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200766 trans->sms.cp_state = GSM411_CPS_IDLE;
767 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000768 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000769 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200770 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
771 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200772 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200773 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000774 break;
775 }
776
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000777 return rc;
778}
779
Harald Welte8c2e36e2008-12-30 15:00:14 +0000780#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000781/* Test TPDU - ALL YOUR */
782static u_int8_t tpdu_test[] = {
783 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
784 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
785 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
786 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000787};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000788#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000789
Harald Weltecf6a3812009-08-09 19:07:41 +0200790/* Take a SMS in gsm_sms structure and send it through an already
791 * existing lchan. We also assume that the caller ensured this lchan already
792 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200793int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000794{
795 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200796 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200797 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200798 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200799 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200800 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000801
Harald Weltecf6a3812009-08-09 19:07:41 +0200802 transaction_id = 4; /* FIXME: we always use 4 for now */
803
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000804 msg->lchan = lchan;
805
Harald Welte76042182009-08-08 16:03:15 +0200806 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200807
Harald Welte76042182009-08-08 16:03:15 +0200808 /* FIXME: allocate transaction with message reference */
809 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
810 transaction_id, new_callref++);
811 if (!trans) {
812 DEBUGP(DSMS, "No memory for trans\n");
813 /* FIXME: send some error message */
814 return -ENOMEM;
815 }
816 trans->sms.cp_state = GSM411_CPS_IDLE;
817 trans->sms.rp_state = GSM411_RPS_IDLE;
818 trans->sms.is_mt = 1;
819 trans->sms.sms = sms;
820
821 trans->lchan = lchan;
822 use_lchan(lchan);
823
824 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000825 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200826 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200827 data[1] = 0x91; /* type of number: international, ISDN */
828 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000829 data[3] = 0x77;
830 data[4] = 0x58;
831 data[5] = 0x10;
832 data[6] = 0x06;
833 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200834
835 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000836 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200837 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000838
Harald Welte76042182009-08-08 16:03:15 +0200839 /* obtain a pointer for the rp_ud_len, so we can fill it later */
840 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000841
Harald Welte76042182009-08-08 16:03:15 +0200842#if 1
843 /* generate the 03.40 TPDU */
844 rc = gsm340_gen_tpdu(msg, sms);
845 if (rc < 0) {
846 msgb_free(msg);
847 return rc;
848 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000849
Harald Welte76042182009-08-08 16:03:15 +0200850 *rp_ud_len = rc;
851#else
852 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000853 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200854 *rp_ud_len = sizeof(tpdu_test);
855#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000856
Harald Welte76042182009-08-08 16:03:15 +0200857 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000858
Harald Weltef3efc592009-07-27 20:11:35 +0200859 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
860 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000861}
Harald Weltef3efc592009-07-27 20:11:35 +0200862
Harald Weltecf6a3812009-08-09 19:07:41 +0200863/* RLL SAPI3 establish callback. Now we have a RLL connection and
864 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200865static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
866 void *_sms, enum bsc_rllr_ind type)
867{
868 struct gsm_sms *sms = _sms;
869
870 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
871 lchan, link_id, sms, type);
872
873 switch (type) {
874 case BSC_RLLR_IND_EST_CONF:
875 gsm411_send_sms_lchan(lchan, sms);
876 break;
877 case BSC_RLLR_IND_REL_IND:
878 case BSC_RLLR_IND_ERR_IND:
879 case BSC_RLLR_IND_TIMEOUT:
880 sms_free(sms);
881 break;
882 }
883}
884
Harald Weltecf6a3812009-08-09 19:07:41 +0200885/* paging callback. Here we get called if paging a subscriber has
886 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200887static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
888 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200889{
Harald Welte76042182009-08-08 16:03:15 +0200890 struct gsm_lchan *lchan = _lchan;
891 struct gsm_sms *sms = _sms;
892 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200893
Harald Welte76042182009-08-08 16:03:15 +0200894 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
895 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
896
897 if (hooknum != GSM_HOOK_RR_PAGING)
898 return -EINVAL;
899
900 switch (event) {
901 case GSM_PAGING_SUCCEEDED:
902 /* Paging aborted without lchan ?!? */
903 if (!lchan) {
904 sms_free(sms);
905 rc = -EIO;
906 break;
907 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200908 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200909 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200910 break;
911 case GSM_PAGING_EXPIRED:
912 sms_free(sms);
913 rc = -ETIMEDOUT;
914 break;
915 default:
916 rc = -EINVAL;
917 break;
918 }
919
920 return rc;
921}
922
Harald Weltecf6a3812009-08-09 19:07:41 +0200923/* high-level function to send a SMS to a given subscriber. The function
924 * will take care of paging the subscriber, establishing the RLL SAPI3
925 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200926int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
927 struct gsm_sms *sms)
928{
Harald Weltecf6a3812009-08-09 19:07:41 +0200929 struct gsm_lchan *lchan;
930
Harald Welte76042182009-08-08 16:03:15 +0200931 /* check if we already have an open lchan to the subscriber.
932 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200933 lchan = lchan_for_subscr(subscr);
934 if (lchan)
935 return rll_establish(lchan, UM_SAPI_SMS,
936 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200937
938 /* if not, we have to start paging */
939 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
940 paging_cb_send_sms, sms);
941
942 return 0;
943}
Harald Welte3366a942009-07-28 00:44:49 +0200944
Harald Weltecf6a3812009-08-09 19:07:41 +0200945static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
946 void *handler_data, void *signal_data)
947{
948 struct gsm_subscriber *subscr;
949 struct gsm_lchan *lchan;
950 struct gsm_sms *sms;
951
952 switch (signal) {
953 case S_SUBSCR_ATTACHED:
954 /* A subscriber has attached. Check if there are
955 * any pending SMS for him to be delivered */
956 subscr = signal_data;
957 lchan = lchan_for_subscr(subscr);
958 if (!lchan)
959 break;
960 sms = db_sms_get_unsent_for_subscr(subscr);
961 if (!sms)
962 break;
963 /* Establish a SAPI3 RLL connection for SMS */
964 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
965 break;
966 default:
967 break;
968 }
969 return 0;
970}
971
Harald Welte7bfc2672009-07-28 00:41:45 +0200972static __attribute__((constructor)) void on_dso_load_sms(void)
973{
Harald Welte7bfc2672009-07-28 00:41:45 +0200974 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200975
976 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200977}