blob: 6290ce6d39b30fb72f0b170b9f1df6ff3fd63a3c [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* 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>
Harald Welte7e310b12009-03-30 20:56:32 +00006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Daniel Willmann8b3390e2008-12-28 00:31:09 +00007 *
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 Weltef3efc592009-07-27 20:11:35 +020031#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
Harald Welte7e310b12009-03-30 20:56:32 +000035#include <openbsc/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000036#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000037#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000041#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000042#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000043#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000044#include <openbsc/db.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Weltef3efc592009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020049#include <openbsc/chan_alloc.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000050
Daniel Willmann471712b2008-12-29 01:54:02 +000051#define GSM411_ALLOC_SIZE 1024
52#define GSM411_ALLOC_HEADROOM 128
53
Harald Weltecb8f4432009-08-09 14:59:02 +020054#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
55
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020056void *tall_gsms_ctx;
Harald Weltef3efc592009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte (local)c89a5112009-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 Welte76042182009-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
Holger Freythera553d092009-01-04 20:16:25 +0000136struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +0000137{
Harald Welte966636f2009-06-26 19:39:35 +0200138 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
139 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +0000140}
141
Harald Welte (local)daef6062009-08-14 11:41:12 +0200142static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Daniel Willmann471712b2008-12-29 01:54:02 +0000143{
144 if (msg->lchan)
145 msg->trx = msg->lchan->ts->trx;
146
147 msg->l3h = msg->data;
148
Harald Welte76042182009-08-08 16:03:15 +0200149 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
150
Harald Welte (local)daef6062009-08-14 11:41:12 +0200151 return rsl_data_request(msg, link_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000152}
153
Harald Welte41985612009-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 Welte87f5d632009-07-04 17:39:00 +0200164/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200165static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
166 u_int8_t msg_type)
Harald Welte87f5d632009-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 Weltef3efc592009-07-27 20:11:35 +0200172 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200173 gh->msg_type = msg_type;
174
Harald Weltef3efc592009-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 Weltecb8f4432009-08-09 14:59:02 +0200182 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200183 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte41985612009-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)c89a5112009-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 Weltef3efc592009-07-27 20:11:35 +0200195 break;
196 }
197
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200198 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
199
Harald Welte (local)daef6062009-08-14 11:41:12 +0200200 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte87f5d632009-07-04 17:39:00 +0200201}
202
203/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-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 Welte87f5d632009-07-04 17:39:00 +0200206{
207 struct gsm411_rp_hdr *rp;
Harald Welte0d544e72009-08-10 00:22:19 +0200208 u_int8_t len = msg->len;
Harald Welte87f5d632009-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 Welte0d544e72009-08-10 00:22:19 +0200212 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200213 rp->msg_type = rp_msg_type;
214 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
215
Harald Weltef3efc592009-07-27 20:11:35 +0200216 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200217}
218
Harald Welte76042182009-08-08 16:03:15 +0200219static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000220{
221 u_int8_t vp;
222 unsigned long minutes;
223
Harald Welte76042182009-08-08 16:03:15 +0200224 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000225 case GSM340_TP_VPF_RELATIVE:
226 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200227 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000228 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 Willmann58c83d82009-08-13 03:40:49 +0200247 case GSM340_TP_VPF_NONE:
248 /* Default validity: two days */
249 minutes = 24 * 60 * 2;
250 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000251 }
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
265 switch (dcs & 3) {
266 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 Welte76042182009-08-08 16:03:15 +0200290static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000291{
292 if (db_sms_store(gsms) != 0) {
293 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200294 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000295 }
Harald Welte76042182009-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 Welte7e310b12009-03-30 20:56:32 +0000298 return 0;
299}
300
Harald Welte76042182009-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 Weltef3efc592009-07-27 20:11:35 +0200304{
Harald Welte76042182009-08-08 16:03:15 +0200305 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200306
Harald Welte76042182009-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 Weltef3efc592009-07-27 20:11:35 +0200315}
316
317static u_int8_t bcdify(u_int8_t value)
318{
319 u_int8_t ret;
320
Harald Welte76042182009-08-08 16:03:15 +0200321 ret = value / 10;
322 ret |= (value % 10) << 4;
Harald Weltef3efc592009-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 Weltef3efc592009-07-27 20:11:35 +0200331
332 *scts++ = bcdify(tm->tm_year % 100);
Stefan Schmidt689537a2009-08-13 21:00:44 +0200333 *scts++ = bcdify(tm->tm_mon + 1);
Harald Weltef3efc592009-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 Welte76042182009-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 Weltef3efc592009-07-27 20:11:35 +0200344{
Harald Weltef3efc592009-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 Willmann9aef1452009-08-13 03:39:07 +0200348 u_int8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200349 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200350
351 /* generate first octet with masked bits */
352 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200353 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200354 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200355 /* TP-MMS (more messages to send) */
356 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200357 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200358 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200359 if (sms->status_rep_req)
360 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200361 /* TP-UDHI (indicating TP-UD contains a header) */
362 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200363 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200364#if 0
365 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200366 if (sms->
367 *smsp |= 0x80;
368#endif
369
370 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200371 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200372 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-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 Welte76042182009-08-08 16:03:15 +0200386
Harald Weltef3efc592009-07-27 20:11:35 +0200387 /* generate TP-UDL */
388 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200389 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200390
391 /* generate TP-UD */
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200392 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
393 case DCS_7BIT_DEFAULT:
Daniel Willmann9aef1452009-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 Willmann6b1e8222009-08-12 21:17:06 +0200397 /* Warning, user_data_len indicates the amount of septets
398 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200399 smsp = msgb_put(msg, octet_len);
400 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b024cb2009-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 Willmann6b1e8222009-08-12 21:17:06 +0200410 }
Harald Weltef3efc592009-07-27 20:11:35 +0200411
Harald Welte76042182009-08-08 16:03:15 +0200412 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200413}
414
Harald Welteb9c758b2009-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 Welte7e310b12009-03-30 20:56:32 +0000417static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000418{
Harald Welte9176bd42009-07-23 18:46:00 +0200419 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000420 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000421 struct gsm_sms *gsms;
Harald Welte76042182009-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 Welte7e310b12009-03-30 20:56:32 +0000424 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;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000427
Harald Welte76042182009-08-08 16:03:15 +0200428 gsms = sms_alloc();
429 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200430 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000431
432 /* invert those fields where 0 means active/present */
Harald Welte76042182009-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);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000439
440 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200441 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000442
Harald Welte7e310b12009-03-30 20:56:32 +0000443 /* 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 Welteb9c758b2009-07-05 14:02:46 +0200447 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000448 goto out;
449 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800450 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000451 memcpy(address_lv, smsp, da_len_bytes);
452 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800453 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000454 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200455 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000456 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000457
Harald Welte76042182009-08-08 16:03:15 +0200458 gsms->protocol_id = *smsp++;
459 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000460
Harald Welte76042182009-08-08 16:03:15 +0200461 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000462
Harald Welte76042182009-08-08 16:03:15 +0200463 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000464 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200465 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000466 break;
467 case GSM340_TP_VPF_ABSOLUTE:
468 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200469 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000470 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000471 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200472 case GSM340_TP_VPF_NONE:
473 sms_vp = 0;
474 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000475 default:
476 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200477 sms_vpf);
478 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000479 }
Harald Welte76042182009-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);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000483
Harald Welte76042182009-08-08 16:03:15 +0200484 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000485 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200486 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000487 break;
488 case DCS_8BIT_DATA:
489 case DCS_UCS2:
490 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000491 break;
492 }
493 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000494
Harald Welte7e310b12009-03-30 20:56:32 +0000495 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 Welte76042182009-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));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000502
Harald Welte76042182009-08-08 16:03:15 +0200503 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000504
Harald Welte76042182009-08-08 16:03:15 +0200505 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200506
Harald Welte76042182009-08-08 16:03:15 +0200507 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200508
Harald Welte7e310b12009-03-30 20:56:32 +0000509 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200510 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000511 if (!gsms->receiver) {
512 rc = 1; /* cause 1: unknown subscriber */
513 goto out;
514 }
515
Harald Welte76042182009-08-08 16:03:15 +0200516 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000517 case GSM340_SMS_SUBMIT_MS2SC:
518 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200519 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000520 break;
521 case GSM340_SMS_COMMAND_MS2SC:
522 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200523 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200524 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000525 break;
526 default:
Harald Welte76042182009-08-08 16:03:15 +0200527 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200528 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000529 break;
530 }
531
Harald Welteb9c758b2009-07-05 14:02:46 +0200532 if (!rc && !gsms->receiver)
533 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
534
Harald Welte7e310b12009-03-30 20:56:32 +0000535out:
Harald Welte76042182009-08-08 16:03:15 +0200536 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000537
Harald Welte7e310b12009-03-30 20:56:32 +0000538 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000539}
540
Harald Weltef3efc592009-07-27 20:11:35 +0200541static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000542{
543 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000544
Daniel Willmann471712b2008-12-29 01:54:02 +0000545 DEBUGP(DSMS, "TX: SMS RP ACK\n");
546
Harald Weltef3efc592009-07-27 20:11:35 +0200547 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000548}
549
Harald Weltef3efc592009-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)
Daniel Willmann471712b2008-12-29 01:54:02 +0000552{
553 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000554
Harald Welte7e310b12009-03-30 20:56:32 +0000555 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000556
Harald Welte (local)c89a5112009-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));
Daniel Willmann471712b2008-12-29 01:54:02 +0000559
Harald Weltef3efc592009-07-27 20:11:35 +0200560 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000561}
562
Harald Welte7e310b12009-03-30 20:56:32 +0000563/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-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 Welte7e310b12009-03-30 20:56:32 +0000566 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)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000569{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000570 int rc = 0;
571
Harald Welte7e310b12009-03-30 20:56:32 +0000572 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 Weltef3efc592009-07-27 20:11:35 +0200577 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200578 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000579 return -EIO;
580 }
581 msg->smsh = tpdu;
582
583 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000584
585 rc = gsm340_rx_tpdu(msg);
586 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200587 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000588 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200589 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000590 else
591 return rc;
592}
593
594/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-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 Welte7e310b12009-03-30 20:56:32 +0000597{
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 Welteb9c758b2009-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 Weltef3efc592009-07-27 20:11:35 +0200616 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000617 rpud_len, rp_ud);
618}
619
Harald Weltecb8f4432009-08-09 14:59:02 +0200620/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200623{
Harald Welte76042182009-08-08 16:03:15 +0200624 struct gsm_sms *sms = trans->sms.sms;
625
Harald Welteb9c758b2009-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 Weltecb8f4432009-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 Welte3e0f6172009-07-09 23:52:59 +0200635
Harald Welte76042182009-08-08 16:03:15 +0200636 if (!sms) {
Harald Weltecb8f4432009-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 Welte76042182009-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 Weltecf6a3812009-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)daef6062009-08-14 11:41:12 +0200657 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte76042182009-08-08 16:03:15 +0200658
659 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200660}
661
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200664{
Harald Welte76042182009-08-08 16:03:15 +0200665 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200666 u_int8_t cause_len = rph->data[0];
667 u_int8_t cause = rph->data[1];
668
Harald Welteb9c758b2009-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)c89a5112009-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 Weltef3efc592009-07-27 20:11:35 +0200675
Harald Weltecb8f4432009-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 Welte3e0f6172009-07-09 23:52:59 +0200681
Harald Welte76042182009-08-08 16:03:15 +0200682 if (!sms) {
Harald Weltecb8f4432009-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 Welte76042182009-08-08 16:03:15 +0200693 }
694
695 sms_free(sms);
696 trans->sms.sms = NULL;
697
Harald Welte (local)86b17172009-08-14 14:52:17 +0200698 //trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200699
Harald Weltef3efc592009-07-27 20:11:35 +0200700 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200701}
702
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200705{
Harald Weltecf6a3812009-08-09 19:07:41 +0200706 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200707 int rc;
708
Harald Weltecf6a3812009-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 Welteb9c758b2009-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 Welte76042182009-08-08 16:03:15 +0200715 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200716
Harald Weltecf6a3812009-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)daef6062009-08-14 11:41:12 +0200722 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Weltef3efc592009-07-27 20:11:35 +0200723
724 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200725}
726
Harald Weltef3efc592009-07-27 20:11:35 +0200727static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
728 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000729{
Daniel Willmann471712b2008-12-29 01:54:02 +0000730 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000731 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000732 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000733
734 switch (msg_type) {
735 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-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 Welte7e310b12009-03-30 20:56:32 +0000740 break;
741 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-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 Welteb9c758b2009-07-05 14:02:46 +0200744 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000745 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-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);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000753 break;
754 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000755 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200756 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
757 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000758 break;
759 }
760
761 return rc;
762}
763
Harald Weltef3efc592009-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 Weltecf6a3812009-08-09 19:07:41 +0200768 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200769
Harald Weltecf6a3812009-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)86b17172009-08-14 14:52:17 +0200775 //trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200776 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200777
778 return rc;
Harald Weltef3efc592009-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)c89a5112009-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 Welte76042182009-08-08 16:03:15 +0200789 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-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)daef6062009-08-14 11:41:12 +0200796int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000797{
798 struct gsm48_hdr *gh = msgb_l3(msg);
799 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-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;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000803 int rc = 0;
804
Harald Weltef3efc592009-07-27 20:11:35 +0200805 if (!lchan->subscr)
806 return -EIO;
807 /* FIXME: send some error message */
808
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200809 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Weltef3efc592009-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)c89a5112009-08-14 10:42:43 +0200813 DEBUGPC(DSMS, "(unknown) ");
Harald Weltef3efc592009-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)c89a5112009-08-14 10:42:43 +0200817 DEBUGPC(DSMS, "No memory for trans\n");
Harald Weltef3efc592009-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)daef6062009-08-14 11:41:12 +0200824 trans->sms.link_id = link_id;
Harald Weltef3efc592009-07-27 20:11:35 +0200825
826 trans->lchan = lchan;
827 use_lchan(lchan);
828 }
829
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000830 switch(msg_type) {
831 case GSM411_MT_CP_DATA:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200832 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-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 Weltef3efc592009-07-27 20:11:35 +0200838
Harald Welte (local)daef6062009-08-14 11:41:12 +0200839 /* SMC instance acknowledges the CP-DATA frame */
840 gsm411_tx_cp_ack(trans);
841
Harald Weltef3efc592009-07-27 20:11:35 +0200842 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200843#if 0
Harald Weltef3efc592009-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)daef6062009-08-14 11:41:12 +0200849#endif
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000850 break;
851 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200852 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200853 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-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 Welte41985612009-08-10 00:24:32 +0200857 /* Stop TC1* after CP-ACK has been received */
858 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200859
Harald Weltef3efc592009-07-27 20:11:35 +0200860 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-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 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000867 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000868 case GSM411_MT_CP_ERROR:
Harald Welte (local)c89a5112009-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 Welte41985612009-08-10 00:24:32 +0200871 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200872 trans->sms.cp_state = GSM411_CPS_IDLE;
873 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000874 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000875 default:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200876 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200877 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200878 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200879 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000880 break;
881 }
882
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000883 return rc;
884}
885
Harald Welte8c2e36e2008-12-30 15:00:14 +0000886#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000887/* 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
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000893};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000894#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000895
Harald Weltecf6a3812009-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 Welte76042182009-08-08 16:03:15 +0200899int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000900{
901 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200902 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200903 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200904 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200905 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200906 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000907
Harald Weltecf6a3812009-08-09 19:07:41 +0200908 transaction_id = 4; /* FIXME: we always use 4 for now */
909
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000910 msg->lchan = lchan;
911
Harald Welte76042182009-08-08 16:03:15 +0200912 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200913
Harald Welte76042182009-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)daef6062009-08-14 11:41:12 +0200926 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +0200927
928 trans->lchan = lchan;
929 use_lchan(lchan);
930
931 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000932 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200933 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200934 data[1] = 0x91; /* type of number: international, ISDN */
935 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000936 data[3] = 0x77;
937 data[4] = 0x58;
938 data[5] = 0x10;
939 data[6] = 0x06;
940 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200941
942 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000943 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200944 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000945
Harald Welte76042182009-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);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000948
Harald Welte76042182009-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 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000956
Harald Welte76042182009-08-08 16:03:15 +0200957 *rp_ud_len = rc;
958#else
959 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000960 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200961 *rp_ud_len = sizeof(tpdu_test);
962#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000963
Harald Welte76042182009-08-08 16:03:15 +0200964 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000965
Harald Weltef3efc592009-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 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000968}
Harald Weltef3efc592009-07-27 20:11:35 +0200969
Harald Weltecf6a3812009-08-09 19:07:41 +0200970/* RLL SAPI3 establish callback. Now we have a RLL connection and
971 * can deliver the actual message */
Harald Weltecb8f4432009-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 Weltecf6a3812009-08-09 19:07:41 +0200992/* paging callback. Here we get called if paging a subscriber has
993 * succeeded or failed. */
Harald Welte76042182009-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 Weltef3efc592009-07-27 20:11:35 +0200996{
Harald Welte76042182009-08-08 16:03:15 +0200997 struct gsm_lchan *lchan = _lchan;
998 struct gsm_sms *sms = _sms;
999 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +02001000
Harald Welte76042182009-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 Weltecf6a3812009-08-09 19:07:41 +02001015 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +02001016 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-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 Weltecf6a3812009-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 Welte76042182009-08-08 16:03:15 +02001033int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1034 struct gsm_sms *sms)
1035{
Harald Weltecf6a3812009-08-09 19:07:41 +02001036 struct gsm_lchan *lchan;
1037
Harald Welte76042182009-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 Weltecf6a3812009-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 Welte76042182009-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 Welte3366a942009-07-28 00:44:49 +02001051
Harald Weltecf6a3812009-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 Luebbe336f8ec2009-08-12 15:18:52 +02001059 u_int32_t token;
1060
Harald Weltecf6a3812009-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)86b17172009-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 Welte7bfc2672009-07-28 00:41:45 +02001086static __attribute__((constructor)) void on_dso_load_sms(void)
1087{
Harald Weltecf6a3812009-08-09 19:07:41 +02001088 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +02001089}