blob: 728574ad7d688456a105d148eb6d8ee9edf8caf9 [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;
Harald Welte0d544e72009-08-10 00:22:19 +0200124 u_int8_t len = msg->len;
Harald Welte87f5d632009-07-04 17:39:00 +0200125
126 /* GSM 04.11 RP-DATA header */
127 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Welte0d544e72009-08-10 00:22:19 +0200128 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200129 rp->msg_type = rp_msg_type;
130 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
131
Harald Weltef3efc592009-07-27 20:11:35 +0200132 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200133}
134
Harald Welte76042182009-08-08 16:03:15 +0200135static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000136{
137 u_int8_t vp;
138 unsigned long minutes;
139
Harald Welte76042182009-08-08 16:03:15 +0200140 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000141 case GSM340_TP_VPF_RELATIVE:
142 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200143 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000144 if (vp <= 143)
145 minutes = vp + 1 * 5;
146 else if (vp <= 167)
147 minutes = 12*60 + (vp-143) * 30;
148 else if (vp <= 196)
149 minutes = vp-166 * 60 * 24;
150 else
151 minutes = vp-192 * 60 * 24 * 7;
152 break;
153 case GSM340_TP_VPF_ABSOLUTE:
154 /* Chapter 9.2.3.12.2 */
155 /* FIXME: like service center time stamp */
156 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
157 break;
158 case GSM340_TP_VPF_ENHANCED:
159 /* Chapter 9.2.3.12.3 */
160 /* FIXME: implementation */
161 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
162 break;
163 }
164 return minutes;
165}
166
167/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
168enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
169{
170 u_int8_t cgbits = dcs >> 4;
171 enum sms_alphabet alpha = DCS_NONE;
172
173 if ((cgbits & 0xc) == 0) {
174 if (cgbits & 2)
175 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
176
177 switch (dcs & 3) {
178 case 0:
179 alpha = DCS_7BIT_DEFAULT;
180 break;
181 case 1:
182 alpha = DCS_8BIT_DATA;
183 break;
184 case 2:
185 alpha = DCS_UCS2;
186 break;
187 }
188 } else if (cgbits == 0xc || cgbits == 0xd)
189 alpha = DCS_7BIT_DEFAULT;
190 else if (cgbits == 0xe)
191 alpha = DCS_UCS2;
192 else if (cgbits == 0xf) {
193 if (dcs & 4)
194 alpha = DCS_8BIT_DATA;
195 else
196 alpha = DCS_7BIT_DEFAULT;
197 }
198
199 return alpha;
200}
201
Harald Welte76042182009-08-08 16:03:15 +0200202static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000203{
204 if (db_sms_store(gsms) != 0) {
205 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200206 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000207 }
Harald Welte76042182009-08-08 16:03:15 +0200208 /* dispatch a signal to tell higher level about it */
209 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000210 return 0;
211}
212
Harald Welte76042182009-08-08 16:03:15 +0200213/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
214static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
215 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200216{
Harald Welte76042182009-08-08 16:03:15 +0200217 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200218
Harald Welte76042182009-08-08 16:03:15 +0200219 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
220
221 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
222
223 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
224 oa[0] = strlen(subscr->extension) & 0xff;
225
226 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200227}
228
229static u_int8_t bcdify(u_int8_t value)
230{
231 u_int8_t ret;
232
Harald Welte76042182009-08-08 16:03:15 +0200233 ret = value / 10;
234 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200235
236 return ret;
237}
238
239/* Generate 03.40 TP-SCTS */
240static void gsm340_gen_scts(u_int8_t *scts, time_t time)
241{
242 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200243
244 *scts++ = bcdify(tm->tm_year % 100);
245 *scts++ = bcdify(tm->tm_mon);
246 *scts++ = bcdify(tm->tm_mday);
247 *scts++ = bcdify(tm->tm_hour);
248 *scts++ = bcdify(tm->tm_min);
249 *scts++ = bcdify(tm->tm_sec);
250 *scts++ = 0; /* FIXME: timezone */
251}
252
Harald Welte76042182009-08-08 16:03:15 +0200253/* generate a msgb containing a TPDU derived from struct gsm_sms,
254 * returns total size of TPDU */
255static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200256{
Harald Weltef3efc592009-07-27 20:11:35 +0200257 u_int8_t *smsp;
258 u_int8_t oa[12]; /* max len per 03.40 */
259 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200260 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200261
262 /* generate first octet with masked bits */
263 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200264 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200265 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200266 /* TP-MMS (more messages to send) */
267 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200268 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200269 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200270 if (sms->status_rep_req)
271 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200272 /* TP-UDHI (indicating TP-UD contains a header) */
273 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200274 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200275#if 0
276 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200277 if (sms->
278 *smsp |= 0x80;
279#endif
280
281 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200282 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200283 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200284 memcpy(smsp, oa, oa_len);
285
286 /* generate TP-PID */
287 smsp = msgb_put(msg, 1);
288 *smsp = sms->protocol_id;
289
290 /* generate TP-DCS */
291 smsp = msgb_put(msg, 1);
292 *smsp = sms->data_coding_scheme;
293
294 /* generate TP-SCTS */
295 smsp = msgb_put(msg, 7);
296 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200297
Harald Weltef3efc592009-07-27 20:11:35 +0200298 /* generate TP-UDL */
299 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200300 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200301
302 /* generate TP-UD */
Harald Welte76042182009-08-08 16:03:15 +0200303 smsp = msgb_put(msg, sms->user_data_len);
304 memcpy(smsp, sms->user_data, sms->user_data_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200305
Harald Welte76042182009-08-08 16:03:15 +0200306 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200307}
308
Harald Welteb9c758b2009-07-05 14:02:46 +0200309/* process an incoming TPDU (called from RP-DATA)
310 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000311static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000312{
Harald Welte9176bd42009-07-23 18:46:00 +0200313 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000314 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000315 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200316 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
317 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000318 u_int8_t da_len_bytes;
319 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
320 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000321
Harald Welte76042182009-08-08 16:03:15 +0200322 gsms = sms_alloc();
323 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200324 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000325
326 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200327 sms_mti = *smsp & 0x03;
328 sms_mms = !!(*smsp & 0x04);
329 sms_vpf = (*smsp & 0x18) >> 3;
330 gsms->status_rep_req = (*smsp & 0x20);
331 gsms->ud_hdr_ind = (*smsp & 0x40);
332 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000333
334 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200335 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000336
Harald Welte7e310b12009-03-30 20:56:32 +0000337 /* length in bytes of the destination address */
338 da_len_bytes = 2 + *smsp/2 + *smsp%2;
339 if (da_len_bytes > 12) {
340 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200341 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000342 goto out;
343 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800344 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000345 memcpy(address_lv, smsp, da_len_bytes);
346 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800347 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000348 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200349 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000350 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000351
Harald Welte76042182009-08-08 16:03:15 +0200352 gsms->protocol_id = *smsp++;
353 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000354
Harald Welte76042182009-08-08 16:03:15 +0200355 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000356
Harald Welte76042182009-08-08 16:03:15 +0200357 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000358 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200359 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000360 break;
361 case GSM340_TP_VPF_ABSOLUTE:
362 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200363 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000364 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000365 break;
366 default:
367 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200368 sms_vpf);
369 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000370 }
Harald Welte76042182009-08-08 16:03:15 +0200371 gsms->user_data_len = *smsp++;
372 if (gsms->user_data_len) {
373 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000374
Harald Welte76042182009-08-08 16:03:15 +0200375 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000376 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200377 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000378 break;
379 case DCS_8BIT_DATA:
380 case DCS_UCS2:
381 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000382 break;
383 }
384 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000385
Harald Welte7e310b12009-03-30 20:56:32 +0000386 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
387 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200388 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
389 gsms->protocol_id, gsms->data_coding_scheme,
390 gsms->dest_addr, gsms->user_data_len,
391 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
392 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000393
Harald Welte76042182009-08-08 16:03:15 +0200394 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000395
Harald Welte76042182009-08-08 16:03:15 +0200396 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200397
Harald Welte76042182009-08-08 16:03:15 +0200398 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200399
Harald Welte7e310b12009-03-30 20:56:32 +0000400 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200401 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000402 if (!gsms->receiver) {
403 rc = 1; /* cause 1: unknown subscriber */
404 goto out;
405 }
406
Harald Welte76042182009-08-08 16:03:15 +0200407 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000408 case GSM340_SMS_SUBMIT_MS2SC:
409 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200410 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000411 break;
412 case GSM340_SMS_COMMAND_MS2SC:
413 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200414 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200415 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000416 break;
417 default:
Harald Welte76042182009-08-08 16:03:15 +0200418 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200419 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000420 break;
421 }
422
Harald Welteb9c758b2009-07-05 14:02:46 +0200423 if (!rc && !gsms->receiver)
424 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
425
Harald Welte7e310b12009-03-30 20:56:32 +0000426out:
Harald Welte76042182009-08-08 16:03:15 +0200427 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000428
Harald Welte7e310b12009-03-30 20:56:32 +0000429 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000430}
431
Harald Weltef3efc592009-07-27 20:11:35 +0200432static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000433{
434 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000435
Daniel Willmann471712b2008-12-29 01:54:02 +0000436 DEBUGP(DSMS, "TX: SMS RP ACK\n");
437
Harald Weltef3efc592009-07-27 20:11:35 +0200438 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000439}
440
Harald Weltef3efc592009-07-27 20:11:35 +0200441static int gsm411_send_rp_error(struct gsm_trans *trans,
442 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000443{
444 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000445
Harald Welte7e310b12009-03-30 20:56:32 +0000446 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000447
Harald Welte7e310b12009-03-30 20:56:32 +0000448 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000449
Harald Weltef3efc592009-07-27 20:11:35 +0200450 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000451}
452
Harald Welte7e310b12009-03-30 20:56:32 +0000453/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200454static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
455 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000456 u_int8_t src_len, u_int8_t *src,
457 u_int8_t dst_len, u_int8_t *dst,
458 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000459{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000460 int rc = 0;
461
Harald Welte7e310b12009-03-30 20:56:32 +0000462 if (src_len && src)
463 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
464
465 if (!dst_len || !dst || !tpdu_len || !tpdu) {
466 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200467 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200468 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000469 return -EIO;
470 }
471 msg->smsh = tpdu;
472
473 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000474
475 rc = gsm340_rx_tpdu(msg);
476 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200477 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000478 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200479 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000480 else
481 return rc;
482}
483
484/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200485static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
486 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000487{
488 u_int8_t src_len, dst_len, rpud_len;
489 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
490
491 /* in the MO case, this should always be zero length */
492 src_len = rph->data[0];
493 if (src_len)
494 src = &rph->data[1];
495
496 dst_len = rph->data[1+src_len];
497 if (dst_len)
498 dst = &rph->data[1+src_len+1];
499
500 rpud_len = rph->data[1+src_len+1+dst_len];
501 if (rpud_len)
502 rp_ud = &rph->data[1+src_len+1+dst_len+1];
503
Harald Welteb9c758b2009-07-05 14:02:46 +0200504 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
505 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200506 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000507 rpud_len, rp_ud);
508}
509
Harald Weltecb8f4432009-08-09 14:59:02 +0200510/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200511static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
512 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200513{
Harald Welte76042182009-08-08 16:03:15 +0200514 struct gsm_sms *sms = trans->sms.sms;
515
Harald Welteb9c758b2009-07-05 14:02:46 +0200516 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
517 * successfully received a SMS. We can now safely mark it as
518 * transmitted */
519
Harald Weltecb8f4432009-08-09 14:59:02 +0200520 if (!trans->sms.is_mt) {
521 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
522 return gsm411_send_rp_error(trans, rph->msg_ref,
523 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
524 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200525
Harald Welte76042182009-08-08 16:03:15 +0200526 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200527 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
528 return gsm411_send_rp_error(trans, rph->msg_ref,
529 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200530 }
531
532 /* mark this SMS as sent in database */
533 db_sms_mark_sent(sms);
534
535 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
536
537 sms_free(sms);
538 trans->sms.sms = NULL;
539
Harald Weltecf6a3812009-08-09 19:07:41 +0200540 /* do not free the transaction here, this is done by sending CP-ACK */
541
542 /* check for more messages for this subscriber */
543 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
544 if (sms)
545 gsm411_send_sms_lchan(msg->lchan, sms);
546 else
547 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Welte76042182009-08-08 16:03:15 +0200548
549 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200550}
551
Harald Weltef3efc592009-07-27 20:11:35 +0200552static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
553 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200554{
Harald Welte76042182009-08-08 16:03:15 +0200555 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200556 u_int8_t cause_len = rph->data[0];
557 u_int8_t cause = rph->data[1];
558
Harald Welteb9c758b2009-07-05 14:02:46 +0200559 /* Error in response to MT RP_DATA, i.e. the MS did not
560 * successfully receive the SMS. We need to investigate
561 * the cause and take action depending on it */
562
Harald Weltef3efc592009-07-27 20:11:35 +0200563 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
564
Harald Weltecb8f4432009-08-09 14:59:02 +0200565 if (!trans->sms.is_mt) {
566 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
567 return gsm411_send_rp_error(trans, rph->msg_ref,
568 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
569 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200570
Harald Welte76042182009-08-08 16:03:15 +0200571 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200572 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
573 return gsm411_send_rp_error(trans, rph->msg_ref,
574 GSM411_RP_CAUSE_PROTOCOL_ERR);
575 }
576
577 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
578 /* MS has not enough memory to store the message. We need
579 * to store this in our database and wati for a SMMA message */
580 /* FIXME */
581 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200582 }
583
584 sms_free(sms);
585 trans->sms.sms = NULL;
586
Harald Weltecb8f4432009-08-09 14:59:02 +0200587 trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200588
Harald Weltef3efc592009-07-27 20:11:35 +0200589 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200590}
591
Harald Weltef3efc592009-07-27 20:11:35 +0200592static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
593 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200594{
Harald Weltecf6a3812009-08-09 19:07:41 +0200595 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200596 int rc;
597
Harald Weltecf6a3812009-08-09 19:07:41 +0200598 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
599 trans->sms.rp_state = GSM411_RPS_IDLE;
600
Harald Welteb9c758b2009-07-05 14:02:46 +0200601 /* MS tells us that it has memory for more SMS, we need
602 * to check if we have any pending messages for it and then
603 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200604 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200605
Harald Weltecf6a3812009-08-09 19:07:41 +0200606 /* check for more messages for this subscriber */
607 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
608 if (sms)
609 gsm411_send_sms_lchan(msg->lchan, sms);
610 else
611 rsl_release_request(msg->lchan, UM_SAPI_SMS);
Harald Weltef3efc592009-07-27 20:11:35 +0200612
613 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200614}
615
Harald Weltef3efc592009-07-27 20:11:35 +0200616static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
617 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000618{
Daniel Willmann471712b2008-12-29 01:54:02 +0000619 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000620 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000621 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000622
623 switch (msg_type) {
624 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200625 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
626 /* start TR2N and enter 'wait to send RP-ACK state' */
627 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
628 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000629 break;
630 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200631 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
632 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200633 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000634 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200635 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
636 /* start TR2N and enter 'wait to send RP-ACK state' */
637 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
638 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
639 break;
640 case GSM411_MT_RP_ERROR_MO:
641 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000642 break;
643 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000644 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200645 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
646 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000647 break;
648 }
649
650 return rc;
651}
652
Harald Weltef3efc592009-07-27 20:11:35 +0200653/* send CP-ACK to given transaction */
654static int gsm411_tx_cp_ack(struct gsm_trans *trans)
655{
656 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200657 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200658
Harald Weltecf6a3812009-08-09 19:07:41 +0200659 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
660
661 if (trans->sms.is_mt) {
662 /* If this is a MT SMS DELIVER, we can clear transaction here */
663 trans->sms.cp_state = GSM411_CPS_IDLE;
664 trans_free(trans);
665 }
Harald Weltef3efc592009-07-27 20:11:35 +0200666}
667
668static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
669{
670 struct msgb *msg = gsm411_msgb_alloc();
671 u_int8_t *causep;
672
Harald Welte76042182009-08-08 16:03:15 +0200673 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200674 *causep = cause;
675
676 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
677}
678
679/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000680int gsm0411_rcv_sms(struct msgb *msg)
681{
682 struct gsm48_hdr *gh = msgb_l3(msg);
683 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200684 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
685 struct gsm_lchan *lchan = msg->lchan;
686 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000687 int rc = 0;
688
Harald Weltef3efc592009-07-27 20:11:35 +0200689 if (!lchan->subscr)
690 return -EIO;
691 /* FIXME: send some error message */
692
693 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
694 transaction_id);
695 if (!trans) {
696 DEBUGP(DSMS, "Unknown transaction ID %x, "
697 "creating new trans\n", transaction_id);
698 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
699 transaction_id, new_callref++);
700 if (!trans) {
701 DEBUGP(DSMS, "No memory for trans\n");
702 /* FIXME: send some error message */
703 return -ENOMEM;
704 }
705 trans->sms.cp_state = GSM411_CPS_IDLE;
706 trans->sms.rp_state = GSM411_RPS_IDLE;
707 trans->sms.is_mt = 0;
708
709 trans->lchan = lchan;
710 use_lchan(lchan);
711 }
712
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000713 switch(msg_type) {
714 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200715 DEBUGP(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200716 /* 5.2.3.1.3: MO state exists when SMC has received
717 * CP-DATA, including sending of the assoc. CP-ACK */
718 /* 5.2.3.2.4: MT state exists when SMC has received
719 * CP-DATA, including sending of the assoc. CP-ACK */
720 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200721
722 rc = gsm411_rx_cp_data(msg, gh, trans);
723 /* Send CP-ACK or CP-ERORR in response */
724 if (rc < 0) {
725 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
726 } else
727 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000728 break;
729 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200730 /* previous CP-DATA in this transaction was confirmed */
731 DEBUGP(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200732 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
733 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
734 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
735
Harald Weltef3efc592009-07-27 20:11:35 +0200736 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200737 /* FIXME: we have sont one CP-DATA, which was now
738 * acknowledged. Check if we want to transfer more,
739 * i.e. multi-part message */
740 trans->sms.cp_state = GSM411_CPS_IDLE;
741 trans_free(trans);
742 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000743 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000744 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200745 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
746 trans->sms.cp_state = GSM411_CPS_IDLE;
747 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000748 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000749 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200750 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
751 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200752 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200753 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000754 break;
755 }
756
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000757 return rc;
758}
759
Harald Welte8c2e36e2008-12-30 15:00:14 +0000760#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000761/* Test TPDU - ALL YOUR */
762static u_int8_t tpdu_test[] = {
763 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
764 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
765 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
766 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000767};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000768#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000769
Harald Weltecf6a3812009-08-09 19:07:41 +0200770/* Take a SMS in gsm_sms structure and send it through an already
771 * existing lchan. We also assume that the caller ensured this lchan already
772 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200773int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000774{
775 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200776 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200777 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200778 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200779 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200780 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000781
Harald Weltecf6a3812009-08-09 19:07:41 +0200782 transaction_id = 4; /* FIXME: we always use 4 for now */
783
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000784 msg->lchan = lchan;
785
Harald Welte76042182009-08-08 16:03:15 +0200786 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200787
Harald Welte76042182009-08-08 16:03:15 +0200788 /* FIXME: allocate transaction with message reference */
789 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
790 transaction_id, new_callref++);
791 if (!trans) {
792 DEBUGP(DSMS, "No memory for trans\n");
793 /* FIXME: send some error message */
794 return -ENOMEM;
795 }
796 trans->sms.cp_state = GSM411_CPS_IDLE;
797 trans->sms.rp_state = GSM411_RPS_IDLE;
798 trans->sms.is_mt = 1;
799 trans->sms.sms = sms;
800
801 trans->lchan = lchan;
802 use_lchan(lchan);
803
804 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000805 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200806 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200807 data[1] = 0x91; /* type of number: international, ISDN */
808 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000809 data[3] = 0x77;
810 data[4] = 0x58;
811 data[5] = 0x10;
812 data[6] = 0x06;
813 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200814
815 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000816 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200817 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000818
Harald Welte76042182009-08-08 16:03:15 +0200819 /* obtain a pointer for the rp_ud_len, so we can fill it later */
820 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000821
Harald Welte76042182009-08-08 16:03:15 +0200822#if 1
823 /* generate the 03.40 TPDU */
824 rc = gsm340_gen_tpdu(msg, sms);
825 if (rc < 0) {
826 msgb_free(msg);
827 return rc;
828 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000829
Harald Welte76042182009-08-08 16:03:15 +0200830 *rp_ud_len = rc;
831#else
832 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000833 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200834 *rp_ud_len = sizeof(tpdu_test);
835#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000836
Harald Welte76042182009-08-08 16:03:15 +0200837 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000838
Harald Weltef3efc592009-07-27 20:11:35 +0200839 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
840 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000841}
Harald Weltef3efc592009-07-27 20:11:35 +0200842
Harald Weltecf6a3812009-08-09 19:07:41 +0200843/* RLL SAPI3 establish callback. Now we have a RLL connection and
844 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200845static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
846 void *_sms, enum bsc_rllr_ind type)
847{
848 struct gsm_sms *sms = _sms;
849
850 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
851 lchan, link_id, sms, type);
852
853 switch (type) {
854 case BSC_RLLR_IND_EST_CONF:
855 gsm411_send_sms_lchan(lchan, sms);
856 break;
857 case BSC_RLLR_IND_REL_IND:
858 case BSC_RLLR_IND_ERR_IND:
859 case BSC_RLLR_IND_TIMEOUT:
860 sms_free(sms);
861 break;
862 }
863}
864
Harald Weltecf6a3812009-08-09 19:07:41 +0200865/* paging callback. Here we get called if paging a subscriber has
866 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200867static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
868 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200869{
Harald Welte76042182009-08-08 16:03:15 +0200870 struct gsm_lchan *lchan = _lchan;
871 struct gsm_sms *sms = _sms;
872 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200873
Harald Welte76042182009-08-08 16:03:15 +0200874 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
875 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
876
877 if (hooknum != GSM_HOOK_RR_PAGING)
878 return -EINVAL;
879
880 switch (event) {
881 case GSM_PAGING_SUCCEEDED:
882 /* Paging aborted without lchan ?!? */
883 if (!lchan) {
884 sms_free(sms);
885 rc = -EIO;
886 break;
887 }
Harald Weltecf6a3812009-08-09 19:07:41 +0200888 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +0200889 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200890 break;
891 case GSM_PAGING_EXPIRED:
892 sms_free(sms);
893 rc = -ETIMEDOUT;
894 break;
895 default:
896 rc = -EINVAL;
897 break;
898 }
899
900 return rc;
901}
902
Harald Weltecf6a3812009-08-09 19:07:41 +0200903/* high-level function to send a SMS to a given subscriber. The function
904 * will take care of paging the subscriber, establishing the RLL SAPI3
905 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +0200906int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
907 struct gsm_sms *sms)
908{
Harald Weltecf6a3812009-08-09 19:07:41 +0200909 struct gsm_lchan *lchan;
910
Harald Welte76042182009-08-08 16:03:15 +0200911 /* check if we already have an open lchan to the subscriber.
912 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +0200913 lchan = lchan_for_subscr(subscr);
914 if (lchan)
915 return rll_establish(lchan, UM_SAPI_SMS,
916 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +0200917
918 /* if not, we have to start paging */
919 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
920 paging_cb_send_sms, sms);
921
922 return 0;
923}
Harald Welte3366a942009-07-28 00:44:49 +0200924
Harald Weltecf6a3812009-08-09 19:07:41 +0200925static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
926 void *handler_data, void *signal_data)
927{
928 struct gsm_subscriber *subscr;
929 struct gsm_lchan *lchan;
930 struct gsm_sms *sms;
931
932 switch (signal) {
933 case S_SUBSCR_ATTACHED:
934 /* A subscriber has attached. Check if there are
935 * any pending SMS for him to be delivered */
936 subscr = signal_data;
937 lchan = lchan_for_subscr(subscr);
938 if (!lchan)
939 break;
940 sms = db_sms_get_unsent_for_subscr(subscr);
941 if (!sms)
942 break;
943 /* Establish a SAPI3 RLL connection for SMS */
944 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
945 break;
946 default:
947 break;
948 }
949 return 0;
950}
951
Harald Welte7bfc2672009-07-28 00:41:45 +0200952static __attribute__((constructor)) void on_dso_load_sms(void)
953{
Harald Welte7bfc2672009-07-28 00:41:45 +0200954 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
Harald Weltecf6a3812009-08-09 19:07:41 +0200955
956 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +0200957}