blob: 9a5a08cde65bb29066b649ad9a906aa380e0ff37 [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Harald Welte7e310b12009-03-30 20:56:32 +00006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Daniel Willmann8b3390e2008-12-28 00:31:09 +00007 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
Harald Weltef3efc592009-07-27 20:11:35 +020031#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
Harald Welte7e310b12009-03-30 20:56:32 +000035#include <openbsc/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000036#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000037#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000041#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000042#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000043#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000044#include <openbsc/db.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Weltef3efc592009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000049
Daniel Willmann471712b2008-12-29 01:54:02 +000050#define GSM411_ALLOC_SIZE 1024
51#define GSM411_ALLOC_HEADROOM 128
52
Harald Weltecb8f4432009-08-09 14:59:02 +020053#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
54
Harald Welte2cf161b2009-06-20 22:36:41 +020055static void *tall_gsms_ctx;
56
Harald Weltef3efc592009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte76042182009-08-08 16:03:15 +020059struct gsm_sms *sms_alloc(void)
60{
61 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
62}
63
64void sms_free(struct gsm_sms *sms)
65{
66 /* drop references to subscriber structure */
67 if (sms->sender)
68 subscr_put(sms->sender);
69 if (sms->receiver)
70 subscr_put(sms->receiver);
71
72 talloc_free(sms);
73}
74
Holger Freythera553d092009-01-04 20:16:25 +000075struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000076{
Harald Welte966636f2009-06-26 19:39:35 +020077 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
78 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +000079}
80
Harald Welte87f5d632009-07-04 17:39:00 +020081static int gsm411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000082{
83 if (msg->lchan)
84 msg->trx = msg->lchan->ts->trx;
85
86 msg->l3h = msg->data;
87
Harald Welte76042182009-08-08 16:03:15 +020088 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
89
Harald Weltecb8f4432009-08-09 14:59:02 +020090 return rsl_data_request(msg, UM_SAPI_SMS);
Daniel Willmann471712b2008-12-29 01:54:02 +000091}
92
Harald Welte87f5d632009-07-04 17:39:00 +020093/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +020094static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
95 u_int8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +020096{
97 struct gsm48_hdr *gh;
98
99 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
100 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +0200101 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200102 gh->msg_type = msg_type;
103
Harald Weltef3efc592009-07-27 20:11:35 +0200104 /* assign the outgoing lchan */
105 msg->lchan = trans->lchan;
106
107 /* mobile originating */
108 switch (gh->msg_type) {
109 case GSM411_MT_CP_DATA:
110 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Weltecb8f4432009-08-09 14:59:02 +0200111 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200112 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
113 break;
114 }
115
Harald Welte87f5d632009-07-04 17:39:00 +0200116 return gsm411_sendmsg(msg);
117}
118
119/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200120static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
121 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte87f5d632009-07-04 17:39:00 +0200122{
123 struct gsm411_rp_hdr *rp;
124
125 /* GSM 04.11 RP-DATA header */
126 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
127 rp->len = msg->len;
128 rp->msg_type = rp_msg_type;
129 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
130
Harald Weltef3efc592009-07-27 20:11:35 +0200131 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200132}
133
Harald Welte76042182009-08-08 16:03:15 +0200134static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000135{
136 u_int8_t vp;
137 unsigned long minutes;
138
Harald Welte76042182009-08-08 16:03:15 +0200139 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000140 case GSM340_TP_VPF_RELATIVE:
141 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200142 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000143 if (vp <= 143)
144 minutes = vp + 1 * 5;
145 else if (vp <= 167)
146 minutes = 12*60 + (vp-143) * 30;
147 else if (vp <= 196)
148 minutes = vp-166 * 60 * 24;
149 else
150 minutes = vp-192 * 60 * 24 * 7;
151 break;
152 case GSM340_TP_VPF_ABSOLUTE:
153 /* Chapter 9.2.3.12.2 */
154 /* FIXME: like service center time stamp */
155 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
156 break;
157 case GSM340_TP_VPF_ENHANCED:
158 /* Chapter 9.2.3.12.3 */
159 /* FIXME: implementation */
160 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
161 break;
162 }
163 return minutes;
164}
165
166/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
167enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
168{
169 u_int8_t cgbits = dcs >> 4;
170 enum sms_alphabet alpha = DCS_NONE;
171
172 if ((cgbits & 0xc) == 0) {
173 if (cgbits & 2)
174 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
175
176 switch (dcs & 3) {
177 case 0:
178 alpha = DCS_7BIT_DEFAULT;
179 break;
180 case 1:
181 alpha = DCS_8BIT_DATA;
182 break;
183 case 2:
184 alpha = DCS_UCS2;
185 break;
186 }
187 } else if (cgbits == 0xc || cgbits == 0xd)
188 alpha = DCS_7BIT_DEFAULT;
189 else if (cgbits == 0xe)
190 alpha = DCS_UCS2;
191 else if (cgbits == 0xf) {
192 if (dcs & 4)
193 alpha = DCS_8BIT_DATA;
194 else
195 alpha = DCS_7BIT_DEFAULT;
196 }
197
198 return alpha;
199}
200
Harald Welte76042182009-08-08 16:03:15 +0200201static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000202{
203 if (db_sms_store(gsms) != 0) {
204 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200205 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000206 }
Harald Welte76042182009-08-08 16:03:15 +0200207 /* dispatch a signal to tell higher level about it */
208 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000209 return 0;
210}
211
Harald Welte76042182009-08-08 16:03:15 +0200212/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
213static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
214 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200215{
Harald Welte76042182009-08-08 16:03:15 +0200216 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200217
Harald Welte76042182009-08-08 16:03:15 +0200218 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
219
220 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
221
222 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
223 oa[0] = strlen(subscr->extension) & 0xff;
224
225 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200226}
227
228static u_int8_t bcdify(u_int8_t value)
229{
230 u_int8_t ret;
231
Harald Welte76042182009-08-08 16:03:15 +0200232 ret = value / 10;
233 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200234
235 return ret;
236}
237
238/* Generate 03.40 TP-SCTS */
239static void gsm340_gen_scts(u_int8_t *scts, time_t time)
240{
241 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200242
243 *scts++ = bcdify(tm->tm_year % 100);
244 *scts++ = bcdify(tm->tm_mon);
245 *scts++ = bcdify(tm->tm_mday);
246 *scts++ = bcdify(tm->tm_hour);
247 *scts++ = bcdify(tm->tm_min);
248 *scts++ = bcdify(tm->tm_sec);
249 *scts++ = 0; /* FIXME: timezone */
250}
251
Harald Welte76042182009-08-08 16:03:15 +0200252/* generate a msgb containing a TPDU derived from struct gsm_sms,
253 * returns total size of TPDU */
254static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200255{
Harald Weltef3efc592009-07-27 20:11:35 +0200256 u_int8_t *smsp;
257 u_int8_t oa[12]; /* max len per 03.40 */
258 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200259 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200260
261 /* generate first octet with masked bits */
262 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200263 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200264 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200265 /* TP-MMS (more messages to send) */
266 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200267 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200268 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200269 if (sms->status_rep_req)
270 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200271 /* TP-UDHI (indicating TP-UD contains a header) */
272 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200273 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200274#if 0
275 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200276 if (sms->
277 *smsp |= 0x80;
278#endif
279
280 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200281 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200282 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200283 memcpy(smsp, oa, oa_len);
284
285 /* generate TP-PID */
286 smsp = msgb_put(msg, 1);
287 *smsp = sms->protocol_id;
288
289 /* generate TP-DCS */
290 smsp = msgb_put(msg, 1);
291 *smsp = sms->data_coding_scheme;
292
293 /* generate TP-SCTS */
294 smsp = msgb_put(msg, 7);
295 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200296
Harald Weltef3efc592009-07-27 20:11:35 +0200297 /* generate TP-UDL */
298 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200299 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200300
301 /* generate TP-UD */
Harald Welte76042182009-08-08 16:03:15 +0200302 smsp = msgb_put(msg, sms->user_data_len);
303 memcpy(smsp, sms->user_data, sms->user_data_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200304
Harald Welte76042182009-08-08 16:03:15 +0200305 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200306}
307
Harald Welteb9c758b2009-07-05 14:02:46 +0200308/* process an incoming TPDU (called from RP-DATA)
309 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000310static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000311{
Harald Welte9176bd42009-07-23 18:46:00 +0200312 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000313 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000314 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200315 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
316 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000317 u_int8_t da_len_bytes;
318 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
319 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000320
Harald Welte76042182009-08-08 16:03:15 +0200321 gsms = sms_alloc();
322 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200323 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000324
325 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200326 sms_mti = *smsp & 0x03;
327 sms_mms = !!(*smsp & 0x04);
328 sms_vpf = (*smsp & 0x18) >> 3;
329 gsms->status_rep_req = (*smsp & 0x20);
330 gsms->ud_hdr_ind = (*smsp & 0x40);
331 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000332
333 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200334 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000335
Harald Welte7e310b12009-03-30 20:56:32 +0000336 /* length in bytes of the destination address */
337 da_len_bytes = 2 + *smsp/2 + *smsp%2;
338 if (da_len_bytes > 12) {
339 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200340 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000341 goto out;
342 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800343 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000344 memcpy(address_lv, smsp, da_len_bytes);
345 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800346 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000347 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200348 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000349 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000350
Harald Welte76042182009-08-08 16:03:15 +0200351 gsms->protocol_id = *smsp++;
352 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000353
Harald Welte76042182009-08-08 16:03:15 +0200354 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000355
Harald Welte76042182009-08-08 16:03:15 +0200356 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000357 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200358 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000359 break;
360 case GSM340_TP_VPF_ABSOLUTE:
361 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200362 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000363 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000364 break;
365 default:
366 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200367 sms_vpf);
368 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000369 }
Harald Welte76042182009-08-08 16:03:15 +0200370 gsms->user_data_len = *smsp++;
371 if (gsms->user_data_len) {
372 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000373
Harald Welte76042182009-08-08 16:03:15 +0200374 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000375 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200376 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000377 break;
378 case DCS_8BIT_DATA:
379 case DCS_UCS2:
380 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000381 break;
382 }
383 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000384
Harald Welte7e310b12009-03-30 20:56:32 +0000385 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
386 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200387 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
388 gsms->protocol_id, gsms->data_coding_scheme,
389 gsms->dest_addr, gsms->user_data_len,
390 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
391 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000392
Harald Welte76042182009-08-08 16:03:15 +0200393 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000394
Harald Welte76042182009-08-08 16:03:15 +0200395 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200396
Harald Welte76042182009-08-08 16:03:15 +0200397 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200398
Harald Welte7e310b12009-03-30 20:56:32 +0000399 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200400 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000401 if (!gsms->receiver) {
402 rc = 1; /* cause 1: unknown subscriber */
403 goto out;
404 }
405
Harald Welte76042182009-08-08 16:03:15 +0200406 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000407 case GSM340_SMS_SUBMIT_MS2SC:
408 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200409 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000410 break;
411 case GSM340_SMS_COMMAND_MS2SC:
412 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200413 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200414 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000415 break;
416 default:
Harald Welte76042182009-08-08 16:03:15 +0200417 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200418 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000419 break;
420 }
421
Harald Welteb9c758b2009-07-05 14:02:46 +0200422 if (!rc && !gsms->receiver)
423 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
424
Harald Welte7e310b12009-03-30 20:56:32 +0000425out:
Harald Welte76042182009-08-08 16:03:15 +0200426 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000427
Harald Welte7e310b12009-03-30 20:56:32 +0000428 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000429}
430
Harald Weltef3efc592009-07-27 20:11:35 +0200431static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000432{
433 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000434
Daniel Willmann471712b2008-12-29 01:54:02 +0000435 DEBUGP(DSMS, "TX: SMS RP ACK\n");
436
Harald Weltef3efc592009-07-27 20:11:35 +0200437 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000438}
439
Harald Weltef3efc592009-07-27 20:11:35 +0200440static int gsm411_send_rp_error(struct gsm_trans *trans,
441 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000442{
443 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000444
Harald Welte7e310b12009-03-30 20:56:32 +0000445 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000446
Harald Welte7e310b12009-03-30 20:56:32 +0000447 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000448
Harald Weltef3efc592009-07-27 20:11:35 +0200449 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000450}
451
Harald Welte7e310b12009-03-30 20:56:32 +0000452/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200453static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
454 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000455 u_int8_t src_len, u_int8_t *src,
456 u_int8_t dst_len, u_int8_t *dst,
457 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000458{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000459 int rc = 0;
460
Harald Welte7e310b12009-03-30 20:56:32 +0000461 if (src_len && src)
462 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
463
464 if (!dst_len || !dst || !tpdu_len || !tpdu) {
465 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200466 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200467 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000468 return -EIO;
469 }
470 msg->smsh = tpdu;
471
472 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000473
474 rc = gsm340_rx_tpdu(msg);
475 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200476 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000477 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200478 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000479 else
480 return rc;
481}
482
483/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200484static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
485 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000486{
487 u_int8_t src_len, dst_len, rpud_len;
488 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
489
490 /* in the MO case, this should always be zero length */
491 src_len = rph->data[0];
492 if (src_len)
493 src = &rph->data[1];
494
495 dst_len = rph->data[1+src_len];
496 if (dst_len)
497 dst = &rph->data[1+src_len+1];
498
499 rpud_len = rph->data[1+src_len+1+dst_len];
500 if (rpud_len)
501 rp_ud = &rph->data[1+src_len+1+dst_len+1];
502
Harald Welteb9c758b2009-07-05 14:02:46 +0200503 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
504 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200505 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000506 rpud_len, rp_ud);
507}
508
Harald Weltecb8f4432009-08-09 14:59:02 +0200509/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200510static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
511 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200512{
Harald Welte76042182009-08-08 16:03:15 +0200513 struct gsm_sms *sms = trans->sms.sms;
514
Harald Welteb9c758b2009-07-05 14:02:46 +0200515 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
516 * successfully received a SMS. We can now safely mark it as
517 * transmitted */
518
Harald Weltecb8f4432009-08-09 14:59:02 +0200519 if (!trans->sms.is_mt) {
520 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
521 return gsm411_send_rp_error(trans, rph->msg_ref,
522 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
523 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200524
Harald Welte76042182009-08-08 16:03:15 +0200525 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200526 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
527 return gsm411_send_rp_error(trans, rph->msg_ref,
528 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200529 }
530
531 /* mark this SMS as sent in database */
532 db_sms_mark_sent(sms);
533
534 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
535
536 sms_free(sms);
537 trans->sms.sms = NULL;
538
Harald Weltecf6a3812009-08-09 19:07:41 +0200539 /* do not free the transaction here, this is done by sending CP-ACK */
540
541 /* check for more messages for this subscriber */
542 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
543 if (sms)
544 gsm411_send_sms_lchan(msg->lchan, sms);
545 else
546 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200547
548 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200549}
550
Harald Weltef3efc592009-07-27 20:11:35 +0200551static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
552 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200553{
Harald Welte76042182009-08-08 16:03:15 +0200554 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200555 u_int8_t cause_len = rph->data[0];
556 u_int8_t cause = rph->data[1];
557
Harald Welteb9c758b2009-07-05 14:02:46 +0200558 /* Error in response to MT RP_DATA, i.e. the MS did not
559 * successfully receive the SMS. We need to investigate
560 * the cause and take action depending on it */
561
Harald Weltef3efc592009-07-27 20:11:35 +0200562 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
563
Harald Weltecb8f4432009-08-09 14:59:02 +0200564 if (!trans->sms.is_mt) {
565 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
566 return gsm411_send_rp_error(trans, rph->msg_ref,
567 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
568 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200569
Harald Welte76042182009-08-08 16:03:15 +0200570 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200571 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
572 return gsm411_send_rp_error(trans, rph->msg_ref,
573 GSM411_RP_CAUSE_PROTOCOL_ERR);
574 }
575
576 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
577 /* MS has not enough memory to store the message. We need
578 * to store this in our database and wati for a SMMA message */
579 /* FIXME */
580 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200581 }
582
583 sms_free(sms);
584 trans->sms.sms = NULL;
585
Harald Weltecb8f4432009-08-09 14:59:02 +0200586 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200587
Harald Weltef3efc592009-07-27 20:11:35 +0200588 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200589}
590
Harald Weltef3efc592009-07-27 20:11:35 +0200591static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
592 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200593{
Harald Weltecf6a3812009-08-09 19:07:41 +0200594 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200595 int rc;
596
Harald Weltecf6a3812009-08-09 19:07:41 +0200597 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
598 trans->sms.rp_state = GSM411_RPS_IDLE;
599
Harald Welteb9c758b2009-07-05 14:02:46 +0200600 /* MS tells us that it has memory for more SMS, we need
601 * to check if we have any pending messages for it and then
602 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200603 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200604
Harald Weltecf6a3812009-08-09 19:07:41 +0200605 /* check for more messages for this subscriber */
606 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
607 if (sms)
608 gsm411_send_sms_lchan(msg->lchan, sms);
609 else
610 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200611
612 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200613}
614
Harald Weltef3efc592009-07-27 20:11:35 +0200615static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
616 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000617{
Daniel Willmann471712b2008-12-29 01:54:02 +0000618 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000619 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000620 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000621
622 switch (msg_type) {
623 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200624 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
625 /* start TR2N and enter 'wait to send RP-ACK state' */
626 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
627 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000628 break;
629 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200630 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
631 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200632 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000633 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200634 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
635 /* start TR2N and enter 'wait to send RP-ACK state' */
636 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
637 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
638 break;
639 case GSM411_MT_RP_ERROR_MO:
640 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000641 break;
642 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000643 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200644 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
645 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000646 break;
647 }
648
649 return rc;
650}
651
Harald Weltef3efc592009-07-27 20:11:35 +0200652/* send CP-ACK to given transaction */
653static int gsm411_tx_cp_ack(struct gsm_trans *trans)
654{
655 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200656 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200657
Harald Weltecf6a3812009-08-09 19:07:41 +0200658 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
659
660 if (trans->sms.is_mt) {
661 /* If this is a MT SMS DELIVER, we can clear transaction here */
662 trans->sms.cp_state = GSM411_CPS_IDLE;
663 trans_free(trans);
664 }
Harald Weltef3efc592009-07-27 20:11:35 +0200665}
666
667static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
668{
669 struct msgb *msg = gsm411_msgb_alloc();
670 u_int8_t *causep;
671
Harald Welte76042182009-08-08 16:03:15 +0200672 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200673 *causep = cause;
674
675 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
676}
677
678/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000679int gsm0411_rcv_sms(struct msgb *msg)
680{
681 struct gsm48_hdr *gh = msgb_l3(msg);
682 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200683 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
684 struct gsm_lchan *lchan = msg->lchan;
685 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000686 int rc = 0;
687
Harald Weltef3efc592009-07-27 20:11:35 +0200688 if (!lchan->subscr)
689 return -EIO;
690 /* FIXME: send some error message */
691
692 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
693 transaction_id);
694 if (!trans) {
695 DEBUGP(DSMS, "Unknown transaction ID %x, "
696 "creating new trans\n", transaction_id);
697 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
698 transaction_id, new_callref++);
699 if (!trans) {
700 DEBUGP(DSMS, "No memory for trans\n");
701 /* FIXME: send some error message */
702 return -ENOMEM;
703 }
704 trans->sms.cp_state = GSM411_CPS_IDLE;
705 trans->sms.rp_state = GSM411_RPS_IDLE;
706 trans->sms.is_mt = 0;
707
708 trans->lchan = lchan;
709 use_lchan(lchan);
710 }
711
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000712 switch(msg_type) {
713 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200714 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200715 /* 5.2.3.1.3: MO state exists when SMC has received
716 * CP-DATA, including sending of the assoc. CP-ACK */
717 /* 5.2.3.2.4: MT state exists when SMC has received
718 * CP-DATA, including sending of the assoc. CP-ACK */
719 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200720
721 rc = gsm411_rx_cp_data(msg, gh, trans);
722 /* Send CP-ACK or CP-ERORR in response */
723 if (rc < 0) {
724 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
725 } else
726 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000727 break;
728 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200729 /* previous CP-DATA in this transaction was confirmed */
730 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200731 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
732 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
733 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
734
Harald Weltef3efc592009-07-27 20:11:35 +0200735 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200736 /* FIXME: we have sont one CP-DATA, which was now
737 * acknowledged. Check if we want to transfer more,
738 * i.e. multi-part message */
739 trans->sms.cp_state = GSM411_CPS_IDLE;
740 trans_free(trans);
741 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000742 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000743 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200744 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
745 trans->sms.cp_state = GSM411_CPS_IDLE;
746 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000747 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000748 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200749 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
750 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200751 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200752 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000753 break;
754 }
755
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000756 return rc;
757}
758
Harald Welte8c2e36e2008-12-30 15:00:14 +0000759#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000760/* Test TPDU - ALL YOUR */
761static u_int8_t tpdu_test[] = {
762 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
763 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
764 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
765 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000766};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000767#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000768
Harald Weltecf6a3812009-08-09 19:07:41 +0200769/* Take a SMS in gsm_sms structure and send it through an already
770 * existing lchan. We also assume that the caller ensured this lchan already
771 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200772int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000773{
774 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200775 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200776 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200777 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200778 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200779 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000780
Harald Weltecf6a3812009-08-09 19:07:41 +0200781 transaction_id = 4; /* FIXME: we always use 4 for now */
782
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000783 msg->lchan = lchan;
784
Harald Welte76042182009-08-08 16:03:15 +0200785 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200786
Harald Welte76042182009-08-08 16:03:15 +0200787 /* FIXME: allocate transaction with message reference */
788 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
789 transaction_id, new_callref++);
790 if (!trans) {
791 DEBUGP(DSMS, "No memory for trans\n");
792 /* FIXME: send some error message */
793 return -ENOMEM;
794 }
795 trans->sms.cp_state = GSM411_CPS_IDLE;
796 trans->sms.rp_state = GSM411_RPS_IDLE;
797 trans->sms.is_mt = 1;
798 trans->sms.sms = sms;
799
800 trans->lchan = lchan;
801 use_lchan(lchan);
802
803 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000804 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200805 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200806 data[1] = 0x91; /* type of number: international, ISDN */
807 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000808 data[3] = 0x77;
809 data[4] = 0x58;
810 data[5] = 0x10;
811 data[6] = 0x06;
812 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200813
814 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000815 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200816 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000817
Harald Welte76042182009-08-08 16:03:15 +0200818 /* obtain a pointer for the rp_ud_len, so we can fill it later */
819 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000820
Harald Welte76042182009-08-08 16:03:15 +0200821#if 1
822 /* generate the 03.40 TPDU */
823 rc = gsm340_gen_tpdu(msg, sms);
824 if (rc < 0) {
825 msgb_free(msg);
826 return rc;
827 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000828
Harald Welte76042182009-08-08 16:03:15 +0200829 *rp_ud_len = rc;
830#else
831 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000832 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200833 *rp_ud_len = sizeof(tpdu_test);
834#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000835
Harald Welte76042182009-08-08 16:03:15 +0200836 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000837
Harald Weltef3efc592009-07-27 20:11:35 +0200838 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
839 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000840}
Harald Weltef3efc592009-07-27 20:11:35 +0200841
Harald Weltecf6a3812009-08-09 19:07:41 +0200842/* RLL SAPI3 establish callback. Now we have a RLL connection and
843 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200844static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
845 void *_sms, enum bsc_rllr_ind type)
846{
847 struct gsm_sms *sms = _sms;
848
849 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
850 lchan, link_id, sms, type);
851
852 switch (type) {
853 case BSC_RLLR_IND_EST_CONF:
854 gsm411_send_sms_lchan(lchan, sms);
855 break;
856 case BSC_RLLR_IND_REL_IND:
857 case BSC_RLLR_IND_ERR_IND:
858 case BSC_RLLR_IND_TIMEOUT:
859 sms_free(sms);
860 break;
861 }
862}
863
Harald Weltecf6a3812009-08-09 19:07:41 +0200864/* paging callback. Here we get called if paging a subscriber has
865 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200866static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
867 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200868{
Harald Welte76042182009-08-08 16:03:15 +0200869 struct gsm_lchan *lchan = _lchan;
870 struct gsm_sms *sms = _sms;
871 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200872
Harald Welte76042182009-08-08 16:03:15 +0200873 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
874 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
875
876 if (hooknum != GSM_HOOK_RR_PAGING)
877 return -EINVAL;
878
879 switch (event) {
880 case GSM_PAGING_SUCCEEDED:
881 /* Paging aborted without lchan ?!? */
882 if (!lchan) {
883 sms_free(sms);
884 rc = -EIO;
885 break;
886 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200887 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200888 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200889 break;
890 case GSM_PAGING_EXPIRED:
891 sms_free(sms);
892 rc = -ETIMEDOUT;
893 break;
894 default:
895 rc = -EINVAL;
896 break;
897 }
898
899 return rc;
900}
901
Harald Weltecf6a3812009-08-09 19:07:41 +0200902/* high-level function to send a SMS to a given subscriber. The function
903 * will take care of paging the subscriber, establishing the RLL SAPI3
904 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200905int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
906 struct gsm_sms *sms)
907{
Harald Weltecf6a3812009-08-09 19:07:41 +0200908 struct gsm_lchan *lchan;
909
Harald Welte76042182009-08-08 16:03:15 +0200910 /* check if we already have an open lchan to the subscriber.
911 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200912 lchan = lchan_for_subscr(subscr);
913 if (lchan)
914 return rll_establish(lchan, UM_SAPI_SMS,
915 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200916
917 /* if not, we have to start paging */
918 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
919 paging_cb_send_sms, sms);
920
921 return 0;
922}
Harald Welte3366a942009-07-28 00:44:49 +0200923
Harald Weltecf6a3812009-08-09 19:07:41 +0200924static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
925 void *handler_data, void *signal_data)
926{
927 struct gsm_subscriber *subscr;
928 struct gsm_lchan *lchan;
929 struct gsm_sms *sms;
930
931 switch (signal) {
932 case S_SUBSCR_ATTACHED:
933 /* A subscriber has attached. Check if there are
934 * any pending SMS for him to be delivered */
935 subscr = signal_data;
936 lchan = lchan_for_subscr(subscr);
937 if (!lchan)
938 break;
939 sms = db_sms_get_unsent_for_subscr(subscr);
940 if (!sms)
941 break;
942 /* Establish a SAPI3 RLL connection for SMS */
943 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
944 break;
945 default:
946 break;
947 }
948 return 0;
949}
950
Harald Welte7bfc2672009-07-28 00:41:45 +0200951static __attribute__((constructor)) void on_dso_load_sms(void)
952{
Harald Welte7bfc2672009-07-28 00:41:45 +0200953 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200954
955 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200956}