blob: 89f77e56f54993f96a6915ee5fbc3bdf9e9e7c02 [file] [log] [blame]
Harald Welte9ee48252009-07-23 21:25:08 +02001/* GSM 04.07 Transaction handling */
2
3/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
Harald Welte9ee48252009-07-23 21:25:08 +02009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Harald Welte9ee48252009-07-23 21:25:08 +020015 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte9ee48252009-07-23 21:25:08 +020018 *
19 */
20
Neels Hofmeyr90843962017-09-04 15:04:35 +020021#include <osmocom/msc/transaction.h>
22#include <osmocom/msc/gsm_data.h>
23#include <osmocom/msc/mncc.h>
24#include <osmocom/msc/debug.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010025#include <osmocom/core/talloc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020026#include <osmocom/msc/gsm_04_08.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020027#include <osmocom/msc/vlr.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010028#include <osmocom/msc/msc_a.h>
29#include <osmocom/msc/msub.h>
30#include <osmocom/msc/paging.h>
31#include <osmocom/msc/silent_call.h>
Andreas Eversberge24636c2023-04-23 12:20:55 +020032#include <osmocom/msc/msc_vgcs.h>
Harald Welte9ee48252009-07-23 21:25:08 +020033
Harald Welte (local)d19e58b2009-08-15 02:30:58 +020034void *tall_trans_ctx;
Harald Welte9ee48252009-07-23 21:25:08 +020035
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020036void _gsm48_cc_trans_free(struct gsm_trans *trans);
Vadim Yanitskiyc350c092018-11-21 20:51:51 +070037void _gsm411_sms_trans_free(struct gsm_trans *trans);
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +070038void _gsm911_nc_ss_trans_free(struct gsm_trans *trans);
Holger Hans Peter Freyther34e97492009-08-10 07:54:02 +020039
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010040struct gsm_trans *trans_find_by_type(const struct msc_a *msc_a, enum trans_type type)
41{
42 struct gsm_trans *trans;
43 struct gsm_network *net = msc_a_net(msc_a);
44 struct vlr_subscr *vsub = msc_a_vsub(msc_a);
45
46 llist_for_each_entry(trans, &net->trans_list, entry) {
47 if (trans->vsub == vsub && trans->type == type)
48 return trans;
49 }
50 return NULL;
51}
52
Harald Welte2483f1b2016-06-19 18:06:02 +020053/*! Find a transaction in connection for given protocol + transaction ID
Vadim Yanitskiy380b2192018-11-27 15:14:31 +070054 * \param[in] conn Connection in which we want to find transaction
Harald Welte2483f1b2016-06-19 18:06:02 +020055 * \param[in] proto Protocol of transaction
56 * \param[in] trans_id Transaction ID of transaction
57 * \returns Matching transaction, if any
58 */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010059struct gsm_trans *trans_find_by_id(const struct msc_a *msc_a,
60 enum trans_type type, uint8_t trans_id)
Harald Welte9ee48252009-07-23 21:25:08 +020061{
62 struct gsm_trans *trans;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010063 struct gsm_network *net = msc_a_net(msc_a);
64 struct vlr_subscr *vsub = msc_a_vsub(msc_a);
Harald Welte9ee48252009-07-23 21:25:08 +020065
66 llist_for_each_entry(trans, &net->trans_list, entry) {
Harald Welte2483f1b2016-06-19 18:06:02 +020067 if (trans->vsub == vsub &&
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010068 trans->type == type &&
Harald Welteb8b40732009-07-23 21:58:40 +020069 trans->transaction_id == trans_id)
Harald Welte9ee48252009-07-23 21:25:08 +020070 return trans;
71 }
72 return NULL;
73}
74
Harald Welte2483f1b2016-06-19 18:06:02 +020075/*! Find a transaction by call reference
76 * \param[in] net Network in which we should search
Andreas Eversberg7e4b0322023-04-23 11:43:13 +020077 * \param[in] type Transaction type (e.g. TRANS_CC)
Harald Welte2483f1b2016-06-19 18:06:02 +020078 * \param[in] callref Call Reference of transaction
79 * \returns Matching transaction, if any
80 */
Andreas Eversberg7e4b0322023-04-23 11:43:13 +020081struct gsm_trans *trans_find_by_callref(const struct gsm_network *net, enum trans_type type,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020082 uint32_t callref)
Harald Welte9ee48252009-07-23 21:25:08 +020083{
84 struct gsm_trans *trans;
85
86 llist_for_each_entry(trans, &net->trans_list, entry) {
Andreas Eversberg7e4b0322023-04-23 11:43:13 +020087 if (trans->callref == callref && trans->type == type)
Harald Welte9ee48252009-07-23 21:25:08 +020088 return trans;
89 }
90 return NULL;
91}
92
Ivan Kluchnikov9bd4fd62015-12-21 12:05:56 +030093/*! Find a transaction by SM-RP-MR (RP Message Reference)
Vadim Yanitskiy36c44b22019-01-23 21:22:27 +070094 * \param[in] net Network in which we should search
95 * \param[in] vsub Subscriber for which we should search
Ivan Kluchnikov9bd4fd62015-12-21 12:05:56 +030096 * \param[in] sm_rp_mr RP Message Reference (see GSM TS 04.11, section 8.2.3)
97 * \returns Matching transaction, NULL otherwise
98 */
Vadim Yanitskiy36c44b22019-01-23 21:22:27 +070099struct gsm_trans *trans_find_by_sm_rp_mr(const struct gsm_network *net,
100 const struct vlr_subscr *vsub,
Ivan Kluchnikov9bd4fd62015-12-21 12:05:56 +0300101 uint8_t sm_rp_mr)
102{
Ivan Kluchnikov9bd4fd62015-12-21 12:05:56 +0300103 struct gsm_trans *trans;
104
105 llist_for_each_entry(trans, &net->trans_list, entry) {
106 if (trans->vsub == vsub &&
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100107 trans->type == TRANS_SMS &&
Ivan Kluchnikov9bd4fd62015-12-21 12:05:56 +0300108 trans->sms.sm_rp_mr == sm_rp_mr)
109 return trans;
110 }
111
112 return NULL;
113}
114
Keith Whytea1a70be2021-05-16 02:59:52 +0200115struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac)
116{
Vadim Yanitskiy583883b2021-10-26 10:25:36 +0300117 if (!trans) {
118 LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for unallocated transaction\n");
119 return NULL;
120 }
121
Keith Whytea1a70be2021-05-16 02:59:52 +0200122 if (!trans->net->a.sri->sccp)
123 return NULL;
124
125 struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(trans->net->a.sri->sccp);
126 struct osmo_lcls *lcls;
127 uint8_t w = osmo_ss7_pc_width(&ss7->cfg.pc_fmt);
128
Keith Whytea1a70be2021-05-16 02:59:52 +0200129 if (!trans->net->lcls_permitted) {
130 LOGP(DCC, LOGL_NOTICE, "LCLS disabled globally\n");
131 return NULL;
132 }
133
134 if (!trans->msc_a) {
135 LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for transaction without connection\n");
136 return NULL;
137 }
138
139 if (trans->msc_a->c.ran->type != OSMO_RAT_GERAN_A) {
140 LOGP(DCC, LOGL_ERROR, "LCLS: only A interface is supported at the moment\n");
141 return NULL;
142 }
143
144 lcls = talloc_zero(trans, struct osmo_lcls);
145 if (!lcls) {
146 LOGP(DCC, LOGL_ERROR, "LCLS: failed to allocate osmo_lcls\n");
147 return NULL;
148 }
149
150 LOGP(DCC, LOGL_INFO, "LCLS: using %u bits (%u bytes) for node ID\n", w, w / 8);
151
152 lcls->gcr.net_len = 3;
153 lcls->gcr.node = ss7->cfg.primary_pc;
154
155 /* net id from Q.1902.3 3-5 bytes, this function gives 3 bytes exactly */
156 osmo_plmn_to_bcd(lcls->gcr.net, &trans->net->plmn);
157
Keith Whytea1a70be2021-05-16 02:59:52 +0200158
Keith Whyte404fb1b2023-01-31 20:09:31 +0100159 /* TS 29.205 Table B.2.1.9.2 Call Reference ID
160 * 3 octets Call ID + 2 octets BSS ID
161 */
162 lcls->gcr.cr[2] = (trans->callref >> 0) & 0xff;
163 lcls->gcr.cr[1] = (trans->callref >> 8) & 0xff;
164 lcls->gcr.cr[0] = (trans->callref >> 16) & 0xff;
165 osmo_store16be(use_lac ? trans->msc_a->via_cell.lai.lac : trans->msc_a->via_cell.cell_identity, &lcls->gcr.cr[3]);
166
167 LOGP(DCC, LOGL_INFO, "LCLS: allocated %s-based CR-ID %sfor callref 0x%04x\n", use_lac ? "LAC" : "CI",
168 osmo_hexdump(lcls->gcr.cr, 5), trans->callref);
Keith Whytea1a70be2021-05-16 02:59:52 +0200169
170 lcls->config = GSM0808_LCLS_CFG_BOTH_WAY;
171 lcls->control = GSM0808_LCLS_CSC_CONNECT;
172 lcls->corr_needed = true;
173 lcls->gcr_available = true;
174
175 LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_lcls_dump(lcls));
176 LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_gcr_dump(lcls));
177
178 return lcls;
179}
180
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100181static const char *trans_vsub_use(enum trans_type type)
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +0100182{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100183 return get_value_string_or_null(trans_type_names, type) ? : "trans-type-unknown";
Neels Hofmeyr7c5346c2019-02-19 02:36:35 +0100184}
185
Andreas Eversberg712b28e2023-06-21 11:17:26 +0200186static uint32_t new_call_id = 1;
187
Harald Welte2483f1b2016-06-19 18:06:02 +0200188/*! Allocate a new transaction and add it to network list
189 * \param[in] net Netwokr in which we allocate transaction
190 * \param[in] subscr Subscriber for which we allocate transaction
191 * \param[in] protocol Protocol (CC/SMS/...)
192 * \param[in] callref Call Reference
193 * \returns Transaction
194 */
Jacob Erlbeckaf792d62014-12-02 14:22:53 +0100195struct gsm_trans *trans_alloc(struct gsm_network *net,
Harald Welte2483f1b2016-06-19 18:06:02 +0200196 struct vlr_subscr *vsub,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100197 enum trans_type type, uint8_t trans_id,
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +0200198 uint32_t callref)
Harald Welte9ee48252009-07-23 21:25:08 +0200199{
Vadim Yanitskiyb683dcf2019-05-11 02:17:16 +0700200 int subsys = trans_log_subsys(type);
201 struct gsm_trans *trans;
Harald Welte9ee48252009-07-23 21:25:08 +0200202
Andreas Eversberg5b1ab542023-06-05 14:25:59 +0200203 /* A valid subscriber is indispensable, except for voice group/broadcast calls. */
204 if (vsub == NULL && type != TRANS_GCC && type != TRANS_BCC) {
Vadim Yanitskiyb683dcf2019-05-11 02:17:16 +0700205 LOGP(subsys, LOGL_ERROR, "unable to alloc transaction, invalid subscriber (NULL)\n");
Benoit Bolseee7cf5e72017-07-05 12:34:18 +0200206 return NULL;
207 }
208
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100209 trans = talloc(tall_trans_ctx, struct gsm_trans);
Harald Welte9ee48252009-07-23 21:25:08 +0200210 if (!trans)
211 return NULL;
212
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100213 *trans = (struct gsm_trans){
214 .vsub = vsub,
215 .type = type,
Vadim Yanitskiyb683dcf2019-05-11 02:17:16 +0700216 .log_subsys = subsys,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100217 .transaction_id = trans_id,
218 .callref = callref,
Andreas Eversberg712b28e2023-06-21 11:17:26 +0200219 .call_id = new_call_id++,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100220 .net = net,
Neels Hofmeyr85031ee2019-08-28 03:42:03 +0200221 /* empty bearer_cap: make sure the speech_ver array is empty */
222 .bearer_cap = {
223 .speech_ver = { -1 },
224 },
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100225 };
Andreas Eversberg5b1ab542023-06-05 14:25:59 +0200226 if (vsub)
227 vlr_subscr_get(vsub, trans_vsub_use(type));
Jacob Erlbeckf07c6052014-12-02 11:58:00 +0100228 llist_add_tail(&trans->entry, &net->trans_list);
Harald Welte9ee48252009-07-23 21:25:08 +0200229
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100230 LOG_TRANS(trans, LOGL_DEBUG, "New transaction\n");
Harald Welte9ee48252009-07-23 21:25:08 +0200231 return trans;
232}
233
Harald Welte2483f1b2016-06-19 18:06:02 +0200234/*! Release a transaction
235 * \param[in] trans Transaction to be released
236 */
Harald Welte9ee48252009-07-23 21:25:08 +0200237void trans_free(struct gsm_trans *trans)
238{
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100239 const char *usage_token;
240 struct msc_a *msc_a;
Neels Hofmeyr6166f292017-11-22 14:33:12 +0100241
Neels Hofmeyrff7074a2019-02-28 05:50:06 +0100242 LOG_TRANS(trans, LOGL_DEBUG, "Freeing transaction\n");
243
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100244 switch (trans->type) {
Andreas Eversberge24636c2023-04-23 12:20:55 +0200245 case TRANS_GCC:
246 gsm44068_bcc_gcc_trans_free(trans);
247 usage_token = MSC_A_USE_GCC;
248 break;
249 case TRANS_BCC:
250 gsm44068_bcc_gcc_trans_free(trans);
251 usage_token = MSC_A_USE_BCC;
252 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100253 case TRANS_CC:
Harald Welte9ee48252009-07-23 21:25:08 +0200254 _gsm48_cc_trans_free(trans);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100255 usage_token = MSC_A_USE_CC;
Harald Welte9ee48252009-07-23 21:25:08 +0200256 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100257 case TRANS_SMS:
Harald Welte (local)86b17172009-08-14 14:52:17 +0200258 _gsm411_sms_trans_free(trans);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100259 usage_token = MSC_A_USE_SMS;
Harald Welte (local)86b17172009-08-14 14:52:17 +0200260 break;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100261 case TRANS_USSD:
Vadim Yanitskiyf2f83b02018-06-17 21:09:28 +0700262 _gsm911_nc_ss_trans_free(trans);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100263 usage_token = MSC_A_USE_NC_SS;
264 break;
265 case TRANS_SILENT_CALL:
266 trans_silent_call_free(trans);
267 usage_token = MSC_A_USE_SILENT_CALL;
Vadim Yanitskiy10c64192018-04-17 19:17:11 +0700268 break;
Vadim Yanitskiye4574f02019-01-25 19:23:25 +0700269 default:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100270 usage_token = NULL;
Vadim Yanitskiye4574f02019-01-25 19:23:25 +0700271 break;
Harald Welte9ee48252009-07-23 21:25:08 +0200272 }
273
Holger Hans Peter Freytherd6d7aff2015-04-06 12:03:45 +0200274 if (trans->paging_request) {
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100275 paging_request_remove(trans->paging_request);
Holger Hans Peter Freyther49b3ed22010-12-29 17:09:07 +0100276 trans->paging_request = NULL;
Harald Welte9ee48252009-07-23 21:25:08 +0200277 }
278
Harald Welte2483f1b2016-06-19 18:06:02 +0200279 if (trans->vsub) {
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100280 vlr_subscr_put(trans->vsub, trans_vsub_use(trans->type));
Harald Welte2483f1b2016-06-19 18:06:02 +0200281 trans->vsub = NULL;
Holger Hans Peter Freyther405824c2012-12-22 18:16:47 +0100282 }
Harald Welte9ee48252009-07-23 21:25:08 +0200283
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100284 msc_a = trans->msc_a;
285 trans->msc_a = NULL;
286
Neels Hofmeyre3d3dc62018-03-31 00:02:14 +0200287 llist_del(&trans->entry);
Harald Welte9ee48252009-07-23 21:25:08 +0200288 talloc_free(trans);
Neels Hofmeyrd6a769b2018-03-12 23:59:07 +0100289
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100290 if (msc_a && usage_token)
291 msc_a_put(msc_a, usage_token);
Harald Welte9ee48252009-07-23 21:25:08 +0200292}
293
Harald Welte2483f1b2016-06-19 18:06:02 +0200294/*! allocate an unused transaction ID for the given subscriber
Max30fb97a2019-01-10 17:25:33 +0100295 * in the given protocol using TI flag = 0 (allocated by us).
296 * See GSM 04.07, section 11.2.3.1.3 "Transaction identifier".
Harald Welte2483f1b2016-06-19 18:06:02 +0200297 * \param[in] net GSM network
Vadim Yanitskiybaeeb902019-02-14 16:41:30 +0700298 * \param[in] subscr Subscriber for which to assign a new TID
299 * \param[in] protocol Protocol of to be assigned TID
Harald Welte2483f1b2016-06-19 18:06:02 +0200300 */
Max7916ca12019-01-02 11:48:14 +0100301int trans_assign_trans_id(const struct gsm_network *net, const struct vlr_subscr *vsub,
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100302 enum trans_type type)
Harald Welte9ee48252009-07-23 21:25:08 +0200303{
Harald Welte9ee48252009-07-23 21:25:08 +0200304 struct gsm_trans *trans;
305 unsigned int used_tid_bitmask = 0;
Sylvain Munaut926fcec2009-12-24 13:26:17 +0100306 int i, j, h;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100307 uint8_t proto = trans_type_to_gsm48_proto(type);
Harald Welte78283ef2009-07-23 21:36:44 +0200308
Harald Welte9ee48252009-07-23 21:25:08 +0200309 /* generate bitmask of already-used TIDs for this (subscr,proto) */
310 llist_for_each_entry(trans, &net->trans_list, entry) {
Harald Welte2483f1b2016-06-19 18:06:02 +0200311 if (trans->vsub != vsub ||
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100312 proto != trans_type_to_gsm48_proto(trans->type) ||
Maxd8daaae2019-02-14 16:54:10 +0700313 trans->transaction_id == TRANS_ID_UNASSIGNED)
Harald Welte9ee48252009-07-23 21:25:08 +0200314 continue;
315 used_tid_bitmask |= (1 << trans->transaction_id);
316 }
317
Sylvain Munaut926fcec2009-12-24 13:26:17 +0100318 /* find a new one, trying to go in a 'circular' pattern */
319 for (h = 6; h > 0; h--)
Max30fb97a2019-01-10 17:25:33 +0100320 if (used_tid_bitmask & (1 << h))
Sylvain Munaut926fcec2009-12-24 13:26:17 +0100321 break;
Sylvain Munautb9f3dce2009-12-18 18:28:11 +0100322 for (i = 0; i < 7; i++) {
Max30fb97a2019-01-10 17:25:33 +0100323 j = (h + i) % 7;
Sylvain Munaut926fcec2009-12-24 13:26:17 +0100324 if ((used_tid_bitmask & (1 << j)) == 0)
325 return j;
Harald Welte78283ef2009-07-23 21:36:44 +0200326 }
327
328 return -1;
Harald Welte9ee48252009-07-23 21:25:08 +0200329}
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100330
Harald Welte2483f1b2016-06-19 18:06:02 +0200331/*! Check if we have any transaction for given connection
332 * \param[in] conn Connection to check
Maxc065ca32019-01-14 11:51:28 +0100333 * \returns transaction pointer if found, NULL otherwise
Harald Welte2483f1b2016-06-19 18:06:02 +0200334 */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100335struct gsm_trans *trans_has_conn(const struct msc_a *msc_a)
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100336{
337 struct gsm_trans *trans;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100338 struct gsm_network *net = msc_a_net(msc_a);
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100339
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100340 llist_for_each_entry(trans, &net->trans_list, entry)
341 if (trans->msc_a == msc_a)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200342 return trans;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100343
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200344 return NULL;
Holger Hans Peter Freyther70ae5d32012-11-23 21:33:15 +0100345}
Harald Welte2483f1b2016-06-19 18:06:02 +0200346
347/*! Free all transactions associated with a connection, presumably when the
348 * conn is being closed. The transaction code will inform the CC or SMS
349 * facilities, which will then send the necessary release indications.
350 * \param[in] conn Connection that is going to be closed.
351 */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100352void trans_conn_closed(const struct msc_a *msc_a)
Harald Welte2483f1b2016-06-19 18:06:02 +0200353{
Harald Welte2483f1b2016-06-19 18:06:02 +0200354 /* As part of the CC REL_IND the remote leg might be released and this
355 * will trigger another call to trans_free. This is something the llist
356 * macro can not handle and we need to re-iterate the list every time.
357 */
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100358 struct gsm_trans *trans;
359 while ((trans = trans_has_conn(msc_a)))
360 trans_free(trans);
361}
362
363const struct value_string trans_type_names[] = {
Andreas Eversberg456c6f72023-04-23 11:54:16 +0200364 { TRANS_GCC, "GCC" },
365 { TRANS_BCC, "BCC" },
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100366 { TRANS_CC, "CC" },
367 { TRANS_SMS, "SMS" },
368 { TRANS_USSD, "NCSS" },
369 { TRANS_SILENT_CALL, "silent-call" },
370 {}
371};
372
373uint8_t trans_type_to_gsm48_proto(enum trans_type type)
374{
375 switch (type) {
Andreas Eversberg456c6f72023-04-23 11:54:16 +0200376 case TRANS_GCC:
377 return GSM48_PDISC_GROUP_CC;
378 case TRANS_BCC:
379 return GSM48_PDISC_BCAST_CC;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100380 case TRANS_CC:
381 case TRANS_SILENT_CALL:
382 return GSM48_PDISC_CC;
383 case TRANS_SMS:
384 return GSM48_PDISC_SMS;
385 case TRANS_USSD:
386 return GSM48_PDISC_NC_SS;
387 default:
388 return GSM48_PDISC_TEST;
Harald Welte2483f1b2016-06-19 18:06:02 +0200389 }
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100390
Harald Welte2483f1b2016-06-19 18:06:02 +0200391}
Neels Hofmeyrf636e6c2019-10-07 21:20:43 +0200392
393const char *trans_name(const struct gsm_trans *trans)
394{
395 static char namebuf[32];
396 if (!trans)
397 return "NULL";
398 switch (trans->type) {
399 case TRANS_CC:
400 snprintf(namebuf, sizeof(namebuf), "%s:%s",
401 trans_type_name(trans->type), gsm48_cc_state_name(trans->cc.state));
402 return namebuf;
403
Andreas Eversberge24636c2023-04-23 12:20:55 +0200404 case TRANS_GCC:
405 case TRANS_BCC:
406 snprintf(namebuf, sizeof(namebuf), "%s:%s",
407 trans_type_name(trans->type), gsm44068_group_id_string(trans->callref));
408 return namebuf;
409
Neels Hofmeyrf636e6c2019-10-07 21:20:43 +0200410 default:
411 return trans_type_name(trans->type);
412 }
413}