blob: c29953806fc6b9b1679f03041fca8fbbe553a710 [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 }
189 memcpy(address_lv, smsp, da_len_bytes);
190 /* mangle first byte to reflect length in bytes, not digits */
191 address_lv[0] = da_len_bytes;
192 /* convert to real number */
193 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv);
194
195 smsp += da_len_bytes;
196
197 sms->pid = *smsp++;
198
199 sms->dcs = *smsp++;
200 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
201
202 switch (sms->vpf) {
203 case GSM340_TP_VPF_RELATIVE:
204 sms->vp = smsp++;
205 break;
206 case GSM340_TP_VPF_ABSOLUTE:
207 case GSM340_TP_VPF_ENHANCED:
208 sms->vp = smsp;
209 smsp += 7;
210 break;
211 default:
212 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
213 sms->vpf);
214 }
215 sms->ud_len = *smsp++;
216 if (sms->ud_len)
217 sms->user_data = smsp;
218 else
219 sms->user_data = NULL;
220
221 if (sms->ud_len) {
222 switch (sms->alphabet) {
223 case DCS_7BIT_DEFAULT:
224 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
225 break;
226 case DCS_8BIT_DATA:
227 case DCS_UCS2:
228 case DCS_NONE:
229 memcpy(sms->decoded, sms->user_data, sms->ud_len);
230 break;
231 }
232 }
233
234 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
235 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
236 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
237 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
238 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded : hexdump(sms->user_data, sms->ud_len));
239
240 dispatch_signal(SS_SMS, 0, sms);
241
242 gsms->sender = msg->lchan->subscr;
243 /* FIXME: sender refcount */
244
245 /* determine gsms->receiver based on dialled number */
246 gsms->receiver = subscr_get_by_extension(sms->dest_addr);
247 if (!gsms->receiver) {
248 rc = 1; /* cause 1: unknown subscriber */
249 goto out;
250 }
251
252 if (sms->user_data)
253 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
254
255 switch (sms->mti) {
256 case GSM340_SMS_SUBMIT_MS2SC:
257 /* MS is submitting a SMS */
258 rc = gsm340_rx_sms_submit(msg, sms, gsms);
259 break;
260 case GSM340_SMS_COMMAND_MS2SC:
261 case GSM340_SMS_DELIVER_REP_MS2SC:
262 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
263 break;
264 default:
265 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
266 break;
267 }
268
269out:
270 free(gsms);
271 free(sms);
272
273 return rc;
274}
275
276static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
277 u_int8_t msg_ref)
278{
279 struct msgb *msg = gsm411_msgb_alloc();
280 struct gsm48_hdr *gh;
281 struct gsm411_rp_hdr *rp;
282
283 msg->lchan = lchan;
284
285 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
286 // Outgoing needs the highest bit set
287 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
288 gh->msg_type = GSM411_MT_CP_DATA;
289
290 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
291 rp->len = 2;
292 rp->msg_type = GSM411_MT_RP_ACK_MT;
293 rp->msg_ref = msg_ref;
294
295 DEBUGP(DSMS, "TX: SMS RP ACK\n");
296
297 return gsm0411_sendmsg(msg);
298}
299
300static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
301 u_int8_t msg_ref, u_int8_t cause)
302{
303 struct msgb *msg = gsm411_msgb_alloc();
304 struct gsm48_hdr *gh;
305 struct gsm411_rp_hdr *rp;
306
307 msg->lchan = lchan;
308
309 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
310 // Outgoing needs the highest bit set
311 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
312 gh->msg_type = GSM411_MT_CP_DATA;
313
314 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
315 rp->msg_type = GSM411_MT_RP_ERROR_MT;
316 rp->msg_ref = msg_ref;
317 msgb_tv_put(msg, 1, cause);
318
319 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
320
321 return gsm0411_sendmsg(msg);
322}
323
324/* Receive a 04.11 TPDU inside RP-DATA / user data */
325static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
326 u_int8_t src_len, u_int8_t *src,
327 u_int8_t dst_len, u_int8_t *dst,
328 u_int8_t tpdu_len, u_int8_t *tpdu)
329{
330 struct gsm48_hdr *gh = msgb_l3(msg);
331 u_int8_t trans_id = gh->proto_discr >> 4;
332 int rc = 0;
333
334 if (src_len && src)
335 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
336
337 if (!dst_len || !dst || !tpdu_len || !tpdu) {
338 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
339 return -EIO;
340 }
341 msg->smsh = tpdu;
342
343 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
344 //return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
345
346 rc = gsm340_rx_tpdu(msg);
347 if (rc == 0)
348 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
349 else if (rc > 0)
350 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
351 else
352 return rc;
353}
354
355/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
356static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
357{
358 u_int8_t src_len, dst_len, rpud_len;
359 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
360
361 /* in the MO case, this should always be zero length */
362 src_len = rph->data[0];
363 if (src_len)
364 src = &rph->data[1];
365
366 dst_len = rph->data[1+src_len];
367 if (dst_len)
368 dst = &rph->data[1+src_len+1];
369
370 rpud_len = rph->data[1+src_len+1+dst_len];
371 if (rpud_len)
372 rp_ud = &rph->data[1+src_len+1+dst_len+1];
373
374 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n", src_len, dst_len, rpud_len);
375 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
376 rpud_len, rp_ud);
377}
378
379static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
380{
381 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
382 u_int8_t msg_type = rp_data->msg_type & 0x07;
383 int rc = 0;
384
385 switch (msg_type) {
386 case GSM411_MT_RP_DATA_MO:
387 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
388 rc = gsm411_rx_rp_data(msg, rp_data);
389 break;
390 case GSM411_MT_RP_ACK_MO:
391 /* Acnkowledgement to MT RP_DATA */
392 case GSM411_MT_RP_ERROR_MO:
393 /* Error in response to MT RP_DATA */
394 case GSM411_MT_RP_SMMA_MO:
395 /* MS tells us that it has memory for more SMS, we need
396 * to check if we have any pending messages for it and then
397 * transfer those */
398 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
399 break;
400 default:
401 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
402 break;
403 }
404
405 return rc;
406}
407
408int gsm0411_rcv_sms(struct msgb *msg)
409{
410 struct gsm48_hdr *gh = msgb_l3(msg);
411 u_int8_t msg_type = gh->msg_type;
412 int rc = 0;
413
414 switch(msg_type) {
415 case GSM411_MT_CP_DATA:
416 DEBUGP(DSMS, "SMS CP-DATA\n");
417 rc = gsm411_rx_cp_data(msg, gh);
418 break;
419 case GSM411_MT_CP_ACK:
420 DEBUGP(DSMS, "SMS CP-ACK\n");
421 break;
422 case GSM411_MT_CP_ERROR:
423 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
424 break;
425 default:
426 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
427 break;
428 }
429
430
431 return rc;
432}
433
434/* Test TPDU - 25c3 welcome */
435#if 0
436static u_int8_t tpdu_test[] = {
437 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
438 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
439 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
440 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
441 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
442 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
443 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
444};
445#else
446/* Test TPDU - ALL YOUR */
447static u_int8_t tpdu_test[] = {
448 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
449 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
450 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
451 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
452};
453#endif
454
455int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
456{
457 struct msgb *msg = gsm411_msgb_alloc();
458 struct gsm48_hdr *gh;
459 struct gsm411_rp_hdr *rp;
460 u_int8_t *data;
461
462 msg->lchan = lchan;
463
464 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
465 gh->proto_discr = GSM48_PDISC_SMS;
466 gh->msg_type = GSM411_MT_CP_DATA;
467
468 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
469 rp->len = sizeof(tpdu_test) + 10;
470 rp->msg_type = GSM411_MT_RP_DATA_MT;
471 rp->msg_ref = 42; /* FIXME: Choose randomly */
472 /* Hardcode OA for now */
473 data = (u_int8_t *)msgb_put(msg, 8);
474 data[0] = 0x07;
475 data[1] = 0x91;
476 data[2] = 0x44;
477 data[3] = 0x77;
478 data[4] = 0x58;
479 data[5] = 0x10;
480 data[6] = 0x06;
481 data[7] = 0x50;
482 data = (u_int8_t *)msgb_put(msg, 1);
483 data[0] = 0;
484
485 /* FIXME: Hardcoded for now */
486 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
487
488 /* RPDU length */
489 data = (u_int8_t *)msgb_put(msg, 1);
490 data[0] = sizeof(tpdu_test);
491
492 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
493
494 //memcpy(data, tpdu, smslen);
495 memcpy(data, tpdu_test, sizeof(tpdu_test));
496
497 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
498
499 return gsm0411_sendmsg(msg);
500}