blob: d5b011609b671f580a8525ebde9f4166278bc148 [file] [log] [blame]
Daniel Willmann8b3390e2008-12-28 00:31:09 +00001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Harald Welte7e310b12009-03-30 20:56:32 +00006 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
Daniel Willmann8b3390e2008-12-28 00:31:09 +00007 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 *
24 */
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
Harald Weltef3efc592009-07-27 20:11:35 +020031#include <time.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000032#include <netinet/in.h>
33
34#include <openbsc/msgb.h>
Harald Welte7e310b12009-03-30 20:56:32 +000035#include <openbsc/tlv.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000036#include <openbsc/debug.h>
Daniel Willmann471712b2008-12-29 01:54:02 +000037#include <openbsc/gsm_data.h>
38#include <openbsc/gsm_subscriber.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000039#include <openbsc/gsm_04_11.h>
40#include <openbsc/gsm_04_08.h>
Holger Freyther76c95692009-02-17 20:31:30 +000041#include <openbsc/gsm_utils.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000042#include <openbsc/abis_rsl.h>
Holger Freyther9b177762009-02-16 19:07:18 +000043#include <openbsc/signal.h>
Harald Welte7e310b12009-03-30 20:56:32 +000044#include <openbsc/db.h>
Harald Welte2cf161b2009-06-20 22:36:41 +020045#include <openbsc/talloc.h>
Harald Weltef3efc592009-07-27 20:11:35 +020046#include <openbsc/transaction.h>
Harald Welte76042182009-08-08 16:03:15 +020047#include <openbsc/paging.h>
Harald Weltecb8f4432009-08-09 14:59:02 +020048#include <openbsc/bsc_rll.h>
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020049#include <openbsc/chan_alloc.h>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000050
Daniel Willmann471712b2008-12-29 01:54:02 +000051#define GSM411_ALLOC_SIZE 1024
52#define GSM411_ALLOC_HEADROOM 128
53
Harald Weltecb8f4432009-08-09 14:59:02 +020054#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
55
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020056void *tall_gsms_ctx;
Harald Weltef3efc592009-07-27 20:11:35 +020057static u_int32_t new_callref = 0x40000001;
58
Harald Welte (local)c89a5112009-08-14 10:42:43 +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 Welte76042182009-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
Holger Freythera553d092009-01-04 20:16:25 +0000118struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +0000119{
Harald Welte966636f2009-06-26 19:39:35 +0200120 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
121 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +0000122}
123
Harald Welte (local)daef6062009-08-14 11:41:12 +0200124static int gsm411_sendmsg(struct msgb *msg, u_int8_t link_id)
Daniel Willmann471712b2008-12-29 01:54:02 +0000125{
126 if (msg->lchan)
127 msg->trx = msg->lchan->ts->trx;
128
129 msg->l3h = msg->data;
130
Harald Welte76042182009-08-08 16:03:15 +0200131 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
132
Harald Welte (local)daef6062009-08-14 11:41:12 +0200133 return rsl_data_request(msg, link_id);
Daniel Willmann471712b2008-12-29 01:54:02 +0000134}
135
Harald Welte41985612009-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 Welte87f5d632009-07-04 17:39:00 +0200146/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +0200147static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
148 u_int8_t msg_type)
Harald Welte87f5d632009-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 Weltef3efc592009-07-27 20:11:35 +0200154 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +0200155 gh->msg_type = msg_type;
156
Harald Weltef3efc592009-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 Weltecb8f4432009-08-09 14:59:02 +0200164 /* 5.2.3.2.3: enter MT-wait for CP-ACK */
Harald Weltef3efc592009-07-27 20:11:35 +0200165 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
Harald Welte41985612009-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)c89a5112009-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 Munaut1d9efd62009-12-18 18:28:07 +0100176 DEBUGP(DSMS, "TX: CP-ERROR ");
Harald Weltef3efc592009-07-27 20:11:35 +0200177 break;
178 }
179
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200180 DEBUGPC(DSMS, "trans=%x\n", trans->transaction_id);
181
Harald Welte (local)daef6062009-08-14 11:41:12 +0200182 return gsm411_sendmsg(msg, trans->sms.link_id);
Harald Welte87f5d632009-07-04 17:39:00 +0200183}
184
185/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-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 Welte87f5d632009-07-04 17:39:00 +0200188{
189 struct gsm411_rp_hdr *rp;
Harald Welte0d544e72009-08-10 00:22:19 +0200190 u_int8_t len = msg->len;
Harald Welte87f5d632009-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 Welte0d544e72009-08-10 00:22:19 +0200194 rp->len = len + 2;
Harald Welte87f5d632009-07-04 17:39:00 +0200195 rp->msg_type = rp_msg_type;
196 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
197
Harald Weltef3efc592009-07-27 20:11:35 +0200198 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200199}
200
Steffen Neubauerf3262672009-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 Neubauer5727cf42009-11-11 23:02:07 +0900205
Steffen Neubauerf3262672009-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)
218 DEBUGP(DSMS, "unbcdify got too big nibble: 0x%02X\n", value);
219
220 ret = (value&0x0F)*10;
Steffen Neubauerad69d7f2009-11-26 23:38:41 +0100221 ret += value>>4;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100222
223 return ret;
224}
225
226/* Generate 03.40 TP-SCTS */
227static void gsm340_gen_scts(u_int8_t *scts, time_t time)
228{
229 struct tm *tm = localtime(&time);
230
231 *scts++ = bcdify(tm->tm_year % 100);
232 *scts++ = bcdify(tm->tm_mon + 1);
233 *scts++ = bcdify(tm->tm_mday);
234 *scts++ = bcdify(tm->tm_hour);
235 *scts++ = bcdify(tm->tm_min);
236 *scts++ = bcdify(tm->tm_sec);
237 *scts++ = bcdify(tm->tm_gmtoff/(60*15));
238}
239
240/* Decode 03.40 TP-SCTS (into utc/gmt timestamp) */
241static time_t gsm340_scts(u_int8_t *scts)
242{
243 struct tm tm;
244
245 u_int8_t yr = unbcdify(*scts++);
246
247 if (yr <= 80)
248 tm.tm_year = 100 + yr;
249 else
250 tm.tm_year = yr;
251 tm.tm_mon = unbcdify(*scts++) - 1;
252 tm.tm_mday = unbcdify(*scts++);
253 tm.tm_hour = unbcdify(*scts++);
254 tm.tm_min = unbcdify(*scts++);
255 tm.tm_sec = unbcdify(*scts++);
256 /* according to gsm 03.40 time zone is
257 "expressed in quarters of an hour" */
258 tm.tm_gmtoff = unbcdify(*scts++) * 15*60;
259
260 return mktime(&tm);
261}
262
263/* Return the default validity period in minutes */
264static unsigned long gsm340_vp_default(void)
265{
266 unsigned long minutes;
267 /* Default validity: two days */
268 minutes = 24 * 60 * 2;
269 return minutes;
270}
271
272/* Decode validity period format 'relative' */
273static unsigned long gsm340_vp_relative(u_int8_t *sms_vp)
274{
275 /* Chapter 9.2.3.12.1 */
276 u_int8_t vp;
277 unsigned long minutes;
278
279 vp = *(sms_vp);
280 if (vp <= 143)
281 minutes = vp + 1 * 5;
282 else if (vp <= 167)
283 minutes = 12*60 + (vp-143) * 30;
284 else if (vp <= 196)
285 minutes = vp-166 * 60 * 24;
286 else
287 minutes = vp-192 * 60 * 24 * 7;
288 return minutes;
289}
290
291/* Decode validity period format 'absolute' */
292static unsigned long gsm340_vp_absolute(u_int8_t *sms_vp)
293{
294 /* Chapter 9.2.3.12.2 */
295 time_t expires, now;
296 unsigned long minutes;
297
298 expires = gsm340_scts(sms_vp);
299 now = mktime(gmtime(NULL));
300 if (expires <= now)
301 minutes = 0;
302 else
303 minutes = (expires-now)/60;
304 return minutes;
305}
306
307/* Decode validity period format 'relative in integer representation' */
308static unsigned long gsm340_vp_relative_integer(u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000309{
310 u_int8_t vp;
311 unsigned long minutes;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100312 vp = *(sms_vp);
313 if (vp == 0) {
314 DEBUGP(DSMS, "reserved relative_integer validity period\n");
315 return gsm340_vp_default();
316 }
317 minutes = vp/60;
318 return minutes;
319}
320
321/* Decode validity period format 'relative in semi-octet representation' */
322static unsigned long gsm340_vp_relative_semioctet(u_int8_t *sms_vp)
323{
324 unsigned long minutes;
325 minutes = unbcdify(*sms_vp++)*60; /* hours */
326 minutes += unbcdify(*sms_vp++); /* minutes */
327 minutes += unbcdify(*sms_vp++)/60; /* seconds */
328 return minutes;
329}
330
331/* decode validity period. return minutes */
332static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
333{
334 u_int8_t fi; /* functionality indicator */
Harald Welte7e310b12009-03-30 20:56:32 +0000335
Harald Welte76042182009-08-08 16:03:15 +0200336 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000337 case GSM340_TP_VPF_RELATIVE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100338 return gsm340_vp_relative(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000339 case GSM340_TP_VPF_ABSOLUTE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100340 return gsm340_vp_absolute(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000341 case GSM340_TP_VPF_ENHANCED:
342 /* Chapter 9.2.3.12.3 */
Steffen Neubauerf3262672009-11-26 12:28:41 +0100343 fi = *sms_vp++;
344 /* ignore additional fi */
345 if (fi & (1<<7)) sms_vp++;
346 /* read validity period format */
347 switch (fi & 0b111) {
348 case 0b000:
349 return gsm340_vp_default(); /* no vpf specified */
350 case 0b001:
351 return gsm340_vp_relative(sms_vp);
352 case 0b010:
353 return gsm340_vp_relative_integer(sms_vp);
354 case 0b011:
355 return gsm340_vp_relative_semioctet(sms_vp);
356 default:
357 /* The GSM spec says that the SC should reject any
358 unsupported and/or undefined values. FIXME */
359 DEBUGP(DSMS, "Reserved enhanced validity period format\n");
360 return gsm340_vp_default();
361 }
Daniel Willmann58c83d82009-08-13 03:40:49 +0200362 case GSM340_TP_VPF_NONE:
Steffen Neubauerf3262672009-11-26 12:28:41 +0100363 default:
364 return gsm340_vp_default();
Harald Welte7e310b12009-03-30 20:56:32 +0000365 }
Harald Welte7e310b12009-03-30 20:56:32 +0000366}
367
368/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
369enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
370{
371 u_int8_t cgbits = dcs >> 4;
372 enum sms_alphabet alpha = DCS_NONE;
373
374 if ((cgbits & 0xc) == 0) {
375 if (cgbits & 2)
376 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
377
Daniel Willmannd5d5e1d2009-08-15 03:01:17 +0200378 switch ((dcs >> 2)&0x03) {
Harald Welte7e310b12009-03-30 20:56:32 +0000379 case 0:
380 alpha = DCS_7BIT_DEFAULT;
381 break;
382 case 1:
383 alpha = DCS_8BIT_DATA;
384 break;
385 case 2:
386 alpha = DCS_UCS2;
387 break;
388 }
389 } else if (cgbits == 0xc || cgbits == 0xd)
390 alpha = DCS_7BIT_DEFAULT;
391 else if (cgbits == 0xe)
392 alpha = DCS_UCS2;
393 else if (cgbits == 0xf) {
394 if (dcs & 4)
395 alpha = DCS_8BIT_DATA;
396 else
397 alpha = DCS_7BIT_DEFAULT;
398 }
399
400 return alpha;
401}
402
Harald Welte76042182009-08-08 16:03:15 +0200403static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000404{
405 if (db_sms_store(gsms) != 0) {
406 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200407 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000408 }
Harald Welte76042182009-08-08 16:03:15 +0200409 /* dispatch a signal to tell higher level about it */
410 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200411 /* try delivering the SMS right now */
412 //gsm411_send_sms_subscr(gsms->receiver, gsms);
413
Harald Welte7e310b12009-03-30 20:56:32 +0000414 return 0;
415}
416
Harald Welte76042182009-08-08 16:03:15 +0200417/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
418static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
419 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200420{
Harald Welte76042182009-08-08 16:03:15 +0200421 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200422
Harald Welte76042182009-08-08 16:03:15 +0200423 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
424
425 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
426
427 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
428 oa[0] = strlen(subscr->extension) & 0xff;
429
430 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200431}
432
Harald Welte76042182009-08-08 16:03:15 +0200433/* generate a msgb containing a TPDU derived from struct gsm_sms,
434 * returns total size of TPDU */
435static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200436{
Harald Weltef3efc592009-07-27 20:11:35 +0200437 u_int8_t *smsp;
438 u_int8_t oa[12]; /* max len per 03.40 */
439 u_int8_t oa_len = 0;
Daniel Willmann9aef1452009-08-13 03:39:07 +0200440 u_int8_t octet_len;
Harald Welte76042182009-08-08 16:03:15 +0200441 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200442
443 /* generate first octet with masked bits */
444 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200445 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200446 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200447 /* TP-MMS (more messages to send) */
448 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200449 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200450 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200451 if (sms->status_rep_req)
452 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200453 /* TP-UDHI (indicating TP-UD contains a header) */
454 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200455 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200456#if 0
457 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200458 if (sms->
459 *smsp |= 0x80;
460#endif
461
462 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200463 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200464 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200465 memcpy(smsp, oa, oa_len);
466
467 /* generate TP-PID */
468 smsp = msgb_put(msg, 1);
469 *smsp = sms->protocol_id;
470
471 /* generate TP-DCS */
472 smsp = msgb_put(msg, 1);
473 *smsp = sms->data_coding_scheme;
474
475 /* generate TP-SCTS */
476 smsp = msgb_put(msg, 7);
477 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200478
Harald Weltef3efc592009-07-27 20:11:35 +0200479 /* generate TP-UDL */
480 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200481 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200482
483 /* generate TP-UD */
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200484 switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
485 case DCS_7BIT_DEFAULT:
Daniel Willmann9aef1452009-08-13 03:39:07 +0200486 octet_len = sms->user_data_len*7/8;
487 if (sms->user_data_len*7%8 != 0)
488 octet_len++;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200489 /* Warning, user_data_len indicates the amount of septets
490 * (characters), we need amount of octets occupied */
Daniel Willmann9aef1452009-08-13 03:39:07 +0200491 smsp = msgb_put(msg, octet_len);
492 memcpy(smsp, sms->user_data, octet_len);
Daniel Willmann6b024cb2009-08-15 03:01:46 +0200493 break;
494 case DCS_UCS2:
495 case DCS_8BIT_DATA:
496 smsp = msgb_put(msg, sms->user_data_len);
497 memcpy(smsp, sms->user_data, sms->user_data_len);
498 break;
499 default:
500 DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
501 break;
Daniel Willmann6b1e8222009-08-12 21:17:06 +0200502 }
Harald Weltef3efc592009-07-27 20:11:35 +0200503
Harald Welte76042182009-08-08 16:03:15 +0200504 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200505}
506
Harald Welteb9c758b2009-07-05 14:02:46 +0200507/* process an incoming TPDU (called from RP-DATA)
508 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000509static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000510{
Harald Welte9176bd42009-07-23 18:46:00 +0200511 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000512 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000513 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200514 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
515 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000516 u_int8_t da_len_bytes;
517 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
518 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000519
Harald Welteffa55a42009-12-22 19:07:32 +0100520 counter_inc(bts->network->stats.sms.submitted);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100521
Harald Welte76042182009-08-08 16:03:15 +0200522 gsms = sms_alloc();
523 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200524 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000525
526 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200527 sms_mti = *smsp & 0x03;
528 sms_mms = !!(*smsp & 0x04);
529 sms_vpf = (*smsp & 0x18) >> 3;
530 gsms->status_rep_req = (*smsp & 0x20);
531 gsms->ud_hdr_ind = (*smsp & 0x40);
532 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000533
534 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200535 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000536
Harald Welte7e310b12009-03-30 20:56:32 +0000537 /* length in bytes of the destination address */
538 da_len_bytes = 2 + *smsp/2 + *smsp%2;
539 if (da_len_bytes > 12) {
540 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200541 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000542 goto out;
543 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800544 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000545 memcpy(address_lv, smsp, da_len_bytes);
546 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800547 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000548 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200549 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000550 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000551
Harald Welte76042182009-08-08 16:03:15 +0200552 gsms->protocol_id = *smsp++;
553 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000554
Harald Welte76042182009-08-08 16:03:15 +0200555 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000556
Harald Welte76042182009-08-08 16:03:15 +0200557 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000558 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200559 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000560 break;
561 case GSM340_TP_VPF_ABSOLUTE:
562 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200563 sms_vp = smsp;
Steffen Neubauerf3262672009-11-26 12:28:41 +0100564 /* the additional functionality indicator... */
Steffen Neubauerac0c13c2009-12-05 12:44:41 +0100565 if (sms_vpf == GSM340_TP_VPF_ENHANCED && *smsp & (1<<7))
566 smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000567 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000568 break;
Daniel Willmann58c83d82009-08-13 03:40:49 +0200569 case GSM340_TP_VPF_NONE:
570 sms_vp = 0;
571 break;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000572 default:
573 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200574 sms_vpf);
575 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000576 }
Harald Welte76042182009-08-08 16:03:15 +0200577 gsms->user_data_len = *smsp++;
578 if (gsms->user_data_len) {
579 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000580
Harald Welte76042182009-08-08 16:03:15 +0200581 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000582 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200583 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000584 break;
585 case DCS_8BIT_DATA:
586 case DCS_UCS2:
587 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000588 break;
589 }
590 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000591
Harald Welte7e310b12009-03-30 20:56:32 +0000592 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
593 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200594 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
595 gsms->protocol_id, gsms->data_coding_scheme,
596 gsms->dest_addr, gsms->user_data_len,
597 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
598 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000599
Harald Welte76042182009-08-08 16:03:15 +0200600 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000601
Harald Welte76042182009-08-08 16:03:15 +0200602 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200603
Harald Welte76042182009-08-08 16:03:15 +0200604 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200605
Harald Welte7e310b12009-03-30 20:56:32 +0000606 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200607 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000608 if (!gsms->receiver) {
609 rc = 1; /* cause 1: unknown subscriber */
Harald Welteffa55a42009-12-22 19:07:32 +0100610 counter_inc(bts->network->stats.sms.no_receiver);
Harald Welte7e310b12009-03-30 20:56:32 +0000611 goto out;
612 }
613
Harald Welte76042182009-08-08 16:03:15 +0200614 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000615 case GSM340_SMS_SUBMIT_MS2SC:
616 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200617 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000618 break;
619 case GSM340_SMS_COMMAND_MS2SC:
620 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200621 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200622 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000623 break;
624 default:
Harald Welte76042182009-08-08 16:03:15 +0200625 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200626 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000627 break;
628 }
629
Harald Welteb9c758b2009-07-05 14:02:46 +0200630 if (!rc && !gsms->receiver)
631 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
632
Harald Welte7e310b12009-03-30 20:56:32 +0000633out:
Harald Welte76042182009-08-08 16:03:15 +0200634 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000635
Harald Welte7e310b12009-03-30 20:56:32 +0000636 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000637}
638
Harald Weltef3efc592009-07-27 20:11:35 +0200639static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000640{
641 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000642
Daniel Willmann471712b2008-12-29 01:54:02 +0000643 DEBUGP(DSMS, "TX: SMS RP ACK\n");
644
Harald Weltef3efc592009-07-27 20:11:35 +0200645 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000646}
647
Harald Weltef3efc592009-07-27 20:11:35 +0200648static int gsm411_send_rp_error(struct gsm_trans *trans,
649 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000650{
651 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000652
Harald Welte7e310b12009-03-30 20:56:32 +0000653 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000654
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200655 DEBUGP(DSMS, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
656 get_value_string(rp_cause_strs, cause));
Daniel Willmann471712b2008-12-29 01:54:02 +0000657
Harald Weltef3efc592009-07-27 20:11:35 +0200658 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000659}
660
Harald Welte7e310b12009-03-30 20:56:32 +0000661/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200662static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
663 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000664 u_int8_t src_len, u_int8_t *src,
665 u_int8_t dst_len, u_int8_t *dst,
666 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000667{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000668 int rc = 0;
669
Harald Welte7e310b12009-03-30 20:56:32 +0000670 if (src_len && src)
671 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
672
673 if (!dst_len || !dst || !tpdu_len || !tpdu) {
674 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200675 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200676 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000677 return -EIO;
678 }
679 msg->smsh = tpdu;
680
681 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000682
683 rc = gsm340_rx_tpdu(msg);
684 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200685 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000686 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200687 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000688 else
689 return rc;
690}
691
692/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200693static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
694 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000695{
696 u_int8_t src_len, dst_len, rpud_len;
697 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
698
699 /* in the MO case, this should always be zero length */
700 src_len = rph->data[0];
701 if (src_len)
702 src = &rph->data[1];
703
704 dst_len = rph->data[1+src_len];
705 if (dst_len)
706 dst = &rph->data[1+src_len+1];
707
708 rpud_len = rph->data[1+src_len+1+dst_len];
709 if (rpud_len)
710 rp_ud = &rph->data[1+src_len+1+dst_len+1];
711
Harald Welteb9c758b2009-07-05 14:02:46 +0200712 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
713 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200714 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000715 rpud_len, rp_ud);
716}
717
Harald Weltecb8f4432009-08-09 14:59:02 +0200718/* Receive a 04.11 RP-ACK message (response to RP-DATA from us) */
Harald Weltef3efc592009-07-27 20:11:35 +0200719static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
720 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200721{
Harald Welte76042182009-08-08 16:03:15 +0200722 struct gsm_sms *sms = trans->sms.sms;
723
Harald Welteb9c758b2009-07-05 14:02:46 +0200724 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
725 * successfully received a SMS. We can now safely mark it as
726 * transmitted */
727
Harald Weltecb8f4432009-08-09 14:59:02 +0200728 if (!trans->sms.is_mt) {
729 DEBUGP(DSMS, "RX RP-ACK on a MO transfer ?\n");
730 return gsm411_send_rp_error(trans, rph->msg_ref,
731 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
732 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200733
Harald Welte76042182009-08-08 16:03:15 +0200734 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200735 DEBUGP(DSMS, "RX RP-ACK but no sms in transaction?!?\n");
736 return gsm411_send_rp_error(trans, rph->msg_ref,
737 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte76042182009-08-08 16:03:15 +0200738 }
739
740 /* mark this SMS as sent in database */
741 db_sms_mark_sent(sms);
742
743 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
744
745 sms_free(sms);
746 trans->sms.sms = NULL;
747
Sylvain Munaut6b0b1032009-09-27 11:16:22 +0200748 /* free the transaction here */
749 trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200750
751 /* check for more messages for this subscriber */
752 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
753 if (sms)
754 gsm411_send_sms_lchan(msg->lchan, sms);
755 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200756 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Welte76042182009-08-08 16:03:15 +0200757
758 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200759}
760
Harald Weltef3efc592009-07-27 20:11:35 +0200761static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
762 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200763{
Harald Welteffa55a42009-12-22 19:07:32 +0100764 struct gsm_network *net = trans->lchan->ts->trx->bts->network;
Harald Welte76042182009-08-08 16:03:15 +0200765 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200766 u_int8_t cause_len = rph->data[0];
767 u_int8_t cause = rph->data[1];
768
Harald Welteb9c758b2009-07-05 14:02:46 +0200769 /* Error in response to MT RP_DATA, i.e. the MS did not
770 * successfully receive the SMS. We need to investigate
771 * the cause and take action depending on it */
772
Holger Hans Peter Freytherdc1e1052009-10-22 15:40:33 +0200773 DEBUGP(DSMS, "RX SMS RP-ERROR, cause %d:%d (%s)\n", cause_len, cause,
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200774 get_value_string(rp_cause_strs, cause));
Harald Weltef3efc592009-07-27 20:11:35 +0200775
Harald Weltecb8f4432009-08-09 14:59:02 +0200776 if (!trans->sms.is_mt) {
777 DEBUGP(DSMS, "RX RP-ERR on a MO transfer ?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200778#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200779 return gsm411_send_rp_error(trans, rph->msg_ref,
780 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200781#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200782 }
Harald Welte3e0f6172009-07-09 23:52:59 +0200783
Harald Welte76042182009-08-08 16:03:15 +0200784 if (!sms) {
Harald Weltecb8f4432009-08-09 14:59:02 +0200785 DEBUGP(DSMS, "RX RP-ERR, but no sms in transaction?!?\n");
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200786 return -EINVAL;
787#if 0
Harald Weltecb8f4432009-08-09 14:59:02 +0200788 return gsm411_send_rp_error(trans, rph->msg_ref,
789 GSM411_RP_CAUSE_PROTOCOL_ERR);
Harald Welte (local)ee4410a2009-08-17 09:39:55 +0200790#endif
Harald Weltecb8f4432009-08-09 14:59:02 +0200791 }
792
793 if (cause == GSM411_RP_CAUSE_MT_MEM_EXCEEDED) {
794 /* MS has not enough memory to store the message. We need
795 * to store this in our database and wati for a SMMA message */
796 /* FIXME */
797 dispatch_signal(SS_SMS, S_SMS_MEM_EXCEEDED, trans->subscr);
Harald Welteffa55a42009-12-22 19:07:32 +0100798 counter_inc(net->stats.sms.rp_err_mem);
Harald Welte24ff6ee2009-12-22 00:41:05 +0100799 } else
Harald Welteffa55a42009-12-22 19:07:32 +0100800 counter_inc(net->stats.sms.rp_err_other);
Harald Welte76042182009-08-08 16:03:15 +0200801
802 sms_free(sms);
803 trans->sms.sms = NULL;
804
Harald Welte (local)86b17172009-08-14 14:52:17 +0200805 //trans_free(trans);
Harald Welte76042182009-08-08 16:03:15 +0200806
Harald Weltef3efc592009-07-27 20:11:35 +0200807 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200808}
809
Harald Weltef3efc592009-07-27 20:11:35 +0200810static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
811 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200812{
Harald Weltecf6a3812009-08-09 19:07:41 +0200813 struct gsm_sms *sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200814 int rc;
815
Harald Weltecf6a3812009-08-09 19:07:41 +0200816 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
817 trans->sms.rp_state = GSM411_RPS_IDLE;
818
Harald Welteb9c758b2009-07-05 14:02:46 +0200819 /* MS tells us that it has memory for more SMS, we need
820 * to check if we have any pending messages for it and then
821 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200822 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200823
Harald Weltecf6a3812009-08-09 19:07:41 +0200824 /* check for more messages for this subscriber */
825 sms = db_sms_get_unsent_for_subscr(msg->lchan->subscr);
826 if (sms)
827 gsm411_send_sms_lchan(msg->lchan, sms);
828 else
Harald Welte (local)daef6062009-08-14 11:41:12 +0200829 rsl_release_request(msg->lchan, trans->sms.link_id);
Harald Weltef3efc592009-07-27 20:11:35 +0200830
831 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200832}
833
Harald Weltef3efc592009-07-27 20:11:35 +0200834static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
835 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000836{
Daniel Willmann471712b2008-12-29 01:54:02 +0000837 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000838 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000839 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000840
841 switch (msg_type) {
842 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200843 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
844 /* start TR2N and enter 'wait to send RP-ACK state' */
845 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
846 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000847 break;
848 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200849 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
850 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200851 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000852 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200853 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
854 /* start TR2N and enter 'wait to send RP-ACK state' */
855 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
856 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
857 break;
858 case GSM411_MT_RP_ERROR_MO:
859 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000860 break;
861 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000862 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200863 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
864 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000865 break;
866 }
867
868 return rc;
869}
870
Harald Weltef3efc592009-07-27 20:11:35 +0200871/* send CP-ACK to given transaction */
872static int gsm411_tx_cp_ack(struct gsm_trans *trans)
873{
874 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltecf6a3812009-08-09 19:07:41 +0200875 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200876
Harald Weltecf6a3812009-08-09 19:07:41 +0200877 rc = gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
878
879 if (trans->sms.is_mt) {
880 /* If this is a MT SMS DELIVER, we can clear transaction here */
881 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Welte (local)86b17172009-08-14 14:52:17 +0200882 //trans_free(trans);
Harald Weltecf6a3812009-08-09 19:07:41 +0200883 }
Holger Hans Peter Freyther09e364b2009-08-10 07:59:27 +0200884
885 return rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200886}
887
888static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
889{
890 struct msgb *msg = gsm411_msgb_alloc();
891 u_int8_t *causep;
892
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200893 DEBUGP(DSMS, "TX CP-ERROR, cause %d (%s)\n", cause,
894 get_value_string(cp_cause_strs, cause));
895
Harald Welte76042182009-08-08 16:03:15 +0200896 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200897 *causep = cause;
898
899 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
900}
901
902/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Harald Welte (local)daef6062009-08-14 11:41:12 +0200903int gsm0411_rcv_sms(struct msgb *msg, u_int8_t link_id)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000904{
905 struct gsm48_hdr *gh = msgb_l3(msg);
906 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200907 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
908 struct gsm_lchan *lchan = msg->lchan;
909 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000910 int rc = 0;
911
Harald Weltef3efc592009-07-27 20:11:35 +0200912 if (!lchan->subscr)
913 return -EIO;
914 /* FIXME: send some error message */
915
Sylvain Munautc56a1412009-12-18 18:28:08 +0100916 DEBUGP(DSMS, "trans_id=%x ", transaction_id);
Harald Weltef3efc592009-07-27 20:11:35 +0200917 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
918 transaction_id);
919 if (!trans) {
Sylvain Munautfeaca922009-12-18 18:28:09 +0100920 DEBUGPC(DSMS, "(new) ");
Harald Weltef3efc592009-07-27 20:11:35 +0200921 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
922 transaction_id, new_callref++);
923 if (!trans) {
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200924 DEBUGPC(DSMS, "No memory for trans\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200925 /* FIXME: send some error message */
926 return -ENOMEM;
927 }
928 trans->sms.cp_state = GSM411_CPS_IDLE;
929 trans->sms.rp_state = GSM411_RPS_IDLE;
930 trans->sms.is_mt = 0;
Harald Welte (local)daef6062009-08-14 11:41:12 +0200931 trans->sms.link_id = link_id;
Harald Weltef3efc592009-07-27 20:11:35 +0200932
933 trans->lchan = lchan;
934 use_lchan(lchan);
935 }
936
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000937 switch(msg_type) {
938 case GSM411_MT_CP_DATA:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200939 DEBUGPC(DSMS, "RX SMS CP-DATA\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200940 /* 5.2.3.1.3: MO state exists when SMC has received
941 * CP-DATA, including sending of the assoc. CP-ACK */
942 /* 5.2.3.2.4: MT state exists when SMC has received
943 * CP-DATA, including sending of the assoc. CP-ACK */
944 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Weltef3efc592009-07-27 20:11:35 +0200945
Harald Welte (local)daef6062009-08-14 11:41:12 +0200946 /* SMC instance acknowledges the CP-DATA frame */
947 gsm411_tx_cp_ack(trans);
948
Harald Weltef3efc592009-07-27 20:11:35 +0200949 rc = gsm411_rx_cp_data(msg, gh, trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200950#if 0
Harald Weltef3efc592009-07-27 20:11:35 +0200951 /* Send CP-ACK or CP-ERORR in response */
952 if (rc < 0) {
953 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
954 } else
955 rc = gsm411_tx_cp_ack(trans);
Harald Welte (local)daef6062009-08-14 11:41:12 +0200956#endif
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000957 break;
958 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200959 /* previous CP-DATA in this transaction was confirmed */
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200960 DEBUGPC(DSMS, "RX SMS CP-ACK\n");
Harald Weltecb8f4432009-08-09 14:59:02 +0200961 /* 5.2.3.1.3: MO state exists when SMC has received CP-ACK */
962 /* 5.2.3.2.4: MT state exists when SMC has received CP-ACK */
963 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
Harald Welte41985612009-08-10 00:24:32 +0200964 /* Stop TC1* after CP-ACK has been received */
965 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltecb8f4432009-08-09 14:59:02 +0200966
Harald Weltef3efc592009-07-27 20:11:35 +0200967 if (!trans->sms.is_mt) {
Harald Weltef3efc592009-07-27 20:11:35 +0200968 /* FIXME: we have sont one CP-DATA, which was now
969 * acknowledged. Check if we want to transfer more,
970 * i.e. multi-part message */
971 trans->sms.cp_state = GSM411_CPS_IDLE;
972 trans_free(trans);
973 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000974 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000975 case GSM411_MT_CP_ERROR:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200976 DEBUGPC(DSMS, "RX SMS CP-ERROR, cause %d (%s)\n", gh->data[0],
977 get_value_string(cp_cause_strs, gh->data[0]));
Harald Welte41985612009-08-10 00:24:32 +0200978 bsc_del_timer(&trans->sms.cp_timer);
Harald Weltef3efc592009-07-27 20:11:35 +0200979 trans->sms.cp_state = GSM411_CPS_IDLE;
980 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000981 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000982 default:
Harald Welte (local)c89a5112009-08-14 10:42:43 +0200983 DEBUGPC(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200984 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
Harald Weltecb8f4432009-08-09 14:59:02 +0200985 trans->sms.cp_state = GSM411_CPS_IDLE;
Harald Weltef3efc592009-07-27 20:11:35 +0200986 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000987 break;
988 }
989
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000990 return rc;
991}
992
Harald Welte8c2e36e2008-12-30 15:00:14 +0000993#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000994/* Test TPDU - ALL YOUR */
995static u_int8_t tpdu_test[] = {
996 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
997 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
998 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
999 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +00001000};
Harald Welte8c2e36e2008-12-30 15:00:14 +00001001#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001002
Harald Weltecf6a3812009-08-09 19:07:41 +02001003/* Take a SMS in gsm_sms structure and send it through an already
1004 * existing lchan. We also assume that the caller ensured this lchan already
1005 * has a SAPI3 RLL connection! */
Harald Welte76042182009-08-08 16:03:15 +02001006int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001007{
1008 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +02001009 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +02001010 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +02001011 u_int8_t msg_ref = 42;
Harald Weltecf6a3812009-08-09 19:07:41 +02001012 u_int8_t transaction_id;
Harald Welte76042182009-08-08 16:03:15 +02001013 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001014
Harald Welte49839212009-12-22 13:45:58 +01001015 transaction_id = trans_assign_trans_id(lchan->subscr, GSM48_PDISC_SMS, 0);
1016 if (transaction_id == -1) {
1017 DEBUGP(DSMS, "No available transaction ids\n");
1018 return -EBUSY;
1019 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001020
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001021 msg->lchan = lchan;
1022
Harald Welte76042182009-08-08 16:03:15 +02001023 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +02001024
Harald Welte76042182009-08-08 16:03:15 +02001025 /* FIXME: allocate transaction with message reference */
1026 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
1027 transaction_id, new_callref++);
1028 if (!trans) {
1029 DEBUGP(DSMS, "No memory for trans\n");
1030 /* FIXME: send some error message */
1031 return -ENOMEM;
1032 }
1033 trans->sms.cp_state = GSM411_CPS_IDLE;
1034 trans->sms.rp_state = GSM411_RPS_IDLE;
1035 trans->sms.is_mt = 1;
1036 trans->sms.sms = sms;
Harald Welte (local)daef6062009-08-14 11:41:12 +02001037 trans->sms.link_id = UM_SAPI_SMS; /* FIXME: main or SACCH ? */
Harald Welte76042182009-08-08 16:03:15 +02001038
1039 trans->lchan = lchan;
1040 use_lchan(lchan);
1041
1042 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +00001043 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +02001044 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +02001045 data[1] = 0x91; /* type of number: international, ISDN */
1046 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +00001047 data[3] = 0x77;
1048 data[4] = 0x58;
1049 data[5] = 0x10;
1050 data[6] = 0x06;
1051 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +02001052
1053 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001054 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +02001055 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001056
Harald Welte76042182009-08-08 16:03:15 +02001057 /* obtain a pointer for the rp_ud_len, so we can fill it later */
1058 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +00001059
Harald Welte76042182009-08-08 16:03:15 +02001060#if 1
1061 /* generate the 03.40 TPDU */
1062 rc = gsm340_gen_tpdu(msg, sms);
1063 if (rc < 0) {
1064 msgb_free(msg);
1065 return rc;
1066 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001067
Harald Welte76042182009-08-08 16:03:15 +02001068 *rp_ud_len = rc;
1069#else
1070 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001071 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +02001072 *rp_ud_len = sizeof(tpdu_test);
1073#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001074
Harald Welte76042182009-08-08 16:03:15 +02001075 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001076
Harald Welteffa55a42009-12-22 19:07:32 +01001077 counter_inc(lchan->ts->trx->bts->network->stats.sms.delivered);
Harald Welte24ff6ee2009-12-22 00:41:05 +01001078
Harald Weltef3efc592009-07-27 20:11:35 +02001079 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
1080 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +00001081}
Harald Weltef3efc592009-07-27 20:11:35 +02001082
Harald Weltecf6a3812009-08-09 19:07:41 +02001083/* RLL SAPI3 establish callback. Now we have a RLL connection and
1084 * can deliver the actual message */
Harald Weltecb8f4432009-08-09 14:59:02 +02001085static void rll_ind_cb(struct gsm_lchan *lchan, u_int8_t link_id,
1086 void *_sms, enum bsc_rllr_ind type)
1087{
1088 struct gsm_sms *sms = _sms;
1089
1090 DEBUGP(DSMS, "rll_ind_cb(lchan=%p, link_id=%u, sms=%p, type=%u\n",
1091 lchan, link_id, sms, type);
1092
1093 switch (type) {
1094 case BSC_RLLR_IND_EST_CONF:
1095 gsm411_send_sms_lchan(lchan, sms);
1096 break;
1097 case BSC_RLLR_IND_REL_IND:
1098 case BSC_RLLR_IND_ERR_IND:
1099 case BSC_RLLR_IND_TIMEOUT:
1100 sms_free(sms);
1101 break;
1102 }
1103}
1104
Harald Weltecf6a3812009-08-09 19:07:41 +02001105/* paging callback. Here we get called if paging a subscriber has
1106 * succeeded or failed. */
Harald Welte76042182009-08-08 16:03:15 +02001107static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
1108 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +02001109{
Harald Welte76042182009-08-08 16:03:15 +02001110 struct gsm_lchan *lchan = _lchan;
1111 struct gsm_sms *sms = _sms;
1112 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +02001113
Harald Welte76042182009-08-08 16:03:15 +02001114 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
1115 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
1116
1117 if (hooknum != GSM_HOOK_RR_PAGING)
1118 return -EINVAL;
1119
1120 switch (event) {
1121 case GSM_PAGING_SUCCEEDED:
1122 /* Paging aborted without lchan ?!? */
1123 if (!lchan) {
1124 sms_free(sms);
1125 rc = -EIO;
1126 break;
1127 }
Harald Weltecf6a3812009-08-09 19:07:41 +02001128 /* Establish a SAPI3 RLL connection for SMS */
Harald Weltecb8f4432009-08-09 14:59:02 +02001129 rc = rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001130 break;
1131 case GSM_PAGING_EXPIRED:
1132 sms_free(sms);
1133 rc = -ETIMEDOUT;
1134 break;
1135 default:
1136 rc = -EINVAL;
1137 break;
1138 }
1139
1140 return rc;
1141}
1142
Harald Weltecf6a3812009-08-09 19:07:41 +02001143/* high-level function to send a SMS to a given subscriber. The function
1144 * will take care of paging the subscriber, establishing the RLL SAPI3
1145 * connection, etc. */
Harald Welte76042182009-08-08 16:03:15 +02001146int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
1147 struct gsm_sms *sms)
1148{
Harald Weltecf6a3812009-08-09 19:07:41 +02001149 struct gsm_lchan *lchan;
Harald Weltee903edf2009-08-15 03:16:17 +02001150 int rc;
Harald Weltecf6a3812009-08-09 19:07:41 +02001151
Harald Welte76042182009-08-08 16:03:15 +02001152 /* check if we already have an open lchan to the subscriber.
1153 * if yes, send the SMS this way */
Harald Weltecf6a3812009-08-09 19:07:41 +02001154 lchan = lchan_for_subscr(subscr);
1155 if (lchan)
1156 return rll_establish(lchan, UM_SAPI_SMS,
1157 rll_ind_cb, sms);
Harald Welte76042182009-08-08 16:03:15 +02001158
1159 /* if not, we have to start paging */
Harald Weltee903edf2009-08-15 03:16:17 +02001160 rc = paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
1161 paging_cb_send_sms, sms);
Harald Welte (local)0abaf332009-08-15 11:25:45 +02001162 if (rc <= 0)
Harald Weltee903edf2009-08-15 03:16:17 +02001163 sms_free(sms);
Harald Welte76042182009-08-08 16:03:15 +02001164
1165 return 0;
1166}
Harald Welte3366a942009-07-28 00:44:49 +02001167
Harald Weltecf6a3812009-08-09 19:07:41 +02001168static int subscr_sig_cb(unsigned int subsys, unsigned int signal,
1169 void *handler_data, void *signal_data)
1170{
1171 struct gsm_subscriber *subscr;
1172 struct gsm_lchan *lchan;
1173 struct gsm_sms *sms;
1174
1175 switch (signal) {
1176 case S_SUBSCR_ATTACHED:
1177 /* A subscriber has attached. Check if there are
1178 * any pending SMS for him to be delivered */
1179 subscr = signal_data;
1180 lchan = lchan_for_subscr(subscr);
1181 if (!lchan)
1182 break;
1183 sms = db_sms_get_unsent_for_subscr(subscr);
1184 if (!sms)
1185 break;
1186 /* Establish a SAPI3 RLL connection for SMS */
1187 rll_establish(lchan, UM_SAPI_SMS, rll_ind_cb, sms);
1188 break;
1189 default:
1190 break;
1191 }
1192 return 0;
1193}
1194
Harald Welte (local)86b17172009-08-14 14:52:17 +02001195void _gsm411_sms_trans_free(struct gsm_trans *trans)
1196{
1197 bsc_del_timer(&trans->sms.cp_timer);
1198}
1199
Harald Welte7bfc2672009-07-28 00:41:45 +02001200static __attribute__((constructor)) void on_dso_load_sms(void)
1201{
Harald Weltecf6a3812009-08-09 19:07:41 +02001202 register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
Harald Welte7bfc2672009-07-28 00:41:45 +02001203}