blob: ed39f792898fcce59178e98a602466df18c4825d [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 (!gsms->receiver) {
297 rc = 1; /* cause 1: unknown subscriber */
298 goto out;
299 }
300
301 if (sms->user_data)
Harald Welteb9c758b2009-07-05 14:02:46 +0200302 memcpy(gsms->header, sms->user_data, sms->ud_len);
303
304 if (sms->decoded)
Harald Welte7e310b12009-03-30 20:56:32 +0000305 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
306
307 switch (sms->mti) {
308 case GSM340_SMS_SUBMIT_MS2SC:
309 /* MS is submitting a SMS */
310 rc = gsm340_rx_sms_submit(msg, sms, gsms);
311 break;
312 case GSM340_SMS_COMMAND_MS2SC:
313 case GSM340_SMS_DELIVER_REP_MS2SC:
314 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200315 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000316 break;
317 default:
318 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200319 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000320 break;
321 }
322
Harald Welteb9c758b2009-07-05 14:02:46 +0200323 if (!rc && !gsms->receiver)
324 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
325
Harald Welte7e310b12009-03-30 20:56:32 +0000326out:
Harald Welte2cf161b2009-06-20 22:36:41 +0200327 talloc_free(gsms);
328 talloc_free(sms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000329
Harald Welte7e310b12009-03-30 20:56:32 +0000330 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000331}
332
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000333static int gsm411_send_rp_ack(struct gsm_lchan *lchan, u_int8_t trans_id,
334 u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000335{
336 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000337
338 msg->lchan = lchan;
339
Daniel Willmann471712b2008-12-29 01:54:02 +0000340 DEBUGP(DSMS, "TX: SMS RP ACK\n");
341
Harald Welte87f5d632009-07-04 17:39:00 +0200342 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ACK_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000343}
344
Daniel Willmann9dfbf252008-12-29 03:24:29 +0000345static int gsm411_send_rp_error(struct gsm_lchan *lchan, u_int8_t trans_id,
Harald Welte7e310b12009-03-30 20:56:32 +0000346 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000347{
348 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000349
350 msg->lchan = lchan;
351
Harald Welte7e310b12009-03-30 20:56:32 +0000352 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000353
Harald Welte7e310b12009-03-30 20:56:32 +0000354 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000355
Harald Welte87f5d632009-07-04 17:39:00 +0200356 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_ERROR_MT, msg_ref, trans_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000357}
358
Harald Welte7e310b12009-03-30 20:56:32 +0000359/* Receive a 04.11 TPDU inside RP-DATA / user data */
360static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm411_rp_hdr *rph,
361 u_int8_t src_len, u_int8_t *src,
362 u_int8_t dst_len, u_int8_t *dst,
363 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000364{
365 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000366 u_int8_t trans_id = gh->proto_discr >> 4;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000367 int rc = 0;
368
Harald Welte7e310b12009-03-30 20:56:32 +0000369 if (src_len && src)
370 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
371
372 if (!dst_len || !dst || !tpdu_len || !tpdu) {
373 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200374 gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref,
375 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000376 return -EIO;
377 }
378 msg->smsh = tpdu;
379
380 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000381
382 rc = gsm340_rx_tpdu(msg);
383 if (rc == 0)
384 return gsm411_send_rp_ack(msg->lchan, trans_id, rph->msg_ref);
385 else if (rc > 0)
386 return gsm411_send_rp_error(msg->lchan, trans_id, rph->msg_ref, rc);
387 else
388 return rc;
389}
390
391/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
392static int gsm411_rx_rp_data(struct msgb *msg, struct gsm411_rp_hdr *rph)
393{
394 u_int8_t src_len, dst_len, rpud_len;
395 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
396
397 /* in the MO case, this should always be zero length */
398 src_len = rph->data[0];
399 if (src_len)
400 src = &rph->data[1];
401
402 dst_len = rph->data[1+src_len];
403 if (dst_len)
404 dst = &rph->data[1+src_len+1];
405
406 rpud_len = rph->data[1+src_len+1+dst_len];
407 if (rpud_len)
408 rp_ud = &rph->data[1+src_len+1+dst_len+1];
409
Harald Welteb9c758b2009-07-05 14:02:46 +0200410 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
411 src_len, dst_len, rpud_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000412 return gsm411_rx_rp_ud(msg, rph, src_len, src, dst_len, dst,
413 rpud_len, rp_ud);
414}
415
Harald Welteb9c758b2009-07-05 14:02:46 +0200416
417static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm411_rp_hdr *rph)
418{
419 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
420 * successfully received a SMS. We can now safely mark it as
421 * transmitted */
422
Harald Welte3e0f6172009-07-09 23:52:59 +0200423 /* we need to look-up the transaction based on rph->msg_ref to
424 * identify which particular RP_DATA/SMS-submit was ACKed */
425
Harald Welteb9c758b2009-07-05 14:02:46 +0200426}
427
428static int gsm411_rx_rp_error(struct msgb *msg, struct gsm411_rp_hdr *rph)
429{
430 /* Error in response to MT RP_DATA, i.e. the MS did not
431 * successfully receive the SMS. We need to investigate
432 * the cause and take action depending on it */
433
Harald Welte3e0f6172009-07-09 23:52:59 +0200434 /* we need to look-up the transaction based on rph->msg_ref to
435 * identify which particular RP_DATA/SMS-submit failed */
436
Harald Welteb9c758b2009-07-05 14:02:46 +0200437}
438
439static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm411_rp_hdr *rph)
440{
441 /* MS tells us that it has memory for more SMS, we need
442 * to check if we have any pending messages for it and then
443 * transfer those */
444}
445
Harald Welte7e310b12009-03-30 20:56:32 +0000446static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh)
447{
Daniel Willmann471712b2008-12-29 01:54:02 +0000448 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000449 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000450 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000451
452 switch (msg_type) {
453 case GSM411_MT_RP_DATA_MO:
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000454 DEBUGP(DSMS, "SMS RP-DATA (MO)\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000455 rc = gsm411_rx_rp_data(msg, rp_data);
456 break;
457 case GSM411_MT_RP_ACK_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200458 rc = gsm411_rx_rp_ack(msg, rp_data);
459 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000460 case GSM411_MT_RP_ERROR_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200461 rc = gsm411_rx_rp_error(msg, rp_data);
462 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000463 case GSM411_MT_RP_SMMA_MO:
Harald Welteb9c758b2009-07-05 14:02:46 +0200464 rc = gsm411_rx_rp_smma(msg, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000465 DEBUGP(DSMS, "Unimplemented RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000466 break;
467 default:
Harald Welteb9c758b2009-07-05 14:02:46 +0200468 /* FIXME: send GSM411_CP_CAUSE_MSGTYPE_NOTEXIST */
Harald Welte7e310b12009-03-30 20:56:32 +0000469 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000470 break;
471 }
472
473 return rc;
474}
475
476int gsm0411_rcv_sms(struct msgb *msg)
477{
478 struct gsm48_hdr *gh = msgb_l3(msg);
479 u_int8_t msg_type = gh->msg_type;
480 int rc = 0;
481
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000482 switch(msg_type) {
483 case GSM411_MT_CP_DATA:
484 DEBUGP(DSMS, "SMS CP-DATA\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000485 rc = gsm411_rx_cp_data(msg, gh);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000486 break;
487 case GSM411_MT_CP_ACK:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000488 DEBUGP(DSMS, "SMS CP-ACK\n");
489 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000490 case GSM411_MT_CP_ERROR:
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000491 DEBUGP(DSMS, "SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
492 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000493 default:
494 DEBUGP(DSMS, "Unimplemented CP msg_type: 0x%02x\n", msg_type);
495 break;
496 }
497
498
499 return rc;
500}
501
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000502/* Test TPDU - 25c3 welcome */
Harald Welte8c2e36e2008-12-30 15:00:14 +0000503#if 0
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000504static u_int8_t tpdu_test[] = {
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000505 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
506 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
507 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
508 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
509 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
510 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
511 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000512};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000513#else
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000514/* Test TPDU - ALL YOUR */
515static u_int8_t tpdu_test[] = {
516 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
517 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
518 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
519 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000520};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000521#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000522
523int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
524{
525 struct msgb *msg = gsm411_msgb_alloc();
Holger Freytherca362a62009-01-04 21:05:01 +0000526 u_int8_t *data;
Harald Welte87f5d632009-07-04 17:39:00 +0200527 u_int8_t msg_ref = 42;
528 u_int8_t trans_id = 23;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000529
530 msg->lchan = lchan;
531
Harald Welte87f5d632009-07-04 17:39:00 +0200532 /* Hardcode Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000533 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200534 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200535 data[1] = 0x91; /* type of number: international, ISDN */
536 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000537 data[3] = 0x77;
538 data[4] = 0x58;
539 data[5] = 0x10;
540 data[6] = 0x06;
541 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200542
543 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000544 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200545 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000546
547 /* FIXME: Hardcoded for now */
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000548 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
549
550 /* RPDU length */
551 data = (u_int8_t *)msgb_put(msg, 1);
552 data[0] = sizeof(tpdu_test);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000553
554 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
555
556 //memcpy(data, tpdu, smslen);
557 memcpy(data, tpdu_test, sizeof(tpdu_test));
558
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000559 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
560
Harald Welte87f5d632009-07-04 17:39:00 +0200561 return gsm411_rp_sendmsg(msg, GSM411_MT_RP_DATA_MT, msg_ref, trans_id);
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000562}