blob: 4ab06ecb9ed5e09540e4a40d8a26c63ef827ca6f [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 Welte09421d32009-08-09 14:59:02 +0200539 trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200540
541 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200542}
543
Harald Welteb78996d2009-07-27 20:11:35 +0200544static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
545 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200546{
Harald Welte68b7df22009-08-08 16:03:15 +0200547 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200548 u_int8_t cause_len = rph->data[0];
549 u_int8_t cause = rph->data[1];
550
Harald Welte156c5e62009-07-05 14:02:46 +0200551 /* Error in response to MT RP_DATA, i.e. the MS did not
552 * successfully receive the SMS. We need to investigate
553 * the cause and take action depending on it */
554
Harald Welteb78996d2009-07-27 20:11:35 +0200555 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
556
Harald Welte09421d32009-08-09 14:59:02 +0200557 if (!trans->sms.is_mt) {
558 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
559 return gsm411_send_rp_error(trans, rph->msg_ref,
560 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
561 }
Harald Weltedd62b162009-07-09 23:52:59 +0200562
Harald Welte68b7df22009-08-08 16:03:15 +0200563 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200564 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
565 return gsm411_send_rp_error(trans, rph->msg_ref,
566 GSM411_RP_CAUSE_PROTOCOL_ERR);
567 }
568
569 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
570 /* MS has not enough memory to store the message. We need
571 * to store this in our database and wati for a SMMA message */
572 /* FIXME */
573 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200574 }
575
576 sms_free(sms);
577 trans->sms.sms = NULL;
578
Harald Welte09421d32009-08-09 14:59:02 +0200579 trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200580
Harald Welteb78996d2009-07-27 20:11:35 +0200581 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200582}
583
Harald Welteb78996d2009-07-27 20:11:35 +0200584static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
585 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200586{
Harald Welteb78996d2009-07-27 20:11:35 +0200587 int rc;
588
Harald Welte156c5e62009-07-05 14:02:46 +0200589 /* MS tells us that it has memory for more SMS, we need
590 * to check if we have any pending messages for it and then
591 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200592 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200593
594 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
595 trans->sms.rp_state = GSM411_RPS_IDLE;
596
597 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200598}
599
Harald Welteb78996d2009-07-27 20:11:35 +0200600static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
601 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800602{
603 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
604 u_int8_t msg_type = rp_data->msg_type & 0x07;
605 int rc = 0;
606
607 switch (msg_type) {
608 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200609 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
610 /* start TR2N and enter 'wait to send RP-ACK state' */
611 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
612 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800613 break;
614 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200615 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
616 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200617 break;
Harald Welte59b04682009-06-10 05:40:52 +0800618 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200619 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
620 /* start TR2N and enter 'wait to send RP-ACK state' */
621 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
622 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
623 break;
624 case GSM411_MT_RP_ERROR_MO:
625 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800626 break;
627 default:
628 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200629 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
630 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800631 break;
632 }
633
634 return rc;
635}
636
Harald Welteb78996d2009-07-27 20:11:35 +0200637/* send CP-ACK to given transaction */
638static int gsm411_tx_cp_ack(struct gsm_trans *trans)
639{
640 struct msgb *msg = gsm411_msgb_alloc();
641
642 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
643}
644
645static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
646{
647 struct msgb *msg = gsm411_msgb_alloc();
648 u_int8_t *causep;
649
Harald Welte68b7df22009-08-08 16:03:15 +0200650 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200651 *causep = cause;
652
653 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
654}
655
656/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte59b04682009-06-10 05:40:52 +0800657int gsm0411_rcv_sms(struct msgb *msg)
658{
659 struct gsm48_hdr *gh = msgb_l3(msg);
660 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200661 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
662 struct gsm_lchan *lchan = msg->lchan;
663 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800664 int rc = 0;
665
Harald Welteb78996d2009-07-27 20:11:35 +0200666 if (!lchan->subscr)
667 return -EIO;
668 /* FIXME: send some error message */
669
670 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
671 transaction_id);
672 if (!trans) {
673 DEBUGP(DSMS, "Unknown transaction ID %x, "
674 "creating new trans\n", transaction_id);
675 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
676 transaction_id, new_callref++);
677 if (!trans) {
678 DEBUGP(DSMS, "No memory for trans\n");
679 /* FIXME: send some error message */
680 return -ENOMEM;
681 }
682 trans->sms.cp_state = GSM411_CPS_IDLE;
683 trans->sms.rp_state = GSM411_RPS_IDLE;
684 trans->sms.is_mt = 0;
685
686 trans->lchan = lchan;
687 use_lchan(lchan);
688 }
689
Harald Welte59b04682009-06-10 05:40:52 +0800690 switch(msg_type) {
691 case GSM411_MT_CP_DATA:
Harald Welteb78996d2009-07-27 20:11:35 +0200692 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200693 /* 5.2.3.1.3: MO state exists when SMC has received
694 * CP-DATA, including sending of the assoc. CP-ACK */
695 /* 5.2.3.2.4: MT state exists when SMC has received
696 * CP-DATA, including sending of the assoc. CP-ACK */
697 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200698
699 rc = gsm411_rx_cp_data(msg, gh, trans);
700 /* Send CP-ACK or CP-ERORR in response */
701 if (rc < 0) {
702 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
703 } else
704 rc = gsm411_tx_cp_ack(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800705 break;
706 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200707 /* previous CP-DATA in this transaction was confirmed */
708 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200709 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
710 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
711 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
712
Harald Welteb78996d2009-07-27 20:11:35 +0200713 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200714 /* FIXME: we have sont one CP-DATA, which was now
715 * acknowledged. Check if we want to transfer more,
716 * i.e. multi-part message */
717 trans->sms.cp_state = GSM411_CPS_IDLE;
718 trans_free(trans);
719 }
Harald Welte59b04682009-06-10 05:40:52 +0800720 break;
721 case GSM411_MT_CP_ERROR:
Harald Welteb78996d2009-07-27 20:11:35 +0200722 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
723 trans->sms.cp_state = GSM411_CPS_IDLE;
724 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800725 break;
726 default:
Harald Welteb78996d2009-07-27 20:11:35 +0200727 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
728 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200729 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200730 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800731 break;
732 }
733
Harald Welte59b04682009-06-10 05:40:52 +0800734 return rc;
735}
736
Harald Welte59b04682009-06-10 05:40:52 +0800737#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800738/* Test TPDU - ALL YOUR */
739static u_int8_t tpdu_test[] = {
740 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
741 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
742 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
743 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
744};
745#endif
746
Harald Welte68b7df22009-08-08 16:03:15 +0200747/* Take a SMS in gsm_sms structure and send it through lchan */
748int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800749{
750 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200751 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +0200752 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200753 u_int8_t msg_ref = 42;
Harald Welte68b7df22009-08-08 16:03:15 +0200754 u_int8_t transaction_id = 1; /* FIXME: random */
755 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800756
757 msg->lchan = lchan;
758
Harald Welte68b7df22009-08-08 16:03:15 +0200759 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200760
Harald Welte68b7df22009-08-08 16:03:15 +0200761 /* FIXME: allocate transaction with message reference */
762 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
763 transaction_id, new_callref++);
764 if (!trans) {
765 DEBUGP(DSMS, "No memory for trans\n");
766 /* FIXME: send some error message */
767 return -ENOMEM;
768 }
769 trans->sms.cp_state = GSM411_CPS_IDLE;
770 trans->sms.rp_state = GSM411_RPS_IDLE;
771 trans->sms.is_mt = 1;
772 trans->sms.sms = sms;
773
774 trans->lchan = lchan;
775 use_lchan(lchan);
776
777 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800778 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200779 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200780 data[1] = 0x91; /* type of number: international, ISDN */
781 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800782 data[3] = 0x77;
783 data[4] = 0x58;
784 data[5] = 0x10;
785 data[6] = 0x06;
786 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200787
788 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800789 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200790 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800791
Harald Welte68b7df22009-08-08 16:03:15 +0200792 /* obtain a pointer for the rp_ud_len, so we can fill it later */
793 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800794
Harald Welte68b7df22009-08-08 16:03:15 +0200795#if 1
796 /* generate the 03.40 TPDU */
797 rc = gsm340_gen_tpdu(msg, sms);
798 if (rc < 0) {
799 msgb_free(msg);
800 return rc;
801 }
Harald Welte59b04682009-06-10 05:40:52 +0800802
Harald Welte68b7df22009-08-08 16:03:15 +0200803 *rp_ud_len = rc;
804#else
805 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +0800806 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +0200807 *rp_ud_len = sizeof(tpdu_test);
808#endif
Harald Welte59b04682009-06-10 05:40:52 +0800809
Harald Welte68b7df22009-08-08 16:03:15 +0200810 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +0800811
Harald Welteb78996d2009-07-27 20:11:35 +0200812 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
813 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800814}
Harald Welteb78996d2009-07-27 20:11:35 +0200815
Harald Welte09421d32009-08-09 14:59:02 +0200816/* RLL SAPI3 establish callback */
817static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
818 void *_sms, enum bsc_rllr_ind type)
819{
820 struct gsm_sms *sms = _sms;
821
822 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
823 lchan, link_id, sms, type);
824
825 switch (type) {
826 case BSC_RLLR_IND_EST_CONF:
827 gsm411_send_sms_lchan(lchan, sms);
828 break;
829 case BSC_RLLR_IND_REL_IND:
830 case BSC_RLLR_IND_ERR_IND:
831 case BSC_RLLR_IND_TIMEOUT:
832 sms_free(sms);
833 break;
834 }
835}
836
Harald Welte68b7df22009-08-08 16:03:15 +0200837/* paging callback */
838static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
839 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200840{
Harald Welte68b7df22009-08-08 16:03:15 +0200841 struct gsm_lchan *lchan = _lchan;
842 struct gsm_sms *sms = _sms;
843 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200844
Harald Welte68b7df22009-08-08 16:03:15 +0200845 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
846 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
847
848 if (hooknum != GSM_HOOK_RR_PAGING)
849 return -EINVAL;
850
851 switch (event) {
852 case GSM_PAGING_SUCCEEDED:
853 /* Paging aborted without lchan ?!? */
854 if (!lchan) {
855 sms_free(sms);
856 rc = -EIO;
857 break;
858 }
Harald Welte09421d32009-08-09 14:59:02 +0200859 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +0200860 break;
861 case GSM_PAGING_EXPIRED:
862 sms_free(sms);
863 rc = -ETIMEDOUT;
864 break;
865 default:
866 rc = -EINVAL;
867 break;
868 }
869
870 return rc;
871}
872
873int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
874 struct gsm_sms *sms)
875{
876 /* check if we already have an open lchan to the subscriber.
877 * if yes, send the SMS this way */
878 //if (subscr->lchan)
879 //return gsm411_send_sms_lchan(subscr->lchan, sms);
880
881 /* if not, we have to start paging */
882 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
883 paging_cb_send_sms, sms);
884
885 return 0;
886}
Harald Welte5b359d82009-07-28 00:44:49 +0200887
Harald Welte932e20d2009-07-28 00:41:45 +0200888static __attribute__((constructor)) void on_dso_load_sms(void)
889{
Harald Welte932e20d2009-07-28 00:41:45 +0200890 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
891}