From 0931531ea8e28d59e403fed6dab1b31ec7aca601 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 2 Apr 2017 11:58:17 +0200 Subject: WIP: Add IPA/SCCPlite stacking Change-Id: I9098574cddeba10fcf8f1b6c196a7069a6805c56 --- include/osmocom/sigtran/osmo_ss7.h | 1 + src/osmo_ss7.c | 138 ++++++++++++++++++++++++++++++++++--- src/sccp_scrc.c | 4 +- 3 files changed, 134 insertions(+), 9 deletions(-) diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h index d765ae0..c7f1069 100644 --- a/include/osmocom/sigtran/osmo_ss7.h +++ b/include/osmocom/sigtran/osmo_ss7.h @@ -248,6 +248,7 @@ enum osmo_ss7_asp_protocol { OSMO_SS7_ASP_PROT_NONE, OSMO_SS7_ASP_PROT_SUA, OSMO_SS7_ASP_PROT_M3UA, + OSMO_SS7_ASP_PROT_IPA, _NUM_OSMO_SS7_ASP_PROT }; diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c index 8ec099a..fc92251 100644 --- a/src/osmo_ss7.c +++ b/src/osmo_ss7.c @@ -40,6 +40,7 @@ #include #include +#include #include "sccp_internal.h" #include "xua_internal.h" @@ -66,12 +67,25 @@ struct value_string osmo_ss7_asp_protocol_vals[] = { { OSMO_SS7_ASP_PROT_NONE, "none" }, { OSMO_SS7_ASP_PROT_SUA, "sua" }, { OSMO_SS7_ASP_PROT_M3UA, "m3ua" }, + { OSMO_SS7_ASP_PROT_IPA, "ipa" }, { 0, NULL } }; #define LOGSS7(inst, level, fmt, args ...) \ LOGP(DLSS7, level, "%u: " fmt, (inst)->cfg.id, ## args) +static int asp_proto_to_ip_proto(enum osmo_ss7_asp_protocol proto) +{ + switch (proto) { + case OSMO_SS7_ASP_PROT_IPA: + return IPPROTO_TCP; + case OSMO_SS7_ASP_PROT_SUA: + case OSMO_SS7_ASP_PROT_M3UA: + default: + return IPPROTO_SCTP; + } +} + /*********************************************************************** * SS7 Point Code Parsing / Printing @@ -770,7 +784,8 @@ osmo_ss7_as_find_or_create(struct osmo_ss7_instance *inst, const char *name, as->cfg.proto = proto; as->cfg.mode = OSMO_SS7_AS_TMOD_LOADSHARE; as->cfg.recovery_timeout_msec = 2000; - as->fi = xua_as_fsm_start(as, LOGL_DEBUG); + if (proto != OSMO_SS7_ASP_PROT_IPA) + as->fi = xua_as_fsm_start(as, LOGL_DEBUG); llist_add_tail(&as->list, &inst->as_list); } @@ -1004,6 +1019,7 @@ void osmo_ss7_asp_destroy(struct osmo_ss7_asp *asp) } static int xua_cli_read_cb(struct osmo_stream_cli *conn); +static int ipa_cli_read_cb(struct osmo_stream_cli *conn); static int xua_cli_connect_cb(struct osmo_stream_cli *cli); int osmo_ss7_asp_restart(struct osmo_ss7_asp *asp) @@ -1031,10 +1047,13 @@ int osmo_ss7_asp_restart(struct osmo_ss7_asp *asp) } osmo_stream_cli_set_addr(asp->client, asp->cfg.remote.host); osmo_stream_cli_set_port(asp->client, asp->cfg.remote.port); - osmo_stream_cli_set_proto(asp->client, IPPROTO_SCTP); + osmo_stream_cli_set_proto(asp->client, asp_proto_to_ip_proto(asp->cfg.proto)); osmo_stream_cli_set_reconnect_timeout(asp->client, 5); osmo_stream_cli_set_connect_cb(asp->client, xua_cli_connect_cb); - osmo_stream_cli_set_read_cb(asp->client, xua_cli_read_cb); + if (asp->cfg.proto == OSMO_SS7_ASP_PROT_IPA) + osmo_stream_cli_set_read_cb(asp->client, ipa_cli_read_cb); + else + osmo_stream_cli_set_read_cb(asp->client, xua_cli_read_cb); osmo_stream_cli_set_data(asp->client, asp); rc = osmo_stream_cli_open2(asp->client, 1); if (rc < 0) { @@ -1061,7 +1080,8 @@ int osmo_ss7_asp_restart(struct osmo_ss7_asp *asp) /* (re)start the ASP FSM */ if (asp->fi) osmo_fsm_inst_term(asp->fi, OSMO_FSM_TERM_REQUEST, NULL); - asp->fi = xua_asp_fsm_start(asp, role, LOGL_DEBUG); + if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA) + asp->fi = xua_asp_fsm_start(asp, role, LOGL_DEBUG); return 0; } @@ -1146,6 +1166,64 @@ static void log_sctp_notification(struct osmo_ss7_asp *asp, const char *pfx, } } +static int ipa_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg) +{ + struct osmo_mtp_prim *omp; + + /* FIXME: pull the IPA header */ + + /* Generate an MTP-TRANSFER.ind and hand it into the MTP core + * so it can dispatch it to SCCP */ + omp = (struct osmo_mtp_prim *) msgb_push(msg, sizeof(*omp)); + osmo_prim_init(&omp->oph, MTP_SAP_USER, + OSMO_MTP_PRIM_TRANSFER, PRIM_OP_INDICATION, msg); + omp->u.transfer.opc = 0; + omp->u.transfer.dpc = 0; + omp->u.transfer.sio = MTP_SI_SCCP; + omp->u.transfer.sls = 0; + + return osmo_ss7_mtp_to_user(asp->inst, omp); +} + +/* netif code tells us we can read something from the socket */ +static int ipa_srv_conn_cb(struct osmo_stream_srv *conn) +{ + struct osmo_fd *ofd = osmo_stream_srv_get_ofd(conn); + struct osmo_ss7_asp *asp = osmo_stream_srv_get_data(conn); + struct msgb *msg = msgb_alloc(ASP_MSGB_SIZE, "xUA Server Rx"); + int rc; + + if (!msg) + return -ENOMEM; + + /* read xUA message from socket and process it */ + rc = osmo_stream_srv_recv(conn, msg); + LOGPASP(asp, DLSS7, LOGL_DEBUG, "%s(): recvmsg() returned %d\n", + __func__, rc); + if (rc < 0) { + osmo_stream_srv_destroy(conn); + goto out; + } else if (rc == 0) { + osmo_stream_srv_destroy(conn); + goto out; + } + if (osmo_ipa_process_msg(msg) < 0) { + LOGPASP(asp, DLSS7, LOGL_ERROR, "Bad IPA message\n"); + osmo_stream_srv_destroy(conn); + goto out; + } + msg->dst = asp; + + /* Handle IPA PING, PONG and ID_ACK messages */ + if (osmo_ipa_rcvmsg_base(msg, ofd, 1)) + return 0; + + rc = ipa_rx_msg(asp, msg); +out: + msgb_free(msg); + return rc; +} + /* netif code tells us we can read something from the socket */ static int xua_srv_conn_cb(struct osmo_stream_srv *conn) { @@ -1230,6 +1308,40 @@ static int xua_cli_connect_cb(struct osmo_stream_cli *cli) return 0; } +/* read call-back for IPA/SCCPlite socket */ +static int ipa_cli_read_cb(struct osmo_stream_cli *conn) +{ + struct osmo_fd *ofd = osmo_stream_cli_get_ofd(conn); + struct osmo_ss7_asp *asp = osmo_stream_cli_get_data(conn); + struct msgb *msg = msgb_alloc(ASP_MSGB_SIZE, "IPA Client Rx"); + int rc; + + if (!msg) + return -ENOMEM; + + rc = osmo_stream_cli_recv(conn, msg); + if (rc <= 0) { + LOGPASP(asp, DLSS7, LOGL_ERROR, "Cannot receive message\n"); + osmo_stream_cli_reconnect(conn); + goto out; + } + if (osmo_ipa_process_msg(msg) < 0) { + LOGPASP(asp, DLSS7, LOGL_ERROR, "Bad IPA message\n"); + osmo_stream_cli_reconnect(conn); + goto out; + } + + /* Handle IPA PING, PONG and ID_ACK messages */ + if (osmo_ipa_rcvmsg_base(msg, ofd, 0)) + return 0; + + msg->dst = asp; + rc = ipa_rx_msg(asp, msg); +out: + msgb_free(msg); + return rc; +} + static int xua_cli_read_cb(struct osmo_stream_cli *conn) { struct osmo_fd *ofd = osmo_stream_cli_get_ofd(conn); @@ -1322,9 +1434,15 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd) LOGP(DLSS7, LOGL_INFO, "%s: New SCTP connection accepted\n", sock_name); - srv = osmo_stream_srv_create(oxs, link, fd, - xua_srv_conn_cb, - xua_srv_conn_closed_cb, NULL); + if (oxs->cfg.proto == OSMO_SS7_ASP_PROT_IPA) { + srv = osmo_stream_srv_create(oxs, link, fd, + ipa_srv_conn_cb, + xua_srv_conn_closed_cb, NULL); + } else { + srv = osmo_stream_srv_create(oxs, link, fd, + xua_srv_conn_cb, + xua_srv_conn_closed_cb, NULL); + } if (!srv) { LOGP(DLSS7, LOGL_ERROR, "%s: Unable to create stream server " "for SCTP connection\n", sock_name); @@ -1372,6 +1490,10 @@ int osmo_ss7_asp_send(struct osmo_ss7_asp *asp, struct msgb *msg) case OSMO_SS7_ASP_PROT_M3UA: msgb_sctp_ppid(msg) = M3UA_PPID; break; + case OSMO_SS7_ASP_PROT_IPA: + /* do we really want to do this here? */ + osmo_ipa_msg_push_header(msg, FIXME); + break; default: OSMO_ASSERT(0); } @@ -1434,7 +1556,7 @@ osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_pro osmo_stream_srv_link_set_addr(oxs->server, oxs->cfg.local.host); osmo_stream_srv_link_set_port(oxs->server, oxs->cfg.local.port); - osmo_stream_srv_link_set_proto(oxs->server, IPPROTO_SCTP); + osmo_stream_srv_link_set_proto(oxs->server, asp_proto_to_ip_proto(proto)); rc = osmo_stream_srv_link_open(oxs->server); if (rc < 0) { diff --git a/src/sccp_scrc.c b/src/sccp_scrc.c index 0ab25cb..2511dfe 100644 --- a/src/sccp_scrc.c +++ b/src/sccp_scrc.c @@ -142,6 +142,7 @@ static int gen_mtp_transfer_req_xua(struct osmo_sccp_instance *inst, case OSMO_SS7_ASP_PROT_SUA: return sua_tx_xua_as(as, xua); case OSMO_SS7_ASP_PROT_M3UA: + case OSMO_SS7_ASP_PROT_IPA: return sua2sccp_tx_m3ua(inst, xua); default: LOGP(DLSCCP, LOGL_ERROR, "MTP-TRANSFER.req for " @@ -295,7 +296,8 @@ static int scrc_node_6(struct osmo_sccp_instance *inst, const struct osmo_sccp_addr *called) { struct osmo_sccp_user *scu; - + /* it is not really clear that called->pc will be set to + * anything here, in the case of a SSN-only CalledAddr */ scu = sccp_user_find(inst, called->ssn, called->pc); /* Is subsystem equipped? */ -- cgit v1.2.3