blob: 881c3755a2901876b11afdac9777e5250617849c [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
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
Harald Welteb78996d2009-07-27 20:11:35 +020031#include <time.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <netinet/in.h>
33
Harald Weltef4625b12010-02-20 16:24:02 +010034#include <osmocore/msgb.h>
35#include <osmocore/tlv.h>
Harald Welte59b04682009-06-10 05:40:52 +080036#include <openbsc/debug.h>
37#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
39#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
Harald Weltef4625b12010-02-20 16:24:02 +010041#include <osmocore/gsm_utils.h>
Harald Welte59b04682009-06-10 05:40:52 +080042#include <openbsc/abis_rsl.h>
43#include <openbsc/signal.h>
44#include <openbsc/db.h>
Harald Weltef4625b12010-02-20 16:24:02 +010045#include <osmocore/talloc.h>
Harald Welteb78996d2009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte68b7df22009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Welte09421d32009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther735cd9e2009-08-10 07:54:02 +020049#include <openbsc/chan_alloc.h>
Harald Welte59b04682009-06-10 05:40:52 +080050
51#define GSM411_ALLOC_SIZE 1024
52#define GSM411_ALLOC_HEADROOM 128
53
Harald Welte09421d32009-08-09 14:59:02 +020054#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
55
Harald Welte (local)8751ee92009-08-15 02:30:58 +020056void *tall_gsms_ctx;
Harald Welteb78996d2009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte (local)cb4715c2009-08-14 10:42:43 +020059static const struct value_string cp_cause_strs[] = {
60 { GSM411_CP_CAUSE_NET_FAIL, "Network Failure" },
61 { GSM411_CP_CAUSE_CONGESTION, "Congestion" },
62 { GSM411_CP_CAUSE_INV_TRANS_ID, "Invalid Transaction ID" },
63 { GSM411_CP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
64 { GSM411_CP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
65 { GSM411_CP_CAUSE_MSGTYPE_NOTEXIST, "Message Type doesn't exist" },
66 { GSM411_CP_CAUSE_MSG_INCOMP_STATE,
67 "Message incompatible with protocol state" },
68 { GSM411_CP_CAUSE_IE_NOTEXIST, "IE does not exist" },
69 { GSM411_CP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
70 { 0, 0 }
71};
72
73static const struct value_string rp_cause_strs[] = {
74 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
75 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
76 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
77 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
78 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
79 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
80 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
81 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
82 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
83 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
84 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
85 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
86 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
87 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
88 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
89 /* valid only for MT */
90 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
91 /* valid for both directions */
92 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
93 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
94 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
95 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
96 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
97 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
98 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
99 { 0, NULL }
100};
101
Harald Welte68b7df22009-08-08 16:03:15 +0200102struct gsm_sms *sms_alloc(void)
103{
104 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
105}
106
107void sms_free(struct gsm_sms *sms)
108{
109 /* drop references to subscriber structure */
110 if (sms->sender)
111 subscr_put(sms->sender);
112 if (sms->receiver)
113 subscr_put(sms->receiver);
114
115 talloc_free(sms);
116}
117
Harald Welte59b04682009-06-10 05:40:52 +0800118struct msgb *gsm411_msgb_alloc(void)
119{
Harald Welte9cfc9352009-06-26 19:39:35 +0200120 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
121 "GSM 04.11");
Harald Welte59b04682009-06-10 05:40:52 +0800122}
123
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200124static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800125{
126 if (msg->lchan)
127 msg->trx = msg->lchan->ts->trx;
128
129 msg->l3h = msg->data;
130
Harald Welte68b7df22009-08-08 16:03:15 +0200131 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
132
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200133 return rsl_data_request(msg, link_id);
Harald Welte59b04682009-06-10 05:40:52 +0800134}
135
Harald Welte5fa17a22009-08-10 00:24:32 +0200136/* SMC TC1* is expired */
137static void cp_timer_expired(void *data)
138{
139 struct gsm_trans *trans = data;
140
141 DEBUGP(DSMS, "SMC Timer TC1* is expired, calling trans_free()\n");
142 /* FIXME: we need to re-transmit the last CP-DATA 1..3 times */
143 trans_free(trans);
144}
145
Harald Welte7e2f57d2009-07-04 17:39:00 +0200146/* Prefix msg with a 04.08/04.11 CP header */
Harald Welteb78996d2009-07-27 20:11:35 +0200147static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
148 u_int8_t msg_type)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200149{
150 struct gsm48_hdr *gh;
151
152 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
153 /* Outgoing needs the highest bit set */
Harald Welteb78996d2009-07-27 20:11:35 +0200154 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200155 gh->msg_type = msg_type;
156
Harald Welteb78996d2009-07-27 20:11:35 +0200157 /* assign the outgoing lchan */
158 msg->lchan = trans->lchan;
159
160 /* mobile originating */
161 switch (gh->msg_type) {
162 case GSM411_MT_CP_DATA:
163 /* 5.2.3.1.2: enter MO-wait for CP-ack */
Harald Welte09421d32009-08-09 14:59:02 +0200164 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Welteb78996d2009-07-27 20:11:35 +0200165 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte5fa17a22009-08-10 00:24:32 +0200166 trans->sms.cp_timer.data = trans;
167 trans->sms.cp_timer.cb = cp_timer_expired;
168 /* 5.3.2.1: Set Timer TC1A */
169 bsc_schedule_timer(&trans->sms.cp_timer, GSM411_TMR_TC1A);
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200170 DEBUGP(DSMS, "TX: CP-DATA ");
171 break;
172 case GSM411_MT_CP_ACK:
173 DEBUGP(DSMS, "TX: CP-ACK ");
174 break;
175 case GSM411_MT_CP_ERROR:
Sylvain Munaut163a24a2009-12-18 18:28:07 +0100176 DEBUGP(DSMS, "TX: CP-ERROR ");
Harald Welteb78996d2009-07-27 20:11:35 +0200177 break;
178 }
179
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200180 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
181
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200182 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200183}
184
185/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Welteb78996d2009-07-27 20:11:35 +0200186static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
187 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte7e2f57d2009-07-04 17:39:00 +0200188{
189 struct gsm411_rp_hdr *rp;
Harald Weltef2e680b2009-08-10 00:22:19 +0200190 u_int8_t len = msg->len;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200191
192 /* GSM 04.11 RP-DATA header */
193 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
Harald Weltef2e680b2009-08-10 00:22:19 +0200194 rp->len = len + 2;
Harald Welte7e2f57d2009-07-04 17:39:00 +0200195 rp->msg_type = rp_msg_type;
196 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
197
Harald Welteb78996d2009-07-27 20:11:35 +0200198 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte7e2f57d2009-07-04 17:39:00 +0200199}
200
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100201/* Turn int into semi-octet representation: 98 => 0x89 */
202static u_int8_t bcdify(u_int8_t value)
203{
204 u_int8_t ret;
Steffen Neubauer94436952009-11-11 23:02:07 +0900205
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100206 ret = value / 10;
207 ret |= (value % 10) << 4;
208
209 return ret;
210}
211
212/* Turn semi-octet representation into int: 0x89 => 98 */
213static u_int8_t unbcdify(u_int8_t value)
214{
215 u_int8_t ret;
216
217 if ((value & 0x0F) > 9 || (value >> 4) > 9)
Harald Welteced9a912009-12-24 15:08:18 +0100218 LOGP(DSMS, LOGL_ERROR,
219 "unbcdify got too big nibble: 0x%02X\n", value);
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100220
221 ret = (value&0x0F)*10;
Steffen Neubauere5e0eb72009-11-26 23:38:41 +0100222 ret += value>>4;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100223
224 return ret;
225}
226
227/* Generate 03.40 TP-SCTS */
228static void gsm340_gen_scts(u_int8_t *scts, time_t time)
229{
230 struct tm *tm = localtime(&time);
231
232 *scts++ = bcdify(tm->tm_year % 100);
233 *scts++ = bcdify(tm->tm_mon + 1);
234 *scts++ = bcdify(tm->tm_mday);
235 *scts++ = bcdify(tm->tm_hour);
236 *scts++ = bcdify(tm->tm_min);
237 *scts++ = bcdify(tm->tm_sec);
238 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
239}
240
241/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
242static time_t gsm340_scts(u_int8_t *scts)
243{
244 struct tm tm;
245
246 u_int8_t yr = unbcdify(*scts++);
247
248 if (yr <= 80)
249 tm.tm_year = 100 + yr;
250 else
251 tm.tm_year = yr;
252 tm.tm_mon = unbcdify(*scts++) - 1;
253 tm.tm_mday = unbcdify(*scts++);
254 tm.tm_hour = unbcdify(*scts++);
255 tm.tm_min = unbcdify(*scts++);
256 tm.tm_sec = unbcdify(*scts++);
257 /* according to gsm 03.40 time zone is
258 "expressed in quarters of an hour" */
259 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
260
261 return mktime(&tm);
262}
263
264/* Return the default validity period in minutes */
265static unsigned long gsm340_vp_default(void)
266{
267 unsigned long minutes;
268 /* Default validity: two days */
269 minutes = 24 * 60 * 2;
270 return minutes;
271}
272
273/* Decode validity period format 'relative' */
274static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
275{
276 /* Chapter 9.2.3.12.1 */
277 u_int8_t vp;
278 unsigned long minutes;
279
280 vp = *(sms_vp);
281 if (vp <= 143)
282 minutes = vp + 1 * 5;
283 else if (vp <= 167)
284 minutes = 12*60 + (vp-143) * 30;
285 else if (vp <= 196)
286 minutes = vp-166 * 60 * 24;
287 else
288 minutes = vp-192 * 60 * 24 * 7;
289 return minutes;
290}
291
292/* Decode validity period format 'absolute' */
293static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
294{
295 /* Chapter 9.2.3.12.2 */
296 time_t expires, now;
297 unsigned long minutes;
298
299 expires = gsm340_scts(sms_vp);
300 now = mktime(gmtime(NULL));
301 if (expires <= now)
302 minutes = 0;
303 else
304 minutes = (expires-now)/60;
305 return minutes;
306}
307
308/* Decode validity period format 'relative in integer representation' */
309static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte59b04682009-06-10 05:40:52 +0800310{
311 u_int8_t vp;
312 unsigned long minutes;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100313 vp = *(sms_vp);
314 if (vp == 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100315 LOGP(DSMS, LOGL_ERROR,
316 "reserved relative_integer validity period\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100317 return gsm340_vp_default();
318 }
319 minutes = vp/60;
320 return minutes;
321}
322
323/* Decode validity period format 'relative in semi-octet representation' */
324static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
325{
326 unsigned long minutes;
327 minutes = unbcdify(*sms_vp++)*60; /* hours */
328 minutes += unbcdify(*sms_vp++); /* minutes */
329 minutes += unbcdify(*sms_vp++)/60; /* seconds */
330 return minutes;
331}
332
333/* decode validity period. return minutes */
334static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
335{
336 u_int8_t fi; /* functionality indicator */
Harald Welte59b04682009-06-10 05:40:52 +0800337
Harald Welte68b7df22009-08-08 16:03:15 +0200338 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800339 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100340 return gsm340_vp_relative(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800341 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100342 return gsm340_vp_absolute(sms_vp);
Harald Welte59b04682009-06-10 05:40:52 +0800343 case GSM340_TP_VPF_ENHANCED:
344 /* Chapter 9.2.3.12.3 */
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100345 fi = *sms_vp++;
346 /* ignore additional fi */
347 if (fi & (1<<7)) sms_vp++;
348 /* read validity period format */
349 switch (fi & 0b111) {
350 case 0b000:
351 return gsm340_vp_default(); /* no vpf specified */
352 case 0b001:
353 return gsm340_vp_relative(sms_vp);
354 case 0b010:
355 return gsm340_vp_relative_integer(sms_vp);
356 case 0b011:
357 return gsm340_vp_relative_semioctet(sms_vp);
358 default:
359 /* The GSM spec says that the SC should reject any
360 unsupported and/or undefined values. FIXME */
Harald Welteced9a912009-12-24 15:08:18 +0100361 LOGP(DSMS, LOGL_ERROR,
362 "Reserved enhanced validity period format\n");
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100363 return gsm340_vp_default();
364 }
Daniel Willmann426bb162009-08-13 03:40:49 +0200365 case GSM340_TP_VPF_NONE:
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100366 default:
367 return gsm340_vp_default();
Harald Welte59b04682009-06-10 05:40:52 +0800368 }
Harald Welte59b04682009-06-10 05:40:52 +0800369}
370
371/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
372enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
373{
374 u_int8_t cgbits = dcs >> 4;
375 enum sms_alphabet alpha = DCS_NONE;
376
377 if ((cgbits & 0xc) == 0) {
378 if (cgbits & 2)
Harald Welteced9a912009-12-24 15:08:18 +0100379 LOGP(DSMS, LOGL_NOTICE,
380 "Compressed SMS not supported yet\n");
Harald Welte59b04682009-06-10 05:40:52 +0800381
Daniel Willmannf2861022009-08-15 03:01:17 +0200382 switch ((dcs >> 2)&0x03) {
Harald Welte59b04682009-06-10 05:40:52 +0800383 case 0:
384 alpha = DCS_7BIT_DEFAULT;
385 break;
386 case 1:
387 alpha = DCS_8BIT_DATA;
388 break;
389 case 2:
390 alpha = DCS_UCS2;
391 break;
392 }
393 } else if (cgbits == 0xc || cgbits == 0xd)
394 alpha = DCS_7BIT_DEFAULT;
395 else if (cgbits == 0xe)
396 alpha = DCS_UCS2;
397 else if (cgbits == 0xf) {
398 if (dcs & 4)
399 alpha = DCS_8BIT_DATA;
400 else
401 alpha = DCS_7BIT_DEFAULT;
402 }
403
404 return alpha;
405}
406
Harald Welte68b7df22009-08-08 16:03:15 +0200407static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte59b04682009-06-10 05:40:52 +0800408{
409 if (db_sms_store(gsms) != 0) {
Harald Welteced9a912009-12-24 15:08:18 +0100410 LOGP(DSMS, LOGL_ERROR, "Failed to store SMS in Database\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200411 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800412 }
Harald Welte68b7df22009-08-08 16:03:15 +0200413 /* dispatch a signal to tell higher level about it */
414 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200415 /* try delivering the SMS right now */
416 //gsm411_send_sms_subscr(gsms->receiver, gsms);
417
Harald Welte59b04682009-06-10 05:40:52 +0800418 return 0;
419}
420
Harald Welte68b7df22009-08-08 16:03:15 +0200421/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
422static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
423 struct gsm_subscriber *subscr)
Harald Welteb78996d2009-07-27 20:11:35 +0200424{
Harald Welte68b7df22009-08-08 16:03:15 +0200425 int len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200426
Harald Welte68b7df22009-08-08 16:03:15 +0200427 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
428
Harald Weltefdc93d92010-03-07 23:40:35 +0100429 len_in_bytes = gsm48_encode_bcd_number(oa, oa_len, 1, subscr->extension);
Harald Welte68b7df22009-08-08 16:03:15 +0200430
431 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
432 oa[0] = strlen(subscr->extension) & 0xff;
433
434 return len_in_bytes;
Harald Welteb78996d2009-07-27 20:11:35 +0200435}
436
Harald Welte68b7df22009-08-08 16:03:15 +0200437/* generate a msgb containing a TPDU derived from struct gsm_sms,
438 * returns total size of TPDU */
439static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Welteb78996d2009-07-27 20:11:35 +0200440{
Harald Welteb78996d2009-07-27 20:11:35 +0200441 u_int8_t *smsp;
442 u_int8_t oa[12]; /* max len per 03.40 */
443 u_int8_t oa_len = 0;
Daniel Willmanna31ed622009-08-13 03:39:07 +0200444 u_int8_t octet_len;
Harald Welte68b7df22009-08-08 16:03:15 +0200445 unsigned int old_msg_len = msg->len;
Harald Welteb78996d2009-07-27 20:11:35 +0200446
447 /* generate first octet with masked bits */
448 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200449 /* TP-MTI (message type indicator) */
Harald Welteb78996d2009-07-27 20:11:35 +0200450 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte68b7df22009-08-08 16:03:15 +0200451 /* TP-MMS (more messages to send) */
452 if (0 /* FIXME */)
Harald Welteb78996d2009-07-27 20:11:35 +0200453 *smsp |= 0x04;
Harald Welte68b7df22009-08-08 16:03:15 +0200454 /* TP-SRI(deliver)/SRR(submit) */
Harald Welteb78996d2009-07-27 20:11:35 +0200455 if (sms->status_rep_req)
456 *smsp |= 0x20;
Harald Welte68b7df22009-08-08 16:03:15 +0200457 /* TP-UDHI (indicating TP-UD contains a header) */
458 if (sms->ud_hdr_ind)
Harald Welteb78996d2009-07-27 20:11:35 +0200459 *smsp |= 0x40;
Harald Welte68b7df22009-08-08 16:03:15 +0200460#if 0
461 /* TP-RP (indicating that a reply path exists) */
Harald Welteb78996d2009-07-27 20:11:35 +0200462 if (sms->
463 *smsp |= 0x80;
464#endif
465
466 /* generate originator address */
Harald Welte68b7df22009-08-08 16:03:15 +0200467 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Welteb78996d2009-07-27 20:11:35 +0200468 smsp = msgb_put(msg, oa_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200469 memcpy(smsp, oa, oa_len);
470
471 /* generate TP-PID */
472 smsp = msgb_put(msg, 1);
473 *smsp = sms->protocol_id;
474
475 /* generate TP-DCS */
476 smsp = msgb_put(msg, 1);
477 *smsp = sms->data_coding_scheme;
478
479 /* generate TP-SCTS */
480 smsp = msgb_put(msg, 7);
481 gsm340_gen_scts(smsp, time(NULL));
Harald Welte68b7df22009-08-08 16:03:15 +0200482
Harald Welteb78996d2009-07-27 20:11:35 +0200483 /* generate TP-UDL */
484 smsp = msgb_put(msg, 1);
Harald Welte68b7df22009-08-08 16:03:15 +0200485 *smsp = sms->user_data_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200486
487 /* generate TP-UD */
Daniel Willmann8d786602009-08-15 03:01:46 +0200488 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
489 case DCS_7BIT_DEFAULT:
Daniel Willmanna31ed622009-08-13 03:39:07 +0200490 octet_len = sms->user_data_len*7/8;
491 if (sms->user_data_len*7%8 != 0)
492 octet_len++;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200493 /* Warning, user_data_len indicates the amount of septets
494 * (characters), we need amount of octets occupied */
Daniel Willmanna31ed622009-08-13 03:39:07 +0200495 smsp = msgb_put(msg, octet_len);
496 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann8d786602009-08-15 03:01:46 +0200497 break;
498 case DCS_UCS2:
499 case DCS_8BIT_DATA:
500 smsp = msgb_put(msg, sms->user_data_len);
501 memcpy(smsp, sms->user_data, sms->user_data_len);
502 break;
503 default:
Harald Welteced9a912009-12-24 15:08:18 +0100504 LOGP(DSMS, LOGL_NOTICE, "Unhandled Data Coding Scheme: 0x%02X\n",
505 sms->data_coding_scheme);
Daniel Willmann8d786602009-08-15 03:01:46 +0200506 break;
Daniel Willmann8f31ed92009-08-12 21:17:06 +0200507 }
Harald Welteb78996d2009-07-27 20:11:35 +0200508
Harald Welte68b7df22009-08-08 16:03:15 +0200509 return msg->len - old_msg_len;
Harald Welteb78996d2009-07-27 20:11:35 +0200510}
511
Harald Welte156c5e62009-07-05 14:02:46 +0200512/* process an incoming TPDU (called from RP-DATA)
513 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte59b04682009-06-10 05:40:52 +0800514static int gsm340_rx_tpdu(struct msgb *msg)
515{
Harald Welte75350412009-07-23 18:46:00 +0200516 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Harald Welte59b04682009-06-10 05:40:52 +0800517 u_int8_t *smsp = msgb_sms(msg);
Harald Welte59b04682009-06-10 05:40:52 +0800518 struct gsm_sms *gsms;
Harald Welte68b7df22009-08-08 16:03:15 +0200519 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
520 u_int8_t *sms_vp;
Harald Welte59b04682009-06-10 05:40:52 +0800521 u_int8_t da_len_bytes;
522 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
523 int rc = 0;
524
Harald Weltebdbb7442009-12-22 19:07:32 +0100525 counter_inc(bts->network->stats.sms.submitted);
Harald Welte3edc5a92009-12-22 00:41:05 +0100526
Harald Welte68b7df22009-08-08 16:03:15 +0200527 gsms = sms_alloc();
528 if (!gsms)
Harald Welte156c5e62009-07-05 14:02:46 +0200529 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800530
531 /* invert those fields where 0 means active/present */
Harald Welte68b7df22009-08-08 16:03:15 +0200532 sms_mti = *smsp & 0x03;
533 sms_mms = !!(*smsp & 0x04);
534 sms_vpf = (*smsp & 0x18) >> 3;
535 gsms->status_rep_req = (*smsp & 0x20);
536 gsms->ud_hdr_ind = (*smsp & 0x40);
537 sms_rp = (*smsp & 0x80);
Harald Welte59b04682009-06-10 05:40:52 +0800538
539 smsp++;
Harald Welte68b7df22009-08-08 16:03:15 +0200540 gsms->msg_ref = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800541
542 /* length in bytes of the destination address */
543 da_len_bytes = 2 + *smsp/2 + *smsp%2;
544 if (da_len_bytes > 12) {
Harald Welteced9a912009-12-24 15:08:18 +0100545 LOGP(DSMS, LOGL_ERROR, "Destination Address > 12 bytes ?!?\n");
Harald Welte156c5e62009-07-05 14:02:46 +0200546 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte59b04682009-06-10 05:40:52 +0800547 goto out;
548 }
Harald Welte3794e152009-06-12 02:42:11 +0800549 memset(address_lv, 0, sizeof(address_lv));
Harald Welte59b04682009-06-10 05:40:52 +0800550 memcpy(address_lv, smsp, da_len_bytes);
551 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3794e152009-06-12 02:42:11 +0800552 address_lv[0] = da_len_bytes - 1;
Harald Welte59b04682009-06-10 05:40:52 +0800553 /* convert to real number */
Harald Weltefdc93d92010-03-07 23:40:35 +0100554 gsm48_decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte59b04682009-06-10 05:40:52 +0800555 smsp += da_len_bytes;
556
Harald Welte68b7df22009-08-08 16:03:15 +0200557 gsms->protocol_id = *smsp++;
558 gsms->data_coding_scheme = *smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800559
Harald Welte68b7df22009-08-08 16:03:15 +0200560 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte59b04682009-06-10 05:40:52 +0800561
Harald Welte68b7df22009-08-08 16:03:15 +0200562 switch (sms_vpf) {
Harald Welte59b04682009-06-10 05:40:52 +0800563 case GSM340_TP_VPF_RELATIVE:
Harald Welte68b7df22009-08-08 16:03:15 +0200564 sms_vp = smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800565 break;
566 case GSM340_TP_VPF_ABSOLUTE:
567 case GSM340_TP_VPF_ENHANCED:
Harald Welte68b7df22009-08-08 16:03:15 +0200568 sms_vp = smsp;
Steffen Neubauer9cfb0402009-11-26 12:28:41 +0100569 /* the additional functionality indicator... */
Steffen Neubauerdd488d12009-12-05 12:44:41 +0100570 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
571 smsp++;
Harald Welte59b04682009-06-10 05:40:52 +0800572 smsp += 7;
573 break;
Daniel Willmann426bb162009-08-13 03:40:49 +0200574 case GSM340_TP_VPF_NONE:
575 sms_vp = 0;
576 break;
Harald Welte59b04682009-06-10 05:40:52 +0800577 default:
Harald Welteced9a912009-12-24 15:08:18 +0100578 LOGP(DSMS, LOGL_NOTICE,
579 "SMS Validity period not implemented: 0x%02x\n", sms_vpf);
Harald Welte68b7df22009-08-08 16:03:15 +0200580 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte59b04682009-06-10 05:40:52 +0800581 }
Harald Welte68b7df22009-08-08 16:03:15 +0200582 gsms->user_data_len = *smsp++;
583 if (gsms->user_data_len) {
584 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800585
Harald Welte68b7df22009-08-08 16:03:15 +0200586 switch (sms_alphabet) {
Harald Welte59b04682009-06-10 05:40:52 +0800587 case DCS_7BIT_DEFAULT:
Harald Welte68b7df22009-08-08 16:03:15 +0200588 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte59b04682009-06-10 05:40:52 +0800589 break;
590 case DCS_8BIT_DATA:
591 case DCS_UCS2:
592 case DCS_NONE:
Harald Welte59b04682009-06-10 05:40:52 +0800593 break;
594 }
595 }
596
Harald Welteced9a912009-12-24 15:08:18 +0100597 gsms->sender = subscr_get(msg->lchan->subscr);
598
599 LOGP(DSMS, LOGL_INFO, "RX SMS: Sender: %s, MTI: 0x%02x, VPF: 0x%02x, "
600 "MR: 0x%02x PID: 0x%02x, DCS: 0x%02x, DA: %s, "
601 "UserDataLength: 0x%02x, UserData: \"%s\"\n",
602 subscr_name(gsms->sender), sms_mti, sms_vpf, gsms->msg_ref,
603 gsms->protocol_id, gsms->data_coding_scheme, gsms->dest_addr,
604 gsms->user_data_len,
Harald Welte68b7df22009-08-08 16:03:15 +0200605 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
606 hexdump(gsms->user_data, gsms->user_data_len));
Harald Welte59b04682009-06-10 05:40:52 +0800607
Harald Welte68b7df22009-08-08 16:03:15 +0200608 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welte156c5e62009-07-05 14:02:46 +0200609
Harald Welte68b7df22009-08-08 16:03:15 +0200610 dispatch_signal(SS_SMS, 0, gsms);
Harald Welte156c5e62009-07-05 14:02:46 +0200611
Harald Welte59b04682009-06-10 05:40:52 +0800612 /* determine gsms->receiver based on dialled number */
Harald Welte68b7df22009-08-08 16:03:15 +0200613 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte59b04682009-06-10 05:40:52 +0800614 if (!gsms->receiver) {
615 rc = 1; /* cause 1: unknown subscriber */
Harald Weltebdbb7442009-12-22 19:07:32 +0100616 counter_inc(bts->network->stats.sms.no_receiver);
Harald Welte59b04682009-06-10 05:40:52 +0800617 goto out;
618 }
619
Harald Welte68b7df22009-08-08 16:03:15 +0200620 switch (sms_mti) {
Harald Welte59b04682009-06-10 05:40:52 +0800621 case GSM340_SMS_SUBMIT_MS2SC:
622 /* MS is submitting a SMS */
Harald Welte68b7df22009-08-08 16:03:15 +0200623 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800624 break;
625 case GSM340_SMS_COMMAND_MS2SC:
626 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welteced9a912009-12-24 15:08:18 +0100627 LOGP(DSMS, LOGL_NOTICE, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200628 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800629 break;
630 default:
Harald Welteced9a912009-12-24 15:08:18 +0100631 LOGP(DSMS, LOGL_NOTICE, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welte156c5e62009-07-05 14:02:46 +0200632 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte59b04682009-06-10 05:40:52 +0800633 break;
634 }
635
Harald Welte156c5e62009-07-05 14:02:46 +0200636 if (!rc && !gsms->receiver)
637 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
638
Harald Welte59b04682009-06-10 05:40:52 +0800639out:
Harald Welte68b7df22009-08-08 16:03:15 +0200640 sms_free(gsms);
Harald Welte59b04682009-06-10 05:40:52 +0800641
642 return rc;
643}
644
Harald Welteb78996d2009-07-27 20:11:35 +0200645static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Harald Welte59b04682009-06-10 05:40:52 +0800646{
647 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800648
Harald Welte59b04682009-06-10 05:40:52 +0800649 DEBUGP(DSMS, "TX: SMS RP ACK\n");
650
Harald Welteb78996d2009-07-27 20:11:35 +0200651 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800652}
653
Harald Welteb78996d2009-07-27 20:11:35 +0200654static int gsm411_send_rp_error(struct gsm_trans *trans,
655 u_int8_t msg_ref, u_int8_t cause)
Harald Welte59b04682009-06-10 05:40:52 +0800656{
657 struct msgb *msg = gsm411_msgb_alloc();
Harald Welte59b04682009-06-10 05:40:52 +0800658
Harald Welte59b04682009-06-10 05:40:52 +0800659 msgb_tv_put(msg, 1, cause);
660
Harald Welteced9a912009-12-24 15:08:18 +0100661 LOGP(DSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200662 get_value_string(rp_cause_strs, cause));
Harald Welte59b04682009-06-10 05:40:52 +0800663
Harald Welteb78996d2009-07-27 20:11:35 +0200664 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800665}
666
667/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Welteb78996d2009-07-27 20:11:35 +0200668static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
669 struct gsm411_rp_hdr *rph,
Harald Welte59b04682009-06-10 05:40:52 +0800670 u_int8_t src_len, u_int8_t *src,
671 u_int8_t dst_len, u_int8_t *dst,
672 u_int8_t tpdu_len, u_int8_t *tpdu)
673{
Harald Welte59b04682009-06-10 05:40:52 +0800674 int rc = 0;
675
676 if (src_len && src)
Harald Welteced9a912009-12-24 15:08:18 +0100677 LOGP(DSMS, LOGL_ERROR, "RP-DATA (MO) with SRC ?!?\n");
Harald Welte59b04682009-06-10 05:40:52 +0800678
679 if (!dst_len || !dst || !tpdu_len || !tpdu) {
Harald Welteced9a912009-12-24 15:08:18 +0100680 LOGP(DSMS, LOGL_ERROR,
681 "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200682 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welte156c5e62009-07-05 14:02:46 +0200683 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte59b04682009-06-10 05:40:52 +0800684 return -EIO;
685 }
686 msg->smsh = tpdu;
687
688 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte59b04682009-06-10 05:40:52 +0800689
690 rc = gsm340_rx_tpdu(msg);
691 if (rc == 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200692 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte59b04682009-06-10 05:40:52 +0800693 else if (rc > 0)
Harald Welteb78996d2009-07-27 20:11:35 +0200694 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte59b04682009-06-10 05:40:52 +0800695 else
696 return rc;
697}
698
699/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Welteb78996d2009-07-27 20:11:35 +0200700static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
701 struct gsm411_rp_hdr *rph)
Harald Welte59b04682009-06-10 05:40:52 +0800702{
703 u_int8_t src_len, dst_len, rpud_len;
704 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
705
706 /* in the MO case, this should always be zero length */
707 src_len = rph->data[0];
708 if (src_len)
709 src = &rph->data[1];
710
711 dst_len = rph->data[1+src_len];
712 if (dst_len)
713 dst = &rph->data[1+src_len+1];
714
715 rpud_len = rph->data[1+src_len+1+dst_len];
716 if (rpud_len)
717 rp_ud = &rph->data[1+src_len+1+dst_len+1];
718
Harald Welte156c5e62009-07-05 14:02:46 +0200719 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
720 src_len, dst_len, rpud_len);
Harald Welteb78996d2009-07-27 20:11:35 +0200721 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte59b04682009-06-10 05:40:52 +0800722 rpud_len, rp_ud);
723}
724
Harald Welte09421d32009-08-09 14:59:02 +0200725/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Welteb78996d2009-07-27 20:11:35 +0200726static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
727 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200728{
Harald Welte68b7df22009-08-08 16:03:15 +0200729 struct gsm_sms *sms = trans->sms.sms;
730
Harald Welte156c5e62009-07-05 14:02:46 +0200731 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
732 * successfully received a SMS. We can now safely mark it as
733 * transmitted */
734
Harald Welte09421d32009-08-09 14:59:02 +0200735 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100736 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK on a MO transfer ?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200737 return gsm411_send_rp_error(trans, rph->msg_ref,
738 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
739 }
Harald Weltedd62b162009-07-09 23:52:59 +0200740
Harald Welte68b7df22009-08-08 16:03:15 +0200741 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100742 LOGP(DSMS, LOGL_ERROR, "RX RP-ACK but no sms in transaction?!?\n");
Harald Welte09421d32009-08-09 14:59:02 +0200743 return gsm411_send_rp_error(trans, rph->msg_ref,
744 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte68b7df22009-08-08 16:03:15 +0200745 }
746
747 /* mark this SMS as sent in database */
748 db_sms_mark_sent(sms);
749
750 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
751
752 sms_free(sms);
753 trans->sms.sms = NULL;
754
Harald Weltefc01b242009-08-09 19:07:41 +0200755 /* check for more messages for this subscriber */
756 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
757 if (sms)
758 gsm411_send_sms_lchan(msg->lchan, sms);
Sylvain Munautd17cdeb2009-12-24 13:33:51 +0100759
760 /* free the transaction here */
761 trans_free(trans);
762
763 /* release channel if done */
764 if (!sms)
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200765 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte68b7df22009-08-08 16:03:15 +0200766
767 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200768}
769
Harald Welteb78996d2009-07-27 20:11:35 +0200770static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
771 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200772{
Harald Weltebdbb7442009-12-22 19:07:32 +0100773 struct gsm_network *net = trans->lchan->ts->trx->bts->network;
Harald Welte68b7df22009-08-08 16:03:15 +0200774 struct gsm_sms *sms = trans->sms.sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200775 u_int8_t cause_len = rph->data[0];
776 u_int8_t cause = rph->data[1];
777
Harald Welte156c5e62009-07-05 14:02:46 +0200778 /* Error in response to MT RP_DATA, i.e. the MS did not
779 * successfully receive the SMS. We need to investigate
780 * the cause and take action depending on it */
781
Harald Welteced9a912009-12-24 15:08:18 +0100782 LOGP(DSMS, LOGL_NOTICE, "%s: RX SMS RP-ERROR, cause %d:%d (%s)\n",
783 subscr_name(msg->lchan->subscr), cause_len, cause,
784 get_value_string(rp_cause_strs, cause));
Harald Welteb78996d2009-07-27 20:11:35 +0200785
Harald Welte09421d32009-08-09 14:59:02 +0200786 if (!trans->sms.is_mt) {
Harald Welteced9a912009-12-24 15:08:18 +0100787 LOGP(DSMS, LOGL_ERROR, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200788#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200789 return gsm411_send_rp_error(trans, rph->msg_ref,
790 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200791#endif
Harald Welte09421d32009-08-09 14:59:02 +0200792 }
Harald Weltedd62b162009-07-09 23:52:59 +0200793
Harald Welte68b7df22009-08-08 16:03:15 +0200794 if (!sms) {
Harald Welteced9a912009-12-24 15:08:18 +0100795 LOGP(DSMS, LOGL_ERROR,
796 "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200797 return -EINVAL;
798#if 0
Harald Welte09421d32009-08-09 14:59:02 +0200799 return gsm411_send_rp_error(trans, rph->msg_ref,
800 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ced09ed2009-08-17 09:39:55 +0200801#endif
Harald Welte09421d32009-08-09 14:59:02 +0200802 }
803
804 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
805 /* MS has not enough memory to store the message. We need
806 * to store this in our database and wati for a SMMA message */
807 /* FIXME */
808 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Weltebdbb7442009-12-22 19:07:32 +0100809 counter_inc(net->stats.sms.rp_err_mem);
Harald Welte3edc5a92009-12-22 00:41:05 +0100810 } else
Harald Weltebdbb7442009-12-22 19:07:32 +0100811 counter_inc(net->stats.sms.rp_err_other);
Harald Welte68b7df22009-08-08 16:03:15 +0200812
813 sms_free(sms);
814 trans->sms.sms = NULL;
815
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200816 //trans_free(trans);
Harald Welte68b7df22009-08-08 16:03:15 +0200817
Harald Welteb78996d2009-07-27 20:11:35 +0200818 return 0;
Harald Welte156c5e62009-07-05 14:02:46 +0200819}
820
Harald Welteb78996d2009-07-27 20:11:35 +0200821static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
822 struct gsm411_rp_hdr *rph)
Harald Welte156c5e62009-07-05 14:02:46 +0200823{
Harald Weltefc01b242009-08-09 19:07:41 +0200824 struct gsm_sms *sms;
Harald Welteb78996d2009-07-27 20:11:35 +0200825 int rc;
826
Harald Weltefc01b242009-08-09 19:07:41 +0200827 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
828 trans->sms.rp_state = GSM411_RPS_IDLE;
829
Harald Welte156c5e62009-07-05 14:02:46 +0200830 /* MS tells us that it has memory for more SMS, we need
831 * to check if we have any pending messages for it and then
832 * transfer those */
Harald Welte68b7df22009-08-08 16:03:15 +0200833 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Welteb78996d2009-07-27 20:11:35 +0200834
Harald Weltefc01b242009-08-09 19:07:41 +0200835 /* check for more messages for this subscriber */
836 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
837 if (sms)
838 gsm411_send_sms_lchan(msg->lchan, sms);
839 else
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200840 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200841
842 return rc;
Harald Welte156c5e62009-07-05 14:02:46 +0200843}
844
Harald Welteb78996d2009-07-27 20:11:35 +0200845static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
846 struct gsm_trans *trans)
Harald Welte59b04682009-06-10 05:40:52 +0800847{
848 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
849 u_int8_t msg_type = rp_data->msg_type & 0x07;
850 int rc = 0;
851
852 switch (msg_type) {
853 case GSM411_MT_RP_DATA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200854 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
855 /* start TR2N and enter 'wait to send RP-ACK state' */
856 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
857 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800858 break;
859 case GSM411_MT_RP_ACK_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200860 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
861 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welte156c5e62009-07-05 14:02:46 +0200862 break;
Harald Welte59b04682009-06-10 05:40:52 +0800863 case GSM411_MT_RP_SMMA_MO:
Harald Welteb78996d2009-07-27 20:11:35 +0200864 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
865 /* start TR2N and enter 'wait to send RP-ACK state' */
866 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
867 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
868 break;
869 case GSM411_MT_RP_ERROR_MO:
870 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Harald Welte59b04682009-06-10 05:40:52 +0800871 break;
872 default:
Harald Welteced9a912009-12-24 15:08:18 +0100873 LOGP(DSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +0200874 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
875 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte59b04682009-06-10 05:40:52 +0800876 break;
877 }
878
879 return rc;
880}
881
Harald Welteb78996d2009-07-27 20:11:35 +0200882/* send CP-ACK to given transaction */
883static int gsm411_tx_cp_ack(struct gsm_trans *trans)
884{
885 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltefc01b242009-08-09 19:07:41 +0200886 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200887
Harald Weltefc01b242009-08-09 19:07:41 +0200888 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
889
890 if (trans->sms.is_mt) {
891 /* If this is a MT SMS DELIVER, we can clear transaction here */
892 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)9d0bd792009-08-14 14:52:17 +0200893 //trans_free(trans);
Harald Weltefc01b242009-08-09 19:07:41 +0200894 }
Holger Hans Peter Freyther182c7452009-08-10 07:59:27 +0200895
896 return rc;
Harald Welteb78996d2009-07-27 20:11:35 +0200897}
898
899static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
900{
901 struct msgb *msg = gsm411_msgb_alloc();
902 u_int8_t *causep;
903
Harald Welteced9a912009-12-24 15:08:18 +0100904 LOGP(DSMS, LOGL_NOTICE, "TX CP-ERROR, cause %d (%s)\n", cause,
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200905 get_value_string(cp_cause_strs, cause));
906
Harald Welte68b7df22009-08-08 16:03:15 +0200907 causep = msgb_put(msg, 1);
Harald Welteb78996d2009-07-27 20:11:35 +0200908 *causep = cause;
909
910 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
911}
912
913/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200914int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Harald Welte59b04682009-06-10 05:40:52 +0800915{
916 struct gsm48_hdr *gh = msgb_l3(msg);
917 u_int8_t msg_type = gh->msg_type;
Harald Welteb78996d2009-07-27 20:11:35 +0200918 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
919 struct gsm_lchan *lchan = msg->lchan;
920 struct gsm_trans *trans;
Harald Welte59b04682009-06-10 05:40:52 +0800921 int rc = 0;
922
Harald Welteb78996d2009-07-27 20:11:35 +0200923 if (!lchan->subscr)
924 return -EIO;
925 /* FIXME: send some error message */
926
Sylvain Munaute02fb9a2009-12-18 18:28:08 +0100927 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Harald Welteb78996d2009-07-27 20:11:35 +0200928 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
929 transaction_id);
930 if (!trans) {
Sylvain Munaut40c23322009-12-18 18:28:09 +0100931 DEBUGPC(DSMS, "(new) ");
Harald Welteb78996d2009-07-27 20:11:35 +0200932 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
933 transaction_id, new_callref++);
934 if (!trans) {
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200935 DEBUGPC(DSMS, "No memory for trans\n");
Harald Welteb78996d2009-07-27 20:11:35 +0200936 /* FIXME: send some error message */
937 return -ENOMEM;
938 }
939 trans->sms.cp_state = GSM411_CPS_IDLE;
940 trans->sms.rp_state = GSM411_RPS_IDLE;
941 trans->sms.is_mt = 0;
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200942 trans->sms.link_id = link_id;
Harald Welteb78996d2009-07-27 20:11:35 +0200943
944 trans->lchan = lchan;
945 use_lchan(lchan);
946 }
947
Harald Welte59b04682009-06-10 05:40:52 +0800948 switch(msg_type) {
949 case GSM411_MT_CP_DATA:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200950 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Sylvain Munauta5914da2009-12-24 16:47:08 +0100951
952 /* 5.4: For MO, if a CP-DATA is received for a new
953 * transaction, equals reception of an implicit
954 * last CP-ACK for previous transaction */
955 if (trans->sms.cp_state == GSM411_CPS_IDLE) {
956 int i;
957 struct gsm_trans *ptrans;
958
959 /* Scan through all remote initiated transactions */
960 for (i=8; i<15; i++) {
961 if (i == transaction_id)
962 continue;
963
964 ptrans = trans_find_by_id(lchan->subscr,
965 GSM48_PDISC_SMS, i);
966 if (!ptrans)
967 continue;
968
969 DEBUGP(DSMS, "Implicit CP-ACK for trans_id=%x\n", i);
970
971 /* Finish it for good */
972 bsc_del_timer(&ptrans->sms.cp_timer);
973 ptrans->sms.cp_state = GSM411_CPS_IDLE;
974 trans_free(ptrans);
975 }
976 }
977
Harald Welte09421d32009-08-09 14:59:02 +0200978 /* 5.2.3.1.3: MO state exists when SMC has received
979 * CP-DATA, including sending of the assoc. CP-ACK */
980 /* 5.2.3.2.4: MT state exists when SMC has received
981 * CP-DATA, including sending of the assoc. CP-ACK */
982 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welteb78996d2009-07-27 20:11:35 +0200983
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200984 /* SMC instance acknowledges the CP-DATA frame */
985 gsm411_tx_cp_ack(trans);
986
Harald Welteb78996d2009-07-27 20:11:35 +0200987 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200988#if 0
Harald Welteb78996d2009-07-27 20:11:35 +0200989 /* Send CP-ACK or CP-ERORR in response */
990 if (rc < 0) {
991 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
992 } else
993 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)64994ce2009-08-14 11:41:12 +0200994#endif
Harald Welte59b04682009-06-10 05:40:52 +0800995 break;
996 case GSM411_MT_CP_ACK:
Harald Welteb78996d2009-07-27 20:11:35 +0200997 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)cb4715c2009-08-14 10:42:43 +0200998 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Welte09421d32009-08-09 14:59:02 +0200999 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
1000 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
1001 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte5fa17a22009-08-10 00:24:32 +02001002 /* Stop TC1* after CP-ACK has been received */
1003 bsc_del_timer(&trans->sms.cp_timer);
Harald Welte09421d32009-08-09 14:59:02 +02001004
Harald Welteb78996d2009-07-27 20:11:35 +02001005 if (!trans->sms.is_mt) {
Harald Welteb78996d2009-07-27 20:11:35 +02001006 /* FIXME: we have sont one CP-DATA, which was now
1007 * acknowledged. Check if we want to transfer more,
1008 * i.e. multi-part message */
1009 trans->sms.cp_state = GSM411_CPS_IDLE;
1010 trans_free(trans);
1011 }
Harald Welte59b04682009-06-10 05:40:52 +08001012 break;
1013 case GSM411_MT_CP_ERROR:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001014 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
1015 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte5fa17a22009-08-10 00:24:32 +02001016 bsc_del_timer(&trans->sms.cp_timer);
Harald Welteb78996d2009-07-27 20:11:35 +02001017 trans->sms.cp_state = GSM411_CPS_IDLE;
1018 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001019 break;
1020 default:
Harald Welte (local)cb4715c2009-08-14 10:42:43 +02001021 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Welteb78996d2009-07-27 20:11:35 +02001022 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Welte09421d32009-08-09 14:59:02 +02001023 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welteb78996d2009-07-27 20:11:35 +02001024 trans_free(trans);
Harald Welte59b04682009-06-10 05:40:52 +08001025 break;
1026 }
1027
Harald Welte59b04682009-06-10 05:40:52 +08001028 return rc;
1029}
1030
Harald Welte59b04682009-06-10 05:40:52 +08001031#if 0
Harald Welte59b04682009-06-10 05:40:52 +08001032/* Test TPDU - ALL YOUR */
1033static u_int8_t tpdu_test[] = {
1034 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
1035 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
1036 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
1037 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
1038};
1039#endif
1040
Harald Weltefc01b242009-08-09 19:07:41 +02001041/* Take a SMS in gsm_sms structure and send it through an already
1042 * existing lchan. We also assume that the caller ensured this lchan already
1043 * has a SAPI3 RLL connection! */
Harald Welte68b7df22009-08-08 16:03:15 +02001044int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Harald Welte59b04682009-06-10 05:40:52 +08001045{
1046 struct msgb *msg = gsm411_msgb_alloc();
Harald Welteb78996d2009-07-27 20:11:35 +02001047 struct gsm_trans *trans;
Harald Welte68b7df22009-08-08 16:03:15 +02001048 u_int8_t *data, *rp_ud_len;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001049 u_int8_t msg_ref = 42;
Sylvain Munaute65af1b2009-12-24 13:27:36 +01001050 int transaction_id;
Harald Welte68b7df22009-08-08 16:03:15 +02001051 int rc;
Harald Welte59b04682009-06-10 05:40:52 +08001052
Harald Welte6e55abf2009-12-22 13:45:58 +01001053 transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
1054 if (transaction_id == -1) {
Harald Welteced9a912009-12-24 15:08:18 +01001055 LOGP(DSMS, LOGL_ERROR, "No available transaction ids\n");
Harald Welte6e55abf2009-12-22 13:45:58 +01001056 return -EBUSY;
1057 }
Harald Weltefc01b242009-08-09 19:07:41 +02001058
Harald Welte59b04682009-06-10 05:40:52 +08001059 msg->lchan = lchan;
1060
Harald Welte68b7df22009-08-08 16:03:15 +02001061 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Welteb78996d2009-07-27 20:11:35 +02001062
Harald Welte68b7df22009-08-08 16:03:15 +02001063 /* FIXME: allocate transaction with message reference */
1064 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
1065 transaction_id, new_callref++);
1066 if (!trans) {
Harald Welteced9a912009-12-24 15:08:18 +01001067 LOGP(DSMS, LOGL_ERROR, "No memory for trans\n");
Harald Welte68b7df22009-08-08 16:03:15 +02001068 /* FIXME: send some error message */
1069 return -ENOMEM;
1070 }
1071 trans->sms.cp_state = GSM411_CPS_IDLE;
1072 trans->sms.rp_state = GSM411_RPS_IDLE;
1073 trans->sms.is_mt = 1;
1074 trans->sms.sms = sms;
Harald Welte (local)64994ce2009-08-14 11:41:12 +02001075 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte68b7df22009-08-08 16:03:15 +02001076
1077 trans->lchan = lchan;
1078 use_lchan(lchan);
1079
1080 /* Hardcode SMSC Originating Address for now */
Harald Welte59b04682009-06-10 05:40:52 +08001081 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001082 data[0] = 0x07; /* originator length == 7 */
Harald Welte156c5e62009-07-05 14:02:46 +02001083 data[1] = 0x91; /* type of number: international, ISDN */
1084 data[2] = 0x44; /* 447785016005 */
Harald Welte59b04682009-06-10 05:40:52 +08001085 data[3] = 0x77;
1086 data[4] = 0x58;
1087 data[5] = 0x10;
1088 data[6] = 0x06;
1089 data[7] = 0x50;
Harald Welte7e2f57d2009-07-04 17:39:00 +02001090
1091 /* Hardcoded Destination Address */
Harald Welte59b04682009-06-10 05:40:52 +08001092 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte7e2f57d2009-07-04 17:39:00 +02001093 data[0] = 0; /* destination length == 0 */
Harald Welte59b04682009-06-10 05:40:52 +08001094
Harald Welte68b7df22009-08-08 16:03:15 +02001095 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1096 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Harald Welte59b04682009-06-10 05:40:52 +08001097
Harald Welte68b7df22009-08-08 16:03:15 +02001098#if 1
1099 /* generate the 03.40 TPDU */
1100 rc = gsm340_gen_tpdu(msg, sms);
1101 if (rc < 0) {
1102 msgb_free(msg);
1103 return rc;
1104 }
Harald Welte59b04682009-06-10 05:40:52 +08001105
Harald Welte68b7df22009-08-08 16:03:15 +02001106 *rp_ud_len = rc;
1107#else
1108 data = msgb_put(msg, sizeof(tpdu_test));
Harald Welte59b04682009-06-10 05:40:52 +08001109 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte68b7df22009-08-08 16:03:15 +02001110 *rp_ud_len = sizeof(tpdu_test);
1111#endif
Harald Welte59b04682009-06-10 05:40:52 +08001112
Harald Welte68b7df22009-08-08 16:03:15 +02001113 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Harald Welte59b04682009-06-10 05:40:52 +08001114
Harald Weltebdbb7442009-12-22 19:07:32 +01001115 counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered);
Harald Welte3edc5a92009-12-22 00:41:05 +01001116
Harald Welteb78996d2009-07-27 20:11:35 +02001117 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1118 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Harald Welte59b04682009-06-10 05:40:52 +08001119}
Harald Welteb78996d2009-07-27 20:11:35 +02001120
Harald Weltefc01b242009-08-09 19:07:41 +02001121/* RLL SAPI3 establish callback. Now we have a RLL connection and
1122 * can deliver the actual message */
Harald Welte09421d32009-08-09 14:59:02 +02001123static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1124 void *_sms, enum bsc_rllr_ind type)
1125{
1126 struct gsm_sms *sms = _sms;
1127
1128 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1129 lchan, link_id, sms, type);
1130
1131 switch (type) {
1132 case BSC_RLLR_IND_EST_CONF:
1133 gsm411_send_sms_lchan(lchan, sms);
1134 break;
1135 case BSC_RLLR_IND_REL_IND:
1136 case BSC_RLLR_IND_ERR_IND:
1137 case BSC_RLLR_IND_TIMEOUT:
1138 sms_free(sms);
1139 break;
1140 }
1141}
1142
Harald Weltefc01b242009-08-09 19:07:41 +02001143/* paging callback. Here we get called if paging a subscriber has
1144 * succeeded or failed. */
Harald Welte68b7df22009-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 Welteb78996d2009-07-27 20:11:35 +02001147{
Harald Welte68b7df22009-08-08 16:03:15 +02001148 struct gsm_lchan *lchan = _lchan;
1149 struct gsm_sms *sms = _sms;
1150 int rc;
Harald Welteb78996d2009-07-27 20:11:35 +02001151
Harald Welte68b7df22009-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 Weltefc01b242009-08-09 19:07:41 +02001166 /* Establish a SAPI3 RLL connection for SMS */
Harald Welte09421d32009-08-09 14:59:02 +02001167 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte68b7df22009-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 Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +02001184int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1185 struct gsm_sms *sms)
1186{
Harald Weltefc01b242009-08-09 19:07:41 +02001187 struct gsm_lchan *lchan;
Harald Welted363c952009-08-15 03:16:17 +02001188 int rc;
Harald Weltefc01b242009-08-09 19:07:41 +02001189
Harald Welte68b7df22009-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 Weltefc01b242009-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 Welte68b7df22009-08-08 16:03:15 +02001196
1197 /* if not, we have to start paging */
Harald Welted363c952009-08-15 03:16:17 +02001198 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1199 paging_cb_send_sms, sms);
Harald Welte (local)dec08ee2009-08-15 11:25:45 +02001200 if (rc <= 0)
Harald Welted363c952009-08-15 03:16:17 +02001201 sms_free(sms);
Harald Welte68b7df22009-08-08 16:03:15 +02001202
1203 return 0;
1204}
Harald Welte5b359d82009-07-28 00:44:49 +02001205
Harald Weltefc01b242009-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)9d0bd792009-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 Welte932e20d2009-07-28 00:41:45 +02001238static __attribute__((constructor)) void on_dso_load_sms(void)
1239{
Harald Weltefc01b242009-08-09 19:07:41 +02001240 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte932e20d2009-07-28 00:41:45 +02001241}