blob: 527929120b0d373e5c75711d4d5e35b66211cf3e [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>
Harald Weltea8379772009-06-20 22:36:41 +020044#include <openbsc/talloc.h>
Harald Welte59b04682009-06-10 05:40:52 +080045
46#define GSM411_ALLOC_SIZE 1024
47#define GSM411_ALLOC_HEADROOM 128
48
Harald Weltea8379772009-06-20 22:36:41 +020049static void *tall_sms_ctx;
50static void *tall_gsms_ctx;
51
Harald Welte59b04682009-06-10 05:40:52 +080052struct msgb *gsm411_msgb_alloc(void)
53{
Harald Welte9cfc9352009-06-26 19:39:35 +020054 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
55 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +080056}
57
Harald Welte7e2f57d2009-07-04 17:39:00 +020058static int gsm411_sendmsg(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +080059{
60 if (msg->lchan)
61 msg->trx = msg->lchan->ts->trx;
62
63 msg->l3h = msg->data;
64
65 return rsl_data_request(msg, 0);
66}
67
Harald Welte7e2f57d2009-07-04 17:39:00 +020068/* Prefix msg with a 04.08/04.11 CP header */
69static int gsm411_cp_sendmsg(struct msgb *msg, u_int8_t msg_type,
70 u_int8_t trans_id)
71{
72 struct gsm48_hdr *gh;
73
74 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
75 /* Outgoing needs the highest bit set */
76 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
77 gh->msg_type = msg_type;
78
79 return gsm411_sendmsg(msg);
80}
81
82/* Prefix msg with a RP-DATA header and send as CP-DATA */
83static int gsm411_rp_sendmsg(struct msgb *msg, u_int8_t rp_msg_type,
84 u_int8_t rp_msg_ref, u_int8_t cp_trans_id)
85{
86 struct gsm411_rp_hdr *rp;
87
88 /* GSM 04.11 RP-DATA header */
89 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
90 rp->len = msg->len;
91 rp->msg_type = rp_msg_type;
92 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
93
94 return gsm411_cp_sendmsg(msg, GSM411_MT_CP_DATA, cp_trans_id);
95}
96
Harald Welte59b04682009-06-10 05:40:52 +080097
98#if 0
99static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
100{
101}
102#endif
103
104static unsigned long gsm340_validity_period(struct sms_submit *sms)
105{
106 u_int8_t vp;
107 unsigned long minutes;
108
109 switch (sms->vpf) {
110 case GSM340_TP_VPF_RELATIVE:
111 /* Chapter 9.2.3.12.1 */
112 vp = *(sms->vp);
113 if (vp <= 143)
114 minutes = vp + 1 * 5;
115 else if (vp <= 167)
116 minutes = 12*60 + (vp-143) * 30;
117 else if (vp <= 196)
118 minutes = vp-166 * 60 * 24;
119 else
120 minutes = vp-192 * 60 * 24 * 7;
121 break;
122 case GSM340_TP_VPF_ABSOLUTE:
123 /* Chapter 9.2.3.12.2 */
124 /* FIXME: like service center time stamp */
125 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
126 break;
127 case GSM340_TP_VPF_ENHANCED:
128 /* Chapter 9.2.3.12.3 */
129 /* FIXME: implementation */
130 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
131 break;
132 }
133 return minutes;
134}
135
136/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
137enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
138{
139 u_int8_t cgbits = dcs >> 4;
140 enum sms_alphabet alpha = DCS_NONE;
141
142 if ((cgbits & 0xc) == 0) {
143 if (cgbits & 2)
144 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
145
146 switch (dcs & 3) {
147 case 0:
148 alpha = DCS_7BIT_DEFAULT;
149 break;
150 case 1:
151 alpha = DCS_8BIT_DATA;
152 break;
153 case 2:
154 alpha = DCS_UCS2;
155 break;
156 }
157 } else if (cgbits == 0xc || cgbits == 0xd)
158 alpha = DCS_7BIT_DEFAULT;
159 else if (cgbits == 0xe)
160 alpha = DCS_UCS2;
161 else if (cgbits == 0xf) {
162 if (dcs & 4)
163 alpha = DCS_8BIT_DATA;
164 else
165 alpha = DCS_7BIT_DEFAULT;
166 }
167
168 return alpha;
169}
170
171static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
172 struct gsm_sms *gsms)
173{
174 if (db_sms_store(gsms) != 0) {
175 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200176 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800177 }
178 return 0;
179}
180
Harald Welte156c5e62009-07-05 14:02:46 +0200181/* process an incoming TPDU (called from RP-DATA)
182 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800183static int gsm340_rx_tpdu(struct msgb *msg)
184{
Harald Welte75350412009-07-23 18:46:00 +0200185 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800186 u_int8_t *smsp = msgb_sms(msg);
187 struct sms_submit *sms;
188 struct gsm_sms *gsms;
189 u_int8_t da_len_bytes;
190 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
191 int rc = 0;
192
Harald Weltea8379772009-06-20 22:36:41 +0200193 if (!tall_sms_ctx)
194 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1,
195 "sms_submit");
196
197 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte59b04682009-06-10 05:40:52 +0800198 if (!sms)
Harald Welte156c5e62009-07-05 14:02:46 +0200199 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800200 memset(sms, 0, sizeof(*sms));
201
Harald Weltea8379772009-06-20 22:36:41 +0200202 if (!tall_gsms_ctx)
203 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1,
204 "sms");
205
206 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte59b04682009-06-10 05:40:52 +0800207 if (!gsms) {
Harald Weltea8379772009-06-20 22:36:41 +0200208 talloc_free(sms);
Harald Welte156c5e62009-07-05 14:02:46 +0200209 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800210 }
211 memset(gsms, 0, sizeof(*gsms));
212
213 /* invert those fields where 0 means active/present */
214 sms->mti = *smsp & 0x03;
215 sms->mms = !!(*smsp & 0x04);
216 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welte156c5e62009-07-05 14:02:46 +0200217 sms->srr = !!(*smsp & 0x20);
Harald Welte59b04682009-06-10 05:40:52 +0800218 sms->udhi= !!(*smsp & 0x40);
219 sms->rp = !!(*smsp & 0x80);
220
221 smsp++;
222 sms->msg_ref = *smsp++;
223
224 /* length in bytes of the destination address */
225 da_len_bytes = 2 + *smsp/2 + *smsp%2;
226 if (da_len_bytes > 12) {
227 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200228 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800229 goto out;
230 }
Harald Welte3794e152009-06-12 02:42:11 +0800231 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800232 memcpy(address_lv, smsp, da_len_bytes);
233 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800234 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800235 /* convert to real number */
Harald Welte3794e152009-06-12 02:42:11 +0800236 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800237
238 smsp += da_len_bytes;
239
240 sms->pid = *smsp++;
241
242 sms->dcs = *smsp++;
243 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
244
245 switch (sms->vpf) {
246 case GSM340_TP_VPF_RELATIVE:
247 sms->vp = smsp++;
248 break;
249 case GSM340_TP_VPF_ABSOLUTE:
250 case GSM340_TP_VPF_ENHANCED:
251 sms->vp = smsp;
252 smsp += 7;
253 break;
254 default:
255 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
256 sms->vpf);
257 }
258 sms->ud_len = *smsp++;
259 if (sms->ud_len)
260 sms->user_data = smsp;
261 else
262 sms->user_data = NULL;
263
264 if (sms->ud_len) {
265 switch (sms->alphabet) {
266 case DCS_7BIT_DEFAULT:
267 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
268 break;
269 case DCS_8BIT_DATA:
270 case DCS_UCS2:
271 case DCS_NONE:
272 memcpy(sms->decoded, sms->user_data, sms->ud_len);
273 break;
274 }
275 }
276
277 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
278 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
279 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
280 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welte156c5e62009-07-05 14:02:46 +0200281 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
282 hexdump(sms->user_data, sms->ud_len));
Harald Welte59b04682009-06-10 05:40:52 +0800283
284 dispatch_signal(SS_SMS, 0, sms);
285
Harald Welte156c5e62009-07-05 14:02:46 +0200286 /* now we've filled the 'sms' structure. Go on filling
287 * the gsms structure based on information from the sms */
288
Harald Welte59b04682009-06-10 05:40:52 +0800289 gsms->sender = msg->lchan->subscr;
290 /* FIXME: sender refcount */
291
Harald Welte156c5e62009-07-05 14:02:46 +0200292 gsms->validity_minutes = gsm340_validity_period(sms);
293
Harald Welte59b04682009-06-10 05:40:52 +0800294 /* determine gsms->receiver based on dialled number */
Harald Welte75350412009-07-23 18:46:00 +0200295 gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800296 if (sms->user_data)
Harald Welte156c5e62009-07-05 14:02:46 +0200297 memcpy(gsms->header, sms->user_data, sms->ud_len);
298
299 if (sms->decoded)
Harald Welte59b04682009-06-10 05:40:52 +0800300 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
301
302 switch (sms->mti) {
303 case GSM340_SMS_SUBMIT_MS2SC:
304 /* MS is submitting a SMS */
305 rc = gsm340_rx_sms_submit(msg, sms, gsms);
306 break;
307 case GSM340_SMS_COMMAND_MS2SC:
308 case GSM340_SMS_DELIVER_REP_MS2SC:
309 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200310 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800311 break;
312 default:
313 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200314 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800315 break;
316 }
317
Harald Welte156c5e62009-07-05 14:02:46 +0200318 if (!rc && !gsms->receiver)
319 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
320
Harald Welte59b04682009-06-10 05:40:52 +0800321out:
Harald Weltea8379772009-06-20 22:36:41 +0200322 talloc_free(gsms);
323 talloc_free(sms);
Harald Welte59b04682009-06-10 05:40:52 +0800324
325 return rc;
326}
327
328static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
329 u_int8_t msg_ref)
330{
331 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800332
333 msg->lchan = lchan;
334
Harald Welte59b04682009-06-10 05:40:52 +0800335 DEBUGP(DSMS, "TX: SMS RP ACK\n");
336
Harald Welte7e2f57d2009-07-04 17:39:00 +0200337 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800338}
339
340static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
341 u_int8_t msg_ref, u_int8_t cause)
342{
343 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800344
345 msg->lchan = lchan;
346
Harald Welte59b04682009-06-10 05:40:52 +0800347 msgb_tv_put(msg, 1, cause);
348
349 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
350
Harald Welte7e2f57d2009-07-04 17:39:00 +0200351 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800352}
353
354/* Receive a 04.11 TPDU inside RP-DATA / user data */
355static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
356 u_int8_t src_len, u_int8_t *src,
357 u_int8_t dst_len, u_int8_t *dst,
358 u_int8_t tpdu_len, u_int8_t *tpdu)
359{
360 struct gsm48_hdr *gh = msgb_l3(msg);
361 u_int8_t trans_id = gh->proto_discr >> 4;
362 int rc = 0;
363
364 if (src_len && src)
365 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
366
367 if (!dst_len || !dst || !tpdu_len || !tpdu) {
368 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200369 gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
370 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800371 return -EIO;
372 }
373 msg->smsh = tpdu;
374
375 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800376
377 rc = gsm340_rx_tpdu(msg);
378 if (rc == 0)
379 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
380 else if (rc > 0)
381 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
382 else
383 return rc;
384}
385
386/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
387static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
388{
389 u_int8_t src_len, dst_len, rpud_len;
390 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
391
392 /* in the MO case, this should always be zero length */
393 src_len = rph->data[0];
394 if (src_len)
395 src = &rph->data[1];
396
397 dst_len = rph->data[1+src_len];
398 if (dst_len)
399 dst = &rph->data[1+src_len+1];
400
401 rpud_len = rph->data[1+src_len+1+dst_len];
402 if (rpud_len)
403 rp_ud = &rph->data[1+src_len+1+dst_len+1];
404
Harald Welte156c5e62009-07-05 14:02:46 +0200405 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
406 src_len, dst_len, rpud_len);
Harald Welte59b04682009-06-10 05:40:52 +0800407 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
408 rpud_len, rp_ud);
409}
410
Harald Welte156c5e62009-07-05 14:02:46 +0200411
412static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
413{
414 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
415 * successfully received a SMS. We can now safely mark it as
416 * transmitted */
417
Harald Weltedd62b162009-07-09 23:52:59 +0200418 /* we need to look-up the transaction based on rph->msg_ref to
419 * identify which particular RP_DATA/SMS-submit was ACKed */
420
Harald Welte156c5e62009-07-05 14:02:46 +0200421}
422
423static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
424{
425 /* Error in response to MT RP_DATA, i.e. the MS did not
426 * successfully receive the SMS. We need to investigate
427 * the cause and take action depending on it */
428
Harald Weltedd62b162009-07-09 23:52:59 +0200429 /* we need to look-up the transaction based on rph->msg_ref to
430 * identify which particular RP_DATA/SMS-submit failed */
431
Harald Welte156c5e62009-07-05 14:02:46 +0200432}
433
434static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
435{
436 /* MS tells us that it has memory for more SMS, we need
437 * to check if we have any pending messages for it and then
438 * transfer those */
439}
440
Harald Welte59b04682009-06-10 05:40:52 +0800441static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
442{
443 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
444 u_int8_t msg_type = rp_data->msg_type & 0x07;
445 int rc = 0;
446
447 switch (msg_type) {
448 case GSM411_MT_RP_DATA_MO:
449 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
450 rc = gsm411_rx_rp_data(msg, rp_data);
451 break;
452 case GSM411_MT_RP_ACK_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200453 rc = gsm411_rx_rp_ack(msg, rp_data);
454 break;
Harald Welte59b04682009-06-10 05:40:52 +0800455 case GSM411_MT_RP_ERROR_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200456 rc = gsm411_rx_rp_error(msg, rp_data);
457 break;
Harald Welte59b04682009-06-10 05:40:52 +0800458 case GSM411_MT_RP_SMMA_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200459 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800460 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
461 break;
462 default:
Harald Welte156c5e62009-07-05 14:02:46 +0200463 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte59b04682009-06-10 05:40:52 +0800464 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
465 break;
466 }
467
468 return rc;
469}
470
471int gsm0411_rcv_sms(struct msgb *msg)
472{
473 struct gsm48_hdr *gh = msgb_l3(msg);
474 u_int8_t msg_type = gh->msg_type;
475 int rc = 0;
476
477 switch(msg_type) {
478 case GSM411_MT_CP_DATA:
479 DEBUGP(DSMS, "SMS CP-DATA\n");
480 rc = gsm411_rx_cp_data(msg, gh);
481 break;
482 case GSM411_MT_CP_ACK:
483 DEBUGP(DSMS, "SMS CP-ACK\n");
484 break;
485 case GSM411_MT_CP_ERROR:
486 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
487 break;
488 default:
489 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
490 break;
491 }
492
493
494 return rc;
495}
496
497/* Test TPDU - 25c3 welcome */
498#if 0
499static u_int8_t tpdu_test[] = {
500 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
501 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
502 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
503 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
504 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
505 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
506 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
507};
508#else
509/* Test TPDU - ALL YOUR */
510static u_int8_t tpdu_test[] = {
511 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
512 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
513 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
514 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
515};
516#endif
517
518int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
519{
520 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800521 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200522 u_int8_t msg_ref = 42;
523 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800524
525 msg->lchan = lchan;
526
Harald Welte7e2f57d2009-07-04 17:39:00 +0200527 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800528 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200529 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200530 data[1] = 0x91; /* type of number: international, ISDN */
531 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800532 data[3] = 0x77;
533 data[4] = 0x58;
534 data[5] = 0x10;
535 data[6] = 0x06;
536 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200537
538 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800539 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200540 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800541
542 /* FIXME: Hardcoded for now */
543 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
544
545 /* RPDU length */
546 data = (u_int8_t *)msgb_put(msg, 1);
547 data[0] = sizeof(tpdu_test);
548
549 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
550
551 //memcpy(data, tpdu, smslen);
552 memcpy(data, tpdu_test, sizeof(tpdu_test));
553
554 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
555
Harald Welte7e2f57d2009-07-04 17:39:00 +0200556 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800557}