blob: e29fe0e879528ed8b027214410fab996ea0b7f80 [file] [log] [blame]
Neels Hofmeyre2f24d52017-05-08 15:12:20 +02001/* Implementation for MSC decisions which interface to send messages out on. */
2
3/* (C) 2016 by sysmocom s.m.f.c GmbH <info@sysmocom.de>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <osmocom/core/logging.h>
22
Neels Hofmeyr90843962017-09-04 15:04:35 +020023#include <osmocom/msc/debug.h>
24#include <osmocom/msc/gsm_data.h>
25#include <osmocom/msc/msc_ifaces.h>
26#include <osmocom/msc/gsm_subscriber.h>
27#include <osmocom/msc/transaction.h>
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +020028#include <osmocom/mgcp_client/mgcp_client.h>
Neels Hofmeyr90843962017-09-04 15:04:35 +020029#include <osmocom/msc/vlr.h>
30#include <osmocom/msc/a_iface.h>
Max43b01b02017-09-15 11:22:30 +020031#include <osmocom/msc/gsm_04_08.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020032
33#include "../../bscconfig.h"
34
35#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020036#include <osmocom/ranap/iu_client.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020037extern struct msgb *ranap_new_msg_rab_assign_voice(uint8_t rab_id,
38 uint32_t rtp_ip,
39 uint16_t rtp_port,
40 bool use_x213_nsap);
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020041#else
Neels Hofmeyr90843962017-09-04 15:04:35 +020042#include <osmocom/msc/iu_dummy.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020043#endif /* BUILD_IU */
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020044
45static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
46{
Philipp Maierfbf66102017-04-09 12:32:51 +020047 if (!msg)
48 return -EINVAL;
Philipp Maier4502f5f2017-09-07 11:39:58 +020049 if (!conn) {
50 msgb_free(msg);
51 return -EINVAL;
52 }
Philipp Maierfbf66102017-04-09 12:32:51 +020053
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020054 DEBUGP(DMSC, "msc_tx %u bytes to %s via %s\n",
55 msg->len, vlr_subscr_name(conn->vsub),
56 ran_type_name(conn->via_ran));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020057 switch (conn->via_ran) {
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020058 case RAN_GERAN_A:
59 msg->dst = conn;
Philipp Maierfbf66102017-04-09 12:32:51 +020060 return a_iface_tx_dtap(msg);
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020061
62 case RAN_UTRAN_IU:
63 msg->dst = conn->iu.ue_ctx;
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020064 return ranap_iu_tx(msg, 0);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020065
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020066 default:
67 LOGP(DMSC, LOGL_ERROR,
68 "msc_tx(): conn->via_ran invalid (%d)\n",
69 conn->via_ran);
Philipp Maier4502f5f2017-09-07 11:39:58 +020070 msgb_free(msg);
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020071 return -1;
72 }
73}
74
75
76int msc_tx_dtap(struct gsm_subscriber_connection *conn,
77 struct msgb *msg)
78{
79 return msc_tx(conn, msg);
80}
81
82
83/* 9.2.5 CM service accept */
84int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
85{
Philipp Maierfbf66102017-04-09 12:32:51 +020086 struct msgb *msg;
87 struct gsm48_hdr *gh;
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020088
Philipp Maierfbf66102017-04-09 12:32:51 +020089 if (!conn)
90 return -EINVAL;
91
92 msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
93
94 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020095 gh->proto_discr = GSM48_PDISC_MM;
96 gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
97
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020098 DEBUGP(DMM, "-> CM SERVICE ACCEPT %s\n",
99 vlr_subscr_name(conn->vsub));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200100
101 return msc_tx_dtap(conn, msg);
102}
103
104/* 9.2.6 CM service reject */
105int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
106 enum gsm48_reject_value value)
107{
108 struct msgb *msg;
Philipp Maierfbf66102017-04-09 12:32:51 +0200109
110 if (!conn)
111 return -EINVAL;
112
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200113 conn->received_cm_service_request = false;
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200114
115 msg = gsm48_create_mm_serv_rej(value);
116 if (!msg) {
117 LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
118 return -1;
119 }
120
121 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
122
123 return msc_tx_dtap(conn, msg);
124}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200125
126int msc_tx_common_id(struct gsm_subscriber_connection *conn)
127{
Philipp Maierfbf66102017-04-09 12:32:51 +0200128 if (!conn)
129 return -EINVAL;
130
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200131 /* Common ID is only sent over IuCS */
132 if (conn->via_ran != RAN_UTRAN_IU) {
133 LOGP(DMM, LOGL_INFO,
134 "%s: Asked to transmit Common ID, but skipping"
135 " because this is not on UTRAN\n",
136 vlr_subscr_name(conn->vsub));
137 return 0;
138 }
139
140 DEBUGP(DIUCS, "%s: tx CommonID %s\n",
141 vlr_subscr_name(conn->vsub), conn->vsub->imsi);
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200142 return ranap_iu_tx_common_id(conn->iu.ue_ctx, conn->vsub->imsi);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200143}
144
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200145static int iu_rab_act_cs(struct ranap_ue_conn_ctx *uectx, uint8_t rab_id,
Philipp Maierfbf66102017-04-09 12:32:51 +0200146 uint32_t rtp_ip, uint16_t rtp_port)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200147{
Philipp Maierfbf66102017-04-09 12:32:51 +0200148#ifdef BUILD_IU
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200149 struct msgb *msg;
150 bool use_x213_nsap;
151 uint32_t conn_id = uectx->conn_id;
152
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200153 use_x213_nsap = (uectx->rab_assign_addr_enc == RANAP_NSAP_ADDR_ENC_X213);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200154
155 LOGP(DIUCS, LOGL_DEBUG, "Assigning RAB: conn_id=%u, rab_id=%d,"
156 " rtp=%x:%u, use_x213_nsap=%d\n", conn_id, rab_id, rtp_ip,
157 rtp_port, use_x213_nsap);
158
159 msg = ranap_new_msg_rab_assign_voice(rab_id, rtp_ip, rtp_port,
160 use_x213_nsap);
161 msg->l2h = msg->data;
162
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200163 if (ranap_iu_rab_act(uectx, msg))
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200164 LOGP(DIUCS, LOGL_ERROR, "Failed to send RAB Assignment:"
165 " conn_id=%d rab_id=%d rtp=%x:%u\n",
166 conn_id, rab_id, rtp_ip, rtp_port);
Philipp Maierfbf66102017-04-09 12:32:51 +0200167 return 0;
168#else
169 LOGP(DMSC, LOGL_ERROR, "Cannot send Iu RAB Assignment: built without Iu support\n");
170 return -ENOTSUP;
171#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200172}
173
174static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
175{
176 struct gsm_trans *trans = priv;
177 struct gsm_subscriber_connection *conn = trans->conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200178 uint32_t rtp_ip;
179 int rc;
180
181 if (r->head.response_code != 200) {
182 LOGP(DMGCP, LOGL_ERROR,
183 "MGCPGW response yields error: %d %s\n",
184 r->head.response_code, r->head.comment);
185 goto rab_act_cs_error;
186 }
187
188 rc = mgcp_response_parse_params(r);
189 if (rc) {
190 LOGP(DMGCP, LOGL_ERROR,
191 "Cannot parse MGCP response, for %s\n",
192 vlr_subscr_name(trans->vsub));
193 goto rab_act_cs_error;
194 }
195
Philipp Maierfbf66102017-04-09 12:32:51 +0200196 conn->rtp.port_cn = r->audio_port;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200197
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200198 rtp_ip = mgcp_client_remote_addr_n(conn->network->mgw.client);
Philipp Maierfbf66102017-04-09 12:32:51 +0200199
200 if (trans->conn->via_ran == RAN_UTRAN_IU) {
201 /* Assign a voice channel via RANAP on 3G */
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200202 if (iu_rab_act_cs(conn->iu.ue_ctx, conn->iu.rab_id, rtp_ip, conn->rtp.port_subscr))
Philipp Maierfbf66102017-04-09 12:32:51 +0200203 goto rab_act_cs_error;
204 } else if (trans->conn->via_ran == RAN_GERAN_A) {
205 /* Assign a voice channel via A on 2G */
206 if (a_iface_tx_assignment(trans))
207 goto rab_act_cs_error;
208 } else
209 goto rab_act_cs_error;
210
211 /* Respond back to MNCC (if requested) */
212 if (trans->tch_rtp_create) {
213 if (gsm48_tch_rtp_create(trans))
214 goto rab_act_cs_error;
215 }
216 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200217
218rab_act_cs_error:
219 /* FIXME abort call, invalidate conn, ... */
Philipp Maierfbf66102017-04-09 12:32:51 +0200220 LOGP(DMSC, LOGL_ERROR, "%s: failure during assignment\n",
221 vlr_subscr_name(trans->vsub));
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200222 return;
223}
224
Philipp Maierfbf66102017-04-09 12:32:51 +0200225int msc_call_assignment(struct gsm_trans *trans)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200226{
Philipp Maierfbf66102017-04-09 12:32:51 +0200227 struct gsm_subscriber_connection *conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200228 struct mgcp_client *mgcp;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200229 struct msgb *msg;
Philipp Maierfbf66102017-04-09 12:32:51 +0200230 uint16_t bts_base;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200231
Philipp Maierfbf66102017-04-09 12:32:51 +0200232 if (!trans)
233 return -EINVAL;
234 if (!trans->conn)
235 return -EINVAL;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200236
Philipp Maierfbf66102017-04-09 12:32:51 +0200237 conn = trans->conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200238 mgcp = conn->network->mgw.client;
Philipp Maierfbf66102017-04-09 12:32:51 +0200239
240#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200241 /* FIXME: HACK. where to scope the RAB Id? At the conn / subscriber / ranap_ue_conn_ctx? */
Philipp Maierfbf66102017-04-09 12:32:51 +0200242 static uint8_t next_iu_rab_id = 1;
243 if (conn->via_ran == RAN_UTRAN_IU)
244 conn->iu.rab_id = next_iu_rab_id ++;
245#endif
246
247 conn->rtp.mgcp_rtp_endpoint =
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200248 mgcp_client_next_endpoint(conn->network->mgw.client);
Philipp Maierfbf66102017-04-09 12:32:51 +0200249
250 /* This will calculate the port we assign to the BTS via AoIP
251 * assignment command (or rab-assignment on 3G) The BTS will send
252 * its RTP traffic to that port on the MGCPGW side. The MGCPGW only
253 * gets the endpoint ID via the CRCX. It will do the same calculation
254 * on his side too to get knowledge of the rtp port. */
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200255 bts_base = mgcp_client_conf_actual(mgcp)->bts_base;
Philipp Maierfbf66102017-04-09 12:32:51 +0200256 conn->rtp.port_subscr = bts_base + 2 * conn->rtp.mgcp_rtp_endpoint;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200257
258 /* Establish the RTP stream first as looping back to the originator.
259 * The MDCX will patch through to the counterpart. TODO: play a ring
260 * tone instead. */
Philipp Maierfbf66102017-04-09 12:32:51 +0200261 msg = mgcp_msg_crcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
262 conn->rtp.mgcp_rtp_endpoint, MGCP_CONN_LOOPBACK);
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200263 return mgcp_client_tx(mgcp, msg, mgcp_response_rab_act_cs_crcx, trans);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200264}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200265
266static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv);
267
268static void mgcp_bridge(struct gsm_trans *from, struct gsm_trans *to,
269 enum bridge_state state,
270 enum mgcp_connection_mode mode)
271{
272 struct gsm_subscriber_connection *conn1 = from->conn;
273 struct gsm_subscriber_connection *conn2 = to->conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200274 struct mgcp_client *mgcp = conn1->network->mgw.client;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200275 const char *ip;
276 struct msgb *msg;
277
278 OSMO_ASSERT(mgcp);
279
280 from->bridge.peer = to;
281 from->bridge.state = state;
282
283 /* Loop back to the same MGCP GW */
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200284 ip = mgcp_client_remote_addr_str(mgcp);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200285
286 msg = mgcp_msg_mdcx(mgcp,
Philipp Maierfbf66102017-04-09 12:32:51 +0200287 conn1->rtp.mgcp_rtp_endpoint,
288 ip, conn2->rtp.port_cn,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200289 mode);
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200290 if (mgcp_client_tx(mgcp, msg, mgcp_response_bridge_mdcx, from))
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200291 LOGP(DMGCP, LOGL_ERROR,
292 "Failed to send MDCX message for %s\n",
293 vlr_subscr_name(from->vsub));
294}
295
296static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
297{
298 struct gsm_trans *trans = priv;
299 struct gsm_trans *peer = trans->bridge.peer;
300
301 switch (trans->bridge.state) {
302 case BRIDGE_STATE_LOOPBACK_PENDING:
303 trans->bridge.state = BRIDGE_STATE_LOOPBACK_ESTABLISHED;
304
305 switch (peer->bridge.state) {
306 case BRIDGE_STATE_LOOPBACK_PENDING:
307 /* Wait until the other is done as well. */
308 return;
309 case BRIDGE_STATE_LOOPBACK_ESTABLISHED:
310 /* Now that both are in loopback, switch both to
311 * forwarding. */
312 mgcp_bridge(trans, peer, BRIDGE_STATE_BRIDGE_PENDING,
313 MGCP_CONN_RECV_SEND);
314 mgcp_bridge(peer, trans, BRIDGE_STATE_BRIDGE_PENDING,
315 MGCP_CONN_RECV_SEND);
316 break;
317 default:
318 LOGP(DMGCP, LOGL_ERROR,
319 "Unexpected bridge state: %d for %s\n",
320 trans->bridge.state, vlr_subscr_name(trans->vsub));
321 break;
322 }
323 break;
324
325 case BRIDGE_STATE_BRIDGE_PENDING:
326 trans->bridge.state = BRIDGE_STATE_BRIDGE_ESTABLISHED;
327 break;
328
329 default:
330 LOGP(DMGCP, LOGL_ERROR,
331 "Unexpected bridge state: %d for %s\n",
332 trans->bridge.state, vlr_subscr_name(trans->vsub));
333 break;
334 }
335}
336
Philipp Maierfbf66102017-04-09 12:32:51 +0200337int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip)
338{
339 /* With this function we inform the MGCP-GW where (ip/port) it
340 * has to send its outgoing voic traffic. The receiving end will
341 * usually be a PBX (e.g. Asterisk). The IP-Address we tell, will
342 * not only be used to direct the traffic, it will also be used
343 * as a filter to make sure only RTP packets from the right
344 * remote end will reach the BSS. This is also the reason why
345 * inbound audio will not work until this step is performed */
346
347 /* NOTE: This function is used when msc_call_bridge(), is not
348 * applicable. This is usually the case when an external MNCC
349 * is in use */
350
351 struct gsm_subscriber_connection *conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200352 struct mgcp_client *mgcp;
Philipp Maierfbf66102017-04-09 12:32:51 +0200353 struct msgb *msg;
354
355 if (!trans)
356 return -EINVAL;
357 if (!trans->conn)
358 return -EINVAL;
359 if (!trans->conn->network)
360 return -EINVAL;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200361 if (!trans->conn->network->mgw.client)
Philipp Maierfbf66102017-04-09 12:32:51 +0200362 return -EINVAL;
363
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200364 mgcp = trans->conn->network->mgw.client;
Philipp Maierfbf66102017-04-09 12:32:51 +0200365
366 struct in_addr ip_addr;
367 ip_addr.s_addr = ntohl(ip);
368
369 conn = trans->conn;
370
371 msg = mgcp_msg_mdcx(mgcp,
372 conn->rtp.mgcp_rtp_endpoint,
373 inet_ntoa(ip_addr), port, MGCP_CONN_RECV_SEND);
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200374 if (mgcp_client_tx(mgcp, msg, NULL, trans))
Philipp Maierfbf66102017-04-09 12:32:51 +0200375 LOGP(DMGCP, LOGL_ERROR,
376 "Failed to send MDCX message for %s\n",
377 vlr_subscr_name(trans->vsub));
378
379 return 0;
380}
381
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200382int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2)
383{
Philipp Maierfbf66102017-04-09 12:32:51 +0200384 if (!trans1)
385 return -EINVAL;
386 if (!trans2)
387 return -EINVAL;
388
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200389 /* First setup as loopback and configure the counterparts' endpoints,
390 * so that when transmission starts the originating addresses are
391 * already known to be valid. The mgcp callback will continue. */
392 mgcp_bridge(trans1, trans2, BRIDGE_STATE_LOOPBACK_PENDING,
393 MGCP_CONN_LOOPBACK);
394 mgcp_bridge(trans2, trans1, BRIDGE_STATE_LOOPBACK_PENDING,
395 MGCP_CONN_LOOPBACK);
396
397 return 0;
398}
Philipp Maierfbf66102017-04-09 12:32:51 +0200399
400void msc_call_release(struct gsm_trans *trans)
401{
402 struct msgb *msg;
403 struct gsm_subscriber_connection *conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200404 struct mgcp_client *mgcp;
Philipp Maierfbf66102017-04-09 12:32:51 +0200405
406 if (!trans)
407 return;
408 if (!trans->conn)
409 return;
410 if (!trans->conn->network)
411 return;
412
413 conn = trans->conn;
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200414 mgcp = conn->network->mgw.client;
Philipp Maierfbf66102017-04-09 12:32:51 +0200415
416 /* Send DLCX */
417 msg = mgcp_msg_dlcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
418 conn->rtp.mgcp_rtp_endpoint);
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200419 if (mgcp_client_tx(mgcp, msg, NULL, NULL))
Philipp Maierfbf66102017-04-09 12:32:51 +0200420 LOGP(DMGCP, LOGL_ERROR,
421 "Failed to send DLCX message for %s\n",
422 vlr_subscr_name(trans->vsub));
423
424 /* Release endpoint id */
Neels Hofmeyr6c8afe12017-09-04 01:03:58 +0200425 mgcp_client_release_endpoint(conn->rtp.mgcp_rtp_endpoint, mgcp);
Philipp Maierfbf66102017-04-09 12:32:51 +0200426}