blob: b835679f6d57b35aa811dbd65ac2303bf940138a [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
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +010027#include <assert.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <errno.h>
Harald Weltef3efc592009-07-27 20:11:35 +020032#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000033#include <netinet/in.h>
34
Harald Weltedfe6c7d2010-02-20 16:24:02 +010035#include <osmocore/msgb.h>
36#include <osmocore/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000037#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000038#include <openbsc/gsm_data.h>
39#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000040#include <openbsc/gsm_04_11.h>
41#include <openbsc/gsm_04_08.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010042#include <osmocore/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000043#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000044#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000045#include <openbsc/db.h>
Harald Weltedfe6c7d2010-02-20 16:24:02 +010046#include <osmocore/talloc.h>
Harald Weltef3efc592009-07-27 20:11:35 +020047#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020048#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020049#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020050#include <openbsc/chan_alloc.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000051
Daniel Willmann471712b2008-12-29 01:54:02 +000052#define GSM411_ALLOC_SIZE 1024
53#define GSM411_ALLOC_HEADROOM 128
54
Harald Weltecb8f4432009-08-09 14:59:02 +020055#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
56
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020057void *tall_gsms_ctx;
Harald Weltef3efc592009-07-27 20:11:35 +020058static u_int32_t new_callref = 0x40000001;
59
Harald Welte (local)c89a5112009-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 Welte76042182009-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
Holger Freythera553d092009-01-04 20:16:25 +0000119struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +0000120{
Harald Welte966636f2009-06-26 19:39:35 +0200121 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
122 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +0000123}
124
Holger Hans Peter Freytherec32b582010-03-23 07:40:46 +0100125static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id)
Daniel Willmann471712b2008-12-29 01:54:02 +0000126{
Harald Welte76042182009-08-08 16:03:15 +0200127 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
Holger Hans Peter Freytherec32b582010-03-23 07:40:46 +0100128 msg->l3h = msg->data;
129 return gsm0808_submit_dtap(conn, msg, link_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000130}
131
Harald Welte41985612009-08-10 00:24:32 +0200132/* SMC TC1* is expired */
133static void cp_timer_expired(void *data)
134{
135 struct gsm_trans *trans = data;
136
137 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
138 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
139 trans_free(trans);
140}
141
Harald Welte87f5d632009-07-04 17:39:00 +0200142/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200143static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
144 u_int8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +0200145{
146 struct gsm48_hdr *gh;
147
148 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
149 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +0200150 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200151 gh->msg_type = msg_type;
152
Harald Weltef3efc592009-07-27 20:11:35 +0200153 /* mobile originating */
154 switch (gh->msg_type) {
155 case GSM411_MT_CP_DATA:
156 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Weltecb8f4432009-08-09 14:59:02 +0200157 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200158 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte41985612009-08-10 00:24:32 +0200159 trans->sms.cp_timer.data = trans;
160 trans->sms.cp_timer.cb = cp_timer_expired;
161 /* 5.3.2.1: Set Timer TC1A */
162 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200163 DEBUGP(DSMS, "TX: CP-DATA ");
164 break;
165 case GSM411_MT_CP_ACK:
166 DEBUGP(DSMS, "TX: CP-ACK ");
167 break;
168 case GSM411_MT_CP_ERROR:
Sylvain Munaut1d9efd62009-12-18 18:28:07 +0100169 DEBUGP(DSMS, "TX: CP-ERROR ");
Harald Weltef3efc592009-07-27 20:11:35 +0200170 break;
171 }
172
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200173 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
174
Holger Hans Peter Freytherec32b582010-03-23 07:40:46 +0100175 return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id);
Harald Welte87f5d632009-07-04 17:39:00 +0200176}
177
178/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200179static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
180 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte87f5d632009-07-04 17:39:00 +0200181{
182 struct gsm411_rp_hdr *rp;
Harald Welte0d544e72009-08-10 00:22:19 +0200183 u_int8_t len = msg->len;
Harald Welte87f5d632009-07-04 17:39:00 +0200184
185 /* GSM 04.11 RP-DATA header */
186 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Welte0d544e72009-08-10 00:22:19 +0200187 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200188 rp->msg_type = rp_msg_type;
189 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
190
Harald Weltef3efc592009-07-27 20:11:35 +0200191 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200192}
193
Steffen Neubauerf3262672009-11-26 12:28:41 +0100194/* Turn int into semi-octet representation: 98 => 0x89 */
195static u_int8_t bcdify(u_int8_t value)
196{
197 u_int8_t ret;
Steffen Neubauer5727cf42009-11-11 23:02:07 +0900198
Steffen Neubauerf3262672009-11-26 12:28:41 +0100199 ret = value / 10;
200 ret |= (value % 10) << 4;
201
202 return ret;
203}
204
205/* Turn semi-octet representation into int: 0x89 => 98 */
206static u_int8_t unbcdify(u_int8_t value)
207{
208 u_int8_t ret;
209
210 if ((value & 0x0F) > 9 || (value >> 4) > 9)
Harald Welted0cf7ba2009-12-24 15:08:18 +0100211 LOGP(DSMS, LOGL_ERROR,
212 "unbcdify got too big nibble: 0x%02X\n", value);
Steffen Neubauerf3262672009-11-26 12:28:41 +0100213
214 ret = (value&0x0F)*10;
Steffen Neubauerad69d7f2009-11-26 23:38:41 +0100215 ret += value>>4;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100216
217 return ret;
218}
219
220/* Generate 03.40 TP-SCTS */
221static void gsm340_gen_scts(u_int8_t *scts, time_t time)
222{
223 struct tm *tm = localtime(&time);
224
225 *scts++ = bcdify(tm->tm_year % 100);
226 *scts++ = bcdify(tm->tm_mon + 1);
227 *scts++ = bcdify(tm->tm_mday);
228 *scts++ = bcdify(tm->tm_hour);
229 *scts++ = bcdify(tm->tm_min);
230 *scts++ = bcdify(tm->tm_sec);
231 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
232}
233
234/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
235static time_t gsm340_scts(u_int8_t *scts)
236{
237 struct tm tm;
238
239 u_int8_t yr = unbcdify(*scts++);
240
241 if (yr <= 80)
242 tm.tm_year = 100 + yr;
243 else
244 tm.tm_year = yr;
245 tm.tm_mon = unbcdify(*scts++) - 1;
246 tm.tm_mday = unbcdify(*scts++);
247 tm.tm_hour = unbcdify(*scts++);
248 tm.tm_min = unbcdify(*scts++);
249 tm.tm_sec = unbcdify(*scts++);
250 /* according to gsm 03.40 time zone is
251 "expressed in quarters of an hour" */
252 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
253
254 return mktime(&tm);
255}
256
257/* Return the default validity period in minutes */
258static unsigned long gsm340_vp_default(void)
259{
260 unsigned long minutes;
261 /* Default validity: two days */
262 minutes = 24 * 60 * 2;
263 return minutes;
264}
265
266/* Decode validity period format 'relative' */
267static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
268{
269 /* Chapter 9.2.3.12.1 */
270 u_int8_t vp;
271 unsigned long minutes;
272
273 vp = *(sms_vp);
274 if (vp <= 143)
275 minutes = vp + 1 * 5;
276 else if (vp <= 167)
277 minutes = 12*60 + (vp-143) * 30;
278 else if (vp <= 196)
279 minutes = vp-166 * 60 * 24;
280 else
281 minutes = vp-192 * 60 * 24 * 7;
282 return minutes;
283}
284
285/* Decode validity period format 'absolute' */
286static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
287{
288 /* Chapter 9.2.3.12.2 */
289 time_t expires, now;
290 unsigned long minutes;
291
292 expires = gsm340_scts(sms_vp);
293 now = mktime(gmtime(NULL));
294 if (expires <= now)
295 minutes = 0;
296 else
297 minutes = (expires-now)/60;
298 return minutes;
299}
300
301/* Decode validity period format 'relative in integer representation' */
302static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000303{
304 u_int8_t vp;
305 unsigned long minutes;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100306 vp = *(sms_vp);
307 if (vp == 0) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100308 LOGP(DSMS, LOGL_ERROR,
309 "reserved relative_integer validity period\n");
Steffen Neubauerf3262672009-11-26 12:28:41 +0100310 return gsm340_vp_default();
311 }
312 minutes = vp/60;
313 return minutes;
314}
315
316/* Decode validity period format 'relative in semi-octet representation' */
317static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
318{
319 unsigned long minutes;
320 minutes = unbcdify(*sms_vp++)*60; /* hours */
321 minutes += unbcdify(*sms_vp++); /* minutes */
322 minutes += unbcdify(*sms_vp++)/60; /* seconds */
323 return minutes;
324}
325
326/* decode validity period. return minutes */
327static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
328{
329 u_int8_t fi; /* functionality indicator */
Harald Welte7e310b12009-03-30 20:56:32 +0000330
Harald Welte76042182009-08-08 16:03:15 +0200331 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000332 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100333 return gsm340_vp_relative(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000334 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100335 return gsm340_vp_absolute(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000336 case GSM340_TP_VPF_ENHANCED:
337 /* Chapter 9.2.3.12.3 */
Steffen Neubauerf3262672009-11-26 12:28:41 +0100338 fi = *sms_vp++;
339 /* ignore additional fi */
340 if (fi & (1<<7)) sms_vp++;
341 /* read validity period format */
342 switch (fi & 0b111) {
343 case 0b000:
344 return gsm340_vp_default(); /* no vpf specified */
345 case 0b001:
346 return gsm340_vp_relative(sms_vp);
347 case 0b010:
348 return gsm340_vp_relative_integer(sms_vp);
349 case 0b011:
350 return gsm340_vp_relative_semioctet(sms_vp);
351 default:
352 /* The GSM spec says that the SC should reject any
353 unsupported and/or undefined values. FIXME */
Harald Welted0cf7ba2009-12-24 15:08:18 +0100354 LOGP(DSMS, LOGL_ERROR,
355 "Reserved enhanced validity period format\n");
Steffen Neubauerf3262672009-11-26 12:28:41 +0100356 return gsm340_vp_default();
357 }
Daniel Willmann58c83d82009-08-13 03:40:49 +0200358 case GSM340_TP_VPF_NONE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100359 default:
360 return gsm340_vp_default();
Harald Welte7e310b12009-03-30 20:56:32 +0000361 }
Harald Welte7e310b12009-03-30 20:56:32 +0000362}
363
364/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
365enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
366{
367 u_int8_t cgbits = dcs >> 4;
368 enum sms_alphabet alpha = DCS_NONE;
369
370 if ((cgbits & 0xc) == 0) {
371 if (cgbits & 2)
Harald Welted0cf7ba2009-12-24 15:08:18 +0100372 LOGP(DSMS, LOGL_NOTICE,
373 "Compressed SMS not supported yet\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000374
Daniel Willmannd5d5e1d2009-08-15 03:01:17 +0200375 switch ((dcs >> 2)&0x03) {
Harald Welte7e310b12009-03-30 20:56:32 +0000376 case 0:
377 alpha = DCS_7BIT_DEFAULT;
378 break;
379 case 1:
380 alpha = DCS_8BIT_DATA;
381 break;
382 case 2:
383 alpha = DCS_UCS2;
384 break;
385 }
386 } else if (cgbits == 0xc || cgbits == 0xd)
387 alpha = DCS_7BIT_DEFAULT;
388 else if (cgbits == 0xe)
389 alpha = DCS_UCS2;
390 else if (cgbits == 0xf) {
391 if (dcs & 4)
392 alpha = DCS_8BIT_DATA;
393 else
394 alpha = DCS_7BIT_DEFAULT;
395 }
396
397 return alpha;
398}
399
Harald Welte76042182009-08-08 16:03:15 +0200400static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000401{
402 if (db_sms_store(gsms) != 0) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100403 LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200404 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000405 }
Harald Welte76042182009-08-08 16:03:15 +0200406 /* dispatch a signal to tell higher level about it */
407 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200408 /* try delivering the SMS right now */
409 //gsm411_send_sms_subscr(gsms->receiver, gsms);
410
Harald Welte7e310b12009-03-30 20:56:32 +0000411 return 0;
412}
413
Harald Welte76042182009-08-08 16:03:15 +0200414/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
415static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
416 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200417{
Harald Welte76042182009-08-08 16:03:15 +0200418 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200419
Harald Welte76042182009-08-08 16:03:15 +0200420 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
421
Harald Welte55c8f352010-03-07 23:40:35 +0100422 len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, subscr->extension);
Harald Welte76042182009-08-08 16:03:15 +0200423
424 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
425 oa[0] = strlen(subscr->extension) & 0xff;
426
427 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200428}
429
Harald Welte76042182009-08-08 16:03:15 +0200430/* generate a msgb containing a TPDU derived from struct gsm_sms,
431 * returns total size of TPDU */
432static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200433{
Harald Weltef3efc592009-07-27 20:11:35 +0200434 u_int8_t *smsp;
435 u_int8_t oa[12]; /* max len per 03.40 */
436 u_int8_t oa_len = 0;
Daniel Willmann9aef1452009-08-13 03:39:07 +0200437 u_int8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200438 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200439
440 /* generate first octet with masked bits */
441 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200442 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200443 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200444 /* TP-MMS (more messages to send) */
445 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200446 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200447 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200448 if (sms->status_rep_req)
449 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200450 /* TP-UDHI (indicating TP-UD contains a header) */
451 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200452 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200453#if 0
454 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200455 if (sms->
456 *smsp |= 0x80;
457#endif
458
459 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200460 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200461 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200462 memcpy(smsp, oa, oa_len);
463
464 /* generate TP-PID */
465 smsp = msgb_put(msg, 1);
466 *smsp = sms->protocol_id;
467
468 /* generate TP-DCS */
469 smsp = msgb_put(msg, 1);
470 *smsp = sms->data_coding_scheme;
471
472 /* generate TP-SCTS */
473 smsp = msgb_put(msg, 7);
474 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200475
Harald Weltef3efc592009-07-27 20:11:35 +0200476 /* generate TP-UDL */
477 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200478 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200479
480 /* generate TP-UD */
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200481 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
482 case DCS_7BIT_DEFAULT:
Daniel Willmann9aef1452009-08-13 03:39:07 +0200483 octet_len = sms->user_data_len*7/8;
484 if (sms->user_data_len*7%8 != 0)
485 octet_len++;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200486 /* Warning, user_data_len indicates the amount of septets
487 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200488 smsp = msgb_put(msg, octet_len);
489 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200490 break;
491 case DCS_UCS2:
492 case DCS_8BIT_DATA:
493 smsp = msgb_put(msg, sms->user_data_len);
494 memcpy(smsp, sms->user_data, sms->user_data_len);
495 break;
496 default:
Harald Welted0cf7ba2009-12-24 15:08:18 +0100497 LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
498 sms->data_coding_scheme);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200499 break;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200500 }
Harald Weltef3efc592009-07-27 20:11:35 +0200501
Harald Welte76042182009-08-08 16:03:15 +0200502 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200503}
504
Harald Welteb9c758b2009-07-05 14:02:46 +0200505/* process an incoming TPDU (called from RP-DATA)
506 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000507static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000508{
Harald Welte9176bd42009-07-23 18:46:00 +0200509 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000510 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000511 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200512 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
513 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000514 u_int8_t da_len_bytes;
515 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
516 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000517
Harald Welteffa55a42009-12-22 19:07:32 +0100518 counter_inc(bts->network->stats.sms.submitted);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100519
Harald Welte76042182009-08-08 16:03:15 +0200520 gsms = sms_alloc();
521 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200522 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000523
524 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200525 sms_mti = *smsp & 0x03;
526 sms_mms = !!(*smsp & 0x04);
527 sms_vpf = (*smsp & 0x18) >> 3;
528 gsms->status_rep_req = (*smsp & 0x20);
529 gsms->ud_hdr_ind = (*smsp & 0x40);
530 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000531
532 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200533 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000534
Harald Welte7e310b12009-03-30 20:56:32 +0000535 /* length in bytes of the destination address */
536 da_len_bytes = 2 + *smsp/2 + *smsp%2;
537 if (da_len_bytes > 12) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100538 LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200539 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000540 goto out;
541 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800542 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000543 memcpy(address_lv, smsp, da_len_bytes);
544 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800545 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000546 /* convert to real number */
Harald Welte55c8f352010-03-07 23:40:35 +0100547 gsm48_decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000548 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000549
Harald Welte76042182009-08-08 16:03:15 +0200550 gsms->protocol_id = *smsp++;
551 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000552
Harald Welte76042182009-08-08 16:03:15 +0200553 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000554
Harald Welte76042182009-08-08 16:03:15 +0200555 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000556 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200557 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000558 break;
559 case GSM340_TP_VPF_ABSOLUTE:
560 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200561 sms_vp = smsp;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100562 /* the additional functionality indicator... */
Steffen Neubauerac0c13c2009-12-05 12:44:41 +0100563 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
564 smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000565 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000566 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200567 case GSM340_TP_VPF_NONE:
568 sms_vp = 0;
569 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000570 default:
Harald Welted0cf7ba2009-12-24 15:08:18 +0100571 LOGP(DSMS, LOGL_NOTICE,
572 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte76042182009-08-08 16:03:15 +0200573 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000574 }
Harald Welte76042182009-08-08 16:03:15 +0200575 gsms->user_data_len = *smsp++;
576 if (gsms->user_data_len) {
577 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000578
Harald Welte76042182009-08-08 16:03:15 +0200579 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000580 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200581 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000582 break;
583 case DCS_8BIT_DATA:
584 case DCS_UCS2:
585 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000586 break;
587 }
588 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000589
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100590 gsms->sender = subscr_get(msg->lchan->conn.subscr);
Harald Welted0cf7ba2009-12-24 15:08:18 +0100591
592 LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
593 "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
594 "UserDataLength: 0x%02x, UserData: \"%s\"\n",
595 subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
596 gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
597 gsms->user_data_len,
Harald Welte76042182009-08-08 16:03:15 +0200598 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
599 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000600
Harald Welte76042182009-08-08 16:03:15 +0200601 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200602
Harald Welte76042182009-08-08 16:03:15 +0200603 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200604
Harald Welte7e310b12009-03-30 20:56:32 +0000605 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200606 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000607 if (!gsms->receiver) {
608 rc = 1; /* cause 1: unknown subscriber */
Harald Welteffa55a42009-12-22 19:07:32 +0100609 counter_inc(bts->network->stats.sms.no_receiver);
Harald Welte7e310b12009-03-30 20:56:32 +0000610 goto out;
611 }
612
Harald Welte76042182009-08-08 16:03:15 +0200613 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000614 case GSM340_SMS_SUBMIT_MS2SC:
615 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200616 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000617 break;
618 case GSM340_SMS_COMMAND_MS2SC:
619 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welted0cf7ba2009-12-24 15:08:18 +0100620 LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200621 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000622 break;
623 default:
Harald Welted0cf7ba2009-12-24 15:08:18 +0100624 LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200625 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000626 break;
627 }
628
Harald Welteb9c758b2009-07-05 14:02:46 +0200629 if (!rc && !gsms->receiver)
630 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
631
Harald Welte7e310b12009-03-30 20:56:32 +0000632out:
Harald Welte76042182009-08-08 16:03:15 +0200633 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000634
Harald Welte7e310b12009-03-30 20:56:32 +0000635 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000636}
637
Harald Weltef3efc592009-07-27 20:11:35 +0200638static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000639{
640 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000641
Daniel Willmann471712b2008-12-29 01:54:02 +0000642 DEBUGP(DSMS, "TX: SMS RP ACK\n");
643
Harald Weltef3efc592009-07-27 20:11:35 +0200644 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000645}
646
Harald Weltef3efc592009-07-27 20:11:35 +0200647static int gsm411_send_rp_error(struct gsm_trans *trans,
648 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000649{
650 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000651
Harald Welte7e310b12009-03-30 20:56:32 +0000652 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000653
Harald Welted0cf7ba2009-12-24 15:08:18 +0100654 LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200655 get_value_string(rp_cause_strs, cause));
Daniel Willmann471712b2008-12-29 01:54:02 +0000656
Harald Weltef3efc592009-07-27 20:11:35 +0200657 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000658}
659
Harald Welte7e310b12009-03-30 20:56:32 +0000660/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200661static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
662 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000663 u_int8_t src_len, u_int8_t *src,
664 u_int8_t dst_len, u_int8_t *dst,
665 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000666{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000667 int rc = 0;
668
Harald Welte7e310b12009-03-30 20:56:32 +0000669 if (src_len && src)
Harald Welted0cf7ba2009-12-24 15:08:18 +0100670 LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte7e310b12009-03-30 20:56:32 +0000671
672 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100673 LOGP(DSMS, LOGL_ERROR,
674 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200675 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200676 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000677 return -EIO;
678 }
679 msg->smsh = tpdu;
680
681 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000682
683 rc = gsm340_rx_tpdu(msg);
684 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200685 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000686 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200687 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000688 else
689 return rc;
690}
691
692/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200693static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
694 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000695{
696 u_int8_t src_len, dst_len, rpud_len;
697 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
698
699 /* in the MO case, this should always be zero length */
700 src_len = rph->data[0];
701 if (src_len)
702 src = &rph->data[1];
703
704 dst_len = rph->data[1+src_len];
705 if (dst_len)
706 dst = &rph->data[1+src_len+1];
707
708 rpud_len = rph->data[1+src_len+1+dst_len];
709 if (rpud_len)
710 rp_ud = &rph->data[1+src_len+1+dst_len+1];
711
Harald Welteb9c758b2009-07-05 14:02:46 +0200712 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
713 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200714 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000715 rpud_len, rp_ud);
716}
717
Harald Weltecb8f4432009-08-09 14:59:02 +0200718/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200719static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
720 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200721{
Harald Welte76042182009-08-08 16:03:15 +0200722 struct gsm_sms *sms = trans->sms.sms;
723
Harald Welteb9c758b2009-07-05 14:02:46 +0200724 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
725 * successfully received a SMS. We can now safely mark it as
726 * transmitted */
727
Harald Weltecb8f4432009-08-09 14:59:02 +0200728 if (!trans->sms.is_mt) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100729 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200730 return gsm411_send_rp_error(trans, rph->msg_ref,
731 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
732 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200733
Harald Welte76042182009-08-08 16:03:15 +0200734 if (!sms) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100735 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200736 return gsm411_send_rp_error(trans, rph->msg_ref,
737 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200738 }
739
740 /* mark this SMS as sent in database */
741 db_sms_mark_sent(sms);
742
743 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
744
745 sms_free(sms);
746 trans->sms.sms = NULL;
747
Harald Weltecf6a3812009-08-09 19:07:41 +0200748 /* check for more messages for this subscriber */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100749 assert(msg->lchan->conn.subscr == trans->subscr);
750
751 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltecf6a3812009-08-09 19:07:41 +0200752 if (sms)
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100753 gsm411_send_sms_lchan(trans->conn, sms);
Sylvain Munautd6c35f62009-12-24 13:33:51 +0100754
755 /* free the transaction here */
756 trans_free(trans);
757
758 /* release channel if done */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100759#warning "BROKEN. The SAPI will be released automatically by the BSC"
Sylvain Munautd6c35f62009-12-24 13:33:51 +0100760 if (!sms)
Harald Welte (local)daef6062009-08-14 11:41:12 +0200761 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte76042182009-08-08 16:03:15 +0200762
763 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200764}
765
Harald Weltef3efc592009-07-27 20:11:35 +0200766static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
767 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200768{
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +0100769 struct gsm_network *net = trans->conn->lchan->ts->trx->bts->network;
Harald Welte76042182009-08-08 16:03:15 +0200770 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200771 u_int8_t cause_len = rph->data[0];
772 u_int8_t cause = rph->data[1];
773
Harald Welteb9c758b2009-07-05 14:02:46 +0200774 /* Error in response to MT RP_DATA, i.e. the MS did not
775 * successfully receive the SMS. We need to investigate
776 * the cause and take action depending on it */
777
Harald Welted0cf7ba2009-12-24 15:08:18 +0100778 LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100779 subscr_name(msg->lchan->conn.subscr), cause_len, cause,
Harald Welted0cf7ba2009-12-24 15:08:18 +0100780 get_value_string(rp_cause_strs, cause));
Harald Weltef3efc592009-07-27 20:11:35 +0200781
Harald Weltecb8f4432009-08-09 14:59:02 +0200782 if (!trans->sms.is_mt) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100783 LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200784#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200785 return gsm411_send_rp_error(trans, rph->msg_ref,
786 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200787#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200788 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200789
Harald Welte76042182009-08-08 16:03:15 +0200790 if (!sms) {
Harald Welted0cf7ba2009-12-24 15:08:18 +0100791 LOGP(DSMS, LOGL_ERROR,
792 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200793 return -EINVAL;
794#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200795 return gsm411_send_rp_error(trans, rph->msg_ref,
796 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200797#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200798 }
799
800 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
801 /* MS has not enough memory to store the message. We need
802 * to store this in our database and wati for a SMMA message */
803 /* FIXME */
804 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welteffa55a42009-12-22 19:07:32 +0100805 counter_inc(net->stats.sms.rp_err_mem);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100806 } else
Harald Welteffa55a42009-12-22 19:07:32 +0100807 counter_inc(net->stats.sms.rp_err_other);
Harald Welte76042182009-08-08 16:03:15 +0200808
809 sms_free(sms);
810 trans->sms.sms = NULL;
811
Harald Welte (local)86b17172009-08-14 14:52:17 +0200812 //trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200813
Harald Weltef3efc592009-07-27 20:11:35 +0200814 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200815}
816
Harald Weltef3efc592009-07-27 20:11:35 +0200817static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
818 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200819{
Harald Weltecf6a3812009-08-09 19:07:41 +0200820 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200821 int rc;
822
Harald Weltecf6a3812009-08-09 19:07:41 +0200823 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
824 trans->sms.rp_state = GSM411_RPS_IDLE;
825
Harald Welteb9c758b2009-07-05 14:02:46 +0200826 /* MS tells us that it has memory for more SMS, we need
827 * to check if we have any pending messages for it and then
828 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200829 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200830
Harald Weltecf6a3812009-08-09 19:07:41 +0200831 /* check for more messages for this subscriber */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100832 assert(msg->lchan->conn.subscr == trans->subscr);
833 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltecf6a3812009-08-09 19:07:41 +0200834 if (sms)
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100835 gsm411_send_sms_lchan(trans->conn, sms);
Harald Weltecf6a3812009-08-09 19:07:41 +0200836 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200837 rsl_release_request(msg->lchan, trans->sms.link_id);
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +0100838#warning "BROKEN: The SAPI=3 will be released automatically by the BSC"
Harald Weltef3efc592009-07-27 20:11:35 +0200839
840 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200841}
842
Harald Weltef3efc592009-07-27 20:11:35 +0200843static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
844 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000845{
Daniel Willmann471712b2008-12-29 01:54:02 +0000846 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000847 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000848 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000849
850 switch (msg_type) {
851 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200852 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
853 /* start TR2N and enter 'wait to send RP-ACK state' */
854 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
855 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000856 break;
857 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200858 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
859 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200860 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000861 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200862 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
863 /* start TR2N and enter 'wait to send RP-ACK state' */
864 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
865 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
866 break;
867 case GSM411_MT_RP_ERROR_MO:
868 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000869 break;
870 default:
Harald Welted0cf7ba2009-12-24 15:08:18 +0100871 LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200872 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
873 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000874 break;
875 }
876
877 return rc;
878}
879
Harald Weltef3efc592009-07-27 20:11:35 +0200880/* send CP-ACK to given transaction */
881static int gsm411_tx_cp_ack(struct gsm_trans *trans)
882{
883 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200884 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200885
Harald Weltecf6a3812009-08-09 19:07:41 +0200886 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
887
888 if (trans->sms.is_mt) {
889 /* If this is a MT SMS DELIVER, we can clear transaction here */
890 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)86b17172009-08-14 14:52:17 +0200891 //trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200892 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200893
894 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200895}
896
897static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
898{
899 struct msgb *msg = gsm411_msgb_alloc();
900 u_int8_t *causep;
901
Harald Welted0cf7ba2009-12-24 15:08:18 +0100902 LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200903 get_value_string(cp_cause_strs, cause));
904
Harald Welte76042182009-08-08 16:03:15 +0200905 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200906 *causep = cause;
907
908 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
909}
910
911/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)daef6062009-08-14 11:41:12 +0200912int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000913{
914 struct gsm48_hdr *gh = msgb_l3(msg);
915 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200916 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
917 struct gsm_lchan *lchan = msg->lchan;
918 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000919 int rc = 0;
920
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100921 if (!lchan->conn.subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200922 return -EIO;
923 /* FIXME: send some error message */
924
Sylvain Munautc56a1412009-12-18 18:28:08 +0100925 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100926 trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Weltef3efc592009-07-27 20:11:35 +0200927 transaction_id);
928 if (!trans) {
Sylvain Munautfeaca922009-12-18 18:28:09 +0100929 DEBUGPC(DSMS, "(new) ");
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100930 trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Weltef3efc592009-07-27 20:11:35 +0200931 transaction_id, new_callref++);
932 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200933 DEBUGPC(DSMS, "No memory for trans\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200934 /* FIXME: send some error message */
935 return -ENOMEM;
936 }
937 trans->sms.cp_state = GSM411_CPS_IDLE;
938 trans->sms.rp_state = GSM411_RPS_IDLE;
939 trans->sms.is_mt = 0;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200940 trans->sms.link_id = link_id;
Harald Weltef3efc592009-07-27 20:11:35 +0200941
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +0100942 trans->conn = &lchan->conn;
943 use_subscr_con(trans->conn);
Harald Weltef3efc592009-07-27 20:11:35 +0200944 }
945
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000946 switch(msg_type) {
947 case GSM411_MT_CP_DATA:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200948 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100949
950 /* 5.4: For MO, if a CP-DATA is received for a new
951 * transaction, equals reception of an implicit
952 * last CP-ACK for previous transaction */
953 if (trans->sms.cp_state == GSM411_CPS_IDLE) {
954 int i;
955 struct gsm_trans *ptrans;
956
957 /* Scan through all remote initiated transactions */
958 for (i=8; i<15; i++) {
959 if (i == transaction_id)
960 continue;
961
Holger Hans Peter Freyther68884aa2010-03-23 06:41:45 +0100962 ptrans = trans_find_by_id(lchan->conn.subscr,
Sylvain Munaut258e2f92009-12-24 16:47:08 +0100963 GSM48_PDISC_SMS, i);
964 if (!ptrans)
965 continue;
966
967 DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
968
969 /* Finish it for good */
970 bsc_del_timer(&ptrans->sms.cp_timer);
971 ptrans->sms.cp_state = GSM411_CPS_IDLE;
972 trans_free(ptrans);
973 }
974 }
975
Harald Weltecb8f4432009-08-09 14:59:02 +0200976 /* 5.2.3.1.3: MO state exists when SMC has received
977 * CP-DATA, including sending of the assoc. CP-ACK */
978 /* 5.2.3.2.4: MT state exists when SMC has received
979 * CP-DATA, including sending of the assoc. CP-ACK */
980 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200981
Harald Welte (local)daef6062009-08-14 11:41:12 +0200982 /* SMC instance acknowledges the CP-DATA frame */
983 gsm411_tx_cp_ack(trans);
984
Harald Weltef3efc592009-07-27 20:11:35 +0200985 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200986#if 0
Harald Weltef3efc592009-07-27 20:11:35 +0200987 /* Send CP-ACK or CP-ERORR in response */
988 if (rc < 0) {
989 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
990 } else
991 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200992#endif
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000993 break;
994 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200995 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200996 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200997 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
998 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
999 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +02001000 /* Stop TC1* after CP-ACK has been received */
1001 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +02001002
Harald Weltef3efc592009-07-27 20:11:35 +02001003 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +02001004 /* FIXME: we have sont one CP-DATA, which was now
1005 * acknowledged. Check if we want to transfer more,
1006 * i.e. multi-part message */
1007 trans->sms.cp_state = GSM411_CPS_IDLE;
1008 trans_free(trans);
1009 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +00001010 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001011 case GSM411_MT_CP_ERROR:
Harald Welte (local)c89a5112009-08-14 10:42:43 +02001012 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
1013 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte41985612009-08-10 00:24:32 +02001014 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +02001015 trans->sms.cp_state = GSM411_CPS_IDLE;
1016 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +00001017 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001018 default:
Harald Welte (local)c89a5112009-08-14 10:42:43 +02001019 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +02001020 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +02001021 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +02001022 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001023 break;
1024 }
1025
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001026 return rc;
1027}
1028
Harald Welte8c2e36e2008-12-30 15:00:14 +00001029#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +00001030/* Test TPDU - ALL YOUR */
1031static u_int8_t tpdu_test[] = {
1032 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
1033 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
1034 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
1035 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +00001036};
Harald Welte8c2e36e2008-12-30 15:00:14 +00001037#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001038
Harald Weltecf6a3812009-08-09 19:07:41 +02001039/* Take a SMS in gsm_sms structure and send it through an already
1040 * existing lchan. We also assume that the caller ensured this lchan already
1041 * has a SAPI3 RLL connection! */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001042int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001043{
1044 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +02001045 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +02001046 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +02001047 u_int8_t msg_ref = 42;
Sylvain Munautc4052cf2009-12-24 13:27:36 +01001048 int transaction_id;
Harald Welte76042182009-08-08 16:03:15 +02001049 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001050
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001051 transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
Harald Welte49839212009-12-22 13:45:58 +01001052 if (transaction_id == -1) {
Harald Welted0cf7ba2009-12-24 15:08:18 +01001053 LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
Harald Welte49839212009-12-22 13:45:58 +01001054 return -EBUSY;
1055 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001056
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001057 msg->lchan = conn->lchan;
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001058
Harald Welte76042182009-08-08 16:03:15 +02001059 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +02001060
Harald Welte76042182009-08-08 16:03:15 +02001061 /* FIXME: allocate transaction with message reference */
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001062 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welte76042182009-08-08 16:03:15 +02001063 transaction_id, new_callref++);
1064 if (!trans) {
Harald Welted0cf7ba2009-12-24 15:08:18 +01001065 LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
Harald Welte76042182009-08-08 16:03:15 +02001066 /* FIXME: send some error message */
1067 return -ENOMEM;
1068 }
1069 trans->sms.cp_state = GSM411_CPS_IDLE;
1070 trans->sms.rp_state = GSM411_RPS_IDLE;
1071 trans->sms.is_mt = 1;
1072 trans->sms.sms = sms;
Harald Welte (local)daef6062009-08-14 11:41:12 +02001073 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +02001074
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001075 trans->conn = conn;
Holger Hans Peter Freythere95d4822010-03-23 07:00:22 +01001076 use_subscr_con(trans->conn);
Harald Welte76042182009-08-08 16:03:15 +02001077
1078 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +00001079 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +02001080 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +02001081 data[1] = 0x91; /* type of number: international, ISDN */
1082 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +00001083 data[3] = 0x77;
1084 data[4] = 0x58;
1085 data[5] = 0x10;
1086 data[6] = 0x06;
1087 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +02001088
1089 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001090 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +02001091 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001092
Harald Welte76042182009-08-08 16:03:15 +02001093 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1094 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +00001095
Harald Welte76042182009-08-08 16:03:15 +02001096#if 1
1097 /* generate the 03.40 TPDU */
1098 rc = gsm340_gen_tpdu(msg, sms);
1099 if (rc < 0) {
1100 msgb_free(msg);
1101 return rc;
1102 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001103
Harald Welte76042182009-08-08 16:03:15 +02001104 *rp_ud_len = rc;
1105#else
1106 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001107 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +02001108 *rp_ud_len = sizeof(tpdu_test);
1109#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001110
Harald Welte76042182009-08-08 16:03:15 +02001111 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001112
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001113 counter_inc(conn->lchan->ts->trx->bts->network->stats.sms.delivered);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001114
Harald Weltef3efc592009-07-27 20:11:35 +02001115 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1116 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001117}
Harald Weltef3efc592009-07-27 20:11:35 +02001118
Harald Weltecf6a3812009-08-09 19:07:41 +02001119/* RLL SAPI3 establish callback. Now we have a RLL connection and
1120 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +02001121static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1122 void *_sms, enum bsc_rllr_ind type)
1123{
1124 struct gsm_sms *sms = _sms;
1125
1126 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1127 lchan, link_id, sms, type);
1128
1129 switch (type) {
1130 case BSC_RLLR_IND_EST_CONF:
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001131#warning "BROKEN: The BSC will establish this transparently"
1132 gsm411_send_sms_lchan(&lchan->conn, sms);
Harald Weltecb8f4432009-08-09 14:59:02 +02001133 break;
1134 case BSC_RLLR_IND_REL_IND:
1135 case BSC_RLLR_IND_ERR_IND:
1136 case BSC_RLLR_IND_TIMEOUT:
Holger Hans Peter Freyther5179c8e2010-03-23 07:32:23 +01001137#warning "BROKEN: We will need to handle SAPI n Reject"
Harald Weltecb8f4432009-08-09 14:59:02 +02001138 sms_free(sms);
1139 break;
1140 }
1141}
1142
Harald Weltecf6a3812009-08-09 19:07:41 +02001143/* paging callback. Here we get called if paging a subscriber has
1144 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +02001145static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1146 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +02001147{
Harald Welte76042182009-08-08 16:03:15 +02001148 struct gsm_lchan *lchan = _lchan;
1149 struct gsm_sms *sms = _sms;
1150 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +02001151
Harald Welte76042182009-08-08 16:03:15 +02001152 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1153 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1154
1155 if (hooknum != GSM_HOOK_RR_PAGING)
1156 return -EINVAL;
1157
1158 switch (event) {
1159 case GSM_PAGING_SUCCEEDED:
1160 /* Paging aborted without lchan ?!? */
1161 if (!lchan) {
1162 sms_free(sms);
1163 rc = -EIO;
1164 break;
1165 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001166 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +02001167 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001168 break;
1169 case GSM_PAGING_EXPIRED:
1170 sms_free(sms);
1171 rc = -ETIMEDOUT;
1172 break;
1173 default:
1174 rc = -EINVAL;
1175 break;
1176 }
1177
1178 return rc;
1179}
1180
Harald Weltecf6a3812009-08-09 19:07:41 +02001181/* high-level function to send a SMS to a given subscriber. The function
1182 * will take care of paging the subscriber, establishing the RLL SAPI3
1183 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +02001184int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1185 struct gsm_sms *sms)
1186{
Harald Weltecf6a3812009-08-09 19:07:41 +02001187 struct gsm_lchan *lchan;
Harald Weltee903edf2009-08-15 03:16:17 +02001188 int rc;
Harald Weltecf6a3812009-08-09 19:07:41 +02001189
Harald Welte76042182009-08-08 16:03:15 +02001190 /* check if we already have an open lchan to the subscriber.
1191 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +02001192 lchan = lchan_for_subscr(subscr);
1193 if (lchan)
1194 return rll_establish(lchan, UM_SAPI_SMS,
1195 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001196
1197 /* if not, we have to start paging */
Harald Weltee903edf2009-08-15 03:16:17 +02001198 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1199 paging_cb_send_sms, sms);
Harald Welte (local)0abaf332009-08-15 11:25:45 +02001200 if (rc <= 0)
Harald Weltee903edf2009-08-15 03:16:17 +02001201 sms_free(sms);
Harald Welte76042182009-08-08 16:03:15 +02001202
1203 return 0;
1204}
Harald Welte3366a942009-07-28 00:44:49 +02001205
Harald Weltecf6a3812009-08-09 19:07:41 +02001206static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1207 void *handler_data, void *signal_data)
1208{
1209 struct gsm_subscriber *subscr;
1210 struct gsm_lchan *lchan;
1211 struct gsm_sms *sms;
1212
1213 switch (signal) {
1214 case S_SUBSCR_ATTACHED:
1215 /* A subscriber has attached. Check if there are
1216 * any pending SMS for him to be delivered */
1217 subscr = signal_data;
1218 lchan = lchan_for_subscr(subscr);
1219 if (!lchan)
1220 break;
1221 sms = db_sms_get_unsent_for_subscr(subscr);
1222 if (!sms)
1223 break;
1224 /* Establish a SAPI3 RLL connection for SMS */
1225 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1226 break;
1227 default:
1228 break;
1229 }
1230 return 0;
1231}
1232
Harald Welte (local)86b17172009-08-14 14:52:17 +02001233void _gsm411_sms_trans_free(struct gsm_trans *trans)
1234{
1235 bsc_del_timer(&trans->sms.cp_timer);
1236}
1237
Harald Welte7bfc2672009-07-28 00:41:45 +02001238static __attribute__((constructor)) void on_dso_load_sms(void)
1239{
Harald Weltecf6a3812009-08-09 19:07:41 +02001240 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +02001241}