blob: 4aa34224bfde32da5a5e059184f605db40d660e5 [file] [log] [blame]
Harald Weltec4338de2015-12-24 00:40:52 +01001/* IuCS/IuPS Core Network interface of HNB-GW */
2
3/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * 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
9 * (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
14 * GNU Affero General Public License for more details.
15 *
16 * 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/>.
18 *
19 */
20
Neels Hofmeyr37017f52016-04-15 22:47:21 +020021#include <arpa/inet.h>
22
Harald Weltec4338de2015-12-24 00:40:52 +010023#include <osmocom/core/msgb.h>
24#include <osmocom/core/utils.h>
25#include <osmocom/core/timer.h>
26
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020027#include <osmocom/sigtran/protocol/m3ua.h>
Harald Weltec4338de2015-12-24 00:40:52 +010028#include <osmocom/sigtran/sccp_sap.h>
Neels Hofmeyr3da86082016-03-30 12:36:15 +020029#include <osmocom/sigtran/sccp_helpers.h>
Harald Weltec4338de2015-12-24 00:40:52 +010030
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020031#include <osmocom/iuh/hnbgw.h>
32#include <osmocom/iuh/hnbgw_rua.h>
Neels Hofmeyr96979af2016-01-05 15:19:44 +010033#include <osmocom/ranap/ranap_ies_defs.h>
34#include <osmocom/ranap/ranap_msg_factory.h>
Neels Hofmeyrdf63de22016-08-18 13:13:55 +020035#include <osmocom/iuh/context_map.h>
Harald Weltec4338de2015-12-24 00:40:52 +010036
Harald Weltec4338de2015-12-24 00:40:52 +010037/***********************************************************************
38 * Outbound RANAP RESET to CN
39 ***********************************************************************/
40
41int hnbgw_cnlink_change_state(struct hnbgw_cnlink *cnlink, enum hnbgw_cnlink_state state);
42
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020043static int transmit_rst(struct hnb_gw *gw, RANAP_CN_DomainIndicator_t domain,
44 struct osmo_sccp_addr *remote_addr)
Harald Weltec4338de2015-12-24 00:40:52 +010045{
46 struct msgb *msg;
47 struct msgb *msgprim;
Harald Weltec4338de2015-12-24 00:40:52 +010048 RANAP_Cause_t cause = {
49 .present = RANAP_Cause_PR_transmissionNetwork,
50 .choice. transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure,
51 };
52
Harald Weltec4338de2015-12-24 00:40:52 +010053 msg = ranap_new_msg_reset(domain, &cause);
54
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020055 return osmo_sccp_tx_unitdata_msg(gw->sccp.cnlink->sccp_user,
56 &gw->sccp.local_addr,
57 remote_addr,
58 msg);
Harald Weltec4338de2015-12-24 00:40:52 +010059}
60
61/* Timer callback once T_RafC expires */
62static void cnlink_trafc_cb(void *data)
63{
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020064 struct hnb_gw *gw = data;
Harald Weltec4338de2015-12-24 00:40:52 +010065
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +020066 transmit_rst(gw, RANAP_CN_DomainIndicator_cs_domain, &gw->sccp.iucs_remote_addr);
67 transmit_rst(gw, RANAP_CN_DomainIndicator_ps_domain, &gw->sccp.iups_remote_addr);
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020068 hnbgw_cnlink_change_state(gw->sccp.cnlink, CNLINK_S_EST_RST_TX_WAIT_ACK);
Harald Weltec4338de2015-12-24 00:40:52 +010069 /* The spec states that we should abandon after a configurable
70 * number of times. We decide to simply continue trying */
71}
72
73/* change the state of a CN Link */
74int hnbgw_cnlink_change_state(struct hnbgw_cnlink *cnlink, enum hnbgw_cnlink_state state)
75{
76 switch (state) {
77 case CNLINK_S_NULL:
78 case CNLINK_S_EST_PEND:
79 break;
80 case CNLINK_S_EST_CONF:
Neels Hofmeyr0f88c112017-07-03 16:49:43 +020081 cnlink_trafc_cb(cnlink->gw);
Harald Weltec4338de2015-12-24 00:40:52 +010082 break;
83 case CNLINK_S_EST_RST_TX_WAIT_ACK:
84 osmo_timer_schedule(&cnlink->T_RafC, 5, 0);
85 break;
86 case CNLINK_S_EST_ACTIVE:
87 osmo_timer_del(&cnlink->T_RafC);
88 break;
89 }
90}
91
92/***********************************************************************
93 * Incoming primitives from SCCP User SAP
94 ***********************************************************************/
95
96static int cn_ranap_rx_reset_cmd(struct hnbgw_cnlink *cnlink,
97 RANAP_InitiatingMessage_t *imsg)
98{
99 RANAP_ResetIEs_t ies;
100 int rc;
101
102 rc = ranap_decode_reseties(&ies, &imsg->value);
103 /* FIXME: reset resources and return reset ack */
Daniel Willmann11e912a2016-01-07 13:19:30 +0100104
105 ranap_free_reseties(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100106 return rc;
107}
108
109static int cn_ranap_rx_reset_ack(struct hnbgw_cnlink *cnlink,
110 RANAP_SuccessfulOutcome_t *omsg)
111{
112 RANAP_ResetAcknowledgeIEs_t ies;
113 int rc;
114
115 rc = ranap_decode_resetacknowledgeies(&ies, &omsg->value);
116
117 hnbgw_cnlink_change_state(cnlink, CNLINK_S_EST_ACTIVE);
118
Daniel Willmann11e912a2016-01-07 13:19:30 +0100119 ranap_free_resetacknowledgeies(&ies);
Harald Weltec4338de2015-12-24 00:40:52 +0100120 return rc;
121}
122
123static int cn_ranap_rx_paging_cmd(struct hnbgw_cnlink *cnlink,
Harald Weltebc4560c2015-12-24 08:46:58 +0100124 RANAP_InitiatingMessage_t *imsg,
125 const uint8_t *data, unsigned int len)
Harald Weltec4338de2015-12-24 00:40:52 +0100126{
Neels Hofmeyr2b01f3a2016-04-19 17:57:03 +0200127 struct hnb_gw *gw = cnlink->gw;
Harald Weltebc4560c2015-12-24 08:46:58 +0100128 struct hnb_context *hnb;
Harald Weltec4338de2015-12-24 00:40:52 +0100129 RANAP_PagingIEs_t ies;
Harald Weltebc4560c2015-12-24 08:46:58 +0100130 int rc = 0;
Harald Weltec4338de2015-12-24 00:40:52 +0100131
132 rc = ranap_decode_pagingies(&ies, &imsg->value);
133
Harald Weltebc4560c2015-12-24 08:46:58 +0100134 /* FIXME: determine which HNBs to send this Paging command,
135 * rather than broadcasting to all HNBs */
136 llist_for_each_entry(hnb, &gw->hnb_list, list) {
137 rc = rua_tx_udt(hnb, data, len);
138 }
Daniel Willmann11e912a2016-01-07 13:19:30 +0100139
140 ranap_free_pagingies(&ies);
Harald Weltebc4560c2015-12-24 08:46:58 +0100141 return 0;
Harald Weltec4338de2015-12-24 00:40:52 +0100142}
143
144static int cn_ranap_rx_initiating_msg(struct hnbgw_cnlink *cnlink,
Harald Weltebc4560c2015-12-24 08:46:58 +0100145 RANAP_InitiatingMessage_t *imsg,
146 const uint8_t *data, unsigned int len)
Harald Weltec4338de2015-12-24 00:40:52 +0100147{
148 int rc;
149
150 switch (imsg->procedureCode) {
151 case RANAP_ProcedureCode_id_Reset:
152 return cn_ranap_rx_reset_cmd(cnlink, imsg);
153 case RANAP_ProcedureCode_id_Paging:
Harald Weltebc4560c2015-12-24 08:46:58 +0100154 return cn_ranap_rx_paging_cmd(cnlink, imsg, data, len);
Harald Weltec4338de2015-12-24 00:40:52 +0100155 case RANAP_ProcedureCode_id_OverloadControl: /* Overload ind */
156 break;
157 case RANAP_ProcedureCode_id_ErrorIndication: /* Error ind */
158 break;
159 case RANAP_ProcedureCode_id_ResetResource: /* request */
160 case RANAP_ProcedureCode_id_InformationTransfer:
161 case RANAP_ProcedureCode_id_DirectInformationTransfer:
162 case RANAP_ProcedureCode_id_UplinkInformationExchange:
163 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
164 "Procedure %u from CN, ignoring\n", imsg->procedureCode);
165 break;
166 default:
167 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
168 "Procedure %u from CN, ignoring\n", imsg->procedureCode);
169 break;
170 }
171 return 0;
172}
173
174static int cn_ranap_rx_successful_msg(struct hnbgw_cnlink *cnlink,
175 RANAP_SuccessfulOutcome_t *omsg)
176{
177 int rc;
178
179 switch (omsg->procedureCode) {
180 case RANAP_ProcedureCode_id_Reset: /* Reset acknowledge */
181 return cn_ranap_rx_reset_ack(cnlink, omsg);
182 case RANAP_ProcedureCode_id_ResetResource: /* response */
183 case RANAP_ProcedureCode_id_InformationTransfer:
184 case RANAP_ProcedureCode_id_DirectInformationTransfer:
185 case RANAP_ProcedureCode_id_UplinkInformationExchange:
186 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
187 "Procedure %u from CN, ignoring\n", omsg->procedureCode);
188 break;
189 default:
190 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
191 "Procedure %u from CN, ignoring\n", omsg->procedureCode);
192 break;
193 }
194 return 0;
195}
196
197
Harald Weltebc4560c2015-12-24 08:46:58 +0100198static int _cn_ranap_rx(struct hnbgw_cnlink *cnlink, RANAP_RANAP_PDU_t *pdu,
199 const uint8_t *data, unsigned int len)
Harald Weltec4338de2015-12-24 00:40:52 +0100200{
201 int rc;
202
203 switch (pdu->present) {
204 case RANAP_RANAP_PDU_PR_initiatingMessage:
Harald Weltebc4560c2015-12-24 08:46:58 +0100205 rc = cn_ranap_rx_initiating_msg(cnlink, &pdu->choice.initiatingMessage,
206 data, len);
Harald Weltec4338de2015-12-24 00:40:52 +0100207 break;
208 case RANAP_RANAP_PDU_PR_successfulOutcome:
209 rc = cn_ranap_rx_successful_msg(cnlink, &pdu->choice.successfulOutcome);
210 break;
211 case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
212 LOGP(DRANAP, LOGL_NOTICE, "Received unsupported RANAP "
213 "unsuccessful outcome procedure %u from CN, ignoring\n",
214 pdu->choice.unsuccessfulOutcome.procedureCode);
215 break;
216 default:
217 LOGP(DRANAP, LOGL_NOTICE, "Received suspicious RANAP "
218 "presence %u from CN, ignoring\n", pdu->present);
219 break;
220 }
221}
222
223static int handle_cn_ranap(struct hnbgw_cnlink *cnlink, const uint8_t *data,
224 unsigned int len)
225{
226 RANAP_RANAP_PDU_t _pdu, *pdu = &_pdu;
227 asn_dec_rval_t dec_ret;
228 int rc;
229
230 memset(pdu, 0, sizeof(*pdu));
231 dec_ret = aper_decode(NULL,&asn_DEF_RANAP_RANAP_PDU, (void **) &pdu,
232 data, len, 0, 0);
233 if (dec_ret.code != RC_OK) {
234 LOGP(DRANAP, LOGL_ERROR, "Error in RANAP ASN.1 decode\n");
Neels Hofmeyra6a68e62016-11-25 13:21:02 +0100235 return -1;
Harald Weltec4338de2015-12-24 00:40:52 +0100236 }
237
Harald Weltebc4560c2015-12-24 08:46:58 +0100238 rc = _cn_ranap_rx(cnlink, pdu, data, len);
Harald Weltec4338de2015-12-24 00:40:52 +0100239
240 return rc;
241}
242
Neels Hofmeyra3bcd6d2017-07-03 14:29:04 +0200243static bool pc_and_ssn_match(const struct osmo_sccp_addr *a, const struct osmo_sccp_addr *b)
244{
245 return (a == b)
246 || ((a->pc == b->pc)
247 && (a->ssn == b->ssn));
248}
249
250static int classify_cn_remote_addr(const struct hnb_gw *gw,
251 const struct osmo_sccp_addr *cn_remote_addr,
252 bool *is_ps)
253{
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200254 if (pc_and_ssn_match(cn_remote_addr, &gw->sccp.iucs_remote_addr)) {
Neels Hofmeyra3bcd6d2017-07-03 14:29:04 +0200255 if (is_ps)
256 *is_ps = false;
257 return 0;
258 }
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200259 if (pc_and_ssn_match(cn_remote_addr, &gw->sccp.iups_remote_addr)) {
Neels Hofmeyra3bcd6d2017-07-03 14:29:04 +0200260 if (is_ps)
261 *is_ps = true;
262 return 0;
263 }
264 LOGP(DMAIN, LOGL_ERROR, "Unexpected remote address, matches neither CS nor PS address: %s\n",
265 osmo_sccp_addr_dump(cn_remote_addr));
266 return -1;
267}
Harald Weltec4338de2015-12-24 00:40:52 +0100268
269static int handle_cn_unitdata(struct hnbgw_cnlink *cnlink,
270 const struct osmo_scu_unitdata_param *param,
271 struct osmo_prim_hdr *oph)
272{
Harald Welte8c572fe2015-12-26 08:42:07 +0100273 if (param->called_addr.ssn != OSMO_SCCP_SSN_RANAP) {
Harald Weltec4338de2015-12-24 00:40:52 +0100274 LOGP(DMAIN, LOGL_NOTICE, "N-UNITDATA.ind for unknown SSN %u\n",
275 param->called_addr.ssn);
276 return -1;
277 }
278
Neels Hofmeyra3bcd6d2017-07-03 14:29:04 +0200279 if (classify_cn_remote_addr(cnlink->gw, &param->calling_addr, NULL) < 0)
280 return -1;
281
Harald Weltec4338de2015-12-24 00:40:52 +0100282 return handle_cn_ranap(cnlink, msgb_l2(oph->msg), msgb_l2len(oph->msg));
283}
284
Neels Hofmeyr65037672016-04-19 18:00:54 +0200285static int handle_cn_conn_conf(struct hnbgw_cnlink *cnlink,
Neels Hofmeyr630483b2016-04-19 18:01:25 +0200286 const struct osmo_scu_connect_param *param,
287 struct osmo_prim_hdr *oph)
Harald Weltec4338de2015-12-24 00:40:52 +0100288{
289 /* we don't actually need to do anything, as RUA towards the HNB
290 * doesn't seem to know any confirmations to its CONNECT
291 * operation */
292
Neels Hofmeyr0ff24432016-04-04 18:33:33 +0200293 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() conn_id=%d\n",
294 param->conn_id);
295 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() called_addr=%s\n",
296 inet_ntoa(param->called_addr.ip.v4));
297 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() calling_addr=%s\n",
298 inet_ntoa(param->calling_addr.ip.v4));
299 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() responding_addr=%s\n",
300 inet_ntoa(param->responding_addr.ip.v4));
301
Harald Weltec4338de2015-12-24 00:40:52 +0100302 return 0;
303}
304
Neels Hofmeyr65037672016-04-19 18:00:54 +0200305static int handle_cn_data_ind(struct hnbgw_cnlink *cnlink,
Harald Weltec4338de2015-12-24 00:40:52 +0100306 const struct osmo_scu_data_param *param,
307 struct osmo_prim_hdr *oph)
308{
309 struct hnbgw_context_map *map;
310
311 /* connection-oriented data is always passed transparently
312 * towards the specific HNB, via a RUA connection identified by
313 * conn_id */
314
315 map = context_map_by_cn(cnlink, param->conn_id);
316 if (!map) {
317 /* FIXME: Return an error / released primitive */
318 return 0;
319 }
320
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200321 return rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id,
Harald Weltec4338de2015-12-24 00:40:52 +0100322 msgb_l2(oph->msg), msgb_l2len(oph->msg));
323}
324
Neels Hofmeyr65037672016-04-19 18:00:54 +0200325static int handle_cn_disc_ind(struct hnbgw_cnlink *cnlink,
Harald Weltec4338de2015-12-24 00:40:52 +0100326 const struct osmo_scu_disconn_param *param,
327 struct osmo_prim_hdr *oph)
328{
329 struct hnbgw_context_map *map;
330
Neels Hofmeyr02be4e32016-04-04 19:29:35 +0200331 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() conn_id=%d originator=%d\n",
332 param->conn_id, param->originator);
333 LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() responding_addr=%s\n",
334 inet_ntoa(param->responding_addr.ip.v4));
335
Harald Weltec4338de2015-12-24 00:40:52 +0100336 RUA_Cause_t rua_cause = {
337 .present = RUA_Cause_PR_NOTHING,
338 /* FIXME: Convert incoming SCCP cause to RUA cause */
339 };
340
341 /* we need to notify the HNB associated with this connection via
342 * a RUA DISCONNECT */
343
344 map = context_map_by_cn(cnlink, param->conn_id);
345 if (!map) {
346 /* FIXME: Return an error / released primitive */
347 return 0;
348 }
349
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200350 return rua_tx_disc(map->hnb_ctx, map->is_ps, map->rua_ctx_id,
Harald Weltec4338de2015-12-24 00:40:52 +0100351 &rua_cause, msgb_l2(oph->msg), msgb_l2len(oph->msg));
352}
353
354/* Entry point for primitives coming up from SCCP User SAP */
Neels Hofmeyra1bf4f32016-07-07 15:36:07 +0200355static int sccp_sap_up(struct osmo_prim_hdr *oph, void *ctx)
Harald Weltec4338de2015-12-24 00:40:52 +0100356{
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200357 struct osmo_sccp_user *scu = ctx;
Neels Hofmeyrcb246312017-06-20 22:49:34 +0200358 struct hnbgw_cnlink *cnlink;
Harald Weltec4338de2015-12-24 00:40:52 +0100359 struct osmo_scu_prim *prim = (struct osmo_scu_prim *) oph;
360 int rc;
361
362 LOGP(DMAIN, LOGL_DEBUG, "sccp_sap_up(%s)\n", osmo_scu_prim_name(oph));
363
Neels Hofmeyrcb246312017-06-20 22:49:34 +0200364 if (!scu) {
365 LOGP(DMAIN, LOGL_ERROR,
366 "sccp_sap_up(): NULL osmo_sccp_user, cannot send prim (sap %u prim %u op %d)\n",
367 oph->sap, oph->primitive, oph->operation);
368 return -1;
369 }
370
371 cnlink = osmo_sccp_user_get_priv(scu);
372 if (!cnlink) {
373 LOGP(DMAIN, LOGL_ERROR,
374 "sccp_sap_up(): NULL hnbgw_cnlink, cannot send prim (sap %u prim %u op %d)\n",
375 oph->sap, oph->primitive, oph->operation);
376 return -1;
377 }
378
Harald Weltec4338de2015-12-24 00:40:52 +0100379 switch (OSMO_PRIM_HDR(oph)) {
380 case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
Neels Hofmeyr65037672016-04-19 18:00:54 +0200381 rc = handle_cn_unitdata(cnlink, &prim->u.unitdata, oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100382 break;
383 case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM):
Neels Hofmeyr65037672016-04-19 18:00:54 +0200384 rc = handle_cn_conn_conf(cnlink, &prim->u.connect, oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100385 break;
386 case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
Neels Hofmeyr65037672016-04-19 18:00:54 +0200387 rc = handle_cn_data_ind(cnlink, &prim->u.data, oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100388 break;
389 case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION):
Neels Hofmeyr65037672016-04-19 18:00:54 +0200390 rc = handle_cn_disc_ind(cnlink, &prim->u.disconnect, oph);
Harald Weltec4338de2015-12-24 00:40:52 +0100391 break;
392 defualt:
393 LOGP(DMAIN, LOGL_ERROR,
394 "Received unknown prim %u from SCCP USER SAP\n",
395 OSMO_PRIM_HDR(oph));
396 break;
397 }
398
399 msgb_free(oph->msg);
400
401 return 0;
402}
403
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200404static bool addr_has_pc_and_ssn(const struct osmo_sccp_addr *addr)
Harald Weltec4338de2015-12-24 00:40:52 +0100405{
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200406 if (!(addr->presence & OSMO_SCCP_ADDR_T_SSN))
407 return false;
408 if (!(addr->presence & OSMO_SCCP_ADDR_T_PC))
409 return false;
410 return true;
411}
Harald Weltec4338de2015-12-24 00:40:52 +0100412
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200413static int resolve_addr_name(struct osmo_sccp_addr *dest, struct osmo_ss7_instance **ss7,
414 const char *addr_name, const char *label)
415{
416 struct osmo_ss7_instance *ss7_tmp;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200417
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200418 if (!addr_name) {
419 LOGP(DMAIN, LOGL_ERROR, "Missing config: %s remote-addr\n", label);
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200420 return -1;
421 }
422
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200423 ss7_tmp = osmo_sccp_addr_by_name(dest, addr_name);
424 if (!ss7_tmp) {
425 LOGP(DMAIN, LOGL_ERROR, "%s remote addr: no such SCCP address book entry: '%s'\n",
426 label, addr_name);
427 return -1;
428 }
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200429
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200430 if (*ss7 && (*ss7 != ss7_tmp)) {
431 LOGP(DMAIN, LOGL_ERROR, "IuCS and IuPS cannot be served from separate CS7 instances,"
432 " cs7 instance %d != %d\n", (*ss7)->cfg.id, ss7_tmp->cfg.id);
433 return -1;
434 }
435
436 *ss7 = ss7_tmp;
437
438 osmo_sccp_addr_set_ssn(dest, OSMO_SCCP_SSN_RANAP);
439
440 if (!addr_has_pc_and_ssn(dest)) {
441 LOGP(DMAIN, LOGL_ERROR, "Invalid/incomplete %s remote-addr: %s\n",
442 label, osmo_sccp_addr_name(dest));
443 return -1;
444 }
445
446 LOGP(DRANAP, LOGL_NOTICE, "Remote %s SCCP addr: %s\n",
447 label, osmo_sccp_addr_name(*ss7, dest));
448 return 0;
449}
450
451int hnbgw_cnlink_init(struct hnb_gw *gw, const char *stp_host, uint16_t stp_port, const char *local_ip)
452{
453 struct hnbgw_cnlink *cnlink;
454 struct osmo_ss7_instance *ss7;
455 uint32_t local_pc;
456 int rc;
457
458 OSMO_ASSERT(!gw->sccp.client);
459 OSMO_ASSERT(!gw->sccp.cnlink);
460
461 ss7 = NULL;
462 if (resolve_addr_name(&gw->sccp.iucs_remote_addr, &ss7,
463 gw->config.iucs_remote_addr_name, "IuCS"))
464 return -1;
465 if (resolve_addr_name(&gw->sccp.iups_remote_addr, &ss7,
466 gw->config.iups_remote_addr_name, "IuPS"))
467 return -1;
468
469 if (!osmo_ss7_pc_is_valid(ss7->cfg.primary_pc)) {
470 LOGP(DMAIN, LOGL_ERROR, "IuCS/IuPS uplink cannot be setup: CS7 instance %d has no point-code set\n",
471 ss7->cfg.id);
472 return -1;
473 }
474 local_pc = ss7->cfg.primary_pc;
475
476 osmo_sccp_make_addr_pc_ssn(&gw->sccp.local_addr, local_pc, OSMO_SCCP_SSN_RANAP);
477
478 LOGP(DRANAP, LOGL_NOTICE, "M3UA uplink to STP: %s %u\n", stp_host, stp_port);
479 LOGP(DRANAP, LOGL_NOTICE, "Local SCCP addr: %s\n", osmo_sccp_addr_name(ss7, &gw->sccp.local_addr));
480
481 gw->sccp.client = osmo_sccp_simple_client_on_ss7_id(gw, ss7->cfg.id, "OsmoHNBGW",
482 local_pc, OSMO_SS7_ASP_PROT_M3UA,
483 0, local_ip, stp_port, stp_host);
484 if (!gw->sccp.client) {
485 LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP Client\n");
486 return -1;
487 }
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200488
489 cnlink = talloc_zero(gw, struct hnbgw_cnlink);
Neels Hofmeyr2b01f3a2016-04-19 17:57:03 +0200490 cnlink->gw = gw;
Harald Weltec4338de2015-12-24 00:40:52 +0100491 INIT_LLIST_HEAD(&cnlink->map_list);
492 cnlink->T_RafC.cb = cnlink_trafc_cb;
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200493 cnlink->T_RafC.data = gw;
Harald Welte552fdf12015-12-26 23:39:30 +0100494 cnlink->next_conn_id = 1000;
Harald Weltec4338de2015-12-24 00:40:52 +0100495
Neels Hofmeyrecbdc5c2017-07-31 13:13:24 +0200496 cnlink->sccp_user = osmo_sccp_user_bind_pc(gw->sccp.client, "OsmoHNBGW", sccp_sap_up,
497 OSMO_SCCP_SSN_RANAP, gw->sccp.local_addr.pc);
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200498 if (!cnlink->sccp_user) {
499 LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP User\n");
500 return -1;
Harald Weltec4338de2015-12-24 00:40:52 +0100501 }
502
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200503 /* In sccp_sap_up() we expect the cnlink in the user's priv. */
504 osmo_sccp_user_set_priv(cnlink->sccp_user, cnlink);
Harald Weltec4338de2015-12-24 00:40:52 +0100505
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200506 gw->sccp.cnlink = cnlink;
Harald Weltec4338de2015-12-24 00:40:52 +0100507
Neels Hofmeyr0f88c112017-07-03 16:49:43 +0200508 return 0;
Harald Weltec4338de2015-12-24 00:40:52 +0100509}