blob: 1260eee1c316ef8e7eb0f6f0907d6878cb314aba [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* 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>
6 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
7 *
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>
Harald Welteb78996d2009-07-27 20:11:35 +020031#include <time.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
35#include <openbsc/tlv.h>
36#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
41#include <openbsc/gsm_utils.h>
42#include <openbsc/abis_rsl.h>
43#include <openbsc/signal.h>
44#include <openbsc/db.h>
Harald Weltea8379772009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Welteb78996d2009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte59b04682009-06-10 05:40:52 +080047
48#define GSM411_ALLOC_SIZE 1024
49#define GSM411_ALLOC_HEADROOM 128
50
Harald Weltea8379772009-06-20 22:36:41 +020051static void *tall_sms_ctx;
52static void *tall_gsms_ctx;
53
Harald Welteb78996d2009-07-27 20:11:35 +020054static u_int32_t new_callref = 0x40000001;
55
Harald Welte59b04682009-06-10 05:40:52 +080056struct msgb *gsm411_msgb_alloc(void)
57{
Harald Welte9cfc9352009-06-26 19:39:35 +020058 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
59 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +080060}
61
Harald Welte7e2f57d2009-07-04 17:39:00 +020062static int gsm411_sendmsg(struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +080063{
64 if (msg->lchan)
65 msg->trx = msg->lchan->ts->trx;
66
67 msg->l3h = msg->data;
68
69 return rsl_data_request(msg, 0);
70}
71
Harald Welte7e2f57d2009-07-04 17:39:00 +020072/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +020073static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
74 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +020075{
76 struct gsm48_hdr *gh;
77
78 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
79 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +020080 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +020081 gh->msg_type = msg_type;
82
Harald Welteb78996d2009-07-27 20:11:35 +020083 /* assign the outgoing lchan */
84 msg->lchan = trans->lchan;
85
86 /* mobile originating */
87 switch (gh->msg_type) {
88 case GSM411_MT_CP_DATA:
89 /* 5.2.3.1.2: enter MO-wait for CP-ack */
90 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
91 break;
92 }
93
Harald Welte7e2f57d2009-07-04 17:39:00 +020094 return gsm411_sendmsg(msg);
95}
96
97/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +020098static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
99 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200100{
101 struct gsm411_rp_hdr *rp;
102
103 /* GSM 04.11 RP-DATA header */
104 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
105 rp->len = msg->len;
106 rp->msg_type = rp_msg_type;
107 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
108
Harald Welteb78996d2009-07-27 20:11:35 +0200109 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200110}
111
Harald Welte59b04682009-06-10 05:40:52 +0800112#if 0
113static u_int8_t gsm0411_tpdu_from_sms(u_int8_t *tpdu, struct sms_deliver *sms)
114{
115}
116#endif
117
118static unsigned long gsm340_validity_period(struct sms_submit *sms)
119{
120 u_int8_t vp;
121 unsigned long minutes;
122
123 switch (sms->vpf) {
124 case GSM340_TP_VPF_RELATIVE:
125 /* Chapter 9.2.3.12.1 */
126 vp = *(sms->vp);
127 if (vp <= 143)
128 minutes = vp + 1 * 5;
129 else if (vp <= 167)
130 minutes = 12*60 + (vp-143) * 30;
131 else if (vp <= 196)
132 minutes = vp-166 * 60 * 24;
133 else
134 minutes = vp-192 * 60 * 24 * 7;
135 break;
136 case GSM340_TP_VPF_ABSOLUTE:
137 /* Chapter 9.2.3.12.2 */
138 /* FIXME: like service center time stamp */
139 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
140 break;
141 case GSM340_TP_VPF_ENHANCED:
142 /* Chapter 9.2.3.12.3 */
143 /* FIXME: implementation */
144 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
145 break;
146 }
147 return minutes;
148}
149
150/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
151enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
152{
153 u_int8_t cgbits = dcs >> 4;
154 enum sms_alphabet alpha = DCS_NONE;
155
156 if ((cgbits & 0xc) == 0) {
157 if (cgbits & 2)
158 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
159
160 switch (dcs & 3) {
161 case 0:
162 alpha = DCS_7BIT_DEFAULT;
163 break;
164 case 1:
165 alpha = DCS_8BIT_DATA;
166 break;
167 case 2:
168 alpha = DCS_UCS2;
169 break;
170 }
171 } else if (cgbits == 0xc || cgbits == 0xd)
172 alpha = DCS_7BIT_DEFAULT;
173 else if (cgbits == 0xe)
174 alpha = DCS_UCS2;
175 else if (cgbits == 0xf) {
176 if (dcs & 4)
177 alpha = DCS_8BIT_DATA;
178 else
179 alpha = DCS_7BIT_DEFAULT;
180 }
181
182 return alpha;
183}
184
185static int gsm340_rx_sms_submit(struct msgb *msg, struct sms_submit *sms,
186 struct gsm_sms *gsms)
187{
188 if (db_sms_store(gsms) != 0) {
189 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200190 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800191 }
192 return 0;
193}
194
Harald Welteb78996d2009-07-27 20:11:35 +0200195static int gsm340_gen_oa(u_int8_t *oa, struct gsm_subscriber *subscr)
196{
197 int len = 0;
198
199}
200
201static u_int8_t bcdify(u_int8_t value)
202{
203 u_int8_t ret;
204
205 ret = value % 10;
206 ret |= (value / 10) << 4;
207
208 return ret;
209}
210
211/* Generate 03.40 TP-SCTS */
212static void gsm340_gen_scts(u_int8_t *scts, time_t time)
213{
214 struct tm *tm = localtime(&time);
215 u_int8_t digit;
216
217 *scts++ = bcdify(tm->tm_year % 100);
218 *scts++ = bcdify(tm->tm_mon);
219 *scts++ = bcdify(tm->tm_mday);
220 *scts++ = bcdify(tm->tm_hour);
221 *scts++ = bcdify(tm->tm_min);
222 *scts++ = bcdify(tm->tm_sec);
223 *scts++ = 0; /* FIXME: timezone */
224}
225
226static struct msgb *gsm340_gen_tpdu(struct gsm_sms *sms)
227{
228 struct msgb *msg = gsm411_msgb_alloc();
229 u_int8_t *smsp;
230 u_int8_t oa[12]; /* max len per 03.40 */
231 u_int8_t oa_len = 0;
232
233 /* generate first octet with masked bits */
234 smsp = msgb_put(msg, 1);
235 *smsp = GSM340_SMS_DELIVER_SC2MS;
236 if (0 /* FIXME: MMS */)
237 *smsp |= 0x04;
238 /* two bits empty */
239 if (sms->status_rep_req)
240 *smsp |= 0x20;
241#if 0
242 if (sms->header_len)
243 *smsp |= 0x40;
244 if (sms->
245 *smsp |= 0x80;
246#endif
247
248 /* generate originator address */
249 smsp = msgb_put(msg, oa_len);
250 oa_len = gsm340_gen_oa(&oa, sms->sender);
251 memcpy(smsp, oa, oa_len);
252
253 /* generate TP-PID */
254 smsp = msgb_put(msg, 1);
255 *smsp = sms->protocol_id;
256
257 /* generate TP-DCS */
258 smsp = msgb_put(msg, 1);
259 *smsp = sms->data_coding_scheme;
260
261 /* generate TP-SCTS */
262 smsp = msgb_put(msg, 7);
263 gsm340_gen_scts(smsp, time(NULL));
264#if 0
265 /* generate TP-UDL */
266 smsp = msgb_put(msg, 1);
267 *smsp = ud_len;
268
269 /* generate TP-UD */
270 smsp = msgb_put(msg, ud_len);
271 memcpy(smsp, FIXME, ud_len);
272#endif
273
274 return msg;
275}
276
Harald Welte156c5e62009-07-05 14:02:46 +0200277/* process an incoming TPDU (called from RP-DATA)
278 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800279static int gsm340_rx_tpdu(struct msgb *msg)
280{
Harald Welte75350412009-07-23 18:46:00 +0200281 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800282 u_int8_t *smsp = msgb_sms(msg);
283 struct sms_submit *sms;
284 struct gsm_sms *gsms;
285 u_int8_t da_len_bytes;
286 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
287 int rc = 0;
288
Harald Weltea8379772009-06-20 22:36:41 +0200289 if (!tall_sms_ctx)
290 tall_sms_ctx = talloc_named_const(tall_bsc_ctx, 1,
291 "sms_submit");
292
293 sms = talloc(tall_sms_ctx, struct sms_submit);
Harald Welte59b04682009-06-10 05:40:52 +0800294 if (!sms)
Harald Welte156c5e62009-07-05 14:02:46 +0200295 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800296 memset(sms, 0, sizeof(*sms));
297
Harald Weltea8379772009-06-20 22:36:41 +0200298 if (!tall_gsms_ctx)
299 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1,
300 "sms");
301
302 gsms = talloc(tall_gsms_ctx, struct gsm_sms);
Harald Welte59b04682009-06-10 05:40:52 +0800303 if (!gsms) {
Harald Weltea8379772009-06-20 22:36:41 +0200304 talloc_free(sms);
Harald Welte156c5e62009-07-05 14:02:46 +0200305 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800306 }
307 memset(gsms, 0, sizeof(*gsms));
308
309 /* invert those fields where 0 means active/present */
310 sms->mti = *smsp & 0x03;
311 sms->mms = !!(*smsp & 0x04);
312 sms->vpf = (*smsp & 0x18) >> 3;
Harald Welteb78996d2009-07-27 20:11:35 +0200313 sms->srr = (*smsp & 0x20);
314 sms->udhi= (*smsp & 0x40);
315 sms->rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800316
317 smsp++;
318 sms->msg_ref = *smsp++;
319
320 /* length in bytes of the destination address */
321 da_len_bytes = 2 + *smsp/2 + *smsp%2;
322 if (da_len_bytes > 12) {
323 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200324 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800325 goto out;
326 }
Harald Welte3794e152009-06-12 02:42:11 +0800327 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800328 memcpy(address_lv, smsp, da_len_bytes);
329 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800330 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800331 /* convert to real number */
Harald Welte3794e152009-06-12 02:42:11 +0800332 decode_bcd_number(sms->dest_addr, sizeof(sms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800333
334 smsp += da_len_bytes;
335
336 sms->pid = *smsp++;
337
338 sms->dcs = *smsp++;
339 sms->alphabet = gsm338_get_sms_alphabet(sms->dcs);
340
341 switch (sms->vpf) {
342 case GSM340_TP_VPF_RELATIVE:
343 sms->vp = smsp++;
344 break;
345 case GSM340_TP_VPF_ABSOLUTE:
346 case GSM340_TP_VPF_ENHANCED:
347 sms->vp = smsp;
348 smsp += 7;
349 break;
350 default:
351 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
352 sms->vpf);
353 }
354 sms->ud_len = *smsp++;
355 if (sms->ud_len)
356 sms->user_data = smsp;
357 else
358 sms->user_data = NULL;
359
360 if (sms->ud_len) {
361 switch (sms->alphabet) {
362 case DCS_7BIT_DEFAULT:
363 gsm_7bit_decode(sms->decoded, smsp, sms->ud_len);
364 break;
365 case DCS_8BIT_DATA:
366 case DCS_UCS2:
367 case DCS_NONE:
368 memcpy(sms->decoded, sms->user_data, sms->ud_len);
369 break;
370 }
371 }
372
373 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
374 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
375 "UserData: \"%s\"\n", sms->mti, sms->vpf, sms->msg_ref,
376 sms->pid, sms->dcs, sms->dest_addr, sms->ud_len,
Harald Welte156c5e62009-07-05 14:02:46 +0200377 sms->alphabet == DCS_7BIT_DEFAULT ? sms->decoded :
378 hexdump(sms->user_data, sms->ud_len));
Harald Welte59b04682009-06-10 05:40:52 +0800379
380 dispatch_signal(SS_SMS, 0, sms);
381
Harald Welte156c5e62009-07-05 14:02:46 +0200382 /* now we've filled the 'sms' structure. Go on filling
383 * the gsms structure based on information from the sms */
384
Harald Welte59b04682009-06-10 05:40:52 +0800385 gsms->sender = msg->lchan->subscr;
386 /* FIXME: sender refcount */
387
Harald Welte156c5e62009-07-05 14:02:46 +0200388 gsms->validity_minutes = gsm340_validity_period(sms);
389
Harald Welte59b04682009-06-10 05:40:52 +0800390 /* determine gsms->receiver based on dialled number */
Harald Welte75350412009-07-23 18:46:00 +0200391 gsms->receiver = subscr_get_by_extension(bts->network, sms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800392 if (!gsms->receiver) {
393 rc = 1; /* cause 1: unknown subscriber */
394 goto out;
395 }
396
Harald Welteb78996d2009-07-27 20:11:35 +0200397 if (sms->user_data) {
398 gsms->header_len = sms->ud_len;
Harald Welte156c5e62009-07-05 14:02:46 +0200399 memcpy(gsms->header, sms->user_data, sms->ud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200400 }
Harald Welte156c5e62009-07-05 14:02:46 +0200401
402 if (sms->decoded)
Harald Welte59b04682009-06-10 05:40:52 +0800403 strncpy(gsms->text, sms->decoded, sizeof(gsms->text));
404
405 switch (sms->mti) {
406 case GSM340_SMS_SUBMIT_MS2SC:
407 /* MS is submitting a SMS */
408 rc = gsm340_rx_sms_submit(msg, sms, gsms);
409 break;
410 case GSM340_SMS_COMMAND_MS2SC:
411 case GSM340_SMS_DELIVER_REP_MS2SC:
412 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200413 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800414 break;
415 default:
416 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms->mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200417 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800418 break;
419 }
420
Harald Welte156c5e62009-07-05 14:02:46 +0200421 if (!rc && !gsms->receiver)
422 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
423
Harald Welte59b04682009-06-10 05:40:52 +0800424out:
Harald Weltea8379772009-06-20 22:36:41 +0200425 talloc_free(gsms);
426 talloc_free(sms);
Harald Welte59b04682009-06-10 05:40:52 +0800427
428 return rc;
429}
430
Harald Welteb78996d2009-07-27 20:11:35 +0200431static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800432{
433 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800434
Harald Welte59b04682009-06-10 05:40:52 +0800435 DEBUGP(DSMS, "TX: SMS RP ACK\n");
436
Harald Welteb78996d2009-07-27 20:11:35 +0200437 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800438}
439
Harald Welteb78996d2009-07-27 20:11:35 +0200440static int gsm411_send_rp_error(struct gsm_trans *trans,
441 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800442{
443 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800444
Harald Welte59b04682009-06-10 05:40:52 +0800445 msgb_tv_put(msg, 1, cause);
446
447 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
448
Harald Welteb78996d2009-07-27 20:11:35 +0200449 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800450}
451
452/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200453static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
454 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800455 u_int8_t src_len, u_int8_t *src,
456 u_int8_t dst_len, u_int8_t *dst,
457 u_int8_t tpdu_len, u_int8_t *tpdu)
458{
459 struct gsm48_hdr *gh = msgb_l3(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800460 int rc = 0;
461
462 if (src_len && src)
463 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
464
465 if (!dst_len || !dst || !tpdu_len || !tpdu) {
466 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200467 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200468 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800469 return -EIO;
470 }
471 msg->smsh = tpdu;
472
473 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800474
475 rc = gsm340_rx_tpdu(msg);
476 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200477 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800478 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200479 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800480 else
481 return rc;
482}
483
484/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200485static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
486 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800487{
488 u_int8_t src_len, dst_len, rpud_len;
489 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
490
491 /* in the MO case, this should always be zero length */
492 src_len = rph->data[0];
493 if (src_len)
494 src = &rph->data[1];
495
496 dst_len = rph->data[1+src_len];
497 if (dst_len)
498 dst = &rph->data[1+src_len+1];
499
500 rpud_len = rph->data[1+src_len+1+dst_len];
501 if (rpud_len)
502 rp_ud = &rph->data[1+src_len+1+dst_len+1];
503
Harald Welte156c5e62009-07-05 14:02:46 +0200504 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
505 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200506 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800507 rpud_len, rp_ud);
508}
509
Harald Welte156c5e62009-07-05 14:02:46 +0200510
Harald Welteb78996d2009-07-27 20:11:35 +0200511static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
512 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200513{
514 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
515 * successfully received a SMS. We can now safely mark it as
516 * transmitted */
517
Harald Weltedd62b162009-07-09 23:52:59 +0200518 /* we need to look-up the transaction based on rph->msg_ref to
519 * identify which particular RP_DATA/SMS-submit was ACKed */
520
Harald Welte156c5e62009-07-05 14:02:46 +0200521}
522
Harald Welteb78996d2009-07-27 20:11:35 +0200523static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
524 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200525{
Harald Welteb78996d2009-07-27 20:11:35 +0200526 u_int8_t cause_len = rph->data[0];
527 u_int8_t cause = rph->data[1];
528
Harald Welte156c5e62009-07-05 14:02:46 +0200529 /* Error in response to MT RP_DATA, i.e. the MS did not
530 * successfully receive the SMS. We need to investigate
531 * the cause and take action depending on it */
532
Harald Welteb78996d2009-07-27 20:11:35 +0200533 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
534
Harald Weltedd62b162009-07-09 23:52:59 +0200535 /* we need to look-up the transaction based on rph->msg_ref to
536 * identify which particular RP_DATA/SMS-submit failed */
537
Harald Welteb78996d2009-07-27 20:11:35 +0200538 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200539}
540
Harald Welteb78996d2009-07-27 20:11:35 +0200541static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
542 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200543{
Harald Welteb78996d2009-07-27 20:11:35 +0200544 int rc;
545
Harald Welte156c5e62009-07-05 14:02:46 +0200546 /* MS tells us that it has memory for more SMS, we need
547 * to check if we have any pending messages for it and then
548 * transfer those */
Harald Welteb78996d2009-07-27 20:11:35 +0200549
550 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
551 trans->sms.rp_state = GSM411_RPS_IDLE;
552
553 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200554}
555
Harald Welteb78996d2009-07-27 20:11:35 +0200556static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
557 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800558{
559 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
560 u_int8_t msg_type = rp_data->msg_type & 0x07;
561 int rc = 0;
562
563 switch (msg_type) {
564 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200565 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
566 /* start TR2N and enter 'wait to send RP-ACK state' */
567 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
568 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800569 break;
570 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200571 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
572 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200573 break;
Harald Welte59b04682009-06-10 05:40:52 +0800574 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200575 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
576 /* start TR2N and enter 'wait to send RP-ACK state' */
577 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
578 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
579 break;
580 case GSM411_MT_RP_ERROR_MO:
581 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800582 break;
583 default:
584 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200585 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
586 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800587 break;
588 }
589
590 return rc;
591}
592
Harald Welteb78996d2009-07-27 20:11:35 +0200593/* send CP-ACK to given transaction */
594static int gsm411_tx_cp_ack(struct gsm_trans *trans)
595{
596 struct msgb *msg = gsm411_msgb_alloc();
597
598 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
599}
600
601static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
602{
603 struct msgb *msg = gsm411_msgb_alloc();
604 u_int8_t *causep;
605
606 cause = msgb_put(msg, 1);
607 *causep = cause;
608
609 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
610}
611
612/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte59b04682009-06-10 05:40:52 +0800613int gsm0411_rcv_sms(struct msgb *msg)
614{
615 struct gsm48_hdr *gh = msgb_l3(msg);
616 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200617 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
618 struct gsm_lchan *lchan = msg->lchan;
619 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800620 int rc = 0;
621
Harald Welteb78996d2009-07-27 20:11:35 +0200622 if (!lchan->subscr)
623 return -EIO;
624 /* FIXME: send some error message */
625
626 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
627 transaction_id);
628 if (!trans) {
629 DEBUGP(DSMS, "Unknown transaction ID %x, "
630 "creating new trans\n", transaction_id);
631 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
632 transaction_id, new_callref++);
633 if (!trans) {
634 DEBUGP(DSMS, "No memory for trans\n");
635 /* FIXME: send some error message */
636 return -ENOMEM;
637 }
638 trans->sms.cp_state = GSM411_CPS_IDLE;
639 trans->sms.rp_state = GSM411_RPS_IDLE;
640 trans->sms.is_mt = 0;
641
642 trans->lchan = lchan;
643 use_lchan(lchan);
644 }
645
Harald Welte59b04682009-06-10 05:40:52 +0800646 switch(msg_type) {
647 case GSM411_MT_CP_DATA:
Harald Welteb78996d2009-07-27 20:11:35 +0200648 DEBUGP(DSMS, "RX SMS CP-DATA\n");
649 if (!trans->sms.is_mt) {
650 /* 5.2.3.1.3: MO state exists when SMC has received
651 * CP-DATA, including sending of the assoc. CP-ACK */
652 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
653 }
654
655 rc = gsm411_rx_cp_data(msg, gh, trans);
656 /* Send CP-ACK or CP-ERORR in response */
657 if (rc < 0) {
658 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
659 } else
660 rc = gsm411_tx_cp_ack(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800661 break;
662 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200663 /* previous CP-DATA in this transaction was confirmed */
664 DEBUGP(DSMS, "RX SMS CP-ACK\n");
665 if (!trans->sms.is_mt) {
666 /* 5.2.3.1.3: MO state exists when SMC has received
667 * CP-ACK */
668 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
669 /* FIXME: we have sont one CP-DATA, which was now
670 * acknowledged. Check if we want to transfer more,
671 * i.e. multi-part message */
672 trans->sms.cp_state = GSM411_CPS_IDLE;
673 trans_free(trans);
674 }
Harald Welte59b04682009-06-10 05:40:52 +0800675 break;
676 case GSM411_MT_CP_ERROR:
Harald Welteb78996d2009-07-27 20:11:35 +0200677 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
678 trans->sms.cp_state = GSM411_CPS_IDLE;
679 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800680 break;
681 default:
Harald Welteb78996d2009-07-27 20:11:35 +0200682 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
683 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
684 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800685 break;
686 }
687
Harald Welte59b04682009-06-10 05:40:52 +0800688 return rc;
689}
690
691/* Test TPDU - 25c3 welcome */
692#if 0
693static u_int8_t tpdu_test[] = {
694 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x92, 0x90, 0x32,
695 0x24, 0x40, 0x4D, 0xB2, 0xDA, 0x70, 0xD6, 0x9A, 0x97, 0xE5, 0xF6, 0xF4,
696 0xB8, 0x0C, 0x0A, 0xBB, 0xDD, 0xEF, 0xBA, 0x7B, 0x5C, 0x6E, 0x97, 0xDD,
697 0x74, 0x1D, 0x08, 0xCA, 0x2E, 0x87, 0xE7, 0x65, 0x50, 0x98, 0x4E, 0x2F,
698 0xBB, 0xC9, 0x20, 0x3A, 0xBA, 0x0C, 0x3A, 0x4E, 0x9B, 0x20, 0x7A, 0x98,
699 0xBD, 0x06, 0x85, 0xE9, 0xA0, 0x58, 0x4C, 0x37, 0x83, 0x81, 0xD2, 0x6E,
700 0xD0, 0x34, 0x1C, 0x66, 0x83, 0x62, 0x21, 0x90, 0xAE, 0x95, 0x02
701};
702#else
703/* Test TPDU - ALL YOUR */
704static u_int8_t tpdu_test[] = {
705 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
706 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
707 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
708 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
709};
710#endif
711
712int gsm0411_send_sms(struct gsm_lchan *lchan, struct sms_deliver *sms)
713{
714 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200715 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800716 u_int8_t *data;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200717 u_int8_t msg_ref = 42;
718 u_int8_t trans_id = 23;
Harald Welte59b04682009-06-10 05:40:52 +0800719
720 msg->lchan = lchan;
721
Harald Welteb78996d2009-07-27 20:11:35 +0200722 /* FIXME: allocate trans */
723
Harald Welte7e2f57d2009-07-04 17:39:00 +0200724 /* Hardcode Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800725 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200726 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200727 data[1] = 0x91; /* type of number: international, ISDN */
728 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800729 data[3] = 0x77;
730 data[4] = 0x58;
731 data[5] = 0x10;
732 data[6] = 0x06;
733 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200734
735 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800736 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200737 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800738
739 /* FIXME: Hardcoded for now */
740 //smslen = gsm0411_tpdu_from_sms(tpdu, sms);
741
742 /* RPDU length */
743 data = (u_int8_t *)msgb_put(msg, 1);
744 data[0] = sizeof(tpdu_test);
745
746 data = (u_int8_t *)msgb_put(msg, sizeof(tpdu_test));
747
748 //memcpy(data, tpdu, smslen);
749 memcpy(data, tpdu_test, sizeof(tpdu_test));
750
751 DEBUGP(DSMS, "TX: SMS SUBMIT\n");
752
Harald Welteb78996d2009-07-27 20:11:35 +0200753 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
754 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800755}
Harald Welteb78996d2009-07-27 20:11:35 +0200756
757
758#if 0
759{
760 struct sms_deliver *smsd;
761
762 smsd->mti = GSM340_SMS_DELIVER_SC2MS;
763 smsd->mms = 0; /* FIXME: determine if there are more */
764 smsd->rp = FIXME;
765 smsd->udhi = FIXME;
766 smsd->sri = 1;
767 smsd->oa = FIXME;
768 smsd->pid = FIXME;
769 smsd->dcs = FIXME;
770 smsd->scts = FIXME;
771 smsd->ud_len = FIXME;
772 smsd->ud = FIXME;
773}
774#endif