blob: 40b257d507c396ede47db97935f75bba0ef21fef [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
6 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
7 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
26
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +010027#include <assert.h>
Harald Welte59b04682009-06-10 05:40:52 +080028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <errno.h>
Harald Welteb78996d2009-07-27 20:11:35 +020032#include <time.h>
Harald Welte59b04682009-06-10 05:40:52 +080033#include <netinet/in.h>
34
Harald Weltef4625b12010-02-20 16:24:02 +010035#include <osmocore/msgb.h>
36#include <osmocore/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080037#include <openbsc/debug.h>
38#include <openbsc/gsm_data.h>
39#include <openbsc/gsm_subscriber.h>
40#include <openbsc/gsm_04_11.h>
41#include <openbsc/gsm_04_08.h>
Harald Weltef4625b12010-02-20 16:24:02 +010042#include <osmocore/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080043#include <openbsc/abis_rsl.h>
44#include <openbsc/signal.h>
45#include <openbsc/db.h>
Harald Weltef4625b12010-02-20 16:24:02 +010046#include <osmocore/talloc.h>
Harald Welteb78996d2009-07-27 20:11:35 +020047#include <openbsc/transaction.h>
Harald Welte68b7df22009-08-08 16:03:15 +020048#include <openbsc/paging.h>
Harald Welte09421d32009-08-09 14:59:02 +020049#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther735cd9e2009-08-10 07:54:02 +020050#include <openbsc/chan_alloc.h>
Harald Welte59b04682009-06-10 05:40:52 +080051
52#define GSM411_ALLOC_SIZE 1024
53#define GSM411_ALLOC_HEADROOM 128
54
Harald Welte09421d32009-08-09 14:59:02 +020055#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
56
Harald Welte (local)8751ee92009-08-15 02:30:58 +020057void *tall_gsms_ctx;
Harald Welteb78996d2009-07-27 20:11:35 +020058static u_int32_t new_callref = 0x40000001;
59
Harald Welte (local)cb4715c2009-08-14 10:42:43 +020060static const struct value_string cp_cause_strs[] = {
61 { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
62 { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
63 { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
64 { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
65 { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
66 { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
67 { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
68 "Message incompatible with protocol state" },
69 { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
70 { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
71 { 0, 0 }
72};
73
74static const struct value_string rp_cause_strs[] = {
75 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
76 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
77 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
78 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
79 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
80 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
81 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
82 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
83 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
84 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
85 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
86 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
87 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
88 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
89 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
90 /* valid only for MT */
91 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
92 /* valid for both directions */
93 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
94 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
95 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
96 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
97 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
98 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
99 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
100 { 0, NULL }
101};
102
Harald Welte68b7df22009-08-08 16:03:15 +0200103struct gsm_sms *sms_alloc(void)
104{
105 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
106}
107
108void sms_free(struct gsm_sms *sms)
109{
110 /* drop references to subscriber structure */
111 if (sms->sender)
112 subscr_put(sms->sender);
113 if (sms->receiver)
114 subscr_put(sms->receiver);
115
116 talloc_free(sms);
117}
118
Harald Welte59b04682009-06-10 05:40:52 +0800119struct msgb *gsm411_msgb_alloc(void)
120{
Harald Welte9cfc9352009-06-26 19:39:35 +0200121 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
122 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +0800123}
124
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200125static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800126{
127 if (msg->lchan)
128 msg->trx = msg->lchan->ts->trx;
129
130 msg->l3h = msg->data;
131
Harald Welte68b7df22009-08-08 16:03:15 +0200132 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
133
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200134 return rsl_data_request(msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +0800135}
136
Harald Welte5fa17a22009-08-10 00:24:32 +0200137/* SMC TC1* is expired */
138static void cp_timer_expired(void *data)
139{
140 struct gsm_trans *trans = data;
141
142 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
143 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
144 trans_free(trans);
145}
146
Harald Welte7e2f57d2009-07-04 17:39:00 +0200147/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200148static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
149 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200150{
151 struct gsm48_hdr *gh;
152
153 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
154 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +0200155 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200156 gh->msg_type = msg_type;
157
Harald Welteb78996d2009-07-27 20:11:35 +0200158 /* assign the outgoing lchan */
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +0100159 msg->lchan = trans->conn->lchan;
Harald Welteb78996d2009-07-27 20:11:35 +0200160
161 /* mobile originating */
162 switch (gh->msg_type) {
163 case GSM411_MT_CP_DATA:
164 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Welte09421d32009-08-09 14:59:02 +0200165 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200166 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte5fa17a22009-08-10 00:24:32 +0200167 trans->sms.cp_timer.data = trans;
168 trans->sms.cp_timer.cb = cp_timer_expired;
169 /* 5.3.2.1: Set Timer TC1A */
170 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200171 DEBUGP(DSMS, "TX: CP-DATA ");
172 break;
173 case GSM411_MT_CP_ACK:
174 DEBUGP(DSMS, "TX: CP-ACK ");
175 break;
176 case GSM411_MT_CP_ERROR:
Sylvain Munaut163a24a2009-12-18 18:28:07 +0100177 DEBUGP(DSMS, "TX: CP-ERROR ");
Harald Welteb78996d2009-07-27 20:11:35 +0200178 break;
179 }
180
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200181 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
182
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200183 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200184}
185
186/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200187static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
188 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200189{
190 struct gsm411_rp_hdr *rp;
Harald Weltef2e680b2009-08-10 00:22:19 +0200191 u_int8_t len = msg->len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200192
193 /* GSM 04.11 RP-DATA header */
194 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Weltef2e680b2009-08-10 00:22:19 +0200195 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200196 rp->msg_type = rp_msg_type;
197 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
198
Harald Welteb78996d2009-07-27 20:11:35 +0200199 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200200}
201
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100202/* Turn int into semi-octet representation: 98 => 0x89 */
203static u_int8_t bcdify(u_int8_t value)
204{
205 u_int8_t ret;
Steffen Neubauer94436952009-11-11 23:02:07 +0900206
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100207 ret = value / 10;
208 ret |= (value % 10) << 4;
209
210 return ret;
211}
212
213/* Turn semi-octet representation into int: 0x89 => 98 */
214static u_int8_t unbcdify(u_int8_t value)
215{
216 u_int8_t ret;
217
218 if ((value & 0x0F) > 9 || (value >> 4) > 9)
Harald Welteced9a912009-12-24 15:08:18 +0100219 LOGP(DSMS, LOGL_ERROR,
220 "unbcdify got too big nibble: 0x%02X\n", value);
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100221
222 ret = (value&0x0F)*10;
Steffen Neubauere5e0eb72009-11-26 23:38:41 +0100223 ret += value>>4;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100224
225 return ret;
226}
227
228/* Generate 03.40 TP-SCTS */
229static void gsm340_gen_scts(u_int8_t *scts, time_t time)
230{
231 struct tm *tm = localtime(&time);
232
233 *scts++ = bcdify(tm->tm_year % 100);
234 *scts++ = bcdify(tm->tm_mon + 1);
235 *scts++ = bcdify(tm->tm_mday);
236 *scts++ = bcdify(tm->tm_hour);
237 *scts++ = bcdify(tm->tm_min);
238 *scts++ = bcdify(tm->tm_sec);
239 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
240}
241
242/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
243static time_t gsm340_scts(u_int8_t *scts)
244{
245 struct tm tm;
246
247 u_int8_t yr = unbcdify(*scts++);
248
249 if (yr <= 80)
250 tm.tm_year = 100 + yr;
251 else
252 tm.tm_year = yr;
253 tm.tm_mon = unbcdify(*scts++) - 1;
254 tm.tm_mday = unbcdify(*scts++);
255 tm.tm_hour = unbcdify(*scts++);
256 tm.tm_min = unbcdify(*scts++);
257 tm.tm_sec = unbcdify(*scts++);
258 /* according to gsm 03.40 time zone is
259 "expressed in quarters of an hour" */
260 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
261
262 return mktime(&tm);
263}
264
265/* Return the default validity period in minutes */
266static unsigned long gsm340_vp_default(void)
267{
268 unsigned long minutes;
269 /* Default validity: two days */
270 minutes = 24 * 60 * 2;
271 return minutes;
272}
273
274/* Decode validity period format 'relative' */
275static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
276{
277 /* Chapter 9.2.3.12.1 */
278 u_int8_t vp;
279 unsigned long minutes;
280
281 vp = *(sms_vp);
282 if (vp <= 143)
283 minutes = vp + 1 * 5;
284 else if (vp <= 167)
285 minutes = 12*60 + (vp-143) * 30;
286 else if (vp <= 196)
287 minutes = vp-166 * 60 * 24;
288 else
289 minutes = vp-192 * 60 * 24 * 7;
290 return minutes;
291}
292
293/* Decode validity period format 'absolute' */
294static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
295{
296 /* Chapter 9.2.3.12.2 */
297 time_t expires, now;
298 unsigned long minutes;
299
300 expires = gsm340_scts(sms_vp);
301 now = mktime(gmtime(NULL));
302 if (expires <= now)
303 minutes = 0;
304 else
305 minutes = (expires-now)/60;
306 return minutes;
307}
308
309/* Decode validity period format 'relative in integer representation' */
310static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800311{
312 u_int8_t vp;
313 unsigned long minutes;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100314 vp = *(sms_vp);
315 if (vp == 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100316 LOGP(DSMS, LOGL_ERROR,
317 "reserved relative_integer validity period\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100318 return gsm340_vp_default();
319 }
320 minutes = vp/60;
321 return minutes;
322}
323
324/* Decode validity period format 'relative in semi-octet representation' */
325static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
326{
327 unsigned long minutes;
328 minutes = unbcdify(*sms_vp++)*60; /* hours */
329 minutes += unbcdify(*sms_vp++); /* minutes */
330 minutes += unbcdify(*sms_vp++)/60; /* seconds */
331 return minutes;
332}
333
334/* decode validity period. return minutes */
335static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
336{
337 u_int8_t fi; /* functionality indicator */
Harald Welte59b04682009-06-10 05:40:52 +0800338
Harald Welte68b7df22009-08-08 16:03:15 +0200339 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800340 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100341 return gsm340_vp_relative(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800342 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100343 return gsm340_vp_absolute(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800344 case GSM340_TP_VPF_ENHANCED:
345 /* Chapter 9.2.3.12.3 */
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100346 fi = *sms_vp++;
347 /* ignore additional fi */
348 if (fi & (1<<7)) sms_vp++;
349 /* read validity period format */
350 switch (fi & 0b111) {
351 case 0b000:
352 return gsm340_vp_default(); /* no vpf specified */
353 case 0b001:
354 return gsm340_vp_relative(sms_vp);
355 case 0b010:
356 return gsm340_vp_relative_integer(sms_vp);
357 case 0b011:
358 return gsm340_vp_relative_semioctet(sms_vp);
359 default:
360 /* The GSM spec says that the SC should reject any
361 unsupported and/or undefined values. FIXME */
Harald Welteced9a912009-12-24 15:08:18 +0100362 LOGP(DSMS, LOGL_ERROR,
363 "Reserved enhanced validity period format\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100364 return gsm340_vp_default();
365 }
Daniel Willmann426bb162009-08-13 03:40:49 +0200366 case GSM340_TP_VPF_NONE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100367 default:
368 return gsm340_vp_default();
Harald Welte59b04682009-06-10 05:40:52 +0800369 }
Harald Welte59b04682009-06-10 05:40:52 +0800370}
371
372/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
373enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
374{
375 u_int8_t cgbits = dcs >> 4;
376 enum sms_alphabet alpha = DCS_NONE;
377
378 if ((cgbits & 0xc) == 0) {
379 if (cgbits & 2)
Harald Welteced9a912009-12-24 15:08:18 +0100380 LOGP(DSMS, LOGL_NOTICE,
381 "Compressed SMS not supported yet\n");
Harald Welte59b04682009-06-10 05:40:52 +0800382
Daniel Willmannf2861022009-08-15 03:01:17 +0200383 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800384 case 0:
385 alpha = DCS_7BIT_DEFAULT;
386 break;
387 case 1:
388 alpha = DCS_8BIT_DATA;
389 break;
390 case 2:
391 alpha = DCS_UCS2;
392 break;
393 }
394 } else if (cgbits == 0xc || cgbits == 0xd)
395 alpha = DCS_7BIT_DEFAULT;
396 else if (cgbits == 0xe)
397 alpha = DCS_UCS2;
398 else if (cgbits == 0xf) {
399 if (dcs & 4)
400 alpha = DCS_8BIT_DATA;
401 else
402 alpha = DCS_7BIT_DEFAULT;
403 }
404
405 return alpha;
406}
407
Harald Welte68b7df22009-08-08 16:03:15 +0200408static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800409{
410 if (db_sms_store(gsms) != 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100411 LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200412 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800413 }
Harald Welte68b7df22009-08-08 16:03:15 +0200414 /* dispatch a signal to tell higher level about it */
415 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200416 /* try delivering the SMS right now */
417 //gsm411_send_sms_subscr(gsms->receiver, gsms);
418
Harald Welte59b04682009-06-10 05:40:52 +0800419 return 0;
420}
421
Harald Welte68b7df22009-08-08 16:03:15 +0200422/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
423static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
424 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200425{
Harald Welte68b7df22009-08-08 16:03:15 +0200426 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200427
Harald Welte68b7df22009-08-08 16:03:15 +0200428 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
429
Harald Weltefdc93d92010-03-07 23:40:35 +0100430 len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, subscr->extension);
Harald Welte68b7df22009-08-08 16:03:15 +0200431
432 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
433 oa[0] = strlen(subscr->extension) & 0xff;
434
435 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200436}
437
Harald Welte68b7df22009-08-08 16:03:15 +0200438/* generate a msgb containing a TPDU derived from struct gsm_sms,
439 * returns total size of TPDU */
440static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200441{
Harald Welteb78996d2009-07-27 20:11:35 +0200442 u_int8_t *smsp;
443 u_int8_t oa[12]; /* max len per 03.40 */
444 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200445 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200446 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200447
448 /* generate first octet with masked bits */
449 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200450 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200451 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200452 /* TP-MMS (more messages to send) */
453 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200454 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200455 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200456 if (sms->status_rep_req)
457 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200458 /* TP-UDHI (indicating TP-UD contains a header) */
459 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200460 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200461#if 0
462 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200463 if (sms->
464 *smsp |= 0x80;
465#endif
466
467 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200468 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200469 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200470 memcpy(smsp, oa, oa_len);
471
472 /* generate TP-PID */
473 smsp = msgb_put(msg, 1);
474 *smsp = sms->protocol_id;
475
476 /* generate TP-DCS */
477 smsp = msgb_put(msg, 1);
478 *smsp = sms->data_coding_scheme;
479
480 /* generate TP-SCTS */
481 smsp = msgb_put(msg, 7);
482 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200483
Harald Welteb78996d2009-07-27 20:11:35 +0200484 /* generate TP-UDL */
485 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200486 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200487
488 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200489 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
490 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200491 octet_len = sms->user_data_len*7/8;
492 if (sms->user_data_len*7%8 != 0)
493 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200494 /* Warning, user_data_len indicates the amount of septets
495 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200496 smsp = msgb_put(msg, octet_len);
497 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200498 break;
499 case DCS_UCS2:
500 case DCS_8BIT_DATA:
501 smsp = msgb_put(msg, sms->user_data_len);
502 memcpy(smsp, sms->user_data, sms->user_data_len);
503 break;
504 default:
Harald Welteced9a912009-12-24 15:08:18 +0100505 LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
506 sms->data_coding_scheme);
Daniel Willmann8d786602009-08-15 03:01:46 +0200507 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200508 }
Harald Welteb78996d2009-07-27 20:11:35 +0200509
Harald Welte68b7df22009-08-08 16:03:15 +0200510 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200511}
512
Harald Welte156c5e62009-07-05 14:02:46 +0200513/* process an incoming TPDU (called from RP-DATA)
514 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800515static int gsm340_rx_tpdu(struct msgb *msg)
516{
Harald Welte75350412009-07-23 18:46:00 +0200517 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800518 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800519 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200520 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
521 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800522 u_int8_t da_len_bytes;
523 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
524 int rc = 0;
525
Harald Weltebdbb7442009-12-22 19:07:32 +0100526 counter_inc(bts->network->stats.sms.submitted);
Harald Welte3edc5a92009-12-22 00:41:05 +0100527
Harald Welte68b7df22009-08-08 16:03:15 +0200528 gsms = sms_alloc();
529 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200530 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800531
532 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200533 sms_mti = *smsp & 0x03;
534 sms_mms = !!(*smsp & 0x04);
535 sms_vpf = (*smsp & 0x18) >> 3;
536 gsms->status_rep_req = (*smsp & 0x20);
537 gsms->ud_hdr_ind = (*smsp & 0x40);
538 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800539
540 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200541 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800542
543 /* length in bytes of the destination address */
544 da_len_bytes = 2 + *smsp/2 + *smsp%2;
545 if (da_len_bytes > 12) {
Harald Welteced9a912009-12-24 15:08:18 +0100546 LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200547 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800548 goto out;
549 }
Harald Welte3794e152009-06-12 02:42:11 +0800550 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800551 memcpy(address_lv, smsp, da_len_bytes);
552 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800553 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800554 /* convert to real number */
Harald Weltefdc93d92010-03-07 23:40:35 +0100555 gsm48_decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800556 smsp += da_len_bytes;
557
Harald Welte68b7df22009-08-08 16:03:15 +0200558 gsms->protocol_id = *smsp++;
559 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800560
Harald Welte68b7df22009-08-08 16:03:15 +0200561 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800562
Harald Welte68b7df22009-08-08 16:03:15 +0200563 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800564 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200565 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800566 break;
567 case GSM340_TP_VPF_ABSOLUTE:
568 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200569 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100570 /* the additional functionality indicator... */
Steffen Neubauerdd488d12009-12-05 12:44:41 +0100571 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
572 smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800573 smsp += 7;
574 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200575 case GSM340_TP_VPF_NONE:
576 sms_vp = 0;
577 break;
Harald Welte59b04682009-06-10 05:40:52 +0800578 default:
Harald Welteced9a912009-12-24 15:08:18 +0100579 LOGP(DSMS, LOGL_NOTICE,
580 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte68b7df22009-08-08 16:03:15 +0200581 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800582 }
Harald Welte68b7df22009-08-08 16:03:15 +0200583 gsms->user_data_len = *smsp++;
584 if (gsms->user_data_len) {
585 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800586
Harald Welte68b7df22009-08-08 16:03:15 +0200587 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800588 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200589 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800590 break;
591 case DCS_8BIT_DATA:
592 case DCS_UCS2:
593 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800594 break;
595 }
596 }
597
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100598 gsms->sender = subscr_get(msg->lchan->conn.subscr);
Harald Welteced9a912009-12-24 15:08:18 +0100599
600 LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
601 "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
602 "UserDataLength: 0x%02x, UserData: \"%s\"\n",
603 subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
604 gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
605 gsms->user_data_len,
Harald Welte68b7df22009-08-08 16:03:15 +0200606 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
607 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800608
Harald Welte68b7df22009-08-08 16:03:15 +0200609 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200610
Harald Welte68b7df22009-08-08 16:03:15 +0200611 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200612
Harald Welte59b04682009-06-10 05:40:52 +0800613 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200614 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800615 if (!gsms->receiver) {
616 rc = 1; /* cause 1: unknown subscriber */
Harald Weltebdbb7442009-12-22 19:07:32 +0100617 counter_inc(bts->network->stats.sms.no_receiver);
Harald Welte59b04682009-06-10 05:40:52 +0800618 goto out;
619 }
620
Harald Welte68b7df22009-08-08 16:03:15 +0200621 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800622 case GSM340_SMS_SUBMIT_MS2SC:
623 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200624 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800625 break;
626 case GSM340_SMS_COMMAND_MS2SC:
627 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welteced9a912009-12-24 15:08:18 +0100628 LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200629 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800630 break;
631 default:
Harald Welteced9a912009-12-24 15:08:18 +0100632 LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200633 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800634 break;
635 }
636
Harald Welte156c5e62009-07-05 14:02:46 +0200637 if (!rc && !gsms->receiver)
638 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
639
Harald Welte59b04682009-06-10 05:40:52 +0800640out:
Harald Welte68b7df22009-08-08 16:03:15 +0200641 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800642
643 return rc;
644}
645
Harald Welteb78996d2009-07-27 20:11:35 +0200646static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800647{
648 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800649
Harald Welte59b04682009-06-10 05:40:52 +0800650 DEBUGP(DSMS, "TX: SMS RP ACK\n");
651
Harald Welteb78996d2009-07-27 20:11:35 +0200652 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800653}
654
Harald Welteb78996d2009-07-27 20:11:35 +0200655static int gsm411_send_rp_error(struct gsm_trans *trans,
656 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800657{
658 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800659
Harald Welte59b04682009-06-10 05:40:52 +0800660 msgb_tv_put(msg, 1, cause);
661
Harald Welteced9a912009-12-24 15:08:18 +0100662 LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200663 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800664
Harald Welteb78996d2009-07-27 20:11:35 +0200665 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800666}
667
668/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200669static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
670 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800671 u_int8_t src_len, u_int8_t *src,
672 u_int8_t dst_len, u_int8_t *dst,
673 u_int8_t tpdu_len, u_int8_t *tpdu)
674{
Harald Welte59b04682009-06-10 05:40:52 +0800675 int rc = 0;
676
677 if (src_len && src)
Harald Welteced9a912009-12-24 15:08:18 +0100678 LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte59b04682009-06-10 05:40:52 +0800679
680 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Harald Welteced9a912009-12-24 15:08:18 +0100681 LOGP(DSMS, LOGL_ERROR,
682 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200683 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200684 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800685 return -EIO;
686 }
687 msg->smsh = tpdu;
688
689 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800690
691 rc = gsm340_rx_tpdu(msg);
692 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200693 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800694 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200695 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800696 else
697 return rc;
698}
699
700/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200701static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
702 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800703{
704 u_int8_t src_len, dst_len, rpud_len;
705 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
706
707 /* in the MO case, this should always be zero length */
708 src_len = rph->data[0];
709 if (src_len)
710 src = &rph->data[1];
711
712 dst_len = rph->data[1+src_len];
713 if (dst_len)
714 dst = &rph->data[1+src_len+1];
715
716 rpud_len = rph->data[1+src_len+1+dst_len];
717 if (rpud_len)
718 rp_ud = &rph->data[1+src_len+1+dst_len+1];
719
Harald Welte156c5e62009-07-05 14:02:46 +0200720 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
721 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200722 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800723 rpud_len, rp_ud);
724}
725
Harald Welte09421d32009-08-09 14:59:02 +0200726/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200727static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
728 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200729{
Harald Welte68b7df22009-08-08 16:03:15 +0200730 struct gsm_sms *sms = trans->sms.sms;
731
Harald Welte156c5e62009-07-05 14:02:46 +0200732 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
733 * successfully received a SMS. We can now safely mark it as
734 * transmitted */
735
Harald Welte09421d32009-08-09 14:59:02 +0200736 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100737 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200738 return gsm411_send_rp_error(trans, rph->msg_ref,
739 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
740 }
Harald Weltedd62b162009-07-09 23:52:59 +0200741
Harald Welte68b7df22009-08-08 16:03:15 +0200742 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100743 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200744 return gsm411_send_rp_error(trans, rph->msg_ref,
745 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200746 }
747
748 /* mark this SMS as sent in database */
749 db_sms_mark_sent(sms);
750
751 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
752
753 sms_free(sms);
754 trans->sms.sms = NULL;
755
Harald Weltefc01b242009-08-09 19:07:41 +0200756 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100757 assert(msg->lchan->conn.subscr == trans->subscr);
758
759 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltefc01b242009-08-09 19:07:41 +0200760 if (sms)
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100761 gsm411_send_sms_lchan(trans->conn, sms);
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100762
763 /* free the transaction here */
764 trans_free(trans);
765
766 /* release channel if done */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100767#warning "BROKEN. The SAPI will be released automatically by the BSC"
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100768 if (!sms)
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200769 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200770
771 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200772}
773
Harald Welteb78996d2009-07-27 20:11:35 +0200774static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
775 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200776{
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +0100777 struct gsm_network *net = trans->conn->lchan->ts->trx->bts->network;
Harald Welte68b7df22009-08-08 16:03:15 +0200778 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200779 u_int8_t cause_len = rph->data[0];
780 u_int8_t cause = rph->data[1];
781
Harald Welte156c5e62009-07-05 14:02:46 +0200782 /* Error in response to MT RP_DATA, i.e. the MS did not
783 * successfully receive the SMS. We need to investigate
784 * the cause and take action depending on it */
785
Harald Welteced9a912009-12-24 15:08:18 +0100786 LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100787 subscr_name(msg->lchan->conn.subscr), cause_len, cause,
Harald Welteced9a912009-12-24 15:08:18 +0100788 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200789
Harald Welte09421d32009-08-09 14:59:02 +0200790 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100791 LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200792#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200793 return gsm411_send_rp_error(trans, rph->msg_ref,
794 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200795#endif
Harald Welte09421d32009-08-09 14:59:02 +0200796 }
Harald Weltedd62b162009-07-09 23:52:59 +0200797
Harald Welte68b7df22009-08-08 16:03:15 +0200798 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100799 LOGP(DSMS, LOGL_ERROR,
800 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200801 return -EINVAL;
802#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200803 return gsm411_send_rp_error(trans, rph->msg_ref,
804 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200805#endif
Harald Welte09421d32009-08-09 14:59:02 +0200806 }
807
808 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
809 /* MS has not enough memory to store the message. We need
810 * to store this in our database and wati for a SMMA message */
811 /* FIXME */
812 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Weltebdbb7442009-12-22 19:07:32 +0100813 counter_inc(net->stats.sms.rp_err_mem);
Harald Welte3edc5a92009-12-22 00:41:05 +0100814 } else
Harald Weltebdbb7442009-12-22 19:07:32 +0100815 counter_inc(net->stats.sms.rp_err_other);
Harald Welte68b7df22009-08-08 16:03:15 +0200816
817 sms_free(sms);
818 trans->sms.sms = NULL;
819
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200820 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200821
Harald Welteb78996d2009-07-27 20:11:35 +0200822 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200823}
824
Harald Welteb78996d2009-07-27 20:11:35 +0200825static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
826 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200827{
Harald Weltefc01b242009-08-09 19:07:41 +0200828 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200829 int rc;
830
Harald Weltefc01b242009-08-09 19:07:41 +0200831 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
832 trans->sms.rp_state = GSM411_RPS_IDLE;
833
Harald Welte156c5e62009-07-05 14:02:46 +0200834 /* MS tells us that it has memory for more SMS, we need
835 * to check if we have any pending messages for it and then
836 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200837 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200838
Harald Weltefc01b242009-08-09 19:07:41 +0200839 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100840 assert(msg->lchan->conn.subscr == trans->subscr);
841 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltefc01b242009-08-09 19:07:41 +0200842 if (sms)
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100843 gsm411_send_sms_lchan(trans->conn, sms);
Harald Weltefc01b242009-08-09 19:07:41 +0200844 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200845 rsl_release_request(msg->lchan, trans->sms.link_id);
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100846#warning "BROKEN: The SAPI=3 will be released automatically by the BSC"
Harald Welteb78996d2009-07-27 20:11:35 +0200847
848 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200849}
850
Harald Welteb78996d2009-07-27 20:11:35 +0200851static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
852 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800853{
854 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
855 u_int8_t msg_type = rp_data->msg_type & 0x07;
856 int rc = 0;
857
858 switch (msg_type) {
859 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200860 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
861 /* start TR2N and enter 'wait to send RP-ACK state' */
862 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
863 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800864 break;
865 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200866 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
867 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200868 break;
Harald Welte59b04682009-06-10 05:40:52 +0800869 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200870 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
871 /* start TR2N and enter 'wait to send RP-ACK state' */
872 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
873 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
874 break;
875 case GSM411_MT_RP_ERROR_MO:
876 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800877 break;
878 default:
Harald Welteced9a912009-12-24 15:08:18 +0100879 LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200880 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
881 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800882 break;
883 }
884
885 return rc;
886}
887
Harald Welteb78996d2009-07-27 20:11:35 +0200888/* send CP-ACK to given transaction */
889static int gsm411_tx_cp_ack(struct gsm_trans *trans)
890{
891 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200892 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200893
Harald Weltefc01b242009-08-09 19:07:41 +0200894 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
895
896 if (trans->sms.is_mt) {
897 /* If this is a MT SMS DELIVER, we can clear transaction here */
898 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200899 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200900 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200901
902 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200903}
904
905static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
906{
907 struct msgb *msg = gsm411_msgb_alloc();
908 u_int8_t *causep;
909
Harald Welteced9a912009-12-24 15:08:18 +0100910 LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200911 get_value_string(cp_cause_strs, cause));
912
Harald Welte68b7df22009-08-08 16:03:15 +0200913 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200914 *causep = cause;
915
916 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
917}
918
919/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200920int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800921{
922 struct gsm48_hdr *gh = msgb_l3(msg);
923 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200924 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
925 struct gsm_lchan *lchan = msg->lchan;
926 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800927 int rc = 0;
928
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100929 if (!lchan->conn.subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200930 return -EIO;
931 /* FIXME: send some error message */
932
Sylvain Munaute02fb9a2009-12-18 18:28:08 +0100933 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100934 trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200935 transaction_id);
936 if (!trans) {
Sylvain Munaut40c23322009-12-18 18:28:09 +0100937 DEBUGPC(DSMS, "(new) ");
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100938 trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200939 transaction_id, new_callref++);
940 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200941 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200942 /* FIXME: send some error message */
943 return -ENOMEM;
944 }
945 trans->sms.cp_state = GSM411_CPS_IDLE;
946 trans->sms.rp_state = GSM411_RPS_IDLE;
947 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200948 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200949
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +0100950 trans->conn = &lchan->conn;
951 use_subscr_con(trans->conn);
Harald Welteb78996d2009-07-27 20:11:35 +0200952 }
953
Harald Welte59b04682009-06-10 05:40:52 +0800954 switch(msg_type) {
955 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200956 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Sylvain Munauta5914da2009-12-24 16:47:08 +0100957
958 /* 5.4: For MO, if a CP-DATA is received for a new
959 * transaction, equals reception of an implicit
960 * last CP-ACK for previous transaction */
961 if (trans->sms.cp_state == GSM411_CPS_IDLE) {
962 int i;
963 struct gsm_trans *ptrans;
964
965 /* Scan through all remote initiated transactions */
966 for (i=8; i<15; i++) {
967 if (i == transaction_id)
968 continue;
969
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100970 ptrans = trans_find_by_id(lchan->conn.subscr,
Sylvain Munauta5914da2009-12-24 16:47:08 +0100971 GSM48_PDISC_SMS, i);
972 if (!ptrans)
973 continue;
974
975 DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
976
977 /* Finish it for good */
978 bsc_del_timer(&ptrans->sms.cp_timer);
979 ptrans->sms.cp_state = GSM411_CPS_IDLE;
980 trans_free(ptrans);
981 }
982 }
983
Harald Welte09421d32009-08-09 14:59:02 +0200984 /* 5.2.3.1.3: MO state exists when SMC has received
985 * CP-DATA, including sending of the assoc. CP-ACK */
986 /* 5.2.3.2.4: MT state exists when SMC has received
987 * CP-DATA, including sending of the assoc. CP-ACK */
988 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200989
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200990 /* SMC instance acknowledges the CP-DATA frame */
991 gsm411_tx_cp_ack(trans);
992
Harald Welteb78996d2009-07-27 20:11:35 +0200993 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200994#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200995 /* Send CP-ACK or CP-ERORR in response */
996 if (rc < 0) {
997 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
998 } else
999 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001000#endif
Harald Welte59b04682009-06-10 05:40:52 +08001001 break;
1002 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +02001003 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001004 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +02001005 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
1006 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
1007 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +02001008 /* Stop TC1* after CP-ACK has been received */
1009 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +02001010
Harald Welteb78996d2009-07-27 20:11:35 +02001011 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +02001012 /* FIXME: we have sont one CP-DATA, which was now
1013 * acknowledged. Check if we want to transfer more,
1014 * i.e. multi-part message */
1015 trans->sms.cp_state = GSM411_CPS_IDLE;
1016 trans_free(trans);
1017 }
Harald Welte59b04682009-06-10 05:40:52 +08001018 break;
1019 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001020 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
1021 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +02001022 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +02001023 trans->sms.cp_state = GSM411_CPS_IDLE;
1024 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001025 break;
1026 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001027 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +02001028 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +02001029 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +02001030 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001031 break;
1032 }
1033
Harald Welte59b04682009-06-10 05:40:52 +08001034 return rc;
1035}
1036
Harald Welte59b04682009-06-10 05:40:52 +08001037#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001038/* Test TPDU - ALL YOUR */
1039static u_int8_t tpdu_test[] = {
1040 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
1041 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
1042 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
1043 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
1044};
1045#endif
1046
Harald Weltefc01b242009-08-09 19:07:41 +02001047/* Take a SMS in gsm_sms structure and send it through an already
1048 * existing lchan. We also assume that the caller ensured this lchan already
1049 * has a SAPI3 RLL connection! */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001050int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +08001051{
1052 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +02001053 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +02001054 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001055 u_int8_t msg_ref = 42;
Sylvain Munaute65af1b2009-12-24 13:27:36 +01001056 int transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +02001057 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001058
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001059 transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
Harald Welte6e55abf2009-12-22 13:45:58 +01001060 if (transaction_id == -1) {
Harald Welteced9a912009-12-24 15:08:18 +01001061 LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
Harald Welte6e55abf2009-12-22 13:45:58 +01001062 return -EBUSY;
1063 }
Harald Weltefc01b242009-08-09 19:07:41 +02001064
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001065 msg->lchan = conn->lchan;
Harald Welte59b04682009-06-10 05:40:52 +08001066
Harald Welte68b7df22009-08-08 16:03:15 +02001067 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +02001068
Harald Welte68b7df22009-08-08 16:03:15 +02001069 /* FIXME: allocate transaction with message reference */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001070 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welte68b7df22009-08-08 16:03:15 +02001071 transaction_id, new_callref++);
1072 if (!trans) {
Harald Welteced9a912009-12-24 15:08:18 +01001073 LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
Harald Welte68b7df22009-08-08 16:03:15 +02001074 /* FIXME: send some error message */
1075 return -ENOMEM;
1076 }
1077 trans->sms.cp_state = GSM411_CPS_IDLE;
1078 trans->sms.rp_state = GSM411_RPS_IDLE;
1079 trans->sms.is_mt = 1;
1080 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001081 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +02001082
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001083 trans->conn = conn;
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +01001084 use_subscr_con(trans->conn);
Harald Welte68b7df22009-08-08 16:03:15 +02001085
1086 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +08001087 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001088 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +02001089 data[1] = 0x91; /* type of number: international, ISDN */
1090 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +08001091 data[3] = 0x77;
1092 data[4] = 0x58;
1093 data[5] = 0x10;
1094 data[6] = 0x06;
1095 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001096
1097 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +08001098 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001099 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +08001100
Harald Welte68b7df22009-08-08 16:03:15 +02001101 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1102 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +08001103
Harald Welte68b7df22009-08-08 16:03:15 +02001104#if 1
1105 /* generate the 03.40 TPDU */
1106 rc = gsm340_gen_tpdu(msg, sms);
1107 if (rc < 0) {
1108 msgb_free(msg);
1109 return rc;
1110 }
Harald Welte59b04682009-06-10 05:40:52 +08001111
Harald Welte68b7df22009-08-08 16:03:15 +02001112 *rp_ud_len = rc;
1113#else
1114 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +08001115 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +02001116 *rp_ud_len = sizeof(tpdu_test);
1117#endif
Harald Welte59b04682009-06-10 05:40:52 +08001118
Harald Welte68b7df22009-08-08 16:03:15 +02001119 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001120
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001121 counter_inc(conn->lchan->ts->trx->bts->network->stats.sms.delivered);
Harald Welte3edc5a92009-12-22 00:41:05 +01001122
Harald Welteb78996d2009-07-27 20:11:35 +02001123 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1124 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001125}
Harald Welteb78996d2009-07-27 20:11:35 +02001126
Harald Weltefc01b242009-08-09 19:07:41 +02001127/* RLL SAPI3 establish callback. Now we have a RLL connection and
1128 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001129static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1130 void *_sms, enum bsc_rllr_ind type)
1131{
1132 struct gsm_sms *sms = _sms;
1133
1134 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1135 lchan, link_id, sms, type);
1136
1137 switch (type) {
1138 case BSC_RLLR_IND_EST_CONF:
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001139#warning "BROKEN: The BSC will establish this transparently"
1140 gsm411_send_sms_lchan(&lchan->conn, sms);
Harald Welte09421d32009-08-09 14:59:02 +02001141 break;
1142 case BSC_RLLR_IND_REL_IND:
1143 case BSC_RLLR_IND_ERR_IND:
1144 case BSC_RLLR_IND_TIMEOUT:
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001145#warning "BROKEN: We will need to handle SAPI n Reject"
Harald Welte09421d32009-08-09 14:59:02 +02001146 sms_free(sms);
1147 break;
1148 }
1149}
1150
Harald Weltefc01b242009-08-09 19:07:41 +02001151/* paging callback. Here we get called if paging a subscriber has
1152 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001153static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1154 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001155{
Harald Welte68b7df22009-08-08 16:03:15 +02001156 struct gsm_lchan *lchan = _lchan;
1157 struct gsm_sms *sms = _sms;
1158 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001159
Harald Welte68b7df22009-08-08 16:03:15 +02001160 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1161 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1162
1163 if (hooknum != GSM_HOOK_RR_PAGING)
1164 return -EINVAL;
1165
1166 switch (event) {
1167 case GSM_PAGING_SUCCEEDED:
1168 /* Paging aborted without lchan ?!? */
1169 if (!lchan) {
1170 sms_free(sms);
1171 rc = -EIO;
1172 break;
1173 }
Harald Weltefc01b242009-08-09 19:07:41 +02001174 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001175 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001176 break;
1177 case GSM_PAGING_EXPIRED:
1178 sms_free(sms);
1179 rc = -ETIMEDOUT;
1180 break;
1181 default:
1182 rc = -EINVAL;
1183 break;
1184 }
1185
1186 return rc;
1187}
1188
Harald Weltefc01b242009-08-09 19:07:41 +02001189/* high-level function to send a SMS to a given subscriber. The function
1190 * will take care of paging the subscriber, establishing the RLL SAPI3
1191 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001192int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1193 struct gsm_sms *sms)
1194{
Harald Weltefc01b242009-08-09 19:07:41 +02001195 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001196 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001197
Harald Welte68b7df22009-08-08 16:03:15 +02001198 /* check if we already have an open lchan to the subscriber.
1199 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001200 lchan = lchan_for_subscr(subscr);
1201 if (lchan)
1202 return rll_establish(lchan, UM_SAPI_SMS,
1203 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001204
1205 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001206 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1207 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001208 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001209 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001210
1211 return 0;
1212}
Harald Welte5b359d82009-07-28 00:44:49 +02001213
Harald Weltefc01b242009-08-09 19:07:41 +02001214static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1215 void *handler_data, void *signal_data)
1216{
1217 struct gsm_subscriber *subscr;
1218 struct gsm_lchan *lchan;
1219 struct gsm_sms *sms;
1220
1221 switch (signal) {
1222 case S_SUBSCR_ATTACHED:
1223 /* A subscriber has attached. Check if there are
1224 * any pending SMS for him to be delivered */
1225 subscr = signal_data;
1226 lchan = lchan_for_subscr(subscr);
1227 if (!lchan)
1228 break;
1229 sms = db_sms_get_unsent_for_subscr(subscr);
1230 if (!sms)
1231 break;
1232 /* Establish a SAPI3 RLL connection for SMS */
1233 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1234 break;
1235 default:
1236 break;
1237 }
1238 return 0;
1239}
1240
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001241void _gsm411_sms_trans_free(struct gsm_trans *trans)
1242{
1243 bsc_del_timer(&trans->sms.cp_timer);
1244}
1245
Harald Welte932e20d2009-07-28 00:41:45 +02001246static __attribute__((constructor)) void on_dso_load_sms(void)
1247{
Harald Weltefc01b242009-08-09 19:07:41 +02001248 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001249}