blob: 7a306535967f3063ac680e889187ca666018cb8f [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 Welte59b04682009-06-10 05:40:52 +0800298 return 0;
299}
300
Harald Welte68b7df22009-08-08 16:03:15 +0200301/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
302static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
303 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200304{
Harald Welte68b7df22009-08-08 16:03:15 +0200305 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200306
Harald Welte68b7df22009-08-08 16:03:15 +0200307 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
308
309 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
310
311 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
312 oa[0] = strlen(subscr->extension) & 0xff;
313
314 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200315}
316
317static u_int8_t bcdify(u_int8_t value)
318{
319 u_int8_t ret;
320
Harald Welte68b7df22009-08-08 16:03:15 +0200321 ret = value / 10;
322 ret |= (value % 10) << 4;
Harald Welteb78996d2009-07-27 20:11:35 +0200323
324 return ret;
325}
326
327/* Generate 03.40 TP-SCTS */
328static void gsm340_gen_scts(u_int8_t *scts, time_t time)
329{
330 struct tm *tm = localtime(&time);
Harald Welteb78996d2009-07-27 20:11:35 +0200331
332 *scts++ = bcdify(tm->tm_year % 100);
Stefan Schmidt84b95e52009-08-13 21:00:44 +0200333 *scts++ = bcdify(tm->tm_mon + 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200334 *scts++ = bcdify(tm->tm_mday);
335 *scts++ = bcdify(tm->tm_hour);
336 *scts++ = bcdify(tm->tm_min);
337 *scts++ = bcdify(tm->tm_sec);
338 *scts++ = 0; /* FIXME: timezone */
339}
340
Harald Welte68b7df22009-08-08 16:03:15 +0200341/* generate a msgb containing a TPDU derived from struct gsm_sms,
342 * returns total size of TPDU */
343static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200344{
Harald Welteb78996d2009-07-27 20:11:35 +0200345 u_int8_t *smsp;
346 u_int8_t oa[12]; /* max len per 03.40 */
347 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200348 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200349 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200350
351 /* generate first octet with masked bits */
352 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200353 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200354 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200355 /* TP-MMS (more messages to send) */
356 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200357 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200358 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200359 if (sms->status_rep_req)
360 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200361 /* TP-UDHI (indicating TP-UD contains a header) */
362 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200363 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200364#if 0
365 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200366 if (sms->
367 *smsp |= 0x80;
368#endif
369
370 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200371 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200372 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200373 memcpy(smsp, oa, oa_len);
374
375 /* generate TP-PID */
376 smsp = msgb_put(msg, 1);
377 *smsp = sms->protocol_id;
378
379 /* generate TP-DCS */
380 smsp = msgb_put(msg, 1);
381 *smsp = sms->data_coding_scheme;
382
383 /* generate TP-SCTS */
384 smsp = msgb_put(msg, 7);
385 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200386
Harald Welteb78996d2009-07-27 20:11:35 +0200387 /* generate TP-UDL */
388 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200389 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200390
391 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200392 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
393 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200394 octet_len = sms->user_data_len*7/8;
395 if (sms->user_data_len*7%8 != 0)
396 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200397 /* Warning, user_data_len indicates the amount of septets
398 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200399 smsp = msgb_put(msg, octet_len);
400 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200401 break;
402 case DCS_UCS2:
403 case DCS_8BIT_DATA:
404 smsp = msgb_put(msg, sms->user_data_len);
405 memcpy(smsp, sms->user_data, sms->user_data_len);
406 break;
407 default:
408 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
409 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200410 }
Harald Welteb78996d2009-07-27 20:11:35 +0200411
Harald Welte68b7df22009-08-08 16:03:15 +0200412 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200413}
414
Harald Welte156c5e62009-07-05 14:02:46 +0200415/* process an incoming TPDU (called from RP-DATA)
416 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800417static int gsm340_rx_tpdu(struct msgb *msg)
418{
Harald Welte75350412009-07-23 18:46:00 +0200419 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800420 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800421 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200422 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
423 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800424 u_int8_t da_len_bytes;
425 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
426 int rc = 0;
427
Harald Welte68b7df22009-08-08 16:03:15 +0200428 gsms = sms_alloc();
429 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200430 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800431
432 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200433 sms_mti = *smsp & 0x03;
434 sms_mms = !!(*smsp & 0x04);
435 sms_vpf = (*smsp & 0x18) >> 3;
436 gsms->status_rep_req = (*smsp & 0x20);
437 gsms->ud_hdr_ind = (*smsp & 0x40);
438 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800439
440 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200441 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800442
443 /* length in bytes of the destination address */
444 da_len_bytes = 2 + *smsp/2 + *smsp%2;
445 if (da_len_bytes > 12) {
446 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200447 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800448 goto out;
449 }
Harald Welte3794e152009-06-12 02:42:11 +0800450 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800451 memcpy(address_lv, smsp, da_len_bytes);
452 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800453 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800454 /* convert to real number */
Harald Welte68b7df22009-08-08 16:03:15 +0200455 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800456 smsp += da_len_bytes;
457
Harald Welte68b7df22009-08-08 16:03:15 +0200458 gsms->protocol_id = *smsp++;
459 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800460
Harald Welte68b7df22009-08-08 16:03:15 +0200461 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800462
Harald Welte68b7df22009-08-08 16:03:15 +0200463 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800464 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200465 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800466 break;
467 case GSM340_TP_VPF_ABSOLUTE:
468 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200469 sms_vp = smsp;
Harald Welte59b04682009-06-10 05:40:52 +0800470 smsp += 7;
471 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200472 case GSM340_TP_VPF_NONE:
473 sms_vp = 0;
474 break;
Harald Welte59b04682009-06-10 05:40:52 +0800475 default:
476 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte68b7df22009-08-08 16:03:15 +0200477 sms_vpf);
478 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800479 }
Harald Welte68b7df22009-08-08 16:03:15 +0200480 gsms->user_data_len = *smsp++;
481 if (gsms->user_data_len) {
482 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800483
Harald Welte68b7df22009-08-08 16:03:15 +0200484 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800485 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200486 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800487 break;
488 case DCS_8BIT_DATA:
489 case DCS_UCS2:
490 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800491 break;
492 }
493 }
494
495 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
496 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte68b7df22009-08-08 16:03:15 +0200497 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
498 gsms->protocol_id, gsms->data_coding_scheme,
499 gsms->dest_addr, gsms->user_data_len,
500 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
501 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800502
Harald Welte68b7df22009-08-08 16:03:15 +0200503 gsms->sender = subscr_get(msg->lchan->subscr);
Harald Welte59b04682009-06-10 05:40:52 +0800504
Harald Welte68b7df22009-08-08 16:03:15 +0200505 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200506
Harald Welte68b7df22009-08-08 16:03:15 +0200507 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200508
Harald Welte59b04682009-06-10 05:40:52 +0800509 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200510 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800511 if (!gsms->receiver) {
512 rc = 1; /* cause 1: unknown subscriber */
513 goto out;
514 }
515
Harald Welte68b7df22009-08-08 16:03:15 +0200516 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800517 case GSM340_SMS_SUBMIT_MS2SC:
518 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200519 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800520 break;
521 case GSM340_SMS_COMMAND_MS2SC:
522 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte68b7df22009-08-08 16:03:15 +0200523 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200524 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800525 break;
526 default:
Harald Welte68b7df22009-08-08 16:03:15 +0200527 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200528 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800529 break;
530 }
531
Harald Welte156c5e62009-07-05 14:02:46 +0200532 if (!rc && !gsms->receiver)
533 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
534
Harald Welte59b04682009-06-10 05:40:52 +0800535out:
Harald Welte68b7df22009-08-08 16:03:15 +0200536 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800537
538 return rc;
539}
540
Harald Welteb78996d2009-07-27 20:11:35 +0200541static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800542{
543 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800544
Harald Welte59b04682009-06-10 05:40:52 +0800545 DEBUGP(DSMS, "TX: SMS RP ACK\n");
546
Harald Welteb78996d2009-07-27 20:11:35 +0200547 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800548}
549
Harald Welteb78996d2009-07-27 20:11:35 +0200550static int gsm411_send_rp_error(struct gsm_trans *trans,
551 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800552{
553 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800554
Harald Welte59b04682009-06-10 05:40:52 +0800555 msgb_tv_put(msg, 1, cause);
556
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200557 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
558 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800559
Harald Welteb78996d2009-07-27 20:11:35 +0200560 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800561}
562
563/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200564static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
565 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800566 u_int8_t src_len, u_int8_t *src,
567 u_int8_t dst_len, u_int8_t *dst,
568 u_int8_t tpdu_len, u_int8_t *tpdu)
569{
Harald Welte59b04682009-06-10 05:40:52 +0800570 int rc = 0;
571
572 if (src_len && src)
573 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
574
575 if (!dst_len || !dst || !tpdu_len || !tpdu) {
576 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200577 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200578 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800579 return -EIO;
580 }
581 msg->smsh = tpdu;
582
583 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800584
585 rc = gsm340_rx_tpdu(msg);
586 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200587 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800588 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200589 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800590 else
591 return rc;
592}
593
594/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200595static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
596 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800597{
598 u_int8_t src_len, dst_len, rpud_len;
599 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
600
601 /* in the MO case, this should always be zero length */
602 src_len = rph->data[0];
603 if (src_len)
604 src = &rph->data[1];
605
606 dst_len = rph->data[1+src_len];
607 if (dst_len)
608 dst = &rph->data[1+src_len+1];
609
610 rpud_len = rph->data[1+src_len+1+dst_len];
611 if (rpud_len)
612 rp_ud = &rph->data[1+src_len+1+dst_len+1];
613
Harald Welte156c5e62009-07-05 14:02:46 +0200614 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
615 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200616 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800617 rpud_len, rp_ud);
618}
619
Harald Welte09421d32009-08-09 14:59:02 +0200620/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200621static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
622 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200623{
Harald Welte68b7df22009-08-08 16:03:15 +0200624 struct gsm_sms *sms = trans->sms.sms;
625
Harald Welte156c5e62009-07-05 14:02:46 +0200626 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
627 * successfully received a SMS. We can now safely mark it as
628 * transmitted */
629
Harald Welte09421d32009-08-09 14:59:02 +0200630 if (!trans->sms.is_mt) {
631 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
632 return gsm411_send_rp_error(trans, rph->msg_ref,
633 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
634 }
Harald Weltedd62b162009-07-09 23:52:59 +0200635
Harald Welte68b7df22009-08-08 16:03:15 +0200636 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200637 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
638 return gsm411_send_rp_error(trans, rph->msg_ref,
639 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200640 }
641
642 /* mark this SMS as sent in database */
643 db_sms_mark_sent(sms);
644
645 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
646
647 sms_free(sms);
648 trans->sms.sms = NULL;
649
Harald Weltefc01b242009-08-09 19:07:41 +0200650 /* do not free the transaction here, this is done by sending CP-ACK */
651
652 /* check for more messages for this subscriber */
653 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
654 if (sms)
655 gsm411_send_sms_lchan(msg->lchan, sms);
656 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200657 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200658
659 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200660}
661
Harald Welteb78996d2009-07-27 20:11:35 +0200662static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
663 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200664{
Harald Welte68b7df22009-08-08 16:03:15 +0200665 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200666 u_int8_t cause_len = rph->data[0];
667 u_int8_t cause = rph->data[1];
668
Harald Welte156c5e62009-07-05 14:02:46 +0200669 /* Error in response to MT RP_DATA, i.e. the MS did not
670 * successfully receive the SMS. We need to investigate
671 * the cause and take action depending on it */
672
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200673 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d (%s)\n", cause,
674 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200675
Harald Welte09421d32009-08-09 14:59:02 +0200676 if (!trans->sms.is_mt) {
677 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
678 return gsm411_send_rp_error(trans, rph->msg_ref,
679 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
680 }
Harald Weltedd62b162009-07-09 23:52:59 +0200681
Harald Welte68b7df22009-08-08 16:03:15 +0200682 if (!sms) {
Harald Welte09421d32009-08-09 14:59:02 +0200683 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
684 return gsm411_send_rp_error(trans, rph->msg_ref,
685 GSM411_RP_CAUSE_PROTOCOL_ERR);
686 }
687
688 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
689 /* MS has not enough memory to store the message. We need
690 * to store this in our database and wati for a SMMA message */
691 /* FIXME */
692 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte68b7df22009-08-08 16:03:15 +0200693 }
694
695 sms_free(sms);
696 trans->sms.sms = NULL;
697
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200698 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200699
Harald Welteb78996d2009-07-27 20:11:35 +0200700 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200701}
702
Harald Welteb78996d2009-07-27 20:11:35 +0200703static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
704 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200705{
Harald Weltefc01b242009-08-09 19:07:41 +0200706 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200707 int rc;
708
Harald Weltefc01b242009-08-09 19:07:41 +0200709 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
710 trans->sms.rp_state = GSM411_RPS_IDLE;
711
Harald Welte156c5e62009-07-05 14:02:46 +0200712 /* MS tells us that it has memory for more SMS, we need
713 * to check if we have any pending messages for it and then
714 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200715 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200716
Harald Weltefc01b242009-08-09 19:07:41 +0200717 /* check for more messages for this subscriber */
718 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
719 if (sms)
720 gsm411_send_sms_lchan(msg->lchan, sms);
721 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200722 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200723
724 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200725}
726
Harald Welteb78996d2009-07-27 20:11:35 +0200727static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
728 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800729{
730 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
731 u_int8_t msg_type = rp_data->msg_type & 0x07;
732 int rc = 0;
733
734 switch (msg_type) {
735 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200736 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
737 /* start TR2N and enter 'wait to send RP-ACK state' */
738 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
739 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800740 break;
741 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200742 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
743 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200744 break;
Harald Welte59b04682009-06-10 05:40:52 +0800745 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200746 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
747 /* start TR2N and enter 'wait to send RP-ACK state' */
748 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
749 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
750 break;
751 case GSM411_MT_RP_ERROR_MO:
752 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800753 break;
754 default:
755 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200756 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
757 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800758 break;
759 }
760
761 return rc;
762}
763
Harald Welteb78996d2009-07-27 20:11:35 +0200764/* send CP-ACK to given transaction */
765static int gsm411_tx_cp_ack(struct gsm_trans *trans)
766{
767 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200768 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200769
Harald Weltefc01b242009-08-09 19:07:41 +0200770 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
771
772 if (trans->sms.is_mt) {
773 /* If this is a MT SMS DELIVER, we can clear transaction here */
774 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200775 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200776 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200777
778 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200779}
780
781static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
782{
783 struct msgb *msg = gsm411_msgb_alloc();
784 u_int8_t *causep;
785
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200786 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
787 get_value_string(cp_cause_strs, cause));
788
Harald Welte68b7df22009-08-08 16:03:15 +0200789 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200790 *causep = cause;
791
792 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
793}
794
795/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200796int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800797{
798 struct gsm48_hdr *gh = msgb_l3(msg);
799 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200800 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
801 struct gsm_lchan *lchan = msg->lchan;
802 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800803 int rc = 0;
804
Harald Welteb78996d2009-07-27 20:11:35 +0200805 if (!lchan->subscr)
806 return -EIO;
807 /* FIXME: send some error message */
808
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200809 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Welteb78996d2009-07-27 20:11:35 +0200810 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
811 transaction_id);
812 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200813 DEBUGPC(DSMS, "(unknown) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200814 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
815 transaction_id, new_callref++);
816 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200817 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200818 /* FIXME: send some error message */
819 return -ENOMEM;
820 }
821 trans->sms.cp_state = GSM411_CPS_IDLE;
822 trans->sms.rp_state = GSM411_RPS_IDLE;
823 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200824 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200825
826 trans->lchan = lchan;
827 use_lchan(lchan);
828 }
829
Harald Welte59b04682009-06-10 05:40:52 +0800830 switch(msg_type) {
831 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200832 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Welte09421d32009-08-09 14:59:02 +0200833 /* 5.2.3.1.3: MO state exists when SMC has received
834 * CP-DATA, including sending of the assoc. CP-ACK */
835 /* 5.2.3.2.4: MT state exists when SMC has received
836 * CP-DATA, including sending of the assoc. CP-ACK */
837 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200838
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200839 /* SMC instance acknowledges the CP-DATA frame */
840 gsm411_tx_cp_ack(trans);
841
Harald Welteb78996d2009-07-27 20:11:35 +0200842 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200843#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200844 /* Send CP-ACK or CP-ERORR in response */
845 if (rc < 0) {
846 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
847 } else
848 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200849#endif
Harald Welte59b04682009-06-10 05:40:52 +0800850 break;
851 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200852 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200853 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200854 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
855 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
856 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +0200857 /* Stop TC1* after CP-ACK has been received */
858 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +0200859
Harald Welteb78996d2009-07-27 20:11:35 +0200860 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +0200861 /* FIXME: we have sont one CP-DATA, which was now
862 * acknowledged. Check if we want to transfer more,
863 * i.e. multi-part message */
864 trans->sms.cp_state = GSM411_CPS_IDLE;
865 trans_free(trans);
866 }
Harald Welte59b04682009-06-10 05:40:52 +0800867 break;
868 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200869 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
870 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +0200871 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +0200872 trans->sms.cp_state = GSM411_CPS_IDLE;
873 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800874 break;
875 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200876 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200877 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +0200878 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +0200879 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +0800880 break;
881 }
882
Harald Welte59b04682009-06-10 05:40:52 +0800883 return rc;
884}
885
Harald Welte59b04682009-06-10 05:40:52 +0800886#if 0
Harald Welte59b04682009-06-10 05:40:52 +0800887/* Test TPDU - ALL YOUR */
888static u_int8_t tpdu_test[] = {
889 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
890 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
891 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
892 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
893};
894#endif
895
Harald Weltefc01b242009-08-09 19:07:41 +0200896/* Take a SMS in gsm_sms structure and send it through an already
897 * existing lchan. We also assume that the caller ensured this lchan already
898 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +0200899int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +0800900{
901 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +0200902 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +0200903 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200904 u_int8_t msg_ref = 42;
Harald Weltefc01b242009-08-09 19:07:41 +0200905 u_int8_t transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +0200906 int rc;
Harald Welte59b04682009-06-10 05:40:52 +0800907
Harald Weltefc01b242009-08-09 19:07:41 +0200908 transaction_id = 4; /* FIXME: we always use 4 for now */
909
Harald Welte59b04682009-06-10 05:40:52 +0800910 msg->lchan = lchan;
911
Harald Welte68b7df22009-08-08 16:03:15 +0200912 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200913
Harald Welte68b7df22009-08-08 16:03:15 +0200914 /* FIXME: allocate transaction with message reference */
915 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
916 transaction_id, new_callref++);
917 if (!trans) {
918 DEBUGP(DSMS, "No memory for trans\n");
919 /* FIXME: send some error message */
920 return -ENOMEM;
921 }
922 trans->sms.cp_state = GSM411_CPS_IDLE;
923 trans->sms.rp_state = GSM411_RPS_IDLE;
924 trans->sms.is_mt = 1;
925 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200926 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +0200927
928 trans->lchan = lchan;
929 use_lchan(lchan);
930
931 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +0800932 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200933 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +0200934 data[1] = 0x91; /* type of number: international, ISDN */
935 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +0800936 data[3] = 0x77;
937 data[4] = 0x58;
938 data[5] = 0x10;
939 data[6] = 0x06;
940 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200941
942 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +0800943 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200944 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +0800945
Harald Welte68b7df22009-08-08 16:03:15 +0200946 /* obtain a pointer for the rp_ud_len, so we can fill it later */
947 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800948
Harald Welte68b7df22009-08-08 16:03:15 +0200949#if 1
950 /* generate the 03.40 TPDU */
951 rc = gsm340_gen_tpdu(msg, sms);
952 if (rc < 0) {
953 msgb_free(msg);
954 return rc;
955 }
Harald Welte59b04682009-06-10 05:40:52 +0800956
Harald Welte68b7df22009-08-08 16:03:15 +0200957 *rp_ud_len = rc;
958#else
959 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +0800960 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +0200961 *rp_ud_len = sizeof(tpdu_test);
962#endif
Harald Welte59b04682009-06-10 05:40:52 +0800963
Harald Welte68b7df22009-08-08 16:03:15 +0200964 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +0800965
Harald Welteb78996d2009-07-27 20:11:35 +0200966 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
967 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +0800968}
Harald Welteb78996d2009-07-27 20:11:35 +0200969
Harald Weltefc01b242009-08-09 19:07:41 +0200970/* RLL SAPI3 establish callback. Now we have a RLL connection and
971 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +0200972static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
973 void *_sms, enum bsc_rllr_ind type)
974{
975 struct gsm_sms *sms = _sms;
976
977 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
978 lchan, link_id, sms, type);
979
980 switch (type) {
981 case BSC_RLLR_IND_EST_CONF:
982 gsm411_send_sms_lchan(lchan, sms);
983 break;
984 case BSC_RLLR_IND_REL_IND:
985 case BSC_RLLR_IND_ERR_IND:
986 case BSC_RLLR_IND_TIMEOUT:
987 sms_free(sms);
988 break;
989 }
990}
991
Harald Weltefc01b242009-08-09 19:07:41 +0200992/* paging callback. Here we get called if paging a subscriber has
993 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +0200994static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
995 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200996{
Harald Welte68b7df22009-08-08 16:03:15 +0200997 struct gsm_lchan *lchan = _lchan;
998 struct gsm_sms *sms = _sms;
999 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001000
Harald Welte68b7df22009-08-08 16:03:15 +02001001 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1002 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1003
1004 if (hooknum != GSM_HOOK_RR_PAGING)
1005 return -EINVAL;
1006
1007 switch (event) {
1008 case GSM_PAGING_SUCCEEDED:
1009 /* Paging aborted without lchan ?!? */
1010 if (!lchan) {
1011 sms_free(sms);
1012 rc = -EIO;
1013 break;
1014 }
Harald Weltefc01b242009-08-09 19:07:41 +02001015 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001016 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001017 break;
1018 case GSM_PAGING_EXPIRED:
1019 sms_free(sms);
1020 rc = -ETIMEDOUT;
1021 break;
1022 default:
1023 rc = -EINVAL;
1024 break;
1025 }
1026
1027 return rc;
1028}
1029
Harald Weltefc01b242009-08-09 19:07:41 +02001030/* high-level function to send a SMS to a given subscriber. The function
1031 * will take care of paging the subscriber, establishing the RLL SAPI3
1032 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001033int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1034 struct gsm_sms *sms)
1035{
Harald Weltefc01b242009-08-09 19:07:41 +02001036 struct gsm_lchan *lchan;
1037
Harald Welte68b7df22009-08-08 16:03:15 +02001038 /* check if we already have an open lchan to the subscriber.
1039 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001040 lchan = lchan_for_subscr(subscr);
1041 if (lchan)
1042 return rll_establish(lchan, UM_SAPI_SMS,
1043 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001044
1045 /* if not, we have to start paging */
1046 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1047 paging_cb_send_sms, sms);
1048
1049 return 0;
1050}
Harald Welte5b359d82009-07-28 00:44:49 +02001051
Harald Weltefc01b242009-08-09 19:07:41 +02001052static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1053 void *handler_data, void *signal_data)
1054{
1055 struct gsm_subscriber *subscr;
1056 struct gsm_lchan *lchan;
1057 struct gsm_sms *sms;
1058
Jan Luebbebab4a2a2009-08-12 15:18:52 +02001059 u_int32_t token;
1060
Harald Weltefc01b242009-08-09 19:07:41 +02001061 switch (signal) {
1062 case S_SUBSCR_ATTACHED:
1063 /* A subscriber has attached. Check if there are
1064 * any pending SMS for him to be delivered */
1065 subscr = signal_data;
1066 lchan = lchan_for_subscr(subscr);
1067 if (!lchan)
1068 break;
1069 sms = db_sms_get_unsent_for_subscr(subscr);
1070 if (!sms)
1071 break;
1072 /* Establish a SAPI3 RLL connection for SMS */
1073 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1074 break;
1075 default:
1076 break;
1077 }
1078 return 0;
1079}
1080
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001081void _gsm411_sms_trans_free(struct gsm_trans *trans)
1082{
1083 bsc_del_timer(&trans->sms.cp_timer);
1084}
1085
Harald Welte932e20d2009-07-28 00:41:45 +02001086static __attribute__((constructor)) void on_dso_load_sms(void)
1087{
Harald Weltefc01b242009-08-09 19:07:41 +02001088 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001089}