blob: 647420155193bbd812b29c08fd08fd3614bcefbd [file] [log] [blame]
Harald Welte3e6376d2010-12-22 23:54:51 +01001/* mncc_builtin.c - default, minimal built-in MNCC Application for
Alexander Couzensfbd96f52016-08-29 18:40:02 +02002 * standalone bsc_hack (network-in-the-box mode) */
Harald Welte3e6376d2010-12-22 23:54:51 +01003
4/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2009 by Andreas Eversberg <Andreas.Eversberg@versatel.de>
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
Harald Welte3e6376d2010-12-22 23:54:51 +010018 */
19
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <errno.h>
Harald Welte3e6376d2010-12-22 23:54:51 +010025
Neels Hofmeyr90843962017-09-04 15:04:35 +020026#include <osmocom/msc/gsm_04_08.h>
27#include <osmocom/msc/debug.h>
28#include <osmocom/msc/mncc.h>
29#include <osmocom/msc/mncc_int.h>
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010030#include <osmocom/core/talloc.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020031#include <osmocom/msc/gsm_data.h>
32#include <osmocom/msc/transaction.h>
Harald Welte3e6376d2010-12-22 23:54:51 +010033
Max3332ac42018-12-17 11:17:33 +010034#define DEBUGCC(l, r, fmt, args...) DEBUGP(DMNCC, "(call %x, remote %x) " fmt, l->callref, r->callref, ##args)
35
Harald Welte3e6376d2010-12-22 23:54:51 +010036void *tall_call_ctx;
37
38static LLIST_HEAD(call_list);
39
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020040static uint32_t new_callref = 0x00000001;
Harald Welte3e6376d2010-12-22 23:54:51 +010041
Harald Welteab386e62011-09-01 18:18:43 +020042struct mncc_int mncc_int = {
Andreas Eversberga83d5112013-12-07 18:32:28 +010043 .def_codec = { GSM48_CMODE_SPEECH_V1, GSM48_CMODE_SPEECH_V1 },
Harald Welteab386e62011-09-01 18:18:43 +020044};
45
Harald Welte3e6376d2010-12-22 23:54:51 +010046static void free_call(struct gsm_call *call)
47{
48 llist_del(&call->entry);
49 DEBUGP(DMNCC, "(call %x) Call removed.\n", call->callref);
50 talloc_free(call);
51}
52
53
Holger Hans Peter Freytherc42ad8b2011-04-18 17:04:00 +020054static struct gsm_call *get_call_ref(uint32_t callref)
Harald Welte3e6376d2010-12-22 23:54:51 +010055{
56 struct gsm_call *callt;
57
58 llist_for_each_entry(callt, &call_list, entry) {
59 if (callt->callref == callref)
60 return callt;
61 }
62 return NULL;
63}
64
Harald Welte3e6376d2010-12-22 23:54:51 +010065/* on incoming call, look up database and send setup to remote subscr. */
Neels Hofmeyr52558742019-05-09 01:23:09 +020066static int mncc_setup_ind(struct gsm_call *call,
Harald Welte3e6376d2010-12-22 23:54:51 +010067 struct gsm_mncc *setup)
68{
69 struct gsm_mncc mncc;
70 struct gsm_call *remote;
71
72 memset(&mncc, 0, sizeof(struct gsm_mncc));
73 mncc.callref = call->callref;
74
75 /* already have remote call */
76 if (call->remote_ref)
77 return 0;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010078
Harald Welte3e6376d2010-12-22 23:54:51 +010079 /* transfer mode 1 would be packet mode, which was never specified */
80 if (setup->bearer_cap.mode != 0) {
81 LOGP(DMNCC, LOGL_NOTICE, "(call %x) We don't support "
82 "packet mode\n", call->callref);
83 mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
84 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
85 goto out_reject;
86 }
87
Oliver Smith429ab7b2023-07-10 16:24:36 +020088 /* we currently only do speech and CSD */
89 switch (setup->bearer_cap.transfer) {
90 case GSM_MNCC_BCAP_SPEECH:
Manawyrm1ed12ea2023-10-14 17:23:04 +020091 case GSM_MNCC_BCAP_AUDIO:
92 case GSM_MNCC_BCAP_FAX_G3:
Oliver Smith429ab7b2023-07-10 16:24:36 +020093 case GSM_MNCC_BCAP_UNR_DIG:
94 break;
95 default:
Harald Welte3e6376d2010-12-22 23:54:51 +010096 LOGP(DMNCC, LOGL_NOTICE, "(call %x) We only support "
Oliver Smith429ab7b2023-07-10 16:24:36 +020097 "voice calls and CSD\n", call->callref);
Harald Welte3e6376d2010-12-22 23:54:51 +010098 mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
99 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
100 goto out_reject;
101 }
102
103 /* create remote call */
Andreas Eversbergc5e08512013-01-25 08:36:32 +0100104 if (!(remote = talloc_zero(tall_call_ctx, struct gsm_call))) {
Harald Welte3e6376d2010-12-22 23:54:51 +0100105 mncc_set_cause(&mncc, GSM48_CAUSE_LOC_PRN_S_LU,
106 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
107 goto out_reject;
108 }
109 llist_add_tail(&remote->entry, &call_list);
110 remote->net = call->net;
111 remote->callref = new_callref++;
Max3332ac42018-12-17 11:17:33 +0100112 DEBUGCC(call, remote, "Creating new remote instance.\n");
Harald Welte3e6376d2010-12-22 23:54:51 +0100113
114 /* link remote call */
115 call->remote_ref = remote->callref;
116 remote->remote_ref = call->callref;
117
Harald Weltebf0a7c92012-08-24 16:48:21 +0200118 /* send call proceeding */
119 memset(&mncc, 0, sizeof(struct gsm_mncc));
120 mncc.callref = call->callref;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200121 mncc.msg_type = MNCC_CALL_PROC_REQ;
Max3332ac42018-12-17 11:17:33 +0100122 DEBUGCC(call, remote, "Accepting call.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200123 mncc_tx_to_cc(call->net, &mncc);
Harald Weltebf0a7c92012-08-24 16:48:21 +0200124
Harald Welte3e6376d2010-12-22 23:54:51 +0100125 /* modify mode */
126 memset(&mncc, 0, sizeof(struct gsm_mncc));
127 mncc.callref = call->callref;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200128 mncc.msg_type = MNCC_LCHAN_MODIFY;
Max3332ac42018-12-17 11:17:33 +0100129 DEBUGCC(call, remote, "Modify channel mode.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200130 mncc_tx_to_cc(call->net, &mncc);
Harald Welte3e6376d2010-12-22 23:54:51 +0100131
Harald Welte3e6376d2010-12-22 23:54:51 +0100132 /* send setup to remote */
133// setup->fields |= MNCC_F_SIGNAL;
134// setup->signal = GSM48_SIGNAL_DIALTONE;
135 setup->callref = remote->callref;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200136 setup->msg_type = MNCC_SETUP_REQ;
Max3332ac42018-12-17 11:17:33 +0100137 DEBUGCC(call, remote, "Forwarding SETUP to remote.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200138 return mncc_tx_to_cc(remote->net, setup);
Harald Welte3e6376d2010-12-22 23:54:51 +0100139
140out_reject:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200141 mncc.msg_type = MNCC_REJ_REQ;
142 mncc_tx_to_cc(call->net, &mncc);
Harald Welte3e6376d2010-12-22 23:54:51 +0100143 free_call(call);
144 return 0;
145}
146
Neels Hofmeyr52558742019-05-09 01:23:09 +0200147static int mncc_alert_ind(struct gsm_call *call,
Harald Welte3e6376d2010-12-22 23:54:51 +0100148 struct gsm_mncc *alert)
149{
150 struct gsm_call *remote;
151
152 /* send alerting to remote */
153 if (!(remote = get_call_ref(call->remote_ref)))
154 return 0;
155 alert->callref = remote->callref;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200156 alert->msg_type = MNCC_ALERT_REQ;
Max3332ac42018-12-17 11:17:33 +0100157 DEBUGCC(call, remote, "Forwarding ALERT to remote.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200158 return mncc_tx_to_cc(remote->net, alert);
Harald Welte3e6376d2010-12-22 23:54:51 +0100159}
160
Neels Hofmeyr52558742019-05-09 01:23:09 +0200161static int mncc_notify_ind(struct gsm_call *call,
Harald Welte3e6376d2010-12-22 23:54:51 +0100162 struct gsm_mncc *notify)
163{
164 struct gsm_call *remote;
165
166 /* send notify to remote */
167 if (!(remote = get_call_ref(call->remote_ref)))
168 return 0;
169 notify->callref = remote->callref;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200170 notify->msg_type = MNCC_NOTIFY_REQ;
Max3332ac42018-12-17 11:17:33 +0100171 DEBUGCC(call, remote, "Forwarding NOTIF to remote.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200172 return mncc_tx_to_cc(remote->net, notify);
Harald Welte3e6376d2010-12-22 23:54:51 +0100173}
174
Neels Hofmeyr52558742019-05-09 01:23:09 +0200175static int mncc_setup_cnf(struct gsm_call *call,
Harald Welte3e6376d2010-12-22 23:54:51 +0100176 struct gsm_mncc *connect)
177{
Neels Hofmeyrf9773b02018-11-29 23:01:58 +0100178 struct gsm_mncc connect_ack;
Harald Welte3e6376d2010-12-22 23:54:51 +0100179 struct gsm_call *remote;
Harald Welte53d51f52015-12-03 14:59:04 +0100180 struct gsm_mncc_bridge bridge = { .msg_type = MNCC_BRIDGE };
Harald Welte3e6376d2010-12-22 23:54:51 +0100181
182 /* acknowledge connect */
183 memset(&connect_ack, 0, sizeof(struct gsm_mncc));
Neels Hofmeyr52558742019-05-09 01:23:09 +0200184 connect_ack.msg_type = MNCC_SETUP_COMPL_REQ;
Harald Welte3e6376d2010-12-22 23:54:51 +0100185 connect_ack.callref = call->callref;
186 DEBUGP(DMNCC, "(call %x) Acknowledge SETUP.\n", call->callref);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200187 mncc_tx_to_cc(call->net, &connect_ack);
Harald Welte3e6376d2010-12-22 23:54:51 +0100188
189 /* send connect message to remote */
190 if (!(remote = get_call_ref(call->remote_ref)))
191 return 0;
Neels Hofmeyr52558742019-05-09 01:23:09 +0200192 connect->msg_type = MNCC_SETUP_RSP;
Harald Welte3e6376d2010-12-22 23:54:51 +0100193 connect->callref = remote->callref;
Max3332ac42018-12-17 11:17:33 +0100194 DEBUGCC(call, remote, "Sending CONNECT to remote.\n");
Neels Hofmeyr52558742019-05-09 01:23:09 +0200195 mncc_tx_to_cc(remote->net, connect);
Harald Welte3e6376d2010-12-22 23:54:51 +0100196
197 /* bridge tch */
Neels Hofmeyr52558742019-05-09 01:23:09 +0200198 bridge.msg_type = MNCC_BRIDGE;
Harald Welte53d51f52015-12-03 14:59:04 +0100199 bridge.callref[0] = call->callref;
200 bridge.callref[1] = call->remote_ref;
Max3332ac42018-12-17 11:17:33 +0100201 DEBUGCC(call, remote, "Bridging with remote.\n");
Harald Welte3e6376d2010-12-22 23:54:51 +0100202
Neels Hofmeyr52558742019-05-09 01:23:09 +0200203 return mncc_tx_to_cc(call->net, &bridge);
Harald Welte3e6376d2010-12-22 23:54:51 +0100204}
205
Neels Hofmeyr52558742019-05-09 01:23:09 +0200206static int mncc_disc_ind(struct gsm_call *call,
Harald Welte3e6376d2010-12-22 23:54:51 +0100207 struct gsm_mncc *disc)
208{
209 struct gsm_call *remote;
210
211 /* send release */
212 DEBUGP(DMNCC, "(call %x) Releasing call with cause %d\n",
213 call->callref, disc->cause.value);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200214 disc->msg_type = MNCC_REL_REQ;
215 mncc_tx_to_cc(call->net, disc);
Harald Welte3e6376d2010-12-22 23:54:51 +0100216
217 /* send disc to remote */
218 if (!(remote = get_call_ref(call->remote_ref))) {
219 return 0;
220 }
Neels Hofmeyr52558742019-05-09 01:23:09 +0200221 disc->msg_type = MNCC_DISC_REQ;
Harald Welte3e6376d2010-12-22 23:54:51 +0100222 disc->callref = remote->callref;
Max3332ac42018-12-17 11:17:33 +0100223 DEBUGCC(call, remote, "Disconnecting remote with cause %d\n", disc->cause.value);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200224 return mncc_tx_to_cc(remote->net, disc);
Harald Welte3e6376d2010-12-22 23:54:51 +0100225}
226
Neels Hofmeyr52558742019-05-09 01:23:09 +0200227static int mncc_rel_ind(struct gsm_call *call, struct gsm_mncc *rel)
Harald Welte3e6376d2010-12-22 23:54:51 +0100228{
229 struct gsm_call *remote;
230
231 /* send release to remote */
232 if (!(remote = get_call_ref(call->remote_ref))) {
233 free_call(call);
234 return 0;
235 }
Holger Hans Peter Freythera61c7092011-01-27 15:05:45 +0100236
Neels Hofmeyr52558742019-05-09 01:23:09 +0200237 rel->msg_type = MNCC_REL_REQ;
Harald Welte3e6376d2010-12-22 23:54:51 +0100238 rel->callref = remote->callref;
Max3332ac42018-12-17 11:17:33 +0100239 DEBUGCC(call, remote, "Releasing remote with cause %d\n", rel->cause.value);
Harald Welte3e6376d2010-12-22 23:54:51 +0100240
Holger Hans Peter Freythera61c7092011-01-27 15:05:45 +0100241 /*
242 * Release this side of the call right now. Otherwise we end up
243 * in this method for the other call and will also try to release
244 * it and then we will end up with a double free and a crash
245 */
Harald Welte3e6376d2010-12-22 23:54:51 +0100246 free_call(call);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200247 mncc_tx_to_cc(remote->net, rel);
Harald Welte3e6376d2010-12-22 23:54:51 +0100248
249 return 0;
250}
251
Neels Hofmeyr52558742019-05-09 01:23:09 +0200252static int mncc_rel_cnf(struct gsm_call *call, struct gsm_mncc *rel)
Harald Welte3e6376d2010-12-22 23:54:51 +0100253{
254 free_call(call);
255 return 0;
256}
257
Harald Welte3e6376d2010-12-22 23:54:51 +0100258/* Internal MNCC handler input function (from CC -> MNCC -> here) */
Harald Welte29b64e92010-12-23 01:07:46 +0100259int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
Harald Welte3e6376d2010-12-22 23:54:51 +0100260{
Harald Welte29b64e92010-12-23 01:07:46 +0100261 void *arg = msgb_data(msg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100262 struct gsm_mncc *data = arg;
Harald Welte29b64e92010-12-23 01:07:46 +0100263 int msg_type = data->msg_type;
Harald Welte3e6376d2010-12-22 23:54:51 +0100264 int callref;
265 struct gsm_call *call = NULL, *callt;
266 int rc = 0;
267
Harald Welte3e6376d2010-12-22 23:54:51 +0100268 /* find callref */
269 callref = data->callref;
270 llist_for_each_entry(callt, &call_list, entry) {
271 if (callt->callref == callref) {
272 call = callt;
273 break;
274 }
275 }
276
277 /* create callref, if setup is received */
278 if (!call) {
279 if (msg_type != MNCC_SETUP_IND)
Harald Welte29b64e92010-12-23 01:07:46 +0100280 goto out_free; /* drop */
Harald Welte3e6376d2010-12-22 23:54:51 +0100281 /* create call */
282 if (!(call = talloc_zero(tall_call_ctx, struct gsm_call))) {
283 struct gsm_mncc rel;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100284
Harald Welte3e6376d2010-12-22 23:54:51 +0100285 memset(&rel, 0, sizeof(struct gsm_mncc));
Neels Hofmeyr52558742019-05-09 01:23:09 +0200286 rel.msg_type = MNCC_REL_REQ;
Harald Welte3e6376d2010-12-22 23:54:51 +0100287 rel.callref = callref;
288 mncc_set_cause(&rel, GSM48_CAUSE_LOC_PRN_S_LU,
289 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200290 mncc_tx_to_cc(net, &rel);
Harald Welte29b64e92010-12-23 01:07:46 +0100291 goto out_free;
Harald Welte3e6376d2010-12-22 23:54:51 +0100292 }
293 llist_add_tail(&call->entry, &call_list);
294 call->net = net;
295 call->callref = callref;
296 DEBUGP(DMNCC, "(call %x) Call created.\n", call->callref);
297 }
298
Andreas Eversberg9acbe4c2013-03-11 08:12:43 +0100299 if (mncc_is_data_frame(msg_type)) {
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200300 LOGP(DMNCC, LOGL_ERROR, "(call %x) Received data frame, which is not supported.\n",
301 call->callref);
Andreas Eversberg9acbe4c2013-03-11 08:12:43 +0100302 goto out_free;
Harald Welte3e6376d2010-12-22 23:54:51 +0100303 }
304
Andreas Eversberg9acbe4c2013-03-11 08:12:43 +0100305 DEBUGP(DMNCC, "(call %x) Received message %s\n", call->callref,
306 get_mncc_name(msg_type));
307
Vadim Yanitskiy880a6932020-08-22 17:47:54 +0700308 switch (msg_type) {
Harald Welte3e6376d2010-12-22 23:54:51 +0100309 case MNCC_SETUP_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200310 rc = mncc_setup_ind(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100311 break;
312 case MNCC_SETUP_CNF:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200313 rc = mncc_setup_cnf(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100314 break;
315 case MNCC_SETUP_COMPL_IND:
316 break;
317 case MNCC_CALL_CONF_IND:
318 /* we now need to MODIFY the channel */
Neels Hofmeyr52558742019-05-09 01:23:09 +0200319 data->msg_type = MNCC_LCHAN_MODIFY;
320 mncc_tx_to_cc(call->net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100321 break;
322 case MNCC_ALERT_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200323 rc = mncc_alert_ind(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100324 break;
325 case MNCC_NOTIFY_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200326 rc = mncc_notify_ind(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100327 break;
328 case MNCC_DISC_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200329 rc = mncc_disc_ind(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100330 break;
331 case MNCC_REL_IND:
332 case MNCC_REJ_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200333 rc = mncc_rel_ind(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100334 break;
335 case MNCC_REL_CNF:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200336 rc = mncc_rel_cnf(call, arg);
Harald Welte3e6376d2010-12-22 23:54:51 +0100337 break;
338 case MNCC_FACILITY_IND:
339 break;
340 case MNCC_START_DTMF_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200341 data->msg_type = MNCC_START_DTMF_REJ;
342 rc = mncc_tx_to_cc(net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100343 break;
344 case MNCC_STOP_DTMF_IND:
Neels Hofmeyr52558742019-05-09 01:23:09 +0200345 data->msg_type = MNCC_STOP_DTMF_RSP;
346 rc = mncc_tx_to_cc(net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100347 break;
348 case MNCC_MODIFY_IND:
349 mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
350 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
351 DEBUGP(DMNCC, "(call %x) Rejecting MODIFY with cause %d\n",
352 call->callref, data->cause.value);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200353 data->msg_type = MNCC_MODIFY_REJ;
354 rc = mncc_tx_to_cc(net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100355 break;
356 case MNCC_MODIFY_CNF:
357 break;
358 case MNCC_HOLD_IND:
359 mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
360 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
361 DEBUGP(DMNCC, "(call %x) Rejecting HOLD with cause %d\n",
362 call->callref, data->cause.value);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200363 data->msg_type = MNCC_HOLD_REJ;
364 rc = mncc_tx_to_cc(net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100365 break;
366 case MNCC_RETRIEVE_IND:
367 mncc_set_cause(data, GSM48_CAUSE_LOC_PRN_S_LU,
368 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
369 DEBUGP(DMNCC, "(call %x) Rejecting RETRIEVE with cause %d\n",
370 call->callref, data->cause.value);
Neels Hofmeyr52558742019-05-09 01:23:09 +0200371 data->msg_type = MNCC_RETRIEVE_REJ;
372 rc = mncc_tx_to_cc(net, data);
Harald Welte3e6376d2010-12-22 23:54:51 +0100373 break;
Harald Welte3e6376d2010-12-22 23:54:51 +0100374 default:
Vadim Yanitskiy4d755592020-08-22 17:49:35 +0700375 LOGP(DMNCC, LOGL_NOTICE, "(call %x) Message '%s' unhandled\n",
376 callref, get_mncc_name(msg_type));
Harald Welte3e6376d2010-12-22 23:54:51 +0100377 break;
378 }
379
Harald Welte29b64e92010-12-23 01:07:46 +0100380out_free:
Holger Hans Peter Freythera8ddb082012-03-01 20:30:32 +0100381 msgb_free(msg);
Harald Welte29b64e92010-12-23 01:07:46 +0100382
Harald Welte3e6376d2010-12-22 23:54:51 +0100383 return rc;
384}