blob: 5ce25f3dced81656015bde7f87828b0e50790971 [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 Welte59b04682009-06-10 05:40:52 +080047
48#define GSM411_ALLOC_SIZE 1024
49#define GSM411_ALLOC_HEADROOM 128
50
Harald Weltea8379772009-06-20 22:36:41 +020051static void *tall_sms_ctx;
52static void *tall_gsms_ctx;
53
Harald Welteb78996d2009-07-27 20:11:35 +020054static u_int32_t new_callref = 0x40000001;
55
Harald Welte59b04682009-06-10 05:40:52 +080056struct msgb *gsm411_msgb_alloc(void)
57{
Harald Welte9cfc9352009-06-26 19:39:35 +020058 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
59 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +080060}
61
Harald Welte7e2f57d2009-07-04 17:39:00 +020062static int gsm411_sendmsg(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +080063{
64 if (msg->lchan)
65 msg->trx = msg->lchan->ts->trx;
66
67 msg->l3h = msg->data;
68
69 return rsl_data_request(msg, 0);
70}
71
Harald Welte7e2f57d2009-07-04 17:39:00 +020072/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +020073static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
74 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +020075{
76 struct gsm48_hdr *gh;
77
78 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
79 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +020080 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +020081 gh->msg_type = msg_type;
82
Harald Welteb78996d2009-07-27 20:11:35 +020083 /* assign the outgoing lchan */
84 msg->lchan = trans->lchan;
85
86 /* mobile originating */
87 switch (gh->msg_type) {
88 case GSM411_MT_CP_DATA:
89 /* 5.2.3.1.2: enter MO-wait for CP-ack */
90 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
91 break;
92 }
93
Harald Welte7e2f57d2009-07-04 17:39:00 +020094 return gsm411_sendmsg(msg);
95}
96
97/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +020098static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
99 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200100{
101 struct gsm411_rp_hdr *rp;
102
103 /* GSM 04.11 RP-DATA header */
104 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
105 rp->len = msg->len;
106 rp->msg_type = rp_msg_type;
107 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
108
Harald Welteb78996d2009-07-27 20:11:35 +0200109 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200110}
111
Harald Welte59b04682009-06-10 05:40:52 +0800112#if 0
113static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
114{
115}
116#endif
117
118static unsigned long gsm340_validity_period(struct sms_submit *sms)
119{
120 u_int8_t vp;
121 unsigned long minutes;
122
123 switch (sms->vpf) {
124 case GSM340_TP_VPF_RELATIVE:
125 /* Chapter 9.2.3.12.1 */
126 vp = *(sms->vp);
127 if (vp <= 143)
128 minutes = vp + 1 * 5;
129 else if (vp <= 167)
130 minutes = 12*60 + (vp-143) * 30;
131 else if (vp <= 196)
132 minutes = vp-166 * 60 * 24;
133 else
134 minutes = vp-192 * 60 * 24 * 7;
135 break;
136 case GSM340_TP_VPF_ABSOLUTE:
137 /* Chapter 9.2.3.12.2 */
138 /* FIXME: like service center time stamp */
139 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
140 break;
141 case GSM340_TP_VPF_ENHANCED:
142 /* Chapter 9.2.3.12.3 */
143 /* FIXME: implementation */
144 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
145 break;
146 }
147 return minutes;
148}
149
150/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
151enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
152{
153 u_int8_t cgbits = dcs >> 4;
154 enum sms_alphabet alpha = DCS_NONE;
155
156 if ((cgbits & 0xc) == 0) {
157 if (cgbits & 2)
158 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
159
160 switch (dcs & 3) {
161 case 0:
162 alpha = DCS_7BIT_DEFAULT;
163 break;
164 case 1:
165 alpha = DCS_8BIT_DATA;
166 break;
167 case 2:
168 alpha = DCS_UCS2;
169 break;
170 }
171 } else if (cgbits == 0xc || cgbits == 0xd)
172 alpha = DCS_7BIT_DEFAULT;
173 else if (cgbits == 0xe)
174 alpha = DCS_UCS2;
175 else if (cgbits == 0xf) {
176 if (dcs & 4)
177 alpha = DCS_8BIT_DATA;
178 else
179 alpha = DCS_7BIT_DEFAULT;
180 }
181
182 return alpha;
183}
184
185static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
186 struct gsm_sms *gsms)
187{
188 if (db_sms_store(gsms) != 0) {
189 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200190 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800191 }
192 return 0;
193}
194
Harald Welteb78996d2009-07-27 20:11:35 +0200195static int gsm340_gen_oa(u_int8_t *oa, struct gsm_subscriber *subscr)
196{
197 int len = 0;
198
199}
200
201static u_int8_t bcdify(u_int8_t value)
202{
203 u_int8_t ret;
204
205 ret = value % 10;
206 ret |= (value / 10) << 4;
207
208 return ret;
209}
210
211/* Generate 03.40 TP-SCTS */
212static void gsm340_gen_scts(u_int8_t *scts, time_t time)
213{
214 struct tm *tm = localtime(&time);
215 u_int8_t digit;
216
217 *scts++ = bcdify(tm->tm_year % 100);
218 *scts++ = bcdify(tm->tm_mon);
219 *scts++ = bcdify(tm->tm_mday);
220 *scts++ = bcdify(tm->tm_hour);
221 *scts++ = bcdify(tm->tm_min);
222 *scts++ = bcdify(tm->tm_sec);
223 *scts++ = 0; /* FIXME: timezone */
224}
225
226static struct msgb *gsm340_gen_tpdu(struct gsm_sms *sms)
227{
228 struct msgb *msg = gsm411_msgb_alloc();
229 u_int8_t *smsp;
230 u_int8_t oa[12]; /* max len per 03.40 */
231 u_int8_t oa_len = 0;
232
233 /* generate first octet with masked bits */
234 smsp = msgb_put(msg, 1);
235 *smsp = GSM340_SMS_DELIVER_SC2MS;
236 if (0 /* FIXME: MMS */)
237 *smsp |= 0x04;
238 /* two bits empty */
239 if (sms->status_rep_req)
240 *smsp |= 0x20;
241#if 0
242 if (sms->header_len)
243 *smsp |= 0x40;
244 if (sms->
245 *smsp |= 0x80;
246#endif
247
248 /* generate originator address */
249 smsp = msgb_put(msg, oa_len);
250 oa_len = gsm340_gen_oa(&oa, sms->sender);
251 memcpy(smsp, oa, oa_len);
252
253 /* generate TP-PID */
254 smsp = msgb_put(msg, 1);
255 *smsp = sms->protocol_id;
256
257 /* generate TP-DCS */
258 smsp = msgb_put(msg, 1);
259 *smsp = sms->data_coding_scheme;
260
261 /* generate TP-SCTS */
262 smsp = msgb_put(msg, 7);
263 gsm340_gen_scts(smsp, time(NULL));
264#if 0
265 /* generate TP-UDL */
266 smsp = msgb_put(msg, 1);
267 *smsp = ud_len;
268
269 /* generate TP-UD */
270 smsp = msgb_put(msg, ud_len);
271 memcpy(smsp, FIXME, ud_len);
272#endif
273
274 return msg;
275}
276
Harald Welte156c5e62009-07-05 14:02:46 +0200277/* process an incoming TPDU (called from RP-DATA)
278 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800279static int gsm340_rx_tpdu(struct msgb *msg)
280{
Harald Welte75350412009-07-23 18:46:00 +0200281 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800282 u_int8_t *smsp = msgb_sms(msg);
283 struct sms_submit *sms;
284 struct gsm_sms *gsms;
285 u_int8_t da_len_bytes;
286 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
287 int rc = 0;
288
Harald Weltea8379772009-06-20 22:36:41 +0200289 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte59b04682009-06-10 05:40:52 +0800290 if (!sms)
Harald Welte156c5e62009-07-05 14:02:46 +0200291 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800292 memset(sms, 0, sizeof(*sms));
293
Harald Weltea8379772009-06-20 22:36:41 +0200294 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte59b04682009-06-10 05:40:52 +0800295 if (!gsms) {
Harald Weltea8379772009-06-20 22:36:41 +0200296 talloc_free(sms);
Harald Welte156c5e62009-07-05 14:02:46 +0200297 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800298 }
299 memset(gsms, 0, sizeof(*gsms));
300
301 /* invert those fields where 0 means active/present */
302 sms->mti = *smsp & 0x03;
303 sms->mms = !!(*smsp & 0x04);
304 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welteb78996d2009-07-27 20:11:35 +0200305 sms->srr = (*smsp & 0x20);
306 sms->udhi= (*smsp & 0x40);
307 sms->rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800308
309 smsp++;
310 sms->msg_ref = *smsp++;
311
312 /* length in bytes of the destination address */
313 da_len_bytes = 2 + *smsp/2 + *smsp%2;
314 if (da_len_bytes > 12) {
315 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200316 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800317 goto out;
318 }
Harald Welte3794e152009-06-12 02:42:11 +0800319 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800320 memcpy(address_lv, smsp, da_len_bytes);
321 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800322 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800323 /* convert to real number */
Harald Welte3794e152009-06-12 02:42:11 +0800324 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800325
326 smsp += da_len_bytes;
327
328 sms->pid = *smsp++;
329
330 sms->dcs = *smsp++;
331 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
332
333 switch (sms->vpf) {
334 case GSM340_TP_VPF_RELATIVE:
335 sms->vp = smsp++;
336 break;
337 case GSM340_TP_VPF_ABSOLUTE:
338 case GSM340_TP_VPF_ENHANCED:
339 sms->vp = smsp;
340 smsp += 7;
341 break;
342 default:
343 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
344 sms->vpf);
345 }
346 sms->ud_len = *smsp++;
347 if (sms->ud_len)
348 sms->user_data = smsp;
349 else
350 sms->user_data = NULL;
351
352 if (sms->ud_len) {
353 switch (sms->alphabet) {
354 case DCS_7BIT_DEFAULT:
355 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
356 break;
357 case DCS_8BIT_DATA:
358 case DCS_UCS2:
359 case DCS_NONE:
360 memcpy(sms->decoded, sms->user_data, sms->ud_len);
361 break;
362 }
363 }
364
365 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
366 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
367 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
368 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welte156c5e62009-07-05 14:02:46 +0200369 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
370 hexdump(sms->user_data, sms->ud_len));
Harald Welte59b04682009-06-10 05:40:52 +0800371
372 dispatch_signal(SS_SMS, 0, sms);
373
Harald Welte156c5e62009-07-05 14:02:46 +0200374 /* now we've filled the 'sms' structure. Go on filling
375 * the gsms structure based on information from the sms */
376
Harald Welte59b04682009-06-10 05:40:52 +0800377 gsms->sender = msg->lchan->subscr;
378 /* FIXME: sender refcount */
379
Harald Welte156c5e62009-07-05 14:02:46 +0200380 gsms->validity_minutes = gsm340_validity_period(sms);
381
Harald Welte59b04682009-06-10 05:40:52 +0800382 /* determine gsms->receiver based on dialled number */
Harald Welte75350412009-07-23 18:46:00 +0200383 gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800384 if (!gsms->receiver) {
385 rc = 1; /* cause 1: unknown subscriber */
386 goto out;
387 }
388
Harald Welteb78996d2009-07-27 20:11:35 +0200389 if (sms->user_data) {
390 gsms->header_len = sms->ud_len;
Harald Welte156c5e62009-07-05 14:02:46 +0200391 memcpy(gsms->header, sms->user_data, sms->ud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200392 }
Harald Welte156c5e62009-07-05 14:02:46 +0200393
394 if (sms->decoded)
Harald Welte59b04682009-06-10 05:40:52 +0800395 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
396
397 switch (sms->mti) {
398 case GSM340_SMS_SUBMIT_MS2SC:
399 /* MS is submitting a SMS */
400 rc = gsm340_rx_sms_submit(msg, sms, gsms);
401 break;
402 case GSM340_SMS_COMMAND_MS2SC:
403 case GSM340_SMS_DELIVER_REP_MS2SC:
404 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200405 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800406 break;
407 default:
408 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200409 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800410 break;
411 }
412
Harald Welte156c5e62009-07-05 14:02:46 +0200413 if (!rc && !gsms->receiver)
414 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
415
Harald Welte59b04682009-06-10 05:40:52 +0800416out:
Harald Weltea8379772009-06-20 22:36:41 +0200417 talloc_free(gsms);
418 talloc_free(sms);
Harald Welte59b04682009-06-10 05:40:52 +0800419
420 return rc;
421}
422
Harald Welteb78996d2009-07-27 20:11:35 +0200423static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800424{
425 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800426
Harald Welte59b04682009-06-10 05:40:52 +0800427 DEBUGP(DSMS, "TX: SMS RP ACK\n");
428
Harald Welteb78996d2009-07-27 20:11:35 +0200429 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800430}
431
Harald Welteb78996d2009-07-27 20:11:35 +0200432static int gsm411_send_rp_error(struct gsm_trans *trans,
433 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800434{
435 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800436
Harald Welte59b04682009-06-10 05:40:52 +0800437 msgb_tv_put(msg, 1, cause);
438
439 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
440
Harald Welteb78996d2009-07-27 20:11:35 +0200441 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800442}
443
444/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200445static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
446 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800447 u_int8_t src_len, u_int8_t *src,
448 u_int8_t dst_len, u_int8_t *dst,
449 u_int8_t tpdu_len, u_int8_t *tpdu)
450{
451 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800452 int rc = 0;
453
454 if (src_len && src)
455 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
456
457 if (!dst_len || !dst || !tpdu_len || !tpdu) {
458 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200459 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200460 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800461 return -EIO;
462 }
463 msg->smsh = tpdu;
464
465 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800466
467 rc = gsm340_rx_tpdu(msg);
468 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200469 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800470 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200471 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800472 else
473 return rc;
474}
475
476/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200477static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
478 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800479{
480 u_int8_t src_len, dst_len, rpud_len;
481 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
482
483 /* in the MO case, this should always be zero length */
484 src_len = rph->data[0];
485 if (src_len)
486 src = &rph->data[1];
487
488 dst_len = rph->data[1+src_len];
489 if (dst_len)
490 dst = &rph->data[1+src_len+1];
491
492 rpud_len = rph->data[1+src_len+1+dst_len];
493 if (rpud_len)
494 rp_ud = &rph->data[1+src_len+1+dst_len+1];
495
Harald Welte156c5e62009-07-05 14:02:46 +0200496 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
497 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200498 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800499 rpud_len, rp_ud);
500}
501
Harald Welte156c5e62009-07-05 14:02:46 +0200502
Harald Welteb78996d2009-07-27 20:11:35 +0200503static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
504 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200505{
506 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
507 * successfully received a SMS. We can now safely mark it as
508 * transmitted */
509
Harald Weltedd62b162009-07-09 23:52:59 +0200510 /* we need to look-up the transaction based on rph->msg_ref to
511 * identify which particular RP_DATA/SMS-submit was ACKed */
512
Harald Welte156c5e62009-07-05 14:02:46 +0200513}
514
Harald Welteb78996d2009-07-27 20:11:35 +0200515static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
516 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200517{
Harald Welteb78996d2009-07-27 20:11:35 +0200518 u_int8_t cause_len = rph->data[0];
519 u_int8_t cause = rph->data[1];
520
Harald Welte156c5e62009-07-05 14:02:46 +0200521 /* Error in response to MT RP_DATA, i.e. the MS did not
522 * successfully receive the SMS. We need to investigate
523 * the cause and take action depending on it */
524
Harald Welteb78996d2009-07-27 20:11:35 +0200525 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
526
Harald Weltedd62b162009-07-09 23:52:59 +0200527 /* we need to look-up the transaction based on rph->msg_ref to
528 * identify which particular RP_DATA/SMS-submit failed */
529
Harald Welteb78996d2009-07-27 20:11:35 +0200530 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200531}
532
Harald Welteb78996d2009-07-27 20:11:35 +0200533static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
534 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200535{
Harald Welteb78996d2009-07-27 20:11:35 +0200536 int rc;
537
Harald Welte156c5e62009-07-05 14:02:46 +0200538 /* MS tells us that it has memory for more SMS, we need
539 * to check if we have any pending messages for it and then
540 * transfer those */
Harald Welteb78996d2009-07-27 20:11:35 +0200541
542 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
543 trans->sms.rp_state = GSM411_RPS_IDLE;
544
545 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200546}
547
Harald Welteb78996d2009-07-27 20:11:35 +0200548static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
549 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800550{
551 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
552 u_int8_t msg_type = rp_data->msg_type & 0x07;
553 int rc = 0;
554
555 switch (msg_type) {
556 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200557 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
558 /* start TR2N and enter 'wait to send RP-ACK state' */
559 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
560 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800561 break;
562 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200563 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
564 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200565 break;
Harald Welte59b04682009-06-10 05:40:52 +0800566 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200567 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
568 /* start TR2N and enter 'wait to send RP-ACK state' */
569 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
570 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
571 break;
572 case GSM411_MT_RP_ERROR_MO:
573 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800574 break;
575 default:
576 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200577 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
578 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800579 break;
580 }
581
582 return rc;
583}
584
Harald Welteb78996d2009-07-27 20:11:35 +0200585/* send CP-ACK to given transaction */
586static int gsm411_tx_cp_ack(struct gsm_trans *trans)
587{
588 struct msgb *msg = gsm411_msgb_alloc();
589
590 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
591}
592
593static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
594{
595 struct msgb *msg = gsm411_msgb_alloc();
596 u_int8_t *causep;
597
598 cause = msgb_put(msg, 1);
599 *causep = cause;
600
601 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
602}
603
604/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte59b04682009-06-10 05:40:52 +0800605int gsm0411_rcv_sms(struct msgb *msg)
606{
607 struct gsm48_hdr *gh = msgb_l3(msg);
608 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200609 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
610 struct gsm_lchan *lchan = msg->lchan;
611 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800612 int rc = 0;
613
Harald Welteb78996d2009-07-27 20:11:35 +0200614 if (!lchan->subscr)
615 return -EIO;
616 /* FIXME: send some error message */
617
618 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
619 transaction_id);
620 if (!trans) {
621 DEBUGP(DSMS, "Unknown transaction ID %x, "
622 "creating new trans\n", transaction_id);
623 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
624 transaction_id, new_callref++);
625 if (!trans) {
626 DEBUGP(DSMS, "No memory for trans\n");
627 /* FIXME: send some error message */
628 return -ENOMEM;
629 }
630 trans->sms.cp_state = GSM411_CPS_IDLE;
631 trans->sms.rp_state = GSM411_RPS_IDLE;
632 trans->sms.is_mt = 0;
633
634 trans->lchan = lchan;
635 use_lchan(lchan);
636 }
637
Harald Welte59b04682009-06-10 05:40:52 +0800638 switch(msg_type) {
639 case GSM411_MT_CP_DATA:
Harald Welteb78996d2009-07-27 20:11:35 +0200640 DEBUGP(DSMS, "RX SMS CP-DATA\n");
641 if (!trans->sms.is_mt) {
642 /* 5.2.3.1.3: MO state exists when SMC has received
643 * CP-DATA, including sending of the assoc. CP-ACK */
644 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
645 }
646
647 rc = gsm411_rx_cp_data(msg, gh, trans);
648 /* Send CP-ACK or CP-ERORR in response */
649 if (rc < 0) {
650 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
651 } else
652 rc = gsm411_tx_cp_ack(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800653 break;
654 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200655 /* previous CP-DATA in this transaction was confirmed */
656 DEBUGP(DSMS, "RX SMS CP-ACK\n");
657 if (!trans->sms.is_mt) {
658 /* 5.2.3.1.3: MO state exists when SMC has received
659 * CP-ACK */
660 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
661 /* FIXME: we have sont one CP-DATA, which was now
662 * acknowledged. Check if we want to transfer more,
663 * i.e. multi-part message */
664 trans->sms.cp_state = GSM411_CPS_IDLE;
665 trans_free(trans);
666 }
Harald Welte59b04682009-06-10 05:40:52 +0800667 break;
668 case GSM411_MT_CP_ERROR:
Harald Welteb78996d2009-07-27 20:11:35 +0200669 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
670 trans->sms.cp_state = GSM411_CPS_IDLE;
671 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800672 break;
673 default:
Harald Welteb78996d2009-07-27 20:11:35 +0200674 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
675 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
676 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800677 break;
678 }
679
Harald Welte59b04682009-06-10 05:40:52 +0800680 return rc;
681}
682
683/* Test TPDU - 25c3 welcome */
684#if 0
685static u_int8_t tpdu_test[] = {
686 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
687 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
688 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
689 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
690 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
691 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
692 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
693};
694#else
695/* Test TPDU - ALL YOUR */
696static u_int8_t tpdu_test[] = {
697 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
698 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
699 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
700 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
701};
702#endif
703
704int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
705{
706 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200707 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800708 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200709 u_int8_t msg_ref = 42;
710 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800711
712 msg->lchan = lchan;
713
Harald Welteb78996d2009-07-27 20:11:35 +0200714 /* FIXME: allocate trans */
715
Harald Welte7e2f57d2009-07-04 17:39:00 +0200716 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800717 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200718 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200719 data[1] = 0x91; /* type of number: international, ISDN */
720 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800721 data[3] = 0x77;
722 data[4] = 0x58;
723 data[5] = 0x10;
724 data[6] = 0x06;
725 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200726
727 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800728 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200729 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800730
731 /* FIXME: Hardcoded for now */
732 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
733
734 /* RPDU length */
735 data = (u_int8_t *)msgb_put(msg, 1);
736 data[0] = sizeof(tpdu_test);
737
738 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
739
740 //memcpy(data, tpdu, smslen);
741 memcpy(data, tpdu_test, sizeof(tpdu_test));
742
743 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
744
Harald Welteb78996d2009-07-27 20:11:35 +0200745 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
746 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800747}
Harald Welteb78996d2009-07-27 20:11:35 +0200748
749
750#if 0
751{
752 struct sms_deliver *smsd;
753
754 smsd->mti = GSM340_SMS_DELIVER_SC2MS;
755 smsd->mms = 0; /* FIXME: determine if there are more */
756 smsd->rp = FIXME;
757 smsd->udhi = FIXME;
758 smsd->sri = 1;
759 smsd->oa = FIXME;
760 smsd->pid = FIXME;
761 smsd->dcs = FIXME;
762 smsd->scts = FIXME;
763 smsd->ud_len = FIXME;
764 smsd->ud = FIXME;
765}
766#endif
Harald Welte5b359d82009-07-28 00:44:49 +0200767
Harald Welte932e20d2009-07-28 00:41:45 +0200768static __attribute__((constructor)) void on_dso_load_sms(void)
769{
770 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms_submit");
771 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
772}