blob: 68ccec64ca9ecfc727c194a4e9218fcbb69ceabd [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
Harald Welte87f5d632009-07-04 17:39:00 +020058static int gsm411_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
Harald Welte87f5d632009-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
Daniel Willmanne0fbec82008-12-29 00:44:41 +000097
Holger Freytherca362a62009-01-04 21:05:01 +000098#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +000099static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
100{
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000101}
Holger Freytherca362a62009-01-04 21:05:01 +0000102#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000103
Harald Welte7e310b12009-03-30 20:56:32 +0000104static 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 Welteb9c758b2009-07-05 14:02:46 +0200176 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000177 }
178 return 0;
179}
180
Harald Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000183static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000184{
185 u_int8_t *smsp = msgb_sms(msg);
186 struct sms_submit *sms;
Harald Welte7e310b12009-03-30 20:56:32 +0000187 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;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000191
Harald Welte2cf161b2009-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 Welte7e310b12009-03-30 20:56:32 +0000197 if (!sms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200198 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000199 memset(sms, 0, sizeof(*sms));
200
Harald Welte2cf161b2009-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 Welte7e310b12009-03-30 20:56:32 +0000206 if (!gsms) {
Harald Welte2cf161b2009-06-20 22:36:41 +0200207 talloc_free(sms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200208 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000209 }
210 memset(gsms, 0, sizeof(*gsms));
211
212 /* invert those fields where 0 means active/present */
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000213 sms->mti = *smsp & 0x03;
214 sms->mms = !!(*smsp & 0x04);
215 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welteb9c758b2009-07-05 14:02:46 +0200216 sms->srr = !!(*smsp & 0x20);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000217 sms->udhi= !!(*smsp & 0x40);
218 sms->rp = !!(*smsp & 0x80);
219
220 smsp++;
221 sms->msg_ref = *smsp++;
222
Harald Welte7e310b12009-03-30 20:56:32 +0000223 /* 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 Welteb9c758b2009-07-05 14:02:46 +0200227 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000228 goto out;
229 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800230 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000231 memcpy(address_lv, smsp, da_len_bytes);
232 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800233 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000234 /* convert to real number */
Harald Welte3cfdb222009-06-12 02:42:11 +0800235 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000236
237 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000238
239 sms->pid = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000240
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000241 sms->dcs = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000242 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;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000252 break;
253 default:
254 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
255 sms->vpf);
256 }
257 sms->ud_len = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000258 if (sms->ud_len)
259 sms->user_data = smsp;
260 else
261 sms->user_data = NULL;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000262
Harald Welte7e310b12009-03-30 20:56:32 +0000263 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 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000275
Harald Welte7e310b12009-03-30 20:56:32 +0000276 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
277 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000278 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
Harald Welte7e310b12009-03-30 20:56:32 +0000279 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welteb9c758b2009-07-05 14:02:46 +0200280 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
281 hexdump(sms->user_data, sms->ud_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000282
Harald Welte595ad7b2009-02-16 22:05:44 +0000283 dispatch_signal(SS_SMS, 0, sms);
Holger Freyther9b177762009-02-16 19:07:18 +0000284
Harald Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000288 gsms->sender = msg->lchan->subscr;
289 /* FIXME: sender refcount */
290
Harald Welteb9c758b2009-07-05 14:02:46 +0200291 gsms->validity_minutes = gsm340_validity_period(sms);
292
Harald Welte7e310b12009-03-30 20:56:32 +0000293 /* determine gsms->receiver based on dialled number */
294 gsms->receiver = subscr_get_by_extension(sms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000295 if (sms->user_data)
Harald Welteb9c758b2009-07-05 14:02:46 +0200296 memcpy(gsms->header, sms->user_data, sms->ud_len);
297
298 if (sms->decoded)
Harald Welte7e310b12009-03-30 20:56:32 +0000299 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 Welteb9c758b2009-07-05 14:02:46 +0200309 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000310 break;
311 default:
312 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200313 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000314 break;
315 }
316
Harald Welteb9c758b2009-07-05 14:02:46 +0200317 if (!rc && !gsms->receiver)
318 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
319
Harald Welte7e310b12009-03-30 20:56:32 +0000320out:
Harald Welte2cf161b2009-06-20 22:36:41 +0200321 talloc_free(gsms);
322 talloc_free(sms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000323
Harald Welte7e310b12009-03-30 20:56:32 +0000324 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000325}
326
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000327static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
328 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000329{
330 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000331
332 msg->lchan = lchan;
333
Daniel Willmann471712b2008-12-29 01:54:02 +0000334 DEBUGP(DSMS, "TX: SMS RP ACK\n");
335
Harald Welte87f5d632009-07-04 17:39:00 +0200336 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000337}
338
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000339static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
Harald Welte7e310b12009-03-30 20:56:32 +0000340 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000341{
342 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000343
344 msg->lchan = lchan;
345
Harald Welte7e310b12009-03-30 20:56:32 +0000346 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000347
Harald Welte7e310b12009-03-30 20:56:32 +0000348 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000349
Harald Welte87f5d632009-07-04 17:39:00 +0200350 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000351}
352
Harald Welte7e310b12009-03-30 20:56:32 +0000353/* 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)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000358{
359 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000360 u_int8_t trans_id = gh->proto_discr >> 4;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000361 int rc = 0;
362
Harald Welte7e310b12009-03-30 20:56:32 +0000363 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 Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000370 return -EIO;
371 }
372 msg->smsh = tpdu;
373
374 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000375
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 Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000406 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
407 rpud_len, rp_ud);
408}
409
Harald Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000434static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
435{
Daniel Willmann471712b2008-12-29 01:54:02 +0000436 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000437 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000438 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000439
440 switch (msg_type) {
441 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000442 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000443 rc = gsm411_rx_rp_data(msg, rp_data);
444 break;
445 case GSM411_MT_RP_ACK_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200446 rc = gsm411_rx_rp_ack(msg, rp_data);
447 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000448 case GSM411_MT_RP_ERROR_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200449 rc = gsm411_rx_rp_error(msg, rp_data);
450 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000451 case GSM411_MT_RP_SMMA_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200452 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000453 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000454 break;
455 default:
Harald Welteb9c758b2009-07-05 14:02:46 +0200456 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte7e310b12009-03-30 20:56:32 +0000457 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000458 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
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000470 switch(msg_type) {
471 case GSM411_MT_CP_DATA:
472 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000473 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000474 break;
475 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000476 DEBUGP(DSMS, "SMS CP-ACK\n");
477 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000478 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000479 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
480 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000481 default:
482 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
483 break;
484 }
485
486
487 return rc;
488}
489
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000490/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000491#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000492static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000493 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
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000500};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000501#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000502/* 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
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000508};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000509#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000510
511int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
512{
513 struct msgb *msg = gsm411_msgb_alloc();
Holger Freytherca362a62009-01-04 21:05:01 +0000514 u_int8_t *data;
Harald Welte87f5d632009-07-04 17:39:00 +0200515 u_int8_t msg_ref = 42;
516 u_int8_t trans_id = 23;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000517
518 msg->lchan = lchan;
519
Harald Welte87f5d632009-07-04 17:39:00 +0200520 /* Hardcode Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000521 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200522 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200523 data[1] = 0x91; /* type of number: international, ISDN */
524 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000525 data[3] = 0x77;
526 data[4] = 0x58;
527 data[5] = 0x10;
528 data[6] = 0x06;
529 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200530
531 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000532 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200533 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000534
535 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000536 //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);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000541
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
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000547 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
548
Harald Welte87f5d632009-07-04 17:39:00 +0200549 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000550}