blob: 20555101a37ef6bee1d9235370209406b6fda62f [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>
Daniel Willmann8b3390e2008-12-28 00:31:09 +000048
Daniel Willmann471712b2008-12-29 01:54:02 +000049#define GSM411_ALLOC_SIZE 1024
50#define GSM411_ALLOC_HEADROOM 128
51
Harald Welte2cf161b2009-06-20 22:36:41 +020052static void *tall_gsms_ctx;
53
Harald Weltef3efc592009-07-27 20:11:35 +020054static u_int32_t new_callref = 0x40000001;
55
Harald Welte76042182009-08-08 16:03:15 +020056struct gsm_sms *sms_alloc(void)
57{
58 return talloc_zero(tall_gsms_ctx, struct gsm_sms);
59}
60
61void sms_free(struct gsm_sms *sms)
62{
63 /* drop references to subscriber structure */
64 if (sms->sender)
65 subscr_put(sms->sender);
66 if (sms->receiver)
67 subscr_put(sms->receiver);
68
69 talloc_free(sms);
70}
71
Holger Freythera553d092009-01-04 20:16:25 +000072struct msgb *gsm411_msgb_alloc(void)
Daniel Willmann471712b2008-12-29 01:54:02 +000073{
Harald Welte966636f2009-06-26 19:39:35 +020074 return msgb_alloc_headroom(GSM411_ALLOC_SIZE, GSM411_ALLOC_HEADROOM,
75 "GSM 04.11");
Daniel Willmann471712b2008-12-29 01:54:02 +000076}
77
Harald Welte87f5d632009-07-04 17:39:00 +020078static int gsm411_sendmsg(struct msgb *msg)
Daniel Willmann471712b2008-12-29 01:54:02 +000079{
80 if (msg->lchan)
81 msg->trx = msg->lchan->ts->trx;
82
83 msg->l3h = msg->data;
84
Harald Welte76042182009-08-08 16:03:15 +020085 DEBUGP(DSMS, "GSM4.11 TX %s\n", hexdump(msg->data, msg->len));
86
Daniel Willmann471712b2008-12-29 01:54:02 +000087 return rsl_data_request(msg, 0);
88}
89
Harald Welte87f5d632009-07-04 17:39:00 +020090/* Prefix msg with a 04.08/04.11 CP header */
Harald Weltef3efc592009-07-27 20:11:35 +020091static int gsm411_cp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
92 u_int8_t msg_type)
Harald Welte87f5d632009-07-04 17:39:00 +020093{
94 struct gsm48_hdr *gh;
95
96 gh = (struct gsm48_hdr *) msgb_push(msg, sizeof(*gh));
97 /* Outgoing needs the highest bit set */
Harald Weltef3efc592009-07-27 20:11:35 +020098 gh->proto_discr = trans->protocol | (trans->transaction_id<<4);
Harald Welte87f5d632009-07-04 17:39:00 +020099 gh->msg_type = msg_type;
100
Harald Weltef3efc592009-07-27 20:11:35 +0200101 /* assign the outgoing lchan */
102 msg->lchan = trans->lchan;
103
104 /* mobile originating */
105 switch (gh->msg_type) {
106 case GSM411_MT_CP_DATA:
107 /* 5.2.3.1.2: enter MO-wait for CP-ack */
108 trans->sms.cp_state = GSM411_CPS_WAIT_CP_ACK;
109 break;
110 }
111
Harald Welte87f5d632009-07-04 17:39:00 +0200112 return gsm411_sendmsg(msg);
113}
114
115/* Prefix msg with a RP-DATA header and send as CP-DATA */
Harald Weltef3efc592009-07-27 20:11:35 +0200116static int gsm411_rp_sendmsg(struct msgb *msg, struct gsm_trans *trans,
117 u_int8_t rp_msg_type, u_int8_t rp_msg_ref)
Harald Welte87f5d632009-07-04 17:39:00 +0200118{
119 struct gsm411_rp_hdr *rp;
120
121 /* GSM 04.11 RP-DATA header */
122 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
123 rp->len = msg->len;
124 rp->msg_type = rp_msg_type;
125 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
126
Harald Weltef3efc592009-07-27 20:11:35 +0200127 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_DATA);
Harald Welte87f5d632009-07-04 17:39:00 +0200128}
129
Harald Welte76042182009-08-08 16:03:15 +0200130static unsigned long gsm340_validity_period(u_int8_t sms_vpf, u_int8_t *sms_vp)
Harald Welte7e310b12009-03-30 20:56:32 +0000131{
132 u_int8_t vp;
133 unsigned long minutes;
134
Harald Welte76042182009-08-08 16:03:15 +0200135 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000136 case GSM340_TP_VPF_RELATIVE:
137 /* Chapter 9.2.3.12.1 */
Harald Welte76042182009-08-08 16:03:15 +0200138 vp = *(sms_vp);
Harald Welte7e310b12009-03-30 20:56:32 +0000139 if (vp <= 143)
140 minutes = vp + 1 * 5;
141 else if (vp <= 167)
142 minutes = 12*60 + (vp-143) * 30;
143 else if (vp <= 196)
144 minutes = vp-166 * 60 * 24;
145 else
146 minutes = vp-192 * 60 * 24 * 7;
147 break;
148 case GSM340_TP_VPF_ABSOLUTE:
149 /* Chapter 9.2.3.12.2 */
150 /* FIXME: like service center time stamp */
151 DEBUGP(DSMS, "VPI absolute not implemented yet\n");
152 break;
153 case GSM340_TP_VPF_ENHANCED:
154 /* Chapter 9.2.3.12.3 */
155 /* FIXME: implementation */
156 DEBUGP(DSMS, "VPI enhanced not implemented yet\n");
157 break;
158 }
159 return minutes;
160}
161
162/* determine coding alphabet dependent on GSM 03.38 Section 4 DCS */
163enum sms_alphabet gsm338_get_sms_alphabet(u_int8_t dcs)
164{
165 u_int8_t cgbits = dcs >> 4;
166 enum sms_alphabet alpha = DCS_NONE;
167
168 if ((cgbits & 0xc) == 0) {
169 if (cgbits & 2)
170 DEBUGP(DSMS, "Compressed SMS not supported yet\n");
171
172 switch (dcs & 3) {
173 case 0:
174 alpha = DCS_7BIT_DEFAULT;
175 break;
176 case 1:
177 alpha = DCS_8BIT_DATA;
178 break;
179 case 2:
180 alpha = DCS_UCS2;
181 break;
182 }
183 } else if (cgbits == 0xc || cgbits == 0xd)
184 alpha = DCS_7BIT_DEFAULT;
185 else if (cgbits == 0xe)
186 alpha = DCS_UCS2;
187 else if (cgbits == 0xf) {
188 if (dcs & 4)
189 alpha = DCS_8BIT_DATA;
190 else
191 alpha = DCS_7BIT_DEFAULT;
192 }
193
194 return alpha;
195}
196
Harald Welte76042182009-08-08 16:03:15 +0200197static int gsm340_rx_sms_submit(struct msgb *msg, struct gsm_sms *gsms)
Harald Welte7e310b12009-03-30 20:56:32 +0000198{
199 if (db_sms_store(gsms) != 0) {
200 DEBUGP(DSMS, "Failed to store SMS in Database\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200201 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000202 }
Harald Welte76042182009-08-08 16:03:15 +0200203 /* dispatch a signal to tell higher level about it */
204 dispatch_signal(SS_SMS, S_SMS_SUBMITTED, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000205 return 0;
206}
207
Harald Welte76042182009-08-08 16:03:15 +0200208/* generate a TPDU address field compliant with 03.40 sec. 9.1.2.5 */
209static int gsm340_gen_oa(u_int8_t *oa, unsigned int oa_len,
210 struct gsm_subscriber *subscr)
Harald Weltef3efc592009-07-27 20:11:35 +0200211{
Harald Welte76042182009-08-08 16:03:15 +0200212 int len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200213
Harald Welte76042182009-08-08 16:03:15 +0200214 oa[1] = 0xb9; /* networks-specific number, private numbering plan */
215
216 len_in_bytes = encode_bcd_number(oa, oa_len, 1, subscr->extension);
217
218 /* GSM 03.40 tells us the length is in 'useful semi-octets' */
219 oa[0] = strlen(subscr->extension) & 0xff;
220
221 return len_in_bytes;
Harald Weltef3efc592009-07-27 20:11:35 +0200222}
223
224static u_int8_t bcdify(u_int8_t value)
225{
226 u_int8_t ret;
227
Harald Welte76042182009-08-08 16:03:15 +0200228 ret = value / 10;
229 ret |= (value % 10) << 4;
Harald Weltef3efc592009-07-27 20:11:35 +0200230
231 return ret;
232}
233
234/* Generate 03.40 TP-SCTS */
235static void gsm340_gen_scts(u_int8_t *scts, time_t time)
236{
237 struct tm *tm = localtime(&time);
Harald Weltef3efc592009-07-27 20:11:35 +0200238
239 *scts++ = bcdify(tm->tm_year % 100);
240 *scts++ = bcdify(tm->tm_mon);
241 *scts++ = bcdify(tm->tm_mday);
242 *scts++ = bcdify(tm->tm_hour);
243 *scts++ = bcdify(tm->tm_min);
244 *scts++ = bcdify(tm->tm_sec);
245 *scts++ = 0; /* FIXME: timezone */
246}
247
Harald Welte76042182009-08-08 16:03:15 +0200248/* generate a msgb containing a TPDU derived from struct gsm_sms,
249 * returns total size of TPDU */
250static int gsm340_gen_tpdu(struct msgb *msg, struct gsm_sms *sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200251{
Harald Weltef3efc592009-07-27 20:11:35 +0200252 u_int8_t *smsp;
253 u_int8_t oa[12]; /* max len per 03.40 */
254 u_int8_t oa_len = 0;
Harald Welte76042182009-08-08 16:03:15 +0200255 unsigned int old_msg_len = msg->len;
Harald Weltef3efc592009-07-27 20:11:35 +0200256
257 /* generate first octet with masked bits */
258 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200259 /* TP-MTI (message type indicator) */
Harald Weltef3efc592009-07-27 20:11:35 +0200260 *smsp = GSM340_SMS_DELIVER_SC2MS;
Harald Welte76042182009-08-08 16:03:15 +0200261 /* TP-MMS (more messages to send) */
262 if (0 /* FIXME */)
Harald Weltef3efc592009-07-27 20:11:35 +0200263 *smsp |= 0x04;
Harald Welte76042182009-08-08 16:03:15 +0200264 /* TP-SRI(deliver)/SRR(submit) */
Harald Weltef3efc592009-07-27 20:11:35 +0200265 if (sms->status_rep_req)
266 *smsp |= 0x20;
Harald Welte76042182009-08-08 16:03:15 +0200267 /* TP-UDHI (indicating TP-UD contains a header) */
268 if (sms->ud_hdr_ind)
Harald Weltef3efc592009-07-27 20:11:35 +0200269 *smsp |= 0x40;
Harald Welte76042182009-08-08 16:03:15 +0200270#if 0
271 /* TP-RP (indicating that a reply path exists) */
Harald Weltef3efc592009-07-27 20:11:35 +0200272 if (sms->
273 *smsp |= 0x80;
274#endif
275
276 /* generate originator address */
Harald Welte76042182009-08-08 16:03:15 +0200277 oa_len = gsm340_gen_oa(oa, sizeof(oa), sms->sender);
Harald Weltef3efc592009-07-27 20:11:35 +0200278 smsp = msgb_put(msg, oa_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200279 memcpy(smsp, oa, oa_len);
280
281 /* generate TP-PID */
282 smsp = msgb_put(msg, 1);
283 *smsp = sms->protocol_id;
284
285 /* generate TP-DCS */
286 smsp = msgb_put(msg, 1);
287 *smsp = sms->data_coding_scheme;
288
289 /* generate TP-SCTS */
290 smsp = msgb_put(msg, 7);
291 gsm340_gen_scts(smsp, time(NULL));
Harald Welte76042182009-08-08 16:03:15 +0200292
Harald Weltef3efc592009-07-27 20:11:35 +0200293 /* generate TP-UDL */
294 smsp = msgb_put(msg, 1);
Harald Welte76042182009-08-08 16:03:15 +0200295 *smsp = sms->user_data_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200296
297 /* generate TP-UD */
Harald Welte76042182009-08-08 16:03:15 +0200298 smsp = msgb_put(msg, sms->user_data_len);
299 memcpy(smsp, sms->user_data, sms->user_data_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200300
Harald Welte76042182009-08-08 16:03:15 +0200301 return msg->len - old_msg_len;
Harald Weltef3efc592009-07-27 20:11:35 +0200302}
303
Harald Welteb9c758b2009-07-05 14:02:46 +0200304/* process an incoming TPDU (called from RP-DATA)
305 * return value > 0: RP CAUSE for ERROR; < 0: silent error; 0 = success */
Harald Welte7e310b12009-03-30 20:56:32 +0000306static int gsm340_rx_tpdu(struct msgb *msg)
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000307{
Harald Welte9176bd42009-07-23 18:46:00 +0200308 struct gsm_bts *bts = msg->lchan->ts->trx->bts;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000309 u_int8_t *smsp = msgb_sms(msg);
Harald Welte7e310b12009-03-30 20:56:32 +0000310 struct gsm_sms *gsms;
Harald Welte76042182009-08-08 16:03:15 +0200311 u_int8_t sms_mti, sms_mms, sms_vpf, sms_alphabet, sms_rp;
312 u_int8_t *sms_vp;
Harald Welte7e310b12009-03-30 20:56:32 +0000313 u_int8_t da_len_bytes;
314 u_int8_t address_lv[12]; /* according to 03.40 / 9.1.2.5 */
315 int rc = 0;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000316
Harald Welte76042182009-08-08 16:03:15 +0200317 gsms = sms_alloc();
318 if (!gsms)
Harald Welteb9c758b2009-07-05 14:02:46 +0200319 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Harald Welte7e310b12009-03-30 20:56:32 +0000320
321 /* invert those fields where 0 means active/present */
Harald Welte76042182009-08-08 16:03:15 +0200322 sms_mti = *smsp & 0x03;
323 sms_mms = !!(*smsp & 0x04);
324 sms_vpf = (*smsp & 0x18) >> 3;
325 gsms->status_rep_req = (*smsp & 0x20);
326 gsms->ud_hdr_ind = (*smsp & 0x40);
327 sms_rp = (*smsp & 0x80);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000328
329 smsp++;
Harald Welte76042182009-08-08 16:03:15 +0200330 gsms->msg_ref = *smsp++;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000331
Harald Welte7e310b12009-03-30 20:56:32 +0000332 /* length in bytes of the destination address */
333 da_len_bytes = 2 + *smsp/2 + *smsp%2;
334 if (da_len_bytes > 12) {
335 DEBUGP(DSMS, "Destination Address > 12 bytes ?!?\n");
Harald Welteb9c758b2009-07-05 14:02:46 +0200336 rc = GSM411_RP_CAUSE_SEMANT_INC_MSG;
Harald Welte7e310b12009-03-30 20:56:32 +0000337 goto out;
338 }
Harald Welte3cfdb222009-06-12 02:42:11 +0800339 memset(address_lv, 0, sizeof(address_lv));
Harald Welte7e310b12009-03-30 20:56:32 +0000340 memcpy(address_lv, smsp, da_len_bytes);
341 /* mangle first byte to reflect length in bytes, not digits */
Harald Welte3cfdb222009-06-12 02:42:11 +0800342 address_lv[0] = da_len_bytes - 1;
Harald Welte7e310b12009-03-30 20:56:32 +0000343 /* convert to real number */
Harald Welte76042182009-08-08 16:03:15 +0200344 decode_bcd_number(gsms->dest_addr, sizeof(gsms->dest_addr), address_lv, 1);
Harald Welte7e310b12009-03-30 20:56:32 +0000345 smsp += da_len_bytes;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000346
Harald Welte76042182009-08-08 16:03:15 +0200347 gsms->protocol_id = *smsp++;
348 gsms->data_coding_scheme = *smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000349
Harald Welte76042182009-08-08 16:03:15 +0200350 sms_alphabet = gsm338_get_sms_alphabet(gsms->data_coding_scheme);
Harald Welte7e310b12009-03-30 20:56:32 +0000351
Harald Welte76042182009-08-08 16:03:15 +0200352 switch (sms_vpf) {
Harald Welte7e310b12009-03-30 20:56:32 +0000353 case GSM340_TP_VPF_RELATIVE:
Harald Welte76042182009-08-08 16:03:15 +0200354 sms_vp = smsp++;
Harald Welte7e310b12009-03-30 20:56:32 +0000355 break;
356 case GSM340_TP_VPF_ABSOLUTE:
357 case GSM340_TP_VPF_ENHANCED:
Harald Welte76042182009-08-08 16:03:15 +0200358 sms_vp = smsp;
Harald Welte7e310b12009-03-30 20:56:32 +0000359 smsp += 7;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000360 break;
361 default:
362 DEBUGP(DSMS, "SMS Validity period not implemented: 0x%02x\n",
Harald Welte76042182009-08-08 16:03:15 +0200363 sms_vpf);
364 return GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000365 }
Harald Welte76042182009-08-08 16:03:15 +0200366 gsms->user_data_len = *smsp++;
367 if (gsms->user_data_len) {
368 memcpy(gsms->user_data, smsp, gsms->user_data_len);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000369
Harald Welte76042182009-08-08 16:03:15 +0200370 switch (sms_alphabet) {
Harald Welte7e310b12009-03-30 20:56:32 +0000371 case DCS_7BIT_DEFAULT:
Harald Welte76042182009-08-08 16:03:15 +0200372 gsm_7bit_decode(gsms->text, smsp, gsms->user_data_len);
Harald Welte7e310b12009-03-30 20:56:32 +0000373 break;
374 case DCS_8BIT_DATA:
375 case DCS_UCS2:
376 case DCS_NONE:
Harald Welte7e310b12009-03-30 20:56:32 +0000377 break;
378 }
379 }
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000380
Harald Welte7e310b12009-03-30 20:56:32 +0000381 DEBUGP(DSMS, "SMS:\nMTI: 0x%02x, VPF: 0x%02x, MR: 0x%02x "
382 "PID: 0x%02x, DCS: 0x%02x, DA: %s, UserDataLength: 0x%02x "
Harald Welte76042182009-08-08 16:03:15 +0200383 "UserData: \"%s\"\n", sms_mti, sms_vpf, gsms->msg_ref,
384 gsms->protocol_id, gsms->data_coding_scheme,
385 gsms->dest_addr, gsms->user_data_len,
386 sms_alphabet == DCS_7BIT_DEFAULT ? gsms->text :
387 hexdump(gsms->user_data, gsms->user_data_len));
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000388
Harald Welte76042182009-08-08 16:03:15 +0200389 gsms->sender = subscr_get(msg->lchan->subscr);
Holger Freyther9b177762009-02-16 19:07:18 +0000390
Harald Welte76042182009-08-08 16:03:15 +0200391 gsms->validity_minutes = gsm340_validity_period(sms_vpf, sms_vp);
Harald Welteb9c758b2009-07-05 14:02:46 +0200392
Harald Welte76042182009-08-08 16:03:15 +0200393 dispatch_signal(SS_SMS, 0, gsms);
Harald Welteb9c758b2009-07-05 14:02:46 +0200394
Harald Welte7e310b12009-03-30 20:56:32 +0000395 /* determine gsms->receiver based on dialled number */
Harald Welte76042182009-08-08 16:03:15 +0200396 gsms->receiver = subscr_get_by_extension(bts->network, gsms->dest_addr);
Harald Welte7e310b12009-03-30 20:56:32 +0000397 if (!gsms->receiver) {
398 rc = 1; /* cause 1: unknown subscriber */
399 goto out;
400 }
401
Harald Welte76042182009-08-08 16:03:15 +0200402 switch (sms_mti) {
Harald Welte7e310b12009-03-30 20:56:32 +0000403 case GSM340_SMS_SUBMIT_MS2SC:
404 /* MS is submitting a SMS */
Harald Welte76042182009-08-08 16:03:15 +0200405 rc = gsm340_rx_sms_submit(msg, gsms);
Harald Welte7e310b12009-03-30 20:56:32 +0000406 break;
407 case GSM340_SMS_COMMAND_MS2SC:
408 case GSM340_SMS_DELIVER_REP_MS2SC:
Harald Welte76042182009-08-08 16:03:15 +0200409 DEBUGP(DSMS, "Unimplemented MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200410 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000411 break;
412 default:
Harald Welte76042182009-08-08 16:03:15 +0200413 DEBUGP(DSMS, "Undefined MTI 0x%02x\n", sms_mti);
Harald Welteb9c758b2009-07-05 14:02:46 +0200414 rc = GSM411_RP_CAUSE_IE_NOTEXIST;
Harald Welte7e310b12009-03-30 20:56:32 +0000415 break;
416 }
417
Harald Welteb9c758b2009-07-05 14:02:46 +0200418 if (!rc && !gsms->receiver)
419 rc = GSM411_RP_CAUSE_MO_NUM_UNASSIGNED;
420
Harald Welte7e310b12009-03-30 20:56:32 +0000421out:
Harald Welte76042182009-08-08 16:03:15 +0200422 sms_free(gsms);
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000423
Harald Welte7e310b12009-03-30 20:56:32 +0000424 return rc;
Daniel Willmanne0fbec82008-12-29 00:44:41 +0000425}
426
Harald Weltef3efc592009-07-27 20:11:35 +0200427static int gsm411_send_rp_ack(struct gsm_trans *trans, u_int8_t msg_ref)
Daniel Willmann471712b2008-12-29 01:54:02 +0000428{
429 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000430
Daniel Willmann471712b2008-12-29 01:54:02 +0000431 DEBUGP(DSMS, "TX: SMS RP ACK\n");
432
Harald Weltef3efc592009-07-27 20:11:35 +0200433 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ACK_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000434}
435
Harald Weltef3efc592009-07-27 20:11:35 +0200436static int gsm411_send_rp_error(struct gsm_trans *trans,
437 u_int8_t msg_ref, u_int8_t cause)
Daniel Willmann471712b2008-12-29 01:54:02 +0000438{
439 struct msgb *msg = gsm411_msgb_alloc();
Daniel Willmann471712b2008-12-29 01:54:02 +0000440
Harald Welte7e310b12009-03-30 20:56:32 +0000441 msgb_tv_put(msg, 1, cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000442
Harald Welte7e310b12009-03-30 20:56:32 +0000443 DEBUGP(DSMS, "TX: SMS RP ERROR (cause %02d)\n", cause);
Daniel Willmann471712b2008-12-29 01:54:02 +0000444
Harald Weltef3efc592009-07-27 20:11:35 +0200445 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_ERROR_MT, msg_ref);
Daniel Willmann471712b2008-12-29 01:54:02 +0000446}
447
Harald Welte7e310b12009-03-30 20:56:32 +0000448/* Receive a 04.11 TPDU inside RP-DATA / user data */
Harald Weltef3efc592009-07-27 20:11:35 +0200449static int gsm411_rx_rp_ud(struct msgb *msg, struct gsm_trans *trans,
450 struct gsm411_rp_hdr *rph,
Harald Welte7e310b12009-03-30 20:56:32 +0000451 u_int8_t src_len, u_int8_t *src,
452 u_int8_t dst_len, u_int8_t *dst,
453 u_int8_t tpdu_len, u_int8_t *tpdu)
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000454{
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000455 int rc = 0;
456
Harald Welte7e310b12009-03-30 20:56:32 +0000457 if (src_len && src)
458 DEBUGP(DSMS, "RP-DATA (MO) with SRC ?!?\n");
459
460 if (!dst_len || !dst || !tpdu_len || !tpdu) {
461 DEBUGP(DSMS, "RP-DATA (MO) without DST or TPDU ?!?\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200462 gsm411_send_rp_error(trans, rph->msg_ref,
Harald Welteb9c758b2009-07-05 14:02:46 +0200463 GSM411_RP_CAUSE_INV_MAND_INF);
Harald Welte7e310b12009-03-30 20:56:32 +0000464 return -EIO;
465 }
466 msg->smsh = tpdu;
467
468 DEBUGP(DSMS, "DST(%u,%s)\n", dst_len, hexdump(dst, dst_len));
Harald Welte7e310b12009-03-30 20:56:32 +0000469
470 rc = gsm340_rx_tpdu(msg);
471 if (rc == 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200472 return gsm411_send_rp_ack(trans, rph->msg_ref);
Harald Welte7e310b12009-03-30 20:56:32 +0000473 else if (rc > 0)
Harald Weltef3efc592009-07-27 20:11:35 +0200474 return gsm411_send_rp_error(trans, rph->msg_ref, rc);
Harald Welte7e310b12009-03-30 20:56:32 +0000475 else
476 return rc;
477}
478
479/* Receive a 04.11 RP-DATA message in accordance with Section 7.3.1.2 */
Harald Weltef3efc592009-07-27 20:11:35 +0200480static int gsm411_rx_rp_data(struct msgb *msg, struct gsm_trans *trans,
481 struct gsm411_rp_hdr *rph)
Harald Welte7e310b12009-03-30 20:56:32 +0000482{
483 u_int8_t src_len, dst_len, rpud_len;
484 u_int8_t *src = NULL, *dst = NULL , *rp_ud = NULL;
485
486 /* in the MO case, this should always be zero length */
487 src_len = rph->data[0];
488 if (src_len)
489 src = &rph->data[1];
490
491 dst_len = rph->data[1+src_len];
492 if (dst_len)
493 dst = &rph->data[1+src_len+1];
494
495 rpud_len = rph->data[1+src_len+1+dst_len];
496 if (rpud_len)
497 rp_ud = &rph->data[1+src_len+1+dst_len+1];
498
Harald Welteb9c758b2009-07-05 14:02:46 +0200499 DEBUGP(DSMS, "RX_RP-DATA: src_len=%u, dst_len=%u ud_len=%u\n",
500 src_len, dst_len, rpud_len);
Harald Weltef3efc592009-07-27 20:11:35 +0200501 return gsm411_rx_rp_ud(msg, trans, rph, src_len, src, dst_len, dst,
Harald Welte7e310b12009-03-30 20:56:32 +0000502 rpud_len, rp_ud);
503}
504
Harald Weltef3efc592009-07-27 20:11:35 +0200505static int gsm411_rx_rp_ack(struct msgb *msg, struct gsm_trans *trans,
506 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200507{
Harald Welte76042182009-08-08 16:03:15 +0200508 struct gsm_sms *sms = trans->sms.sms;
509
Harald Welteb9c758b2009-07-05 14:02:46 +0200510 /* Acnkowledgement to MT RP_DATA, i.e. the MS confirms it
511 * successfully received a SMS. We can now safely mark it as
512 * transmitted */
513
Harald Welte3e0f6172009-07-09 23:52:59 +0200514 /* we need to look-up the transaction based on rph->msg_ref to
515 * identify which particular RP_DATA/SMS-submit was ACKed */
516
Harald Welte76042182009-08-08 16:03:15 +0200517 if (!sms) {
518 DEBUGP(DSMS, "RX RP-ACK (MT) but no sms in transaction?!?\n");
519 put_lchan(trans->lchan);
520 return -EIO;
521 }
522
523 /* mark this SMS as sent in database */
524 db_sms_mark_sent(sms);
525
526 dispatch_signal(SS_SMS, S_SMS_DELIVERED, sms);
527
528 sms_free(sms);
529 trans->sms.sms = NULL;
530
531 put_lchan(trans->lchan);
532
533 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200534}
535
Harald Weltef3efc592009-07-27 20:11:35 +0200536static int gsm411_rx_rp_error(struct msgb *msg, struct gsm_trans *trans,
537 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200538{
Harald Welte76042182009-08-08 16:03:15 +0200539 struct gsm_sms *sms = trans->sms.sms;
Harald Weltef3efc592009-07-27 20:11:35 +0200540 u_int8_t cause_len = rph->data[0];
541 u_int8_t cause = rph->data[1];
542
Harald Welteb9c758b2009-07-05 14:02:46 +0200543 /* Error in response to MT RP_DATA, i.e. the MS did not
544 * successfully receive the SMS. We need to investigate
545 * the cause and take action depending on it */
546
Harald Weltef3efc592009-07-27 20:11:35 +0200547 DEBUGP(DSMS, "RX SMS RP-ERROR Cause=0x%02x\n", cause);
548
Harald Welte3e0f6172009-07-09 23:52:59 +0200549 /* we need to look-up the transaction based on rph->msg_ref to
550 * identify which particular RP_DATA/SMS-submit failed */
551
Harald Welte76042182009-08-08 16:03:15 +0200552 if (!sms) {
553 DEBUGP(DSMS, "RX RP-ERR (MT) but no sms in transaction?!?\n");
554 put_lchan(trans->lchan);
555 return -EIO;
556 }
557
558 sms_free(sms);
559 trans->sms.sms = NULL;
560
561 put_lchan(trans->lchan);
562
Harald Weltef3efc592009-07-27 20:11:35 +0200563 return 0;
Harald Welteb9c758b2009-07-05 14:02:46 +0200564}
565
Harald Weltef3efc592009-07-27 20:11:35 +0200566static int gsm411_rx_rp_smma(struct msgb *msg, struct gsm_trans *trans,
567 struct gsm411_rp_hdr *rph)
Harald Welteb9c758b2009-07-05 14:02:46 +0200568{
Harald Weltef3efc592009-07-27 20:11:35 +0200569 int rc;
570
Harald Welteb9c758b2009-07-05 14:02:46 +0200571 /* MS tells us that it has memory for more SMS, we need
572 * to check if we have any pending messages for it and then
573 * transfer those */
Harald Welte76042182009-08-08 16:03:15 +0200574 dispatch_signal(SS_SMS, S_SMS_SMMA, trans->subscr);
Harald Weltef3efc592009-07-27 20:11:35 +0200575
576 rc = gsm411_send_rp_ack(trans, rph->msg_ref);
577 trans->sms.rp_state = GSM411_RPS_IDLE;
578
579 return rc;
Harald Welteb9c758b2009-07-05 14:02:46 +0200580}
581
Harald Weltef3efc592009-07-27 20:11:35 +0200582static int gsm411_rx_cp_data(struct msgb *msg, struct gsm48_hdr *gh,
583 struct gsm_trans *trans)
Harald Welte7e310b12009-03-30 20:56:32 +0000584{
Daniel Willmann471712b2008-12-29 01:54:02 +0000585 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000586 u_int8_t msg_type = rp_data->msg_type & 0x07;
Harald Welte7e310b12009-03-30 20:56:32 +0000587 int rc = 0;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000588
589 switch (msg_type) {
590 case GSM411_MT_RP_DATA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200591 DEBUGP(DSMS, "RX SMS RP-DATA (MO)\n");
592 /* start TR2N and enter 'wait to send RP-ACK state' */
593 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
594 rc = gsm411_rx_rp_data(msg, trans, rp_data);
Harald Welte7e310b12009-03-30 20:56:32 +0000595 break;
596 case GSM411_MT_RP_ACK_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200597 DEBUGP(DSMS,"RX SMS RP-ACK (MO)\n");
598 rc = gsm411_rx_rp_ack(msg, trans, rp_data);
Harald Welteb9c758b2009-07-05 14:02:46 +0200599 break;
Harald Welte7e310b12009-03-30 20:56:32 +0000600 case GSM411_MT_RP_SMMA_MO:
Harald Weltef3efc592009-07-27 20:11:35 +0200601 DEBUGP(DSMS, "RX SMS RP-SMMA\n");
602 /* start TR2N and enter 'wait to send RP-ACK state' */
603 trans->sms.rp_state = GSM411_RPS_WAIT_TO_TX_RP_ACK;
604 rc = gsm411_rx_rp_smma(msg, trans, rp_data);
605 break;
606 case GSM411_MT_RP_ERROR_MO:
607 rc = gsm411_rx_rp_error(msg, trans, rp_data);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000608 break;
609 default:
Harald Welte7e310b12009-03-30 20:56:32 +0000610 DEBUGP(DSMS, "Invalid RP type 0x%02x\n", msg_type);
Harald Weltef3efc592009-07-27 20:11:35 +0200611 rc = gsm411_send_rp_error(trans, rp_data->msg_ref,
612 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000613 break;
614 }
615
616 return rc;
617}
618
Harald Weltef3efc592009-07-27 20:11:35 +0200619/* send CP-ACK to given transaction */
620static int gsm411_tx_cp_ack(struct gsm_trans *trans)
621{
622 struct msgb *msg = gsm411_msgb_alloc();
623
624 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ACK);
625}
626
627static int gsm411_tx_cp_error(struct gsm_trans *trans, u_int8_t cause)
628{
629 struct msgb *msg = gsm411_msgb_alloc();
630 u_int8_t *causep;
631
Harald Welte76042182009-08-08 16:03:15 +0200632 causep = msgb_put(msg, 1);
Harald Weltef3efc592009-07-27 20:11:35 +0200633 *causep = cause;
634
635 return gsm411_cp_sendmsg(msg, trans, GSM411_MT_CP_ERROR);
636}
637
638/* Entry point for incoming GSM48_PDISC_SMS from abis_rsl.c */
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000639int gsm0411_rcv_sms(struct msgb *msg)
640{
641 struct gsm48_hdr *gh = msgb_l3(msg);
642 u_int8_t msg_type = gh->msg_type;
Harald Weltef3efc592009-07-27 20:11:35 +0200643 u_int8_t transaction_id = ((gh->proto_discr >> 4) ^ 0x8); /* flip */
644 struct gsm_lchan *lchan = msg->lchan;
645 struct gsm_trans *trans;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000646 int rc = 0;
647
Harald Weltef3efc592009-07-27 20:11:35 +0200648 if (!lchan->subscr)
649 return -EIO;
650 /* FIXME: send some error message */
651
652 trans = trans_find_by_id(lchan->subscr, GSM48_PDISC_SMS,
653 transaction_id);
654 if (!trans) {
655 DEBUGP(DSMS, "Unknown transaction ID %x, "
656 "creating new trans\n", transaction_id);
657 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
658 transaction_id, new_callref++);
659 if (!trans) {
660 DEBUGP(DSMS, "No memory for trans\n");
661 /* FIXME: send some error message */
662 return -ENOMEM;
663 }
664 trans->sms.cp_state = GSM411_CPS_IDLE;
665 trans->sms.rp_state = GSM411_RPS_IDLE;
666 trans->sms.is_mt = 0;
667
668 trans->lchan = lchan;
669 use_lchan(lchan);
670 }
671
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000672 switch(msg_type) {
673 case GSM411_MT_CP_DATA:
Harald Weltef3efc592009-07-27 20:11:35 +0200674 DEBUGP(DSMS, "RX SMS CP-DATA\n");
675 if (!trans->sms.is_mt) {
676 /* 5.2.3.1.3: MO state exists when SMC has received
677 * CP-DATA, including sending of the assoc. CP-ACK */
678 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
679 }
680
681 rc = gsm411_rx_cp_data(msg, gh, trans);
682 /* Send CP-ACK or CP-ERORR in response */
683 if (rc < 0) {
684 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_NET_FAIL);
685 } else
686 rc = gsm411_tx_cp_ack(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000687 break;
688 case GSM411_MT_CP_ACK:
Harald Weltef3efc592009-07-27 20:11:35 +0200689 /* previous CP-DATA in this transaction was confirmed */
690 DEBUGP(DSMS, "RX SMS CP-ACK\n");
691 if (!trans->sms.is_mt) {
692 /* 5.2.3.1.3: MO state exists when SMC has received
693 * CP-ACK */
694 trans->sms.cp_state = GSM411_CPS_MM_ESTABLISHED;
695 /* FIXME: we have sont one CP-DATA, which was now
696 * acknowledged. Check if we want to transfer more,
697 * i.e. multi-part message */
698 trans->sms.cp_state = GSM411_CPS_IDLE;
699 trans_free(trans);
700 }
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000701 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000702 case GSM411_MT_CP_ERROR:
Harald Weltef3efc592009-07-27 20:11:35 +0200703 DEBUGP(DSMS, "RX SMS CP-ERROR, cause 0x%02x\n", gh->data[0]);
704 trans->sms.cp_state = GSM411_CPS_IDLE;
705 trans_free(trans);
Daniel Willmannbb16e8e2008-12-29 03:53:50 +0000706 break;
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000707 default:
Harald Weltef3efc592009-07-27 20:11:35 +0200708 DEBUGP(DSMS, "RX Unimplemented CP msg_type: 0x%02x\n", msg_type);
709 rc = gsm411_tx_cp_error(trans, GSM411_CP_CAUSE_MSGTYPE_NOTEXIST);
710 trans_free(trans);
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000711 break;
712 }
713
Daniel Willmann8b3390e2008-12-28 00:31:09 +0000714 return rc;
715}
716
Harald Welte8c2e36e2008-12-30 15:00:14 +0000717#if 0
Daniel Willmann3b3f0012008-12-30 13:56:46 +0000718/* Test TPDU - ALL YOUR */
719static u_int8_t tpdu_test[] = {
720 0x04, 0x04, 0x81, 0x32, 0x24, 0x00, 0x00, 0x80, 0x21, 0x03, 0x41, 0x24,
721 0x32, 0x40, 0x1F, 0x41, 0x26, 0x13, 0x94, 0x7D, 0x56, 0xA5, 0x20, 0x28,
722 0xF2, 0xE9, 0x2C, 0x82, 0x82, 0xD2, 0x22, 0x48, 0x58, 0x64, 0x3E, 0x9D,
723 0x47, 0x10, 0xF5, 0x09, 0xAA, 0x4E, 0x01
Daniel Willmanne2a728d2008-12-30 14:03:09 +0000724};
Harald Welte8c2e36e2008-12-30 15:00:14 +0000725#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000726
Harald Welte76042182009-08-08 16:03:15 +0200727/* Take a SMS in gsm_sms structure and send it through lchan */
728int gsm411_send_sms_lchan(struct gsm_lchan *lchan, struct gsm_sms *sms)
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000729{
730 struct msgb *msg = gsm411_msgb_alloc();
Harald Weltef3efc592009-07-27 20:11:35 +0200731 struct gsm_trans *trans;
Harald Welte76042182009-08-08 16:03:15 +0200732 u_int8_t *data, *rp_ud_len;
Harald Welte87f5d632009-07-04 17:39:00 +0200733 u_int8_t msg_ref = 42;
Harald Welte76042182009-08-08 16:03:15 +0200734 u_int8_t transaction_id = 1; /* FIXME: random */
735 int rc;
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000736
737 msg->lchan = lchan;
738
Harald Welte76042182009-08-08 16:03:15 +0200739 DEBUGP(DSMS, "send_sms_lchan()\n");
Harald Weltef3efc592009-07-27 20:11:35 +0200740
Harald Welte76042182009-08-08 16:03:15 +0200741 /* FIXME: allocate transaction with message reference */
742 trans = trans_alloc(lchan->subscr, GSM48_PDISC_SMS,
743 transaction_id, new_callref++);
744 if (!trans) {
745 DEBUGP(DSMS, "No memory for trans\n");
746 /* FIXME: send some error message */
747 return -ENOMEM;
748 }
749 trans->sms.cp_state = GSM411_CPS_IDLE;
750 trans->sms.rp_state = GSM411_RPS_IDLE;
751 trans->sms.is_mt = 1;
752 trans->sms.sms = sms;
753
754 trans->lchan = lchan;
755 use_lchan(lchan);
756
757 /* Hardcode SMSC Originating Address for now */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000758 data = (u_int8_t *)msgb_put(msg, 8);
Harald Welte87f5d632009-07-04 17:39:00 +0200759 data[0] = 0x07; /* originator length == 7 */
Harald Welteb9c758b2009-07-05 14:02:46 +0200760 data[1] = 0x91; /* type of number: international, ISDN */
761 data[2] = 0x44; /* 447785016005 */
Daniel Willmanna3e29842008-12-29 16:03:54 +0000762 data[3] = 0x77;
763 data[4] = 0x58;
764 data[5] = 0x10;
765 data[6] = 0x06;
766 data[7] = 0x50;
Harald Welte87f5d632009-07-04 17:39:00 +0200767
768 /* Hardcoded Destination Address */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000769 data = (u_int8_t *)msgb_put(msg, 1);
Harald Welte87f5d632009-07-04 17:39:00 +0200770 data[0] = 0; /* destination length == 0 */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000771
Harald Welte76042182009-08-08 16:03:15 +0200772 /* obtain a pointer for the rp_ud_len, so we can fill it later */
773 rp_ud_len = (u_int8_t *)msgb_put(msg, 1);
Daniel Willmann4a1e8792008-12-29 06:23:56 +0000774
Harald Welte76042182009-08-08 16:03:15 +0200775#if 1
776 /* generate the 03.40 TPDU */
777 rc = gsm340_gen_tpdu(msg, sms);
778 if (rc < 0) {
779 msgb_free(msg);
780 return rc;
781 }
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000782
Harald Welte76042182009-08-08 16:03:15 +0200783 *rp_ud_len = rc;
784#else
785 data = msgb_put(msg, sizeof(tpdu_test));
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000786 memcpy(data, tpdu_test, sizeof(tpdu_test));
Harald Welte76042182009-08-08 16:03:15 +0200787 *rp_ud_len = sizeof(tpdu_test);
788#endif
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000789
Harald Welte76042182009-08-08 16:03:15 +0200790 DEBUGP(DSMS, "TX: SMS DELIVER\n");
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000791
Harald Weltef3efc592009-07-27 20:11:35 +0200792 return gsm411_rp_sendmsg(msg, trans, GSM411_MT_RP_DATA_MT, msg_ref);
793 /* FIXME: enter 'wait for RP-ACK' state, start TR1N */
Daniel Willmann6fe997e2008-12-29 04:20:41 +0000794}
Harald Weltef3efc592009-07-27 20:11:35 +0200795
Harald Welte76042182009-08-08 16:03:15 +0200796/* paging callback */
797static int paging_cb_send_sms(unsigned int hooknum, unsigned int event,
798 struct msgb *msg, void *_lchan, void *_sms)
Harald Weltef3efc592009-07-27 20:11:35 +0200799{
Harald Welte76042182009-08-08 16:03:15 +0200800 struct gsm_lchan *lchan = _lchan;
801 struct gsm_sms *sms = _sms;
802 int rc;
Harald Weltef3efc592009-07-27 20:11:35 +0200803
Harald Welte76042182009-08-08 16:03:15 +0200804 DEBUGP(DSMS, "paging_cb_send_sms(hooknum=%u, event=%u, msg=%p,"
805 "lchan=%p, sms=%p)\n", hooknum, event, msg, lchan, sms);
806
807 if (hooknum != GSM_HOOK_RR_PAGING)
808 return -EINVAL;
809
810 switch (event) {
811 case GSM_PAGING_SUCCEEDED:
812 /* Paging aborted without lchan ?!? */
813 if (!lchan) {
814 sms_free(sms);
815 rc = -EIO;
816 break;
817 }
818 rc = gsm411_send_sms_lchan(lchan, sms);
819 break;
820 case GSM_PAGING_EXPIRED:
821 sms_free(sms);
822 rc = -ETIMEDOUT;
823 break;
824 default:
825 rc = -EINVAL;
826 break;
827 }
828
829 return rc;
830}
831
832int gsm411_send_sms_subscr(struct gsm_subscriber *subscr,
833 struct gsm_sms *sms)
834{
835 /* check if we already have an open lchan to the subscriber.
836 * if yes, send the SMS this way */
837 //if (subscr->lchan)
838 //return gsm411_send_sms_lchan(subscr->lchan, sms);
839
840 /* if not, we have to start paging */
841 paging_request(subscr->net, subscr, RSL_CHANNEED_SDCCH,
842 paging_cb_send_sms, sms);
843
844 return 0;
845}
Harald Welte3366a942009-07-28 00:44:49 +0200846
Harald Welte7bfc2672009-07-28 00:41:45 +0200847static __attribute__((constructor)) void on_dso_load_sms(void)
848{
Harald Welte7bfc2672009-07-28 00:41:45 +0200849 tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
850}