blob: 6dac9d87c7b9e42e148c4b6590314a094c1be393 [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{
185 u_int8_t *smsp = msgb_sms(msg);
186 struct sms_submit *sms;
187 struct gsm_sms *gsms;
188 u_int8_t da_len_bytes;
189 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
190 int rc = 0;
191
Harald Weltea8379772009-06-20 22:36:41 +0200192 if (!tall_sms_ctx)
193 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1,
194 "sms_submit");
195
196 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte59b04682009-06-10 05:40:52 +0800197 if (!sms)
Harald Welte156c5e62009-07-05 14:02:46 +0200198 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800199 memset(sms, 0, sizeof(*sms));
200
Harald Weltea8379772009-06-20 22:36:41 +0200201 if (!tall_gsms_ctx)
202 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1,
203 "sms");
204
205 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte59b04682009-06-10 05:40:52 +0800206 if (!gsms) {
Harald Weltea8379772009-06-20 22:36:41 +0200207 talloc_free(sms);
Harald Welte156c5e62009-07-05 14:02:46 +0200208 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800209 }
210 memset(gsms, 0, sizeof(*gsms));
211
212 /* invert those fields where 0 means active/present */
213 sms->mti = *smsp & 0x03;
214 sms->mms = !!(*smsp & 0x04);
215 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welte156c5e62009-07-05 14:02:46 +0200216 sms->srr = !!(*smsp & 0x20);
Harald Welte59b04682009-06-10 05:40:52 +0800217 sms->udhi= !!(*smsp & 0x40);
218 sms->rp = !!(*smsp & 0x80);
219
220 smsp++;
221 sms->msg_ref = *smsp++;
222
223 /* length in bytes of the destination address */
224 da_len_bytes = 2 + *smsp/2 + *smsp%2;
225 if (da_len_bytes > 12) {
226 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200227 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800228 goto out;
229 }
Harald Welte3794e152009-06-12 02:42:11 +0800230 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800231 memcpy(address_lv, smsp, da_len_bytes);
232 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800233 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800234 /* convert to real number */
Harald Welte3794e152009-06-12 02:42:11 +0800235 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800236
237 smsp += da_len_bytes;
238
239 sms->pid = *smsp++;
240
241 sms->dcs = *smsp++;
242 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
243
244 switch (sms->vpf) {
245 case GSM340_TP_VPF_RELATIVE:
246 sms->vp = smsp++;
247 break;
248 case GSM340_TP_VPF_ABSOLUTE:
249 case GSM340_TP_VPF_ENHANCED:
250 sms->vp = smsp;
251 smsp += 7;
252 break;
253 default:
254 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
255 sms->vpf);
256 }
257 sms->ud_len = *smsp++;
258 if (sms->ud_len)
259 sms->user_data = smsp;
260 else
261 sms->user_data = NULL;
262
263 if (sms->ud_len) {
264 switch (sms->alphabet) {
265 case DCS_7BIT_DEFAULT:
266 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
267 break;
268 case DCS_8BIT_DATA:
269 case DCS_UCS2:
270 case DCS_NONE:
271 memcpy(sms->decoded, sms->user_data, sms->ud_len);
272 break;
273 }
274 }
275
276 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
277 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
278 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
279 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welte156c5e62009-07-05 14:02:46 +0200280 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
281 hexdump(sms->user_data, sms->ud_len));
Harald Welte59b04682009-06-10 05:40:52 +0800282
283 dispatch_signal(SS_SMS, 0, sms);
284
Harald Welte156c5e62009-07-05 14:02:46 +0200285 /* now we've filled the 'sms' structure. Go on filling
286 * the gsms structure based on information from the sms */
287
Harald Welte59b04682009-06-10 05:40:52 +0800288 gsms->sender = msg->lchan->subscr;
289 /* FIXME: sender refcount */
290
Harald Welte156c5e62009-07-05 14:02:46 +0200291 gsms->validity_minutes = gsm340_validity_period(sms);
292
Harald Welte59b04682009-06-10 05:40:52 +0800293 /* determine gsms->receiver based on dialled number */
294 gsms->receiver = subscr_get_by_extension(sms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800295 if (sms->user_data)
Harald Welte156c5e62009-07-05 14:02:46 +0200296 memcpy(gsms->header, sms->user_data, sms->ud_len);
297
298 if (sms->decoded)
Harald Welte59b04682009-06-10 05:40:52 +0800299 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
300
301 switch (sms->mti) {
302 case GSM340_SMS_SUBMIT_MS2SC:
303 /* MS is submitting a SMS */
304 rc = gsm340_rx_sms_submit(msg, sms, gsms);
305 break;
306 case GSM340_SMS_COMMAND_MS2SC:
307 case GSM340_SMS_DELIVER_REP_MS2SC:
308 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200309 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800310 break;
311 default:
312 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200313 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800314 break;
315 }
316
Harald Welte156c5e62009-07-05 14:02:46 +0200317 if (!rc && !gsms->receiver)
318 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
319
Harald Welte59b04682009-06-10 05:40:52 +0800320out:
Harald Weltea8379772009-06-20 22:36:41 +0200321 talloc_free(gsms);
322 talloc_free(sms);
Harald Welte59b04682009-06-10 05:40:52 +0800323
324 return rc;
325}
326
327static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
328 u_int8_t msg_ref)
329{
330 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800331
332 msg->lchan = lchan;
333
Harald Welte59b04682009-06-10 05:40:52 +0800334 DEBUGP(DSMS, "TX: SMS RP ACK\n");
335
Harald Welte7e2f57d2009-07-04 17:39:00 +0200336 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800337}
338
339static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
340 u_int8_t msg_ref, u_int8_t cause)
341{
342 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800343
344 msg->lchan = lchan;
345
Harald Welte59b04682009-06-10 05:40:52 +0800346 msgb_tv_put(msg, 1, cause);
347
348 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
349
Harald Welte7e2f57d2009-07-04 17:39:00 +0200350 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800351}
352
353/* Receive a 04.11 TPDU inside RP-DATA / user data */
354static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
355 u_int8_t src_len, u_int8_t *src,
356 u_int8_t dst_len, u_int8_t *dst,
357 u_int8_t tpdu_len, u_int8_t *tpdu)
358{
359 struct gsm48_hdr *gh = msgb_l3(msg);
360 u_int8_t trans_id = gh->proto_discr >> 4;
361 int rc = 0;
362
363 if (src_len && src)
364 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
365
366 if (!dst_len || !dst || !tpdu_len || !tpdu) {
367 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200368 gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
369 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800370 return -EIO;
371 }
372 msg->smsh = tpdu;
373
374 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800375
376 rc = gsm340_rx_tpdu(msg);
377 if (rc == 0)
378 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
379 else if (rc > 0)
380 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
381 else
382 return rc;
383}
384
385/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
386static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
387{
388 u_int8_t src_len, dst_len, rpud_len;
389 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
390
391 /* in the MO case, this should always be zero length */
392 src_len = rph->data[0];
393 if (src_len)
394 src = &rph->data[1];
395
396 dst_len = rph->data[1+src_len];
397 if (dst_len)
398 dst = &rph->data[1+src_len+1];
399
400 rpud_len = rph->data[1+src_len+1+dst_len];
401 if (rpud_len)
402 rp_ud = &rph->data[1+src_len+1+dst_len+1];
403
Harald Welte156c5e62009-07-05 14:02:46 +0200404 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
405 src_len, dst_len, rpud_len);
Harald Welte59b04682009-06-10 05:40:52 +0800406 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
407 rpud_len, rp_ud);
408}
409
Harald Welte156c5e62009-07-05 14:02:46 +0200410
411static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
412{
413 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
414 * successfully received a SMS. We can now safely mark it as
415 * transmitted */
416
Harald Weltedd62b162009-07-09 23:52:59 +0200417 /* we need to look-up the transaction based on rph->msg_ref to
418 * identify which particular RP_DATA/SMS-submit was ACKed */
419
Harald Welte156c5e62009-07-05 14:02:46 +0200420}
421
422static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
423{
424 /* Error in response to MT RP_DATA, i.e. the MS did not
425 * successfully receive the SMS. We need to investigate
426 * the cause and take action depending on it */
427
Harald Weltedd62b162009-07-09 23:52:59 +0200428 /* we need to look-up the transaction based on rph->msg_ref to
429 * identify which particular RP_DATA/SMS-submit failed */
430
Harald Welte156c5e62009-07-05 14:02:46 +0200431}
432
433static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
434{
435 /* MS tells us that it has memory for more SMS, we need
436 * to check if we have any pending messages for it and then
437 * transfer those */
438}
439
Harald Welte59b04682009-06-10 05:40:52 +0800440static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
441{
442 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
443 u_int8_t msg_type = rp_data->msg_type & 0x07;
444 int rc = 0;
445
446 switch (msg_type) {
447 case GSM411_MT_RP_DATA_MO:
448 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
449 rc = gsm411_rx_rp_data(msg, rp_data);
450 break;
451 case GSM411_MT_RP_ACK_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200452 rc = gsm411_rx_rp_ack(msg, rp_data);
453 break;
Harald Welte59b04682009-06-10 05:40:52 +0800454 case GSM411_MT_RP_ERROR_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200455 rc = gsm411_rx_rp_error(msg, rp_data);
456 break;
Harald Welte59b04682009-06-10 05:40:52 +0800457 case GSM411_MT_RP_SMMA_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200458 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800459 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
460 break;
461 default:
Harald Welte156c5e62009-07-05 14:02:46 +0200462 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte59b04682009-06-10 05:40:52 +0800463 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
464 break;
465 }
466
467 return rc;
468}
469
470int gsm0411_rcv_sms(struct msgb *msg)
471{
472 struct gsm48_hdr *gh = msgb_l3(msg);
473 u_int8_t msg_type = gh->msg_type;
474 int rc = 0;
475
476 switch(msg_type) {
477 case GSM411_MT_CP_DATA:
478 DEBUGP(DSMS, "SMS CP-DATA\n");
479 rc = gsm411_rx_cp_data(msg, gh);
480 break;
481 case GSM411_MT_CP_ACK:
482 DEBUGP(DSMS, "SMS CP-ACK\n");
483 break;
484 case GSM411_MT_CP_ERROR:
485 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
486 break;
487 default:
488 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
489 break;
490 }
491
492
493 return rc;
494}
495
496/* Test TPDU - 25c3 welcome */
497#if 0
498static u_int8_t tpdu_test[] = {
499 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
500 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
501 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
502 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
503 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
504 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
505 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
506};
507#else
508/* Test TPDU - ALL YOUR */
509static u_int8_t tpdu_test[] = {
510 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
511 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
512 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
513 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
514};
515#endif
516
517int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
518{
519 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800520 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200521 u_int8_t msg_ref = 42;
522 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800523
524 msg->lchan = lchan;
525
Harald Welte7e2f57d2009-07-04 17:39:00 +0200526 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800527 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200528 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200529 data[1] = 0x91; /* type of number: international, ISDN */
530 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800531 data[3] = 0x77;
532 data[4] = 0x58;
533 data[5] = 0x10;
534 data[6] = 0x06;
535 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200536
537 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800538 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200539 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800540
541 /* FIXME: Hardcoded for now */
542 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
543
544 /* RPDU length */
545 data = (u_int8_t *)msgb_put(msg, 1);
546 data[0] = sizeof(tpdu_test);
547
548 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
549
550 //memcpy(data, tpdu, smslen);
551 memcpy(data, tpdu_test, sizeof(tpdu_test));
552
553 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
554
Harald Welte7e2f57d2009-07-04 17:39:00 +0200555 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800556}