blob: 57d808962555390af1ec2891dcd25eace9358493 [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>
Holger Hans Peter Freyther8b820fe2010-05-23 21:05:18 +080051#include <openbsc/bsc_api.h>
Harald Welte59b04682009-06-10 05:40:52 +080052
53#define GSM411_ALLOC_SIZE 1024
54#define GSM411_ALLOC_HEADROOM 128
55
Harald Welte09421d32009-08-09 14:59:02 +020056#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
57
Harald Welte (local)8751ee92009-08-15 02:30:58 +020058void *tall_gsms_ctx;
Harald Welteb78996d2009-07-27 20:11:35 +020059static u_int32_t new_callref = 0x40000001;
60
Harald Welte (local)cb4715c2009-08-14 10:42:43 +020061static const struct value_string cp_cause_strs[] = {
62 { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
63 { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
64 { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
65 { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
66 { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
67 { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +020068 { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +020069 "Message incompatible with protocol state" },
70 { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
71 { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
72 { 0, 0 }
73};
74
75static const struct value_string rp_cause_strs[] = {
76 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
77 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
78 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
79 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
80 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
81 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
82 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
83 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
84 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
85 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
86 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
87 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
88 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
89 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
90 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
91 /* valid only for MT */
92 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
93 /* valid for both directions */
94 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
95 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
96 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
97 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
98 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
99 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
100 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
101 { 0, NULL }
102};
103
Harald Welte68b7df22009-08-08 16:03:15 +0200104struct gsm_sms *sms_alloc(void)
105{
106 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
107}
108
109void sms_free(struct gsm_sms *sms)
110{
111 /* drop references to subscriber structure */
112 if (sms->sender)
113 subscr_put(sms->sender);
114 if (sms->receiver)
115 subscr_put(sms->receiver);
116
117 talloc_free(sms);
118}
119
Harald Welte59b04682009-06-10 05:40:52 +0800120struct msgb *gsm411_msgb_alloc(void)
121{
Harald Welte9cfc9352009-06-26 19:39:35 +0200122 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
123 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +0800124}
125
Holger Hans Peter Freyther7cdff242010-03-23 07:40:46 +0100126static int gsm411_sendmsg(struct gsm_subscriber_connection *conn, struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800127{
Harald Welte68b7df22009-08-08 16:03:15 +0200128 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
Holger Hans Peter Freyther7cdff242010-03-23 07:40:46 +0100129 msg->l3h = msg->data;
130 return gsm0808_submit_dtap(conn, msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +0800131}
132
Harald Welte5fa17a22009-08-10 00:24:32 +0200133/* SMC TC1* is expired */
134static void cp_timer_expired(void *data)
135{
136 struct gsm_trans *trans = data;
137
138 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
139 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
140 trans_free(trans);
141}
142
Harald Welte7e2f57d2009-07-04 17:39:00 +0200143/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200144static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
145 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200146{
147 struct gsm48_hdr *gh;
148
149 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
150 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +0200151 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200152 gh->msg_type = msg_type;
153
Harald Welteb78996d2009-07-27 20:11:35 +0200154 /* mobile originating */
155 switch (gh->msg_type) {
156 case GSM411_MT_CP_DATA:
157 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Welte09421d32009-08-09 14:59:02 +0200158 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200159 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte5fa17a22009-08-10 00:24:32 +0200160 trans->sms.cp_timer.data = trans;
161 trans->sms.cp_timer.cb = cp_timer_expired;
162 /* 5.3.2.1: Set Timer TC1A */
163 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200164 DEBUGP(DSMS, "TX: CP-DATA ");
165 break;
166 case GSM411_MT_CP_ACK:
167 DEBUGP(DSMS, "TX: CP-ACK ");
168 break;
169 case GSM411_MT_CP_ERROR:
Sylvain Munaut163a24a2009-12-18 18:28:07 +0100170 DEBUGP(DSMS, "TX: CP-ERROR ");
Harald Welteb78996d2009-07-27 20:11:35 +0200171 break;
172 }
173
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200174 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
175
Holger Hans Peter Freyther7cdff242010-03-23 07:40:46 +0100176 return gsm411_sendmsg(trans->conn, msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200177}
178
179/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200180static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
181 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200182{
183 struct gsm411_rp_hdr *rp;
Harald Weltef2e680b2009-08-10 00:22:19 +0200184 u_int8_t len = msg->len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200185
186 /* GSM 04.11 RP-DATA header */
187 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Weltef2e680b2009-08-10 00:22:19 +0200188 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200189 rp->msg_type = rp_msg_type;
190 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
191
Harald Welteb78996d2009-07-27 20:11:35 +0200192 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200193}
194
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100195/* Turn int into semi-octet representation: 98 => 0x89 */
196static u_int8_t bcdify(u_int8_t value)
197{
198 u_int8_t ret;
Steffen Neubauer94436952009-11-11 23:02:07 +0900199
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100200 ret = value / 10;
201 ret |= (value % 10) << 4;
202
203 return ret;
204}
205
206/* Turn semi-octet representation into int: 0x89 => 98 */
207static u_int8_t unbcdify(u_int8_t value)
208{
209 u_int8_t ret;
210
211 if ((value & 0x0F) > 9 || (value >> 4) > 9)
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200212 LOGP(DSMS, LOGL_ERROR,
Harald Welteced9a912009-12-24 15:08:18 +0100213 "unbcdify got too big nibble: 0x%02X\n", value);
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100214
215 ret = (value&0x0F)*10;
Steffen Neubauere5e0eb72009-11-26 23:38:41 +0100216 ret += value>>4;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100217
218 return ret;
219}
220
221/* Generate 03.40 TP-SCTS */
222static void gsm340_gen_scts(u_int8_t *scts, time_t time)
223{
224 struct tm *tm = localtime(&time);
225
226 *scts++ = bcdify(tm->tm_year % 100);
227 *scts++ = bcdify(tm->tm_mon + 1);
228 *scts++ = bcdify(tm->tm_mday);
229 *scts++ = bcdify(tm->tm_hour);
230 *scts++ = bcdify(tm->tm_min);
231 *scts++ = bcdify(tm->tm_sec);
232 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
233}
234
235/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
236static time_t gsm340_scts(u_int8_t *scts)
237{
238 struct tm tm;
239
240 u_int8_t yr = unbcdify(*scts++);
241
242 if (yr <= 80)
243 tm.tm_year = 100 + yr;
244 else
245 tm.tm_year = yr;
246 tm.tm_mon = unbcdify(*scts++) - 1;
247 tm.tm_mday = unbcdify(*scts++);
248 tm.tm_hour = unbcdify(*scts++);
249 tm.tm_min = unbcdify(*scts++);
250 tm.tm_sec = unbcdify(*scts++);
251 /* according to gsm 03.40 time zone is
252 "expressed in quarters of an hour" */
253 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
254
255 return mktime(&tm);
256}
257
258/* Return the default validity period in minutes */
259static unsigned long gsm340_vp_default(void)
260{
261 unsigned long minutes;
262 /* Default validity: two days */
263 minutes = 24 * 60 * 2;
264 return minutes;
265}
266
267/* Decode validity period format 'relative' */
268static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
269{
270 /* Chapter 9.2.3.12.1 */
271 u_int8_t vp;
272 unsigned long minutes;
273
274 vp = *(sms_vp);
275 if (vp <= 143)
276 minutes = vp + 1 * 5;
277 else if (vp <= 167)
278 minutes = 12*60 + (vp-143) * 30;
279 else if (vp <= 196)
280 minutes = vp-166 * 60 * 24;
281 else
282 minutes = vp-192 * 60 * 24 * 7;
283 return minutes;
284}
285
286/* Decode validity period format 'absolute' */
287static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
288{
289 /* Chapter 9.2.3.12.2 */
290 time_t expires, now;
291 unsigned long minutes;
292
293 expires = gsm340_scts(sms_vp);
294 now = mktime(gmtime(NULL));
295 if (expires <= now)
296 minutes = 0;
297 else
298 minutes = (expires-now)/60;
299 return minutes;
300}
301
302/* Decode validity period format 'relative in integer representation' */
303static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800304{
305 u_int8_t vp;
306 unsigned long minutes;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100307 vp = *(sms_vp);
308 if (vp == 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100309 LOGP(DSMS, LOGL_ERROR,
310 "reserved relative_integer validity period\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100311 return gsm340_vp_default();
312 }
313 minutes = vp/60;
314 return minutes;
315}
316
317/* Decode validity period format 'relative in semi-octet representation' */
318static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
319{
320 unsigned long minutes;
321 minutes = unbcdify(*sms_vp++)*60; /* hours */
322 minutes += unbcdify(*sms_vp++); /* minutes */
323 minutes += unbcdify(*sms_vp++)/60; /* seconds */
324 return minutes;
325}
326
327/* decode validity period. return minutes */
328static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
329{
330 u_int8_t fi; /* functionality indicator */
Harald Welte59b04682009-06-10 05:40:52 +0800331
Harald Welte68b7df22009-08-08 16:03:15 +0200332 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800333 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100334 return gsm340_vp_relative(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800335 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100336 return gsm340_vp_absolute(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800337 case GSM340_TP_VPF_ENHANCED:
338 /* Chapter 9.2.3.12.3 */
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100339 fi = *sms_vp++;
340 /* ignore additional fi */
341 if (fi & (1<<7)) sms_vp++;
342 /* read validity period format */
343 switch (fi & 0b111) {
344 case 0b000:
345 return gsm340_vp_default(); /* no vpf specified */
346 case 0b001:
347 return gsm340_vp_relative(sms_vp);
348 case 0b010:
349 return gsm340_vp_relative_integer(sms_vp);
350 case 0b011:
351 return gsm340_vp_relative_semioctet(sms_vp);
352 default:
353 /* The GSM spec says that the SC should reject any
354 unsupported and/or undefined values. FIXME */
Harald Welteced9a912009-12-24 15:08:18 +0100355 LOGP(DSMS, LOGL_ERROR,
356 "Reserved enhanced validity period format\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100357 return gsm340_vp_default();
358 }
Daniel Willmann426bb162009-08-13 03:40:49 +0200359 case GSM340_TP_VPF_NONE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100360 default:
361 return gsm340_vp_default();
Harald Welte59b04682009-06-10 05:40:52 +0800362 }
Harald Welte59b04682009-06-10 05:40:52 +0800363}
364
365/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
366enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
367{
368 u_int8_t cgbits = dcs >> 4;
369 enum sms_alphabet alpha = DCS_NONE;
370
371 if ((cgbits & 0xc) == 0) {
372 if (cgbits & 2)
Harald Welteced9a912009-12-24 15:08:18 +0100373 LOGP(DSMS, LOGL_NOTICE,
374 "Compressed SMS not supported yet\n");
Harald Welte59b04682009-06-10 05:40:52 +0800375
Daniel Willmannf2861022009-08-15 03:01:17 +0200376 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800377 case 0:
378 alpha = DCS_7BIT_DEFAULT;
379 break;
380 case 1:
381 alpha = DCS_8BIT_DATA;
382 break;
383 case 2:
384 alpha = DCS_UCS2;
385 break;
386 }
387 } else if (cgbits == 0xc || cgbits == 0xd)
388 alpha = DCS_7BIT_DEFAULT;
389 else if (cgbits == 0xe)
390 alpha = DCS_UCS2;
391 else if (cgbits == 0xf) {
392 if (dcs & 4)
393 alpha = DCS_8BIT_DATA;
394 else
395 alpha = DCS_7BIT_DEFAULT;
396 }
397
398 return alpha;
399}
400
Harald Welte68b7df22009-08-08 16:03:15 +0200401static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800402{
403 if (db_sms_store(gsms) != 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100404 LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200405 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800406 }
Harald Welte68b7df22009-08-08 16:03:15 +0200407 /* dispatch a signal to tell higher level about it */
408 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200409 /* try delivering the SMS right now */
410 //gsm411_send_sms_subscr(gsms->receiver, gsms);
411
Harald Welte59b04682009-06-10 05:40:52 +0800412 return 0;
413}
414
Harald Welte68b7df22009-08-08 16:03:15 +0200415/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
416static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
417 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200418{
Harald Welte68b7df22009-08-08 16:03:15 +0200419 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200420
Harald Welte68b7df22009-08-08 16:03:15 +0200421 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
422
Harald Weltefdc93d92010-03-07 23:40:35 +0100423 len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, subscr->extension);
Harald Welte68b7df22009-08-08 16:03:15 +0200424
425 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
426 oa[0] = strlen(subscr->extension) & 0xff;
427
428 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200429}
430
Harald Welte68b7df22009-08-08 16:03:15 +0200431/* generate a msgb containing a TPDU derived from struct gsm_sms,
432 * returns total size of TPDU */
433static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200434{
Harald Welteb78996d2009-07-27 20:11:35 +0200435 u_int8_t *smsp;
436 u_int8_t oa[12]; /* max len per 03.40 */
437 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200438 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200439 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200440
441 /* generate first octet with masked bits */
442 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200443 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200444 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200445 /* TP-MMS (more messages to send) */
446 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200447 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200448 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200449 if (sms->status_rep_req)
450 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200451 /* TP-UDHI (indicating TP-UD contains a header) */
452 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200453 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200454#if 0
455 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200456 if (sms->
457 *smsp |= 0x80;
458#endif
459
460 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200461 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200462 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200463 memcpy(smsp, oa, oa_len);
464
465 /* generate TP-PID */
466 smsp = msgb_put(msg, 1);
467 *smsp = sms->protocol_id;
468
469 /* generate TP-DCS */
470 smsp = msgb_put(msg, 1);
471 *smsp = sms->data_coding_scheme;
472
473 /* generate TP-SCTS */
474 smsp = msgb_put(msg, 7);
475 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200476
Harald Welteb78996d2009-07-27 20:11:35 +0200477 /* generate TP-UDL */
478 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200479 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200480
481 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200482 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
483 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200484 octet_len = sms->user_data_len*7/8;
485 if (sms->user_data_len*7%8 != 0)
486 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200487 /* Warning, user_data_len indicates the amount of septets
488 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200489 smsp = msgb_put(msg, octet_len);
490 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200491 break;
492 case DCS_UCS2:
493 case DCS_8BIT_DATA:
494 smsp = msgb_put(msg, sms->user_data_len);
495 memcpy(smsp, sms->user_data, sms->user_data_len);
496 break;
497 default:
Harald Welteced9a912009-12-24 15:08:18 +0100498 LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
499 sms->data_coding_scheme);
Daniel Willmann8d786602009-08-15 03:01:46 +0200500 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200501 }
Harald Welteb78996d2009-07-27 20:11:35 +0200502
Harald Welte68b7df22009-08-08 16:03:15 +0200503 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200504}
505
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200506/* process an incoming TPDU (called from RP-DATA)
507 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100508static int gsm340_rx_tpdu(struct gsm_subscriber_connection *conn, struct msgb *msg)
Harald Welte59b04682009-06-10 05:40:52 +0800509{
510 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800511 struct gsm_sms *gsms;
Harald Welte68b7df22009-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 Welte59b04682009-06-10 05:40:52 +0800514 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;
517
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100518 counter_inc(conn->bts->network->stats.sms.submitted);
Harald Welte3edc5a92009-12-22 00:41:05 +0100519
Harald Welte68b7df22009-08-08 16:03:15 +0200520 gsms = sms_alloc();
521 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200522 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800523
524 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800531
532 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200533 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800534
535 /* length in bytes of the destination address */
536 da_len_bytes = 2 + *smsp/2 + *smsp%2;
537 if (da_len_bytes > 12) {
Harald Welteced9a912009-12-24 15:08:18 +0100538 LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200539 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800540 goto out;
541 }
Harald Welte3794e152009-06-12 02:42:11 +0800542 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800543 memcpy(address_lv, smsp, da_len_bytes);
544 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800545 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800546 /* convert to real number */
Harald Weltefdc93d92010-03-07 23:40:35 +0100547 gsm48_decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800548 smsp += da_len_bytes;
549
Harald Welte68b7df22009-08-08 16:03:15 +0200550 gsms->protocol_id = *smsp++;
551 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800552
Harald Welte68b7df22009-08-08 16:03:15 +0200553 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800554
Harald Welte68b7df22009-08-08 16:03:15 +0200555 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800556 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200557 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800558 break;
559 case GSM340_TP_VPF_ABSOLUTE:
560 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200561 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100562 /* the additional functionality indicator... */
Steffen Neubauerdd488d12009-12-05 12:44:41 +0100563 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
564 smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800565 smsp += 7;
566 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200567 case GSM340_TP_VPF_NONE:
568 sms_vp = 0;
569 break;
Harald Welte59b04682009-06-10 05:40:52 +0800570 default:
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200571 LOGP(DSMS, LOGL_NOTICE,
Harald Welteced9a912009-12-24 15:08:18 +0100572 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte68b7df22009-08-08 16:03:15 +0200573 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800574 }
Harald Welte68b7df22009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800578
Harald Welte68b7df22009-08-08 16:03:15 +0200579 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800580 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200581 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800582 break;
583 case DCS_8BIT_DATA:
584 case DCS_UCS2:
585 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800586 break;
587 }
588 }
589
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100590 gsms->sender = subscr_get(msg->lchan->conn.subscr);
Harald Welteced9a912009-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,
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200598 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
Harald Welte68b7df22009-08-08 16:03:15 +0200599 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800600
Harald Welte68b7df22009-08-08 16:03:15 +0200601 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200602
Harald Welte68b7df22009-08-08 16:03:15 +0200603 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200604
Harald Welte59b04682009-06-10 05:40:52 +0800605 /* determine gsms->receiver based on dialled number */
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100606 gsms->receiver = subscr_get_by_extension(conn->bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800607 if (!gsms->receiver) {
608 rc = 1; /* cause 1: unknown subscriber */
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100609 counter_inc(conn->bts->network->stats.sms.no_receiver);
Harald Welte59b04682009-06-10 05:40:52 +0800610 goto out;
611 }
612
Harald Welte68b7df22009-08-08 16:03:15 +0200613 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800614 case GSM340_SMS_SUBMIT_MS2SC:
615 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200616 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800617 break;
618 case GSM340_SMS_COMMAND_MS2SC:
619 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welteced9a912009-12-24 15:08:18 +0100620 LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200621 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800622 break;
623 default:
Harald Welteced9a912009-12-24 15:08:18 +0100624 LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200625 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800626 break;
627 }
628
Harald Welte156c5e62009-07-05 14:02:46 +0200629 if (!rc && !gsms->receiver)
630 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
631
Harald Welte59b04682009-06-10 05:40:52 +0800632out:
Harald Welte68b7df22009-08-08 16:03:15 +0200633 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800634
635 return rc;
636}
637
Harald Welteb78996d2009-07-27 20:11:35 +0200638static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800639{
640 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800641
Harald Welte59b04682009-06-10 05:40:52 +0800642 DEBUGP(DSMS, "TX: SMS RP ACK\n");
643
Harald Welteb78996d2009-07-27 20:11:35 +0200644 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800645}
646
Harald Welteb78996d2009-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)
Harald Welte59b04682009-06-10 05:40:52 +0800649{
650 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800651
Harald Welte59b04682009-06-10 05:40:52 +0800652 msgb_tv_put(msg, 1, cause);
653
Harald Welteced9a912009-12-24 15:08:18 +0100654 LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200655 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800656
Harald Welteb78996d2009-07-27 20:11:35 +0200657 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800658}
659
660/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800663 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)
666{
Harald Welte59b04682009-06-10 05:40:52 +0800667 int rc = 0;
668
669 if (src_len && src)
Harald Welteced9a912009-12-24 15:08:18 +0100670 LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte59b04682009-06-10 05:40:52 +0800671
672 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Harald Welteced9a912009-12-24 15:08:18 +0100673 LOGP(DSMS, LOGL_ERROR,
674 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200675 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200676 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800677 return -EIO;
678 }
Harald Welte2c5706d2010-04-30 14:27:05 +0200679 msg->l4h = tpdu;
Harald Welte59b04682009-06-10 05:40:52 +0800680
681 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800682
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100683 rc = gsm340_rx_tpdu(trans->conn, msg);
Harald Welte59b04682009-06-10 05:40:52 +0800684 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200685 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800686 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200687 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800688 else
689 return rc;
690}
691
692/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800695{
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 Welte156c5e62009-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 Welteb78996d2009-07-27 20:11:35 +0200714 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800715 rpud_len, rp_ud);
716}
717
Harald Welte09421d32009-08-09 14:59:02 +0200718/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200721{
Harald Welte68b7df22009-08-08 16:03:15 +0200722 struct gsm_sms *sms = trans->sms.sms;
723
Harald Welte156c5e62009-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 Welte09421d32009-08-09 14:59:02 +0200728 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100729 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200730 return gsm411_send_rp_error(trans, rph->msg_ref,
731 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
732 }
Harald Weltedd62b162009-07-09 23:52:59 +0200733
Harald Welte68b7df22009-08-08 16:03:15 +0200734 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100735 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200736 return gsm411_send_rp_error(trans, rph->msg_ref,
737 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-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 Weltefc01b242009-08-09 19:07:41 +0200748 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-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 Weltefc01b242009-08-09 19:07:41 +0200752 if (sms)
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100753 gsm411_send_sms_lchan(trans->conn, sms);
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100754
755 /* free the transaction here */
756 trans_free(trans);
757
758 /* release channel if done */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100759#warning "BROKEN. The SAPI will be released automatically by the BSC"
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100760 if (!sms)
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200761 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200762
763 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200764}
765
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200768{
Holger Hans Peter Freythere9781842010-03-23 07:52:17 +0100769 struct gsm_network *net = trans->conn->bts->network;
Harald Welte68b7df22009-08-08 16:03:15 +0200770 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200771 u_int8_t cause_len = rph->data[0];
772 u_int8_t cause = rph->data[1];
773
Harald Welte156c5e62009-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 Welteced9a912009-12-24 15:08:18 +0100778 LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
Holger Hans Peter Freytherde896e52010-03-23 07:56:22 +0100779 subscr_name(trans->conn->subscr), cause_len, cause,
Harald Welteced9a912009-12-24 15:08:18 +0100780 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200781
Harald Welte09421d32009-08-09 14:59:02 +0200782 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100783 LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200784#if 0
Harald Welte09421d32009-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)ced09ed2009-08-17 09:39:55 +0200787#endif
Harald Welte09421d32009-08-09 14:59:02 +0200788 }
Harald Weltedd62b162009-07-09 23:52:59 +0200789
Harald Welte68b7df22009-08-08 16:03:15 +0200790 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100791 LOGP(DSMS, LOGL_ERROR,
792 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200793 return -EINVAL;
794#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200795 return gsm411_send_rp_error(trans, rph->msg_ref,
796 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200797#endif
Harald Welte09421d32009-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 Weltebdbb7442009-12-22 19:07:32 +0100805 counter_inc(net->stats.sms.rp_err_mem);
Harald Welte3edc5a92009-12-22 00:41:05 +0100806 } else
Harald Weltebdbb7442009-12-22 19:07:32 +0100807 counter_inc(net->stats.sms.rp_err_other);
Harald Welte68b7df22009-08-08 16:03:15 +0200808
809 sms_free(sms);
810 trans->sms.sms = NULL;
811
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200812 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200813
Harald Welteb78996d2009-07-27 20:11:35 +0200814 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200815}
816
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200819{
Harald Weltefc01b242009-08-09 19:07:41 +0200820 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200821 int rc;
822
Harald Weltefc01b242009-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 Welte156c5e62009-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 Welte68b7df22009-08-08 16:03:15 +0200829 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200830
Harald Weltefc01b242009-08-09 19:07:41 +0200831 /* check for more messages for this subscriber */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100832 assert(msg->lchan->conn.subscr == trans->subscr);
833 sms = db_sms_get_unsent_for_subscr(trans->subscr);
Harald Weltefc01b242009-08-09 19:07:41 +0200834 if (sms)
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100835 gsm411_send_sms_lchan(trans->conn, sms);
Harald Weltefc01b242009-08-09 19:07:41 +0200836 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200837 rsl_release_request(msg->lchan, trans->sms.link_id);
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +0100838#warning "BROKEN: The SAPI=3 will be released automatically by the BSC"
Harald Welteb78996d2009-07-27 20:11:35 +0200839
840 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200841}
842
Harald Welteb78996d2009-07-27 20:11:35 +0200843static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
844 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800845{
846 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
847 u_int8_t msg_type = rp_data->msg_type & 0x07;
848 int rc = 0;
849
850 switch (msg_type) {
851 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-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 Welte59b04682009-06-10 05:40:52 +0800856 break;
857 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-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 Welte156c5e62009-07-05 14:02:46 +0200860 break;
Harald Welte59b04682009-06-10 05:40:52 +0800861 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-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);
Harald Welte59b04682009-06-10 05:40:52 +0800869 break;
870 default:
Harald Welteced9a912009-12-24 15:08:18 +0100871 LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200872 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
873 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800874 break;
875 }
876
877 return rc;
878}
879
Harald Welteb78996d2009-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 Weltefc01b242009-08-09 19:07:41 +0200884 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200885
Harald Weltefc01b242009-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)9d0bd792009-08-14 14:52:17 +0200891 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200892 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200893
894 return rc;
Harald Welteb78996d2009-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 Welteced9a912009-12-24 15:08:18 +0100902 LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200903 get_value_string(cp_cause_strs, cause));
904
Harald Welte68b7df22009-08-08 16:03:15 +0200905 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-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)64994ce2009-08-14 11:41:12 +0200912int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800913{
914 struct gsm48_hdr *gh = msgb_l3(msg);
915 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-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;
Harald Welte59b04682009-06-10 05:40:52 +0800919 int rc = 0;
920
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100921 if (!lchan->conn.subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200922 return -EIO;
923 /* FIXME: send some error message */
924
Sylvain Munaute02fb9a2009-12-18 18:28:08 +0100925 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100926 trans = trans_find_by_id(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200927 transaction_id);
928 if (!trans) {
Sylvain Munaut40c23322009-12-18 18:28:09 +0100929 DEBUGPC(DSMS, "(new) ");
Holger Hans Peter Freyther065b8112010-03-23 06:41:45 +0100930 trans = trans_alloc(lchan->conn.subscr, GSM48_PDISC_SMS,
Harald Welteb78996d2009-07-27 20:11:35 +0200931 transaction_id, new_callref++);
932 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200933 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-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)64994ce2009-08-14 11:41:12 +0200940 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200941
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +0100942 trans->conn = &lchan->conn;
943 use_subscr_con(trans->conn);
Harald Welteb78996d2009-07-27 20:11:35 +0200944 }
945
Harald Welte59b04682009-06-10 05:40:52 +0800946 switch(msg_type) {
947 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200948 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Sylvain Munauta5914da2009-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 Freyther065b8112010-03-23 06:41:45 +0100962 ptrans = trans_find_by_id(lchan->conn.subscr,
Sylvain Munauta5914da2009-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 Welte09421d32009-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 Welteb78996d2009-07-27 20:11:35 +0200981
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200982 /* SMC instance acknowledges the CP-DATA frame */
983 gsm411_tx_cp_ack(trans);
984
Harald Welteb78996d2009-07-27 20:11:35 +0200985 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200986#if 0
Harald Welteb78996d2009-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)64994ce2009-08-14 11:41:12 +0200992#endif
Harald Welte59b04682009-06-10 05:40:52 +0800993 break;
994 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200995 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200996 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-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 Welte5fa17a22009-08-10 00:24:32 +02001000 /* Stop TC1* after CP-ACK has been received */
1001 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +02001002
Harald Welteb78996d2009-07-27 20:11:35 +02001003 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-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 }
Harald Welte59b04682009-06-10 05:40:52 +08001010 break;
1011 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-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 Welte5fa17a22009-08-10 00:24:32 +02001014 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +02001015 trans->sms.cp_state = GSM411_CPS_IDLE;
1016 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001017 break;
1018 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001019 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +02001020 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +02001021 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +02001022 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001023 break;
1024 }
1025
Harald Welte59b04682009-06-10 05:40:52 +08001026 return rc;
1027}
1028
Harald Welte59b04682009-06-10 05:40:52 +08001029#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001030/* 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
1036};
1037#endif
1038
Harald Weltefc01b242009-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 Freyther40772ef2010-03-23 07:32:23 +01001042int gsm411_send_sms_lchan(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +08001043{
1044 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +02001045 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +02001046 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001047 u_int8_t msg_ref = 42;
Sylvain Munaute65af1b2009-12-24 13:27:36 +01001048 int transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +02001049 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001050
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001051 transaction_id = trans_assign_trans_id(conn->subscr, GSM48_PDISC_SMS, 0);
Harald Welte6e55abf2009-12-22 13:45:58 +01001052 if (transaction_id == -1) {
Harald Welteced9a912009-12-24 15:08:18 +01001053 LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
Harald Welte6e55abf2009-12-22 13:45:58 +01001054 return -EBUSY;
1055 }
Harald Weltefc01b242009-08-09 19:07:41 +02001056
Harald Welte68b7df22009-08-08 16:03:15 +02001057 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +02001058
Harald Welte68b7df22009-08-08 16:03:15 +02001059 /* FIXME: allocate transaction with message reference */
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001060 trans = trans_alloc(conn->subscr, GSM48_PDISC_SMS,
Harald Welte68b7df22009-08-08 16:03:15 +02001061 transaction_id, new_callref++);
1062 if (!trans) {
Harald Welteced9a912009-12-24 15:08:18 +01001063 LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
Harald Welte68b7df22009-08-08 16:03:15 +02001064 /* FIXME: send some error message */
1065 return -ENOMEM;
1066 }
1067 trans->sms.cp_state = GSM411_CPS_IDLE;
1068 trans->sms.rp_state = GSM411_RPS_IDLE;
1069 trans->sms.is_mt = 1;
1070 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001071 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +02001072
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001073 trans->conn = conn;
Holger Hans Peter Freyther4009da42010-03-23 07:00:22 +01001074 use_subscr_con(trans->conn);
Harald Welte68b7df22009-08-08 16:03:15 +02001075
1076 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +08001077 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001078 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +02001079 data[1] = 0x91; /* type of number: international, ISDN */
1080 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +08001081 data[3] = 0x77;
1082 data[4] = 0x58;
1083 data[5] = 0x10;
1084 data[6] = 0x06;
1085 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001086
1087 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +08001088 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001089 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +08001090
Harald Welte68b7df22009-08-08 16:03:15 +02001091 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1092 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +08001093
Harald Welte68b7df22009-08-08 16:03:15 +02001094#if 1
1095 /* generate the 03.40 TPDU */
1096 rc = gsm340_gen_tpdu(msg, sms);
1097 if (rc < 0) {
1098 msgb_free(msg);
1099 return rc;
1100 }
Harald Welte59b04682009-06-10 05:40:52 +08001101
Harald Welte68b7df22009-08-08 16:03:15 +02001102 *rp_ud_len = rc;
1103#else
1104 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +08001105 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +02001106 *rp_ud_len = sizeof(tpdu_test);
1107#endif
Harald Welte59b04682009-06-10 05:40:52 +08001108
Harald Welte68b7df22009-08-08 16:03:15 +02001109 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001110
Holger Hans Peter Freytherde896e52010-03-23 07:56:22 +01001111 counter_inc(conn->bts->network->stats.sms.delivered);
Harald Welte3edc5a92009-12-22 00:41:05 +01001112
Harald Welteb78996d2009-07-27 20:11:35 +02001113 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1114 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001115}
Harald Welteb78996d2009-07-27 20:11:35 +02001116
Harald Weltefc01b242009-08-09 19:07:41 +02001117/* RLL SAPI3 establish callback. Now we have a RLL connection and
1118 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001119static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1120 void *_sms, enum bsc_rllr_ind type)
1121{
1122 struct gsm_sms *sms = _sms;
1123
1124 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1125 lchan, link_id, sms, type);
1126
1127 switch (type) {
1128 case BSC_RLLR_IND_EST_CONF:
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001129#warning "BROKEN: The BSC will establish this transparently"
1130 gsm411_send_sms_lchan(&lchan->conn, sms);
Harald Welte09421d32009-08-09 14:59:02 +02001131 break;
1132 case BSC_RLLR_IND_REL_IND:
1133 case BSC_RLLR_IND_ERR_IND:
1134 case BSC_RLLR_IND_TIMEOUT:
Holger Hans Peter Freyther40772ef2010-03-23 07:32:23 +01001135#warning "BROKEN: We will need to handle SAPI n Reject"
Harald Welte09421d32009-08-09 14:59:02 +02001136 sms_free(sms);
1137 break;
1138 }
1139}
1140
Harald Weltefc01b242009-08-09 19:07:41 +02001141/* paging callback. Here we get called if paging a subscriber has
1142 * succeeded or failed. */
Harald Welte68b7df22009-08-08 16:03:15 +02001143static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1144 struct msgb *msg, void *_lchan, void *_sms)
Harald Welteb78996d2009-07-27 20:11:35 +02001145{
Harald Welte68b7df22009-08-08 16:03:15 +02001146 struct gsm_lchan *lchan = _lchan;
1147 struct gsm_sms *sms = _sms;
1148 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001149
Harald Welte68b7df22009-08-08 16:03:15 +02001150 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1151 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1152
1153 if (hooknum != GSM_HOOK_RR_PAGING)
1154 return -EINVAL;
1155
1156 switch (event) {
1157 case GSM_PAGING_SUCCEEDED:
1158 /* Paging aborted without lchan ?!? */
1159 if (!lchan) {
1160 sms_free(sms);
1161 rc = -EIO;
1162 break;
1163 }
Harald Weltefc01b242009-08-09 19:07:41 +02001164 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001165 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001166 break;
1167 case GSM_PAGING_EXPIRED:
1168 sms_free(sms);
1169 rc = -ETIMEDOUT;
1170 break;
1171 default:
1172 rc = -EINVAL;
1173 break;
1174 }
1175
1176 return rc;
1177}
1178
Harald Weltefc01b242009-08-09 19:07:41 +02001179/* high-level function to send a SMS to a given subscriber. The function
1180 * will take care of paging the subscriber, establishing the RLL SAPI3
1181 * connection, etc. */
Harald Welte68b7df22009-08-08 16:03:15 +02001182int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1183 struct gsm_sms *sms)
1184{
Harald Weltefc01b242009-08-09 19:07:41 +02001185 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001186 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001187
Harald Welte68b7df22009-08-08 16:03:15 +02001188 /* check if we already have an open lchan to the subscriber.
1189 * if yes, send the SMS this way */
Harald Weltefc01b242009-08-09 19:07:41 +02001190 lchan = lchan_for_subscr(subscr);
1191 if (lchan)
1192 return rll_establish(lchan, UM_SAPI_SMS,
1193 rll_ind_cb, sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001194
1195 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001196 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1197 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001198 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001199 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001200
1201 return 0;
1202}
Harald Welte5b359d82009-07-28 00:44:49 +02001203
Harald Weltefc01b242009-08-09 19:07:41 +02001204static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1205 void *handler_data, void *signal_data)
1206{
1207 struct gsm_subscriber *subscr;
1208 struct gsm_lchan *lchan;
1209 struct gsm_sms *sms;
1210
1211 switch (signal) {
1212 case S_SUBSCR_ATTACHED:
1213 /* A subscriber has attached. Check if there are
1214 * any pending SMS for him to be delivered */
1215 subscr = signal_data;
1216 lchan = lchan_for_subscr(subscr);
1217 if (!lchan)
1218 break;
1219 sms = db_sms_get_unsent_for_subscr(subscr);
1220 if (!sms)
1221 break;
1222 /* Establish a SAPI3 RLL connection for SMS */
1223 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1224 break;
1225 default:
1226 break;
1227 }
1228 return 0;
1229}
1230
Harald Welte (local)9d0bd792009-08-14 14:52:17 +02001231void _gsm411_sms_trans_free(struct gsm_trans *trans)
1232{
1233 bsc_del_timer(&trans->sms.cp_timer);
1234}
1235
Harald Welte932e20d2009-07-28 00:41:45 +02001236static __attribute__((constructor)) void on_dso_load_sms(void)
1237{
Harald Weltefc01b242009-08-09 19:07:41 +02001238 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001239}