blob: 3d5820d667be89184108c81dac82fcbb573a1a2f [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>
31#include <netinet/in.h>
32
33#include <openbsc/msgb.h>
34#include <openbsc/tlv.h>
35#include <openbsc/debug.h>
36#include <openbsc/gsm_data.h>
37#include <openbsc/gsm_subscriber.h>
38#include <openbsc/gsm_04_11.h>
39#include <openbsc/gsm_04_08.h>
40#include <openbsc/gsm_utils.h>
41#include <openbsc/abis_rsl.h>
42#include <openbsc/signal.h>
43#include <openbsc/db.h>
44
45#define GSM411_ALLOC_SIZE 1024
46#define GSM411_ALLOC_HEADROOM 128
47
48struct msgb *gsm411_msgb_alloc(void)
49{
50 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM);
51}
52
53int gsm0411_sendmsg(struct msgb *msg)
54{
55 if (msg->lchan)
56 msg->trx = msg->lchan->ts->trx;
57
58 msg->l3h = msg->data;
59
60 return rsl_data_request(msg, 0);
61}
62
63
64#if 0
65static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
66{
67}
68#endif
69
70static unsigned long gsm340_validity_period(struct sms_submit *sms)
71{
72 u_int8_t vp;
73 unsigned long minutes;
74
75 switch (sms->vpf) {
76 case GSM340_TP_VPF_RELATIVE:
77 /* Chapter 9.2.3.12.1 */
78 vp = *(sms->vp);
79 if (vp <= 143)
80 minutes = vp + 1 * 5;
81 else if (vp <= 167)
82 minutes = 12*60 + (vp-143) * 30;
83 else if (vp <= 196)
84 minutes = vp-166 * 60 * 24;
85 else
86 minutes = vp-192 * 60 * 24 * 7;
87 break;
88 case GSM340_TP_VPF_ABSOLUTE:
89 /* Chapter 9.2.3.12.2 */
90 /* FIXME: like service center time stamp */
91 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
92 break;
93 case GSM340_TP_VPF_ENHANCED:
94 /* Chapter 9.2.3.12.3 */
95 /* FIXME: implementation */
96 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
97 break;
98 }
99 return minutes;
100}
101
102/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
103enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
104{
105 u_int8_t cgbits = dcs >> 4;
106 enum sms_alphabet alpha = DCS_NONE;
107
108 if ((cgbits & 0xc) == 0) {
109 if (cgbits & 2)
110 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
111
112 switch (dcs & 3) {
113 case 0:
114 alpha = DCS_7BIT_DEFAULT;
115 break;
116 case 1:
117 alpha = DCS_8BIT_DATA;
118 break;
119 case 2:
120 alpha = DCS_UCS2;
121 break;
122 }
123 } else if (cgbits == 0xc || cgbits == 0xd)
124 alpha = DCS_7BIT_DEFAULT;
125 else if (cgbits == 0xe)
126 alpha = DCS_UCS2;
127 else if (cgbits == 0xf) {
128 if (dcs & 4)
129 alpha = DCS_8BIT_DATA;
130 else
131 alpha = DCS_7BIT_DEFAULT;
132 }
133
134 return alpha;
135}
136
137static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
138 struct gsm_sms *gsms)
139{
140 if (db_sms_store(gsms) != 0) {
141 DEBUGP(DSMS, "Failed to store SMS in Database\n");
142 free(sms);
143 free(gsms);
144 return -EIO;
145 }
146 return 0;
147}
148
149/* process an incoming TPDU (called from RP-DATA) */
150static int gsm340_rx_tpdu(struct msgb *msg)
151{
152 u_int8_t *smsp = msgb_sms(msg);
153 struct sms_submit *sms;
154 struct gsm_sms *gsms;
155 u_int8_t da_len_bytes;
156 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
157 int rc = 0;
158
159 sms = malloc(sizeof(*sms));
160 if (!sms)
161 return -ENOMEM;
162 memset(sms, 0, sizeof(*sms));
163
164 gsms = malloc(sizeof(*gsms));
165 if (!gsms) {
166 free(sms);
167 return -ENOMEM;
168 }
169 memset(gsms, 0, sizeof(*gsms));
170
171 /* invert those fields where 0 means active/present */
172 sms->mti = *smsp & 0x03;
173 sms->mms = !!(*smsp & 0x04);
174 sms->vpf = (*smsp & 0x18) >> 3;
175 sms->sri = !!(*smsp & 0x20);
176 sms->udhi= !!(*smsp & 0x40);
177 sms->rp = !!(*smsp & 0x80);
178
179 smsp++;
180 sms->msg_ref = *smsp++;
181
182 /* length in bytes of the destination address */
183 da_len_bytes = 2 + *smsp/2 + *smsp%2;
184 if (da_len_bytes > 12) {
185 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
186 rc = -EIO;
187 goto out;
188 }
Harald Welte3794e152009-06-12 02:42:11 +0800189 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800190 memcpy(address_lv, smsp, da_len_bytes);
191 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800192 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800193 /* convert to real number */
Harald Welte3794e152009-06-12 02:42:11 +0800194 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800195
196 smsp += da_len_bytes;
197
198 sms->pid = *smsp++;
199
200 sms->dcs = *smsp++;
201 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
202
203 switch (sms->vpf) {
204 case GSM340_TP_VPF_RELATIVE:
205 sms->vp = smsp++;
206 break;
207 case GSM340_TP_VPF_ABSOLUTE:
208 case GSM340_TP_VPF_ENHANCED:
209 sms->vp = smsp;
210 smsp += 7;
211 break;
212 default:
213 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
214 sms->vpf);
215 }
216 sms->ud_len = *smsp++;
217 if (sms->ud_len)
218 sms->user_data = smsp;
219 else
220 sms->user_data = NULL;
221
222 if (sms->ud_len) {
223 switch (sms->alphabet) {
224 case DCS_7BIT_DEFAULT:
225 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
226 break;
227 case DCS_8BIT_DATA:
228 case DCS_UCS2:
229 case DCS_NONE:
230 memcpy(sms->decoded, sms->user_data, sms->ud_len);
231 break;
232 }
233 }
234
235 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
236 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
237 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
238 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
239 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded : hexdump(sms->user_data, sms->ud_len));
240
241 dispatch_signal(SS_SMS, 0, sms);
242
243 gsms->sender = msg->lchan->subscr;
244 /* FIXME: sender refcount */
245
246 /* determine gsms->receiver based on dialled number */
247 gsms->receiver = subscr_get_by_extension(sms->dest_addr);
248 if (!gsms->receiver) {
249 rc = 1; /* cause 1: unknown subscriber */
250 goto out;
251 }
252
253 if (sms->user_data)
254 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
255
256 switch (sms->mti) {
257 case GSM340_SMS_SUBMIT_MS2SC:
258 /* MS is submitting a SMS */
259 rc = gsm340_rx_sms_submit(msg, sms, gsms);
260 break;
261 case GSM340_SMS_COMMAND_MS2SC:
262 case GSM340_SMS_DELIVER_REP_MS2SC:
263 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
264 break;
265 default:
266 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
267 break;
268 }
269
270out:
271 free(gsms);
272 free(sms);
273
274 return rc;
275}
276
277static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
278 u_int8_t msg_ref)
279{
280 struct msgb *msg = gsm411_msgb_alloc();
281 struct gsm48_hdr *gh;
282 struct gsm411_rp_hdr *rp;
283
284 msg->lchan = lchan;
285
286 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
287 // Outgoing needs the highest bit set
288 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
289 gh->msg_type = GSM411_MT_CP_DATA;
290
291 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
292 rp->len = 2;
293 rp->msg_type = GSM411_MT_RP_ACK_MT;
294 rp->msg_ref = msg_ref;
295
296 DEBUGP(DSMS, "TX: SMS RP ACK\n");
297
298 return gsm0411_sendmsg(msg);
299}
300
301static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
302 u_int8_t msg_ref, u_int8_t cause)
303{
304 struct msgb *msg = gsm411_msgb_alloc();
305 struct gsm48_hdr *gh;
306 struct gsm411_rp_hdr *rp;
307
308 msg->lchan = lchan;
309
310 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
311 // Outgoing needs the highest bit set
312 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
313 gh->msg_type = GSM411_MT_CP_DATA;
314
315 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
316 rp->msg_type = GSM411_MT_RP_ERROR_MT;
317 rp->msg_ref = msg_ref;
318 msgb_tv_put(msg, 1, cause);
319
320 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
321
322 return gsm0411_sendmsg(msg);
323}
324
325/* Receive a 04.11 TPDU inside RP-DATA / user data */
326static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
327 u_int8_t src_len, u_int8_t *src,
328 u_int8_t dst_len, u_int8_t *dst,
329 u_int8_t tpdu_len, u_int8_t *tpdu)
330{
331 struct gsm48_hdr *gh = msgb_l3(msg);
332 u_int8_t trans_id = gh->proto_discr >> 4;
333 int rc = 0;
334
335 if (src_len && src)
336 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
337
338 if (!dst_len || !dst || !tpdu_len || !tpdu) {
339 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
340 return -EIO;
341 }
342 msg->smsh = tpdu;
343
344 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
345 //return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
346
347 rc = gsm340_rx_tpdu(msg);
348 if (rc == 0)
349 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
350 else if (rc > 0)
351 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
352 else
353 return rc;
354}
355
356/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
357static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
358{
359 u_int8_t src_len, dst_len, rpud_len;
360 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
361
362 /* in the MO case, this should always be zero length */
363 src_len = rph->data[0];
364 if (src_len)
365 src = &rph->data[1];
366
367 dst_len = rph->data[1+src_len];
368 if (dst_len)
369 dst = &rph->data[1+src_len+1];
370
371 rpud_len = rph->data[1+src_len+1+dst_len];
372 if (rpud_len)
373 rp_ud = &rph->data[1+src_len+1+dst_len+1];
374
375 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n", src_len, dst_len, rpud_len);
376 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
377 rpud_len, rp_ud);
378}
379
380static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
381{
382 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
383 u_int8_t msg_type = rp_data->msg_type & 0x07;
384 int rc = 0;
385
386 switch (msg_type) {
387 case GSM411_MT_RP_DATA_MO:
388 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
389 rc = gsm411_rx_rp_data(msg, rp_data);
390 break;
391 case GSM411_MT_RP_ACK_MO:
392 /* Acnkowledgement to MT RP_DATA */
393 case GSM411_MT_RP_ERROR_MO:
394 /* Error in response to MT RP_DATA */
395 case GSM411_MT_RP_SMMA_MO:
396 /* MS tells us that it has memory for more SMS, we need
397 * to check if we have any pending messages for it and then
398 * transfer those */
399 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
400 break;
401 default:
402 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
403 break;
404 }
405
406 return rc;
407}
408
409int gsm0411_rcv_sms(struct msgb *msg)
410{
411 struct gsm48_hdr *gh = msgb_l3(msg);
412 u_int8_t msg_type = gh->msg_type;
413 int rc = 0;
414
415 switch(msg_type) {
416 case GSM411_MT_CP_DATA:
417 DEBUGP(DSMS, "SMS CP-DATA\n");
418 rc = gsm411_rx_cp_data(msg, gh);
419 break;
420 case GSM411_MT_CP_ACK:
421 DEBUGP(DSMS, "SMS CP-ACK\n");
422 break;
423 case GSM411_MT_CP_ERROR:
424 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
425 break;
426 default:
427 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
428 break;
429 }
430
431
432 return rc;
433}
434
435/* Test TPDU - 25c3 welcome */
436#if 0
437static u_int8_t tpdu_test[] = {
438 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
439 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
440 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
441 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
442 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
443 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
444 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
445};
446#else
447/* Test TPDU - ALL YOUR */
448static u_int8_t tpdu_test[] = {
449 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
450 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
451 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
452 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
453};
454#endif
455
456int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
457{
458 struct msgb *msg = gsm411_msgb_alloc();
459 struct gsm48_hdr *gh;
460 struct gsm411_rp_hdr *rp;
461 u_int8_t *data;
462
463 msg->lchan = lchan;
464
465 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
466 gh->proto_discr = GSM48_PDISC_SMS;
467 gh->msg_type = GSM411_MT_CP_DATA;
468
469 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
470 rp->len = sizeof(tpdu_test) + 10;
471 rp->msg_type = GSM411_MT_RP_DATA_MT;
472 rp->msg_ref = 42; /* FIXME: Choose randomly */
473 /* Hardcode OA for now */
474 data = (u_int8_t *)msgb_put(msg, 8);
475 data[0] = 0x07;
476 data[1] = 0x91;
477 data[2] = 0x44;
478 data[3] = 0x77;
479 data[4] = 0x58;
480 data[5] = 0x10;
481 data[6] = 0x06;
482 data[7] = 0x50;
483 data = (u_int8_t *)msgb_put(msg, 1);
484 data[0] = 0;
485
486 /* FIXME: Hardcoded for now */
487 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
488
489 /* RPDU length */
490 data = (u_int8_t *)msgb_put(msg, 1);
491 data[0] = sizeof(tpdu_test);
492
493 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
494
495 //memcpy(data, tpdu, smslen);
496 memcpy(data, tpdu_test, sizeof(tpdu_test));
497
498 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
499
500 return gsm0411_sendmsg(msg);
501}