blob: 03cf0051ed3828c72f36098d4ffb2a25688a5181 [file] [log] [blame]
Harald Welte55d724a2017-10-16 18:25:45 +02001/* Point-to-Point (PP) Short Message Service (SMS).
Andreas Eversbergc1a91a82011-10-28 11:05:37 +02002 * Support on Mobile Radio Interface
3 * 3GPP TS 04.11 version 7.1.0 Release 1998 / ETSI TS 100 942 V7.1.0 */
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02004/*
5 * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
Andreas Eversbergc1a91a82011-10-28 11:05:37 +02006 * (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 *
Harald Weltee08da972017-11-13 01:00:26 +090013 * SPDX-License-Identifier: GPL-2.0+
14 *
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020015 * This program is free software; you can redistribute it and/or modify
Harald Welte388fb032014-10-26 20:42:49 +010016 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020018 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte388fb032014-10-26 20:42:49 +010023 * GNU General Public License for more details.
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020024 *
Harald Welte388fb032014-10-26 20:42:49 +010025 * You should have received a copy of the GNU General Public License
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020026 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 *
28 */
29
30/* Notes on msg:
31 *
32 * Messages from lower layer are freed by lower layer.
33 *
34 * Messages to upper layer are freed after upper layer call returns, so upper
35 * layer cannot use data after returning. Upper layer must not free the msg.
36 *
37 * This implies: Lower layer messages can be forwarded to upper layer.
38 *
39 * Upper layer messages are freed by lower layer, so they must not be freed
40 * after calling lower layer.
41 *
42 *
43 * Notes on release:
44 *
45 * Sending Abort/Release (MNSMS-ABORT-REQ or MNSMS-REL-REQ) may cause the
46 * lower layer to become IDLE. Then it is allowed to destroy this instance,
Holger Hans Peter Freyther1c4c3732012-11-22 00:33:52 +010047 * so sending this MUST be the last thing that is done.
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020048 *
49 */
50
51
Harald Welte701968f2020-07-30 21:33:48 +020052#include <sys/types.h>
53#include <inttypes.h>
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020054#include <string.h>
55#include <errno.h>
56#include <osmocom/core/msgb.h>
57#include <osmocom/core/logging.h>
58#include <osmocom/core/timer.h>
59#include <osmocom/gsm/tlv.h>
60
61#include <osmocom/gsm/gsm0411_utils.h>
62#include <osmocom/gsm/gsm0411_smc.h>
63#include <osmocom/gsm/gsm0411_smr.h>
64#include <osmocom/gsm/protocol/gsm_04_08.h>
65
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +010066#define SMR_LOG_STR "SMR(%" PRIu64 ") "
67
Harald Welte96e2a002017-06-12 21:44:18 +020068/*! \addtogroup sms
69 * @{
Harald Welte55d724a2017-10-16 18:25:45 +020070 * \file gsm0411_smr.c
Harald Welte96e2a002017-06-12 21:44:18 +020071 */
72
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020073static void rp_timer_expired(void *data);
74
75/* init a new instance */
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +010076void gsm411_smr_init(struct gsm411_smr_inst *inst, uint64_t id, int network,
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020077 int (*rl_recv) (struct gsm411_smr_inst *inst, int msg_type,
78 struct msgb *msg),
79 int (*mn_send) (struct gsm411_smr_inst *inst, int msg_type,
80 struct msgb *msg))
81{
82 memset(inst, 0, sizeof(*inst));
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +010083 inst->id = id;
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020084 inst->network = network;
85 inst->rp_state = GSM411_RPS_IDLE;
86 inst->rl_recv = rl_recv;
87 inst->mn_send = mn_send;
Pablo Neira Ayuso44f423f2017-05-08 18:00:28 +020088 osmo_timer_setup(&inst->rp_timer, rp_timer_expired, inst);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020089
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +010090 LOGP(DLSMS, LOGL_INFO,
Holger Hans Peter Freyther68f94472012-12-01 12:51:34 +010091 SMR_LOG_STR "instance created for %s.\n",
92 inst->id, inst->network ? "network" : "mobile");
Andreas Eversbergc1a91a82011-10-28 11:05:37 +020093}
94
95/* clear instance */
96void gsm411_smr_clear(struct gsm411_smr_inst *inst)
97{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +010098 LOGP(DLSMS, LOGL_INFO,
99 SMR_LOG_STR "clearing SMR instance\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200100
101 osmo_timer_del(&inst->rp_timer);
102}
103
Holger Hans Peter Freyther61d33922014-05-23 08:49:34 +0200104static const char *smr_state_names[] = {
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200105 "IDLE",
106 "WAIT_FOR_RP_ACK",
Holger Hans Peter Freytherda73aa62014-05-23 08:51:22 +0200107 "illegal state 2",
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200108 "WAIT_TO_TX_RP_ACK",
109 "WAIT_FOR_RETRANS_T",
110};
111
112const struct value_string gsm411_rp_cause_strs[] = {
113 { GSM411_RP_CAUSE_MO_NUM_UNASSIGNED, "(MO) Number not assigned" },
114 { GSM411_RP_CAUSE_MO_OP_DET_BARR, "(MO) Operator determined barring" },
115 { GSM411_RP_CAUSE_MO_CALL_BARRED, "(MO) Call barred" },
116 { GSM411_RP_CAUSE_MO_SMS_REJECTED, "(MO) SMS rejected" },
117 { GSM411_RP_CAUSE_MO_DEST_OUT_OF_ORDER, "(MO) Destination out of order" },
118 { GSM411_RP_CAUSE_MO_UNIDENTIFIED_SUBSCR, "(MO) Unidentified subscriber" },
119 { GSM411_RP_CAUSE_MO_FACILITY_REJ, "(MO) Facility reject" },
120 { GSM411_RP_CAUSE_MO_UNKNOWN_SUBSCR, "(MO) Unknown subscriber" },
121 { GSM411_RP_CAUSE_MO_NET_OUT_OF_ORDER, "(MO) Network out of order" },
122 { GSM411_RP_CAUSE_MO_TEMP_FAIL, "(MO) Temporary failure" },
123 { GSM411_RP_CAUSE_MO_CONGESTION, "(MO) Congestion" },
124 { GSM411_RP_CAUSE_MO_RES_UNAVAIL, "(MO) Resource unavailable" },
125 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTSUBSCR, "(MO) Requested facility not subscribed" },
126 { GSM411_RP_CAUSE_MO_REQ_FAC_NOTIMPL, "(MO) Requested facility not implemented" },
127 { GSM411_RP_CAUSE_MO_INTERWORKING, "(MO) Interworking" },
128 /* valid only for MT */
129 { GSM411_RP_CAUSE_MT_MEM_EXCEEDED, "(MT) Memory Exceeded" },
130 /* valid for both directions */
131 { GSM411_RP_CAUSE_INV_TRANS_REF, "Invalid Transaction Reference" },
132 { GSM411_RP_CAUSE_SEMANT_INC_MSG, "Semantically Incorrect Message" },
133 { GSM411_RP_CAUSE_INV_MAND_INF, "Invalid Mandatory Information" },
Vadim Yanitskiy65954ba2020-10-29 18:08:52 +0700134 { GSM411_RP_CAUSE_MSGTYPE_NOTEXIST, "Message Type non-existent" },
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200135 { GSM411_RP_CAUSE_MSG_INCOMP_STATE, "Message incompatible with protocol state" },
136 { GSM411_RP_CAUSE_IE_NOTEXIST, "Information Element not existing" },
137 { GSM411_RP_CAUSE_PROTOCOL_ERR, "Protocol Error" },
138 { 0, NULL }
139};
140
141static void new_rp_state(struct gsm411_smr_inst *inst,
142 enum gsm411_rp_state state)
143{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100144 LOGP(DLSMS, LOGL_INFO,
145 SMR_LOG_STR "new RP state %s -> %s\n", inst->id,
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200146 smr_state_names[inst->rp_state], smr_state_names[state]);
147 inst->rp_state = state;
148
149 /* stop timer when going idle */
150 if (state == GSM411_RPS_IDLE)
151 osmo_timer_del(&inst->rp_timer);
152}
153
154/* Prefix msg with a RP-DATA header and send as CP-DATA */
155static int gsm411_rp_sendmsg(struct gsm411_smr_inst *inst, struct msgb *msg,
156 uint8_t rp_msg_type, uint8_t rp_msg_ref,
157 int mnsms_msg_type)
158{
159 struct gsm411_rp_hdr *rp;
160 uint8_t len = msg->len;
161
162 /* GSM 04.11 RP-DATA header */
163 rp = (struct gsm411_rp_hdr *)msgb_push(msg, sizeof(*rp));
164 rp->len = len + 2;
165 rp->msg_type = rp_msg_type;
Holger Hans Peter Freytherf4f5a842014-02-08 15:14:53 +0100166 rp->msg_ref = rp_msg_ref;
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200167
168 return inst->mn_send(inst, mnsms_msg_type, msg);
169}
170
171static int gsm411_send_rp_error(struct gsm411_smr_inst *inst,
172 uint8_t msg_ref, uint8_t cause)
173{
174 struct msgb *msg = gsm411_msgb_alloc();
175
176 msgb_tv_put(msg, 1, cause);
177
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100178 LOGP(DLSMS, LOGL_NOTICE,
179 SMR_LOG_STR "TX: SMS RP ERROR, cause %d (%s)\n", inst->id,
180 cause, get_value_string(gsm411_rp_cause_strs, cause));
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200181
182 return gsm411_rp_sendmsg(inst, msg,
183 (inst->network) ? GSM411_MT_RP_ERROR_MT : GSM411_MT_RP_ERROR_MO,
184 msg_ref, GSM411_MNSMS_DATA_REQ);
185}
186
187static int gsm411_send_release(struct gsm411_smr_inst *inst)
188{
189 struct msgb *msg = gsm411_msgb_alloc();
190
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100191 LOGP(DLSMS, LOGL_DEBUG,
192 SMR_LOG_STR "TX: MNSMS-REL-REQ\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200193
194 return inst->mn_send(inst, GSM411_MNSMS_REL_REQ, msg);
195}
196
197static int gsm411_send_abort(struct gsm411_smr_inst *inst)
198{
199 struct msgb *msg = gsm411_msgb_alloc();
200
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100201 LOGP(DLSMS, LOGL_DEBUG,
202 SMR_LOG_STR "TX: MNSMS-ABORT-REQ\n", inst->id);
203
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200204 msgb_tv_put(msg, 1, 111); //FIXME: better idea ? */
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200205
206 return inst->mn_send(inst, GSM411_MNSMS_ABORT_REQ, msg);
207}
208
209static int gsm411_send_report(struct gsm411_smr_inst *inst)
210{
211 struct msgb *msg = gsm411_msgb_alloc();
212
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100213 LOGP(DLSMS, LOGL_DEBUG,
214 SMR_LOG_STR "Sending empty SM_RL_REPORT_IND\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200215
216 return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
217}
218
219static int gsm411_rl_data_req(struct gsm411_smr_inst *inst, struct msgb *msg)
220{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100221 LOGP(DLSMS, LOGL_DEBUG,
222 SMR_LOG_STR "TX SMS RP-DATA\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200223 /* start TR1N and enter 'wait for RP-ACK state' */
224 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR1M);
225 new_rp_state(inst, GSM411_RPS_WAIT_FOR_RP_ACK);
226
227 return inst->mn_send(inst, GSM411_MNSMS_EST_REQ, msg);
228}
229
230static int gsm411_rl_report_req(struct gsm411_smr_inst *inst, struct msgb *msg)
231{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100232 LOGP(DLSMS, LOGL_DEBUG,
233 SMR_LOG_STR "TX SMS REPORT\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200234 new_rp_state(inst, GSM411_RPS_IDLE);
235
236 inst->mn_send(inst, GSM411_MNSMS_DATA_REQ, msg);
237 gsm411_send_release(inst);
238 return 0;
239}
240
241static int gsm411_mnsms_est_ind(struct gsm411_smr_inst *inst, struct msgb *msg)
242{
243 struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
244 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
245 uint8_t msg_type = rp_data->msg_type & 0x07;
246 int rc;
247
248 /* check direction */
249 if (inst->network == (msg_type & 1)) {
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100250 LOGP(DLSMS, LOGL_NOTICE,
251 SMR_LOG_STR "Invalid RP type 0x%02x\n",
252 inst->id, msg_type);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200253 gsm411_send_rp_error(inst, rp_data->msg_ref,
254 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
255 new_rp_state(inst, GSM411_RPS_IDLE);
256 gsm411_send_release(inst);
257 return -EINVAL;
258 }
259
260 switch (msg_type) {
261 case GSM411_MT_RP_DATA_MT:
262 case GSM411_MT_RP_DATA_MO:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100263 LOGP(DLSMS, LOGL_DEBUG,
264 SMR_LOG_STR "RX SMS RP-DATA\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200265 /* start TR2N and enter 'wait to send RP-ACK state' */
266 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
267 new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
268 rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
269 break;
270 case GSM411_MT_RP_SMMA_MO:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100271 LOGP(DLSMS, LOGL_DEBUG,
272 SMR_LOG_STR "RX SMS RP-SMMA\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200273 /* start TR2N and enter 'wait to send RP-ACK state' */
274 osmo_timer_schedule(&inst->rp_timer, GSM411_TMR_TR2M);
275 new_rp_state(inst, GSM411_RPS_WAIT_TO_TX_RP_ACK);
276 rc = inst->rl_recv(inst, GSM411_SM_RL_DATA_IND, msg);
277 break;
278 default:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100279 LOGP(DLSMS, LOGL_NOTICE,
280 SMR_LOG_STR "invalid RP type 0x%02x\n",
281 inst->id, msg_type);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200282 gsm411_send_rp_error(inst, rp_data->msg_ref,
283 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
284 new_rp_state(inst, GSM411_RPS_IDLE);
285 rc = -EINVAL;
286 break;
287 }
288
289 return rc;
290}
291
292static int gsm411_mnsms_data_ind_tx(struct gsm411_smr_inst *inst,
293 struct msgb *msg)
294{
295 struct gsm48_hdr *gh = (struct gsm48_hdr*)msg->l3h;
296 struct gsm411_rp_hdr *rp_data = (struct gsm411_rp_hdr*)&gh->data;
297 uint8_t msg_type = rp_data->msg_type & 0x07;
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200298
299 /* check direction */
300 if (inst->network == (msg_type & 1)) {
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100301 LOGP(DLSMS, LOGL_NOTICE,
302 SMR_LOG_STR "invalid RP type 0x%02x\n",
303 inst->id, msg_type);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200304 gsm411_send_rp_error(inst, rp_data->msg_ref,
305 GSM411_RP_CAUSE_MSG_INCOMP_STATE);
306 new_rp_state(inst, GSM411_RPS_IDLE);
307 gsm411_send_release(inst);
308 return -EINVAL;
309 }
310
311 switch (msg_type) {
312 case GSM411_MT_RP_ACK_MO:
313 case GSM411_MT_RP_ACK_MT:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100314 LOGP(DLSMS, LOGL_DEBUG,
315 SMR_LOG_STR "RX SMS RP-ACK\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200316 new_rp_state(inst, GSM411_RPS_IDLE);
317 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
318 gsm411_send_release(inst);
319 return 0;
320 case GSM411_MT_RP_ERROR_MO:
321 case GSM411_MT_RP_ERROR_MT:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100322 LOGP(DLSMS, LOGL_DEBUG,
323 SMR_LOG_STR "RX SMS RP-ERROR\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200324 new_rp_state(inst, GSM411_RPS_IDLE);
325 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
326 gsm411_send_release(inst);
327 return 0;
328 default:
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100329 LOGP(DLSMS, LOGL_NOTICE,
330 SMR_LOG_STR "Invalid RP type 0x%02x\n",
331 inst->id, msg_type);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200332 gsm411_send_rp_error(inst, rp_data->msg_ref,
333 GSM411_RP_CAUSE_MSGTYPE_NOTEXIST);
334 new_rp_state(inst, GSM411_RPS_IDLE);
335 gsm411_send_release(inst);
336 return -EINVAL;
337 }
338
Vadim Yanitskiy4c3e4ea2017-05-15 21:32:43 +0300339 return 0;
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200340}
341
342static int gsm411_mnsms_error_ind_tx(struct gsm411_smr_inst *inst,
343 struct msgb *msg)
344{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100345 LOGP(DLSMS, LOGL_DEBUG,
Holger Hans Peter Freyther1c4c3732012-11-22 00:33:52 +0100346 SMR_LOG_STR "TX SMS MNSMS-ERROR-IND\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200347 new_rp_state(inst, GSM411_RPS_IDLE);
348 inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
349 gsm411_send_release(inst);
350 return 0;
351}
352
353static int gsm411_mnsms_error_ind_rx(struct gsm411_smr_inst *inst,
354 struct msgb *msg)
355{
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100356 LOGP(DLSMS, LOGL_DEBUG,
357 SMR_LOG_STR "RX SMS MNSMS-ERROR-IND\n", inst->id);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200358 new_rp_state(inst, GSM411_RPS_IDLE);
359 return inst->rl_recv(inst, GSM411_SM_RL_REPORT_IND, msg);
360}
361
362/* SMR TR1* is expired */
363static void rp_timer_expired(void *data)
364{
365 struct gsm411_smr_inst *inst = data;
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100366 const char *str;
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200367
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100368 str = inst->rp_state == GSM411_RPS_WAIT_TO_TX_RP_ACK
369 ? "TR2N" : "TR1N";
370
371 LOGP(DLSMS, LOGL_DEBUG,
372 SMR_LOG_STR "%s expired\n", inst->id, str);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200373 gsm411_send_report(inst);
374 gsm411_send_abort(inst);
375}
376
377/* statefull handling for SM-RL SAP messages */
Holger Hans Peter Freyther9473c5d2012-11-22 10:50:52 +0100378static const struct smrdownstate {
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200379 uint32_t states;
380 int type;
381 const char *name;
382 int (*rout) (struct gsm411_smr_inst *inst,
383 struct msgb *msg);
384} smrdownstatelist[] = {
385 /* data request */
386 {SBIT(GSM411_RPS_IDLE),
387 GSM411_SM_RL_DATA_REQ,
388 "SM-RL-DATA_REQ", gsm411_rl_data_req},
389
390 /* report request */
391 {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
392 GSM411_SM_RL_REPORT_REQ,
393 "SM-RL-REPORT_REQ", gsm411_rl_report_req},
394};
395
396#define SMRDOWNSLLEN \
397 (sizeof(smrdownstatelist) / sizeof(struct smrdownstate))
398
399/* message from upper layer */
400int gsm411_smr_send(struct gsm411_smr_inst *inst, int msg_type,
401 struct msgb *msg)
402{
403 int i, rc;
404
405 /* find function for current state and message */
406 for (i = 0; i < SMRDOWNSLLEN; i++) {
407 if ((msg_type == smrdownstatelist[i].type)
408 && (SBIT(inst->rp_state) & smrdownstatelist[i].states))
409 break;
410 }
411 if (i == SMRDOWNSLLEN) {
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100412 LOGP(DLSMS, LOGL_NOTICE,
413 SMR_LOG_STR "message %u unhandled at this state "
414 "%s.\n", inst->id, msg_type,
415 smr_state_names[inst->rp_state]);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200416 msgb_free(msg);
417 return 0;
418 }
419
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100420 LOGP(DLSMS, LOGL_INFO,
421 SMR_LOG_STR "message %s received in state %s\n", inst->id,
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200422 smrdownstatelist[i].name, smr_state_names[inst->rp_state]);
423
424 rc = smrdownstatelist[i].rout(inst, msg);
425
426 return rc;
427}
428
429/* statefull handling for MMSMS SAP messages */
Holger Hans Peter Freyther9473c5d2012-11-22 10:50:52 +0100430static const struct smrdatastate {
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200431 uint32_t states;
432 int type;
433 const char *name;
434 int (*rout) (struct gsm411_smr_inst *inst,
435 struct msgb *msg);
436} smrdatastatelist[] = {
437 /* establish indication */
438 {SBIT(GSM411_RPS_IDLE),
439 GSM411_MNSMS_EST_IND,
440 "MNSMS-EST-IND", gsm411_mnsms_est_ind},
441
442 /* data indication */
443 {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
444 GSM411_MNSMS_DATA_IND,
445 "MNSMS-DATA-IND", gsm411_mnsms_data_ind_tx},
446
447 /* error indication */
448 {SBIT(GSM411_RPS_WAIT_FOR_RP_ACK),
449 GSM411_MNSMS_ERROR_IND,
450 "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_tx},
451
452 /* error indication */
453 {SBIT(GSM411_RPS_WAIT_TO_TX_RP_ACK),
454 GSM411_MNSMS_ERROR_IND,
455 "MNSMS-ERROR-IND", gsm411_mnsms_error_ind_rx},
456
457};
458
459#define SMRDATASLLEN \
460 (sizeof(smrdatastatelist) / sizeof(struct smrdatastate))
461
462/* message from lower layer
463 * WARNING: We must not free msg, since it will be performed by the
464 * lower layer. */
465int gsm411_smr_recv(struct gsm411_smr_inst *inst, int msg_type,
466 struct msgb *msg)
467{
468 int i, rc;
469
470 /* find function for current state and message */
471 for (i = 0; i < SMRDATASLLEN; i++) {
Holger Hans Peter Freyther1c4c3732012-11-22 00:33:52 +0100472 /* state must match, MM message must match
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200473 * CP msg must match only in case of MMSMS_DATA_IND
474 */
475 if ((msg_type == smrdatastatelist[i].type)
476 && (SBIT(inst->rp_state) & smrdatastatelist[i].states))
477 break;
478 }
479 if (i == SMRDATASLLEN) {
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100480 LOGP(DLSMS, LOGL_NOTICE,
481 SMR_LOG_STR "message %u unhandled at this state "
482 "%s.\n", inst->id, msg_type,
483 smr_state_names[inst->rp_state]);
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200484 return 0;
485 }
486
Holger Hans Peter Freytherbcf125c2012-11-14 06:07:47 +0100487 LOGP(DLSMS, LOGL_INFO,
488 SMR_LOG_STR "message %s received in state %s\n", inst->id,
Andreas Eversbergc1a91a82011-10-28 11:05:37 +0200489 smrdatastatelist[i].name, smr_state_names[inst->rp_state]);
490
491 rc = smrdatastatelist[i].rout(inst, msg);
492
493 return rc;
494}
Harald Welte96e2a002017-06-12 21:44:18 +0200495
Harald Welted60e17a2018-01-24 16:50:11 +0100496const struct value_string gsm411_rp_state_names[] = {
497 { GSM411_RPS_IDLE, "IDLE" },
498 { GSM411_RPS_WAIT_FOR_RP_ACK, "WAIT_FOR_RP_ACK" },
499 { GSM411_RPS_WAIT_TO_TX_RP_ACK, "WAIT_TO_TX_RP_ACK" },
500 { GSM411_RPS_WAIT_FOR_RETRANS_T,"WAIT_FOR_RETRANS_T" },
501 { 0, NULL }
502};
Harald Welte96e2a002017-06-12 21:44:18 +0200503/*! @} */