blob: ed39f792898fcce59178e98a602466df18c4825d [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 (!gsms->receiver) {
297 rc = 1; /* cause 1: unknown subscriber */
298 goto out;
299 }
300
301 if (sms->user_data)
Harald Welte156c5e62009-07-05 14:02:46 +0200302 memcpy(gsms->header, sms->user_data, sms->ud_len);
303
304 if (sms->decoded)
Harald Welte59b04682009-06-10 05:40:52 +0800305 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
306
307 switch (sms->mti) {
308 case GSM340_SMS_SUBMIT_MS2SC:
309 /* MS is submitting a SMS */
310 rc = gsm340_rx_sms_submit(msg, sms, gsms);
311 break;
312 case GSM340_SMS_COMMAND_MS2SC:
313 case GSM340_SMS_DELIVER_REP_MS2SC:
314 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200315 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800316 break;
317 default:
318 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200319 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800320 break;
321 }
322
Harald Welte156c5e62009-07-05 14:02:46 +0200323 if (!rc && !gsms->receiver)
324 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
325
Harald Welte59b04682009-06-10 05:40:52 +0800326out:
Harald Weltea8379772009-06-20 22:36:41 +0200327 talloc_free(gsms);
328 talloc_free(sms);
Harald Welte59b04682009-06-10 05:40:52 +0800329
330 return rc;
331}
332
333static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
334 u_int8_t msg_ref)
335{
336 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800337
338 msg->lchan = lchan;
339
Harald Welte59b04682009-06-10 05:40:52 +0800340 DEBUGP(DSMS, "TX: SMS RP ACK\n");
341
Harald Welte7e2f57d2009-07-04 17:39:00 +0200342 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800343}
344
345static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
346 u_int8_t msg_ref, u_int8_t cause)
347{
348 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800349
350 msg->lchan = lchan;
351
Harald Welte59b04682009-06-10 05:40:52 +0800352 msgb_tv_put(msg, 1, cause);
353
354 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
355
Harald Welte7e2f57d2009-07-04 17:39:00 +0200356 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800357}
358
359/* Receive a 04.11 TPDU inside RP-DATA / user data */
360static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
361 u_int8_t src_len, u_int8_t *src,
362 u_int8_t dst_len, u_int8_t *dst,
363 u_int8_t tpdu_len, u_int8_t *tpdu)
364{
365 struct gsm48_hdr *gh = msgb_l3(msg);
366 u_int8_t trans_id = gh->proto_discr >> 4;
367 int rc = 0;
368
369 if (src_len && src)
370 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
371
372 if (!dst_len || !dst || !tpdu_len || !tpdu) {
373 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200374 gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
375 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800376 return -EIO;
377 }
378 msg->smsh = tpdu;
379
380 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800381
382 rc = gsm340_rx_tpdu(msg);
383 if (rc == 0)
384 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
385 else if (rc > 0)
386 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
387 else
388 return rc;
389}
390
391/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
392static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
393{
394 u_int8_t src_len, dst_len, rpud_len;
395 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
396
397 /* in the MO case, this should always be zero length */
398 src_len = rph->data[0];
399 if (src_len)
400 src = &rph->data[1];
401
402 dst_len = rph->data[1+src_len];
403 if (dst_len)
404 dst = &rph->data[1+src_len+1];
405
406 rpud_len = rph->data[1+src_len+1+dst_len];
407 if (rpud_len)
408 rp_ud = &rph->data[1+src_len+1+dst_len+1];
409
Harald Welte156c5e62009-07-05 14:02:46 +0200410 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
411 src_len, dst_len, rpud_len);
Harald Welte59b04682009-06-10 05:40:52 +0800412 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
413 rpud_len, rp_ud);
414}
415
Harald Welte156c5e62009-07-05 14:02:46 +0200416
417static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
418{
419 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
420 * successfully received a SMS. We can now safely mark it as
421 * transmitted */
422
Harald Weltedd62b162009-07-09 23:52:59 +0200423 /* we need to look-up the transaction based on rph->msg_ref to
424 * identify which particular RP_DATA/SMS-submit was ACKed */
425
Harald Welte156c5e62009-07-05 14:02:46 +0200426}
427
428static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
429{
430 /* Error in response to MT RP_DATA, i.e. the MS did not
431 * successfully receive the SMS. We need to investigate
432 * the cause and take action depending on it */
433
Harald Weltedd62b162009-07-09 23:52:59 +0200434 /* we need to look-up the transaction based on rph->msg_ref to
435 * identify which particular RP_DATA/SMS-submit failed */
436
Harald Welte156c5e62009-07-05 14:02:46 +0200437}
438
439static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
440{
441 /* MS tells us that it has memory for more SMS, we need
442 * to check if we have any pending messages for it and then
443 * transfer those */
444}
445
Harald Welte59b04682009-06-10 05:40:52 +0800446static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
447{
448 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
449 u_int8_t msg_type = rp_data->msg_type & 0x07;
450 int rc = 0;
451
452 switch (msg_type) {
453 case GSM411_MT_RP_DATA_MO:
454 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
455 rc = gsm411_rx_rp_data(msg, rp_data);
456 break;
457 case GSM411_MT_RP_ACK_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200458 rc = gsm411_rx_rp_ack(msg, rp_data);
459 break;
Harald Welte59b04682009-06-10 05:40:52 +0800460 case GSM411_MT_RP_ERROR_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200461 rc = gsm411_rx_rp_error(msg, rp_data);
462 break;
Harald Welte59b04682009-06-10 05:40:52 +0800463 case GSM411_MT_RP_SMMA_MO:
Harald Welte156c5e62009-07-05 14:02:46 +0200464 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800465 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
466 break;
467 default:
Harald Welte156c5e62009-07-05 14:02:46 +0200468 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte59b04682009-06-10 05:40:52 +0800469 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
470 break;
471 }
472
473 return rc;
474}
475
476int gsm0411_rcv_sms(struct msgb *msg)
477{
478 struct gsm48_hdr *gh = msgb_l3(msg);
479 u_int8_t msg_type = gh->msg_type;
480 int rc = 0;
481
482 switch(msg_type) {
483 case GSM411_MT_CP_DATA:
484 DEBUGP(DSMS, "SMS CP-DATA\n");
485 rc = gsm411_rx_cp_data(msg, gh);
486 break;
487 case GSM411_MT_CP_ACK:
488 DEBUGP(DSMS, "SMS CP-ACK\n");
489 break;
490 case GSM411_MT_CP_ERROR:
491 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
492 break;
493 default:
494 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
495 break;
496 }
497
498
499 return rc;
500}
501
502/* Test TPDU - 25c3 welcome */
503#if 0
504static u_int8_t tpdu_test[] = {
505 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
506 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
507 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
508 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
509 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
510 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
511 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
512};
513#else
514/* Test TPDU - ALL YOUR */
515static u_int8_t tpdu_test[] = {
516 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
517 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
518 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
519 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
520};
521#endif
522
523int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
524{
525 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800526 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200527 u_int8_t msg_ref = 42;
528 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800529
530 msg->lchan = lchan;
531
Harald Welte7e2f57d2009-07-04 17:39:00 +0200532 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800533 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200534 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200535 data[1] = 0x91; /* type of number: international, ISDN */
536 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800537 data[3] = 0x77;
538 data[4] = 0x58;
539 data[5] = 0x10;
540 data[6] = 0x06;
541 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200542
543 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800544 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200545 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800546
547 /* FIXME: Hardcoded for now */
548 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
549
550 /* RPDU length */
551 data = (u_int8_t *)msgb_put(msg, 1);
552 data[0] = sizeof(tpdu_test);
553
554 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
555
556 //memcpy(data, tpdu, smslen);
557 memcpy(data, tpdu_test, sizeof(tpdu_test));
558
559 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
560
Harald Welte7e2f57d2009-07-04 17:39:00 +0200561 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Harald Welte59b04682009-06-10 05:40:52 +0800562}