blob: 8e3c64974da4c4eee47d5d91b86e61dc9e2b6efa [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 Welte68b7df22009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Welte09421d32009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther735cd9e2009-08-10 07:54:02 +020049#include <openbsc/chan_alloc.h>
Harald Welte59b04682009-06-10 05:40:52 +080050
51#define GSM411_ALLOC_SIZE 1024
52#define GSM411_ALLOC_HEADROOM 128
53
Harald Welte09421d32009-08-09 14:59:02 +020054#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
55
Harald Welte (local)8751ee92009-08-15 02:30:58 +020056void *tall_gsms_ctx;
Harald Welteb78996d2009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte (local)cb4715c2009-08-14 10:42:43 +020059static const struct value_string cp_cause_strs[] = {
60 { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
61 { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
62 { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
63 { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
64 { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
65 { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
66 { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
67 "Message incompatible with protocol state" },
68 { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
69 { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
70 { 0, 0 }
71};
72
73static const struct value_string rp_cause_strs[] = {
74 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
75 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
76 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
77 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
78 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
79 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
80 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
81 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
82 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
83 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
84 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
85 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
86 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
87 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
88 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
89 /* valid only for MT */
90 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
91 /* valid for both directions */
92 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
93 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
94 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
95 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
96 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
97 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
98 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
99 { 0, NULL }
100};
101
Harald Welte68b7df22009-08-08 16:03:15 +0200102struct gsm_sms *sms_alloc(void)
103{
104 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
105}
106
107void sms_free(struct gsm_sms *sms)
108{
109 /* drop references to subscriber structure */
110 if (sms->sender)
111 subscr_put(sms->sender);
112 if (sms->receiver)
113 subscr_put(sms->receiver);
114
115 talloc_free(sms);
116}
117
Harald Welte59b04682009-06-10 05:40:52 +0800118struct msgb *gsm411_msgb_alloc(void)
119{
Harald Welte9cfc9352009-06-26 19:39:35 +0200120 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
121 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +0800122}
123
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200124static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800125{
126 if (msg->lchan)
127 msg->trx = msg->lchan->ts->trx;
128
129 msg->l3h = msg->data;
130
Harald Welte68b7df22009-08-08 16:03:15 +0200131 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
132
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200133 return rsl_data_request(msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +0800134}
135
Harald Welte5fa17a22009-08-10 00:24:32 +0200136/* SMC TC1* is expired */
137static void cp_timer_expired(void *data)
138{
139 struct gsm_trans *trans = data;
140
141 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
142 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
143 trans_free(trans);
144}
145
Harald Welte7e2f57d2009-07-04 17:39:00 +0200146/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200147static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
148 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200149{
150 struct gsm48_hdr *gh;
151
152 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
153 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +0200154 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200155 gh->msg_type = msg_type;
156
Harald Welteb78996d2009-07-27 20:11:35 +0200157 /* assign the outgoing lchan */
158 msg->lchan = trans->lchan;
159
160 /* mobile originating */
161 switch (gh->msg_type) {
162 case GSM411_MT_CP_DATA:
163 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Welte09421d32009-08-09 14:59:02 +0200164 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200165 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte5fa17a22009-08-10 00:24:32 +0200166 trans->sms.cp_timer.data = trans;
167 trans->sms.cp_timer.cb = cp_timer_expired;
168 /* 5.3.2.1: Set Timer TC1A */
169 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200170 DEBUGP(DSMS, "TX: CP-DATA ");
171 break;
172 case GSM411_MT_CP_ACK:
173 DEBUGP(DSMS, "TX: CP-ACK ");
174 break;
175 case GSM411_MT_CP_ERROR:
176 DEBUGP(DSMS, "TX: CP-ACK ");
Harald Welteb78996d2009-07-27 20:11:35 +0200177 break;
178 }
179
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200180 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
181
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200182 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200183}
184
185/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200186static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
187 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200188{
189 struct gsm411_rp_hdr *rp;
Harald Weltef2e680b2009-08-10 00:22:19 +0200190 u_int8_t len = msg->len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200191
192 /* GSM 04.11 RP-DATA header */
193 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Weltef2e680b2009-08-10 00:22:19 +0200194 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200195 rp->msg_type = rp_msg_type;
196 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
197
Harald Welteb78996d2009-07-27 20:11:35 +0200198 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200199}
200
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100201/* Turn int into semi-octet representation: 98 => 0x89 */
202static u_int8_t bcdify(u_int8_t value)
203{
204 u_int8_t ret;
Steffen Neubauer94436952009-11-11 23:02:07 +0900205
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100206 ret = value / 10;
207 ret |= (value % 10) << 4;
208
209 return ret;
210}
211
212/* Turn semi-octet representation into int: 0x89 => 98 */
213static u_int8_t unbcdify(u_int8_t value)
214{
215 u_int8_t ret;
216
217 if ((value & 0x0F) > 9 || (value >> 4) > 9)
218 DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
219
220 ret = (value&0x0F)*10;
221 if (ret > 90)
222 ret += value>>4;
223
224 return ret;
225}
226
227/* Generate 03.40 TP-SCTS */
228static void gsm340_gen_scts(u_int8_t *scts, time_t time)
229{
230 struct tm *tm = localtime(&time);
231
232 *scts++ = bcdify(tm->tm_year % 100);
233 *scts++ = bcdify(tm->tm_mon + 1);
234 *scts++ = bcdify(tm->tm_mday);
235 *scts++ = bcdify(tm->tm_hour);
236 *scts++ = bcdify(tm->tm_min);
237 *scts++ = bcdify(tm->tm_sec);
238 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
239}
240
241/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
242static time_t gsm340_scts(u_int8_t *scts)
243{
244 struct tm tm;
245
246 u_int8_t yr = unbcdify(*scts++);
247
248 if (yr <= 80)
249 tm.tm_year = 100 + yr;
250 else
251 tm.tm_year = yr;
252 tm.tm_mon = unbcdify(*scts++) - 1;
253 tm.tm_mday = unbcdify(*scts++);
254 tm.tm_hour = unbcdify(*scts++);
255 tm.tm_min = unbcdify(*scts++);
256 tm.tm_sec = unbcdify(*scts++);
257 /* according to gsm 03.40 time zone is
258 "expressed in quarters of an hour" */
259 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
260
261 return mktime(&tm);
262}
263
264/* Return the default validity period in minutes */
265static unsigned long gsm340_vp_default(void)
266{
267 unsigned long minutes;
268 /* Default validity: two days */
269 minutes = 24 * 60 * 2;
270 return minutes;
271}
272
273/* Decode validity period format 'relative' */
274static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
275{
276 /* Chapter 9.2.3.12.1 */
277 u_int8_t vp;
278 unsigned long minutes;
279
280 vp = *(sms_vp);
281 if (vp <= 143)
282 minutes = vp + 1 * 5;
283 else if (vp <= 167)
284 minutes = 12*60 + (vp-143) * 30;
285 else if (vp <= 196)
286 minutes = vp-166 * 60 * 24;
287 else
288 minutes = vp-192 * 60 * 24 * 7;
289 return minutes;
290}
291
292/* Decode validity period format 'absolute' */
293static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
294{
295 /* Chapter 9.2.3.12.2 */
296 time_t expires, now;
297 unsigned long minutes;
298
299 expires = gsm340_scts(sms_vp);
300 now = mktime(gmtime(NULL));
301 if (expires <= now)
302 minutes = 0;
303 else
304 minutes = (expires-now)/60;
305 return minutes;
306}
307
308/* Decode validity period format 'relative in integer representation' */
309static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800310{
311 u_int8_t vp;
312 unsigned long minutes;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100313 vp = *(sms_vp);
314 if (vp == 0) {
315 DEBUGP(DSMS, "reserved relative_integer validity period\n");
316 return gsm340_vp_default();
317 }
318 minutes = vp/60;
319 return minutes;
320}
321
322/* Decode validity period format 'relative in semi-octet representation' */
323static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
324{
325 unsigned long minutes;
326 minutes = unbcdify(*sms_vp++)*60; /* hours */
327 minutes += unbcdify(*sms_vp++); /* minutes */
328 minutes += unbcdify(*sms_vp++)/60; /* seconds */
329 return minutes;
330}
331
332/* decode validity period. return minutes */
333static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
334{
335 u_int8_t fi; /* functionality indicator */
Harald Welte59b04682009-06-10 05:40:52 +0800336
Harald Welte68b7df22009-08-08 16:03:15 +0200337 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800338 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100339 return gsm340_vp_relative(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800340 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100341 return gsm340_vp_absolute(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800342 case GSM340_TP_VPF_ENHANCED:
343 /* Chapter 9.2.3.12.3 */
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100344 fi = *sms_vp++;
345 /* ignore additional fi */
346 if (fi & (1<<7)) sms_vp++;
347 /* read validity period format */
348 switch (fi & 0b111) {
349 case 0b000:
350 return gsm340_vp_default(); /* no vpf specified */
351 case 0b001:
352 return gsm340_vp_relative(sms_vp);
353 case 0b010:
354 return gsm340_vp_relative_integer(sms_vp);
355 case 0b011:
356 return gsm340_vp_relative_semioctet(sms_vp);
357 default:
358 /* The GSM spec says that the SC should reject any
359 unsupported and/or undefined values. FIXME */
360 DEBUGP(DSMS, "Reserved enhanced validity period format\n");
361 return gsm340_vp_default();
362 }
Daniel Willmann426bb162009-08-13 03:40:49 +0200363 case GSM340_TP_VPF_NONE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100364 default:
365 return gsm340_vp_default();
Harald Welte59b04682009-06-10 05:40:52 +0800366 }
Harald Welte59b04682009-06-10 05:40:52 +0800367}
368
369/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
370enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
371{
372 u_int8_t cgbits = dcs >> 4;
373 enum sms_alphabet alpha = DCS_NONE;
374
375 if ((cgbits & 0xc) == 0) {
376 if (cgbits & 2)
377 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
378
Daniel Willmannf2861022009-08-15 03:01:17 +0200379 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800380 case 0:
381 alpha = DCS_7BIT_DEFAULT;
382 break;
383 case 1:
384 alpha = DCS_8BIT_DATA;
385 break;
386 case 2:
387 alpha = DCS_UCS2;
388 break;
389 }
390 } else if (cgbits == 0xc || cgbits == 0xd)
391 alpha = DCS_7BIT_DEFAULT;
392 else if (cgbits == 0xe)
393 alpha = DCS_UCS2;
394 else if (cgbits == 0xf) {
395 if (dcs & 4)
396 alpha = DCS_8BIT_DATA;
397 else
398 alpha = DCS_7BIT_DEFAULT;
399 }
400
401 return alpha;
402}
403
Harald Welte68b7df22009-08-08 16:03:15 +0200404static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800405{
406 if (db_sms_store(gsms) != 0) {
407 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200408 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800409 }
Harald Welte68b7df22009-08-08 16:03:15 +0200410 /* dispatch a signal to tell higher level about it */
411 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200412 /* try delivering the SMS right now */
413 //gsm411_send_sms_subscr(gsms->receiver, gsms);
414
Harald Welte59b04682009-06-10 05:40:52 +0800415 return 0;
416}
417
Harald Welte68b7df22009-08-08 16:03:15 +0200418/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
419static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
420 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200421{
Harald Welte68b7df22009-08-08 16:03:15 +0200422 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200423
Harald Welte68b7df22009-08-08 16:03:15 +0200424 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
425
426 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
427
428 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
429 oa[0] = strlen(subscr->extension) & 0xff;
430
431 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200432}
433
Harald Welte68b7df22009-08-08 16:03:15 +0200434/* generate a msgb containing a TPDU derived from struct gsm_sms,
435 * returns total size of TPDU */
436static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200437{
Harald Welteb78996d2009-07-27 20:11:35 +0200438 u_int8_t *smsp;
439 u_int8_t oa[12]; /* max len per 03.40 */
440 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200441 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200442 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200443
444 /* generate first octet with masked bits */
445 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200446 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200447 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200448 /* TP-MMS (more messages to send) */
449 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200450 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200451 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200452 if (sms->status_rep_req)
453 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200454 /* TP-UDHI (indicating TP-UD contains a header) */
455 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200456 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200457#if 0
458 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200459 if (sms->
460 *smsp |= 0x80;
461#endif
462
463 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200464 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200465 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200466 memcpy(smsp, oa, oa_len);
467
468 /* generate TP-PID */
469 smsp = msgb_put(msg, 1);
470 *smsp = sms->protocol_id;
471
472 /* generate TP-DCS */
473 smsp = msgb_put(msg, 1);
474 *smsp = sms->data_coding_scheme;
475
476 /* generate TP-SCTS */
477 smsp = msgb_put(msg, 7);
478 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200479
Harald Welteb78996d2009-07-27 20:11:35 +0200480 /* generate TP-UDL */
481 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200482 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200483
484 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200485 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
486 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200487 octet_len = sms->user_data_len*7/8;
488 if (sms->user_data_len*7%8 != 0)
489 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200490 /* Warning, user_data_len indicates the amount of septets
491 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200492 smsp = msgb_put(msg, octet_len);
493 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200494 break;
495 case DCS_UCS2:
496 case DCS_8BIT_DATA:
497 smsp = msgb_put(msg, sms->user_data_len);
498 memcpy(smsp, sms->user_data, sms->user_data_len);
499 break;
500 default:
501 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
502 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200503 }
Harald Welteb78996d2009-07-27 20:11:35 +0200504
Harald Welte68b7df22009-08-08 16:03:15 +0200505 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200506}
507
Harald Welte156c5e62009-07-05 14:02:46 +0200508/* process an incoming TPDU (called from RP-DATA)
509 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800510static int gsm340_rx_tpdu(struct msgb *msg)
511{
Harald Welte75350412009-07-23 18:46:00 +0200512 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800513 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800514 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200515 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
516 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800517 u_int8_t da_len_bytes;
518 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
519 int rc = 0;
520
Harald Welte68b7df22009-08-08 16:03:15 +0200521 gsms = sms_alloc();
522 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200523 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800524
525 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200526 sms_mti = *smsp & 0x03;
527 sms_mms = !!(*smsp & 0x04);
528 sms_vpf = (*smsp & 0x18) >> 3;
529 gsms->status_rep_req = (*smsp & 0x20);
530 gsms->ud_hdr_ind = (*smsp & 0x40);
531 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800532
533 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200534 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800535
536 /* length in bytes of the destination address */
537 da_len_bytes = 2 + *smsp/2 + *smsp%2;
538 if (da_len_bytes > 12) {
539 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200540 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800541 goto out;
542 }
Harald Welte3794e152009-06-12 02:42:11 +0800543 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800544 memcpy(address_lv, smsp, da_len_bytes);
545 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800546 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800547 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200548 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800549 smsp += da_len_bytes;
550
Harald Welte68b7df22009-08-08 16:03:15 +0200551 gsms->protocol_id = *smsp++;
552 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800553
Harald Welte68b7df22009-08-08 16:03:15 +0200554 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800555
Harald Welte68b7df22009-08-08 16:03:15 +0200556 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800557 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200558 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800559 break;
560 case GSM340_TP_VPF_ABSOLUTE:
561 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200562 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100563 /* the additional functionality indicator... */
564 if (*smsp & (1<<7)) smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800565 smsp += 7;
566 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200567 case GSM340_TP_VPF_NONE:
568 sms_vp = 0;
569 break;
Harald Welte59b04682009-06-10 05:40:52 +0800570 default:
571 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200572 sms_vpf);
573 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800574 }
Harald Welte68b7df22009-08-08 16:03:15 +0200575 gsms->user_data_len = *smsp++;
576 if (gsms->user_data_len) {
577 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800578
Harald Welte68b7df22009-08-08 16:03:15 +0200579 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800580 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200581 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800582 break;
583 case DCS_8BIT_DATA:
584 case DCS_UCS2:
585 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800586 break;
587 }
588 }
589
590 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
591 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte68b7df22009-08-08 16:03:15 +0200592 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
593 gsms->protocol_id, gsms->data_coding_scheme,
594 gsms->dest_addr, gsms->user_data_len,
595 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
596 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800597
Harald Welte68b7df22009-08-08 16:03:15 +0200598 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800599
Harald Welte68b7df22009-08-08 16:03:15 +0200600 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200601
Harald Welte68b7df22009-08-08 16:03:15 +0200602 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200603
Harald Welte59b04682009-06-10 05:40:52 +0800604 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200605 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800606 if (!gsms->receiver) {
607 rc = 1; /* cause 1: unknown subscriber */
608 goto out;
609 }
610
Harald Welte68b7df22009-08-08 16:03:15 +0200611 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800612 case GSM340_SMS_SUBMIT_MS2SC:
613 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200614 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800615 break;
616 case GSM340_SMS_COMMAND_MS2SC:
617 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200618 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200619 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800620 break;
621 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200622 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200623 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800624 break;
625 }
626
Harald Welte156c5e62009-07-05 14:02:46 +0200627 if (!rc && !gsms->receiver)
628 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
629
Harald Welte59b04682009-06-10 05:40:52 +0800630out:
Harald Welte68b7df22009-08-08 16:03:15 +0200631 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800632
633 return rc;
634}
635
Harald Welteb78996d2009-07-27 20:11:35 +0200636static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800637{
638 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800639
Harald Welte59b04682009-06-10 05:40:52 +0800640 DEBUGP(DSMS, "TX: SMS RP ACK\n");
641
Harald Welteb78996d2009-07-27 20:11:35 +0200642 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800643}
644
Harald Welteb78996d2009-07-27 20:11:35 +0200645static int gsm411_send_rp_error(struct gsm_trans *trans,
646 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800647{
648 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800649
Harald Welte59b04682009-06-10 05:40:52 +0800650 msgb_tv_put(msg, 1, cause);
651
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200652 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
653 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800654
Harald Welteb78996d2009-07-27 20:11:35 +0200655 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800656}
657
658/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200659static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
660 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800661 u_int8_t src_len, u_int8_t *src,
662 u_int8_t dst_len, u_int8_t *dst,
663 u_int8_t tpdu_len, u_int8_t *tpdu)
664{
Harald Welte59b04682009-06-10 05:40:52 +0800665 int rc = 0;
666
667 if (src_len && src)
668 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
669
670 if (!dst_len || !dst || !tpdu_len || !tpdu) {
671 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200672 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200673 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800674 return -EIO;
675 }
676 msg->smsh = tpdu;
677
678 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800679
680 rc = gsm340_rx_tpdu(msg);
681 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200682 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800683 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200684 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800685 else
686 return rc;
687}
688
689/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200690static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
691 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800692{
693 u_int8_t src_len, dst_len, rpud_len;
694 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
695
696 /* in the MO case, this should always be zero length */
697 src_len = rph->data[0];
698 if (src_len)
699 src = &rph->data[1];
700
701 dst_len = rph->data[1+src_len];
702 if (dst_len)
703 dst = &rph->data[1+src_len+1];
704
705 rpud_len = rph->data[1+src_len+1+dst_len];
706 if (rpud_len)
707 rp_ud = &rph->data[1+src_len+1+dst_len+1];
708
Harald Welte156c5e62009-07-05 14:02:46 +0200709 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
710 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200711 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800712 rpud_len, rp_ud);
713}
714
Harald Welte09421d32009-08-09 14:59:02 +0200715/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200716static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
717 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200718{
Harald Welte68b7df22009-08-08 16:03:15 +0200719 struct gsm_sms *sms = trans->sms.sms;
720
Harald Welte156c5e62009-07-05 14:02:46 +0200721 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
722 * successfully received a SMS. We can now safely mark it as
723 * transmitted */
724
Harald Welte09421d32009-08-09 14:59:02 +0200725 if (!trans->sms.is_mt) {
726 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
727 return gsm411_send_rp_error(trans, rph->msg_ref,
728 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
729 }
Harald Weltedd62b162009-07-09 23:52:59 +0200730
Harald Welte68b7df22009-08-08 16:03:15 +0200731 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200732 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
733 return gsm411_send_rp_error(trans, rph->msg_ref,
734 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200735 }
736
737 /* mark this SMS as sent in database */
738 db_sms_mark_sent(sms);
739
740 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
741
742 sms_free(sms);
743 trans->sms.sms = NULL;
744
Sylvain Munaut4dd65ae2009-09-27 11:16:22 +0200745 /* free the transaction here */
746 trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200747
748 /* check for more messages for this subscriber */
749 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
750 if (sms)
751 gsm411_send_sms_lchan(msg->lchan, sms);
752 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200753 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200754
755 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200756}
757
Harald Welteb78996d2009-07-27 20:11:35 +0200758static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
759 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200760{
Harald Welte68b7df22009-08-08 16:03:15 +0200761 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200762 u_int8_t cause_len = rph->data[0];
763 u_int8_t cause = rph->data[1];
764
Harald Welte156c5e62009-07-05 14:02:46 +0200765 /* Error in response to MT RP_DATA, i.e. the MS did not
766 * successfully receive the SMS. We need to investigate
767 * the cause and take action depending on it */
768
Holger Hans Peter Freyther80e5ccc2009-10-22 15:40:33 +0200769 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200770 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200771
Harald Welte09421d32009-08-09 14:59:02 +0200772 if (!trans->sms.is_mt) {
773 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200774#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200775 return gsm411_send_rp_error(trans, rph->msg_ref,
776 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200777#endif
Harald Welte09421d32009-08-09 14:59:02 +0200778 }
Harald Weltedd62b162009-07-09 23:52:59 +0200779
Harald Welte68b7df22009-08-08 16:03:15 +0200780 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200781 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200782 return -EINVAL;
783#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200784 return gsm411_send_rp_error(trans, rph->msg_ref,
785 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200786#endif
Harald Welte09421d32009-08-09 14:59:02 +0200787 }
788
789 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
790 /* MS has not enough memory to store the message. We need
791 * to store this in our database and wati for a SMMA message */
792 /* FIXME */
793 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200794 }
795
796 sms_free(sms);
797 trans->sms.sms = NULL;
798
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200799 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200800
Harald Welteb78996d2009-07-27 20:11:35 +0200801 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200802}
803
Harald Welteb78996d2009-07-27 20:11:35 +0200804static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
805 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200806{
Harald Weltefc01b242009-08-09 19:07:41 +0200807 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200808 int rc;
809
Harald Weltefc01b242009-08-09 19:07:41 +0200810 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
811 trans->sms.rp_state = GSM411_RPS_IDLE;
812
Harald Welte156c5e62009-07-05 14:02:46 +0200813 /* MS tells us that it has memory for more SMS, we need
814 * to check if we have any pending messages for it and then
815 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200816 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200817
Harald Weltefc01b242009-08-09 19:07:41 +0200818 /* check for more messages for this subscriber */
819 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
820 if (sms)
821 gsm411_send_sms_lchan(msg->lchan, sms);
822 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200823 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200824
825 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200826}
827
Harald Welteb78996d2009-07-27 20:11:35 +0200828static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
829 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800830{
831 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
832 u_int8_t msg_type = rp_data->msg_type & 0x07;
833 int rc = 0;
834
835 switch (msg_type) {
836 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200837 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
838 /* start TR2N and enter 'wait to send RP-ACK state' */
839 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
840 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800841 break;
842 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200843 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
844 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200845 break;
Harald Welte59b04682009-06-10 05:40:52 +0800846 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200847 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
848 /* start TR2N and enter 'wait to send RP-ACK state' */
849 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
850 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
851 break;
852 case GSM411_MT_RP_ERROR_MO:
853 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800854 break;
855 default:
856 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200857 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
858 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800859 break;
860 }
861
862 return rc;
863}
864
Harald Welteb78996d2009-07-27 20:11:35 +0200865/* send CP-ACK to given transaction */
866static int gsm411_tx_cp_ack(struct gsm_trans *trans)
867{
868 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200869 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200870
Harald Weltefc01b242009-08-09 19:07:41 +0200871 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
872
873 if (trans->sms.is_mt) {
874 /* If this is a MT SMS DELIVER, we can clear transaction here */
875 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200876 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200877 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200878
879 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200880}
881
882static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
883{
884 struct msgb *msg = gsm411_msgb_alloc();
885 u_int8_t *causep;
886
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200887 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
888 get_value_string(cp_cause_strs, cause));
889
Harald Welte68b7df22009-08-08 16:03:15 +0200890 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200891 *causep = cause;
892
893 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
894}
895
896/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200897int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800898{
899 struct gsm48_hdr *gh = msgb_l3(msg);
900 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200901 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
902 struct gsm_lchan *lchan = msg->lchan;
903 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800904 int rc = 0;
905
Harald Welteb78996d2009-07-27 20:11:35 +0200906 if (!lchan->subscr)
907 return -EIO;
908 /* FIXME: send some error message */
909
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200910 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Welteb78996d2009-07-27 20:11:35 +0200911 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
912 transaction_id);
913 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200914 DEBUGPC(DSMS, "(unknown) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200915 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
916 transaction_id, new_callref++);
917 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200918 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200919 /* FIXME: send some error message */
920 return -ENOMEM;
921 }
922 trans->sms.cp_state = GSM411_CPS_IDLE;
923 trans->sms.rp_state = GSM411_RPS_IDLE;
924 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200925 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200926
927 trans->lchan = lchan;
928 use_lchan(lchan);
929 }
930
Harald Welte59b04682009-06-10 05:40:52 +0800931 switch(msg_type) {
932 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200933 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200934 /* 5.2.3.1.3: MO state exists when SMC has received
935 * CP-DATA, including sending of the assoc. CP-ACK */
936 /* 5.2.3.2.4: MT state exists when SMC has received
937 * CP-DATA, including sending of the assoc. CP-ACK */
938 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200939
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200940 /* SMC instance acknowledges the CP-DATA frame */
941 gsm411_tx_cp_ack(trans);
942
Harald Welteb78996d2009-07-27 20:11:35 +0200943 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200944#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200945 /* Send CP-ACK or CP-ERORR in response */
946 if (rc < 0) {
947 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
948 } else
949 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200950#endif
Harald Welte59b04682009-06-10 05:40:52 +0800951 break;
952 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200953 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200954 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200955 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
956 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
957 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +0200958 /* Stop TC1* after CP-ACK has been received */
959 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +0200960
Harald Welteb78996d2009-07-27 20:11:35 +0200961 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200962 /* FIXME: we have sont one CP-DATA, which was now
963 * acknowledged. Check if we want to transfer more,
964 * i.e. multi-part message */
965 trans->sms.cp_state = GSM411_CPS_IDLE;
966 trans_free(trans);
967 }
Harald Welte59b04682009-06-10 05:40:52 +0800968 break;
969 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200970 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
971 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +0200972 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +0200973 trans->sms.cp_state = GSM411_CPS_IDLE;
974 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800975 break;
976 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200977 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200978 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200979 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200980 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800981 break;
982 }
983
Harald Welte59b04682009-06-10 05:40:52 +0800984 return rc;
985}
986
Harald Welte59b04682009-06-10 05:40:52 +0800987#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800988/* Test TPDU - ALL YOUR */
989static u_int8_t tpdu_test[] = {
990 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
991 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
992 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
993 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
994};
995#endif
996
Harald Weltefc01b242009-08-09 19:07:41 +0200997/* Take a SMS in gsm_sms structure and send it through an already
998 * existing lchan. We also assume that the caller ensured this lchan already
999 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +02001000int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +08001001{
1002 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +02001003 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +02001004 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001005 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +02001006 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +02001007 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001008
Harald Weltefc01b242009-08-09 19:07:41 +02001009 transaction_id = 4; /* FIXME: we always use 4 for now */
1010
Harald Welte59b04682009-06-10 05:40:52 +08001011 msg->lchan = lchan;
1012
Harald Welte68b7df22009-08-08 16:03:15 +02001013 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +02001014
Harald Welte68b7df22009-08-08 16:03:15 +02001015 /* FIXME: allocate transaction with message reference */
1016 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
1017 transaction_id, new_callref++);
1018 if (!trans) {
1019 DEBUGP(DSMS, "No memory for trans\n");
1020 /* FIXME: send some error message */
1021 return -ENOMEM;
1022 }
1023 trans->sms.cp_state = GSM411_CPS_IDLE;
1024 trans->sms.rp_state = GSM411_RPS_IDLE;
1025 trans->sms.is_mt = 1;
1026 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001027 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +02001028
1029 trans->lchan = lchan;
1030 use_lchan(lchan);
1031
1032 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +08001033 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001034 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +02001035 data[1] = 0x91; /* type of number: international, ISDN */
1036 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +08001037 data[3] = 0x77;
1038 data[4] = 0x58;
1039 data[5] = 0x10;
1040 data[6] = 0x06;
1041 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001042
1043 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +08001044 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001045 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +08001046
Harald Welte68b7df22009-08-08 16:03:15 +02001047 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1048 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +08001049
Harald Welte68b7df22009-08-08 16:03:15 +02001050#if 1
1051 /* generate the 03.40 TPDU */
1052 rc = gsm340_gen_tpdu(msg, sms);
1053 if (rc < 0) {
1054 msgb_free(msg);
1055 return rc;
1056 }
Harald Welte59b04682009-06-10 05:40:52 +08001057
Harald Welte68b7df22009-08-08 16:03:15 +02001058 *rp_ud_len = rc;
1059#else
1060 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +08001061 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +02001062 *rp_ud_len = sizeof(tpdu_test);
1063#endif
Harald Welte59b04682009-06-10 05:40:52 +08001064
Harald Welte68b7df22009-08-08 16:03:15 +02001065 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001066
Harald Welteb78996d2009-07-27 20:11:35 +02001067 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1068 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001069}
Harald Welteb78996d2009-07-27 20:11:35 +02001070
Harald Weltefc01b242009-08-09 19:07:41 +02001071/* RLL SAPI3 establish callback. Now we have a RLL connection and
1072 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001073static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1074 void *_sms, enum bsc_rllr_ind type)
1075{
1076 struct gsm_sms *sms = _sms;
1077
1078 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1079 lchan, link_id, sms, type);
1080
1081 switch (type) {
1082 case BSC_RLLR_IND_EST_CONF:
1083 gsm411_send_sms_lchan(lchan, sms);
1084 break;
1085 case BSC_RLLR_IND_REL_IND:
1086 case BSC_RLLR_IND_ERR_IND:
1087 case BSC_RLLR_IND_TIMEOUT:
1088 sms_free(sms);
1089 break;
1090 }
1091}
1092
Harald Weltefc01b242009-08-09 19:07:41 +02001093/* paging callback. Here we get called if paging a subscriber has
1094 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001095static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1096 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001097{
Harald Welte68b7df22009-08-08 16:03:15 +02001098 struct gsm_lchan *lchan = _lchan;
1099 struct gsm_sms *sms = _sms;
1100 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001101
Harald Welte68b7df22009-08-08 16:03:15 +02001102 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1103 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1104
1105 if (hooknum != GSM_HOOK_RR_PAGING)
1106 return -EINVAL;
1107
1108 switch (event) {
1109 case GSM_PAGING_SUCCEEDED:
1110 /* Paging aborted without lchan ?!? */
1111 if (!lchan) {
1112 sms_free(sms);
1113 rc = -EIO;
1114 break;
1115 }
Harald Weltefc01b242009-08-09 19:07:41 +02001116 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001117 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001118 break;
1119 case GSM_PAGING_EXPIRED:
1120 sms_free(sms);
1121 rc = -ETIMEDOUT;
1122 break;
1123 default:
1124 rc = -EINVAL;
1125 break;
1126 }
1127
1128 return rc;
1129}
1130
Harald Weltefc01b242009-08-09 19:07:41 +02001131/* high-level function to send a SMS to a given subscriber. The function
1132 * will take care of paging the subscriber, establishing the RLL SAPI3
1133 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001134int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1135 struct gsm_sms *sms)
1136{
Harald Weltefc01b242009-08-09 19:07:41 +02001137 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001138 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001139
Harald Welte68b7df22009-08-08 16:03:15 +02001140 /* check if we already have an open lchan to the subscriber.
1141 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001142 lchan = lchan_for_subscr(subscr);
1143 if (lchan)
1144 return rll_establish(lchan, UM_SAPI_SMS,
1145 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001146
1147 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001148 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1149 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001150 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001151 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001152
1153 return 0;
1154}
Harald Welte5b359d82009-07-28 00:44:49 +02001155
Harald Weltefc01b242009-08-09 19:07:41 +02001156static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1157 void *handler_data, void *signal_data)
1158{
1159 struct gsm_subscriber *subscr;
1160 struct gsm_lchan *lchan;
1161 struct gsm_sms *sms;
1162
1163 switch (signal) {
1164 case S_SUBSCR_ATTACHED:
1165 /* A subscriber has attached. Check if there are
1166 * any pending SMS for him to be delivered */
1167 subscr = signal_data;
1168 lchan = lchan_for_subscr(subscr);
1169 if (!lchan)
1170 break;
1171 sms = db_sms_get_unsent_for_subscr(subscr);
1172 if (!sms)
1173 break;
1174 /* Establish a SAPI3 RLL connection for SMS */
1175 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1176 break;
1177 default:
1178 break;
1179 }
1180 return 0;
1181}
1182
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001183void _gsm411_sms_trans_free(struct gsm_trans *trans)
1184{
1185 bsc_del_timer(&trans->sms.cp_timer);
1186}
1187
Harald Welte932e20d2009-07-28 00:41:45 +02001188static __attribute__((constructor)) void on_dso_load_sms(void)
1189{
Harald Weltefc01b242009-08-09 19:07:41 +02001190 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001191}