blob: 571da4cba8eca5d72c8b9c30c4659a1d2241bd1d [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* 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>
Harald Welte7e310b12009-03-30 20:56:32 +00006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Daniel Willmann8b3390e2008-12-28 00:31:09 +00007 *
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>
Harald Welte7e310b12009-03-30 20:56:32 +000034#include <openbsc/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000035#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000036#include <openbsc/gsm_data.h>
37#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000038#include <openbsc/gsm_04_11.h>
39#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000040#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000041#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000042#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000043#include <openbsc/db.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020044#include <openbsc/talloc.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000045
Daniel Willmann471712b2008-12-29 01:54:02 +000046#define GSM411_ALLOC_SIZE 1024
47#define GSM411_ALLOC_HEADROOM 128
48
Harald Welte2cf161b2009-06-20 22:36:41 +020049static void *tall_sms_ctx;
50static void *tall_gsms_ctx;
51
Holger Freythera553d092009-01-04 20:16:25 +000052struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000053{
54 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM);
55}
56
Holger Freythera553d092009-01-04 20:16:25 +000057int gsm0411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000058{
59 if (msg->lchan)
60 msg->trx = msg->lchan->ts->trx;
61
62 msg->l3h = msg->data;
63
64 return rsl_data_request(msg, 0);
65}
66
Daniel Willmanne0fbec82008-12-29 00:44:41 +000067
Holger Freytherca362a62009-01-04 21:05:01 +000068#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000069static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
70{
Daniel Willmann6fe997e2008-12-29 04:20:41 +000071}
Holger Freytherca362a62009-01-04 21:05:01 +000072#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +000073
Harald Welte7e310b12009-03-30 20:56:32 +000074static unsigned long gsm340_validity_period(struct sms_submit *sms)
75{
76 u_int8_t vp;
77 unsigned long minutes;
78
79 switch (sms->vpf) {
80 case GSM340_TP_VPF_RELATIVE:
81 /* Chapter 9.2.3.12.1 */
82 vp = *(sms->vp);
83 if (vp <= 143)
84 minutes = vp + 1 * 5;
85 else if (vp <= 167)
86 minutes = 12*60 + (vp-143) * 30;
87 else if (vp <= 196)
88 minutes = vp-166 * 60 * 24;
89 else
90 minutes = vp-192 * 60 * 24 * 7;
91 break;
92 case GSM340_TP_VPF_ABSOLUTE:
93 /* Chapter 9.2.3.12.2 */
94 /* FIXME: like service center time stamp */
95 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
96 break;
97 case GSM340_TP_VPF_ENHANCED:
98 /* Chapter 9.2.3.12.3 */
99 /* FIXME: implementation */
100 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
101 break;
102 }
103 return minutes;
104}
105
106/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
107enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
108{
109 u_int8_t cgbits = dcs >> 4;
110 enum sms_alphabet alpha = DCS_NONE;
111
112 if ((cgbits & 0xc) == 0) {
113 if (cgbits & 2)
114 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
115
116 switch (dcs & 3) {
117 case 0:
118 alpha = DCS_7BIT_DEFAULT;
119 break;
120 case 1:
121 alpha = DCS_8BIT_DATA;
122 break;
123 case 2:
124 alpha = DCS_UCS2;
125 break;
126 }
127 } else if (cgbits == 0xc || cgbits == 0xd)
128 alpha = DCS_7BIT_DEFAULT;
129 else if (cgbits == 0xe)
130 alpha = DCS_UCS2;
131 else if (cgbits == 0xf) {
132 if (dcs & 4)
133 alpha = DCS_8BIT_DATA;
134 else
135 alpha = DCS_7BIT_DEFAULT;
136 }
137
138 return alpha;
139}
140
141static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
142 struct gsm_sms *gsms)
143{
144 if (db_sms_store(gsms) != 0) {
145 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte2cf161b2009-06-20 22:36:41 +0200146 talloc_free(sms);
147 talloc_free(gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000148 return -EIO;
149 }
150 return 0;
151}
152
153/* process an incoming TPDU (called from RP-DATA) */
154static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000155{
156 u_int8_t *smsp = msgb_sms(msg);
157 struct sms_submit *sms;
Harald Welte7e310b12009-03-30 20:56:32 +0000158 struct gsm_sms *gsms;
159 u_int8_t da_len_bytes;
160 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
161 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000162
Harald Welte2cf161b2009-06-20 22:36:41 +0200163 if (!tall_sms_ctx)
164 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1,
165 "sms_submit");
166
167 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte7e310b12009-03-30 20:56:32 +0000168 if (!sms)
169 return -ENOMEM;
170 memset(sms, 0, sizeof(*sms));
171
Harald Welte2cf161b2009-06-20 22:36:41 +0200172 if (!tall_gsms_ctx)
173 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1,
174 "sms");
175
176 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte7e310b12009-03-30 20:56:32 +0000177 if (!gsms) {
Harald Welte2cf161b2009-06-20 22:36:41 +0200178 talloc_free(sms);
Harald Welte7e310b12009-03-30 20:56:32 +0000179 return -ENOMEM;
180 }
181 memset(gsms, 0, sizeof(*gsms));
182
183 /* invert those fields where 0 means active/present */
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000184 sms->mti = *smsp & 0x03;
185 sms->mms = !!(*smsp & 0x04);
186 sms->vpf = (*smsp & 0x18) >> 3;
187 sms->sri = !!(*smsp & 0x20);
188 sms->udhi= !!(*smsp & 0x40);
189 sms->rp = !!(*smsp & 0x80);
190
191 smsp++;
192 sms->msg_ref = *smsp++;
193
Harald Welte7e310b12009-03-30 20:56:32 +0000194 /* length in bytes of the destination address */
195 da_len_bytes = 2 + *smsp/2 + *smsp%2;
196 if (da_len_bytes > 12) {
197 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
198 rc = -EIO;
199 goto out;
200 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800201 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000202 memcpy(address_lv, smsp, da_len_bytes);
203 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800204 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000205 /* convert to real number */
Harald Welte3cfdb222009-06-12 02:42:11 +0800206 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000207
208 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000209
210 sms->pid = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000211
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000212 sms->dcs = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000213 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
214
215 switch (sms->vpf) {
216 case GSM340_TP_VPF_RELATIVE:
217 sms->vp = smsp++;
218 break;
219 case GSM340_TP_VPF_ABSOLUTE:
220 case GSM340_TP_VPF_ENHANCED:
221 sms->vp = smsp;
222 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000223 break;
224 default:
225 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
226 sms->vpf);
227 }
228 sms->ud_len = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000229 if (sms->ud_len)
230 sms->user_data = smsp;
231 else
232 sms->user_data = NULL;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000233
Harald Welte7e310b12009-03-30 20:56:32 +0000234 if (sms->ud_len) {
235 switch (sms->alphabet) {
236 case DCS_7BIT_DEFAULT:
237 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
238 break;
239 case DCS_8BIT_DATA:
240 case DCS_UCS2:
241 case DCS_NONE:
242 memcpy(sms->decoded, sms->user_data, sms->ud_len);
243 break;
244 }
245 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000246
Harald Welte7e310b12009-03-30 20:56:32 +0000247 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
248 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000249 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
Harald Welte7e310b12009-03-30 20:56:32 +0000250 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
251 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded : hexdump(sms->user_data, sms->ud_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000252
Harald Welte595ad7b2009-02-16 22:05:44 +0000253 dispatch_signal(SS_SMS, 0, sms);
Holger Freyther9b177762009-02-16 19:07:18 +0000254
Harald Welte7e310b12009-03-30 20:56:32 +0000255 gsms->sender = msg->lchan->subscr;
256 /* FIXME: sender refcount */
257
258 /* determine gsms->receiver based on dialled number */
259 gsms->receiver = subscr_get_by_extension(sms->dest_addr);
260 if (!gsms->receiver) {
261 rc = 1; /* cause 1: unknown subscriber */
262 goto out;
263 }
264
265 if (sms->user_data)
266 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
267
268 switch (sms->mti) {
269 case GSM340_SMS_SUBMIT_MS2SC:
270 /* MS is submitting a SMS */
271 rc = gsm340_rx_sms_submit(msg, sms, gsms);
272 break;
273 case GSM340_SMS_COMMAND_MS2SC:
274 case GSM340_SMS_DELIVER_REP_MS2SC:
275 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
276 break;
277 default:
278 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
279 break;
280 }
281
282out:
Harald Welte2cf161b2009-06-20 22:36:41 +0200283 talloc_free(gsms);
284 talloc_free(sms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000285
Harald Welte7e310b12009-03-30 20:56:32 +0000286 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000287}
288
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000289static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
290 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000291{
292 struct msgb *msg = gsm411_msgb_alloc();
293 struct gsm48_hdr *gh;
294 struct gsm411_rp_hdr *rp;
295
296 msg->lchan = lchan;
297
298 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000299 // Outgoing needs the highest bit set
300 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
301 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000302
303 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000304 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000305 rp->msg_type = GSM411_MT_RP_ACK_MT;
306 rp->msg_ref = msg_ref;
307
308 DEBUGP(DSMS, "TX: SMS RP ACK\n");
309
310 return gsm0411_sendmsg(msg);
311}
312
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000313static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
Harald Welte7e310b12009-03-30 20:56:32 +0000314 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000315{
316 struct msgb *msg = gsm411_msgb_alloc();
317 struct gsm48_hdr *gh;
318 struct gsm411_rp_hdr *rp;
319
320 msg->lchan = lchan;
321
322 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000323 // Outgoing needs the highest bit set
324 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
325 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000326
327 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
328 rp->msg_type = GSM411_MT_RP_ERROR_MT;
329 rp->msg_ref = msg_ref;
Harald Welte7e310b12009-03-30 20:56:32 +0000330 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000331
Harald Welte7e310b12009-03-30 20:56:32 +0000332 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000333
334 return gsm0411_sendmsg(msg);
335}
336
Harald Welte7e310b12009-03-30 20:56:32 +0000337/* Receive a 04.11 TPDU inside RP-DATA / user data */
338static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
339 u_int8_t src_len, u_int8_t *src,
340 u_int8_t dst_len, u_int8_t *dst,
341 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000342{
343 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000344 u_int8_t trans_id = gh->proto_discr >> 4;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000345 int rc = 0;
346
Harald Welte7e310b12009-03-30 20:56:32 +0000347 if (src_len && src)
348 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
349
350 if (!dst_len || !dst || !tpdu_len || !tpdu) {
351 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
352 return -EIO;
353 }
354 msg->smsh = tpdu;
355
356 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
357 //return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
358
359 rc = gsm340_rx_tpdu(msg);
360 if (rc == 0)
361 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
362 else if (rc > 0)
363 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
364 else
365 return rc;
366}
367
368/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
369static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
370{
371 u_int8_t src_len, dst_len, rpud_len;
372 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
373
374 /* in the MO case, this should always be zero length */
375 src_len = rph->data[0];
376 if (src_len)
377 src = &rph->data[1];
378
379 dst_len = rph->data[1+src_len];
380 if (dst_len)
381 dst = &rph->data[1+src_len+1];
382
383 rpud_len = rph->data[1+src_len+1+dst_len];
384 if (rpud_len)
385 rp_ud = &rph->data[1+src_len+1+dst_len+1];
386
387 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n", src_len, dst_len, rpud_len);
388 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
389 rpud_len, rp_ud);
390}
391
392static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
393{
Daniel Willmann471712b2008-12-29 01:54:02 +0000394 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000395 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000396 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000397
398 switch (msg_type) {
399 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000400 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000401 rc = gsm411_rx_rp_data(msg, rp_data);
402 break;
403 case GSM411_MT_RP_ACK_MO:
404 /* Acnkowledgement to MT RP_DATA */
405 case GSM411_MT_RP_ERROR_MO:
406 /* Error in response to MT RP_DATA */
407 case GSM411_MT_RP_SMMA_MO:
408 /* MS tells us that it has memory for more SMS, we need
409 * to check if we have any pending messages for it and then
410 * transfer those */
411 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000412 break;
413 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000414 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000415 break;
416 }
417
418 return rc;
419}
420
421int gsm0411_rcv_sms(struct msgb *msg)
422{
423 struct gsm48_hdr *gh = msgb_l3(msg);
424 u_int8_t msg_type = gh->msg_type;
425 int rc = 0;
426
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000427 switch(msg_type) {
428 case GSM411_MT_CP_DATA:
429 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000430 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000431 break;
432 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000433 DEBUGP(DSMS, "SMS CP-ACK\n");
434 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000435 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000436 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
437 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000438 default:
439 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
440 break;
441 }
442
443
444 return rc;
445}
446
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000447/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000448#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000449static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000450 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
451 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
452 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
453 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
454 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
455 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
456 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000457};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000458#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000459/* Test TPDU - ALL YOUR */
460static u_int8_t tpdu_test[] = {
461 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
462 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
463 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
464 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000465};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000466#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000467
468int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
469{
470 struct msgb *msg = gsm411_msgb_alloc();
471 struct gsm48_hdr *gh;
472 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000473 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000474
475 msg->lchan = lchan;
476
477 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
478 gh->proto_discr = GSM48_PDISC_SMS;
479 gh->msg_type = GSM411_MT_CP_DATA;
480
481 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000482 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000483 rp->msg_type = GSM411_MT_RP_DATA_MT;
484 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000485 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000486 data = (u_int8_t *)msgb_put(msg, 8);
487 data[0] = 0x07;
488 data[1] = 0x91;
489 data[2] = 0x44;
490 data[3] = 0x77;
491 data[4] = 0x58;
492 data[5] = 0x10;
493 data[6] = 0x06;
494 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000495 data = (u_int8_t *)msgb_put(msg, 1);
496 data[0] = 0;
497
498 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000499 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
500
501 /* RPDU length */
502 data = (u_int8_t *)msgb_put(msg, 1);
503 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000504
505 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
506
507 //memcpy(data, tpdu, smslen);
508 memcpy(data, tpdu_test, sizeof(tpdu_test));
509
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000510 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
511
512 return gsm0411_sendmsg(msg);
513}