blob: 68ccec64ca9ecfc727c194a4e9218fcbb69ceabd [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
417}
418
419static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
420{
421 /* Error in response to MT RP_DATA, i.e. the MS did not
422 * successfully receive the SMS. We need to investigate
423 * the cause and take action depending on it */
424
425}
426
427static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
428{
429 /* MS tells us that it has memory for more SMS, we need
430 * to check if we have any pending messages for it and then
431 * transfer those */
432}
433
Harald Welte59b04682009-06-10 05:40:52 +0800434static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
435{
436 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
437 u_int8_t msg_type = rp_data->msg_type & 0x07;
438 int rc = 0;
439
440 switch (msg_type) {
441 case GSM411_MT_RP_DATA_MO:
442 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
443 rc = gsm411_rx_rp_data(msg, rp_data);
444 break;
445 case GSM411_MT_RP_ACK_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200446 rc = gsm411_rx_rp_ack(msg, rp_data);
447 break;
Harald Welte59b04682009-06-10 05:40:52 +0800448 case GSM411_MT_RP_ERROR_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200449 rc = gsm411_rx_rp_error(msg, rp_data);
450 break;
Harald Welte59b04682009-06-10 05:40:52 +0800451 case GSM411_MT_RP_SMMA_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200452 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800453 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
454 break;
455 default:
Harald Welte156c5e62009-07-05 14:02:46 +0200456 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte59b04682009-06-10 05:40:52 +0800457 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
458 break;
459 }
460
461 return rc;
462}
463
464int gsm0411_rcv_sms(struct msgb *msg)
465{
466 struct gsm48_hdr *gh = msgb_l3(msg);
467 u_int8_t msg_type = gh->msg_type;
468 int rc = 0;
469
470 switch(msg_type) {
471 case GSM411_MT_CP_DATA:
472 DEBUGP(DSMS, "SMS CP-DATA\n");
473 rc = gsm411_rx_cp_data(msg, gh);
474 break;
475 case GSM411_MT_CP_ACK:
476 DEBUGP(DSMS, "SMS CP-ACK\n");
477 break;
478 case GSM411_MT_CP_ERROR:
479 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
480 break;
481 default:
482 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
483 break;
484 }
485
486
487 return rc;
488}
489
490/* Test TPDU - 25c3 welcome */
491#if 0
492static u_int8_t tpdu_test[] = {
493 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
494 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
495 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
496 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
497 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
498 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
499 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
500};
501#else
502/* Test TPDU - ALL YOUR */
503static u_int8_t tpdu_test[] = {
504 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
505 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
506 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
507 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
508};
509#endif
510
511int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
512{
513 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800514 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200515 u_int8_t msg_ref = 42;
516 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800517
518 msg->lchan = lchan;
519
Harald Welte7e2f57d2009-07-04 17:39:00 +0200520 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800521 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200522 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200523 data[1] = 0x91; /* type of number: international, ISDN */
524 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800525 data[3] = 0x77;
526 data[4] = 0x58;
527 data[5] = 0x10;
528 data[6] = 0x06;
529 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200530
531 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800532 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200533 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800534
535 /* FIXME: Hardcoded for now */
536 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
537
538 /* RPDU length */
539 data = (u_int8_t *)msgb_put(msg, 1);
540 data[0] = sizeof(tpdu_test);
541
542 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
543
544 //memcpy(data, tpdu, smslen);
545 memcpy(data, tpdu_test, sizeof(tpdu_test));
546
547 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
548
Harald Welte7e2f57d2009-07-04 17:39:00 +0200549 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800550}