blob: 9218783ff2101fc74b5515f4e60b898ff2edb12b [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{
Harald Welte966636f2009-06-26 19:39:35 +020054 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
55 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +000056}
57
Holger Freythera553d092009-01-04 20:16:25 +000058int gsm0411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000059{
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
Daniel Willmanne0fbec82008-12-29 00:44:41 +000068
Holger Freytherca362a62009-01-04 21:05:01 +000069#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000070static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
71{
Daniel Willmann6fe997e2008-12-29 04:20:41 +000072}
Holger Freytherca362a62009-01-04 21:05:01 +000073#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +000074
Harald Welte7e310b12009-03-30 20:56:32 +000075static unsigned long gsm340_validity_period(struct sms_submit *sms)
76{
77 u_int8_t vp;
78 unsigned long minutes;
79
80 switch (sms->vpf) {
81 case GSM340_TP_VPF_RELATIVE:
82 /* Chapter 9.2.3.12.1 */
83 vp = *(sms->vp);
84 if (vp <= 143)
85 minutes = vp + 1 * 5;
86 else if (vp <= 167)
87 minutes = 12*60 + (vp-143) * 30;
88 else if (vp <= 196)
89 minutes = vp-166 * 60 * 24;
90 else
91 minutes = vp-192 * 60 * 24 * 7;
92 break;
93 case GSM340_TP_VPF_ABSOLUTE:
94 /* Chapter 9.2.3.12.2 */
95 /* FIXME: like service center time stamp */
96 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
97 break;
98 case GSM340_TP_VPF_ENHANCED:
99 /* Chapter 9.2.3.12.3 */
100 /* FIXME: implementation */
101 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
102 break;
103 }
104 return minutes;
105}
106
107/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
108enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
109{
110 u_int8_t cgbits = dcs >> 4;
111 enum sms_alphabet alpha = DCS_NONE;
112
113 if ((cgbits & 0xc) == 0) {
114 if (cgbits & 2)
115 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
116
117 switch (dcs & 3) {
118 case 0:
119 alpha = DCS_7BIT_DEFAULT;
120 break;
121 case 1:
122 alpha = DCS_8BIT_DATA;
123 break;
124 case 2:
125 alpha = DCS_UCS2;
126 break;
127 }
128 } else if (cgbits == 0xc || cgbits == 0xd)
129 alpha = DCS_7BIT_DEFAULT;
130 else if (cgbits == 0xe)
131 alpha = DCS_UCS2;
132 else if (cgbits == 0xf) {
133 if (dcs & 4)
134 alpha = DCS_8BIT_DATA;
135 else
136 alpha = DCS_7BIT_DEFAULT;
137 }
138
139 return alpha;
140}
141
142static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
143 struct gsm_sms *gsms)
144{
145 if (db_sms_store(gsms) != 0) {
146 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte2cf161b2009-06-20 22:36:41 +0200147 talloc_free(sms);
148 talloc_free(gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000149 return -EIO;
150 }
151 return 0;
152}
153
154/* process an incoming TPDU (called from RP-DATA) */
155static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000156{
Harald Welte761e9442009-07-23 19:21:02 +0200157 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000158 u_int8_t *smsp = msgb_sms(msg);
159 struct sms_submit *sms;
Harald Welte7e310b12009-03-30 20:56:32 +0000160 struct gsm_sms *gsms;
161 u_int8_t da_len_bytes;
162 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
163 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000164
Harald Welte2cf161b2009-06-20 22:36:41 +0200165 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte7e310b12009-03-30 20:56:32 +0000166 if (!sms)
167 return -ENOMEM;
168 memset(sms, 0, sizeof(*sms));
169
Harald Welte2cf161b2009-06-20 22:36:41 +0200170 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte7e310b12009-03-30 20:56:32 +0000171 if (!gsms) {
Harald Welte2cf161b2009-06-20 22:36:41 +0200172 talloc_free(sms);
Harald Welte7e310b12009-03-30 20:56:32 +0000173 return -ENOMEM;
174 }
175 memset(gsms, 0, sizeof(*gsms));
176
177 /* invert those fields where 0 means active/present */
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000178 sms->mti = *smsp & 0x03;
179 sms->mms = !!(*smsp & 0x04);
180 sms->vpf = (*smsp & 0x18) >> 3;
181 sms->sri = !!(*smsp & 0x20);
182 sms->udhi= !!(*smsp & 0x40);
183 sms->rp = !!(*smsp & 0x80);
184
185 smsp++;
186 sms->msg_ref = *smsp++;
187
Harald Welte7e310b12009-03-30 20:56:32 +0000188 /* length in bytes of the destination address */
189 da_len_bytes = 2 + *smsp/2 + *smsp%2;
190 if (da_len_bytes > 12) {
191 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
192 rc = -EIO;
193 goto out;
194 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800195 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000196 memcpy(address_lv, smsp, da_len_bytes);
197 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800198 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000199 /* convert to real number */
Harald Welte3cfdb222009-06-12 02:42:11 +0800200 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000201
202 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000203
204 sms->pid = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000205
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000206 sms->dcs = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000207 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
208
209 switch (sms->vpf) {
210 case GSM340_TP_VPF_RELATIVE:
211 sms->vp = smsp++;
212 break;
213 case GSM340_TP_VPF_ABSOLUTE:
214 case GSM340_TP_VPF_ENHANCED:
215 sms->vp = smsp;
216 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000217 break;
218 default:
219 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
220 sms->vpf);
221 }
222 sms->ud_len = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000223 if (sms->ud_len)
224 sms->user_data = smsp;
225 else
226 sms->user_data = NULL;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000227
Harald Welte7e310b12009-03-30 20:56:32 +0000228 if (sms->ud_len) {
229 switch (sms->alphabet) {
230 case DCS_7BIT_DEFAULT:
231 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
232 break;
233 case DCS_8BIT_DATA:
234 case DCS_UCS2:
235 case DCS_NONE:
236 memcpy(sms->decoded, sms->user_data, sms->ud_len);
237 break;
238 }
239 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000240
Harald Welte7e310b12009-03-30 20:56:32 +0000241 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
242 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000243 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
Harald Welte7e310b12009-03-30 20:56:32 +0000244 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
245 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded : hexdump(sms->user_data, sms->ud_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000246
Harald Welte595ad7b2009-02-16 22:05:44 +0000247 dispatch_signal(SS_SMS, 0, sms);
Holger Freyther9b177762009-02-16 19:07:18 +0000248
Harald Welte7e310b12009-03-30 20:56:32 +0000249 gsms->sender = msg->lchan->subscr;
250 /* FIXME: sender refcount */
251
252 /* determine gsms->receiver based on dialled number */
Harald Welte761e9442009-07-23 19:21:02 +0200253 gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000254 if (!gsms->receiver) {
255 rc = 1; /* cause 1: unknown subscriber */
256 goto out;
257 }
258
259 if (sms->user_data)
260 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
261
262 switch (sms->mti) {
263 case GSM340_SMS_SUBMIT_MS2SC:
264 /* MS is submitting a SMS */
265 rc = gsm340_rx_sms_submit(msg, sms, gsms);
266 break;
267 case GSM340_SMS_COMMAND_MS2SC:
268 case GSM340_SMS_DELIVER_REP_MS2SC:
269 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
270 break;
271 default:
272 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
273 break;
274 }
275
276out:
Harald Welte2cf161b2009-06-20 22:36:41 +0200277 talloc_free(gsms);
278 talloc_free(sms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000279
Harald Welte7e310b12009-03-30 20:56:32 +0000280 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000281}
282
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000283static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
284 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000285{
286 struct msgb *msg = gsm411_msgb_alloc();
287 struct gsm48_hdr *gh;
288 struct gsm411_rp_hdr *rp;
289
290 msg->lchan = lchan;
291
292 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000293 // Outgoing needs the highest bit set
294 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
295 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000296
297 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000298 rp->len = 2;
Daniel Willmann471712b2008-12-29 01:54:02 +0000299 rp->msg_type = GSM411_MT_RP_ACK_MT;
300 rp->msg_ref = msg_ref;
301
302 DEBUGP(DSMS, "TX: SMS RP ACK\n");
303
304 return gsm0411_sendmsg(msg);
305}
306
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000307static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
Harald Welte7e310b12009-03-30 20:56:32 +0000308 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000309{
310 struct msgb *msg = gsm411_msgb_alloc();
311 struct gsm48_hdr *gh;
312 struct gsm411_rp_hdr *rp;
313
314 msg->lchan = lchan;
315
316 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Daniel Willmannaecbbed2008-12-29 03:45:50 +0000317 // Outgoing needs the highest bit set
318 gh->proto_discr = GSM48_PDISC_SMS | trans_id<<4 | 0x80;
319 gh->msg_type = GSM411_MT_CP_DATA;
Daniel Willmann471712b2008-12-29 01:54:02 +0000320
321 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
322 rp->msg_type = GSM411_MT_RP_ERROR_MT;
323 rp->msg_ref = msg_ref;
Harald Welte7e310b12009-03-30 20:56:32 +0000324 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000325
Harald Welte7e310b12009-03-30 20:56:32 +0000326 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000327
328 return gsm0411_sendmsg(msg);
329}
330
Harald Welte7e310b12009-03-30 20:56:32 +0000331/* Receive a 04.11 TPDU inside RP-DATA / user data */
332static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
333 u_int8_t src_len, u_int8_t *src,
334 u_int8_t dst_len, u_int8_t *dst,
335 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000336{
337 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000338 u_int8_t trans_id = gh->proto_discr >> 4;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000339 int rc = 0;
340
Harald Welte7e310b12009-03-30 20:56:32 +0000341 if (src_len && src)
342 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
343
344 if (!dst_len || !dst || !tpdu_len || !tpdu) {
345 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
346 return -EIO;
347 }
348 msg->smsh = tpdu;
349
350 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
351 //return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
352
353 rc = gsm340_rx_tpdu(msg);
354 if (rc == 0)
355 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
356 else if (rc > 0)
357 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
358 else
359 return rc;
360}
361
362/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
363static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
364{
365 u_int8_t src_len, dst_len, rpud_len;
366 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
367
368 /* in the MO case, this should always be zero length */
369 src_len = rph->data[0];
370 if (src_len)
371 src = &rph->data[1];
372
373 dst_len = rph->data[1+src_len];
374 if (dst_len)
375 dst = &rph->data[1+src_len+1];
376
377 rpud_len = rph->data[1+src_len+1+dst_len];
378 if (rpud_len)
379 rp_ud = &rph->data[1+src_len+1+dst_len+1];
380
381 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n", src_len, dst_len, rpud_len);
382 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
383 rpud_len, rp_ud);
384}
385
386static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
387{
Daniel Willmann471712b2008-12-29 01:54:02 +0000388 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000389 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000390 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000391
392 switch (msg_type) {
393 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000394 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000395 rc = gsm411_rx_rp_data(msg, rp_data);
396 break;
397 case GSM411_MT_RP_ACK_MO:
398 /* Acnkowledgement to MT RP_DATA */
399 case GSM411_MT_RP_ERROR_MO:
400 /* Error in response to MT RP_DATA */
401 case GSM411_MT_RP_SMMA_MO:
402 /* MS tells us that it has memory for more SMS, we need
403 * to check if we have any pending messages for it and then
404 * transfer those */
405 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000406 break;
407 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000408 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000409 break;
410 }
411
412 return rc;
413}
414
415int gsm0411_rcv_sms(struct msgb *msg)
416{
417 struct gsm48_hdr *gh = msgb_l3(msg);
418 u_int8_t msg_type = gh->msg_type;
419 int rc = 0;
420
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000421 switch(msg_type) {
422 case GSM411_MT_CP_DATA:
423 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000424 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000425 break;
426 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000427 DEBUGP(DSMS, "SMS CP-ACK\n");
428 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000429 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000430 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
431 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000432 default:
433 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
434 break;
435 }
436
437
438 return rc;
439}
440
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000441/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000442#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000443static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000444 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
445 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
446 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
447 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
448 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
449 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
450 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000451};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000452#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000453/* Test TPDU - ALL YOUR */
454static u_int8_t tpdu_test[] = {
455 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
456 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
457 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
458 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000459};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000460#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000461
462int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
463{
464 struct msgb *msg = gsm411_msgb_alloc();
465 struct gsm48_hdr *gh;
466 struct gsm411_rp_hdr *rp;
Holger Freytherca362a62009-01-04 21:05:01 +0000467 u_int8_t *data;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000468
469 msg->lchan = lchan;
470
471 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
472 gh->proto_discr = GSM48_PDISC_SMS;
473 gh->msg_type = GSM411_MT_CP_DATA;
474
475 rp = (struct gsm411_rp_hdr *)msgb_put(msg, sizeof(*rp));
Daniel Willmanna3e29842008-12-29 16:03:54 +0000476 rp->len = sizeof(tpdu_test) + 10;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000477 rp->msg_type = GSM411_MT_RP_DATA_MT;
478 rp->msg_ref = 42; /* FIXME: Choose randomly */
Daniel Willmannfad5d0d2008-12-29 16:04:14 +0000479 /* Hardcode OA for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000480 data = (u_int8_t *)msgb_put(msg, 8);
481 data[0] = 0x07;
482 data[1] = 0x91;
483 data[2] = 0x44;
484 data[3] = 0x77;
485 data[4] = 0x58;
486 data[5] = 0x10;
487 data[6] = 0x06;
488 data[7] = 0x50;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000489 data = (u_int8_t *)msgb_put(msg, 1);
490 data[0] = 0;
491
492 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000493 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
494
495 /* RPDU length */
496 data = (u_int8_t *)msgb_put(msg, 1);
497 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000498
499 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
500
501 //memcpy(data, tpdu, smslen);
502 memcpy(data, tpdu_test, sizeof(tpdu_test));
503
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000504 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
505
506 return gsm0411_sendmsg(msg);
507}
Harald Welte7bfc2672009-07-28 00:41:45 +0200508
509static __attribute__((constructor)) void on_dso_load_sms(void)
510{
511 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms_submit");
512 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
513}