blob: 85ad0ecd2f8f7a1038830a18718da0a09dc12b9b [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 Willmann6b1e8222009-08-12 21:17:06 +0200392 /* FIXME: Handle DSC of UCS2 or 8/bit default */
393 if (gsm338_get_sms_alphabet(sms->data_coding_scheme) == 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 Willmann6b1e8222009-08-12 21:17:06 +0200401 }
Harald Weltef3efc592009-07-27 20:11:35 +0200402
Harald Welte76042182009-08-08 16:03:15 +0200403 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200404}
405
Harald Welteb9c758b2009-07-05 14:02:46 +0200406/* process an incoming TPDU (called from RP-DATA)
407 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000408static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000409{
Harald Welte9176bd42009-07-23 18:46:00 +0200410 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000411 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000412 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200413 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
414 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000415 u_int8_t da_len_bytes;
416 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
417 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000418
Harald Welte76042182009-08-08 16:03:15 +0200419 gsms = sms_alloc();
420 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200421 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000422
423 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200424 sms_mti = *smsp & 0x03;
425 sms_mms = !!(*smsp & 0x04);
426 sms_vpf = (*smsp & 0x18) >> 3;
427 gsms->status_rep_req = (*smsp & 0x20);
428 gsms->ud_hdr_ind = (*smsp & 0x40);
429 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000430
431 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200432 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000433
Harald Welte7e310b12009-03-30 20:56:32 +0000434 /* length in bytes of the destination address */
435 da_len_bytes = 2 + *smsp/2 + *smsp%2;
436 if (da_len_bytes > 12) {
437 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200438 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000439 goto out;
440 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800441 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000442 memcpy(address_lv, smsp, da_len_bytes);
443 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800444 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000445 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200446 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000447 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000448
Harald Welte76042182009-08-08 16:03:15 +0200449 gsms->protocol_id = *smsp++;
450 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000451
Harald Welte76042182009-08-08 16:03:15 +0200452 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000453
Harald Welte76042182009-08-08 16:03:15 +0200454 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000455 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200456 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000457 break;
458 case GSM340_TP_VPF_ABSOLUTE:
459 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200460 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000461 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000462 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200463 case GSM340_TP_VPF_NONE:
464 sms_vp = 0;
465 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000466 default:
467 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200468 sms_vpf);
469 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000470 }
Harald Welte76042182009-08-08 16:03:15 +0200471 gsms->user_data_len = *smsp++;
472 if (gsms->user_data_len) {
473 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000474
Harald Welte76042182009-08-08 16:03:15 +0200475 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000476 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200477 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000478 break;
479 case DCS_8BIT_DATA:
480 case DCS_UCS2:
481 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000482 break;
483 }
484 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000485
Harald Welte7e310b12009-03-30 20:56:32 +0000486 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
487 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200488 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
489 gsms->protocol_id, gsms->data_coding_scheme,
490 gsms->dest_addr, gsms->user_data_len,
491 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
492 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000493
Harald Welte76042182009-08-08 16:03:15 +0200494 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000495
Harald Welte76042182009-08-08 16:03:15 +0200496 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200497
Harald Welte76042182009-08-08 16:03:15 +0200498 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200499
Harald Welte7e310b12009-03-30 20:56:32 +0000500 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200501 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000502 if (!gsms->receiver) {
503 rc = 1; /* cause 1: unknown subscriber */
504 goto out;
505 }
506
Harald Welte76042182009-08-08 16:03:15 +0200507 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000508 case GSM340_SMS_SUBMIT_MS2SC:
509 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200510 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000511 break;
512 case GSM340_SMS_COMMAND_MS2SC:
513 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200514 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200515 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000516 break;
517 default:
Harald Welte76042182009-08-08 16:03:15 +0200518 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200519 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000520 break;
521 }
522
Harald Welteb9c758b2009-07-05 14:02:46 +0200523 if (!rc && !gsms->receiver)
524 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
525
Harald Welte7e310b12009-03-30 20:56:32 +0000526out:
Harald Welte76042182009-08-08 16:03:15 +0200527 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000528
Harald Welte7e310b12009-03-30 20:56:32 +0000529 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000530}
531
Harald Weltef3efc592009-07-27 20:11:35 +0200532static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000533{
534 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000535
Daniel Willmann471712b2008-12-29 01:54:02 +0000536 DEBUGP(DSMS, "TX: SMS RP ACK\n");
537
Harald Weltef3efc592009-07-27 20:11:35 +0200538 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000539}
540
Harald Weltef3efc592009-07-27 20:11:35 +0200541static int gsm411_send_rp_error(struct gsm_trans *trans,
542 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000543{
544 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000545
Harald Welte7e310b12009-03-30 20:56:32 +0000546 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000547
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200548 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
549 get_value_string(rp_cause_strs, cause));
Daniel Willmann471712b2008-12-29 01:54:02 +0000550
Harald Weltef3efc592009-07-27 20:11:35 +0200551 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000552}
553
Harald Welte7e310b12009-03-30 20:56:32 +0000554/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200555static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
556 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000557 u_int8_t src_len, u_int8_t *src,
558 u_int8_t dst_len, u_int8_t *dst,
559 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000560{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000561 int rc = 0;
562
Harald Welte7e310b12009-03-30 20:56:32 +0000563 if (src_len && src)
564 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
565
566 if (!dst_len || !dst || !tpdu_len || !tpdu) {
567 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200568 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200569 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000570 return -EIO;
571 }
572 msg->smsh = tpdu;
573
574 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000575
576 rc = gsm340_rx_tpdu(msg);
577 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200578 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000579 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200580 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000581 else
582 return rc;
583}
584
585/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200586static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
587 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000588{
589 u_int8_t src_len, dst_len, rpud_len;
590 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
591
592 /* in the MO case, this should always be zero length */
593 src_len = rph->data[0];
594 if (src_len)
595 src = &rph->data[1];
596
597 dst_len = rph->data[1+src_len];
598 if (dst_len)
599 dst = &rph->data[1+src_len+1];
600
601 rpud_len = rph->data[1+src_len+1+dst_len];
602 if (rpud_len)
603 rp_ud = &rph->data[1+src_len+1+dst_len+1];
604
Harald Welteb9c758b2009-07-05 14:02:46 +0200605 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
606 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200607 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000608 rpud_len, rp_ud);
609}
610
Harald Weltecb8f4432009-08-09 14:59:02 +0200611/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200612static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
613 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200614{
Harald Welte76042182009-08-08 16:03:15 +0200615 struct gsm_sms *sms = trans->sms.sms;
616
Harald Welteb9c758b2009-07-05 14:02:46 +0200617 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
618 * successfully received a SMS. We can now safely mark it as
619 * transmitted */
620
Harald Weltecb8f4432009-08-09 14:59:02 +0200621 if (!trans->sms.is_mt) {
622 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
623 return gsm411_send_rp_error(trans, rph->msg_ref,
624 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
625 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200626
Harald Welte76042182009-08-08 16:03:15 +0200627 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200628 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
629 return gsm411_send_rp_error(trans, rph->msg_ref,
630 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200631 }
632
633 /* mark this SMS as sent in database */
634 db_sms_mark_sent(sms);
635
636 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
637
638 sms_free(sms);
639 trans->sms.sms = NULL;
640
Harald Weltecf6a3812009-08-09 19:07:41 +0200641 /* do not free the transaction here, this is done by sending CP-ACK */
642
643 /* check for more messages for this subscriber */
644 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
645 if (sms)
646 gsm411_send_sms_lchan(msg->lchan, sms);
647 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200648 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte76042182009-08-08 16:03:15 +0200649
650 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200651}
652
Harald Weltef3efc592009-07-27 20:11:35 +0200653static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
654 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200655{
Harald Welte76042182009-08-08 16:03:15 +0200656 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200657 u_int8_t cause_len = rph->data[0];
658 u_int8_t cause = rph->data[1];
659
Harald Welteb9c758b2009-07-05 14:02:46 +0200660 /* Error in response to MT RP_DATA, i.e. the MS did not
661 * successfully receive the SMS. We need to investigate
662 * the cause and take action depending on it */
663
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200664 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d (%s)\n", cause,
665 get_value_string(rp_cause_strs, cause));
Harald Weltef3efc592009-07-27 20:11:35 +0200666
Harald Weltecb8f4432009-08-09 14:59:02 +0200667 if (!trans->sms.is_mt) {
668 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
669 return gsm411_send_rp_error(trans, rph->msg_ref,
670 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
671 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200672
Harald Welte76042182009-08-08 16:03:15 +0200673 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200674 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
675 return gsm411_send_rp_error(trans, rph->msg_ref,
676 GSM411_RP_CAUSE_PROTOCOL_ERR);
677 }
678
679 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
680 /* MS has not enough memory to store the message. We need
681 * to store this in our database and wati for a SMMA message */
682 /* FIXME */
683 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welte76042182009-08-08 16:03:15 +0200684 }
685
686 sms_free(sms);
687 trans->sms.sms = NULL;
688
Harald Welte (local)86b17172009-08-14 14:52:17 +0200689 //trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200690
Harald Weltef3efc592009-07-27 20:11:35 +0200691 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200692}
693
Harald Weltef3efc592009-07-27 20:11:35 +0200694static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
695 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200696{
Harald Weltecf6a3812009-08-09 19:07:41 +0200697 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200698 int rc;
699
Harald Weltecf6a3812009-08-09 19:07:41 +0200700 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
701 trans->sms.rp_state = GSM411_RPS_IDLE;
702
Harald Welteb9c758b2009-07-05 14:02:46 +0200703 /* MS tells us that it has memory for more SMS, we need
704 * to check if we have any pending messages for it and then
705 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200706 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200707
Harald Weltecf6a3812009-08-09 19:07:41 +0200708 /* check for more messages for this subscriber */
709 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
710 if (sms)
711 gsm411_send_sms_lchan(msg->lchan, sms);
712 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200713 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Weltef3efc592009-07-27 20:11:35 +0200714
715 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200716}
717
Harald Weltef3efc592009-07-27 20:11:35 +0200718static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
719 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000720{
Daniel Willmann471712b2008-12-29 01:54:02 +0000721 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000722 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000723 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000724
725 switch (msg_type) {
726 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200727 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
728 /* start TR2N and enter 'wait to send RP-ACK state' */
729 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
730 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000731 break;
732 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200733 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
734 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200735 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000736 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200737 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
738 /* start TR2N and enter 'wait to send RP-ACK state' */
739 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
740 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
741 break;
742 case GSM411_MT_RP_ERROR_MO:
743 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000744 break;
745 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000746 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200747 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
748 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000749 break;
750 }
751
752 return rc;
753}
754
Harald Weltef3efc592009-07-27 20:11:35 +0200755/* send CP-ACK to given transaction */
756static int gsm411_tx_cp_ack(struct gsm_trans *trans)
757{
758 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200759 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200760
Harald Weltecf6a3812009-08-09 19:07:41 +0200761 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
762
763 if (trans->sms.is_mt) {
764 /* If this is a MT SMS DELIVER, we can clear transaction here */
765 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)86b17172009-08-14 14:52:17 +0200766 //trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200767 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200768
769 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200770}
771
772static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
773{
774 struct msgb *msg = gsm411_msgb_alloc();
775 u_int8_t *causep;
776
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200777 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
778 get_value_string(cp_cause_strs, cause));
779
Harald Welte76042182009-08-08 16:03:15 +0200780 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200781 *causep = cause;
782
783 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
784}
785
786/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)daef6062009-08-14 11:41:12 +0200787int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000788{
789 struct gsm48_hdr *gh = msgb_l3(msg);
790 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200791 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
792 struct gsm_lchan *lchan = msg->lchan;
793 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000794 int rc = 0;
795
Harald Weltef3efc592009-07-27 20:11:35 +0200796 if (!lchan->subscr)
797 return -EIO;
798 /* FIXME: send some error message */
799
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200800 DEBUGP(DSMS, "trans_id=%x ", gh->proto_discr >> 4);
Harald Weltef3efc592009-07-27 20:11:35 +0200801 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
802 transaction_id);
803 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200804 DEBUGPC(DSMS, "(unknown) ");
Harald Weltef3efc592009-07-27 20:11:35 +0200805 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
806 transaction_id, new_callref++);
807 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200808 DEBUGPC(DSMS, "No memory for trans\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200809 /* FIXME: send some error message */
810 return -ENOMEM;
811 }
812 trans->sms.cp_state = GSM411_CPS_IDLE;
813 trans->sms.rp_state = GSM411_RPS_IDLE;
814 trans->sms.is_mt = 0;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200815 trans->sms.link_id = link_id;
Harald Weltef3efc592009-07-27 20:11:35 +0200816
817 trans->lchan = lchan;
818 use_lchan(lchan);
819 }
820
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000821 switch(msg_type) {
822 case GSM411_MT_CP_DATA:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200823 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200824 /* 5.2.3.1.3: MO state exists when SMC has received
825 * CP-DATA, including sending of the assoc. CP-ACK */
826 /* 5.2.3.2.4: MT state exists when SMC has received
827 * CP-DATA, including sending of the assoc. CP-ACK */
828 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200829
Harald Welte (local)daef6062009-08-14 11:41:12 +0200830 /* SMC instance acknowledges the CP-DATA frame */
831 gsm411_tx_cp_ack(trans);
832
Harald Weltef3efc592009-07-27 20:11:35 +0200833 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200834#if 0
Harald Weltef3efc592009-07-27 20:11:35 +0200835 /* Send CP-ACK or CP-ERORR in response */
836 if (rc < 0) {
837 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
838 } else
839 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200840#endif
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000841 break;
842 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200843 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200844 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200845 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
846 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
847 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200848 /* Stop TC1* after CP-ACK has been received */
849 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200850
Harald Weltef3efc592009-07-27 20:11:35 +0200851 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200852 /* FIXME: we have sont one CP-DATA, which was now
853 * acknowledged. Check if we want to transfer more,
854 * i.e. multi-part message */
855 trans->sms.cp_state = GSM411_CPS_IDLE;
856 trans_free(trans);
857 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000858 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000859 case GSM411_MT_CP_ERROR:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200860 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
861 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte41985612009-08-10 00:24:32 +0200862 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200863 trans->sms.cp_state = GSM411_CPS_IDLE;
864 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000865 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000866 default:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200867 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200868 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200869 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200870 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000871 break;
872 }
873
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000874 return rc;
875}
876
Harald Welte8c2e36e2008-12-30 15:00:14 +0000877#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000878/* Test TPDU - ALL YOUR */
879static u_int8_t tpdu_test[] = {
880 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
881 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
882 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
883 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000884};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000885#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000886
Harald Weltecf6a3812009-08-09 19:07:41 +0200887/* Take a SMS in gsm_sms structure and send it through an already
888 * existing lchan. We also assume that the caller ensured this lchan already
889 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +0200890int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000891{
892 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200893 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200894 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200895 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +0200896 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +0200897 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000898
Harald Weltecf6a3812009-08-09 19:07:41 +0200899 transaction_id = 4; /* FIXME: we always use 4 for now */
900
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000901 msg->lchan = lchan;
902
Harald Welte76042182009-08-08 16:03:15 +0200903 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200904
Harald Welte76042182009-08-08 16:03:15 +0200905 /* FIXME: allocate transaction with message reference */
906 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
907 transaction_id, new_callref++);
908 if (!trans) {
909 DEBUGP(DSMS, "No memory for trans\n");
910 /* FIXME: send some error message */
911 return -ENOMEM;
912 }
913 trans->sms.cp_state = GSM411_CPS_IDLE;
914 trans->sms.rp_state = GSM411_RPS_IDLE;
915 trans->sms.is_mt = 1;
916 trans->sms.sms = sms;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200917 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +0200918
919 trans->lchan = lchan;
920 use_lchan(lchan);
921
922 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000923 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200924 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200925 data[1] = 0x91; /* type of number: international, ISDN */
926 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000927 data[3] = 0x77;
928 data[4] = 0x58;
929 data[5] = 0x10;
930 data[6] = 0x06;
931 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200932
933 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000934 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200935 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000936
Harald Welte76042182009-08-08 16:03:15 +0200937 /* obtain a pointer for the rp_ud_len, so we can fill it later */
938 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000939
Harald Welte76042182009-08-08 16:03:15 +0200940#if 1
941 /* generate the 03.40 TPDU */
942 rc = gsm340_gen_tpdu(msg, sms);
943 if (rc < 0) {
944 msgb_free(msg);
945 return rc;
946 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000947
Harald Welte76042182009-08-08 16:03:15 +0200948 *rp_ud_len = rc;
949#else
950 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000951 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200952 *rp_ud_len = sizeof(tpdu_test);
953#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000954
Harald Welte76042182009-08-08 16:03:15 +0200955 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000956
Harald Weltef3efc592009-07-27 20:11:35 +0200957 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
958 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000959}
Harald Weltef3efc592009-07-27 20:11:35 +0200960
Harald Weltecf6a3812009-08-09 19:07:41 +0200961/* RLL SAPI3 establish callback. Now we have a RLL connection and
962 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +0200963static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
964 void *_sms, enum bsc_rllr_ind type)
965{
966 struct gsm_sms *sms = _sms;
967
968 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
969 lchan, link_id, sms, type);
970
971 switch (type) {
972 case BSC_RLLR_IND_EST_CONF:
973 gsm411_send_sms_lchan(lchan, sms);
974 break;
975 case BSC_RLLR_IND_REL_IND:
976 case BSC_RLLR_IND_ERR_IND:
977 case BSC_RLLR_IND_TIMEOUT:
978 sms_free(sms);
979 break;
980 }
981}
982
Harald Weltecf6a3812009-08-09 19:07:41 +0200983/* paging callback. Here we get called if paging a subscriber has
984 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +0200985static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
986 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200987{
Harald Welte76042182009-08-08 16:03:15 +0200988 struct gsm_lchan *lchan = _lchan;
989 struct gsm_sms *sms = _sms;
990 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200991
Harald Welte76042182009-08-08 16:03:15 +0200992 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
993 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
994
995 if (hooknum != GSM_HOOK_RR_PAGING)
996 return -EINVAL;
997
998 switch (event) {
999 case GSM_PAGING_SUCCEEDED:
1000 /* Paging aborted without lchan ?!? */
1001 if (!lchan) {
1002 sms_free(sms);
1003 rc = -EIO;
1004 break;
1005 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001006 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +02001007 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001008 break;
1009 case GSM_PAGING_EXPIRED:
1010 sms_free(sms);
1011 rc = -ETIMEDOUT;
1012 break;
1013 default:
1014 rc = -EINVAL;
1015 break;
1016 }
1017
1018 return rc;
1019}
1020
Harald Weltecf6a3812009-08-09 19:07:41 +02001021/* high-level function to send a SMS to a given subscriber. The function
1022 * will take care of paging the subscriber, establishing the RLL SAPI3
1023 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +02001024int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1025 struct gsm_sms *sms)
1026{
Harald Weltecf6a3812009-08-09 19:07:41 +02001027 struct gsm_lchan *lchan;
1028
Harald Welte76042182009-08-08 16:03:15 +02001029 /* check if we already have an open lchan to the subscriber.
1030 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +02001031 lchan = lchan_for_subscr(subscr);
1032 if (lchan)
1033 return rll_establish(lchan, UM_SAPI_SMS,
1034 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001035
1036 /* if not, we have to start paging */
1037 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1038 paging_cb_send_sms, sms);
1039
1040 return 0;
1041}
Harald Welte3366a942009-07-28 00:44:49 +02001042
Harald Weltecf6a3812009-08-09 19:07:41 +02001043static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1044 void *handler_data, void *signal_data)
1045{
1046 struct gsm_subscriber *subscr;
1047 struct gsm_lchan *lchan;
1048 struct gsm_sms *sms;
1049
Jan Luebbe336f8ec2009-08-12 15:18:52 +02001050 u_int32_t token;
1051
Harald Weltecf6a3812009-08-09 19:07:41 +02001052 switch (signal) {
1053 case S_SUBSCR_ATTACHED:
1054 /* A subscriber has attached. Check if there are
1055 * any pending SMS for him to be delivered */
1056 subscr = signal_data;
1057 lchan = lchan_for_subscr(subscr);
1058 if (!lchan)
1059 break;
1060 sms = db_sms_get_unsent_for_subscr(subscr);
1061 if (!sms)
1062 break;
1063 /* Establish a SAPI3 RLL connection for SMS */
1064 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1065 break;
1066 default:
1067 break;
1068 }
1069 return 0;
1070}
1071
Harald Welte (local)86b17172009-08-14 14:52:17 +02001072void _gsm411_sms_trans_free(struct gsm_trans *trans)
1073{
1074 bsc_del_timer(&trans->sms.cp_timer);
1075}
1076
Harald Welte7bfc2672009-07-28 00:41:45 +02001077static __attribute__((constructor)) void on_dso_load_sms(void)
1078{
Harald Weltecf6a3812009-08-09 19:07:41 +02001079 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +02001080}