blob: 527929120b0d373e5c75711d4d5e35b66211cf3e [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{
Harald Welte9176bd42009-07-23 18:46:00 +0200185 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000186 u_int8_t *smsp = msgb_sms(msg);
187 struct sms_submit *sms;
Harald Welte7e310b12009-03-30 20:56:32 +0000188 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;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000192
Harald Welte2cf161b2009-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 Welte7e310b12009-03-30 20:56:32 +0000198 if (!sms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200199 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000200 memset(sms, 0, sizeof(*sms));
201
Harald Welte2cf161b2009-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 Welte7e310b12009-03-30 20:56:32 +0000207 if (!gsms) {
Harald Welte2cf161b2009-06-20 22:36:41 +0200208 talloc_free(sms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200209 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000210 }
211 memset(gsms, 0, sizeof(*gsms));
212
213 /* invert those fields where 0 means active/present */
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000214 sms->mti = *smsp & 0x03;
215 sms->mms = !!(*smsp & 0x04);
216 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welteb9c758b2009-07-05 14:02:46 +0200217 sms->srr = !!(*smsp & 0x20);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000218 sms->udhi= !!(*smsp & 0x40);
219 sms->rp = !!(*smsp & 0x80);
220
221 smsp++;
222 sms->msg_ref = *smsp++;
223
Harald Welte7e310b12009-03-30 20:56:32 +0000224 /* 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 Welteb9c758b2009-07-05 14:02:46 +0200228 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000229 goto out;
230 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800231 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000232 memcpy(address_lv, smsp, da_len_bytes);
233 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800234 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000235 /* convert to real number */
Harald Welte3cfdb222009-06-12 02:42:11 +0800236 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000237
238 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000239
240 sms->pid = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000241
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000242 sms->dcs = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000243 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;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000253 break;
254 default:
255 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
256 sms->vpf);
257 }
258 sms->ud_len = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000259 if (sms->ud_len)
260 sms->user_data = smsp;
261 else
262 sms->user_data = NULL;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000263
Harald Welte7e310b12009-03-30 20:56:32 +0000264 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 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000276
Harald Welte7e310b12009-03-30 20:56:32 +0000277 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
278 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000279 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
Harald Welte7e310b12009-03-30 20:56:32 +0000280 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welteb9c758b2009-07-05 14:02:46 +0200281 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
282 hexdump(sms->user_data, sms->ud_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000283
Harald Welte595ad7b2009-02-16 22:05:44 +0000284 dispatch_signal(SS_SMS, 0, sms);
Holger Freyther9b177762009-02-16 19:07:18 +0000285
Harald Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000289 gsms->sender = msg->lchan->subscr;
290 /* FIXME: sender refcount */
291
Harald Welteb9c758b2009-07-05 14:02:46 +0200292 gsms->validity_minutes = gsm340_validity_period(sms);
293
Harald Welte7e310b12009-03-30 20:56:32 +0000294 /* determine gsms->receiver based on dialled number */
Harald Welte9176bd42009-07-23 18:46:00 +0200295 gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000296 if (sms->user_data)
Harald Welteb9c758b2009-07-05 14:02:46 +0200297 memcpy(gsms->header, sms->user_data, sms->ud_len);
298
299 if (sms->decoded)
Harald Welte7e310b12009-03-30 20:56:32 +0000300 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
301
302 switch (sms->mti) {
303 case GSM340_SMS_SUBMIT_MS2SC:
304 /* MS is submitting a SMS */
305 rc = gsm340_rx_sms_submit(msg, sms, gsms);
306 break;
307 case GSM340_SMS_COMMAND_MS2SC:
308 case GSM340_SMS_DELIVER_REP_MS2SC:
309 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200310 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000311 break;
312 default:
313 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200314 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000315 break;
316 }
317
Harald Welteb9c758b2009-07-05 14:02:46 +0200318 if (!rc && !gsms->receiver)
319 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
320
Harald Welte7e310b12009-03-30 20:56:32 +0000321out:
Harald Welte2cf161b2009-06-20 22:36:41 +0200322 talloc_free(gsms);
323 talloc_free(sms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000324
Harald Welte7e310b12009-03-30 20:56:32 +0000325 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000326}
327
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000328static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
329 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000330{
331 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000332
333 msg->lchan = lchan;
334
Daniel Willmann471712b2008-12-29 01:54:02 +0000335 DEBUGP(DSMS, "TX: SMS RP ACK\n");
336
Harald Welte87f5d632009-07-04 17:39:00 +0200337 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000338}
339
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000340static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
Harald Welte7e310b12009-03-30 20:56:32 +0000341 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000342{
343 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000344
345 msg->lchan = lchan;
346
Harald Welte7e310b12009-03-30 20:56:32 +0000347 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000348
Harald Welte7e310b12009-03-30 20:56:32 +0000349 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000350
Harald Welte87f5d632009-07-04 17:39:00 +0200351 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000352}
353
Harald Welte7e310b12009-03-30 20:56:32 +0000354/* Receive a 04.11 TPDU inside RP-DATA / user data */
355static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
356 u_int8_t src_len, u_int8_t *src,
357 u_int8_t dst_len, u_int8_t *dst,
358 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000359{
360 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000361 u_int8_t trans_id = gh->proto_discr >> 4;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000362 int rc = 0;
363
Harald Welte7e310b12009-03-30 20:56:32 +0000364 if (src_len && src)
365 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
366
367 if (!dst_len || !dst || !tpdu_len || !tpdu) {
368 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200369 gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
370 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000371 return -EIO;
372 }
373 msg->smsh = tpdu;
374
375 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000376
377 rc = gsm340_rx_tpdu(msg);
378 if (rc == 0)
379 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
380 else if (rc > 0)
381 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
382 else
383 return rc;
384}
385
386/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
387static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
388{
389 u_int8_t src_len, dst_len, rpud_len;
390 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
391
392 /* in the MO case, this should always be zero length */
393 src_len = rph->data[0];
394 if (src_len)
395 src = &rph->data[1];
396
397 dst_len = rph->data[1+src_len];
398 if (dst_len)
399 dst = &rph->data[1+src_len+1];
400
401 rpud_len = rph->data[1+src_len+1+dst_len];
402 if (rpud_len)
403 rp_ud = &rph->data[1+src_len+1+dst_len+1];
404
Harald Welteb9c758b2009-07-05 14:02:46 +0200405 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
406 src_len, dst_len, rpud_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000407 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
408 rpud_len, rp_ud);
409}
410
Harald Welteb9c758b2009-07-05 14:02:46 +0200411
412static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
413{
414 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
415 * successfully received a SMS. We can now safely mark it as
416 * transmitted */
417
Harald Welte3e0f6172009-07-09 23:52:59 +0200418 /* we need to look-up the transaction based on rph->msg_ref to
419 * identify which particular RP_DATA/SMS-submit was ACKed */
420
Harald Welteb9c758b2009-07-05 14:02:46 +0200421}
422
423static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
424{
425 /* Error in response to MT RP_DATA, i.e. the MS did not
426 * successfully receive the SMS. We need to investigate
427 * the cause and take action depending on it */
428
Harald Welte3e0f6172009-07-09 23:52:59 +0200429 /* we need to look-up the transaction based on rph->msg_ref to
430 * identify which particular RP_DATA/SMS-submit failed */
431
Harald Welteb9c758b2009-07-05 14:02:46 +0200432}
433
434static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
435{
436 /* MS tells us that it has memory for more SMS, we need
437 * to check if we have any pending messages for it and then
438 * transfer those */
439}
440
Harald Welte7e310b12009-03-30 20:56:32 +0000441static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
442{
Daniel Willmann471712b2008-12-29 01:54:02 +0000443 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000444 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000445 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000446
447 switch (msg_type) {
448 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000449 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000450 rc = gsm411_rx_rp_data(msg, rp_data);
451 break;
452 case GSM411_MT_RP_ACK_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200453 rc = gsm411_rx_rp_ack(msg, rp_data);
454 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000455 case GSM411_MT_RP_ERROR_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200456 rc = gsm411_rx_rp_error(msg, rp_data);
457 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000458 case GSM411_MT_RP_SMMA_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200459 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000460 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000461 break;
462 default:
Harald Welteb9c758b2009-07-05 14:02:46 +0200463 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte7e310b12009-03-30 20:56:32 +0000464 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000465 break;
466 }
467
468 return rc;
469}
470
471int gsm0411_rcv_sms(struct msgb *msg)
472{
473 struct gsm48_hdr *gh = msgb_l3(msg);
474 u_int8_t msg_type = gh->msg_type;
475 int rc = 0;
476
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000477 switch(msg_type) {
478 case GSM411_MT_CP_DATA:
479 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000480 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000481 break;
482 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000483 DEBUGP(DSMS, "SMS CP-ACK\n");
484 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000485 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000486 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
487 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000488 default:
489 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
490 break;
491 }
492
493
494 return rc;
495}
496
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000497/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000498#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000499static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000500 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
501 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
502 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
503 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
504 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
505 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
506 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000507};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000508#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000509/* Test TPDU - ALL YOUR */
510static u_int8_t tpdu_test[] = {
511 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
512 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
513 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
514 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000515};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000516#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000517
518int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
519{
520 struct msgb *msg = gsm411_msgb_alloc();
Holger Freytherca362a62009-01-04 21:05:01 +0000521 u_int8_t *data;
Harald Welte87f5d632009-07-04 17:39:00 +0200522 u_int8_t msg_ref = 42;
523 u_int8_t trans_id = 23;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000524
525 msg->lchan = lchan;
526
Harald Welte87f5d632009-07-04 17:39:00 +0200527 /* Hardcode Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000528 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200529 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200530 data[1] = 0x91; /* type of number: international, ISDN */
531 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000532 data[3] = 0x77;
533 data[4] = 0x58;
534 data[5] = 0x10;
535 data[6] = 0x06;
536 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200537
538 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000539 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200540 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000541
542 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000543 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
544
545 /* RPDU length */
546 data = (u_int8_t *)msgb_put(msg, 1);
547 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000548
549 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
550
551 //memcpy(data, tpdu, smslen);
552 memcpy(data, tpdu_test, sizeof(tpdu_test));
553
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000554 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
555
Harald Welte87f5d632009-07-04 17:39:00 +0200556 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000557}