blob: 6e59eafe45cffaf9bcb32528cf24b7e968494def [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 +020059struct value_string {
60 u_int32_t value;
61 const char *str;
62};
63
64static const struct value_string cp_cause_strs[] = {
65 { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
66 { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
67 { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
68 { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
69 { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
70 { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
71 { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
72 "Message incompatible with protocol state" },
73 { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
74 { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
75 { 0, 0 }
76};
77
78static const struct value_string rp_cause_strs[] = {
79 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
80 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
81 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
82 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
83 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
84 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
85 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
86 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
87 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
88 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
89 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
90 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
91 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
92 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
93 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
94 /* valid only for MT */
95 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
96 /* valid for both directions */
97 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
98 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
99 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
100 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
101 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
102 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
103 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
104 { 0, NULL }
105};
106
107const char *get_value_string(const struct value_string *vs, u_int32_t val)
108{
109 int i;
110
111 for (i = 0;; i++) {
112 if (vs[i].value == 0 && vs[i].str == NULL)
113 break;
114 if (vs[i].value == val)
115 return vs[i].str;
116 }
117 return "unknown";
118}
119
Harald Welte68b7df22009-08-08 16:03:15 +0200120struct gsm_sms *sms_alloc(void)
121{
122 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
123}
124
125void sms_free(struct gsm_sms *sms)
126{
127 /* drop references to subscriber structure */
128 if (sms->sender)
129 subscr_put(sms->sender);
130 if (sms->receiver)
131 subscr_put(sms->receiver);
132
133 talloc_free(sms);
134}
135
Harald Welte59b04682009-06-10 05:40:52 +0800136struct msgb *gsm411_msgb_alloc(void)
137{
Harald Welte9cfc9352009-06-26 19:39:35 +0200138 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
139 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +0800140}
141
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200142static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800143{
144 if (msg->lchan)
145 msg->trx = msg->lchan->ts->trx;
146
147 msg->l3h = msg->data;
148
Harald Welte68b7df22009-08-08 16:03:15 +0200149 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
150
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200151 return rsl_data_request(msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +0800152}
153
Harald Welte5fa17a22009-08-10 00:24:32 +0200154/* SMC TC1* is expired */
155static void cp_timer_expired(void *data)
156{
157 struct gsm_trans *trans = data;
158
159 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
160 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
161 trans_free(trans);
162}
163
Harald Welte7e2f57d2009-07-04 17:39:00 +0200164/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200165static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
166 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200167{
168 struct gsm48_hdr *gh;
169
170 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
171 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +0200172 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200173 gh->msg_type = msg_type;
174
Harald Welteb78996d2009-07-27 20:11:35 +0200175 /* assign the outgoing lchan */
176 msg->lchan = trans->lchan;
177
178 /* mobile originating */
179 switch (gh->msg_type) {
180 case GSM411_MT_CP_DATA:
181 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Welte09421d32009-08-09 14:59:02 +0200182 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200183 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte5fa17a22009-08-10 00:24:32 +0200184 trans->sms.cp_timer.data = trans;
185 trans->sms.cp_timer.cb = cp_timer_expired;
186 /* 5.3.2.1: Set Timer TC1A */
187 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200188 DEBUGP(DSMS, "TX: CP-DATA ");
189 break;
190 case GSM411_MT_CP_ACK:
191 DEBUGP(DSMS, "TX: CP-ACK ");
192 break;
193 case GSM411_MT_CP_ERROR:
194 DEBUGP(DSMS, "TX: CP-ACK ");
Harald Welteb78996d2009-07-27 20:11:35 +0200195 break;
196 }
197
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200198 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
199
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200200 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200201}
202
203/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200204static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
205 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200206{
207 struct gsm411_rp_hdr *rp;
Harald Weltef2e680b2009-08-10 00:22:19 +0200208 u_int8_t len = msg->len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200209
210 /* GSM 04.11 RP-DATA header */
211 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Weltef2e680b2009-08-10 00:22:19 +0200212 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200213 rp->msg_type = rp_msg_type;
214 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
215
Harald Welteb78996d2009-07-27 20:11:35 +0200216 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200217}
218
Harald Welte68b7df22009-08-08 16:03:15 +0200219static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800220{
221 u_int8_t vp;
222 unsigned long minutes;
223
Harald Welte68b7df22009-08-08 16:03:15 +0200224 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800225 case GSM340_TP_VPF_RELATIVE:
226 /* Chapter 9.2.3.12.1 */
Harald Welte68b7df22009-08-08 16:03:15 +0200227 vp = *(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800228 if (vp <= 143)
229 minutes = vp + 1 * 5;
230 else if (vp <= 167)
231 minutes = 12*60 + (vp-143) * 30;
232 else if (vp <= 196)
233 minutes = vp-166 * 60 * 24;
234 else
235 minutes = vp-192 * 60 * 24 * 7;
236 break;
237 case GSM340_TP_VPF_ABSOLUTE:
238 /* Chapter 9.2.3.12.2 */
239 /* FIXME: like service center time stamp */
240 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
241 break;
242 case GSM340_TP_VPF_ENHANCED:
243 /* Chapter 9.2.3.12.3 */
244 /* FIXME: implementation */
245 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
246 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200247 case GSM340_TP_VPF_NONE:
248 /* Default validity: two days */
249 minutes = 24 * 60 * 2;
250 break;
Harald Welte59b04682009-06-10 05:40:52 +0800251 }
252 return minutes;
253}
254
255/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
256enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
257{
258 u_int8_t cgbits = dcs >> 4;
259 enum sms_alphabet alpha = DCS_NONE;
260
261 if ((cgbits & 0xc) == 0) {
262 if (cgbits & 2)
263 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
264
Daniel Willmannf2861022009-08-15 03:01:17 +0200265 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800266 case 0:
267 alpha = DCS_7BIT_DEFAULT;
268 break;
269 case 1:
270 alpha = DCS_8BIT_DATA;
271 break;
272 case 2:
273 alpha = DCS_UCS2;
274 break;
275 }
276 } else if (cgbits == 0xc || cgbits == 0xd)
277 alpha = DCS_7BIT_DEFAULT;
278 else if (cgbits == 0xe)
279 alpha = DCS_UCS2;
280 else if (cgbits == 0xf) {
281 if (dcs & 4)
282 alpha = DCS_8BIT_DATA;
283 else
284 alpha = DCS_7BIT_DEFAULT;
285 }
286
287 return alpha;
288}
289
Harald Welte68b7df22009-08-08 16:03:15 +0200290static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800291{
292 if (db_sms_store(gsms) != 0) {
293 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200294 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800295 }
Harald Welte68b7df22009-08-08 16:03:15 +0200296 /* dispatch a signal to tell higher level about it */
297 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200298 /* try delivering the SMS right now */
299 //gsm411_send_sms_subscr(gsms->receiver, gsms);
300
Harald Welte59b04682009-06-10 05:40:52 +0800301 return 0;
302}
303
Harald Welte68b7df22009-08-08 16:03:15 +0200304/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
305static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
306 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200307{
Harald Welte68b7df22009-08-08 16:03:15 +0200308 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200309
Harald Welte68b7df22009-08-08 16:03:15 +0200310 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
311
312 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
313
314 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
315 oa[0] = strlen(subscr->extension) & 0xff;
316
317 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200318}
319
320static u_int8_t bcdify(u_int8_t value)
321{
322 u_int8_t ret;
323
Harald Welte68b7df22009-08-08 16:03:15 +0200324 ret = value / 10;
325 ret |= (value % 10) << 4;
Harald Welteb78996d2009-07-27 20:11:35 +0200326
327 return ret;
328}
329
330/* Generate 03.40 TP-SCTS */
331static void gsm340_gen_scts(u_int8_t *scts, time_t time)
332{
333 struct tm *tm = localtime(&time);
Harald Welteb78996d2009-07-27 20:11:35 +0200334
335 *scts++ = bcdify(tm->tm_year % 100);
Stefan Schmidt84b95e52009-08-13 21:00:44 +0200336 *scts++ = bcdify(tm->tm_mon + 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200337 *scts++ = bcdify(tm->tm_mday);
338 *scts++ = bcdify(tm->tm_hour);
339 *scts++ = bcdify(tm->tm_min);
340 *scts++ = bcdify(tm->tm_sec);
341 *scts++ = 0; /* FIXME: timezone */
342}
343
Harald Welte68b7df22009-08-08 16:03:15 +0200344/* generate a msgb containing a TPDU derived from struct gsm_sms,
345 * returns total size of TPDU */
346static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200347{
Harald Welteb78996d2009-07-27 20:11:35 +0200348 u_int8_t *smsp;
349 u_int8_t oa[12]; /* max len per 03.40 */
350 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200351 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200352 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200353
354 /* generate first octet with masked bits */
355 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200356 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200357 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200358 /* TP-MMS (more messages to send) */
359 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200360 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200361 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200362 if (sms->status_rep_req)
363 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200364 /* TP-UDHI (indicating TP-UD contains a header) */
365 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200366 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200367#if 0
368 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200369 if (sms->
370 *smsp |= 0x80;
371#endif
372
373 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200374 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200375 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200376 memcpy(smsp, oa, oa_len);
377
378 /* generate TP-PID */
379 smsp = msgb_put(msg, 1);
380 *smsp = sms->protocol_id;
381
382 /* generate TP-DCS */
383 smsp = msgb_put(msg, 1);
384 *smsp = sms->data_coding_scheme;
385
386 /* generate TP-SCTS */
387 smsp = msgb_put(msg, 7);
388 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200389
Harald Welteb78996d2009-07-27 20:11:35 +0200390 /* generate TP-UDL */
391 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200392 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200393
394 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200395 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
396 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200397 octet_len = sms->user_data_len*7/8;
398 if (sms->user_data_len*7%8 != 0)
399 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200400 /* Warning, user_data_len indicates the amount of septets
401 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200402 smsp = msgb_put(msg, octet_len);
403 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200404 break;
405 case DCS_UCS2:
406 case DCS_8BIT_DATA:
407 smsp = msgb_put(msg, sms->user_data_len);
408 memcpy(smsp, sms->user_data, sms->user_data_len);
409 break;
410 default:
411 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
412 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200413 }
Harald Welteb78996d2009-07-27 20:11:35 +0200414
Harald Welte68b7df22009-08-08 16:03:15 +0200415 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200416}
417
Harald Welte156c5e62009-07-05 14:02:46 +0200418/* process an incoming TPDU (called from RP-DATA)
419 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800420static int gsm340_rx_tpdu(struct msgb *msg)
421{
Harald Welte75350412009-07-23 18:46:00 +0200422 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800423 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800424 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200425 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
426 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800427 u_int8_t da_len_bytes;
428 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
429 int rc = 0;
430
Harald Welte68b7df22009-08-08 16:03:15 +0200431 gsms = sms_alloc();
432 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200433 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800434
435 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200436 sms_mti = *smsp & 0x03;
437 sms_mms = !!(*smsp & 0x04);
438 sms_vpf = (*smsp & 0x18) >> 3;
439 gsms->status_rep_req = (*smsp & 0x20);
440 gsms->ud_hdr_ind = (*smsp & 0x40);
441 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800442
443 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200444 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800445
446 /* length in bytes of the destination address */
447 da_len_bytes = 2 + *smsp/2 + *smsp%2;
448 if (da_len_bytes > 12) {
449 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200450 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800451 goto out;
452 }
Harald Welte3794e152009-06-12 02:42:11 +0800453 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800454 memcpy(address_lv, smsp, da_len_bytes);
455 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800456 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800457 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200458 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800459 smsp += da_len_bytes;
460
Harald Welte68b7df22009-08-08 16:03:15 +0200461 gsms->protocol_id = *smsp++;
462 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800463
Harald Welte68b7df22009-08-08 16:03:15 +0200464 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800465
Harald Welte68b7df22009-08-08 16:03:15 +0200466 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800467 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200468 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800469 break;
470 case GSM340_TP_VPF_ABSOLUTE:
471 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200472 sms_vp = smsp;
Harald Welte59b04682009-06-10 05:40:52 +0800473 smsp += 7;
474 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200475 case GSM340_TP_VPF_NONE:
476 sms_vp = 0;
477 break;
Harald Welte59b04682009-06-10 05:40:52 +0800478 default:
479 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200480 sms_vpf);
481 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800482 }
Harald Welte68b7df22009-08-08 16:03:15 +0200483 gsms->user_data_len = *smsp++;
484 if (gsms->user_data_len) {
485 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800486
Harald Welte68b7df22009-08-08 16:03:15 +0200487 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800488 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200489 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800490 break;
491 case DCS_8BIT_DATA:
492 case DCS_UCS2:
493 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800494 break;
495 }
496 }
497
498 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
499 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte68b7df22009-08-08 16:03:15 +0200500 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
501 gsms->protocol_id, gsms->data_coding_scheme,
502 gsms->dest_addr, gsms->user_data_len,
503 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
504 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800505
Harald Welte68b7df22009-08-08 16:03:15 +0200506 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800507
Harald Welte68b7df22009-08-08 16:03:15 +0200508 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200509
Harald Welte68b7df22009-08-08 16:03:15 +0200510 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200511
Harald Welte59b04682009-06-10 05:40:52 +0800512 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200513 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800514 if (!gsms->receiver) {
515 rc = 1; /* cause 1: unknown subscriber */
516 goto out;
517 }
518
Harald Welte68b7df22009-08-08 16:03:15 +0200519 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800520 case GSM340_SMS_SUBMIT_MS2SC:
521 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200522 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800523 break;
524 case GSM340_SMS_COMMAND_MS2SC:
525 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200526 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200527 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800528 break;
529 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200530 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200531 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800532 break;
533 }
534
Harald Welte156c5e62009-07-05 14:02:46 +0200535 if (!rc && !gsms->receiver)
536 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
537
Harald Welte59b04682009-06-10 05:40:52 +0800538out:
Harald Welte68b7df22009-08-08 16:03:15 +0200539 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800540
541 return rc;
542}
543
Harald Welteb78996d2009-07-27 20:11:35 +0200544static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800545{
546 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800547
Harald Welte59b04682009-06-10 05:40:52 +0800548 DEBUGP(DSMS, "TX: SMS RP ACK\n");
549
Harald Welteb78996d2009-07-27 20:11:35 +0200550 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800551}
552
Harald Welteb78996d2009-07-27 20:11:35 +0200553static int gsm411_send_rp_error(struct gsm_trans *trans,
554 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800555{
556 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800557
Harald Welte59b04682009-06-10 05:40:52 +0800558 msgb_tv_put(msg, 1, cause);
559
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200560 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
561 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800562
Harald Welteb78996d2009-07-27 20:11:35 +0200563 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800564}
565
566/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200567static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
568 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800569 u_int8_t src_len, u_int8_t *src,
570 u_int8_t dst_len, u_int8_t *dst,
571 u_int8_t tpdu_len, u_int8_t *tpdu)
572{
Harald Welte59b04682009-06-10 05:40:52 +0800573 int rc = 0;
574
575 if (src_len && src)
576 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
577
578 if (!dst_len || !dst || !tpdu_len || !tpdu) {
579 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200580 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200581 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800582 return -EIO;
583 }
584 msg->smsh = tpdu;
585
586 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800587
588 rc = gsm340_rx_tpdu(msg);
589 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200590 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800591 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200592 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800593 else
594 return rc;
595}
596
597/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200598static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
599 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800600{
601 u_int8_t src_len, dst_len, rpud_len;
602 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
603
604 /* in the MO case, this should always be zero length */
605 src_len = rph->data[0];
606 if (src_len)
607 src = &rph->data[1];
608
609 dst_len = rph->data[1+src_len];
610 if (dst_len)
611 dst = &rph->data[1+src_len+1];
612
613 rpud_len = rph->data[1+src_len+1+dst_len];
614 if (rpud_len)
615 rp_ud = &rph->data[1+src_len+1+dst_len+1];
616
Harald Welte156c5e62009-07-05 14:02:46 +0200617 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
618 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200619 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800620 rpud_len, rp_ud);
621}
622
Harald Welte09421d32009-08-09 14:59:02 +0200623/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200624static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
625 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200626{
Harald Welte68b7df22009-08-08 16:03:15 +0200627 struct gsm_sms *sms = trans->sms.sms;
628
Harald Welte156c5e62009-07-05 14:02:46 +0200629 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
630 * successfully received a SMS. We can now safely mark it as
631 * transmitted */
632
Harald Welte09421d32009-08-09 14:59:02 +0200633 if (!trans->sms.is_mt) {
634 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
635 return gsm411_send_rp_error(trans, rph->msg_ref,
636 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
637 }
Harald Weltedd62b162009-07-09 23:52:59 +0200638
Harald Welte68b7df22009-08-08 16:03:15 +0200639 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200640 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
641 return gsm411_send_rp_error(trans, rph->msg_ref,
642 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200643 }
644
645 /* mark this SMS as sent in database */
646 db_sms_mark_sent(sms);
647
648 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
649
650 sms_free(sms);
651 trans->sms.sms = NULL;
652
Sylvain Munaut4dd65ae2009-09-27 11:16:22 +0200653 /* free the transaction here */
654 trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200655
656 /* check for more messages for this subscriber */
657 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
658 if (sms)
659 gsm411_send_sms_lchan(msg->lchan, sms);
660 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200661 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200662
663 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200664}
665
Harald Welteb78996d2009-07-27 20:11:35 +0200666static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
667 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200668{
Harald Welte68b7df22009-08-08 16:03:15 +0200669 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200670 u_int8_t cause_len = rph->data[0];
671 u_int8_t cause = rph->data[1];
672
Harald Welte156c5e62009-07-05 14:02:46 +0200673 /* Error in response to MT RP_DATA, i.e. the MS did not
674 * successfully receive the SMS. We need to investigate
675 * the cause and take action depending on it */
676
Holger Hans Peter Freyther80e5ccc2009-10-22 15:40:33 +0200677 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200678 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200679
Harald Welte09421d32009-08-09 14:59:02 +0200680 if (!trans->sms.is_mt) {
681 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200682#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200683 return gsm411_send_rp_error(trans, rph->msg_ref,
684 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200685#endif
Harald Welte09421d32009-08-09 14:59:02 +0200686 }
Harald Weltedd62b162009-07-09 23:52:59 +0200687
Harald Welte68b7df22009-08-08 16:03:15 +0200688 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200689 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200690 return -EINVAL;
691#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200692 return gsm411_send_rp_error(trans, rph->msg_ref,
693 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200694#endif
Harald Welte09421d32009-08-09 14:59:02 +0200695 }
696
697 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
698 /* MS has not enough memory to store the message. We need
699 * to store this in our database and wati for a SMMA message */
700 /* FIXME */
701 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200702 }
703
704 sms_free(sms);
705 trans->sms.sms = NULL;
706
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200707 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200708
Harald Welteb78996d2009-07-27 20:11:35 +0200709 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200710}
711
Harald Welteb78996d2009-07-27 20:11:35 +0200712static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
713 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200714{
Harald Weltefc01b242009-08-09 19:07:41 +0200715 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200716 int rc;
717
Harald Weltefc01b242009-08-09 19:07:41 +0200718 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
719 trans->sms.rp_state = GSM411_RPS_IDLE;
720
Harald Welte156c5e62009-07-05 14:02:46 +0200721 /* MS tells us that it has memory for more SMS, we need
722 * to check if we have any pending messages for it and then
723 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200724 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200725
Harald Weltefc01b242009-08-09 19:07:41 +0200726 /* check for more messages for this subscriber */
727 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
728 if (sms)
729 gsm411_send_sms_lchan(msg->lchan, sms);
730 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200731 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200732
733 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200734}
735
Harald Welteb78996d2009-07-27 20:11:35 +0200736static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
737 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800738{
739 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
740 u_int8_t msg_type = rp_data->msg_type & 0x07;
741 int rc = 0;
742
743 switch (msg_type) {
744 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200745 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
746 /* start TR2N and enter 'wait to send RP-ACK state' */
747 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
748 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800749 break;
750 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200751 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
752 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200753 break;
Harald Welte59b04682009-06-10 05:40:52 +0800754 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200755 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
756 /* start TR2N and enter 'wait to send RP-ACK state' */
757 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
758 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
759 break;
760 case GSM411_MT_RP_ERROR_MO:
761 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800762 break;
763 default:
764 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200765 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
766 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800767 break;
768 }
769
770 return rc;
771}
772
Harald Welteb78996d2009-07-27 20:11:35 +0200773/* send CP-ACK to given transaction */
774static int gsm411_tx_cp_ack(struct gsm_trans *trans)
775{
776 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200777 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200778
Harald Weltefc01b242009-08-09 19:07:41 +0200779 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
780
781 if (trans->sms.is_mt) {
782 /* If this is a MT SMS DELIVER, we can clear transaction here */
783 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200784 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200785 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200786
787 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200788}
789
790static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
791{
792 struct msgb *msg = gsm411_msgb_alloc();
793 u_int8_t *causep;
794
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200795 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
796 get_value_string(cp_cause_strs, cause));
797
Harald Welte68b7df22009-08-08 16:03:15 +0200798 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200799 *causep = cause;
800
801 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
802}
803
804/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200805int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800806{
807 struct gsm48_hdr *gh = msgb_l3(msg);
808 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200809 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
810 struct gsm_lchan *lchan = msg->lchan;
811 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800812 int rc = 0;
813
Harald Welteb78996d2009-07-27 20:11:35 +0200814 if (!lchan->subscr)
815 return -EIO;
816 /* FIXME: send some error message */
817
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200818 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Welteb78996d2009-07-27 20:11:35 +0200819 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
820 transaction_id);
821 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200822 DEBUGPC(DSMS, "(unknown) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200823 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
824 transaction_id, new_callref++);
825 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200826 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200827 /* FIXME: send some error message */
828 return -ENOMEM;
829 }
830 trans->sms.cp_state = GSM411_CPS_IDLE;
831 trans->sms.rp_state = GSM411_RPS_IDLE;
832 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200833 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200834
835 trans->lchan = lchan;
836 use_lchan(lchan);
837 }
838
Harald Welte59b04682009-06-10 05:40:52 +0800839 switch(msg_type) {
840 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200841 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200842 /* 5.2.3.1.3: MO state exists when SMC has received
843 * CP-DATA, including sending of the assoc. CP-ACK */
844 /* 5.2.3.2.4: MT state exists when SMC has received
845 * CP-DATA, including sending of the assoc. CP-ACK */
846 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200847
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200848 /* SMC instance acknowledges the CP-DATA frame */
849 gsm411_tx_cp_ack(trans);
850
Harald Welteb78996d2009-07-27 20:11:35 +0200851 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200852#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200853 /* Send CP-ACK or CP-ERORR in response */
854 if (rc < 0) {
855 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
856 } else
857 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200858#endif
Harald Welte59b04682009-06-10 05:40:52 +0800859 break;
860 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200861 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200862 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200863 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
864 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
865 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +0200866 /* Stop TC1* after CP-ACK has been received */
867 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +0200868
Harald Welteb78996d2009-07-27 20:11:35 +0200869 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200870 /* FIXME: we have sont one CP-DATA, which was now
871 * acknowledged. Check if we want to transfer more,
872 * i.e. multi-part message */
873 trans->sms.cp_state = GSM411_CPS_IDLE;
874 trans_free(trans);
875 }
Harald Welte59b04682009-06-10 05:40:52 +0800876 break;
877 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200878 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
879 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +0200880 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +0200881 trans->sms.cp_state = GSM411_CPS_IDLE;
882 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800883 break;
884 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200885 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200886 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200887 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200888 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800889 break;
890 }
891
Harald Welte59b04682009-06-10 05:40:52 +0800892 return rc;
893}
894
Harald Welte59b04682009-06-10 05:40:52 +0800895#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800896/* Test TPDU - ALL YOUR */
897static u_int8_t tpdu_test[] = {
898 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
899 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
900 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
901 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
902};
903#endif
904
Harald Weltefc01b242009-08-09 19:07:41 +0200905/* Take a SMS in gsm_sms structure and send it through an already
906 * existing lchan. We also assume that the caller ensured this lchan already
907 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +0200908int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800909{
910 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200911 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +0200912 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200913 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +0200914 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +0200915 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800916
Harald Weltefc01b242009-08-09 19:07:41 +0200917 transaction_id = 4; /* FIXME: we always use 4 for now */
918
Harald Welte59b04682009-06-10 05:40:52 +0800919 msg->lchan = lchan;
920
Harald Welte68b7df22009-08-08 16:03:15 +0200921 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200922
Harald Welte68b7df22009-08-08 16:03:15 +0200923 /* FIXME: allocate transaction with message reference */
924 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
925 transaction_id, new_callref++);
926 if (!trans) {
927 DEBUGP(DSMS, "No memory for trans\n");
928 /* FIXME: send some error message */
929 return -ENOMEM;
930 }
931 trans->sms.cp_state = GSM411_CPS_IDLE;
932 trans->sms.rp_state = GSM411_RPS_IDLE;
933 trans->sms.is_mt = 1;
934 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200935 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +0200936
937 trans->lchan = lchan;
938 use_lchan(lchan);
939
940 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800941 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200942 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200943 data[1] = 0x91; /* type of number: international, ISDN */
944 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800945 data[3] = 0x77;
946 data[4] = 0x58;
947 data[5] = 0x10;
948 data[6] = 0x06;
949 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200950
951 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800952 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200953 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800954
Harald Welte68b7df22009-08-08 16:03:15 +0200955 /* obtain a pointer for the rp_ud_len, so we can fill it later */
956 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800957
Harald Welte68b7df22009-08-08 16:03:15 +0200958#if 1
959 /* generate the 03.40 TPDU */
960 rc = gsm340_gen_tpdu(msg, sms);
961 if (rc < 0) {
962 msgb_free(msg);
963 return rc;
964 }
Harald Welte59b04682009-06-10 05:40:52 +0800965
Harald Welte68b7df22009-08-08 16:03:15 +0200966 *rp_ud_len = rc;
967#else
968 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +0800969 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +0200970 *rp_ud_len = sizeof(tpdu_test);
971#endif
Harald Welte59b04682009-06-10 05:40:52 +0800972
Harald Welte68b7df22009-08-08 16:03:15 +0200973 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +0800974
Harald Welteb78996d2009-07-27 20:11:35 +0200975 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
976 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800977}
Harald Welteb78996d2009-07-27 20:11:35 +0200978
Harald Weltefc01b242009-08-09 19:07:41 +0200979/* RLL SAPI3 establish callback. Now we have a RLL connection and
980 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +0200981static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
982 void *_sms, enum bsc_rllr_ind type)
983{
984 struct gsm_sms *sms = _sms;
985
986 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
987 lchan, link_id, sms, type);
988
989 switch (type) {
990 case BSC_RLLR_IND_EST_CONF:
991 gsm411_send_sms_lchan(lchan, sms);
992 break;
993 case BSC_RLLR_IND_REL_IND:
994 case BSC_RLLR_IND_ERR_IND:
995 case BSC_RLLR_IND_TIMEOUT:
996 sms_free(sms);
997 break;
998 }
999}
1000
Harald Weltefc01b242009-08-09 19:07:41 +02001001/* paging callback. Here we get called if paging a subscriber has
1002 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001003static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1004 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001005{
Harald Welte68b7df22009-08-08 16:03:15 +02001006 struct gsm_lchan *lchan = _lchan;
1007 struct gsm_sms *sms = _sms;
1008 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001009
Harald Welte68b7df22009-08-08 16:03:15 +02001010 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1011 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1012
1013 if (hooknum != GSM_HOOK_RR_PAGING)
1014 return -EINVAL;
1015
1016 switch (event) {
1017 case GSM_PAGING_SUCCEEDED:
1018 /* Paging aborted without lchan ?!? */
1019 if (!lchan) {
1020 sms_free(sms);
1021 rc = -EIO;
1022 break;
1023 }
Harald Weltefc01b242009-08-09 19:07:41 +02001024 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001025 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001026 break;
1027 case GSM_PAGING_EXPIRED:
1028 sms_free(sms);
1029 rc = -ETIMEDOUT;
1030 break;
1031 default:
1032 rc = -EINVAL;
1033 break;
1034 }
1035
1036 return rc;
1037}
1038
Harald Weltefc01b242009-08-09 19:07:41 +02001039/* high-level function to send a SMS to a given subscriber. The function
1040 * will take care of paging the subscriber, establishing the RLL SAPI3
1041 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001042int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1043 struct gsm_sms *sms)
1044{
Harald Weltefc01b242009-08-09 19:07:41 +02001045 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001046 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001047
Harald Welte68b7df22009-08-08 16:03:15 +02001048 /* check if we already have an open lchan to the subscriber.
1049 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001050 lchan = lchan_for_subscr(subscr);
1051 if (lchan)
1052 return rll_establish(lchan, UM_SAPI_SMS,
1053 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001054
1055 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001056 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1057 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001058 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001059 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001060
1061 return 0;
1062}
Harald Welte5b359d82009-07-28 00:44:49 +02001063
Harald Weltefc01b242009-08-09 19:07:41 +02001064static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1065 void *handler_data, void *signal_data)
1066{
1067 struct gsm_subscriber *subscr;
1068 struct gsm_lchan *lchan;
1069 struct gsm_sms *sms;
1070
1071 switch (signal) {
1072 case S_SUBSCR_ATTACHED:
1073 /* A subscriber has attached. Check if there are
1074 * any pending SMS for him to be delivered */
1075 subscr = signal_data;
1076 lchan = lchan_for_subscr(subscr);
1077 if (!lchan)
1078 break;
1079 sms = db_sms_get_unsent_for_subscr(subscr);
1080 if (!sms)
1081 break;
1082 /* Establish a SAPI3 RLL connection for SMS */
1083 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1084 break;
1085 default:
1086 break;
1087 }
1088 return 0;
1089}
1090
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001091void _gsm411_sms_trans_free(struct gsm_trans *trans)
1092{
1093 bsc_del_timer(&trans->sms.cp_timer);
1094}
1095
Harald Welte932e20d2009-07-28 00:41:45 +02001096static __attribute__((constructor)) void on_dso_load_sms(void)
1097{
Harald Weltefc01b242009-08-09 19:07:41 +02001098 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001099}