Implement M3UA-over-TCP (in addition to SCTP)

RFC 4666 section 1.3.1 states that "TCP MAY be used as the underlying
common transport protocol" under certain scenarios.  There is even
IANA-allocated TCP port 2905 for that purpose (see section 1.4.8).

Since TCP is a stream oriented protocol, so we need to handle message
boundaries ourselves by reading the M3UA header to know the PDU length.

Change-Id: I8c76d271472befacbeb998a93bbdc9e8660d9b5d
Related: SYS#5424
This commit is contained in:
Vadim Yanitskiy 2024-02-27 00:29:30 +07:00
parent 85055b5ca2
commit 22929b1c04
10 changed files with 580 additions and 115 deletions

View File

@ -12,3 +12,8 @@ libosmo-netif >1.4.0 osmo_stream_{srv,cli}_get_fd()
libosmocore >1.9.0 osmo_sock_multiaddr_get_ip_and_port(), osmo_multiaddr_ip_and_port_snprintf()
libosmocore >1.9.0 osmo_sock_sctp_get_peer_addr_info()
libosmo-netif >1.4.0 osmo_sctp_spinfo_state_str(), osmo_sctp_sstat_state_str()
libosmo-sigtran ABI change struct osmo_ss7_asp: new field(s) at the end
libosmo-sigtran ABI change struct osmo_xua_server: new field(s) at the end
libosmo-sigtran API added osmo_ss7_asp_get_trans_proto()
libosmo-sigtran API added osmo_ss7_asp_{find2,find_or_create2}()
libosmo-sigtran API added osmo_ss7_xua_server_{find2,create2}()

View File

@ -453,6 +453,9 @@ struct osmo_ss7_asp {
uint16_t max_attempts_value;
uint16_t max_init_timeo_value; /* ms */
} sctp_init;
/*! The underlaying transport protocol (one of IPPROTO_*) */
int trans_proto;
} cfg;
};
@ -482,11 +485,21 @@ osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
struct osmo_ss7_asp *
osmo_ss7_asp_find(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto);
enum osmo_ss7_asp_protocol proto)
OSMO_DEPRECATED("Use osmo_ss7_asp_find2() instead");
struct osmo_ss7_asp *
osmo_ss7_asp_find2(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
int trans_proto, enum osmo_ss7_asp_protocol proto);
struct osmo_ss7_asp *
osmo_ss7_asp_find_or_create(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto);
enum osmo_ss7_asp_protocol proto)
OSMO_DEPRECATED("Use osmo_ss7_asp_find_or_create2() instead");
struct osmo_ss7_asp *
osmo_ss7_asp_find_or_create2(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
int trans_proto, enum osmo_ss7_asp_protocol proto);
void osmo_ss7_asp_destroy(struct osmo_ss7_asp *asp);
int osmo_ss7_asp_send(struct osmo_ss7_asp *asp, struct msgb *msg);
int osmo_ss7_asp_restart(struct osmo_ss7_asp *asp);
@ -495,6 +508,7 @@ bool osmo_ss7_asp_active(const struct osmo_ss7_asp *asp);
int osmo_ss7_asp_get_log_subsys(const struct osmo_ss7_asp *asp);
const char *osmo_ss7_asp_get_name(const struct osmo_ss7_asp *asp);
enum osmo_ss7_asp_protocol osmo_ss7_asp_get_proto(const struct osmo_ss7_asp *asp);
int osmo_ss7_asp_get_trans_proto(const struct osmo_ss7_asp *asp);
/*! Weak function to handle payload for unknown/unsupported PPID or IPA StreamID.
* This function can be overridden by application code to implement whatever handling
@ -543,16 +557,32 @@ struct osmo_xua_server {
uint16_t num_ostreams_value;
uint16_t max_instreams_value;
} sctp_init;
/*! The underlaying transport protocol (one of IPPROTO_*) */
int trans_proto;
} cfg;
};
struct osmo_xua_server *
osmo_ss7_xua_server_find(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_protocol proto,
uint16_t local_port);
osmo_ss7_xua_server_find(struct osmo_ss7_instance *inst,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port)
OSMO_DEPRECATED("Use osmo_ss7_xua_server_find2() instead");
struct osmo_xua_server *
osmo_ss7_xua_server_find2(struct osmo_ss7_instance *inst,
int trans_proto,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port);
struct osmo_xua_server *
osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host);
osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host)
OSMO_DEPRECATED("Use osmo_ss7_xua_server_create2() instead");
struct osmo_xua_server *
osmo_ss7_xua_server_create2(struct osmo_ss7_instance *inst,
int trans_proto, enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host);
int
osmo_ss7_xua_server_bind(struct osmo_xua_server *xs);

View File

@ -1017,9 +1017,9 @@ osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
}
struct osmo_ss7_asp *
osmo_ss7_asp_find(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto)
osmo_ss7_asp_find2(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
int trans_proto, enum osmo_ss7_asp_protocol proto)
{
struct osmo_ss7_asp *asp;
@ -1028,47 +1028,107 @@ osmo_ss7_asp_find(struct osmo_ss7_instance *inst, const char *name,
if (!asp)
return NULL;
if ((asp->cfg.remote.port != remote_port || asp->cfg.local.port != local_port || asp->cfg.proto != proto))
if (asp->cfg.remote.port != remote_port || asp->cfg.local.port != local_port)
return NULL;
if (asp->cfg.trans_proto != trans_proto)
return NULL;
if (asp->cfg.proto != proto)
return NULL;
return asp;
}
struct osmo_ss7_asp *
osmo_ss7_asp_find(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto)
{
const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
return osmo_ss7_asp_find2(inst, name,
remote_port, local_port,
trans_proto, proto);
}
struct osmo_ss7_asp *
osmo_ss7_asp_find_or_create2(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
int trans_proto, enum osmo_ss7_asp_protocol proto)
{
struct osmo_ss7_asp *asp;
OSMO_ASSERT(ss7_initialized);
asp = osmo_ss7_asp_find_by_name(inst, name);
if (asp) {
if (asp->cfg.remote.port != remote_port || asp->cfg.local.port != local_port)
return NULL;
if (asp->cfg.trans_proto != trans_proto)
return NULL;
if (asp->cfg.proto != proto)
return NULL;
return asp;
}
return ss7_asp_alloc(inst, name, remote_port, local_port, trans_proto, proto);
}
struct osmo_ss7_asp *
osmo_ss7_asp_find_or_create(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto)
{
struct osmo_ss7_asp *asp;
const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
OSMO_ASSERT(ss7_initialized);
asp = osmo_ss7_asp_find_by_name(inst, name);
if (asp) {
if (asp->cfg.remote.port != remote_port ||
asp->cfg.local.port != local_port ||
asp->cfg.proto != proto)
return NULL;
return asp;
}
return ss7_asp_alloc(inst, name, remote_port, local_port, proto);
return osmo_ss7_asp_find_or_create2(inst, name,
remote_port, local_port,
trans_proto, proto);
}
/*! \brief find an xUA server with the given parameters
* \param[in] inst SS7 Instance on which we operate
* \param[in] trans_proto transport protocol in use (one of IPPROTO_*)
* \param[in] proto protocol (xUA variant) in use
* \param[in] local_port local port of the server
* \returns \ref osmo_xua_server or NULL (not found)
*/
struct osmo_xua_server *
osmo_ss7_xua_server_find(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_protocol proto,
uint16_t local_port)
osmo_ss7_xua_server_find2(struct osmo_ss7_instance *inst,
int trans_proto,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port)
{
struct osmo_xua_server *xs;
OSMO_ASSERT(ss7_initialized);
llist_for_each_entry(xs, &inst->xua_servers, list) {
if (proto == xs->cfg.proto &&
local_port == xs->cfg.local.port)
return xs;
if (trans_proto != xs->cfg.trans_proto)
continue;
if (proto != xs->cfg.proto)
continue;
if (local_port != xs->cfg.local.port)
continue;
return xs;
}
return NULL;
}
/*! \brief find an xUA server with the given parameters
* \param[in] inst SS7 Instance on which we operate
* \param[in] proto protocol (xUA variant) in use
* \param[in] local_port local port of the server
* \returns \ref osmo_xua_server or NULL (not found)
*/
struct osmo_xua_server *
osmo_ss7_xua_server_find(struct osmo_ss7_instance *inst,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port)
{
const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
return osmo_ss7_xua_server_find2(inst, trans_proto, proto, local_port);
}
bool osmo_ss7_pc_is_local(struct osmo_ss7_instance *inst, uint32_t pc)
{
OSMO_ASSERT(ss7_initialized);

View File

@ -127,7 +127,32 @@ const struct value_string osmo_ss7_asp_role_names[] = {
{ 0, NULL }
};
int ss7_asp_proto_to_ip_proto(enum osmo_ss7_asp_protocol proto)
/* check if the given transport and ASP protocols are compatible (and implemented) */
bool ss7_asp_protocol_check_trans_proto(enum osmo_ss7_asp_protocol proto, int trans_proto)
{
switch (proto) {
case OSMO_SS7_ASP_PROT_IPA:
if (trans_proto == IPPROTO_TCP)
return true;
return false;
case OSMO_SS7_ASP_PROT_SUA:
if (trans_proto == IPPROTO_SCTP)
return true;
return false;
case OSMO_SS7_ASP_PROT_M3UA:
if (trans_proto == IPPROTO_SCTP)
return true;
if (trans_proto == IPPROTO_TCP)
return true;
return false;
case OSMO_SS7_ASP_PROT_NONE:
default:
return false;
}
}
/* get _default_ transport protocol for the given ASP protocol */
int ss7_default_trans_proto_for_asp_proto(enum osmo_ss7_asp_protocol proto)
{
switch (proto) {
case OSMO_SS7_ASP_PROT_IPA:
@ -503,9 +528,18 @@ ss7_asp_find_by_socket_addr(int fd)
struct osmo_ss7_asp *ss7_asp_alloc(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto)
int trans_proto, enum osmo_ss7_asp_protocol proto)
{
struct osmo_ss7_asp *asp = talloc_zero(inst, struct osmo_ss7_asp);
struct osmo_ss7_asp *asp;
if (!ss7_asp_protocol_check_trans_proto(proto, trans_proto)) {
LOGP(DLSCCP, LOGL_ERROR,
"ASP protocol '%s' with transport protocol %d is not supported",
osmo_ss7_asp_protocol_name(proto), trans_proto);
return NULL;
}
asp = talloc_zero(inst, struct osmo_ss7_asp);
asp->ctrg = rate_ctr_group_alloc(asp, &ss7_asp_rcgd, g_ss7_asp_rcg_idx++);
if (!asp->ctrg) {
talloc_free(asp);
@ -517,6 +551,7 @@ struct osmo_ss7_asp *ss7_asp_alloc(struct osmo_ss7_instance *inst, const char *n
asp->cfg.remote.port = remote_port;
osmo_ss7_asp_peer_init(&asp->cfg.local);
asp->cfg.local.port = local_port;
asp->cfg.trans_proto = trans_proto;
asp->cfg.proto = proto;
asp->cfg.name = talloc_strdup(asp, name);
@ -566,6 +601,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 m3ua_tcp_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)
@ -601,13 +637,27 @@ int osmo_ss7_asp_restart(struct osmo_ss7_asp *asp)
osmo_stream_cli_set_port(asp->client, asp->cfg.remote.port);
osmo_stream_cli_set_local_addrs(asp->client, (const char **)asp->cfg.local.host, asp->cfg.local.host_cnt);
osmo_stream_cli_set_local_port(asp->client, asp->cfg.local.port);
osmo_stream_cli_set_proto(asp->client, ss7_asp_proto_to_ip_proto(asp->cfg.proto));
osmo_stream_cli_set_proto(asp->client, asp->cfg.trans_proto);
osmo_stream_cli_set_reconnect_timeout(asp->client, 5);
osmo_stream_cli_set_connect_cb(asp->client, xua_cli_connect_cb);
if (asp->cfg.proto == OSMO_SS7_ASP_PROT_IPA)
switch (asp->cfg.proto) {
case OSMO_SS7_ASP_PROT_IPA:
OSMO_ASSERT(asp->cfg.trans_proto == IPPROTO_TCP);
osmo_stream_cli_set_read_cb(asp->client, ipa_cli_read_cb);
else
break;
case OSMO_SS7_ASP_PROT_M3UA:
if (asp->cfg.trans_proto == IPPROTO_SCTP)
osmo_stream_cli_set_read_cb(asp->client, xua_cli_read_cb);
else if (asp->cfg.trans_proto == IPPROTO_TCP)
osmo_stream_cli_set_read_cb(asp->client, m3ua_tcp_cli_read_cb);
else
OSMO_ASSERT(0);
break;
default:
OSMO_ASSERT(asp->cfg.trans_proto == IPPROTO_SCTP);
osmo_stream_cli_set_read_cb(asp->client, xua_cli_read_cb);
break;
}
osmo_stream_cli_set_data(asp->client, asp);
byte = 1; /*AUTH is needed by ASCONF. enable, don't abort socket creation if AUTH can't be enabled */
osmo_stream_cli_set_param(asp->client, OSMO_STREAM_CLI_PAR_SCTP_SOCKOPT_AUTH_SUPPORTED, &byte, sizeof(byte));
@ -838,6 +888,78 @@ out:
return rc;
}
/* netif code tells us we can read something from the socket */
int ss7_asp_m3ua_tcp_srv_conn_cb(struct osmo_stream_srv *conn)
{
struct osmo_ss7_asp *asp = osmo_stream_srv_get_data(conn);
int fd = osmo_stream_srv_get_fd(conn);
struct msgb *msg = asp->pending_msg;
const struct xua_common_hdr *hdr;
size_t msg_length;
int rc;
OSMO_ASSERT(fd >= 0);
if (msg == NULL) {
msg = m3ua_msgb_alloc(__func__);
asp->pending_msg = msg;
}
/* read message header first */
if (msg->len < sizeof(*hdr)) {
errno = 0;
rc = recv(fd, msg->tail, sizeof(*hdr) - msg->len, 0);
if (rc <= 0) {
if (errno == EAGAIN || errno == EINTR)
return 0; /* need more data */
osmo_stream_srv_destroy(conn);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
msgb_put(msg, rc);
if (msg->len < sizeof(*hdr))
return 0; /* need more data */
}
hdr = (const struct xua_common_hdr *)msg->data;
msg_length = ntohl(hdr->msg_length); /* includes sizeof(*hdr) */
/* read the rest of the message */
if (msg->len < msg_length) {
errno = 0;
rc = recv(fd, msg->tail, msg_length - msg->len, 0);
if (rc <= 0) {
if (errno == EAGAIN || errno == EINTR)
return 0; /* need more data */
osmo_stream_srv_destroy(conn);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
msgb_put(msg, rc);
if (msg->len < msg_length)
return 0; /* need more data */
}
msg->dst = asp;
rate_ctr_inc2(asp->ctrg, SS7_ASP_CTR_PKT_RX_TOTAL);
/* spoof SCTP Stream ID */
if (hdr->msg_class == M3UA_MSGC_XFER)
msgb_sctp_stream(msg) = 1;
else
msgb_sctp_stream(msg) = 0;
rc = m3ua_rx_msg(asp, msg);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
/* client has established SCTP connection to server */
static int xua_cli_connect_cb(struct osmo_stream_cli *cli)
{
@ -858,7 +980,7 @@ static int xua_cli_connect_cb(struct osmo_stream_cli *cli)
* fed and the local port is known for sure. Apply SCTP Primary addresses
* if needed:
*/
if (asp->cfg.proto != OSMO_SS7_ASP_PROT_IPA) {
if (asp->cfg.trans_proto == IPPROTO_SCTP) {
rc = ss7_asp_apply_peer_primary_address(asp);
rc = ss7_asp_apply_primary_address(asp);
}
@ -926,6 +1048,78 @@ static int ipa_cli_read_cb(struct osmo_stream_cli *conn)
return ipa_rx_msg(asp, msg, fd & 0xf);
}
/* read call-back for M3UA-over-TCP socket */
static int m3ua_tcp_cli_read_cb(struct osmo_stream_cli *conn)
{
struct osmo_ss7_asp *asp = osmo_stream_cli_get_data(conn);
int fd = osmo_stream_cli_get_fd(conn);
struct msgb *msg = asp->pending_msg;
const struct xua_common_hdr *hdr;
size_t msg_length;
int rc;
OSMO_ASSERT(fd >= 0);
if (msg == NULL) {
msg = m3ua_msgb_alloc(__func__);
asp->pending_msg = msg;
}
/* read message header first */
if (msg->len < sizeof(*hdr)) {
errno = 0;
rc = recv(fd, msg->tail, sizeof(*hdr) - msg->len, 0);
if (rc <= 0) {
if (errno == EAGAIN || errno == EINTR)
return 0; /* need more data */
xua_cli_close_and_reconnect(conn);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
msgb_put(msg, rc);
if (msg->len < sizeof(*hdr))
return 0; /* need more data */
}
hdr = (const struct xua_common_hdr *)msg->data;
msg_length = ntohl(hdr->msg_length); /* includes sizeof(*hdr) */
/* read the rest of the message */
if (msg->len < msg_length) {
errno = 0;
rc = recv(fd, msg->tail, msg_length - msg->len, 0);
if (rc <= 0) {
if (errno == EAGAIN || errno == EINTR)
return 0; /* need more data */
xua_cli_close_and_reconnect(conn);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
msgb_put(msg, rc);
if (msg->len < msg_length)
return 0; /* need more data */
}
msg->dst = asp;
rate_ctr_inc2(asp->ctrg, SS7_ASP_CTR_PKT_RX_TOTAL);
/* spoof SCTP Stream ID */
if (hdr->msg_class == M3UA_MSGC_XFER)
msgb_sctp_stream(msg) = 1;
else
msgb_sctp_stream(msg) = 0;
rc = m3ua_rx_msg(asp, msg);
asp->pending_msg = NULL;
msgb_free(msg);
return rc;
}
static int xua_cli_read_cb(struct osmo_stream_cli *conn)
{
struct osmo_ss7_asp *asp = osmo_stream_cli_get_data(conn);
@ -1135,6 +1329,15 @@ enum osmo_ss7_asp_protocol osmo_ss7_asp_get_proto(const struct osmo_ss7_asp *asp
return asp->cfg.proto;
}
/*! \brief Get the transport proto of a given ASP
* \param[in] asp The ASP for which the transport proto is requested
* \returns The transport proto of the ASP (one of IPPROTO_*)
*/
int osmo_ss7_asp_get_trans_proto(const struct osmo_ss7_asp *asp)
{
return asp->cfg.trans_proto;
}
/*! \brief Get the fd of a given ASP
* \param[in] asp The ASP for which the fd is requested
* \returns The fd of the ASP if acailable, negative otherwise

View File

@ -62,6 +62,11 @@
"MTP3 User Adaptation\n" \
"IPA Multiplex (SCCP Lite)\n"
#define IPPROTO_VAR_STR "(sctp|tcp)"
#define IPPROTO_VAR_HELP_STR \
"SCTP (Stream Control Transmission Protocol)\n" \
"TCP (Transmission Control Protocol)\n"
/* netinet/tcp.h */
static const struct value_string tcp_info_state_values[] = {
{ TCP_ESTABLISHED, "ESTABLISHED" },
@ -465,6 +470,17 @@ DEFUN(show_cs7_route, show_cs7_route_cmd,
* xUA Listener Configuration (SG)
***********************************************************************/
static const struct value_string ipproto_vals[] = {
{ IPPROTO_SCTP, "sctp" },
{ IPPROTO_TCP, "tcp" },
{ 0, NULL },
};
static int parse_trans_proto(const char *protocol)
{
return get_string_value(ipproto_vals, protocol);
}
static enum osmo_ss7_asp_protocol parse_asp_proto(const char *protocol)
{
return get_string_value(osmo_ss7_asp_protocol_vals, protocol);
@ -477,19 +493,29 @@ static struct cmd_node xua_node = {
};
DEFUN_ATTR(cs7_xua, cs7_xua_cmd,
"listen " XUA_VAR_STR " <0-65534>",
"listen " XUA_VAR_STR " <0-65534> [" IPPROTO_VAR_STR "]",
"Configure/Enable xUA Listener\n"
XUA_VAR_HELP_STR "SCTP Port number\n",
XUA_VAR_HELP_STR
"Port number\n"
IPPROTO_VAR_HELP_STR,
CMD_ATTR_IMMEDIATE)
{
struct osmo_ss7_instance *inst = vty->index;
struct osmo_xua_server *xs;
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[0]);
uint16_t port = atoi(argv[1]);
int trans_proto;
xs = osmo_ss7_xua_server_find(inst, proto, port);
if (argc > 2)
trans_proto = parse_trans_proto(argv[2]);
else /* default transport protocol */
trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
if (trans_proto < 0)
return CMD_WARNING;
xs = osmo_ss7_xua_server_find2(inst, trans_proto, proto, port);
if (!xs) {
xs = osmo_ss7_xua_server_create(inst, proto, port, NULL);
xs = osmo_ss7_xua_server_create2(inst, trans_proto, proto, port, NULL);
if (!xs)
return CMD_WARNING;
/* Drop first dummy address created automatically by _create(): */
@ -502,17 +528,27 @@ DEFUN_ATTR(cs7_xua, cs7_xua_cmd,
}
DEFUN_ATTR(no_cs7_xua, no_cs7_xua_cmd,
"no listen " XUA_VAR_STR " <0-65534>",
NO_STR "Disable xUA Listener on given SCTP Port\n"
XUA_VAR_HELP_STR "SCTP Port number\n",
"no listen " XUA_VAR_STR " <0-65534> [" IPPROTO_VAR_STR "]",
NO_STR "Disable xUA Listener on given port\n"
XUA_VAR_HELP_STR
"Port number\n"
IPPROTO_VAR_HELP_STR,
CMD_ATTR_IMMEDIATE)
{
struct osmo_ss7_instance *inst = vty->index;
struct osmo_xua_server *xs;
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[0]);
uint16_t port = atoi(argv[1]);
int trans_proto;
xs = osmo_ss7_xua_server_find(inst, proto, port);
if (argc > 2)
trans_proto = parse_trans_proto(argv[2]);
else /* default transport protocol */
trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
if (trans_proto < 0)
return CMD_WARNING;
xs = osmo_ss7_xua_server_find2(inst, trans_proto, proto, port);
if (!xs) {
vty_out(vty, "No xUA server for port %u found%s", port, VTY_NEWLINE);
return CMD_WARNING;
@ -616,9 +652,13 @@ DEFUN_ATTR(xua_no_sctp_param_init, xua_no_sctp_param_init_cmd,
static void write_one_xua(struct vty *vty, struct osmo_xua_server *xs)
{
int i;
vty_out(vty, " listen %s %u%s",
vty_out(vty, " listen %s %u",
get_value_string(osmo_ss7_asp_protocol_vals, xs->cfg.proto),
xs->cfg.local.port, VTY_NEWLINE);
xs->cfg.local.port);
if (xs->cfg.trans_proto != ss7_default_trans_proto_for_asp_proto(xs->cfg.proto))
vty_out(vty, " %s", get_value_string(ipproto_vals, xs->cfg.trans_proto));
vty_out(vty, "%s", VTY_NEWLINE);
for (i = 0; i < xs->cfg.local.host_cnt; i++) {
if (xs->cfg.local.host[i])
@ -646,7 +686,7 @@ static void vty_dump_xua_server(struct vty *vty, struct osmo_xua_server *xs)
size_t num_hostbuf = ARRAY_SIZE(hostbuf);
char portbuf[6];
int rc;
rc = osmo_sock_multiaddr_get_ip_and_port(fd, ss7_asp_proto_to_ip_proto(xs->cfg.proto),
rc = osmo_sock_multiaddr_get_ip_and_port(fd, xs->cfg.trans_proto,
&hostbuf[0][0], &num_hostbuf, sizeof(hostbuf[0]),
portbuf, sizeof(portbuf), true);
if (rc < 0) {
@ -659,37 +699,60 @@ static void vty_dump_xua_server(struct vty *vty, struct osmo_xua_server *xs)
portbuf);
}
}
vty_out(vty, "xUA server for %s on %s is %s%s",
proto, buf, fd >= 0 ? "listening" : "inactive", VTY_NEWLINE);
vty_out(vty, "xUA server for %s/%s on %s is %s%s",
proto, get_value_string(ipproto_vals, xs->cfg.trans_proto),
buf, fd >= 0 ? "listening" : "inactive", VTY_NEWLINE);
}
DEFUN(show_cs7_xua, show_cs7_xua_cmd,
"show cs7 "XUA_VAR_STR" [<0-65534>]",
SHOW_STR CS7_STR XUA_VAR_HELP_STR "Port Number")
static int _show_cs7_xua(struct vty *vty,
enum osmo_ss7_asp_protocol proto,
int trans_proto, int local_port)
{
struct osmo_ss7_instance *inst;
struct osmo_xua_server *xs;
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[0]);
const struct osmo_ss7_instance *inst;
llist_for_each_entry(inst, &osmo_ss7_instances, list) {
if (argc > 1) {
int port = atoi(argv[1]);
xs = osmo_ss7_xua_server_find(inst, proto, port);
if (!xs) {
vty_out(vty, "%% No matching server found%s", VTY_NEWLINE);
return CMD_WARNING;
}
struct osmo_xua_server *xs;
llist_for_each_entry(xs, &inst->xua_servers, list) {
if (xs->cfg.proto != proto)
continue;
if (local_port >= 0 && xs->cfg.local.port != local_port) /* optional */
continue;
if (trans_proto >= 0 && xs->cfg.trans_proto != trans_proto) /* optional */
continue;
vty_dump_xua_server(vty, xs);
} else {
llist_for_each_entry(xs, &inst->xua_servers, list) {
if (xs->cfg.proto == proto)
vty_dump_xua_server(vty, xs);
}
}
}
return CMD_SUCCESS;
}
#define SHOW_CS7_XUA_CMD \
"show cs7 " XUA_VAR_STR
#define SHOW_CS7_XUA_CMD_HELP \
SHOW_STR CS7_STR XUA_VAR_HELP_STR
DEFUN(show_cs7_xua, show_cs7_xua_cmd,
SHOW_CS7_XUA_CMD " [<0-65534>]",
SHOW_CS7_XUA_CMD_HELP "Local Port Number\n")
{
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[0]);
int local_port = (argc > 1) ? atoi(argv[1]) : -1;
return _show_cs7_xua(vty, proto, -1, local_port);
}
DEFUN(show_cs7_xua_trans_proto, show_cs7_xua_trans_proto_cmd,
SHOW_CS7_XUA_CMD " " IPPROTO_VAR_STR " [<0-65534>]",
SHOW_CS7_XUA_CMD_HELP IPPROTO_VAR_HELP_STR "Local Port Number\n")
{
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[0]);
int trans_proto = parse_trans_proto(argv[1]);
int local_port = (argc > 2) ? atoi(argv[2]) : -1;
return _show_cs7_xua(vty, proto, trans_proto, local_port);
}
DEFUN(show_cs7_config, show_cs7_config_cmd,
"show cs7 config",
SHOW_STR CS7_STR "Currently running cs7 configuration")
@ -738,8 +801,8 @@ DEFUN_ATTR(cs7_asp, cs7_asp_cmd,
"asp NAME <0-65535> <0-65535> " XUA_VAR_STR,
"Configure Application Server Process\n"
"Name of ASP\n"
"Remote SCTP port number\n"
"Local SCTP port number\n"
"Remote port number\n"
"Local port number\n"
XUA_VAR_HELP_STR,
CMD_ATTR_NODE_EXIT)
{
@ -747,17 +810,30 @@ DEFUN_ATTR(cs7_asp, cs7_asp_cmd,
const char *name = argv[0];
uint16_t remote_port = atoi(argv[1]);
uint16_t local_port = atoi(argv[2]);
enum osmo_ss7_asp_protocol protocol = parse_asp_proto(argv[3]);
enum osmo_ss7_asp_protocol proto = parse_asp_proto(argv[3]);
struct osmo_ss7_asp *asp;
int trans_proto;
if (protocol == OSMO_SS7_ASP_PROT_NONE) {
if (proto == OSMO_SS7_ASP_PROT_NONE) {
vty_out(vty, "invalid protocol '%s'%s", argv[3], VTY_NEWLINE);
return CMD_WARNING;
}
asp = osmo_ss7_asp_find(inst, name, remote_port, local_port, protocol);
/* argv[4] can be supplied by an alias (see below) */
if (argc > 4)
trans_proto = parse_trans_proto(argv[4]);
else /* default transport protocol */
trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
if (trans_proto < 0)
return CMD_WARNING;
asp = osmo_ss7_asp_find2(inst, name,
remote_port, local_port,
trans_proto, proto);
if (!asp) {
asp = osmo_ss7_asp_find_or_create(inst, name, remote_port, local_port, protocol);
asp = osmo_ss7_asp_find_or_create2(inst, name,
remote_port, local_port,
trans_proto, proto);
if (!asp) {
vty_out(vty, "cannot create ASP '%s'%s", name, VTY_NEWLINE);
return CMD_WARNING;
@ -772,6 +848,18 @@ DEFUN_ATTR(cs7_asp, cs7_asp_cmd,
return CMD_SUCCESS;
}
/* XXX: workaround for https://osmocom.org/issues/6360, can be removed once it's fixed.
* Currently we hit an assert if we make the IPPROTO_VAR_STR optional in cs7_asp_cmd. */
ALIAS_ATTR(cs7_asp, cs7_asp_trans_proto_cmd,
"asp NAME <0-65535> <0-65535> " XUA_VAR_STR " " IPPROTO_VAR_STR,
"Configure Application Server Process\n"
"Name of ASP\n"
"Remote port number\n"
"Local port number\n"
XUA_VAR_HELP_STR
IPPROTO_VAR_HELP_STR,
CMD_ATTR_NODE_EXIT);
DEFUN_ATTR(no_cs7_asp, no_cs7_asp_cmd,
"no asp NAME",
NO_STR "Disable Application Server Process\n"
@ -1217,10 +1305,10 @@ static void show_one_asp(struct vty *vty, struct osmo_ss7_asp *asp)
int fd = ss7_asp_get_fd(asp);
if (fd > 0) {
int proto = ss7_asp_proto_to_ip_proto(asp->cfg.proto);
if (!get_sockname_buf(buf_loc, sizeof(buf_loc), fd, proto, true))
const int trans_proto = asp->cfg.trans_proto;
if (!get_sockname_buf(buf_loc, sizeof(buf_loc), fd, trans_proto, true))
OSMO_STRLCPY_ARRAY(buf_loc, "<sockname-error>");
if (!get_sockname_buf(buf_rem, sizeof(buf_rem), fd, proto, false))
if (!get_sockname_buf(buf_rem, sizeof(buf_rem), fd, trans_proto, false))
OSMO_STRLCPY_ARRAY(buf_rem, "<sockname-error>");
} else {
osmo_ss7_asp_peer_snprintf(buf_loc, sizeof(buf_loc), &asp->cfg.local);
@ -1374,9 +1462,7 @@ static void show_one_asp_remaddr_sctp(struct vty *vty, struct osmo_ss7_asp *asp)
static void show_one_asp_remaddr(struct vty *vty, struct osmo_ss7_asp *asp)
{
int proto = ss7_asp_proto_to_ip_proto(asp->cfg.proto);
switch (proto) {
switch (asp->cfg.trans_proto) {
case IPPROTO_TCP:
show_one_asp_remaddr_tcp(vty, asp);
break;
@ -1386,7 +1472,8 @@ static void show_one_asp_remaddr(struct vty *vty, struct osmo_ss7_asp *asp)
break;
#endif
default:
vty_out(vty, "%-12s %-46s unknown proto %u%s", asp->cfg.name, "", proto, VTY_NEWLINE);
vty_out(vty, "%-12s %-46s unknown proto %d%s",
asp->cfg.name, "", asp->cfg.trans_proto, VTY_NEWLINE);
break;
}
}
@ -1530,9 +1617,7 @@ static void show_one_asp_assoc_status_sctp(struct vty *vty, struct osmo_ss7_asp
static void show_one_asp_assoc_status(struct vty *vty, struct osmo_ss7_asp *asp)
{
int proto = ss7_asp_proto_to_ip_proto(asp->cfg.proto);
switch (proto) {
switch (asp->cfg.trans_proto) {
case IPPROTO_TCP:
show_one_asp_assoc_status_tcp(vty, asp);
break;
@ -1542,7 +1627,8 @@ static void show_one_asp_assoc_status(struct vty *vty, struct osmo_ss7_asp *asp)
break;
#endif
default:
vty_out(vty, "%-12s unknown proto %u%s", asp->cfg.name, proto, VTY_NEWLINE);
vty_out(vty, "%-12s unknown proto %d%s",
asp->cfg.name, asp->cfg.trans_proto, VTY_NEWLINE);
break;
}
}
@ -1611,9 +1697,12 @@ static void write_one_asp(struct vty *vty, struct osmo_ss7_asp *asp, bool show_d
&& !show_dyn_config)
return;
vty_out(vty, " asp %s %u %u %s%s",
vty_out(vty, " asp %s %u %u %s",
asp->cfg.name, asp->cfg.remote.port, asp->cfg.local.port,
osmo_ss7_asp_protocol_name(asp->cfg.proto), VTY_NEWLINE);
osmo_ss7_asp_protocol_name(asp->cfg.proto));
if (asp->cfg.trans_proto != ss7_default_trans_proto_for_asp_proto(asp->cfg.proto))
vty_out(vty, " %s", get_value_string(ipproto_vals, asp->cfg.trans_proto));
vty_out(vty, "%s", VTY_NEWLINE);
if (asp->cfg.description)
vty_out(vty, " description %s%s", asp->cfg.description, VTY_NEWLINE);
for (i = 0; i < asp->cfg.local.host_cnt; i++) {
@ -2862,6 +2951,7 @@ static void vty_init_shared(void *ctx)
install_lib_element_ve(&show_cs7_user_cmd);
install_lib_element_ve(&show_cs7_xua_cmd);
install_lib_element_ve(&show_cs7_xua_trans_proto_cmd);
install_lib_element_ve(&show_cs7_config_cmd);
install_lib_element(ENABLE_NODE, &cs7_asp_disconnect_cmd);
@ -2885,6 +2975,7 @@ static void vty_init_shared(void *ctx)
install_lib_element_ve(&show_cs7_asp_assoc_status_cmd);
install_lib_element_ve(&show_cs7_asp_assoc_status_name_cmd);
install_lib_element(L_CS7_NODE, &cs7_asp_cmd);
install_lib_element(L_CS7_NODE, &cs7_asp_trans_proto_cmd);
install_lib_element(L_CS7_NODE, &no_cs7_asp_cmd);
install_lib_element(L_CS7_ASP_NODE, &cfg_description_cmd);
install_lib_element(L_CS7_ASP_NODE, &asp_remote_ip_cmd);

View File

@ -67,19 +67,32 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
struct osmo_ss7_asp *asp;
char *sock_name = osmo_sock_get_name(link, fd);
const char *proto_name = get_value_string(osmo_ss7_asp_protocol_vals, oxs->cfg.proto);
int (*read_cb)(struct osmo_stream_srv *conn) = NULL;
int rc = 0;
LOGP(DLSS7, LOGL_INFO, "%s: New %s connection accepted\n", sock_name, proto_name);
if (oxs->cfg.proto == OSMO_SS7_ASP_PROT_IPA) {
srv = osmo_stream_srv_create(oxs, link, fd,
ss7_asp_ipa_srv_conn_cb,
ss7_asp_xua_srv_conn_closed_cb, NULL);
} else {
srv = osmo_stream_srv_create(oxs, link, fd,
ss7_asp_xua_srv_conn_cb,
ss7_asp_xua_srv_conn_closed_cb, NULL);
switch (oxs->cfg.proto) {
case OSMO_SS7_ASP_PROT_IPA:
OSMO_ASSERT(oxs->cfg.trans_proto == IPPROTO_TCP);
read_cb = &ss7_asp_ipa_srv_conn_cb;
break;
case OSMO_SS7_ASP_PROT_M3UA:
if (oxs->cfg.trans_proto == IPPROTO_SCTP)
read_cb = &ss7_asp_xua_srv_conn_cb;
else if (oxs->cfg.trans_proto == IPPROTO_TCP)
read_cb = &ss7_asp_m3ua_tcp_srv_conn_cb;
else
OSMO_ASSERT(0);
break;
default:
OSMO_ASSERT(oxs->cfg.trans_proto == IPPROTO_SCTP);
read_cb = &ss7_asp_xua_srv_conn_cb;
break;
}
srv = osmo_stream_srv_create(oxs, link, fd, read_cb,
&ss7_asp_xua_srv_conn_closed_cb, NULL);
if (!srv) {
LOGP(DLSS7, LOGL_ERROR, "%s: Unable to create stream server "
"for connection\n", sock_name);
@ -112,8 +125,9 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
char namebuf[32];
static uint32_t dyn_asp_num = 0;
snprintf(namebuf, sizeof(namebuf), "asp-dyn-%u", dyn_asp_num++);
asp = osmo_ss7_asp_find_or_create(oxs->inst, namebuf, 0, 0,
oxs->cfg.proto);
asp = osmo_ss7_asp_find_or_create2(oxs->inst, namebuf, 0, 0,
oxs->cfg.trans_proto,
oxs->cfg.proto);
if (asp) {
char hostbuf[INET6_ADDRSTRLEN];
const char *hostbuf_ptr = &hostbuf[0];
@ -157,7 +171,7 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
* data */
osmo_stream_srv_set_data(srv, asp);
if (oxs->cfg.proto != OSMO_SS7_ASP_PROT_IPA) {
if (oxs->cfg.trans_proto == IPPROTO_SCTP) {
rc = ss7_asp_apply_peer_primary_address(asp);
rc = ss7_asp_apply_primary_address(asp);
}
@ -170,19 +184,29 @@ static int xua_accept_cb(struct osmo_stream_srv_link *link, int fd)
}
/*! \brief create a new xUA server configured with given ip/port
* \param[in] ctx talloc allocation context
* \param[in] inst SS7 Instance on which we operate
* \param[in] trans_proto transport protocol to use (one of IPPROTO_*)
* \param[in] proto protocol (xUA variant) to use
* \param[in] local_port local SCTP port to bind/listen to
* \param[in] local_host local IP address to bind/listen to (optional)
* \returns callee-allocated \ref osmo_xua_server in case of success
*/
struct osmo_xua_server *
osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host)
osmo_ss7_xua_server_create2(struct osmo_ss7_instance *inst,
int trans_proto, enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host)
{
struct osmo_xua_server *oxs = talloc_zero(inst, struct osmo_xua_server);
struct osmo_xua_server *oxs;
if (!ss7_asp_protocol_check_trans_proto(proto, trans_proto)) {
LOGP(DLSCCP, LOGL_ERROR,
"ASP protocol '%s' with transport protocol %d is not supported",
osmo_ss7_asp_protocol_name(proto), trans_proto);
return NULL;
}
OSMO_ASSERT(ss7_initialized);
oxs = talloc_zero(inst, struct osmo_xua_server);
if (!oxs)
return NULL;
@ -191,6 +215,7 @@ osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_pro
INIT_LLIST_HEAD(&oxs->asp_list);
oxs->cfg.trans_proto = trans_proto;
oxs->cfg.proto = proto;
oxs->cfg.local.port = local_port;
@ -201,7 +226,7 @@ osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_pro
osmo_stream_srv_link_set_nodelay(oxs->server, true);
osmo_stream_srv_link_set_port(oxs->server, oxs->cfg.local.port);
osmo_stream_srv_link_set_proto(oxs->server, ss7_asp_proto_to_ip_proto(proto));
osmo_stream_srv_link_set_proto(oxs->server, trans_proto);
osmo_ss7_xua_server_set_local_host(oxs, local_host);
@ -218,6 +243,24 @@ osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst, enum osmo_ss7_asp_pro
return oxs;
}
/*! \brief create a new xUA server configured with given ip/port
* \param[in] ctx talloc allocation context
* \param[in] proto protocol (xUA variant) to use
* \param[in] local_port local SCTP port to bind/listen to
* \param[in] local_host local IP address to bind/listen to (optional)
* \returns callee-allocated \ref osmo_xua_server in case of success
*/
struct osmo_xua_server *
osmo_ss7_xua_server_create(struct osmo_ss7_instance *inst,
enum osmo_ss7_asp_protocol proto,
uint16_t local_port, const char *local_host)
{
const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
return osmo_ss7_xua_server_create2(inst, trans_proto, proto,
local_port, local_host);
}
/*! \brief Set the xUA server to bind/listen to the currently configured ip/port
* \param[in] xs xUA server to operate
* \returns 0 on success, negative value on error.

View File

@ -515,6 +515,9 @@ osmo_sccp_simple_client_on_ss7_id(void *ctx, uint32_t ss7_id, const char *name,
struct osmo_ss7_asp *asp;
bool asp_created = false;
char *as_name, *asp_name = NULL;
int trans_proto;
trans_proto = ss7_default_trans_proto_for_asp_proto(prot);
/*! The function will examine the given CS7 instance and its sub
* components (as, asp, etc.). If necessary it will allocate
@ -625,11 +628,10 @@ osmo_sccp_simple_client_on_ss7_id(void *ctx, uint32_t ss7_id, const char *name,
asp_name = talloc_asprintf(ctx, "asp-clnt-%s", name);
LOGP(DLSCCP, LOGL_NOTICE, "%s: No unassociated ASP for %s, creating new ASP %s\n",
name, osmo_ss7_asp_protocol_name(prot), asp_name);
asp =
osmo_ss7_asp_find_or_create(ss7, asp_name,
default_remote_port,
default_local_port,
prot);
asp = osmo_ss7_asp_find_or_create2(ss7, asp_name,
default_remote_port,
default_local_port,
trans_proto, prot);
talloc_free(asp_name);
if (!asp)
goto out_rt;
@ -678,7 +680,9 @@ osmo_sccp_simple_client_on_ss7_id(void *ctx, uint32_t ss7_id, const char *name,
LOGP(DLSCCP, LOGL_NOTICE,
"%s: Requesting an SCCP simple client on ASP %s configured with 'sctp-role server'\n",
name, asp->cfg.name);
xs = osmo_ss7_xua_server_find(ss7, prot, asp->cfg.local.port);
xs = osmo_ss7_xua_server_find2(ss7,
asp->cfg.trans_proto, prot,
asp->cfg.local.port);
if (!xs) {
LOGP(DLSCCP, LOGL_ERROR, "%s: Requesting an SCCP simple client on ASP %s configured "
"with 'sctp-role server' but no matching xUA server was configured!\n",
@ -755,8 +759,11 @@ osmo_sccp_simple_server_on_ss7_id(void *ctx, uint32_t ss7_id, uint32_t pc,
{
struct osmo_ss7_instance *ss7;
struct osmo_xua_server *xs;
int trans_proto;
int rc;
trans_proto = ss7_default_trans_proto_for_asp_proto(prot);
if (local_port < 0)
local_port = osmo_ss7_asp_protocol_port(prot);
@ -766,7 +773,7 @@ osmo_sccp_simple_server_on_ss7_id(void *ctx, uint32_t ss7_id, uint32_t pc,
return NULL;
ss7->cfg.primary_pc = pc;
xs = osmo_ss7_xua_server_create(ss7, prot, local_port, local_ip);
xs = osmo_ss7_xua_server_create2(ss7, trans_proto, prot, local_port, local_ip);
if (!xs)
goto out_ss7;
@ -811,6 +818,9 @@ osmo_sccp_simple_server_add_clnt(struct osmo_sccp_instance *inst,
struct osmo_ss7_asp *asp;
struct osmo_xua_server *oxs;
char *as_name, *asp_name;
int trans_proto;
trans_proto = ss7_default_trans_proto_for_asp_proto(prot);
if (local_port < 0)
local_port = osmo_ss7_asp_protocol_port(prot);
@ -831,10 +841,12 @@ osmo_sccp_simple_server_add_clnt(struct osmo_sccp_instance *inst,
if (!rt)
goto out_as;
asp = osmo_ss7_asp_find_or_create(ss7, asp_name, remote_port, local_port, prot);
asp = osmo_ss7_asp_find_or_create2(ss7, asp_name,
remote_port, local_port,
trans_proto, prot);
if (!asp)
goto out_rt;
oxs = osmo_ss7_xua_server_find(ss7, prot, local_port);
oxs = osmo_ss7_xua_server_find2(ss7, asp->cfg.trans_proto, prot, local_port);
if (!oxs)
goto out_asp;
if (osmo_ss7_asp_peer_set_hosts(&asp->cfg.local, asp,

View File

@ -16,15 +16,17 @@ struct osmo_ss7_as *ss7_as_alloc(struct osmo_ss7_instance *inst, const char *nam
struct osmo_ss7_asp *ss7_asp_alloc(struct osmo_ss7_instance *inst, const char *name,
uint16_t remote_port, uint16_t local_port,
enum osmo_ss7_asp_protocol proto);
int trans_proto, enum osmo_ss7_asp_protocol proto);
bool ss7_asp_set_default_peer_hosts(struct osmo_ss7_asp *asp);
bool ss7_asp_is_started(const struct osmo_ss7_asp *asp);
int ss7_asp_get_fd(const struct osmo_ss7_asp *asp);
struct osmo_ss7_asp *ss7_asp_find_by_socket_addr(int fd);
int ss7_asp_proto_to_ip_proto(enum osmo_ss7_asp_protocol proto);
bool ss7_asp_protocol_check_trans_proto(enum osmo_ss7_asp_protocol proto, int trans_proto);
int ss7_default_trans_proto_for_asp_proto(enum osmo_ss7_asp_protocol proto);
int ss7_asp_ipa_srv_conn_cb(struct osmo_stream_srv *conn);
int ss7_asp_xua_srv_conn_cb(struct osmo_stream_srv *conn);
int ss7_asp_m3ua_tcp_srv_conn_cb(struct osmo_stream_srv *conn);
int ss7_asp_xua_srv_conn_closed_cb(struct osmo_stream_srv *srv);
int ss7_asp_apply_peer_primary_address(const struct osmo_ss7_asp *asp);
int ss7_asp_apply_primary_address(const struct osmo_ss7_asp *asp);

View File

@ -248,7 +248,8 @@ static void test_as(void)
OSMO_ASSERT(osmo_ss7_as_find_by_rctx(s7i, 2342) == as);
OSMO_ASSERT(osmo_ss7_as_add_asp(as, "asp1") == -ENODEV);
asp = osmo_ss7_asp_find_or_create(s7i, "asp1", 0, M3UA_PORT, OSMO_SS7_ASP_PROT_M3UA);
asp = osmo_ss7_asp_find_or_create2(s7i, "asp1", 0, M3UA_PORT,
IPPROTO_SCTP, OSMO_SS7_ASP_PROT_M3UA);
OSMO_ASSERT(asp);
OSMO_ASSERT(osmo_ss7_as_has_asp(as, asp) == false);

View File

@ -2,6 +2,7 @@ ss7_asp_vty_test> list
... !show cs7
show cs7 instance <0-15> users
show cs7 (sua|m3ua|ipa) [<0-65534>]
show cs7 (sua|m3ua|ipa) (sctp|tcp) [<0-65534>]
show cs7 config
show cs7 instance <0-15> asp
show cs7 instance <0-15> asp name ASP_NAME
@ -23,6 +24,7 @@ ss7_asp_vty_test# list
... !show cs7
show cs7 instance <0-15> users
show cs7 (sua|m3ua|ipa) [<0-65534>]
show cs7 (sua|m3ua|ipa) (sctp|tcp) [<0-65534>]
show cs7 config
cs7 instance <0-15> asp NAME disconnect
show cs7 instance <0-15> asp
@ -53,7 +55,18 @@ ss7_asp_vty_test# show cs7 ?
config Currently running cs7 configuration
ss7_asp_vty_test# show cs7 m3ua ?
[<0-65534>] Port Number
[<0-65534>] Local Port Number
sctp SCTP (Stream Control Transmission Protocol)
tcp TCP (Transmission Control Protocol)
ss7_asp_vty_test# show cs7 m3ua 2905 ?
<cr>
ss7_asp_vty_test# show cs7 m3ua sctp ?
[<0-65534>] Local Port Number
ss7_asp_vty_test# show cs7 m3ua sctp 2905 ?
<cr>
ss7_asp_vty_test# show cs7 instance ?
<0-15> An instance of the SS7 stack
@ -96,6 +109,7 @@ ss7_asp_vty_test(config-cs7)# list
point-code delimiter (default|dash)
xua rkm routing-key-allocation (static-only|dynamic-permitted)
asp NAME <0-65535> <0-65535> (sua|m3ua|ipa)
asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) (sctp|tcp)
no asp NAME
as NAME (sua|m3ua|ipa)
no as NAME
@ -154,13 +168,17 @@ ss7_asp_vty_test(config-cs7)# xua rkm routing-key-allocation ?
ss7_asp_vty_test(config-cs7)# asp ?
NAME Name of ASP
ss7_asp_vty_test(config-cs7)# asp foo ?
<0-65535> Remote SCTP port number
<0-65535> Remote port number
ss7_asp_vty_test(config-cs7)# asp foo 0 ?
<0-65535> Local SCTP port number
<0-65535> Local port number
ss7_asp_vty_test(config-cs7)# asp foo 0 0 ?
sua SCCP User Adaptation
m3ua MTP3 User Adaptation
ipa IPA Multiplex (SCCP Lite)
ss7_asp_vty_test(config-cs7)# asp foo 0 0 m3ua ?
sctp SCTP (Stream Control Transmission Protocol)
tcp TCP (Transmission Control Protocol)
<cr>
ss7_asp_vty_test(config-cs7)# as ?
NAME Name of the Application Server