blob: 31526e979f409cc167ce68477f1a4e207a1d883a [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:
Sylvain Munaut163a24a2009-12-18 18:28:07 +0100176 DEBUGP(DSMS, "TX: CP-ERROR ");
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;
Steffen Neubauere5e0eb72009-11-26 23:38:41 +0100221 ret += value>>4;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100222
223 return ret;
224}
225
226/* Generate 03.40 TP-SCTS */
227static void gsm340_gen_scts(u_int8_t *scts, time_t time)
228{
229 struct tm *tm = localtime(&time);
230
231 *scts++ = bcdify(tm->tm_year % 100);
232 *scts++ = bcdify(tm->tm_mon + 1);
233 *scts++ = bcdify(tm->tm_mday);
234 *scts++ = bcdify(tm->tm_hour);
235 *scts++ = bcdify(tm->tm_min);
236 *scts++ = bcdify(tm->tm_sec);
237 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
238}
239
240/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
241static time_t gsm340_scts(u_int8_t *scts)
242{
243 struct tm tm;
244
245 u_int8_t yr = unbcdify(*scts++);
246
247 if (yr <= 80)
248 tm.tm_year = 100 + yr;
249 else
250 tm.tm_year = yr;
251 tm.tm_mon = unbcdify(*scts++) - 1;
252 tm.tm_mday = unbcdify(*scts++);
253 tm.tm_hour = unbcdify(*scts++);
254 tm.tm_min = unbcdify(*scts++);
255 tm.tm_sec = unbcdify(*scts++);
256 /* according to gsm 03.40 time zone is
257 "expressed in quarters of an hour" */
258 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
259
260 return mktime(&tm);
261}
262
263/* Return the default validity period in minutes */
264static unsigned long gsm340_vp_default(void)
265{
266 unsigned long minutes;
267 /* Default validity: two days */
268 minutes = 24 * 60 * 2;
269 return minutes;
270}
271
272/* Decode validity period format 'relative' */
273static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
274{
275 /* Chapter 9.2.3.12.1 */
276 u_int8_t vp;
277 unsigned long minutes;
278
279 vp = *(sms_vp);
280 if (vp <= 143)
281 minutes = vp + 1 * 5;
282 else if (vp <= 167)
283 minutes = 12*60 + (vp-143) * 30;
284 else if (vp <= 196)
285 minutes = vp-166 * 60 * 24;
286 else
287 minutes = vp-192 * 60 * 24 * 7;
288 return minutes;
289}
290
291/* Decode validity period format 'absolute' */
292static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
293{
294 /* Chapter 9.2.3.12.2 */
295 time_t expires, now;
296 unsigned long minutes;
297
298 expires = gsm340_scts(sms_vp);
299 now = mktime(gmtime(NULL));
300 if (expires <= now)
301 minutes = 0;
302 else
303 minutes = (expires-now)/60;
304 return minutes;
305}
306
307/* Decode validity period format 'relative in integer representation' */
308static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800309{
310 u_int8_t vp;
311 unsigned long minutes;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100312 vp = *(sms_vp);
313 if (vp == 0) {
314 DEBUGP(DSMS, "reserved relative_integer validity period\n");
315 return gsm340_vp_default();
316 }
317 minutes = vp/60;
318 return minutes;
319}
320
321/* Decode validity period format 'relative in semi-octet representation' */
322static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
323{
324 unsigned long minutes;
325 minutes = unbcdify(*sms_vp++)*60; /* hours */
326 minutes += unbcdify(*sms_vp++); /* minutes */
327 minutes += unbcdify(*sms_vp++)/60; /* seconds */
328 return minutes;
329}
330
331/* decode validity period. return minutes */
332static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
333{
334 u_int8_t fi; /* functionality indicator */
Harald Welte59b04682009-06-10 05:40:52 +0800335
Harald Welte68b7df22009-08-08 16:03:15 +0200336 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800337 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100338 return gsm340_vp_relative(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800339 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100340 return gsm340_vp_absolute(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800341 case GSM340_TP_VPF_ENHANCED:
342 /* Chapter 9.2.3.12.3 */
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100343 fi = *sms_vp++;
344 /* ignore additional fi */
345 if (fi & (1<<7)) sms_vp++;
346 /* read validity period format */
347 switch (fi & 0b111) {
348 case 0b000:
349 return gsm340_vp_default(); /* no vpf specified */
350 case 0b001:
351 return gsm340_vp_relative(sms_vp);
352 case 0b010:
353 return gsm340_vp_relative_integer(sms_vp);
354 case 0b011:
355 return gsm340_vp_relative_semioctet(sms_vp);
356 default:
357 /* The GSM spec says that the SC should reject any
358 unsupported and/or undefined values. FIXME */
359 DEBUGP(DSMS, "Reserved enhanced validity period format\n");
360 return gsm340_vp_default();
361 }
Daniel Willmann426bb162009-08-13 03:40:49 +0200362 case GSM340_TP_VPF_NONE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100363 default:
364 return gsm340_vp_default();
Harald Welte59b04682009-06-10 05:40:52 +0800365 }
Harald Welte59b04682009-06-10 05:40:52 +0800366}
367
368/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
369enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
370{
371 u_int8_t cgbits = dcs >> 4;
372 enum sms_alphabet alpha = DCS_NONE;
373
374 if ((cgbits & 0xc) == 0) {
375 if (cgbits & 2)
376 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
377
Daniel Willmannf2861022009-08-15 03:01:17 +0200378 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800379 case 0:
380 alpha = DCS_7BIT_DEFAULT;
381 break;
382 case 1:
383 alpha = DCS_8BIT_DATA;
384 break;
385 case 2:
386 alpha = DCS_UCS2;
387 break;
388 }
389 } else if (cgbits == 0xc || cgbits == 0xd)
390 alpha = DCS_7BIT_DEFAULT;
391 else if (cgbits == 0xe)
392 alpha = DCS_UCS2;
393 else if (cgbits == 0xf) {
394 if (dcs & 4)
395 alpha = DCS_8BIT_DATA;
396 else
397 alpha = DCS_7BIT_DEFAULT;
398 }
399
400 return alpha;
401}
402
Harald Welte68b7df22009-08-08 16:03:15 +0200403static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800404{
405 if (db_sms_store(gsms) != 0) {
406 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200407 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800408 }
Harald Welte68b7df22009-08-08 16:03:15 +0200409 /* dispatch a signal to tell higher level about it */
410 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200411 /* try delivering the SMS right now */
412 //gsm411_send_sms_subscr(gsms->receiver, gsms);
413
Harald Welte59b04682009-06-10 05:40:52 +0800414 return 0;
415}
416
Harald Welte68b7df22009-08-08 16:03:15 +0200417/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
418static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
419 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200420{
Harald Welte68b7df22009-08-08 16:03:15 +0200421 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200422
Harald Welte68b7df22009-08-08 16:03:15 +0200423 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
424
425 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
426
427 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
428 oa[0] = strlen(subscr->extension) & 0xff;
429
430 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200431}
432
Harald Welte68b7df22009-08-08 16:03:15 +0200433/* generate a msgb containing a TPDU derived from struct gsm_sms,
434 * returns total size of TPDU */
435static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200436{
Harald Welteb78996d2009-07-27 20:11:35 +0200437 u_int8_t *smsp;
438 u_int8_t oa[12]; /* max len per 03.40 */
439 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200440 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200441 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200442
443 /* generate first octet with masked bits */
444 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200445 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200446 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200447 /* TP-MMS (more messages to send) */
448 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200449 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200450 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200451 if (sms->status_rep_req)
452 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200453 /* TP-UDHI (indicating TP-UD contains a header) */
454 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200455 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200456#if 0
457 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200458 if (sms->
459 *smsp |= 0x80;
460#endif
461
462 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200463 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200464 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200465 memcpy(smsp, oa, oa_len);
466
467 /* generate TP-PID */
468 smsp = msgb_put(msg, 1);
469 *smsp = sms->protocol_id;
470
471 /* generate TP-DCS */
472 smsp = msgb_put(msg, 1);
473 *smsp = sms->data_coding_scheme;
474
475 /* generate TP-SCTS */
476 smsp = msgb_put(msg, 7);
477 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200478
Harald Welteb78996d2009-07-27 20:11:35 +0200479 /* generate TP-UDL */
480 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200481 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200482
483 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200484 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
485 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200486 octet_len = sms->user_data_len*7/8;
487 if (sms->user_data_len*7%8 != 0)
488 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200489 /* Warning, user_data_len indicates the amount of septets
490 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200491 smsp = msgb_put(msg, octet_len);
492 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200493 break;
494 case DCS_UCS2:
495 case DCS_8BIT_DATA:
496 smsp = msgb_put(msg, sms->user_data_len);
497 memcpy(smsp, sms->user_data, sms->user_data_len);
498 break;
499 default:
500 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
501 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200502 }
Harald Welteb78996d2009-07-27 20:11:35 +0200503
Harald Welte68b7df22009-08-08 16:03:15 +0200504 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200505}
506
Harald Welte156c5e62009-07-05 14:02:46 +0200507/* process an incoming TPDU (called from RP-DATA)
508 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800509static int gsm340_rx_tpdu(struct msgb *msg)
510{
Harald Welte75350412009-07-23 18:46:00 +0200511 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800512 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800513 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200514 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
515 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800516 u_int8_t da_len_bytes;
517 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
518 int rc = 0;
519
Harald Welte68b7df22009-08-08 16:03:15 +0200520 gsms = sms_alloc();
521 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200522 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800523
524 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200525 sms_mti = *smsp & 0x03;
526 sms_mms = !!(*smsp & 0x04);
527 sms_vpf = (*smsp & 0x18) >> 3;
528 gsms->status_rep_req = (*smsp & 0x20);
529 gsms->ud_hdr_ind = (*smsp & 0x40);
530 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800531
532 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200533 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800534
535 /* length in bytes of the destination address */
536 da_len_bytes = 2 + *smsp/2 + *smsp%2;
537 if (da_len_bytes > 12) {
538 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200539 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800540 goto out;
541 }
Harald Welte3794e152009-06-12 02:42:11 +0800542 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800543 memcpy(address_lv, smsp, da_len_bytes);
544 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800545 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800546 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200547 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800548 smsp += da_len_bytes;
549
Harald Welte68b7df22009-08-08 16:03:15 +0200550 gsms->protocol_id = *smsp++;
551 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800552
Harald Welte68b7df22009-08-08 16:03:15 +0200553 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800554
Harald Welte68b7df22009-08-08 16:03:15 +0200555 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800556 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200557 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800558 break;
559 case GSM340_TP_VPF_ABSOLUTE:
560 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200561 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100562 /* the additional functionality indicator... */
563 if (*smsp & (1<<7)) smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800564 smsp += 7;
565 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200566 case GSM340_TP_VPF_NONE:
567 sms_vp = 0;
568 break;
Harald Welte59b04682009-06-10 05:40:52 +0800569 default:
570 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200571 sms_vpf);
572 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800573 }
Harald Welte68b7df22009-08-08 16:03:15 +0200574 gsms->user_data_len = *smsp++;
575 if (gsms->user_data_len) {
576 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800577
Harald Welte68b7df22009-08-08 16:03:15 +0200578 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800579 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200580 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800581 break;
582 case DCS_8BIT_DATA:
583 case DCS_UCS2:
584 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800585 break;
586 }
587 }
588
589 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
590 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte68b7df22009-08-08 16:03:15 +0200591 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
592 gsms->protocol_id, gsms->data_coding_scheme,
593 gsms->dest_addr, gsms->user_data_len,
594 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
595 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800596
Harald Welte68b7df22009-08-08 16:03:15 +0200597 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800598
Harald Welte68b7df22009-08-08 16:03:15 +0200599 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200600
Harald Welte68b7df22009-08-08 16:03:15 +0200601 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200602
Harald Welte59b04682009-06-10 05:40:52 +0800603 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200604 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800605 if (!gsms->receiver) {
606 rc = 1; /* cause 1: unknown subscriber */
607 goto out;
608 }
609
Harald Welte68b7df22009-08-08 16:03:15 +0200610 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800611 case GSM340_SMS_SUBMIT_MS2SC:
612 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200613 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800614 break;
615 case GSM340_SMS_COMMAND_MS2SC:
616 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200617 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200618 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800619 break;
620 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200621 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200622 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800623 break;
624 }
625
Harald Welte156c5e62009-07-05 14:02:46 +0200626 if (!rc && !gsms->receiver)
627 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
628
Harald Welte59b04682009-06-10 05:40:52 +0800629out:
Harald Welte68b7df22009-08-08 16:03:15 +0200630 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800631
632 return rc;
633}
634
Harald Welteb78996d2009-07-27 20:11:35 +0200635static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800636{
637 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800638
Harald Welte59b04682009-06-10 05:40:52 +0800639 DEBUGP(DSMS, "TX: SMS RP ACK\n");
640
Harald Welteb78996d2009-07-27 20:11:35 +0200641 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800642}
643
Harald Welteb78996d2009-07-27 20:11:35 +0200644static int gsm411_send_rp_error(struct gsm_trans *trans,
645 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800646{
647 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800648
Harald Welte59b04682009-06-10 05:40:52 +0800649 msgb_tv_put(msg, 1, cause);
650
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200651 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
652 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800653
Harald Welteb78996d2009-07-27 20:11:35 +0200654 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800655}
656
657/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200658static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
659 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800660 u_int8_t src_len, u_int8_t *src,
661 u_int8_t dst_len, u_int8_t *dst,
662 u_int8_t tpdu_len, u_int8_t *tpdu)
663{
Harald Welte59b04682009-06-10 05:40:52 +0800664 int rc = 0;
665
666 if (src_len && src)
667 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
668
669 if (!dst_len || !dst || !tpdu_len || !tpdu) {
670 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200671 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200672 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800673 return -EIO;
674 }
675 msg->smsh = tpdu;
676
677 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800678
679 rc = gsm340_rx_tpdu(msg);
680 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200681 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800682 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200683 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800684 else
685 return rc;
686}
687
688/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200689static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
690 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800691{
692 u_int8_t src_len, dst_len, rpud_len;
693 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
694
695 /* in the MO case, this should always be zero length */
696 src_len = rph->data[0];
697 if (src_len)
698 src = &rph->data[1];
699
700 dst_len = rph->data[1+src_len];
701 if (dst_len)
702 dst = &rph->data[1+src_len+1];
703
704 rpud_len = rph->data[1+src_len+1+dst_len];
705 if (rpud_len)
706 rp_ud = &rph->data[1+src_len+1+dst_len+1];
707
Harald Welte156c5e62009-07-05 14:02:46 +0200708 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
709 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200710 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800711 rpud_len, rp_ud);
712}
713
Harald Welte09421d32009-08-09 14:59:02 +0200714/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200715static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
716 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200717{
Harald Welte68b7df22009-08-08 16:03:15 +0200718 struct gsm_sms *sms = trans->sms.sms;
719
Harald Welte156c5e62009-07-05 14:02:46 +0200720 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
721 * successfully received a SMS. We can now safely mark it as
722 * transmitted */
723
Harald Welte09421d32009-08-09 14:59:02 +0200724 if (!trans->sms.is_mt) {
725 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
726 return gsm411_send_rp_error(trans, rph->msg_ref,
727 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
728 }
Harald Weltedd62b162009-07-09 23:52:59 +0200729
Harald Welte68b7df22009-08-08 16:03:15 +0200730 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200731 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
732 return gsm411_send_rp_error(trans, rph->msg_ref,
733 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200734 }
735
736 /* mark this SMS as sent in database */
737 db_sms_mark_sent(sms);
738
739 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
740
741 sms_free(sms);
742 trans->sms.sms = NULL;
743
Sylvain Munaut4dd65ae2009-09-27 11:16:22 +0200744 /* free the transaction here */
745 trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200746
747 /* check for more messages for this subscriber */
748 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
749 if (sms)
750 gsm411_send_sms_lchan(msg->lchan, sms);
751 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200752 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200753
754 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200755}
756
Harald Welteb78996d2009-07-27 20:11:35 +0200757static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
758 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200759{
Harald Welte68b7df22009-08-08 16:03:15 +0200760 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200761 u_int8_t cause_len = rph->data[0];
762 u_int8_t cause = rph->data[1];
763
Harald Welte156c5e62009-07-05 14:02:46 +0200764 /* Error in response to MT RP_DATA, i.e. the MS did not
765 * successfully receive the SMS. We need to investigate
766 * the cause and take action depending on it */
767
Holger Hans Peter Freyther80e5ccc2009-10-22 15:40:33 +0200768 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200769 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200770
Harald Welte09421d32009-08-09 14:59:02 +0200771 if (!trans->sms.is_mt) {
772 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200773#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200774 return gsm411_send_rp_error(trans, rph->msg_ref,
775 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200776#endif
Harald Welte09421d32009-08-09 14:59:02 +0200777 }
Harald Weltedd62b162009-07-09 23:52:59 +0200778
Harald Welte68b7df22009-08-08 16:03:15 +0200779 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200780 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200781 return -EINVAL;
782#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200783 return gsm411_send_rp_error(trans, rph->msg_ref,
784 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200785#endif
Harald Welte09421d32009-08-09 14:59:02 +0200786 }
787
788 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
789 /* MS has not enough memory to store the message. We need
790 * to store this in our database and wati for a SMMA message */
791 /* FIXME */
792 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200793 }
794
795 sms_free(sms);
796 trans->sms.sms = NULL;
797
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200798 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200799
Harald Welteb78996d2009-07-27 20:11:35 +0200800 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200801}
802
Harald Welteb78996d2009-07-27 20:11:35 +0200803static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
804 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200805{
Harald Weltefc01b242009-08-09 19:07:41 +0200806 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200807 int rc;
808
Harald Weltefc01b242009-08-09 19:07:41 +0200809 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
810 trans->sms.rp_state = GSM411_RPS_IDLE;
811
Harald Welte156c5e62009-07-05 14:02:46 +0200812 /* MS tells us that it has memory for more SMS, we need
813 * to check if we have any pending messages for it and then
814 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200815 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200816
Harald Weltefc01b242009-08-09 19:07:41 +0200817 /* check for more messages for this subscriber */
818 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
819 if (sms)
820 gsm411_send_sms_lchan(msg->lchan, sms);
821 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200822 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200823
824 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200825}
826
Harald Welteb78996d2009-07-27 20:11:35 +0200827static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
828 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800829{
830 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
831 u_int8_t msg_type = rp_data->msg_type & 0x07;
832 int rc = 0;
833
834 switch (msg_type) {
835 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200836 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
837 /* start TR2N and enter 'wait to send RP-ACK state' */
838 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
839 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800840 break;
841 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200842 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
843 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200844 break;
Harald Welte59b04682009-06-10 05:40:52 +0800845 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200846 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
847 /* start TR2N and enter 'wait to send RP-ACK state' */
848 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
849 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
850 break;
851 case GSM411_MT_RP_ERROR_MO:
852 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800853 break;
854 default:
855 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200856 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
857 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800858 break;
859 }
860
861 return rc;
862}
863
Harald Welteb78996d2009-07-27 20:11:35 +0200864/* send CP-ACK to given transaction */
865static int gsm411_tx_cp_ack(struct gsm_trans *trans)
866{
867 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200868 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200869
Harald Weltefc01b242009-08-09 19:07:41 +0200870 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
871
872 if (trans->sms.is_mt) {
873 /* If this is a MT SMS DELIVER, we can clear transaction here */
874 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200875 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200876 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200877
878 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200879}
880
881static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
882{
883 struct msgb *msg = gsm411_msgb_alloc();
884 u_int8_t *causep;
885
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200886 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
887 get_value_string(cp_cause_strs, cause));
888
Harald Welte68b7df22009-08-08 16:03:15 +0200889 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200890 *causep = cause;
891
892 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
893}
894
895/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200896int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800897{
898 struct gsm48_hdr *gh = msgb_l3(msg);
899 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200900 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
901 struct gsm_lchan *lchan = msg->lchan;
902 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800903 int rc = 0;
904
Harald Welteb78996d2009-07-27 20:11:35 +0200905 if (!lchan->subscr)
906 return -EIO;
907 /* FIXME: send some error message */
908
Sylvain Munaute02fb9a2009-12-18 18:28:08 +0100909 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200910 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
911 transaction_id);
912 if (!trans) {
Sylvain Munaut40c23322009-12-18 18:28:09 +0100913 DEBUGPC(DSMS, "(new) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200914 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
915 transaction_id, new_callref++);
916 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200917 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200918 /* FIXME: send some error message */
919 return -ENOMEM;
920 }
921 trans->sms.cp_state = GSM411_CPS_IDLE;
922 trans->sms.rp_state = GSM411_RPS_IDLE;
923 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200924 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200925
926 trans->lchan = lchan;
927 use_lchan(lchan);
928 }
929
Harald Welte59b04682009-06-10 05:40:52 +0800930 switch(msg_type) {
931 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200932 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200933 /* 5.2.3.1.3: MO state exists when SMC has received
934 * CP-DATA, including sending of the assoc. CP-ACK */
935 /* 5.2.3.2.4: MT state exists when SMC has received
936 * CP-DATA, including sending of the assoc. CP-ACK */
937 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200938
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200939 /* SMC instance acknowledges the CP-DATA frame */
940 gsm411_tx_cp_ack(trans);
941
Harald Welteb78996d2009-07-27 20:11:35 +0200942 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200943#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200944 /* Send CP-ACK or CP-ERORR in response */
945 if (rc < 0) {
946 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
947 } else
948 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200949#endif
Harald Welte59b04682009-06-10 05:40:52 +0800950 break;
951 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200952 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200953 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200954 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
955 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
956 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +0200957 /* Stop TC1* after CP-ACK has been received */
958 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +0200959
Harald Welteb78996d2009-07-27 20:11:35 +0200960 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200961 /* FIXME: we have sont one CP-DATA, which was now
962 * acknowledged. Check if we want to transfer more,
963 * i.e. multi-part message */
964 trans->sms.cp_state = GSM411_CPS_IDLE;
965 trans_free(trans);
966 }
Harald Welte59b04682009-06-10 05:40:52 +0800967 break;
968 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200969 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
970 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +0200971 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +0200972 trans->sms.cp_state = GSM411_CPS_IDLE;
973 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800974 break;
975 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200976 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200977 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200978 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200979 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800980 break;
981 }
982
Harald Welte59b04682009-06-10 05:40:52 +0800983 return rc;
984}
985
Harald Welte59b04682009-06-10 05:40:52 +0800986#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800987/* Test TPDU - ALL YOUR */
988static u_int8_t tpdu_test[] = {
989 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
990 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
991 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
992 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
993};
994#endif
995
Harald Weltefc01b242009-08-09 19:07:41 +0200996/* Take a SMS in gsm_sms structure and send it through an already
997 * existing lchan. We also assume that the caller ensured this lchan already
998 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +0200999int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +08001000{
1001 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +02001002 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +02001003 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001004 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +02001005 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +02001006 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001007
Harald Weltefc01b242009-08-09 19:07:41 +02001008 transaction_id = 4; /* FIXME: we always use 4 for now */
1009
Harald Welte59b04682009-06-10 05:40:52 +08001010 msg->lchan = lchan;
1011
Harald Welte68b7df22009-08-08 16:03:15 +02001012 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +02001013
Harald Welte68b7df22009-08-08 16:03:15 +02001014 /* FIXME: allocate transaction with message reference */
1015 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
1016 transaction_id, new_callref++);
1017 if (!trans) {
1018 DEBUGP(DSMS, "No memory for trans\n");
1019 /* FIXME: send some error message */
1020 return -ENOMEM;
1021 }
1022 trans->sms.cp_state = GSM411_CPS_IDLE;
1023 trans->sms.rp_state = GSM411_RPS_IDLE;
1024 trans->sms.is_mt = 1;
1025 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001026 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +02001027
1028 trans->lchan = lchan;
1029 use_lchan(lchan);
1030
1031 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +08001032 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001033 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +02001034 data[1] = 0x91; /* type of number: international, ISDN */
1035 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +08001036 data[3] = 0x77;
1037 data[4] = 0x58;
1038 data[5] = 0x10;
1039 data[6] = 0x06;
1040 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001041
1042 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +08001043 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001044 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +08001045
Harald Welte68b7df22009-08-08 16:03:15 +02001046 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1047 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +08001048
Harald Welte68b7df22009-08-08 16:03:15 +02001049#if 1
1050 /* generate the 03.40 TPDU */
1051 rc = gsm340_gen_tpdu(msg, sms);
1052 if (rc < 0) {
1053 msgb_free(msg);
1054 return rc;
1055 }
Harald Welte59b04682009-06-10 05:40:52 +08001056
Harald Welte68b7df22009-08-08 16:03:15 +02001057 *rp_ud_len = rc;
1058#else
1059 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +08001060 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +02001061 *rp_ud_len = sizeof(tpdu_test);
1062#endif
Harald Welte59b04682009-06-10 05:40:52 +08001063
Harald Welte68b7df22009-08-08 16:03:15 +02001064 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001065
Harald Welteb78996d2009-07-27 20:11:35 +02001066 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1067 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001068}
Harald Welteb78996d2009-07-27 20:11:35 +02001069
Harald Weltefc01b242009-08-09 19:07:41 +02001070/* RLL SAPI3 establish callback. Now we have a RLL connection and
1071 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001072static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1073 void *_sms, enum bsc_rllr_ind type)
1074{
1075 struct gsm_sms *sms = _sms;
1076
1077 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1078 lchan, link_id, sms, type);
1079
1080 switch (type) {
1081 case BSC_RLLR_IND_EST_CONF:
1082 gsm411_send_sms_lchan(lchan, sms);
1083 break;
1084 case BSC_RLLR_IND_REL_IND:
1085 case BSC_RLLR_IND_ERR_IND:
1086 case BSC_RLLR_IND_TIMEOUT:
1087 sms_free(sms);
1088 break;
1089 }
1090}
1091
Harald Weltefc01b242009-08-09 19:07:41 +02001092/* paging callback. Here we get called if paging a subscriber has
1093 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001094static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1095 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001096{
Harald Welte68b7df22009-08-08 16:03:15 +02001097 struct gsm_lchan *lchan = _lchan;
1098 struct gsm_sms *sms = _sms;
1099 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001100
Harald Welte68b7df22009-08-08 16:03:15 +02001101 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1102 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1103
1104 if (hooknum != GSM_HOOK_RR_PAGING)
1105 return -EINVAL;
1106
1107 switch (event) {
1108 case GSM_PAGING_SUCCEEDED:
1109 /* Paging aborted without lchan ?!? */
1110 if (!lchan) {
1111 sms_free(sms);
1112 rc = -EIO;
1113 break;
1114 }
Harald Weltefc01b242009-08-09 19:07:41 +02001115 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001116 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001117 break;
1118 case GSM_PAGING_EXPIRED:
1119 sms_free(sms);
1120 rc = -ETIMEDOUT;
1121 break;
1122 default:
1123 rc = -EINVAL;
1124 break;
1125 }
1126
1127 return rc;
1128}
1129
Harald Weltefc01b242009-08-09 19:07:41 +02001130/* high-level function to send a SMS to a given subscriber. The function
1131 * will take care of paging the subscriber, establishing the RLL SAPI3
1132 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001133int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1134 struct gsm_sms *sms)
1135{
Harald Weltefc01b242009-08-09 19:07:41 +02001136 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001137 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001138
Harald Welte68b7df22009-08-08 16:03:15 +02001139 /* check if we already have an open lchan to the subscriber.
1140 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001141 lchan = lchan_for_subscr(subscr);
1142 if (lchan)
1143 return rll_establish(lchan, UM_SAPI_SMS,
1144 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001145
1146 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001147 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1148 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001149 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001150 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001151
1152 return 0;
1153}
Harald Welte5b359d82009-07-28 00:44:49 +02001154
Harald Weltefc01b242009-08-09 19:07:41 +02001155static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1156 void *handler_data, void *signal_data)
1157{
1158 struct gsm_subscriber *subscr;
1159 struct gsm_lchan *lchan;
1160 struct gsm_sms *sms;
1161
1162 switch (signal) {
1163 case S_SUBSCR_ATTACHED:
1164 /* A subscriber has attached. Check if there are
1165 * any pending SMS for him to be delivered */
1166 subscr = signal_data;
1167 lchan = lchan_for_subscr(subscr);
1168 if (!lchan)
1169 break;
1170 sms = db_sms_get_unsent_for_subscr(subscr);
1171 if (!sms)
1172 break;
1173 /* Establish a SAPI3 RLL connection for SMS */
1174 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1175 break;
1176 default:
1177 break;
1178 }
1179 return 0;
1180}
1181
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001182void _gsm411_sms_trans_free(struct gsm_trans *trans)
1183{
1184 bsc_del_timer(&trans->sms.cp_timer);
1185}
1186
Harald Welte932e20d2009-07-28 00:41:45 +02001187static __attribute__((constructor)) void on_dso_load_sms(void)
1188{
Harald Weltefc01b242009-08-09 19:07:41 +02001189 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001190}