blob: 05e55d4dcbcdd0916d01e025067f56655c5a6d3c [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 */
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200318 /* FIXME: Handle DSC of UCS2 or 8/bit default */
319 if (gsm338_get_sms_alphabet(sms->data_coding_scheme) == DCS_7BIT_DEFAULT) {
320 /* Warning, user_data_len indicates the amount of septets
321 * (characters), we need amount of octets occupied */
322 smsp = msgb_put(msg, ceil(sms->user_data_len*7/8.0));
323 memcpy(smsp, sms->user_data, ceil(sms->user_data_len*7/8.0));
324 }
Harald Weltef3efc592009-07-27 20:11:35 +0200325
Harald Welte76042182009-08-08 16:03:15 +0200326 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200327}
328
Harald Welteb9c758b2009-07-05 14:02:46 +0200329/* process an incoming TPDU (called from RP-DATA)
330 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000331static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000332{
Harald Welte9176bd42009-07-23 18:46:00 +0200333 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000334 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000335 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200336 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
337 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000338 u_int8_t da_len_bytes;
339 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
340 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000341
Harald Welte76042182009-08-08 16:03:15 +0200342 gsms = sms_alloc();
343 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200344 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000345
346 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200347 sms_mti = *smsp & 0x03;
348 sms_mms = !!(*smsp & 0x04);
349 sms_vpf = (*smsp & 0x18) >> 3;
350 gsms->status_rep_req = (*smsp & 0x20);
351 gsms->ud_hdr_ind = (*smsp & 0x40);
352 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000353
354 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200355 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000356
Harald Welte7e310b12009-03-30 20:56:32 +0000357 /* length in bytes of the destination address */
358 da_len_bytes = 2 + *smsp/2 + *smsp%2;
359 if (da_len_bytes > 12) {
360 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200361 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000362 goto out;
363 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800364 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000365 memcpy(address_lv, smsp, da_len_bytes);
366 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800367 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000368 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200369 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000370 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000371
Harald Welte76042182009-08-08 16:03:15 +0200372 gsms->protocol_id = *smsp++;
373 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000374
Harald Welte76042182009-08-08 16:03:15 +0200375 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000376
Harald Welte76042182009-08-08 16:03:15 +0200377 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000378 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200379 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000380 break;
381 case GSM340_TP_VPF_ABSOLUTE:
382 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200383 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000384 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000385 break;
386 default:
387 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200388 sms_vpf);
389 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000390 }
Harald Welte76042182009-08-08 16:03:15 +0200391 gsms->user_data_len = *smsp++;
392 if (gsms->user_data_len) {
393 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000394
Harald Welte76042182009-08-08 16:03:15 +0200395 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000396 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200397 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000398 break;
399 case DCS_8BIT_DATA:
400 case DCS_UCS2:
401 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000402 break;
403 }
404 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000405
Harald Welte7e310b12009-03-30 20:56:32 +0000406 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
407 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200408 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
409 gsms->protocol_id, gsms->data_coding_scheme,
410 gsms->dest_addr, gsms->user_data_len,
411 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
412 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000413
Harald Welte76042182009-08-08 16:03:15 +0200414 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000415
Harald Welte76042182009-08-08 16:03:15 +0200416 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200417
Harald Welte76042182009-08-08 16:03:15 +0200418 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200419
Harald Welte7e310b12009-03-30 20:56:32 +0000420 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200421 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000422 if (!gsms->receiver) {
423 rc = 1; /* cause 1: unknown subscriber */
424 goto out;
425 }
426
Harald Welte76042182009-08-08 16:03:15 +0200427 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000428 case GSM340_SMS_SUBMIT_MS2SC:
429 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200430 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000431 break;
432 case GSM340_SMS_COMMAND_MS2SC:
433 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200434 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200435 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000436 break;
437 default:
Harald Welte76042182009-08-08 16:03:15 +0200438 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200439 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000440 break;
441 }
442
Harald Welteb9c758b2009-07-05 14:02:46 +0200443 if (!rc && !gsms->receiver)
444 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
445
Harald Welte7e310b12009-03-30 20:56:32 +0000446out:
Harald Welte76042182009-08-08 16:03:15 +0200447 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000448
Harald Welte7e310b12009-03-30 20:56:32 +0000449 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000450}
451
Harald Weltef3efc592009-07-27 20:11:35 +0200452static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000453{
454 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000455
Daniel Willmann471712b2008-12-29 01:54:02 +0000456 DEBUGP(DSMS, "TX: SMS RP ACK\n");
457
Harald Weltef3efc592009-07-27 20:11:35 +0200458 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000459}
460
Harald Weltef3efc592009-07-27 20:11:35 +0200461static int gsm411_send_rp_error(struct gsm_trans *trans,
462 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000463{
464 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000465
Harald Welte7e310b12009-03-30 20:56:32 +0000466 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000467
Harald Welte7e310b12009-03-30 20:56:32 +0000468 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000469
Harald Weltef3efc592009-07-27 20:11:35 +0200470 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000471}
472
Harald Welte7e310b12009-03-30 20:56:32 +0000473/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200474static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
475 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000476 u_int8_t src_len, u_int8_t *src,
477 u_int8_t dst_len, u_int8_t *dst,
478 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000479{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000480 int rc = 0;
481
Harald Welte7e310b12009-03-30 20:56:32 +0000482 if (src_len && src)
483 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
484
485 if (!dst_len || !dst || !tpdu_len || !tpdu) {
486 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200487 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200488 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000489 return -EIO;
490 }
491 msg->smsh = tpdu;
492
493 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000494
495 rc = gsm340_rx_tpdu(msg);
496 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200497 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000498 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200499 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000500 else
501 return rc;
502}
503
504/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200505static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
506 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000507{
508 u_int8_t src_len, dst_len, rpud_len;
509 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
510
511 /* in the MO case, this should always be zero length */
512 src_len = rph->data[0];
513 if (src_len)
514 src = &rph->data[1];
515
516 dst_len = rph->data[1+src_len];
517 if (dst_len)
518 dst = &rph->data[1+src_len+1];
519
520 rpud_len = rph->data[1+src_len+1+dst_len];
521 if (rpud_len)
522 rp_ud = &rph->data[1+src_len+1+dst_len+1];
523
Harald Welteb9c758b2009-07-05 14:02:46 +0200524 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
525 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200526 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000527 rpud_len, rp_ud);
528}
529
Harald Weltecb8f4432009-08-09 14:59:02 +0200530/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200531static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
532 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200533{
Harald Welte76042182009-08-08 16:03:15 +0200534 struct gsm_sms *sms = trans->sms.sms;
535
Harald Welteb9c758b2009-07-05 14:02:46 +0200536 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
537 * successfully received a SMS. We can now safely mark it as
538 * transmitted */
539
Harald Weltecb8f4432009-08-09 14:59:02 +0200540 if (!trans->sms.is_mt) {
541 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
542 return gsm411_send_rp_error(trans, rph->msg_ref,
543 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
544 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200545
Harald Welte76042182009-08-08 16:03:15 +0200546 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200547 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
548 return gsm411_send_rp_error(trans, rph->msg_ref,
549 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200550 }
551
552 /* mark this SMS as sent in database */
553 db_sms_mark_sent(sms);
554
555 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
556
557 sms_free(sms);
558 trans->sms.sms = NULL;
559
Harald Weltecf6a3812009-08-09 19:07:41 +0200560 /* do not free the transaction here, this is done by sending CP-ACK */
561
562 /* check for more messages for this subscriber */
563 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
564 if (sms)
565 gsm411_send_sms_lchan(msg->lchan, sms);
566 else
567 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200568
569 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200570}
571
Harald Weltef3efc592009-07-27 20:11:35 +0200572static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
573 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200574{
Harald Welte76042182009-08-08 16:03:15 +0200575 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200576 u_int8_t cause_len = rph->data[0];
577 u_int8_t cause = rph->data[1];
578
Harald Welteb9c758b2009-07-05 14:02:46 +0200579 /* Error in response to MT RP_DATA, i.e. the MS did not
580 * successfully receive the SMS. We need to investigate
581 * the cause and take action depending on it */
582
Harald Weltef3efc592009-07-27 20:11:35 +0200583 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
584
Harald Weltecb8f4432009-08-09 14:59:02 +0200585 if (!trans->sms.is_mt) {
586 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
587 return gsm411_send_rp_error(trans, rph->msg_ref,
588 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
589 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200590
Harald Welte76042182009-08-08 16:03:15 +0200591 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200592 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
593 return gsm411_send_rp_error(trans, rph->msg_ref,
594 GSM411_RP_CAUSE_PROTOCOL_ERR);
595 }
596
597 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
598 /* MS has not enough memory to store the message. We need
599 * to store this in our database and wati for a SMMA message */
600 /* FIXME */
601 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200602 }
603
604 sms_free(sms);
605 trans->sms.sms = NULL;
606
Harald Weltecb8f4432009-08-09 14:59:02 +0200607 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200608
Harald Weltef3efc592009-07-27 20:11:35 +0200609 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200610}
611
Harald Weltef3efc592009-07-27 20:11:35 +0200612static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
613 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200614{
Harald Weltecf6a3812009-08-09 19:07:41 +0200615 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200616 int rc;
617
Harald Weltecf6a3812009-08-09 19:07:41 +0200618 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
619 trans->sms.rp_state = GSM411_RPS_IDLE;
620
Harald Welteb9c758b2009-07-05 14:02:46 +0200621 /* MS tells us that it has memory for more SMS, we need
622 * to check if we have any pending messages for it and then
623 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200624 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200625
Harald Weltecf6a3812009-08-09 19:07:41 +0200626 /* check for more messages for this subscriber */
627 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
628 if (sms)
629 gsm411_send_sms_lchan(msg->lchan, sms);
630 else
631 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200632
633 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200634}
635
Harald Weltef3efc592009-07-27 20:11:35 +0200636static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
637 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000638{
Daniel Willmann471712b2008-12-29 01:54:02 +0000639 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000640 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000641 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000642
643 switch (msg_type) {
644 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200645 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
646 /* start TR2N and enter 'wait to send RP-ACK state' */
647 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
648 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000649 break;
650 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200651 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
652 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200653 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000654 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200655 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
656 /* start TR2N and enter 'wait to send RP-ACK state' */
657 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
658 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
659 break;
660 case GSM411_MT_RP_ERROR_MO:
661 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000662 break;
663 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000664 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200665 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
666 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000667 break;
668 }
669
670 return rc;
671}
672
Harald Weltef3efc592009-07-27 20:11:35 +0200673/* send CP-ACK to given transaction */
674static int gsm411_tx_cp_ack(struct gsm_trans *trans)
675{
676 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200677 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200678
Harald Weltecf6a3812009-08-09 19:07:41 +0200679 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
680
681 if (trans->sms.is_mt) {
682 /* If this is a MT SMS DELIVER, we can clear transaction here */
683 trans->sms.cp_state = GSM411_CPS_IDLE;
684 trans_free(trans);
685 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200686
687 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200688}
689
690static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
691{
692 struct msgb *msg = gsm411_msgb_alloc();
693 u_int8_t *causep;
694
Harald Welte76042182009-08-08 16:03:15 +0200695 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200696 *causep = cause;
697
698 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
699}
700
701/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000702int gsm0411_rcv_sms(struct msgb *msg)
703{
704 struct gsm48_hdr *gh = msgb_l3(msg);
705 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200706 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
707 struct gsm_lchan *lchan = msg->lchan;
708 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000709 int rc = 0;
710
Harald Weltef3efc592009-07-27 20:11:35 +0200711 if (!lchan->subscr)
712 return -EIO;
713 /* FIXME: send some error message */
714
715 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
716 transaction_id);
717 if (!trans) {
718 DEBUGP(DSMS, "Unknown transaction ID %x, "
719 "creating new trans\n", transaction_id);
720 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
721 transaction_id, new_callref++);
722 if (!trans) {
723 DEBUGP(DSMS, "No memory for trans\n");
724 /* FIXME: send some error message */
725 return -ENOMEM;
726 }
727 trans->sms.cp_state = GSM411_CPS_IDLE;
728 trans->sms.rp_state = GSM411_RPS_IDLE;
729 trans->sms.is_mt = 0;
730
731 trans->lchan = lchan;
732 use_lchan(lchan);
733 }
734
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000735 switch(msg_type) {
736 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200737 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200738 /* 5.2.3.1.3: MO state exists when SMC has received
739 * CP-DATA, including sending of the assoc. CP-ACK */
740 /* 5.2.3.2.4: MT state exists when SMC has received
741 * CP-DATA, including sending of the assoc. CP-ACK */
742 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200743
744 rc = gsm411_rx_cp_data(msg, gh, trans);
745 /* Send CP-ACK or CP-ERORR in response */
746 if (rc < 0) {
747 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
748 } else
749 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000750 break;
751 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200752 /* previous CP-DATA in this transaction was confirmed */
753 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200754 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
755 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
756 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200757 /* Stop TC1* after CP-ACK has been received */
758 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200759
Harald Weltef3efc592009-07-27 20:11:35 +0200760 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200761 /* FIXME: we have sont one CP-DATA, which was now
762 * acknowledged. Check if we want to transfer more,
763 * i.e. multi-part message */
764 trans->sms.cp_state = GSM411_CPS_IDLE;
765 trans_free(trans);
766 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000767 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000768 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200769 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
Harald Welte41985612009-08-10 00:24:32 +0200770 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200771 trans->sms.cp_state = GSM411_CPS_IDLE;
772 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000773 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000774 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200775 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
776 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200777 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200778 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000779 break;
780 }
781
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000782 return rc;
783}
784
Harald Welte8c2e36e2008-12-30 15:00:14 +0000785#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000786/* Test TPDU - ALL YOUR */
787static u_int8_t tpdu_test[] = {
788 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
789 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
790 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
791 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000792};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000793#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000794
Harald Weltecf6a3812009-08-09 19:07:41 +0200795/* Take a SMS in gsm_sms structure and send it through an already
796 * existing lchan. We also assume that the caller ensured this lchan already
797 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200798int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000799{
800 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200801 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200802 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200803 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200804 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200805 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000806
Harald Weltecf6a3812009-08-09 19:07:41 +0200807 transaction_id = 4; /* FIXME: we always use 4 for now */
808
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000809 msg->lchan = lchan;
810
Harald Welte76042182009-08-08 16:03:15 +0200811 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200812
Harald Welte76042182009-08-08 16:03:15 +0200813 /* FIXME: allocate transaction with message reference */
814 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
815 transaction_id, new_callref++);
816 if (!trans) {
817 DEBUGP(DSMS, "No memory for trans\n");
818 /* FIXME: send some error message */
819 return -ENOMEM;
820 }
821 trans->sms.cp_state = GSM411_CPS_IDLE;
822 trans->sms.rp_state = GSM411_RPS_IDLE;
823 trans->sms.is_mt = 1;
824 trans->sms.sms = sms;
825
826 trans->lchan = lchan;
827 use_lchan(lchan);
828
829 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000830 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200831 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200832 data[1] = 0x91; /* type of number: international, ISDN */
833 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000834 data[3] = 0x77;
835 data[4] = 0x58;
836 data[5] = 0x10;
837 data[6] = 0x06;
838 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200839
840 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000841 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200842 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000843
Harald Welte76042182009-08-08 16:03:15 +0200844 /* obtain a pointer for the rp_ud_len, so we can fill it later */
845 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000846
Harald Welte76042182009-08-08 16:03:15 +0200847#if 1
848 /* generate the 03.40 TPDU */
849 rc = gsm340_gen_tpdu(msg, sms);
850 if (rc < 0) {
851 msgb_free(msg);
852 return rc;
853 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000854
Harald Welte76042182009-08-08 16:03:15 +0200855 *rp_ud_len = rc;
856#else
857 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000858 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200859 *rp_ud_len = sizeof(tpdu_test);
860#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000861
Harald Welte76042182009-08-08 16:03:15 +0200862 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000863
Harald Weltef3efc592009-07-27 20:11:35 +0200864 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
865 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000866}
Harald Weltef3efc592009-07-27 20:11:35 +0200867
Harald Weltecf6a3812009-08-09 19:07:41 +0200868/* RLL SAPI3 establish callback. Now we have a RLL connection and
869 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200870static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
871 void *_sms, enum bsc_rllr_ind type)
872{
873 struct gsm_sms *sms = _sms;
874
875 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
876 lchan, link_id, sms, type);
877
878 switch (type) {
879 case BSC_RLLR_IND_EST_CONF:
880 gsm411_send_sms_lchan(lchan, sms);
881 break;
882 case BSC_RLLR_IND_REL_IND:
883 case BSC_RLLR_IND_ERR_IND:
884 case BSC_RLLR_IND_TIMEOUT:
885 sms_free(sms);
886 break;
887 }
888}
889
Harald Weltecf6a3812009-08-09 19:07:41 +0200890/* paging callback. Here we get called if paging a subscriber has
891 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200892static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
893 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200894{
Harald Welte76042182009-08-08 16:03:15 +0200895 struct gsm_lchan *lchan = _lchan;
896 struct gsm_sms *sms = _sms;
897 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200898
Harald Welte76042182009-08-08 16:03:15 +0200899 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
900 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
901
902 if (hooknum != GSM_HOOK_RR_PAGING)
903 return -EINVAL;
904
905 switch (event) {
906 case GSM_PAGING_SUCCEEDED:
907 /* Paging aborted without lchan ?!? */
908 if (!lchan) {
909 sms_free(sms);
910 rc = -EIO;
911 break;
912 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200913 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200914 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200915 break;
916 case GSM_PAGING_EXPIRED:
917 sms_free(sms);
918 rc = -ETIMEDOUT;
919 break;
920 default:
921 rc = -EINVAL;
922 break;
923 }
924
925 return rc;
926}
927
Harald Weltecf6a3812009-08-09 19:07:41 +0200928/* high-level function to send a SMS to a given subscriber. The function
929 * will take care of paging the subscriber, establishing the RLL SAPI3
930 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200931int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
932 struct gsm_sms *sms)
933{
Harald Weltecf6a3812009-08-09 19:07:41 +0200934 struct gsm_lchan *lchan;
935
Harald Welte76042182009-08-08 16:03:15 +0200936 /* check if we already have an open lchan to the subscriber.
937 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200938 lchan = lchan_for_subscr(subscr);
939 if (lchan)
940 return rll_establish(lchan, UM_SAPI_SMS,
941 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200942
943 /* if not, we have to start paging */
944 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
945 paging_cb_send_sms, sms);
946
947 return 0;
948}
Harald Welte3366a942009-07-28 00:44:49 +0200949
Harald Weltecf6a3812009-08-09 19:07:41 +0200950static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
951 void *handler_data, void *signal_data)
952{
953 struct gsm_subscriber *subscr;
954 struct gsm_lchan *lchan;
955 struct gsm_sms *sms;
956
957 switch (signal) {
958 case S_SUBSCR_ATTACHED:
959 /* A subscriber has attached. Check if there are
960 * any pending SMS for him to be delivered */
961 subscr = signal_data;
962 lchan = lchan_for_subscr(subscr);
963 if (!lchan)
964 break;
965 sms = db_sms_get_unsent_for_subscr(subscr);
966 if (!sms)
967 break;
968 /* Establish a SAPI3 RLL connection for SMS */
969 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
970 break;
971 default:
972 break;
973 }
974 return 0;
975}
976
Harald Welte7bfc2672009-07-28 00:41:45 +0200977static __attribute__((constructor)) void on_dso_load_sms(void)
978{
Harald Welte7bfc2672009-07-28 00:41:45 +0200979 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200980
981 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200982}