blob: 85fd6b690ff69c873b4081e4ccf00fc8c6a46272 [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
Daniel Willmannd5d5e1d2009-08-15 03:01:17 +0200265 switch ((dcs >> 2)&0x03) {
Harald Welte7e310b12009-03-30 20:56:32 +0000266 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 Welte (local)ee4410a2009-08-17 09:39:55 +0200298 /* try delivering the SMS right now */
299 //gsm411_send_sms_subscr(gsms->receiver, gsms);
300
Harald Welte7e310b12009-03-30 20:56:32 +0000301 return 0;
302}
303
Harald Welte76042182009-08-08 16:03:15 +0200304/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
305static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
306 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200307{
Harald Welte76042182009-08-08 16:03:15 +0200308 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200309
Harald Welte76042182009-08-08 16:03:15 +0200310 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
311
312 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
313
314 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
315 oa[0] = strlen(subscr->extension) & 0xff;
316
317 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200318}
319
320static u_int8_t bcdify(u_int8_t value)
321{
322 u_int8_t ret;
323
Harald Welte76042182009-08-08 16:03:15 +0200324 ret = value / 10;
325 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200326
327 return ret;
328}
329
330/* Generate 03.40 TP-SCTS */
331static void gsm340_gen_scts(u_int8_t *scts, time_t time)
332{
333 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200334
335 *scts++ = bcdify(tm->tm_year % 100);
Stefan Schmidt689537a2009-08-13 21:00:44 +0200336 *scts++ = bcdify(tm->tm_mon + 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200337 *scts++ = bcdify(tm->tm_mday);
338 *scts++ = bcdify(tm->tm_hour);
339 *scts++ = bcdify(tm->tm_min);
340 *scts++ = bcdify(tm->tm_sec);
341 *scts++ = 0; /* FIXME: timezone */
342}
343
Harald Welte76042182009-08-08 16:03:15 +0200344/* generate a msgb containing a TPDU derived from struct gsm_sms,
345 * returns total size of TPDU */
346static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200347{
Harald Weltef3efc592009-07-27 20:11:35 +0200348 u_int8_t *smsp;
349 u_int8_t oa[12]; /* max len per 03.40 */
350 u_int8_t oa_len = 0;
Daniel Willmann9aef1452009-08-13 03:39:07 +0200351 u_int8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200352 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200353
354 /* generate first octet with masked bits */
355 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200356 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200357 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200358 /* TP-MMS (more messages to send) */
359 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200360 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200361 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200362 if (sms->status_rep_req)
363 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200364 /* TP-UDHI (indicating TP-UD contains a header) */
365 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200366 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200367#if 0
368 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200369 if (sms->
370 *smsp |= 0x80;
371#endif
372
373 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200374 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200375 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200376 memcpy(smsp, oa, oa_len);
377
378 /* generate TP-PID */
379 smsp = msgb_put(msg, 1);
380 *smsp = sms->protocol_id;
381
382 /* generate TP-DCS */
383 smsp = msgb_put(msg, 1);
384 *smsp = sms->data_coding_scheme;
385
386 /* generate TP-SCTS */
387 smsp = msgb_put(msg, 7);
388 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200389
Harald Weltef3efc592009-07-27 20:11:35 +0200390 /* generate TP-UDL */
391 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200392 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200393
394 /* generate TP-UD */
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200395 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
396 case DCS_7BIT_DEFAULT:
Daniel Willmann9aef1452009-08-13 03:39:07 +0200397 octet_len = sms->user_data_len*7/8;
398 if (sms->user_data_len*7%8 != 0)
399 octet_len++;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200400 /* Warning, user_data_len indicates the amount of septets
401 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200402 smsp = msgb_put(msg, octet_len);
403 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200404 break;
405 case DCS_UCS2:
406 case DCS_8BIT_DATA:
407 smsp = msgb_put(msg, sms->user_data_len);
408 memcpy(smsp, sms->user_data, sms->user_data_len);
409 break;
410 default:
411 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
412 break;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200413 }
Harald Weltef3efc592009-07-27 20:11:35 +0200414
Harald Welte76042182009-08-08 16:03:15 +0200415 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200416}
417
Harald Welteb9c758b2009-07-05 14:02:46 +0200418/* process an incoming TPDU (called from RP-DATA)
419 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000420static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000421{
Harald Welte9176bd42009-07-23 18:46:00 +0200422 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000423 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000424 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200425 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
426 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000427 u_int8_t da_len_bytes;
428 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
429 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000430
Harald Welte76042182009-08-08 16:03:15 +0200431 gsms = sms_alloc();
432 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200433 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000434
435 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200436 sms_mti = *smsp & 0x03;
437 sms_mms = !!(*smsp & 0x04);
438 sms_vpf = (*smsp & 0x18) >> 3;
439 gsms->status_rep_req = (*smsp & 0x20);
440 gsms->ud_hdr_ind = (*smsp & 0x40);
441 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000442
443 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200444 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000445
Harald Welte7e310b12009-03-30 20:56:32 +0000446 /* length in bytes of the destination address */
447 da_len_bytes = 2 + *smsp/2 + *smsp%2;
448 if (da_len_bytes > 12) {
449 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200450 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000451 goto out;
452 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800453 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000454 memcpy(address_lv, smsp, da_len_bytes);
455 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800456 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000457 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200458 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000459 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000460
Harald Welte76042182009-08-08 16:03:15 +0200461 gsms->protocol_id = *smsp++;
462 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000463
Harald Welte76042182009-08-08 16:03:15 +0200464 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000465
Harald Welte76042182009-08-08 16:03:15 +0200466 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000467 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200468 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000469 break;
470 case GSM340_TP_VPF_ABSOLUTE:
471 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200472 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000473 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000474 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200475 case GSM340_TP_VPF_NONE:
476 sms_vp = 0;
477 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000478 default:
479 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200480 sms_vpf);
481 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000482 }
Harald Welte76042182009-08-08 16:03:15 +0200483 gsms->user_data_len = *smsp++;
484 if (gsms->user_data_len) {
485 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000486
Harald Welte76042182009-08-08 16:03:15 +0200487 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000488 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200489 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000490 break;
491 case DCS_8BIT_DATA:
492 case DCS_UCS2:
493 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000494 break;
495 }
496 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000497
Harald Welte7e310b12009-03-30 20:56:32 +0000498 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
499 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200500 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
501 gsms->protocol_id, gsms->data_coding_scheme,
502 gsms->dest_addr, gsms->user_data_len,
503 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
504 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000505
Harald Welte76042182009-08-08 16:03:15 +0200506 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000507
Harald Welte76042182009-08-08 16:03:15 +0200508 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200509
Harald Welte76042182009-08-08 16:03:15 +0200510 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200511
Harald Welte7e310b12009-03-30 20:56:32 +0000512 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200513 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000514 if (!gsms->receiver) {
515 rc = 1; /* cause 1: unknown subscriber */
516 goto out;
517 }
518
Harald Welte76042182009-08-08 16:03:15 +0200519 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000520 case GSM340_SMS_SUBMIT_MS2SC:
521 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200522 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000523 break;
524 case GSM340_SMS_COMMAND_MS2SC:
525 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200526 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200527 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000528 break;
529 default:
Harald Welte76042182009-08-08 16:03:15 +0200530 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200531 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000532 break;
533 }
534
Harald Welteb9c758b2009-07-05 14:02:46 +0200535 if (!rc && !gsms->receiver)
536 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
537
Harald Welte7e310b12009-03-30 20:56:32 +0000538out:
Harald Welte76042182009-08-08 16:03:15 +0200539 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000540
Harald Welte7e310b12009-03-30 20:56:32 +0000541 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000542}
543
Harald Weltef3efc592009-07-27 20:11:35 +0200544static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000545{
546 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000547
Daniel Willmann471712b2008-12-29 01:54:02 +0000548 DEBUGP(DSMS, "TX: SMS RP ACK\n");
549
Harald Weltef3efc592009-07-27 20:11:35 +0200550 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000551}
552
Harald Weltef3efc592009-07-27 20:11:35 +0200553static int gsm411_send_rp_error(struct gsm_trans *trans,
554 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000555{
556 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000557
Harald Welte7e310b12009-03-30 20:56:32 +0000558 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000559
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200560 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
561 get_value_string(rp_cause_strs, cause));
Daniel Willmann471712b2008-12-29 01:54:02 +0000562
Harald Weltef3efc592009-07-27 20:11:35 +0200563 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000564}
565
Harald Welte7e310b12009-03-30 20:56:32 +0000566/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200567static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
568 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000569 u_int8_t src_len, u_int8_t *src,
570 u_int8_t dst_len, u_int8_t *dst,
571 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000572{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000573 int rc = 0;
574
Harald Welte7e310b12009-03-30 20:56:32 +0000575 if (src_len && src)
576 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
577
578 if (!dst_len || !dst || !tpdu_len || !tpdu) {
579 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200580 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200581 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000582 return -EIO;
583 }
584 msg->smsh = tpdu;
585
586 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000587
588 rc = gsm340_rx_tpdu(msg);
589 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200590 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000591 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200592 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000593 else
594 return rc;
595}
596
597/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200598static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
599 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000600{
601 u_int8_t src_len, dst_len, rpud_len;
602 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
603
604 /* in the MO case, this should always be zero length */
605 src_len = rph->data[0];
606 if (src_len)
607 src = &rph->data[1];
608
609 dst_len = rph->data[1+src_len];
610 if (dst_len)
611 dst = &rph->data[1+src_len+1];
612
613 rpud_len = rph->data[1+src_len+1+dst_len];
614 if (rpud_len)
615 rp_ud = &rph->data[1+src_len+1+dst_len+1];
616
Harald Welteb9c758b2009-07-05 14:02:46 +0200617 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
618 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200619 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000620 rpud_len, rp_ud);
621}
622
Harald Weltecb8f4432009-08-09 14:59:02 +0200623/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200624static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
625 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200626{
Harald Welte76042182009-08-08 16:03:15 +0200627 struct gsm_sms *sms = trans->sms.sms;
628
Harald Welteb9c758b2009-07-05 14:02:46 +0200629 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
630 * successfully received a SMS. We can now safely mark it as
631 * transmitted */
632
Harald Weltecb8f4432009-08-09 14:59:02 +0200633 if (!trans->sms.is_mt) {
634 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
635 return gsm411_send_rp_error(trans, rph->msg_ref,
636 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
637 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200638
Harald Welte76042182009-08-08 16:03:15 +0200639 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200640 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
641 return gsm411_send_rp_error(trans, rph->msg_ref,
642 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200643 }
644
645 /* mark this SMS as sent in database */
646 db_sms_mark_sent(sms);
647
648 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
649
650 sms_free(sms);
651 trans->sms.sms = NULL;
652
Harald Weltecf6a3812009-08-09 19:07:41 +0200653 /* do not free the transaction here, this is done by sending CP-ACK */
654
655 /* check for more messages for this subscriber */
656 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
657 if (sms)
658 gsm411_send_sms_lchan(msg->lchan, sms);
659 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200660 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte76042182009-08-08 16:03:15 +0200661
662 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200663}
664
Harald Weltef3efc592009-07-27 20:11:35 +0200665static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
666 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200667{
Harald Welte76042182009-08-08 16:03:15 +0200668 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200669 u_int8_t cause_len = rph->data[0];
670 u_int8_t cause = rph->data[1];
671
Harald Welteb9c758b2009-07-05 14:02:46 +0200672 /* Error in response to MT RP_DATA, i.e. the MS did not
673 * successfully receive the SMS. We need to investigate
674 * the cause and take action depending on it */
675
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200676 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d (%s)\n", cause,
677 get_value_string(rp_cause_strs, cause));
Harald Weltef3efc592009-07-27 20:11:35 +0200678
Harald Weltecb8f4432009-08-09 14:59:02 +0200679 if (!trans->sms.is_mt) {
680 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200681#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200682 return gsm411_send_rp_error(trans, rph->msg_ref,
683 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200684#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200685 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200686
Harald Welte76042182009-08-08 16:03:15 +0200687 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200688 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200689 return -EINVAL;
690#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200691 return gsm411_send_rp_error(trans, rph->msg_ref,
692 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200693#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200694 }
695
696 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
697 /* MS has not enough memory to store the message. We need
698 * to store this in our database and wati for a SMMA message */
699 /* FIXME */
700 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200701 }
702
703 sms_free(sms);
704 trans->sms.sms = NULL;
705
Harald Welte (local)86b17172009-08-14 14:52:17 +0200706 //trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200707
Harald Weltef3efc592009-07-27 20:11:35 +0200708 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200709}
710
Harald Weltef3efc592009-07-27 20:11:35 +0200711static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
712 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200713{
Harald Weltecf6a3812009-08-09 19:07:41 +0200714 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200715 int rc;
716
Harald Weltecf6a3812009-08-09 19:07:41 +0200717 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
718 trans->sms.rp_state = GSM411_RPS_IDLE;
719
Harald Welteb9c758b2009-07-05 14:02:46 +0200720 /* MS tells us that it has memory for more SMS, we need
721 * to check if we have any pending messages for it and then
722 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200723 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200724
Harald Weltecf6a3812009-08-09 19:07:41 +0200725 /* check for more messages for this subscriber */
726 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
727 if (sms)
728 gsm411_send_sms_lchan(msg->lchan, sms);
729 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200730 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Weltef3efc592009-07-27 20:11:35 +0200731
732 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200733}
734
Harald Weltef3efc592009-07-27 20:11:35 +0200735static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
736 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000737{
Daniel Willmann471712b2008-12-29 01:54:02 +0000738 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000739 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000740 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000741
742 switch (msg_type) {
743 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200744 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
745 /* start TR2N and enter 'wait to send RP-ACK state' */
746 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
747 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000748 break;
749 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200750 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
751 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200752 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000753 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200754 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
755 /* start TR2N and enter 'wait to send RP-ACK state' */
756 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
757 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
758 break;
759 case GSM411_MT_RP_ERROR_MO:
760 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000761 break;
762 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000763 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200764 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
765 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000766 break;
767 }
768
769 return rc;
770}
771
Harald Weltef3efc592009-07-27 20:11:35 +0200772/* send CP-ACK to given transaction */
773static int gsm411_tx_cp_ack(struct gsm_trans *trans)
774{
775 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200776 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200777
Harald Weltecf6a3812009-08-09 19:07:41 +0200778 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
779
780 if (trans->sms.is_mt) {
781 /* If this is a MT SMS DELIVER, we can clear transaction here */
782 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)86b17172009-08-14 14:52:17 +0200783 //trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200784 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200785
786 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200787}
788
789static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
790{
791 struct msgb *msg = gsm411_msgb_alloc();
792 u_int8_t *causep;
793
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200794 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
795 get_value_string(cp_cause_strs, cause));
796
Harald Welte76042182009-08-08 16:03:15 +0200797 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200798 *causep = cause;
799
800 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
801}
802
803/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)daef6062009-08-14 11:41:12 +0200804int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000805{
806 struct gsm48_hdr *gh = msgb_l3(msg);
807 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200808 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
809 struct gsm_lchan *lchan = msg->lchan;
810 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000811 int rc = 0;
812
Harald Weltef3efc592009-07-27 20:11:35 +0200813 if (!lchan->subscr)
814 return -EIO;
815 /* FIXME: send some error message */
816
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200817 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Weltef3efc592009-07-27 20:11:35 +0200818 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
819 transaction_id);
820 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200821 DEBUGPC(DSMS, "(unknown) ");
Harald Weltef3efc592009-07-27 20:11:35 +0200822 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
823 transaction_id, new_callref++);
824 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200825 DEBUGPC(DSMS, "No memory for trans\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200826 /* FIXME: send some error message */
827 return -ENOMEM;
828 }
829 trans->sms.cp_state = GSM411_CPS_IDLE;
830 trans->sms.rp_state = GSM411_RPS_IDLE;
831 trans->sms.is_mt = 0;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200832 trans->sms.link_id = link_id;
Harald Weltef3efc592009-07-27 20:11:35 +0200833
834 trans->lchan = lchan;
835 use_lchan(lchan);
836 }
837
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000838 switch(msg_type) {
839 case GSM411_MT_CP_DATA:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200840 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200841 /* 5.2.3.1.3: MO state exists when SMC has received
842 * CP-DATA, including sending of the assoc. CP-ACK */
843 /* 5.2.3.2.4: MT state exists when SMC has received
844 * CP-DATA, including sending of the assoc. CP-ACK */
845 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200846
Harald Welte (local)daef6062009-08-14 11:41:12 +0200847 /* SMC instance acknowledges the CP-DATA frame */
848 gsm411_tx_cp_ack(trans);
849
Harald Weltef3efc592009-07-27 20:11:35 +0200850 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200851#if 0
Harald Weltef3efc592009-07-27 20:11:35 +0200852 /* Send CP-ACK or CP-ERORR in response */
853 if (rc < 0) {
854 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
855 } else
856 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200857#endif
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000858 break;
859 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200860 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200861 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200862 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
863 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
864 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200865 /* Stop TC1* after CP-ACK has been received */
866 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200867
Harald Weltef3efc592009-07-27 20:11:35 +0200868 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200869 /* FIXME: we have sont one CP-DATA, which was now
870 * acknowledged. Check if we want to transfer more,
871 * i.e. multi-part message */
872 trans->sms.cp_state = GSM411_CPS_IDLE;
873 trans_free(trans);
874 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000875 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000876 case GSM411_MT_CP_ERROR:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200877 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
878 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte41985612009-08-10 00:24:32 +0200879 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200880 trans->sms.cp_state = GSM411_CPS_IDLE;
881 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000882 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000883 default:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200884 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200885 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200886 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200887 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000888 break;
889 }
890
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000891 return rc;
892}
893
Harald Welte8c2e36e2008-12-30 15:00:14 +0000894#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000895/* Test TPDU - ALL YOUR */
896static u_int8_t tpdu_test[] = {
897 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
898 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
899 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
900 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000901};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000902#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000903
Harald Weltecf6a3812009-08-09 19:07:41 +0200904/* Take a SMS in gsm_sms structure and send it through an already
905 * existing lchan. We also assume that the caller ensured this lchan already
906 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200907int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000908{
909 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200910 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200911 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200912 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200913 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200914 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000915
Harald Weltecf6a3812009-08-09 19:07:41 +0200916 transaction_id = 4; /* FIXME: we always use 4 for now */
917
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000918 msg->lchan = lchan;
919
Harald Welte76042182009-08-08 16:03:15 +0200920 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200921
Harald Welte76042182009-08-08 16:03:15 +0200922 /* FIXME: allocate transaction with message reference */
923 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
924 transaction_id, new_callref++);
925 if (!trans) {
926 DEBUGP(DSMS, "No memory for trans\n");
927 /* FIXME: send some error message */
928 return -ENOMEM;
929 }
930 trans->sms.cp_state = GSM411_CPS_IDLE;
931 trans->sms.rp_state = GSM411_RPS_IDLE;
932 trans->sms.is_mt = 1;
933 trans->sms.sms = sms;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200934 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +0200935
936 trans->lchan = lchan;
937 use_lchan(lchan);
938
939 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000940 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200941 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200942 data[1] = 0x91; /* type of number: international, ISDN */
943 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000944 data[3] = 0x77;
945 data[4] = 0x58;
946 data[5] = 0x10;
947 data[6] = 0x06;
948 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200949
950 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000951 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200952 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000953
Harald Welte76042182009-08-08 16:03:15 +0200954 /* obtain a pointer for the rp_ud_len, so we can fill it later */
955 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000956
Harald Welte76042182009-08-08 16:03:15 +0200957#if 1
958 /* generate the 03.40 TPDU */
959 rc = gsm340_gen_tpdu(msg, sms);
960 if (rc < 0) {
961 msgb_free(msg);
962 return rc;
963 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000964
Harald Welte76042182009-08-08 16:03:15 +0200965 *rp_ud_len = rc;
966#else
967 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000968 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200969 *rp_ud_len = sizeof(tpdu_test);
970#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000971
Harald Welte76042182009-08-08 16:03:15 +0200972 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000973
Harald Weltef3efc592009-07-27 20:11:35 +0200974 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
975 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000976}
Harald Weltef3efc592009-07-27 20:11:35 +0200977
Harald Weltecf6a3812009-08-09 19:07:41 +0200978/* RLL SAPI3 establish callback. Now we have a RLL connection and
979 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200980static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
981 void *_sms, enum bsc_rllr_ind type)
982{
983 struct gsm_sms *sms = _sms;
984
985 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
986 lchan, link_id, sms, type);
987
988 switch (type) {
989 case BSC_RLLR_IND_EST_CONF:
990 gsm411_send_sms_lchan(lchan, sms);
991 break;
992 case BSC_RLLR_IND_REL_IND:
993 case BSC_RLLR_IND_ERR_IND:
994 case BSC_RLLR_IND_TIMEOUT:
995 sms_free(sms);
996 break;
997 }
998}
999
Harald Weltecf6a3812009-08-09 19:07:41 +02001000/* paging callback. Here we get called if paging a subscriber has
1001 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +02001002static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1003 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +02001004{
Harald Welte76042182009-08-08 16:03:15 +02001005 struct gsm_lchan *lchan = _lchan;
1006 struct gsm_sms *sms = _sms;
1007 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +02001008
Harald Welte76042182009-08-08 16:03:15 +02001009 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1010 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1011
1012 if (hooknum != GSM_HOOK_RR_PAGING)
1013 return -EINVAL;
1014
1015 switch (event) {
1016 case GSM_PAGING_SUCCEEDED:
1017 /* Paging aborted without lchan ?!? */
1018 if (!lchan) {
1019 sms_free(sms);
1020 rc = -EIO;
1021 break;
1022 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001023 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +02001024 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001025 break;
1026 case GSM_PAGING_EXPIRED:
1027 sms_free(sms);
1028 rc = -ETIMEDOUT;
1029 break;
1030 default:
1031 rc = -EINVAL;
1032 break;
1033 }
1034
1035 return rc;
1036}
1037
Harald Weltecf6a3812009-08-09 19:07:41 +02001038/* high-level function to send a SMS to a given subscriber. The function
1039 * will take care of paging the subscriber, establishing the RLL SAPI3
1040 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +02001041int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1042 struct gsm_sms *sms)
1043{
Harald Weltecf6a3812009-08-09 19:07:41 +02001044 struct gsm_lchan *lchan;
Harald Weltee903edf2009-08-15 03:16:17 +02001045 int rc;
Harald Weltecf6a3812009-08-09 19:07:41 +02001046
Harald Welte76042182009-08-08 16:03:15 +02001047 /* check if we already have an open lchan to the subscriber.
1048 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +02001049 lchan = lchan_for_subscr(subscr);
1050 if (lchan)
1051 return rll_establish(lchan, UM_SAPI_SMS,
1052 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001053
1054 /* if not, we have to start paging */
Harald Weltee903edf2009-08-15 03:16:17 +02001055 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1056 paging_cb_send_sms, sms);
Harald Welte (local)0abaf332009-08-15 11:25:45 +02001057 if (rc <= 0)
Harald Weltee903edf2009-08-15 03:16:17 +02001058 sms_free(sms);
Harald Welte76042182009-08-08 16:03:15 +02001059
1060 return 0;
1061}
Harald Welte3366a942009-07-28 00:44:49 +02001062
Harald Weltecf6a3812009-08-09 19:07:41 +02001063static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1064 void *handler_data, void *signal_data)
1065{
1066 struct gsm_subscriber *subscr;
1067 struct gsm_lchan *lchan;
1068 struct gsm_sms *sms;
1069
Jan Luebbe336f8ec2009-08-12 15:18:52 +02001070 u_int32_t token;
1071
Harald Weltecf6a3812009-08-09 19:07:41 +02001072 switch (signal) {
1073 case S_SUBSCR_ATTACHED:
1074 /* A subscriber has attached. Check if there are
1075 * any pending SMS for him to be delivered */
1076 subscr = signal_data;
1077 lchan = lchan_for_subscr(subscr);
1078 if (!lchan)
1079 break;
1080 sms = db_sms_get_unsent_for_subscr(subscr);
1081 if (!sms)
1082 break;
1083 /* Establish a SAPI3 RLL connection for SMS */
1084 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1085 break;
1086 default:
1087 break;
1088 }
1089 return 0;
1090}
1091
Harald Welte (local)86b17172009-08-14 14:52:17 +02001092void _gsm411_sms_trans_free(struct gsm_trans *trans)
1093{
1094 bsc_del_timer(&trans->sms.cp_timer);
1095}
1096
Harald Welte7bfc2672009-07-28 00:41:45 +02001097static __attribute__((constructor)) void on_dso_load_sms(void)
1098{
Harald Weltecf6a3812009-08-09 19:07:41 +02001099 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +02001100}