blob: 75ddf9dd9d56c864c00dea274cc2c2576f6c13f3 [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 Neubauer94436952009-11-11 23:02:07 +0900201static time_t gsm340_scts(u_int8_t *scts);
202
Harald Welte68b7df22009-08-08 16:03:15 +0200203static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800204{
205 u_int8_t vp;
206 unsigned long minutes;
Steffen Neubauer94436952009-11-11 23:02:07 +0900207 time_t expires;
208 time_t now;
Harald Welte59b04682009-06-10 05:40:52 +0800209
Harald Welte68b7df22009-08-08 16:03:15 +0200210 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800211 case GSM340_TP_VPF_RELATIVE:
212 /* Chapter 9.2.3.12.1 */
Harald Welte68b7df22009-08-08 16:03:15 +0200213 vp = *(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800214 if (vp <= 143)
215 minutes = vp + 1 * 5;
216 else if (vp <= 167)
217 minutes = 12*60 + (vp-143) * 30;
218 else if (vp <= 196)
219 minutes = vp-166 * 60 * 24;
220 else
221 minutes = vp-192 * 60 * 24 * 7;
222 break;
223 case GSM340_TP_VPF_ABSOLUTE:
224 /* Chapter 9.2.3.12.2 */
Steffen Neubauer94436952009-11-11 23:02:07 +0900225 expires = gsm340_scts(sms_vp);
226 now = mktime(gmtime(NULL));
227 if (expires <= now)
228 minutes = 0;
229 else
230 minutes = (expires-now)/60;
Harald Welte59b04682009-06-10 05:40:52 +0800231 break;
232 case GSM340_TP_VPF_ENHANCED:
233 /* Chapter 9.2.3.12.3 */
234 /* FIXME: implementation */
235 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
236 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200237 case GSM340_TP_VPF_NONE:
238 /* Default validity: two days */
239 minutes = 24 * 60 * 2;
240 break;
Harald Welte59b04682009-06-10 05:40:52 +0800241 }
242 return minutes;
243}
244
245/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
246enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
247{
248 u_int8_t cgbits = dcs >> 4;
249 enum sms_alphabet alpha = DCS_NONE;
250
251 if ((cgbits & 0xc) == 0) {
252 if (cgbits & 2)
253 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
254
Daniel Willmannf2861022009-08-15 03:01:17 +0200255 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800256 case 0:
257 alpha = DCS_7BIT_DEFAULT;
258 break;
259 case 1:
260 alpha = DCS_8BIT_DATA;
261 break;
262 case 2:
263 alpha = DCS_UCS2;
264 break;
265 }
266 } else if (cgbits == 0xc || cgbits == 0xd)
267 alpha = DCS_7BIT_DEFAULT;
268 else if (cgbits == 0xe)
269 alpha = DCS_UCS2;
270 else if (cgbits == 0xf) {
271 if (dcs & 4)
272 alpha = DCS_8BIT_DATA;
273 else
274 alpha = DCS_7BIT_DEFAULT;
275 }
276
277 return alpha;
278}
279
Harald Welte68b7df22009-08-08 16:03:15 +0200280static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800281{
282 if (db_sms_store(gsms) != 0) {
283 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200284 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800285 }
Harald Welte68b7df22009-08-08 16:03:15 +0200286 /* dispatch a signal to tell higher level about it */
287 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200288 /* try delivering the SMS right now */
289 //gsm411_send_sms_subscr(gsms->receiver, gsms);
290
Harald Welte59b04682009-06-10 05:40:52 +0800291 return 0;
292}
293
Harald Welte68b7df22009-08-08 16:03:15 +0200294/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
295static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
296 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200297{
Harald Welte68b7df22009-08-08 16:03:15 +0200298 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200299
Harald Welte68b7df22009-08-08 16:03:15 +0200300 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
301
302 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
303
304 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
305 oa[0] = strlen(subscr->extension) & 0xff;
306
307 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200308}
309
Steffen Neubauer94436952009-11-11 23:02:07 +0900310/* Turn int into semi-octet representation: 98 => 0x89 */
Harald Welteb78996d2009-07-27 20:11:35 +0200311static u_int8_t bcdify(u_int8_t value)
312{
313 u_int8_t ret;
314
Harald Welte68b7df22009-08-08 16:03:15 +0200315 ret = value / 10;
316 ret |= (value % 10) << 4;
Harald Welteb78996d2009-07-27 20:11:35 +0200317
318 return ret;
319}
320
Steffen Neubauer94436952009-11-11 23:02:07 +0900321/* Turn semi-octet representation into int: 0x89 => 98 */
322static u_int8_t unbcdify(u_int8_t value)
323{
324 u_int8_t ret;
325
326 if ((value & 0x0F) > 9 || (value >> 4) > 9)
327 DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
328
329 ret = (value&0x0F)*10;
330 if (ret > 90)
331 ret += value>>4;
332
333 return ret;
334}
335
Harald Welteb78996d2009-07-27 20:11:35 +0200336/* Generate 03.40 TP-SCTS */
337static void gsm340_gen_scts(u_int8_t *scts, time_t time)
338{
339 struct tm *tm = localtime(&time);
Harald Welteb78996d2009-07-27 20:11:35 +0200340
341 *scts++ = bcdify(tm->tm_year % 100);
Stefan Schmidt84b95e52009-08-13 21:00:44 +0200342 *scts++ = bcdify(tm->tm_mon + 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200343 *scts++ = bcdify(tm->tm_mday);
344 *scts++ = bcdify(tm->tm_hour);
345 *scts++ = bcdify(tm->tm_min);
346 *scts++ = bcdify(tm->tm_sec);
Steffen Neubauer94436952009-11-11 23:02:07 +0900347 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
348}
349
350/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
351static time_t gsm340_scts(u_int8_t *scts)
352{
353 struct tm tm;
354
355 u_int8_t yr = unbcdify(*scts++);
356
357 if (yr <= 80)
358 tm.tm_year = 100 + yr;
359 else
360 tm.tm_year = yr;
361 tm.tm_mon = unbcdify(*scts++) - 1;
362 tm.tm_mday = unbcdify(*scts++);
363 tm.tm_hour = unbcdify(*scts++);
364 tm.tm_min = unbcdify(*scts++);
365 tm.tm_sec = unbcdify(*scts++);
366 /* according to gsm 03.40 time zone is
367 "expressed in quarters of an hour" */
368 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
369
370 return mktime(&tm);
Harald Welteb78996d2009-07-27 20:11:35 +0200371}
372
Harald Welte68b7df22009-08-08 16:03:15 +0200373/* generate a msgb containing a TPDU derived from struct gsm_sms,
374 * returns total size of TPDU */
375static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200376{
Harald Welteb78996d2009-07-27 20:11:35 +0200377 u_int8_t *smsp;
378 u_int8_t oa[12]; /* max len per 03.40 */
379 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200380 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200381 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200382
383 /* generate first octet with masked bits */
384 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200385 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200386 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200387 /* TP-MMS (more messages to send) */
388 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200389 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200390 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200391 if (sms->status_rep_req)
392 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200393 /* TP-UDHI (indicating TP-UD contains a header) */
394 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200395 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200396#if 0
397 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200398 if (sms->
399 *smsp |= 0x80;
400#endif
401
402 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200403 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200404 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200405 memcpy(smsp, oa, oa_len);
406
407 /* generate TP-PID */
408 smsp = msgb_put(msg, 1);
409 *smsp = sms->protocol_id;
410
411 /* generate TP-DCS */
412 smsp = msgb_put(msg, 1);
413 *smsp = sms->data_coding_scheme;
414
415 /* generate TP-SCTS */
416 smsp = msgb_put(msg, 7);
417 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200418
Harald Welteb78996d2009-07-27 20:11:35 +0200419 /* generate TP-UDL */
420 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200421 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200422
423 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200424 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
425 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200426 octet_len = sms->user_data_len*7/8;
427 if (sms->user_data_len*7%8 != 0)
428 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200429 /* Warning, user_data_len indicates the amount of septets
430 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200431 smsp = msgb_put(msg, octet_len);
432 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200433 break;
434 case DCS_UCS2:
435 case DCS_8BIT_DATA:
436 smsp = msgb_put(msg, sms->user_data_len);
437 memcpy(smsp, sms->user_data, sms->user_data_len);
438 break;
439 default:
440 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
441 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200442 }
Harald Welteb78996d2009-07-27 20:11:35 +0200443
Harald Welte68b7df22009-08-08 16:03:15 +0200444 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200445}
446
Harald Welte156c5e62009-07-05 14:02:46 +0200447/* process an incoming TPDU (called from RP-DATA)
448 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800449static int gsm340_rx_tpdu(struct msgb *msg)
450{
Harald Welte75350412009-07-23 18:46:00 +0200451 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800452 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800453 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200454 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
455 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800456 u_int8_t da_len_bytes;
457 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
458 int rc = 0;
459
Harald Welte68b7df22009-08-08 16:03:15 +0200460 gsms = sms_alloc();
461 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200462 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800463
464 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200465 sms_mti = *smsp & 0x03;
466 sms_mms = !!(*smsp & 0x04);
467 sms_vpf = (*smsp & 0x18) >> 3;
468 gsms->status_rep_req = (*smsp & 0x20);
469 gsms->ud_hdr_ind = (*smsp & 0x40);
470 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800471
472 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200473 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800474
475 /* length in bytes of the destination address */
476 da_len_bytes = 2 + *smsp/2 + *smsp%2;
477 if (da_len_bytes > 12) {
478 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200479 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800480 goto out;
481 }
Harald Welte3794e152009-06-12 02:42:11 +0800482 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800483 memcpy(address_lv, smsp, da_len_bytes);
484 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800485 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800486 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200487 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800488 smsp += da_len_bytes;
489
Harald Welte68b7df22009-08-08 16:03:15 +0200490 gsms->protocol_id = *smsp++;
491 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800492
Harald Welte68b7df22009-08-08 16:03:15 +0200493 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800494
Harald Welte68b7df22009-08-08 16:03:15 +0200495 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800496 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200497 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800498 break;
499 case GSM340_TP_VPF_ABSOLUTE:
500 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200501 sms_vp = smsp;
Harald Welte59b04682009-06-10 05:40:52 +0800502 smsp += 7;
503 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200504 case GSM340_TP_VPF_NONE:
505 sms_vp = 0;
506 break;
Harald Welte59b04682009-06-10 05:40:52 +0800507 default:
508 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200509 sms_vpf);
510 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800511 }
Harald Welte68b7df22009-08-08 16:03:15 +0200512 gsms->user_data_len = *smsp++;
513 if (gsms->user_data_len) {
514 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800515
Harald Welte68b7df22009-08-08 16:03:15 +0200516 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800517 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200518 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800519 break;
520 case DCS_8BIT_DATA:
521 case DCS_UCS2:
522 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800523 break;
524 }
525 }
526
527 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
528 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte68b7df22009-08-08 16:03:15 +0200529 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
530 gsms->protocol_id, gsms->data_coding_scheme,
531 gsms->dest_addr, gsms->user_data_len,
532 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
533 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800534
Harald Welte68b7df22009-08-08 16:03:15 +0200535 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800536
Harald Welte68b7df22009-08-08 16:03:15 +0200537 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200538
Harald Welte68b7df22009-08-08 16:03:15 +0200539 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200540
Harald Welte59b04682009-06-10 05:40:52 +0800541 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200542 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800543 if (!gsms->receiver) {
544 rc = 1; /* cause 1: unknown subscriber */
545 goto out;
546 }
547
Harald Welte68b7df22009-08-08 16:03:15 +0200548 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800549 case GSM340_SMS_SUBMIT_MS2SC:
550 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200551 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800552 break;
553 case GSM340_SMS_COMMAND_MS2SC:
554 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200555 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200556 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800557 break;
558 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200559 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200560 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800561 break;
562 }
563
Harald Welte156c5e62009-07-05 14:02:46 +0200564 if (!rc && !gsms->receiver)
565 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
566
Harald Welte59b04682009-06-10 05:40:52 +0800567out:
Harald Welte68b7df22009-08-08 16:03:15 +0200568 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800569
570 return rc;
571}
572
Harald Welteb78996d2009-07-27 20:11:35 +0200573static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800574{
575 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800576
Harald Welte59b04682009-06-10 05:40:52 +0800577 DEBUGP(DSMS, "TX: SMS RP ACK\n");
578
Harald Welteb78996d2009-07-27 20:11:35 +0200579 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800580}
581
Harald Welteb78996d2009-07-27 20:11:35 +0200582static int gsm411_send_rp_error(struct gsm_trans *trans,
583 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800584{
585 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800586
Harald Welte59b04682009-06-10 05:40:52 +0800587 msgb_tv_put(msg, 1, cause);
588
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200589 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
590 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800591
Harald Welteb78996d2009-07-27 20:11:35 +0200592 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800593}
594
595/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200596static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
597 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800598 u_int8_t src_len, u_int8_t *src,
599 u_int8_t dst_len, u_int8_t *dst,
600 u_int8_t tpdu_len, u_int8_t *tpdu)
601{
Harald Welte59b04682009-06-10 05:40:52 +0800602 int rc = 0;
603
604 if (src_len && src)
605 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
606
607 if (!dst_len || !dst || !tpdu_len || !tpdu) {
608 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200609 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200610 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800611 return -EIO;
612 }
613 msg->smsh = tpdu;
614
615 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800616
617 rc = gsm340_rx_tpdu(msg);
618 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200619 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800620 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200621 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800622 else
623 return rc;
624}
625
626/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200627static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
628 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800629{
630 u_int8_t src_len, dst_len, rpud_len;
631 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
632
633 /* in the MO case, this should always be zero length */
634 src_len = rph->data[0];
635 if (src_len)
636 src = &rph->data[1];
637
638 dst_len = rph->data[1+src_len];
639 if (dst_len)
640 dst = &rph->data[1+src_len+1];
641
642 rpud_len = rph->data[1+src_len+1+dst_len];
643 if (rpud_len)
644 rp_ud = &rph->data[1+src_len+1+dst_len+1];
645
Harald Welte156c5e62009-07-05 14:02:46 +0200646 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
647 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200648 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800649 rpud_len, rp_ud);
650}
651
Harald Welte09421d32009-08-09 14:59:02 +0200652/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200653static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
654 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200655{
Harald Welte68b7df22009-08-08 16:03:15 +0200656 struct gsm_sms *sms = trans->sms.sms;
657
Harald Welte156c5e62009-07-05 14:02:46 +0200658 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
659 * successfully received a SMS. We can now safely mark it as
660 * transmitted */
661
Harald Welte09421d32009-08-09 14:59:02 +0200662 if (!trans->sms.is_mt) {
663 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
664 return gsm411_send_rp_error(trans, rph->msg_ref,
665 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
666 }
Harald Weltedd62b162009-07-09 23:52:59 +0200667
Harald Welte68b7df22009-08-08 16:03:15 +0200668 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200669 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
670 return gsm411_send_rp_error(trans, rph->msg_ref,
671 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200672 }
673
674 /* mark this SMS as sent in database */
675 db_sms_mark_sent(sms);
676
677 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
678
679 sms_free(sms);
680 trans->sms.sms = NULL;
681
Sylvain Munaut4dd65ae2009-09-27 11:16:22 +0200682 /* free the transaction here */
683 trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200684
685 /* check for more messages for this subscriber */
686 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
687 if (sms)
688 gsm411_send_sms_lchan(msg->lchan, sms);
689 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200690 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200691
692 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200693}
694
Harald Welteb78996d2009-07-27 20:11:35 +0200695static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
696 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200697{
Harald Welte68b7df22009-08-08 16:03:15 +0200698 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200699 u_int8_t cause_len = rph->data[0];
700 u_int8_t cause = rph->data[1];
701
Harald Welte156c5e62009-07-05 14:02:46 +0200702 /* Error in response to MT RP_DATA, i.e. the MS did not
703 * successfully receive the SMS. We need to investigate
704 * the cause and take action depending on it */
705
Holger Hans Peter Freyther80e5ccc2009-10-22 15:40:33 +0200706 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200707 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200708
Harald Welte09421d32009-08-09 14:59:02 +0200709 if (!trans->sms.is_mt) {
710 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200711#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200712 return gsm411_send_rp_error(trans, rph->msg_ref,
713 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200714#endif
Harald Welte09421d32009-08-09 14:59:02 +0200715 }
Harald Weltedd62b162009-07-09 23:52:59 +0200716
Harald Welte68b7df22009-08-08 16:03:15 +0200717 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200718 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200719 return -EINVAL;
720#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200721 return gsm411_send_rp_error(trans, rph->msg_ref,
722 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200723#endif
Harald Welte09421d32009-08-09 14:59:02 +0200724 }
725
726 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
727 /* MS has not enough memory to store the message. We need
728 * to store this in our database and wati for a SMMA message */
729 /* FIXME */
730 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200731 }
732
733 sms_free(sms);
734 trans->sms.sms = NULL;
735
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200736 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200737
Harald Welteb78996d2009-07-27 20:11:35 +0200738 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200739}
740
Harald Welteb78996d2009-07-27 20:11:35 +0200741static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
742 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200743{
Harald Weltefc01b242009-08-09 19:07:41 +0200744 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200745 int rc;
746
Harald Weltefc01b242009-08-09 19:07:41 +0200747 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
748 trans->sms.rp_state = GSM411_RPS_IDLE;
749
Harald Welte156c5e62009-07-05 14:02:46 +0200750 /* MS tells us that it has memory for more SMS, we need
751 * to check if we have any pending messages for it and then
752 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200753 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200754
Harald Weltefc01b242009-08-09 19:07:41 +0200755 /* check for more messages for this subscriber */
756 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
757 if (sms)
758 gsm411_send_sms_lchan(msg->lchan, sms);
759 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200760 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200761
762 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200763}
764
Harald Welteb78996d2009-07-27 20:11:35 +0200765static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
766 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800767{
768 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
769 u_int8_t msg_type = rp_data->msg_type & 0x07;
770 int rc = 0;
771
772 switch (msg_type) {
773 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200774 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
775 /* start TR2N and enter 'wait to send RP-ACK state' */
776 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
777 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800778 break;
779 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200780 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
781 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200782 break;
Harald Welte59b04682009-06-10 05:40:52 +0800783 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200784 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
785 /* start TR2N and enter 'wait to send RP-ACK state' */
786 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
787 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
788 break;
789 case GSM411_MT_RP_ERROR_MO:
790 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800791 break;
792 default:
793 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200794 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
795 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800796 break;
797 }
798
799 return rc;
800}
801
Harald Welteb78996d2009-07-27 20:11:35 +0200802/* send CP-ACK to given transaction */
803static int gsm411_tx_cp_ack(struct gsm_trans *trans)
804{
805 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200806 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200807
Harald Weltefc01b242009-08-09 19:07:41 +0200808 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
809
810 if (trans->sms.is_mt) {
811 /* If this is a MT SMS DELIVER, we can clear transaction here */
812 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200813 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200814 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200815
816 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200817}
818
819static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
820{
821 struct msgb *msg = gsm411_msgb_alloc();
822 u_int8_t *causep;
823
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200824 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
825 get_value_string(cp_cause_strs, cause));
826
Harald Welte68b7df22009-08-08 16:03:15 +0200827 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200828 *causep = cause;
829
830 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
831}
832
833/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200834int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800835{
836 struct gsm48_hdr *gh = msgb_l3(msg);
837 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200838 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
839 struct gsm_lchan *lchan = msg->lchan;
840 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800841 int rc = 0;
842
Harald Welteb78996d2009-07-27 20:11:35 +0200843 if (!lchan->subscr)
844 return -EIO;
845 /* FIXME: send some error message */
846
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200847 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Welteb78996d2009-07-27 20:11:35 +0200848 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
849 transaction_id);
850 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200851 DEBUGPC(DSMS, "(unknown) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200852 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
853 transaction_id, new_callref++);
854 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200855 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200856 /* FIXME: send some error message */
857 return -ENOMEM;
858 }
859 trans->sms.cp_state = GSM411_CPS_IDLE;
860 trans->sms.rp_state = GSM411_RPS_IDLE;
861 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200862 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200863
864 trans->lchan = lchan;
865 use_lchan(lchan);
866 }
867
Harald Welte59b04682009-06-10 05:40:52 +0800868 switch(msg_type) {
869 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200870 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200871 /* 5.2.3.1.3: MO state exists when SMC has received
872 * CP-DATA, including sending of the assoc. CP-ACK */
873 /* 5.2.3.2.4: MT state exists when SMC has received
874 * CP-DATA, including sending of the assoc. CP-ACK */
875 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200876
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200877 /* SMC instance acknowledges the CP-DATA frame */
878 gsm411_tx_cp_ack(trans);
879
Harald Welteb78996d2009-07-27 20:11:35 +0200880 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200881#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200882 /* Send CP-ACK or CP-ERORR in response */
883 if (rc < 0) {
884 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
885 } else
886 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200887#endif
Harald Welte59b04682009-06-10 05:40:52 +0800888 break;
889 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200890 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200891 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200892 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
893 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
894 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +0200895 /* Stop TC1* after CP-ACK has been received */
896 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +0200897
Harald Welteb78996d2009-07-27 20:11:35 +0200898 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200899 /* FIXME: we have sont one CP-DATA, which was now
900 * acknowledged. Check if we want to transfer more,
901 * i.e. multi-part message */
902 trans->sms.cp_state = GSM411_CPS_IDLE;
903 trans_free(trans);
904 }
Harald Welte59b04682009-06-10 05:40:52 +0800905 break;
906 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200907 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
908 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +0200909 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +0200910 trans->sms.cp_state = GSM411_CPS_IDLE;
911 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800912 break;
913 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200914 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200915 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200916 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200917 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800918 break;
919 }
920
Harald Welte59b04682009-06-10 05:40:52 +0800921 return rc;
922}
923
Harald Welte59b04682009-06-10 05:40:52 +0800924#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800925/* Test TPDU - ALL YOUR */
926static u_int8_t tpdu_test[] = {
927 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
928 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
929 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
930 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
931};
932#endif
933
Harald Weltefc01b242009-08-09 19:07:41 +0200934/* Take a SMS in gsm_sms structure and send it through an already
935 * existing lchan. We also assume that the caller ensured this lchan already
936 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +0200937int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800938{
939 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200940 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +0200941 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200942 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +0200943 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +0200944 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800945
Harald Weltefc01b242009-08-09 19:07:41 +0200946 transaction_id = 4; /* FIXME: we always use 4 for now */
947
Harald Welte59b04682009-06-10 05:40:52 +0800948 msg->lchan = lchan;
949
Harald Welte68b7df22009-08-08 16:03:15 +0200950 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200951
Harald Welte68b7df22009-08-08 16:03:15 +0200952 /* FIXME: allocate transaction with message reference */
953 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
954 transaction_id, new_callref++);
955 if (!trans) {
956 DEBUGP(DSMS, "No memory for trans\n");
957 /* FIXME: send some error message */
958 return -ENOMEM;
959 }
960 trans->sms.cp_state = GSM411_CPS_IDLE;
961 trans->sms.rp_state = GSM411_RPS_IDLE;
962 trans->sms.is_mt = 1;
963 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200964 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +0200965
966 trans->lchan = lchan;
967 use_lchan(lchan);
968
969 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800970 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200971 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200972 data[1] = 0x91; /* type of number: international, ISDN */
973 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800974 data[3] = 0x77;
975 data[4] = 0x58;
976 data[5] = 0x10;
977 data[6] = 0x06;
978 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200979
980 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800981 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200982 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800983
Harald Welte68b7df22009-08-08 16:03:15 +0200984 /* obtain a pointer for the rp_ud_len, so we can fill it later */
985 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800986
Harald Welte68b7df22009-08-08 16:03:15 +0200987#if 1
988 /* generate the 03.40 TPDU */
989 rc = gsm340_gen_tpdu(msg, sms);
990 if (rc < 0) {
991 msgb_free(msg);
992 return rc;
993 }
Harald Welte59b04682009-06-10 05:40:52 +0800994
Harald Welte68b7df22009-08-08 16:03:15 +0200995 *rp_ud_len = rc;
996#else
997 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +0800998 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +0200999 *rp_ud_len = sizeof(tpdu_test);
1000#endif
Harald Welte59b04682009-06-10 05:40:52 +08001001
Harald Welte68b7df22009-08-08 16:03:15 +02001002 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001003
Harald Welteb78996d2009-07-27 20:11:35 +02001004 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1005 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001006}
Harald Welteb78996d2009-07-27 20:11:35 +02001007
Harald Weltefc01b242009-08-09 19:07:41 +02001008/* RLL SAPI3 establish callback. Now we have a RLL connection and
1009 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001010static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1011 void *_sms, enum bsc_rllr_ind type)
1012{
1013 struct gsm_sms *sms = _sms;
1014
1015 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1016 lchan, link_id, sms, type);
1017
1018 switch (type) {
1019 case BSC_RLLR_IND_EST_CONF:
1020 gsm411_send_sms_lchan(lchan, sms);
1021 break;
1022 case BSC_RLLR_IND_REL_IND:
1023 case BSC_RLLR_IND_ERR_IND:
1024 case BSC_RLLR_IND_TIMEOUT:
1025 sms_free(sms);
1026 break;
1027 }
1028}
1029
Harald Weltefc01b242009-08-09 19:07:41 +02001030/* paging callback. Here we get called if paging a subscriber has
1031 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001032static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1033 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001034{
Harald Welte68b7df22009-08-08 16:03:15 +02001035 struct gsm_lchan *lchan = _lchan;
1036 struct gsm_sms *sms = _sms;
1037 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001038
Harald Welte68b7df22009-08-08 16:03:15 +02001039 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1040 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1041
1042 if (hooknum != GSM_HOOK_RR_PAGING)
1043 return -EINVAL;
1044
1045 switch (event) {
1046 case GSM_PAGING_SUCCEEDED:
1047 /* Paging aborted without lchan ?!? */
1048 if (!lchan) {
1049 sms_free(sms);
1050 rc = -EIO;
1051 break;
1052 }
Harald Weltefc01b242009-08-09 19:07:41 +02001053 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001054 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001055 break;
1056 case GSM_PAGING_EXPIRED:
1057 sms_free(sms);
1058 rc = -ETIMEDOUT;
1059 break;
1060 default:
1061 rc = -EINVAL;
1062 break;
1063 }
1064
1065 return rc;
1066}
1067
Harald Weltefc01b242009-08-09 19:07:41 +02001068/* high-level function to send a SMS to a given subscriber. The function
1069 * will take care of paging the subscriber, establishing the RLL SAPI3
1070 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001071int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1072 struct gsm_sms *sms)
1073{
Harald Weltefc01b242009-08-09 19:07:41 +02001074 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001075 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001076
Harald Welte68b7df22009-08-08 16:03:15 +02001077 /* check if we already have an open lchan to the subscriber.
1078 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001079 lchan = lchan_for_subscr(subscr);
1080 if (lchan)
1081 return rll_establish(lchan, UM_SAPI_SMS,
1082 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001083
1084 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001085 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1086 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001087 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001088 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001089
1090 return 0;
1091}
Harald Welte5b359d82009-07-28 00:44:49 +02001092
Harald Weltefc01b242009-08-09 19:07:41 +02001093static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1094 void *handler_data, void *signal_data)
1095{
1096 struct gsm_subscriber *subscr;
1097 struct gsm_lchan *lchan;
1098 struct gsm_sms *sms;
1099
1100 switch (signal) {
1101 case S_SUBSCR_ATTACHED:
1102 /* A subscriber has attached. Check if there are
1103 * any pending SMS for him to be delivered */
1104 subscr = signal_data;
1105 lchan = lchan_for_subscr(subscr);
1106 if (!lchan)
1107 break;
1108 sms = db_sms_get_unsent_for_subscr(subscr);
1109 if (!sms)
1110 break;
1111 /* Establish a SAPI3 RLL connection for SMS */
1112 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1113 break;
1114 default:
1115 break;
1116 }
1117 return 0;
1118}
1119
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001120void _gsm411_sms_trans_free(struct gsm_trans *trans)
1121{
1122 bsc_del_timer(&trans->sms.cp_timer);
1123}
1124
Harald Welte932e20d2009-07-28 00:41:45 +02001125static __attribute__((constructor)) void on_dso_load_sms(void)
1126{
Harald Weltefc01b242009-08-09 19:07:41 +02001127 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001128}