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:
parent
85055b5ca2
commit
22929b1c04
|
@ -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}()
|
||||
|
|
|
@ -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);
|
||||
|
|
102
src/osmo_ss7.c
102
src/osmo_ss7.c
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue