blob: 6dac9d87c7b9e42e148c4b6590314a094c1be393 [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
Harald Welte3e0f6172009-07-09 23:52:59 +0200417 /* we need to look-up the transaction based on rph->msg_ref to
418 * identify which particular RP_DATA/SMS-submit was ACKed */
419
Harald Welteb9c758b2009-07-05 14:02:46 +0200420}
421
422static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
423{
424 /* Error in response to MT RP_DATA, i.e. the MS did not
425 * successfully receive the SMS. We need to investigate
426 * the cause and take action depending on it */
427
Harald Welte3e0f6172009-07-09 23:52:59 +0200428 /* we need to look-up the transaction based on rph->msg_ref to
429 * identify which particular RP_DATA/SMS-submit failed */
430
Harald Welteb9c758b2009-07-05 14:02:46 +0200431}
432
433static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
434{
435 /* MS tells us that it has memory for more SMS, we need
436 * to check if we have any pending messages for it and then
437 * transfer those */
438}
439
Harald Welte7e310b12009-03-30 20:56:32 +0000440static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
441{
Daniel Willmann471712b2008-12-29 01:54:02 +0000442 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000443 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000444 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000445
446 switch (msg_type) {
447 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000448 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000449 rc = gsm411_rx_rp_data(msg, rp_data);
450 break;
451 case GSM411_MT_RP_ACK_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200452 rc = gsm411_rx_rp_ack(msg, rp_data);
453 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000454 case GSM411_MT_RP_ERROR_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200455 rc = gsm411_rx_rp_error(msg, rp_data);
456 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000457 case GSM411_MT_RP_SMMA_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200458 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000459 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000460 break;
461 default:
Harald Welteb9c758b2009-07-05 14:02:46 +0200462 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte7e310b12009-03-30 20:56:32 +0000463 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000464 break;
465 }
466
467 return rc;
468}
469
470int gsm0411_rcv_sms(struct msgb *msg)
471{
472 struct gsm48_hdr *gh = msgb_l3(msg);
473 u_int8_t msg_type = gh->msg_type;
474 int rc = 0;
475
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000476 switch(msg_type) {
477 case GSM411_MT_CP_DATA:
478 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000479 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000480 break;
481 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000482 DEBUGP(DSMS, "SMS CP-ACK\n");
483 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000484 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000485 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
486 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000487 default:
488 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
489 break;
490 }
491
492
493 return rc;
494}
495
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000496/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000497#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000498static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000499 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
500 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
501 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
502 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
503 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
504 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
505 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000506};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000507#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000508/* Test TPDU - ALL YOUR */
509static u_int8_t tpdu_test[] = {
510 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
511 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
512 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
513 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000514};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000515#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000516
517int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
518{
519 struct msgb *msg = gsm411_msgb_alloc();
Holger Freytherca362a62009-01-04 21:05:01 +0000520 u_int8_t *data;
Harald Welte87f5d632009-07-04 17:39:00 +0200521 u_int8_t msg_ref = 42;
522 u_int8_t trans_id = 23;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000523
524 msg->lchan = lchan;
525
Harald Welte87f5d632009-07-04 17:39:00 +0200526 /* Hardcode Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000527 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200528 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200529 data[1] = 0x91; /* type of number: international, ISDN */
530 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000531 data[3] = 0x77;
532 data[4] = 0x58;
533 data[5] = 0x10;
534 data[6] = 0x06;
535 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200536
537 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000538 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200539 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000540
541 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000542 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
543
544 /* RPDU length */
545 data = (u_int8_t *)msgb_put(msg, 1);
546 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000547
548 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
549
550 //memcpy(data, tpdu, smslen);
551 memcpy(data, tpdu_test, sizeof(tpdu_test));
552
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000553 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
554
Harald Welte87f5d632009-07-04 17:39:00 +0200555 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000556}