blob: 9a5a08cde65bb29066b649ad9a906aa380e0ff37 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* 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>
6 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
7 *
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 Welteb78996d2009-07-27 20:11:35 +020031#include <time.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
41#include <openbsc/gsm_utils.h>
42#include <openbsc/abis_rsl.h>
43#include <openbsc/signal.h>
44#include <openbsc/db.h>
Harald Weltea8379772009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Welteb78996d2009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte68b7df22009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Welte09421d32009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Harald Welte59b04682009-06-10 05:40:52 +080049
50#define GSM411_ALLOC_SIZE 1024
51#define GSM411_ALLOC_HEADROOM 128
52
Harald Welte09421d32009-08-09 14:59:02 +020053#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
54
Harald Weltea8379772009-06-20 22:36:41 +020055static void *tall_gsms_ctx;
56
Harald Welteb78996d2009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte68b7df22009-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
Harald Welte59b04682009-06-10 05:40:52 +080075struct msgb *gsm411_msgb_alloc(void)
76{
Harald Welte9cfc9352009-06-26 19:39:35 +020077 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
78 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +080079}
80
Harald Welte7e2f57d2009-07-04 17:39:00 +020081static int gsm411_sendmsg(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +080082{
83 if (msg->lchan)
84 msg->trx = msg->lchan->ts->trx;
85
86 msg->l3h = msg->data;
87
Harald Welte68b7df22009-08-08 16:03:15 +020088 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
89
Harald Welte09421d32009-08-09 14:59:02 +020090 return rsl_data_request(msg, UM_SAPI_SMS);
Harald Welte59b04682009-06-10 05:40:52 +080091}
92
Harald Welte7e2f57d2009-07-04 17:39:00 +020093/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +020094static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
95 u_int8_t msg_type)
Harald Welte7e2f57d2009-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 Welteb78996d2009-07-27 20:11:35 +0200101 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200102 gh->msg_type = msg_type;
103
Harald Welteb78996d2009-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 Welte09421d32009-08-09 14:59:02 +0200111 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200112 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
113 break;
114 }
115
Harald Welte7e2f57d2009-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 Welteb78996d2009-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 Welte7e2f57d2009-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 Welteb78996d2009-07-27 20:11:35 +0200131 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200132}
133
Harald Welte68b7df22009-08-08 16:03:15 +0200134static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800135{
136 u_int8_t vp;
137 unsigned long minutes;
138
Harald Welte68b7df22009-08-08 16:03:15 +0200139 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800140 case GSM340_TP_VPF_RELATIVE:
141 /* Chapter 9.2.3.12.1 */
Harald Welte68b7df22009-08-08 16:03:15 +0200142 vp = *(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800143 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 Welte68b7df22009-08-08 16:03:15 +0200201static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800202{
203 if (db_sms_store(gsms) != 0) {
204 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200205 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800206 }
Harald Welte68b7df22009-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 Welte59b04682009-06-10 05:40:52 +0800209 return 0;
210}
211
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200215{
Harald Welte68b7df22009-08-08 16:03:15 +0200216 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200217
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200226}
227
228static u_int8_t bcdify(u_int8_t value)
229{
230 u_int8_t ret;
231
Harald Welte68b7df22009-08-08 16:03:15 +0200232 ret = value / 10;
233 ret |= (value % 10) << 4;
Harald Welteb78996d2009-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 Welteb78996d2009-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 Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200255{
Harald Welteb78996d2009-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 Welte68b7df22009-08-08 16:03:15 +0200259 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200260
261 /* generate first octet with masked bits */
262 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200263 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200264 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200265 /* TP-MMS (more messages to send) */
266 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200267 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200268 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200269 if (sms->status_rep_req)
270 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200271 /* TP-UDHI (indicating TP-UD contains a header) */
272 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200273 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200274#if 0
275 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200276 if (sms->
277 *smsp |= 0x80;
278#endif
279
280 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200281 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200282 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-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 Welte68b7df22009-08-08 16:03:15 +0200296
Harald Welteb78996d2009-07-27 20:11:35 +0200297 /* generate TP-UDL */
298 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200299 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200300
301 /* generate TP-UD */
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200304
Harald Welte68b7df22009-08-08 16:03:15 +0200305 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200306}
307
Harald Welte156c5e62009-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 Welte59b04682009-06-10 05:40:52 +0800310static int gsm340_rx_tpdu(struct msgb *msg)
311{
Harald Welte75350412009-07-23 18:46:00 +0200312 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800313 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800314 struct gsm_sms *gsms;
Harald Welte68b7df22009-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 Welte59b04682009-06-10 05:40:52 +0800317 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;
320
Harald Welte68b7df22009-08-08 16:03:15 +0200321 gsms = sms_alloc();
322 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200323 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800324
325 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800332
333 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200334 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800335
336 /* 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 Welte156c5e62009-07-05 14:02:46 +0200340 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800341 goto out;
342 }
Harald Welte3794e152009-06-12 02:42:11 +0800343 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800344 memcpy(address_lv, smsp, da_len_bytes);
345 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800346 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800347 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200348 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800349 smsp += da_len_bytes;
350
Harald Welte68b7df22009-08-08 16:03:15 +0200351 gsms->protocol_id = *smsp++;
352 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800353
Harald Welte68b7df22009-08-08 16:03:15 +0200354 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800355
Harald Welte68b7df22009-08-08 16:03:15 +0200356 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800357 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200358 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800359 break;
360 case GSM340_TP_VPF_ABSOLUTE:
361 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200362 sms_vp = smsp;
Harald Welte59b04682009-06-10 05:40:52 +0800363 smsp += 7;
364 break;
365 default:
366 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200367 sms_vpf);
368 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800369 }
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800373
Harald Welte68b7df22009-08-08 16:03:15 +0200374 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800375 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200376 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800377 break;
378 case DCS_8BIT_DATA:
379 case DCS_UCS2:
380 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800381 break;
382 }
383 }
384
385 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 Welte68b7df22009-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));
Harald Welte59b04682009-06-10 05:40:52 +0800392
Harald Welte68b7df22009-08-08 16:03:15 +0200393 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800394
Harald Welte68b7df22009-08-08 16:03:15 +0200395 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200396
Harald Welte68b7df22009-08-08 16:03:15 +0200397 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200398
Harald Welte59b04682009-06-10 05:40:52 +0800399 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200400 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800401 if (!gsms->receiver) {
402 rc = 1; /* cause 1: unknown subscriber */
403 goto out;
404 }
405
Harald Welte68b7df22009-08-08 16:03:15 +0200406 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800407 case GSM340_SMS_SUBMIT_MS2SC:
408 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200409 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800410 break;
411 case GSM340_SMS_COMMAND_MS2SC:
412 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200413 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200414 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800415 break;
416 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200417 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200418 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800419 break;
420 }
421
Harald Welte156c5e62009-07-05 14:02:46 +0200422 if (!rc && !gsms->receiver)
423 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
424
Harald Welte59b04682009-06-10 05:40:52 +0800425out:
Harald Welte68b7df22009-08-08 16:03:15 +0200426 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800427
428 return rc;
429}
430
Harald Welteb78996d2009-07-27 20:11:35 +0200431static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800432{
433 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800434
Harald Welte59b04682009-06-10 05:40:52 +0800435 DEBUGP(DSMS, "TX: SMS RP ACK\n");
436
Harald Welteb78996d2009-07-27 20:11:35 +0200437 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800438}
439
Harald Welteb78996d2009-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)
Harald Welte59b04682009-06-10 05:40:52 +0800442{
443 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800444
Harald Welte59b04682009-06-10 05:40:52 +0800445 msgb_tv_put(msg, 1, cause);
446
447 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
448
Harald Welteb78996d2009-07-27 20:11:35 +0200449 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800450}
451
452/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800455 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)
458{
Harald Welte59b04682009-06-10 05:40:52 +0800459 int rc = 0;
460
461 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 Welteb78996d2009-07-27 20:11:35 +0200466 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200467 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800468 return -EIO;
469 }
470 msg->smsh = tpdu;
471
472 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800473
474 rc = gsm340_rx_tpdu(msg);
475 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200476 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800477 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200478 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800479 else
480 return rc;
481}
482
483/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800486{
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 Welte156c5e62009-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 Welteb78996d2009-07-27 20:11:35 +0200505 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800506 rpud_len, rp_ud);
507}
508
Harald Welte09421d32009-08-09 14:59:02 +0200509/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200512{
Harald Welte68b7df22009-08-08 16:03:15 +0200513 struct gsm_sms *sms = trans->sms.sms;
514
Harald Welte156c5e62009-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 Welte09421d32009-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 Weltedd62b162009-07-09 23:52:59 +0200524
Harald Welte68b7df22009-08-08 16:03:15 +0200525 if (!sms) {
Harald Welte09421d32009-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 Welte68b7df22009-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 Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +0200547
548 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200549}
550
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200553{
Harald Welte68b7df22009-08-08 16:03:15 +0200554 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200555 u_int8_t cause_len = rph->data[0];
556 u_int8_t cause = rph->data[1];
557
Harald Welte156c5e62009-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 Welteb78996d2009-07-27 20:11:35 +0200562 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
563
Harald Welte09421d32009-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 Weltedd62b162009-07-09 23:52:59 +0200569
Harald Welte68b7df22009-08-08 16:03:15 +0200570 if (!sms) {
Harald Welte09421d32009-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 Welte68b7df22009-08-08 16:03:15 +0200581 }
582
583 sms_free(sms);
584 trans->sms.sms = NULL;
585
Harald Welte09421d32009-08-09 14:59:02 +0200586 trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200587
Harald Welteb78996d2009-07-27 20:11:35 +0200588 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200589}
590
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200593{
Harald Weltefc01b242009-08-09 19:07:41 +0200594 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200595 int rc;
596
Harald Weltefc01b242009-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 Welte156c5e62009-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 Welte68b7df22009-08-08 16:03:15 +0200603 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200604
Harald Weltefc01b242009-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 Welteb78996d2009-07-27 20:11:35 +0200611
612 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200613}
614
Harald Welteb78996d2009-07-27 20:11:35 +0200615static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
616 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800617{
618 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
619 u_int8_t msg_type = rp_data->msg_type & 0x07;
620 int rc = 0;
621
622 switch (msg_type) {
623 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800628 break;
629 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200632 break;
Harald Welte59b04682009-06-10 05:40:52 +0800633 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800641 break;
642 default:
643 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200644 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
645 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800646 break;
647 }
648
649 return rc;
650}
651
Harald Welteb78996d2009-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 Weltefc01b242009-08-09 19:07:41 +0200656 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200657
Harald Weltefc01b242009-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 Welteb78996d2009-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 Welte68b7df22009-08-08 16:03:15 +0200672 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-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 */
Harald Welte59b04682009-06-10 05:40:52 +0800679int 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 Welteb78996d2009-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;
Harald Welte59b04682009-06-10 05:40:52 +0800686 int rc = 0;
687
Harald Welteb78996d2009-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
Harald Welte59b04682009-06-10 05:40:52 +0800712 switch(msg_type) {
713 case GSM411_MT_CP_DATA:
Harald Welteb78996d2009-07-27 20:11:35 +0200714 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-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 Welteb78996d2009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800727 break;
728 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200729 /* previous CP-DATA in this transaction was confirmed */
730 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-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 Welteb78996d2009-07-27 20:11:35 +0200735 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-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 }
Harald Welte59b04682009-06-10 05:40:52 +0800742 break;
743 case GSM411_MT_CP_ERROR:
Harald Welteb78996d2009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800747 break;
748 default:
Harald Welteb78996d2009-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 Welte09421d32009-08-09 14:59:02 +0200751 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200752 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800753 break;
754 }
755
Harald Welte59b04682009-06-10 05:40:52 +0800756 return rc;
757}
758
Harald Welte59b04682009-06-10 05:40:52 +0800759#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800760/* 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
766};
767#endif
768
Harald Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +0200772int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800773{
774 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200775 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +0200776 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200777 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +0200778 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +0200779 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800780
Harald Weltefc01b242009-08-09 19:07:41 +0200781 transaction_id = 4; /* FIXME: we always use 4 for now */
782
Harald Welte59b04682009-06-10 05:40:52 +0800783 msg->lchan = lchan;
784
Harald Welte68b7df22009-08-08 16:03:15 +0200785 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200786
Harald Welte68b7df22009-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 */
Harald Welte59b04682009-06-10 05:40:52 +0800804 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200805 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200806 data[1] = 0x91; /* type of number: international, ISDN */
807 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800808 data[3] = 0x77;
809 data[4] = 0x58;
810 data[5] = 0x10;
811 data[6] = 0x06;
812 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200813
814 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800815 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200816 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800817
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800820
Harald Welte68b7df22009-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 }
Harald Welte59b04682009-06-10 05:40:52 +0800828
Harald Welte68b7df22009-08-08 16:03:15 +0200829 *rp_ud_len = rc;
830#else
831 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +0800832 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +0200833 *rp_ud_len = sizeof(tpdu_test);
834#endif
Harald Welte59b04682009-06-10 05:40:52 +0800835
Harald Welte68b7df22009-08-08 16:03:15 +0200836 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +0800837
Harald Welteb78996d2009-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 */
Harald Welte59b04682009-06-10 05:40:52 +0800840}
Harald Welteb78996d2009-07-27 20:11:35 +0200841
Harald Weltefc01b242009-08-09 19:07:41 +0200842/* RLL SAPI3 establish callback. Now we have a RLL connection and
843 * can deliver the actual message */
Harald Welte09421d32009-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 Weltefc01b242009-08-09 19:07:41 +0200864/* paging callback. Here we get called if paging a subscriber has
865 * succeeded or failed. */
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +0200868{
Harald Welte68b7df22009-08-08 16:03:15 +0200869 struct gsm_lchan *lchan = _lchan;
870 struct gsm_sms *sms = _sms;
871 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200872
Harald Welte68b7df22009-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 Weltefc01b242009-08-09 19:07:41 +0200887 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +0200888 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-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 Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +0200905int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
906 struct gsm_sms *sms)
907{
Harald Weltefc01b242009-08-09 19:07:41 +0200908 struct gsm_lchan *lchan;
909
Harald Welte68b7df22009-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 Weltefc01b242009-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 Welte68b7df22009-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 Welte5b359d82009-07-28 00:44:49 +0200923
Harald Weltefc01b242009-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 Welte932e20d2009-07-28 00:41:45 +0200951static __attribute__((constructor)) void on_dso_load_sms(void)
952{
Harald Welte932e20d2009-07-28 00:41:45 +0200953 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltefc01b242009-08-09 19:07:41 +0200954
955 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +0200956}