blob: 262bf98a3563de7e8b86683c283ae02180c753fa [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
23#include <openbsc/debug.h>
24#include <openbsc/gsm_data.h>
25#include <openbsc/msc_ifaces.h>
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020026#include <openbsc/gsm_subscriber.h>
27#include <openbsc/transaction.h>
28#include <openbsc/mgcp.h>
29#include <openbsc/mgcpgw_client.h>
30#include <openbsc/vlr.h>
Philipp Maierfbf66102017-04-09 12:32:51 +020031#include <openbsc/a_iface.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
42#include <openbsc/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 (!conn)
48 return -EINVAL;
49 if (!msg)
50 return -EINVAL;
51
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020052 DEBUGP(DMSC, "msc_tx %u bytes to %s via %s\n",
53 msg->len, vlr_subscr_name(conn->vsub),
54 ran_type_name(conn->via_ran));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020055 switch (conn->via_ran) {
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020056 case RAN_GERAN_A:
57 msg->dst = conn;
Philipp Maierfbf66102017-04-09 12:32:51 +020058 return a_iface_tx_dtap(msg);
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020059
60 case RAN_UTRAN_IU:
61 msg->dst = conn->iu.ue_ctx;
Neels Hofmeyr00e82d62017-07-05 15:19:52 +020062 return ranap_iu_tx(msg, 0);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020063
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020064 default:
65 LOGP(DMSC, LOGL_ERROR,
66 "msc_tx(): conn->via_ran invalid (%d)\n",
67 conn->via_ran);
68 return -1;
69 }
70}
71
72
73int msc_tx_dtap(struct gsm_subscriber_connection *conn,
74 struct msgb *msg)
75{
76 return msc_tx(conn, msg);
77}
78
79
80/* 9.2.5 CM service accept */
81int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
82{
Philipp Maierfbf66102017-04-09 12:32:51 +020083 struct msgb *msg;
84 struct gsm48_hdr *gh;
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020085
Philipp Maierfbf66102017-04-09 12:32:51 +020086 if (!conn)
87 return -EINVAL;
88
89 msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
90
91 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020092 gh->proto_discr = GSM48_PDISC_MM;
93 gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
94
Neels Hofmeyr84da6b12016-05-20 21:59:55 +020095 DEBUGP(DMM, "-> CM SERVICE ACCEPT %s\n",
96 vlr_subscr_name(conn->vsub));
Neels Hofmeyre2f24d52017-05-08 15:12:20 +020097
98 return msc_tx_dtap(conn, msg);
99}
100
101/* 9.2.6 CM service reject */
102int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
103 enum gsm48_reject_value value)
104{
105 struct msgb *msg;
Philipp Maierfbf66102017-04-09 12:32:51 +0200106
107 if (!conn)
108 return -EINVAL;
109
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200110 conn->received_cm_service_request = false;
Neels Hofmeyre2f24d52017-05-08 15:12:20 +0200111
112 msg = gsm48_create_mm_serv_rej(value);
113 if (!msg) {
114 LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
115 return -1;
116 }
117
118 DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
119
120 return msc_tx_dtap(conn, msg);
121}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200122
123int msc_tx_common_id(struct gsm_subscriber_connection *conn)
124{
Philipp Maierfbf66102017-04-09 12:32:51 +0200125 if (!conn)
126 return -EINVAL;
127
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200128 /* Common ID is only sent over IuCS */
129 if (conn->via_ran != RAN_UTRAN_IU) {
130 LOGP(DMM, LOGL_INFO,
131 "%s: Asked to transmit Common ID, but skipping"
132 " because this is not on UTRAN\n",
133 vlr_subscr_name(conn->vsub));
134 return 0;
135 }
136
137 DEBUGP(DIUCS, "%s: tx CommonID %s\n",
138 vlr_subscr_name(conn->vsub), conn->vsub->imsi);
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200139 return ranap_iu_tx_common_id(conn->iu.ue_ctx, conn->vsub->imsi);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200140}
141
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200142static int iu_rab_act_cs(struct ranap_ue_conn_ctx *uectx, uint8_t rab_id,
Philipp Maierfbf66102017-04-09 12:32:51 +0200143 uint32_t rtp_ip, uint16_t rtp_port)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200144{
Philipp Maierfbf66102017-04-09 12:32:51 +0200145#ifdef BUILD_IU
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200146 struct msgb *msg;
147 bool use_x213_nsap;
148 uint32_t conn_id = uectx->conn_id;
149
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200150 use_x213_nsap = (uectx->rab_assign_addr_enc == RANAP_NSAP_ADDR_ENC_X213);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200151
152 LOGP(DIUCS, LOGL_DEBUG, "Assigning RAB: conn_id=%u, rab_id=%d,"
153 " rtp=%x:%u, use_x213_nsap=%d\n", conn_id, rab_id, rtp_ip,
154 rtp_port, use_x213_nsap);
155
156 msg = ranap_new_msg_rab_assign_voice(rab_id, rtp_ip, rtp_port,
157 use_x213_nsap);
158 msg->l2h = msg->data;
159
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200160 if (ranap_iu_rab_act(uectx, msg))
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200161 LOGP(DIUCS, LOGL_ERROR, "Failed to send RAB Assignment:"
162 " conn_id=%d rab_id=%d rtp=%x:%u\n",
163 conn_id, rab_id, rtp_ip, rtp_port);
Philipp Maierfbf66102017-04-09 12:32:51 +0200164 return 0;
165#else
166 LOGP(DMSC, LOGL_ERROR, "Cannot send Iu RAB Assignment: built without Iu support\n");
167 return -ENOTSUP;
168#endif
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200169}
170
171static void mgcp_response_rab_act_cs_crcx(struct mgcp_response *r, void *priv)
172{
173 struct gsm_trans *trans = priv;
174 struct gsm_subscriber_connection *conn = trans->conn;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200175 uint32_t rtp_ip;
176 int rc;
177
178 if (r->head.response_code != 200) {
179 LOGP(DMGCP, LOGL_ERROR,
180 "MGCPGW response yields error: %d %s\n",
181 r->head.response_code, r->head.comment);
182 goto rab_act_cs_error;
183 }
184
185 rc = mgcp_response_parse_params(r);
186 if (rc) {
187 LOGP(DMGCP, LOGL_ERROR,
188 "Cannot parse MGCP response, for %s\n",
189 vlr_subscr_name(trans->vsub));
190 goto rab_act_cs_error;
191 }
192
Philipp Maierfbf66102017-04-09 12:32:51 +0200193 conn->rtp.port_cn = r->audio_port;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200194
195 rtp_ip = mgcpgw_client_remote_addr_n(conn->network->mgcpgw.client);
Philipp Maierfbf66102017-04-09 12:32:51 +0200196
197 if (trans->conn->via_ran == RAN_UTRAN_IU) {
198 /* Assign a voice channel via RANAP on 3G */
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200199 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 +0200200 goto rab_act_cs_error;
201 } else if (trans->conn->via_ran == RAN_GERAN_A) {
202 /* Assign a voice channel via A on 2G */
203 if (a_iface_tx_assignment(trans))
204 goto rab_act_cs_error;
205 } else
206 goto rab_act_cs_error;
207
208 /* Respond back to MNCC (if requested) */
209 if (trans->tch_rtp_create) {
210 if (gsm48_tch_rtp_create(trans))
211 goto rab_act_cs_error;
212 }
213 return;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200214
215rab_act_cs_error:
216 /* FIXME abort call, invalidate conn, ... */
Philipp Maierfbf66102017-04-09 12:32:51 +0200217 LOGP(DMSC, LOGL_ERROR, "%s: failure during assignment\n",
218 vlr_subscr_name(trans->vsub));
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200219 return;
220}
221
Philipp Maierfbf66102017-04-09 12:32:51 +0200222int msc_call_assignment(struct gsm_trans *trans)
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200223{
Philipp Maierfbf66102017-04-09 12:32:51 +0200224 struct gsm_subscriber_connection *conn;
225 struct mgcpgw_client *mgcp;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200226 struct msgb *msg;
Philipp Maierfbf66102017-04-09 12:32:51 +0200227 uint16_t bts_base;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200228
Philipp Maierfbf66102017-04-09 12:32:51 +0200229 if (!trans)
230 return -EINVAL;
231 if (!trans->conn)
232 return -EINVAL;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200233
Philipp Maierfbf66102017-04-09 12:32:51 +0200234 conn = trans->conn;
235 mgcp = conn->network->mgcpgw.client;
236
237#ifdef BUILD_IU
Neels Hofmeyr00e82d62017-07-05 15:19:52 +0200238 /* FIXME: HACK. where to scope the RAB Id? At the conn / subscriber / ranap_ue_conn_ctx? */
Philipp Maierfbf66102017-04-09 12:32:51 +0200239 static uint8_t next_iu_rab_id = 1;
240 if (conn->via_ran == RAN_UTRAN_IU)
241 conn->iu.rab_id = next_iu_rab_id ++;
242#endif
243
244 conn->rtp.mgcp_rtp_endpoint =
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200245 mgcpgw_client_next_endpoint(conn->network->mgcpgw.client);
Philipp Maierfbf66102017-04-09 12:32:51 +0200246
247 /* This will calculate the port we assign to the BTS via AoIP
248 * assignment command (or rab-assignment on 3G) The BTS will send
249 * its RTP traffic to that port on the MGCPGW side. The MGCPGW only
250 * gets the endpoint ID via the CRCX. It will do the same calculation
251 * on his side too to get knowledge of the rtp port. */
252 bts_base = mgcp->actual.bts_base;
253 conn->rtp.port_subscr = bts_base + 2 * conn->rtp.mgcp_rtp_endpoint;
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200254
255 /* Establish the RTP stream first as looping back to the originator.
256 * The MDCX will patch through to the counterpart. TODO: play a ring
257 * tone instead. */
Philipp Maierfbf66102017-04-09 12:32:51 +0200258 msg = mgcp_msg_crcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
259 conn->rtp.mgcp_rtp_endpoint, MGCP_CONN_LOOPBACK);
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200260 return mgcpgw_client_tx(mgcp, msg, mgcp_response_rab_act_cs_crcx, trans);
261}
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200262
263static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv);
264
265static void mgcp_bridge(struct gsm_trans *from, struct gsm_trans *to,
266 enum bridge_state state,
267 enum mgcp_connection_mode mode)
268{
269 struct gsm_subscriber_connection *conn1 = from->conn;
270 struct gsm_subscriber_connection *conn2 = to->conn;
271 struct mgcpgw_client *mgcp = conn1->network->mgcpgw.client;
272 const char *ip;
273 struct msgb *msg;
274
275 OSMO_ASSERT(mgcp);
276
277 from->bridge.peer = to;
278 from->bridge.state = state;
279
280 /* Loop back to the same MGCP GW */
281 ip = mgcpgw_client_remote_addr_str(mgcp);
282
283 msg = mgcp_msg_mdcx(mgcp,
Philipp Maierfbf66102017-04-09 12:32:51 +0200284 conn1->rtp.mgcp_rtp_endpoint,
285 ip, conn2->rtp.port_cn,
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200286 mode);
287 if (mgcpgw_client_tx(mgcp, msg, mgcp_response_bridge_mdcx, from))
288 LOGP(DMGCP, LOGL_ERROR,
289 "Failed to send MDCX message for %s\n",
290 vlr_subscr_name(from->vsub));
291}
292
293static void mgcp_response_bridge_mdcx(struct mgcp_response *r, void *priv)
294{
295 struct gsm_trans *trans = priv;
296 struct gsm_trans *peer = trans->bridge.peer;
297
298 switch (trans->bridge.state) {
299 case BRIDGE_STATE_LOOPBACK_PENDING:
300 trans->bridge.state = BRIDGE_STATE_LOOPBACK_ESTABLISHED;
301
302 switch (peer->bridge.state) {
303 case BRIDGE_STATE_LOOPBACK_PENDING:
304 /* Wait until the other is done as well. */
305 return;
306 case BRIDGE_STATE_LOOPBACK_ESTABLISHED:
307 /* Now that both are in loopback, switch both to
308 * forwarding. */
309 mgcp_bridge(trans, peer, BRIDGE_STATE_BRIDGE_PENDING,
310 MGCP_CONN_RECV_SEND);
311 mgcp_bridge(peer, trans, BRIDGE_STATE_BRIDGE_PENDING,
312 MGCP_CONN_RECV_SEND);
313 break;
314 default:
315 LOGP(DMGCP, LOGL_ERROR,
316 "Unexpected bridge state: %d for %s\n",
317 trans->bridge.state, vlr_subscr_name(trans->vsub));
318 break;
319 }
320 break;
321
322 case BRIDGE_STATE_BRIDGE_PENDING:
323 trans->bridge.state = BRIDGE_STATE_BRIDGE_ESTABLISHED;
324 break;
325
326 default:
327 LOGP(DMGCP, LOGL_ERROR,
328 "Unexpected bridge state: %d for %s\n",
329 trans->bridge.state, vlr_subscr_name(trans->vsub));
330 break;
331 }
332}
333
Philipp Maierfbf66102017-04-09 12:32:51 +0200334int msc_call_connect(struct gsm_trans *trans, uint16_t port, uint32_t ip)
335{
336 /* With this function we inform the MGCP-GW where (ip/port) it
337 * has to send its outgoing voic traffic. The receiving end will
338 * usually be a PBX (e.g. Asterisk). The IP-Address we tell, will
339 * not only be used to direct the traffic, it will also be used
340 * as a filter to make sure only RTP packets from the right
341 * remote end will reach the BSS. This is also the reason why
342 * inbound audio will not work until this step is performed */
343
344 /* NOTE: This function is used when msc_call_bridge(), is not
345 * applicable. This is usually the case when an external MNCC
346 * is in use */
347
348 struct gsm_subscriber_connection *conn;
349 struct mgcpgw_client *mgcp;
350 struct msgb *msg;
351
352 if (!trans)
353 return -EINVAL;
354 if (!trans->conn)
355 return -EINVAL;
356 if (!trans->conn->network)
357 return -EINVAL;
358 if (!trans->conn->network->mgcpgw.client)
359 return -EINVAL;
360
361 mgcp = trans->conn->network->mgcpgw.client;
362
363 struct in_addr ip_addr;
364 ip_addr.s_addr = ntohl(ip);
365
366 conn = trans->conn;
367
368 msg = mgcp_msg_mdcx(mgcp,
369 conn->rtp.mgcp_rtp_endpoint,
370 inet_ntoa(ip_addr), port, MGCP_CONN_RECV_SEND);
371 if (mgcpgw_client_tx(mgcp, msg, NULL, trans))
372 LOGP(DMGCP, LOGL_ERROR,
373 "Failed to send MDCX message for %s\n",
374 vlr_subscr_name(trans->vsub));
375
376 return 0;
377}
378
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200379int msc_call_bridge(struct gsm_trans *trans1, struct gsm_trans *trans2)
380{
Philipp Maierfbf66102017-04-09 12:32:51 +0200381 if (!trans1)
382 return -EINVAL;
383 if (!trans2)
384 return -EINVAL;
385
Neels Hofmeyr84da6b12016-05-20 21:59:55 +0200386 /* First setup as loopback and configure the counterparts' endpoints,
387 * so that when transmission starts the originating addresses are
388 * already known to be valid. The mgcp callback will continue. */
389 mgcp_bridge(trans1, trans2, BRIDGE_STATE_LOOPBACK_PENDING,
390 MGCP_CONN_LOOPBACK);
391 mgcp_bridge(trans2, trans1, BRIDGE_STATE_LOOPBACK_PENDING,
392 MGCP_CONN_LOOPBACK);
393
394 return 0;
395}
Philipp Maierfbf66102017-04-09 12:32:51 +0200396
397void msc_call_release(struct gsm_trans *trans)
398{
399 struct msgb *msg;
400 struct gsm_subscriber_connection *conn;
401 struct mgcpgw_client *mgcp;
402
403 if (!trans)
404 return;
405 if (!trans->conn)
406 return;
407 if (!trans->conn->network)
408 return;
409
410 conn = trans->conn;
411 mgcp = conn->network->mgcpgw.client;
412
413 /* Send DLCX */
414 msg = mgcp_msg_dlcx(mgcp, conn->rtp.mgcp_rtp_endpoint,
415 conn->rtp.mgcp_rtp_endpoint);
416 if (mgcpgw_client_tx(mgcp, msg, NULL, NULL))
417 LOGP(DMGCP, LOGL_ERROR,
418 "Failed to send DLCX message for %s\n",
419 vlr_subscr_name(trans->vsub));
420
421 /* Release endpoint id */
422 mgcpgw_client_release_endpoint(conn->rtp.mgcp_rtp_endpoint, mgcp);
423}