blob: 4ab06ecb9ed5e09540e4a40d8a26c63ef827ca6f [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 Weltecb8f4432009-08-09 14:59:02 +0200539 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200540
541 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200542}
543
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200546{
Harald Welte76042182009-08-08 16:03:15 +0200547 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200548 u_int8_t cause_len = rph->data[0];
549 u_int8_t cause = rph->data[1];
550
Harald Welteb9c758b2009-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 Weltef3efc592009-07-27 20:11:35 +0200555 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
556
Harald Weltecb8f4432009-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 Welte3e0f6172009-07-09 23:52:59 +0200562
Harald Welte76042182009-08-08 16:03:15 +0200563 if (!sms) {
Harald Weltecb8f4432009-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 Welte76042182009-08-08 16:03:15 +0200574 }
575
576 sms_free(sms);
577 trans->sms.sms = NULL;
578
Harald Weltecb8f4432009-08-09 14:59:02 +0200579 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200580
Harald Weltef3efc592009-07-27 20:11:35 +0200581 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200582}
583
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200586{
Harald Weltef3efc592009-07-27 20:11:35 +0200587 int rc;
588
Harald Welteb9c758b2009-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 Welte76042182009-08-08 16:03:15 +0200592 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200598}
599
Harald Weltef3efc592009-07-27 20:11:35 +0200600static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
601 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000602{
Daniel Willmann471712b2008-12-29 01:54:02 +0000603 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000604 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000605 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000606
607 switch (msg_type) {
608 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-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 Welte7e310b12009-03-30 20:56:32 +0000613 break;
614 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200617 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000618 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-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);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000626 break;
627 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000628 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200629 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
630 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000631 break;
632 }
633
634 return rc;
635}
636
Harald Weltef3efc592009-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 Welte76042182009-08-08 16:03:15 +0200650 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-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 */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000657int 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 Weltef3efc592009-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;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000664 int rc = 0;
665
Harald Weltef3efc592009-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
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000690 switch(msg_type) {
691 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200692 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-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 Weltef3efc592009-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);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000705 break;
706 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200707 /* previous CP-DATA in this transaction was confirmed */
708 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-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 Weltef3efc592009-07-27 20:11:35 +0200713 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-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 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000720 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000721 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-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);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000725 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000726 default:
Harald Weltef3efc592009-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 Weltecb8f4432009-08-09 14:59:02 +0200729 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200730 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000731 break;
732 }
733
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000734 return rc;
735}
736
Harald Welte8c2e36e2008-12-30 15:00:14 +0000737#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000738/* 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
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000744};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000745#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000746
Harald Welte76042182009-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)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000749{
750 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200751 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200752 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200753 u_int8_t msg_ref = 42;
Harald Welte76042182009-08-08 16:03:15 +0200754 u_int8_t transaction_id = 1; /* FIXME: random */
755 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000756
757 msg->lchan = lchan;
758
Harald Welte76042182009-08-08 16:03:15 +0200759 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200760
Harald Welte76042182009-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 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000778 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200779 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200780 data[1] = 0x91; /* type of number: international, ISDN */
781 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000782 data[3] = 0x77;
783 data[4] = 0x58;
784 data[5] = 0x10;
785 data[6] = 0x06;
786 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200787
788 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000789 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200790 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000791
Harald Welte76042182009-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);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000794
Harald Welte76042182009-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 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000802
Harald Welte76042182009-08-08 16:03:15 +0200803 *rp_ud_len = rc;
804#else
805 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000806 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200807 *rp_ud_len = sizeof(tpdu_test);
808#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000809
Harald Welte76042182009-08-08 16:03:15 +0200810 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000811
Harald Weltef3efc592009-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 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000814}
Harald Weltef3efc592009-07-27 20:11:35 +0200815
Harald Weltecb8f4432009-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 Welte76042182009-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 Weltef3efc592009-07-27 20:11:35 +0200840{
Harald Welte76042182009-08-08 16:03:15 +0200841 struct gsm_lchan *lchan = _lchan;
842 struct gsm_sms *sms = _sms;
843 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200844
Harald Welte76042182009-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 Weltecb8f4432009-08-09 14:59:02 +0200859 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-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 Welte3366a942009-07-28 00:44:49 +0200887
Harald Welte7bfc2672009-07-28 00:41:45 +0200888static __attribute__((constructor)) void on_dso_load_sms(void)
889{
Harald Welte7bfc2672009-07-28 00:41:45 +0200890 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
891}