blob: d5ca9238b3f6c7e1f643028659f4a77f056c4e5a [file] [log] [blame]
Andreas Eversbergc1a91a82011-10-28 11:05:37 +02001/* Point-to-Point (PP) Short Message Service (SMS)
2 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
4
5/* (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
6 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
7 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
8 * (C) 2010 by On-Waves
9 * (C) 2011 by Andreas Eversberg <jolly@eversberg.eu>
10 *
11 * All Rights Reserved
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Affero General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Affero General Public License for more details.
22 *
23 * You should have received a copy of the GNU Affero General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27
28/* Notes on msg:
29 *
30 * Messages from lower layer are freed by lower layer.
31 *
32 * Messages to upper layer are freed after upper layer call returns, so upper
33 * layer cannot use data after returning. Upper layer must not free the msg.
34 *
35 * This implies: Lower layer messages can be forwarded to upper layer.
36 *
37 * Upper layer messages are freed by lower layer, so they must not be freed
38 * after calling lower layer.
39 *
40 *
41 * Notes on release:
42 *
43 * Sending Abort/Release (MNSMS-ABORT-REQ or MNSMS-REL-REQ) may cause the
44 * lower layer to become IDLE. Then it is allowed to destroy this instance,
45 * so sending this this MUST be the last thing that is done.
46 *
47 */
48
49
50#include <string.h>
51#include <errno.h>
52#include <osmocom/core/msgb.h>
53#include <osmocom/core/logging.h>
54#include <osmocom/core/timer.h>
55#include <osmocom/gsm/tlv.h>
56
57#include <osmocom/gsm/gsm0411_utils.h>
58#include <osmocom/gsm/gsm0411_smc.h>
59#include <osmocom/gsm/gsm0411_smr.h>
60#include <osmocom/gsm/protocol/gsm_04_08.h>
61
62static void rp_timer_expired(void *data);
63
64/* init a new instance */
65void gsm411_smr_init(struct gsm411_smr_inst *inst, int network,
66 int (*rl_recv) (struct gsm411_smr_inst *inst, int msg_type,
67 struct msgb *msg),
68 int (*mn_send) (struct gsm411_smr_inst *inst, int msg_type,
69 struct msgb *msg))
70{
71 memset(inst, 0, sizeof(*inst));
72 inst->network = network;
73 inst->rp_state = GSM411_RPS_IDLE;
74 inst->rl_recv = rl_recv;
75 inst->mn_send = mn_send;
76 inst->rp_timer.data = inst;
77 inst->rp_timer.cb = rp_timer_expired;
78
79 LOGP(DLSMS, LOGL_INFO, "New SMR instance created\n");
80}
81
82/* clear instance */
83void gsm411_smr_clear(struct gsm411_smr_inst *inst)
84{
85 LOGP(DLSMS, LOGL_INFO, "Clear SMR instance\n");
86
87 osmo_timer_del(&inst->rp_timer);
88}
89
90const char *smr_state_names[] = {
91 "IDLE",
92 "WAIT_FOR_RP_ACK",
93 "illegal state 2"
94 "WAIT_TO_TX_RP_ACK",
95 "WAIT_FOR_RETRANS_T",
96};
97
98const struct value_string gsm411_rp_cause_strs[] = {
99 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
100 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
101 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
102 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
103 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
104 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
105 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
106 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
107 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
108 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
109 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
110 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
111 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
112 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
113 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
114 /* valid only for MT */
115 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
116 /* valid for both directions */
117 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
118 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
119 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
120 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existant" },
121 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
122 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
123 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
124 { 0, NULL }
125};
126
127static void new_rp_state(struct gsm411_smr_inst *inst,
128 enum gsm411_rp_state state)
129{
130 LOGP(DLSMS, LOGL_INFO, "New RP state %s -> %s\n",
131 smr_state_names[inst->rp_state], smr_state_names[state]);
132 inst->rp_state = state;
133
134 /* stop timer when going idle */
135 if (state == GSM411_RPS_IDLE)
136 osmo_timer_del(&inst->rp_timer);
137}
138
139/* Prefix msg with a RP-DATA header and send as CP-DATA */
140static int gsm411_rp_sendmsg(struct gsm411_smr_inst *inst, struct msgb *msg,
141 uint8_t rp_msg_type, uint8_t rp_msg_ref,
142 int mnsms_msg_type)
143{
144 struct gsm411_rp_hdr *rp;
145 uint8_t len = msg->len;
146
147 /* GSM 04.11 RP-DATA header */
148 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
149 rp->len = len + 2;
150 rp->msg_type = rp_msg_type;
151 rp->msg_ref = rp_msg_ref; /* FIXME: Choose randomly */
152
153 return inst->mn_send(inst, mnsms_msg_type, msg);
154}
155
156static int gsm411_send_rp_error(struct gsm411_smr_inst *inst,
157 uint8_t msg_ref, uint8_t cause)
158{
159 struct msgb *msg = gsm411_msgb_alloc();
160
161 msgb_tv_put(msg, 1, cause);
162
163 LOGP(DLSMS, LOGL_NOTICE, "TX: SMS RP ERROR, cause %d (%s)\n", cause,
164 get_value_string(gsm411_rp_cause_strs, cause));
165
166 return gsm411_rp_sendmsg(inst, msg,
167 (inst->network) ? GSM411_MT_RP_ERROR_MT : GSM411_MT_RP_ERROR_MO,
168 msg_ref, GSM411_MNSMS_DATA_REQ);
169}
170
171static int gsm411_send_release(struct gsm411_smr_inst *inst)
172{
173 struct msgb *msg = gsm411_msgb_alloc();
174
175 LOGP(DLSMS, LOGL_NOTICE, "TX: MNSMS-REL-REQ\n");
176
177 return inst->mn_send(inst, GSM411_MNSMS_REL_REQ, msg);
178}
179
180static int gsm411_send_abort(struct gsm411_smr_inst *inst)
181{
182 struct msgb *msg = gsm411_msgb_alloc();
183
184 msgb_tv_put(msg, 1, 111); //FIXME: better idea ? */
185 LOGP(DLSMS, LOGL_NOTICE, "TX: MNSMS-ABORT-REQ\n");
186
187 return inst->mn_send(inst, GSM411_MNSMS_ABORT_REQ, msg);
188}
189
190static int gsm411_send_report(struct gsm411_smr_inst *inst)
191{
192 struct msgb *msg = gsm411_msgb_alloc();
193
194 LOGP(DLSMS, LOGL_NOTICE, "send empty SM_RL_REPORT_IND\n");
195
196 return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
197}
198
199static int gsm411_rl_data_req(struct gsm411_smr_inst *inst, struct msgb *msg)
200{
201 LOGP(DLSMS, LOGL_DEBUG, "TX SMS RP-DATA\n");
202 /* start TR1N and enter 'wait for RP-ACK state' */
203 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR1M);
204 new_rp_state(inst, GSM411_RPS_WAIT_FOR_RP_ACK);
205
206 return inst->mn_send(inst, GSM411_MNSMS_EST_REQ, msg);
207}
208
209static int gsm411_rl_report_req(struct gsm411_smr_inst *inst, struct msgb *msg)
210{
211 LOGP(DLSMS, LOGL_DEBUG, "TX SMS REPORT\n");
212 new_rp_state(inst, GSM411_RPS_IDLE);
213
214 inst->mn_send(inst, GSM411_MNSMS_DATA_REQ, msg);
215 gsm411_send_release(inst);
216 return 0;
217}
218
219static int gsm411_mnsms_est_ind(struct gsm411_smr_inst *inst, struct msgb *msg)
220{
221 struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
222 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
223 uint8_t msg_type = rp_data->msg_type & 0x07;
224 int rc;
225
226 /* check direction */
227 if (inst->network == (msg_type & 1)) {
228 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
229 gsm411_send_rp_error(inst, rp_data->msg_ref,
230 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
231 new_rp_state(inst, GSM411_RPS_IDLE);
232 gsm411_send_release(inst);
233 return -EINVAL;
234 }
235
236 switch (msg_type) {
237 case GSM411_MT_RP_DATA_MT:
238 case GSM411_MT_RP_DATA_MO:
239 LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-DATA\n");
240 /* start TR2N and enter 'wait to send RP-ACK state' */
241 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
242 new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
243 rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
244 break;
245 case GSM411_MT_RP_SMMA_MO:
246 LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-SMMA\n");
247 /* start TR2N and enter 'wait to send RP-ACK state' */
248 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
249 new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
250 rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
251 break;
252 default:
253 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
254 gsm411_send_rp_error(inst, rp_data->msg_ref,
255 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
256 new_rp_state(inst, GSM411_RPS_IDLE);
257 rc = -EINVAL;
258 break;
259 }
260
261 return rc;
262}
263
264static int gsm411_mnsms_data_ind_tx(struct gsm411_smr_inst *inst,
265 struct msgb *msg)
266{
267 struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
268 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
269 uint8_t msg_type = rp_data->msg_type & 0x07;
270 int rc;
271
272 /* check direction */
273 if (inst->network == (msg_type & 1)) {
274 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
275 gsm411_send_rp_error(inst, rp_data->msg_ref,
276 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
277 new_rp_state(inst, GSM411_RPS_IDLE);
278 gsm411_send_release(inst);
279 return -EINVAL;
280 }
281
282 switch (msg_type) {
283 case GSM411_MT_RP_ACK_MO:
284 case GSM411_MT_RP_ACK_MT:
285 LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-ACK\n");
286 new_rp_state(inst, GSM411_RPS_IDLE);
287 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
288 gsm411_send_release(inst);
289 return 0;
290 case GSM411_MT_RP_ERROR_MO:
291 case GSM411_MT_RP_ERROR_MT:
292 LOGP(DLSMS, LOGL_DEBUG, "RX SMS RP-ERROR\n");
293 new_rp_state(inst, GSM411_RPS_IDLE);
294 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
295 gsm411_send_release(inst);
296 return 0;
297 default:
298 LOGP(DLSMS, LOGL_NOTICE, "Invalid RP type 0x%02x\n", msg_type);
299 gsm411_send_rp_error(inst, rp_data->msg_ref,
300 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
301 new_rp_state(inst, GSM411_RPS_IDLE);
302 gsm411_send_release(inst);
303 return -EINVAL;
304 }
305
306 return rc;
307}
308
309static int gsm411_mnsms_error_ind_tx(struct gsm411_smr_inst *inst,
310 struct msgb *msg)
311{
312 LOGP(DLSMS, LOGL_DEBUG, "RX SMS MNSMS-ERROR-IND\n");
313 new_rp_state(inst, GSM411_RPS_IDLE);
314 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
315 gsm411_send_release(inst);
316 return 0;
317}
318
319static int gsm411_mnsms_error_ind_rx(struct gsm411_smr_inst *inst,
320 struct msgb *msg)
321{
322 LOGP(DLSMS, LOGL_DEBUG, "RX SMS MNSMS-ERROR-IND\n");
323 new_rp_state(inst, GSM411_RPS_IDLE);
324 return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
325}
326
327/* SMR TR1* is expired */
328static void rp_timer_expired(void *data)
329{
330 struct gsm411_smr_inst *inst = data;
331
332 if (inst->rp_state == GSM411_RPS_WAIT_TO_TX_RP_ACK)
333 LOGP(DLSMS, LOGL_DEBUG, "TR2N\n");
334 else
335 LOGP(DLSMS, LOGL_DEBUG, "TR1N\n");
336 gsm411_send_report(inst);
337 gsm411_send_abort(inst);
338}
339
340/* statefull handling for SM-RL SAP messages */
341static struct smrdownstate {
342 uint32_t states;
343 int type;
344 const char *name;
345 int (*rout) (struct gsm411_smr_inst *inst,
346 struct msgb *msg);
347} smrdownstatelist[] = {
348 /* data request */
349 {SBIT(GSM411_RPS_IDLE),
350 GSM411_SM_RL_DATA_REQ,
351 "SM-RL-DATA_REQ", gsm411_rl_data_req},
352
353 /* report request */
354 {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
355 GSM411_SM_RL_REPORT_REQ,
356 "SM-RL-REPORT_REQ", gsm411_rl_report_req},
357};
358
359#define SMRDOWNSLLEN \
360 (sizeof(smrdownstatelist) / sizeof(struct smrdownstate))
361
362/* message from upper layer */
363int gsm411_smr_send(struct gsm411_smr_inst *inst, int msg_type,
364 struct msgb *msg)
365{
366 int i, rc;
367
368 /* find function for current state and message */
369 for (i = 0; i < SMRDOWNSLLEN; i++) {
370 if ((msg_type == smrdownstatelist[i].type)
371 && (SBIT(inst->rp_state) & smrdownstatelist[i].states))
372 break;
373 }
374 if (i == SMRDOWNSLLEN) {
375 LOGP(DLSMS, LOGL_NOTICE, "Message %u unhandled at this state "
376 "%s.\n", msg_type, smr_state_names[inst->rp_state]);
377 msgb_free(msg);
378 return 0;
379 }
380
381 LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
382 smrdownstatelist[i].name, smr_state_names[inst->rp_state]);
383
384 rc = smrdownstatelist[i].rout(inst, msg);
385
386 return rc;
387}
388
389/* statefull handling for MMSMS SAP messages */
390static struct smrdatastate {
391 uint32_t states;
392 int type;
393 const char *name;
394 int (*rout) (struct gsm411_smr_inst *inst,
395 struct msgb *msg);
396} smrdatastatelist[] = {
397 /* establish indication */
398 {SBIT(GSM411_RPS_IDLE),
399 GSM411_MNSMS_EST_IND,
400 "MNSMS-EST-IND", gsm411_mnsms_est_ind},
401
402 /* data indication */
403 {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
404 GSM411_MNSMS_DATA_IND,
405 "MNSMS-DATA-IND", gsm411_mnsms_data_ind_tx},
406
407 /* error indication */
408 {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
409 GSM411_MNSMS_ERROR_IND,
410 "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_tx},
411
412 /* error indication */
413 {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
414 GSM411_MNSMS_ERROR_IND,
415 "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_rx},
416
417};
418
419#define SMRDATASLLEN \
420 (sizeof(smrdatastatelist) / sizeof(struct smrdatastate))
421
422/* message from lower layer
423 * WARNING: We must not free msg, since it will be performed by the
424 * lower layer. */
425int gsm411_smr_recv(struct gsm411_smr_inst *inst, int msg_type,
426 struct msgb *msg)
427{
428 int i, rc;
429
430 /* find function for current state and message */
431 for (i = 0; i < SMRDATASLLEN; i++) {
432 /* state must machtch, MM message must match
433 * CP msg must match only in case of MMSMS_DATA_IND
434 */
435 if ((msg_type == smrdatastatelist[i].type)
436 && (SBIT(inst->rp_state) & smrdatastatelist[i].states))
437 break;
438 }
439 if (i == SMRDATASLLEN) {
440 LOGP(DLSMS, LOGL_NOTICE, "Message %u unhandled at this state "
441 "%s.\n", msg_type, smr_state_names[inst->rp_state]);
442 return 0;
443 }
444
445 LOGP(DLSMS, LOGL_INFO, "Message %s received in state %s\n",
446 smrdatastatelist[i].name, smr_state_names[inst->rp_state]);
447
448 rc = smrdatastatelist[i].rout(inst, msg);
449
450 return rc;
451}