pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-sigtran/+/38664?usp=email )
Change subject: sigtran: Make osmo_ss7_instance struct private
......................................................................
sigtran: Make osmo_ss7_instance struct private
Change-Id: I4562fe21535c5aa468ac0e3831d505bf08b336ec
---
M TODO-RELEASE
M include/osmocom/sigtran/osmo_ss7.h
M src/Makefile.am
M src/osmo_ss7.c
A src/osmo_ss7_instance.c
M src/sccp_scoc.c
M src/sccp_scrc.c
M src/sccp_vty.c
A src/ss7_instance.h
M src/ss7_internal.h
10 files changed, 685 insertions(+), 612 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/64/38664/1
diff --git a/TODO-RELEASE b/TODO-RELEASE
index f56b4e5..0b4ac9c 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -13,3 +13,4 @@
libosmo-sigtran Make private osmo_ss7_route
libosmo-sigtran add API osmo_ss7_instance_get_id(), osmo_ss7_instance_get_name(),
osmo_ss7_instance_get_pc_fmt(), osmo_ss7_instance_get_primary_pc(), osmo_ss7_get_sccp()
libosmo-sigtran add API osmo_ss7_instances_llist_entry()
+libosmo-sigtran Make private struct osmo_ss7_instance
diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h
index 2babed9..705cff6 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -17,20 +17,7 @@
/* Get an entry pointer from a list item in osmo_ss7_instances: */
struct osmo_ss7_instance *osmo_ss7_instances_llist_entry(struct llist_head *list);
-struct osmo_ss7_user;
-struct osmo_sccp_instance;
-struct osmo_mtp_prim;
-struct osmo_ss7_route_table;
-
int osmo_ss7_init(void);
-int osmo_ss7_find_free_rctx(struct osmo_ss7_instance *inst);
-
-bool osmo_ss7_pc_is_local(const struct osmo_ss7_instance *inst, uint32_t pc);
-int osmo_ss7_pointcode_parse(const struct osmo_ss7_instance *inst, const char *str);
-int osmo_ss7_pointcode_parse_mask_or_len(const struct osmo_ss7_instance *inst, const char
*in);
-const char *osmo_ss7_pointcode_print_buf(char *buf, size_t buf_len, const struct
osmo_ss7_instance *inst, uint32_t pc);
-const char *osmo_ss7_pointcode_print(const struct osmo_ss7_instance *inst, uint32_t pc);
-const char *osmo_ss7_pointcode_print2(const struct osmo_ss7_instance *inst, uint32_t
pc);
/* All known point-code formats have a length of or below 24 bit.
* A point-code value exceeding that is used to indicate an unset PC. */
@@ -52,45 +39,8 @@
* SS7 Instances
***********************************************************************/
-struct osmo_ss7_pc_fmt {
- char delimiter;
- uint8_t component_len[3];
-};
-
-struct osmo_ss7_instance {
- /*! member of global list of instances */
- struct llist_head list;
- /*! list of \ref osmo_ss7_linkset */
- struct llist_head linksets;
- /*! list of \ref osmo_ss7_as */
- struct llist_head as_list;
- /*! list of \ref osmo_ss7_asp */
- struct llist_head asp_list;
- /*! list of \ref osmo_ss7_route_table */
- struct llist_head rtable_list;
- /*! list of \ref osmo_xua_servers */
- struct llist_head xua_servers;
- /* array for faster lookup of user (indexed by service
- * indicator) */
- const struct osmo_ss7_user *user[16];
-
- struct osmo_ss7_route_table *rtable_system;
-
- struct osmo_sccp_instance *sccp;
-
- struct {
- uint32_t id;
- char *name;
- char *description;
- uint32_t primary_pc;
- /* capability PCs */
- uint8_t network_indicator;
- struct osmo_ss7_pc_fmt pc_fmt;
- bool permit_dyn_rkm_alloc;
- struct llist_head sccp_address_book;
- uint32_t secondary_pc;
- } cfg;
-};
+struct osmo_ss7_pc_fmt;
+struct osmo_ss7_instance;
struct osmo_ss7_instance *osmo_ss7_instance_find(uint32_t id);
struct osmo_ss7_instance *
@@ -110,6 +60,15 @@
struct osmo_sccp_instance *osmo_ss7_ensure_sccp(struct osmo_ss7_instance *inst);
struct osmo_sccp_instance *osmo_ss7_get_sccp(struct osmo_ss7_instance *inst);
+int osmo_ss7_find_free_rctx(struct osmo_ss7_instance *inst);
+
+bool osmo_ss7_pc_is_local(const struct osmo_ss7_instance *inst, uint32_t pc);
+int osmo_ss7_pointcode_parse(const struct osmo_ss7_instance *inst, const char *str);
+int osmo_ss7_pointcode_parse_mask_or_len(const struct osmo_ss7_instance *inst, const char
*in);
+const char *osmo_ss7_pointcode_print_buf(char *buf, size_t buf_len, const struct
osmo_ss7_instance *inst, uint32_t pc);
+const char *osmo_ss7_pointcode_print(const struct osmo_ss7_instance *inst, uint32_t pc);
+const char *osmo_ss7_pointcode_print2(const struct osmo_ss7_instance *inst, uint32_t
pc);
+
uint8_t osmo_ss7_pc_width(const struct osmo_ss7_pc_fmt *pc_fmt);
uint32_t osmo_ss7_pc_normalize(const struct osmo_ss7_pc_fmt *pc_fmt, uint32_t pc);
diff --git a/src/Makefile.am b/src/Makefile.am
index 1d09c0e..356a33a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@
sccp_internal.h \
ss7_asp.h \
ss7_asp_peer.h \
+ ss7_instance.h \
ss7_internal.h \
ss7_link.h \
ss7_linkset.h \
@@ -43,6 +44,7 @@
osmo_ss7_asp.c \
osmo_ss7_asp_peer.c \
osmo_ss7_hmrt.c \
+ osmo_ss7_instance.c \
osmo_ss7_link.c \
osmo_ss7_linkset.c \
osmo_ss7_vty.c \
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index 2486378..c906cf5 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -58,8 +58,6 @@
#include "xua_asp_fsm.h"
#include "xua_as_fsm.h"
-#define MAX_PC_STR_LEN 32
-
bool ss7_initialized = false;
LLIST_HEAD(osmo_ss7_instances);
@@ -73,9 +71,6 @@
return pos;
}
-static int32_t next_rctx = 1;
-static int32_t next_l_rk_id = 1;
-
const struct value_string mtp_unavail_cause_vals[] = {
{ MTP_UNAVAIL_C_UNKNOWN, "unknown" },
{ MTP_UNAVAIL_C_UNEQUIP_REM_USER, "unequipped-remote-user" },
@@ -83,94 +78,10 @@
{ 0, NULL }
};
-int osmo_ss7_find_free_rctx(struct osmo_ss7_instance *inst)
-{
- int32_t rctx;
-
- for (rctx = next_rctx; rctx; rctx = ++next_rctx) {
- if (!osmo_ss7_as_find_by_rctx(inst, next_rctx))
- return rctx;
- }
- return -1;
-}
-
-uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst)
-{
- uint32_t l_rk_id;
-
- for (l_rk_id = next_l_rk_id; next_l_rk_id; l_rk_id = ++next_l_rk_id) {
- if (!osmo_ss7_as_find_by_l_rk_id(inst, next_l_rk_id))
- return l_rk_id;
- }
- return -1;
-}
-
/***********************************************************************
* SS7 Point Code Parsing / Printing
***********************************************************************/
-static const struct osmo_ss7_pc_fmt default_pc_fmt = {
- .delimiter = '.',
- .component_len = { 3, 8, 3},
-};
-
-/* like strcat() but appends a single character */
-static int strnappendchar(char *str, char c, size_t n)
-{
- unsigned int curlen = strlen(str);
-
- if (n < curlen + 2)
- return -1;
-
- str[curlen] = c;
- str[curlen+1] = '\0';
-
- return curlen+1;
-}
-
-/* generate a format string for formatting a point code. The result can
- * e.g. be used with sscanf() or sprintf() */
-static const char *gen_pc_fmtstr(const struct osmo_ss7_pc_fmt *pc_fmt,
- unsigned int *num_comp_exp)
-{
- static char buf[MAX_PC_STR_LEN];
- unsigned int num_comp = 0;
-
- buf[0] = '\0';
- strcat(buf, "%u");
- num_comp++;
-
- if (pc_fmt->component_len[1] == 0)
- goto out;
- strnappendchar(buf, pc_fmt->delimiter, sizeof(buf));
- strcat(buf, "%u");
- num_comp++;
-
- if (pc_fmt->component_len[2] == 0)
- goto out;
- strnappendchar(buf, pc_fmt->delimiter, sizeof(buf));
- strcat(buf, "%u");
- num_comp++;
-out:
- if (num_comp_exp)
- *num_comp_exp = num_comp;
- return buf;
-}
-
-/* get number of components we expect for a point code, depending on the
- * configuration of this ss7_instance */
-static unsigned int num_pc_comp_exp(const struct osmo_ss7_pc_fmt *pc_fmt)
-{
- unsigned int num_comp_exp = 1;
-
- if (pc_fmt->component_len[1])
- num_comp_exp++;
- if (pc_fmt->component_len[2])
- num_comp_exp++;
-
- return num_comp_exp;
-}
-
/* get the total width (in bits) of the point-codes in this ss7_instance */
uint8_t osmo_ss7_pc_width(const struct osmo_ss7_pc_fmt *pc_fmt)
{
@@ -186,126 +97,6 @@
return pc & mask;
}
-/* get the number of bits we must shift the given component of a point
- * code in this ss7_instance */
-static unsigned int get_pc_comp_shift(const struct osmo_ss7_pc_fmt *pc_fmt,
- unsigned int comp_num)
-{
- uint32_t pc_width = osmo_ss7_pc_width(pc_fmt);
- switch (comp_num) {
- case 0:
- return pc_width - pc_fmt->component_len[0];
- case 1:
- return pc_width - pc_fmt->component_len[0] - pc_fmt->component_len[1];
- case 2:
- return 0;
- default:
- /* Invalid number of components */
- OSMO_ASSERT(false);
- }
-}
-
-static uint32_t pc_comp_shift_and_mask(const struct osmo_ss7_pc_fmt *pc_fmt,
- unsigned int comp_num, uint32_t pc)
-{
- unsigned int shift = get_pc_comp_shift(pc_fmt, comp_num);
- uint32_t mask = (1 << pc_fmt->component_len[comp_num]) - 1;
-
- return (pc >> shift) & mask;
-}
-
-/* parse a point code according to the structure configured for this
- * ss7_instance */
-int osmo_ss7_pointcode_parse(const struct osmo_ss7_instance *inst, const char *str)
-{
- unsigned int component[3];
- const struct osmo_ss7_pc_fmt *pc_fmt = inst ? &inst->cfg.pc_fmt :
&default_pc_fmt;
- unsigned int num_comp_exp = num_pc_comp_exp(pc_fmt);
- const char *fmtstr = gen_pc_fmtstr(pc_fmt, &num_comp_exp);
- int i, rc;
-
- rc = sscanf(str, fmtstr, &component[0], &component[1], &component[2]);
- /* ensure all components were parsed */
- if (rc != num_comp_exp)
- goto err;
-
- /* check none of the component values exceeds what can be
- * represented within its bit-width */
- for (i = 0; i < num_comp_exp; i++) {
- if (component[i] >= (1 << pc_fmt->component_len[i]))
- goto err;
- }
-
- /* shift them all together */
- rc = (component[0] << get_pc_comp_shift(pc_fmt, 0));
- if (num_comp_exp > 1)
- rc |= (component[1] << get_pc_comp_shift(pc_fmt, 1));
- if (num_comp_exp > 2)
- rc |= (component[2] << get_pc_comp_shift(pc_fmt, 2));
-
- return rc;
-
-err:
- LOGSS7(inst, LOGL_NOTICE, "Error parsing Pointcode '%s'\n", str);
- return -EINVAL;
-}
-
-const char *osmo_ss7_pointcode_print_buf(char *buf, size_t len, const struct
osmo_ss7_instance *inst, uint32_t pc)
-{
- const struct osmo_ss7_pc_fmt *pc_fmt;
- unsigned int num_comp_exp;
- const char *fmtstr;
-
- if (!osmo_ss7_pc_is_valid(pc))
- return "(no PC)";
-
- pc_fmt = inst ? &inst->cfg.pc_fmt : &default_pc_fmt;
- num_comp_exp = num_pc_comp_exp(pc_fmt);
- fmtstr = gen_pc_fmtstr(pc_fmt, &num_comp_exp);
- OSMO_ASSERT(fmtstr);
- snprintf(buf, len, fmtstr,
- pc_comp_shift_and_mask(pc_fmt, 0, pc),
- pc_comp_shift_and_mask(pc_fmt, 1, pc),
- pc_comp_shift_and_mask(pc_fmt, 2, pc));
-
- return buf;
-}
-
-
-/* print a pointcode according to the structure configured for this
- * ss7_instance */
-const char *osmo_ss7_pointcode_print(const struct osmo_ss7_instance *inst, uint32_t pc)
-{
- static char buf[MAX_PC_STR_LEN];
- return osmo_ss7_pointcode_print_buf(buf, sizeof(buf), inst, pc);
-}
-
-/* same as osmo_ss7_pointcode_print() but using a separate buffer, useful for multiple
point codes in the
- * same LOGP/printf. */
-const char *osmo_ss7_pointcode_print2(const struct osmo_ss7_instance *inst, uint32_t pc)
-{
- static char buf[MAX_PC_STR_LEN];
- return osmo_ss7_pointcode_print_buf(buf, sizeof(buf), inst, pc);
-}
-
-int osmo_ss7_pointcode_parse_mask_or_len(const struct osmo_ss7_instance *inst, const char
*in)
-{
- unsigned int width = osmo_ss7_pc_width(inst ? &inst->cfg.pc_fmt :
&default_pc_fmt);
-
- if (in[0] == '/') {
- /* parse mask by length */
- int masklen = atoi(in+1);
- if (masklen < 0 || masklen > 32)
- return -EINVAL;
- if (masklen == 0)
- return 0;
- return (0xFFFFFFFF << (width - masklen)) & ((1 << width)-1);
- } else {
- /* parse mask as point code */
- return osmo_ss7_pointcode_parse(inst, in);
- }
-}
-
/***********************************************************************
* SS7 Instance
***********************************************************************/
@@ -326,41 +117,6 @@
return NULL;
}
-static struct osmo_ss7_instance *
-ss7_instance_alloc(void *ctx, uint32_t id)
-{
- struct osmo_ss7_instance *inst;
-
- inst = talloc_zero(ctx, struct osmo_ss7_instance);
- if (!inst)
- return NULL;
-
- inst->cfg.primary_pc = OSMO_SS7_PC_INVALID;
- inst->cfg.secondary_pc = OSMO_SS7_PC_INVALID;
-
- inst->cfg.id = id;
- LOGSS7(inst, LOGL_INFO, "Creating SS7 Instance\n");
-
- INIT_LLIST_HEAD(&inst->linksets);
- INIT_LLIST_HEAD(&inst->as_list);
- INIT_LLIST_HEAD(&inst->asp_list);
- INIT_LLIST_HEAD(&inst->rtable_list);
- INIT_LLIST_HEAD(&inst->xua_servers);
- inst->rtable_system = ss7_route_table_find_or_create(inst, "system");
-
- /* default point code structure + formatting */
- inst->cfg.pc_fmt.delimiter = '.';
- inst->cfg.pc_fmt.component_len[0] = 3;
- inst->cfg.pc_fmt.component_len[1] = 8;
- inst->cfg.pc_fmt.component_len[2] = 3;
-
- llist_add_tail(&inst->list, &osmo_ss7_instances);
-
- INIT_LLIST_HEAD(&inst->cfg.sccp_address_book);
-
- return inst;
-}
-
/*! \brief Find or create a SS7 Instance
* \param[in] ctx talloc allocation context to use for allocations
* \param[in] id ID of SS7 Instance
@@ -378,206 +134,6 @@
return inst;
}
-/*! \brief Destroy a SS7 Instance
- * \param[in] inst SS7 Instance to be destroyed */
-void osmo_ss7_instance_destroy(struct osmo_ss7_instance *inst)
-{
- struct osmo_ss7_linkset *lset, *lset2;
- struct osmo_ss7_as *as, *as2;
- struct osmo_ss7_asp *asp, *asp2;
-
- OSMO_ASSERT(ss7_initialized);
- LOGSS7(inst, LOGL_INFO, "Destroying SS7 Instance\n");
-
- llist_for_each_entry_safe(asp, asp2, &inst->asp_list, list)
- osmo_ss7_asp_destroy(asp);
-
- llist_for_each_entry_safe(as, as2, &inst->as_list, list)
- osmo_ss7_as_destroy(as);
-
- llist_for_each_entry_safe(lset, lset2, &inst->linksets, list)
- ss7_linkset_destroy(lset);
-
- llist_del(&inst->list);
- talloc_free(inst);
-}
-
-uint32_t osmo_ss7_instance_get_id(const struct osmo_ss7_instance *inst)
-{
- return inst->cfg.id;
-}
-
-const char *osmo_ss7_instance_get_name(const struct osmo_ss7_instance *inst)
-{
- return inst->cfg.name;
-}
-
-uint32_t osmo_ss7_instance_get_primary_pc(const struct osmo_ss7_instance *inst)
-{
- return inst->cfg.primary_pc;
-}
-
-/*! \brief Set the point code format used in given SS7 instance */
-int osmo_ss7_instance_set_pc_fmt(struct osmo_ss7_instance *inst,
- uint8_t c0, uint8_t c1, uint8_t c2)
-{
- if (c0+c1+c2 > 32)
- return -EINVAL;
-
- if (c0+c1+c2 > 14)
- LOGSS7(inst, LOGL_NOTICE, "Point Code Format %u-%u-%u "
- "is longer than 14 bits, odd?\n", c0, c1, c2);
-
- inst->cfg.pc_fmt.component_len[0] = c0;
- inst->cfg.pc_fmt.component_len[1] = c1;
- inst->cfg.pc_fmt.component_len[2] = c2;
-
- return 0;
-}
-
-const struct osmo_ss7_pc_fmt *
-osmo_ss7_instance_get_pc_fmt(const struct osmo_ss7_instance *inst)
-{
- return &inst->cfg.pc_fmt;
-}
-
-/*! Allocate an SCCP instance, if not present yet.
- * \returns inst->sccp. */
-struct osmo_sccp_instance *osmo_ss7_ensure_sccp(struct osmo_ss7_instance *inst)
-{
- if (inst->sccp)
- return inst->sccp;
-
- LOGSS7(inst, LOGL_NOTICE, "Creating SCCP instance\n");
- inst->sccp = osmo_sccp_instance_create(inst, NULL);
- return inst->sccp;
-}
-
-/*! Get the SCCP instance, if present.
- * \param[in] inst SS7 Instance on which we operate
- * \returns inst->sccp, may be NULL if no SCCP instance was created yet (see
osmo_ss7_ensure_sccp()).
- */
-struct osmo_sccp_instance *osmo_ss7_get_sccp(struct osmo_ss7_instance *inst)
-{
- return inst->sccp;
-}
-
-/***********************************************************************
- * SS7 Application Server
- ***********************************************************************/
-
-/*! \brief Find Application Server by given name
- * \param[in] inst SS7 Instance on which we operate
- * \param[in] name Name of AS
- * \returns pointer to Application Server on success; NULL otherwise */
-struct osmo_ss7_as *
-osmo_ss7_as_find_by_name(struct osmo_ss7_instance *inst, const char *name)
-{
- struct osmo_ss7_as *as;
-
- OSMO_ASSERT(ss7_initialized);
- llist_for_each_entry(as, &inst->as_list, list) {
- if (!strcmp(name, as->cfg.name))
- return as;
- }
- return NULL;
-}
-
-/*! \brief Find Application Server by given routing context
- * \param[in] inst SS7 Instance on which we operate
- * \param[in] rctx Routing Context
- * \returns pointer to Application Server on success; NULL otherwise */
-struct osmo_ss7_as *
-osmo_ss7_as_find_by_rctx(struct osmo_ss7_instance *inst, uint32_t rctx)
-{
- struct osmo_ss7_as *as;
-
- OSMO_ASSERT(ss7_initialized);
- llist_for_each_entry(as, &inst->as_list, list) {
- if (as->cfg.routing_key.context == rctx)
- return as;
- }
- return NULL;
-}
-
-/*! \brief Find Application Server by given local routing key ID
- * \param[in] inst SS7 Instance on which we operate
- * \param[in] l_rk_id Local Routing Key ID
- * \returns pointer to Application Server on success; NULL otherwise */
-struct osmo_ss7_as *
-osmo_ss7_as_find_by_l_rk_id(struct osmo_ss7_instance *inst, uint32_t l_rk_id)
-{
- struct osmo_ss7_as *as;
-
- OSMO_ASSERT(ss7_initialized);
- llist_for_each_entry(as, &inst->as_list, list) {
- if (as->cfg.routing_key.l_rk_id == l_rk_id)
- return as;
- }
- return NULL;
-}
-
-/*! \brief Find Application Server (AS) by given protocol.
- * \param[in] inst SS7 Instance on which we operate
- * \param[in] proto Protocol identifier that must match
- * \returns pointer to AS on success; NULL otherwise
- * If an AS has an ASP also matching the given protocol, that AS is preferred.
- * If there are multiple matches, return the first matching AS. */
-struct osmo_ss7_as *osmo_ss7_as_find_by_proto(struct osmo_ss7_instance *inst,
- enum osmo_ss7_asp_protocol proto)
-{
- struct osmo_ss7_as *as;
- struct osmo_ss7_as *as_without_asp = NULL;
-
- OSMO_ASSERT(ss7_initialized);
-
- /* Loop through the list with AS and try to find one where the proto
- matches up */
- llist_for_each_entry(as, &inst->as_list, list) {
- if (as->cfg.proto != proto)
- continue;
-
- /* Put down the first AS that matches the proto, just in
- * case we will not find any matching ASP */
- if (!as_without_asp)
- as_without_asp = as;
-
- /* Check if the candicate we have here has any suitable ASP */
- if (osmo_ss7_asp_find_by_proto(as, proto))
- return as;
- }
-
- /* Return with the second best find, if there is any */
- return as_without_asp;
-}
-
-/*! \brief Find or Create Application Server
- * \param[in] inst SS7 Instance on which we operate
- * \param[in] name Name of Application Server
- * \param[in] proto Protocol of Application Server
- * \returns pointer to Application Server on success; NULL otherwise */
-struct osmo_ss7_as *
-osmo_ss7_as_find_or_create(struct osmo_ss7_instance *inst, const char *name,
- enum osmo_ss7_asp_protocol proto)
-{
- struct osmo_ss7_as *as;
-
- OSMO_ASSERT(ss7_initialized);
- as = osmo_ss7_as_find_by_name(inst, name);
-
- if (as && as->cfg.proto != proto)
- return NULL;
-
- if (!as) {
- as = ss7_as_alloc(inst, name, proto);
- if (!as)
- return NULL;
- LOGPAS(as, DLSS7, LOGL_INFO, "Created AS\n");
- }
-
- return as;
-}
-
bool ss7_ipv6_sctp_supported(const char *host, bool bind)
{
int rc;
@@ -604,116 +160,6 @@
return true;
}
-struct osmo_ss7_asp *
-osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name)
-{
- struct osmo_ss7_asp *asp;
-
- OSMO_ASSERT(ss7_initialized);
- llist_for_each_entry(asp, &inst->asp_list, list) {
- if (!strcmp(name, asp->cfg.name))
- return asp;
- }
- return NULL;
-}
-
-/*! \brief Find an ASP that matches the given ASP protocol (xUA variant).
- * \param[in] as Application Server in which to look for \ref asp
- * \param[in] proto ASP protocol (xUA variant) to match
- * \returns SS7 ASP in case a matching one is found; NULL otherwise */
-struct osmo_ss7_asp *
-osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
- enum osmo_ss7_asp_protocol proto)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
- if (as->cfg.asps[i] && as->cfg.asps[i]->cfg.proto == proto)
- return as->cfg.asps[i];
- }
-
- return NULL;
-}
-
-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 *asp;
-
- OSMO_ASSERT(ss7_initialized);
- asp = osmo_ss7_asp_find_by_name(inst, name);
- if (!asp)
- return NULL;
-
- 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)
-{
- const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
-
- return osmo_ss7_asp_find_or_create2(inst, name,
- remote_port, local_port,
- trans_proto, proto);
-}
-
-bool osmo_ss7_pc_is_local(const struct osmo_ss7_instance *inst, uint32_t pc)
-{
- OSMO_ASSERT(ss7_initialized);
- if (osmo_ss7_pc_is_valid(inst->cfg.primary_pc) && pc ==
inst->cfg.primary_pc)
- return true;
- if (osmo_ss7_pc_is_valid(inst->cfg.secondary_pc) && pc ==
inst->cfg.secondary_pc)
- return true;
- /* FIXME: Capability Point Codes */
- return false;
-}
-
int osmo_ss7_init(void)
{
int rc;
diff --git a/src/osmo_ss7_instance.c b/src/osmo_ss7_instance.c
new file mode 100644
index 0000000..86a45bd
--- /dev/null
+++ b/src/osmo_ss7_instance.c
@@ -0,0 +1,601 @@
+/* (C) 2015-2017 by Harald Welte <laforge(a)gnumonks.org>
+ * (C) 2023-2024 by sysmocom s.f.m.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/***********************************************************************
+ * SS7 Instance
+ ***********************************************************************/
+
+#include <errno.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/talloc.h>
+
+#include <osmocom/sigtran/osmo_ss7.h>
+#include <osmocom/sigtran/sccp_sap.h>
+
+#include "ss7_asp.h"
+#include "ss7_internal.h"
+#include "ss7_instance.h"
+#include "ss7_linkset.h"
+#include "ss7_route_table.h"
+
+static int32_t next_rctx = 1;
+static int32_t next_l_rk_id = 1;
+
+static const struct osmo_ss7_pc_fmt default_pc_fmt = {
+ .delimiter = '.',
+ .component_len = { 3, 8, 3},
+};
+
+struct osmo_ss7_instance *
+ss7_instance_alloc(void *ctx, uint32_t id)
+{
+ struct osmo_ss7_instance *inst;
+
+ inst = talloc_zero(ctx, struct osmo_ss7_instance);
+ if (!inst)
+ return NULL;
+
+ inst->cfg.primary_pc = OSMO_SS7_PC_INVALID;
+ inst->cfg.secondary_pc = OSMO_SS7_PC_INVALID;
+
+ inst->cfg.id = id;
+ LOGSS7(inst, LOGL_INFO, "Creating SS7 Instance\n");
+
+ INIT_LLIST_HEAD(&inst->linksets);
+ INIT_LLIST_HEAD(&inst->as_list);
+ INIT_LLIST_HEAD(&inst->asp_list);
+ INIT_LLIST_HEAD(&inst->rtable_list);
+ INIT_LLIST_HEAD(&inst->xua_servers);
+ inst->rtable_system = ss7_route_table_find_or_create(inst, "system");
+
+ /* default point code structure + formatting */
+ inst->cfg.pc_fmt.delimiter = '.';
+ inst->cfg.pc_fmt.component_len[0] = 3;
+ inst->cfg.pc_fmt.component_len[1] = 8;
+ inst->cfg.pc_fmt.component_len[2] = 3;
+
+ llist_add_tail(&inst->list, &osmo_ss7_instances);
+
+ INIT_LLIST_HEAD(&inst->cfg.sccp_address_book);
+
+ return inst;
+}
+
+
+/*! \brief Destroy a SS7 Instance
+ * \param[in] inst SS7 Instance to be destroyed */
+void osmo_ss7_instance_destroy(struct osmo_ss7_instance *inst)
+{
+ struct osmo_ss7_linkset *lset, *lset2;
+ struct osmo_ss7_as *as, *as2;
+ struct osmo_ss7_asp *asp, *asp2;
+
+ OSMO_ASSERT(ss7_initialized);
+ LOGSS7(inst, LOGL_INFO, "Destroying SS7 Instance\n");
+
+ llist_for_each_entry_safe(asp, asp2, &inst->asp_list, list)
+ osmo_ss7_asp_destroy(asp);
+
+ llist_for_each_entry_safe(as, as2, &inst->as_list, list)
+ osmo_ss7_as_destroy(as);
+
+ llist_for_each_entry_safe(lset, lset2, &inst->linksets, list)
+ ss7_linkset_destroy(lset);
+
+ llist_del(&inst->list);
+ talloc_free(inst);
+}
+
+
+uint32_t osmo_ss7_instance_get_id(const struct osmo_ss7_instance *inst)
+{
+ return inst->cfg.id;
+}
+
+const char *osmo_ss7_instance_get_name(const struct osmo_ss7_instance *inst)
+{
+ return inst->cfg.name;
+}
+
+uint32_t osmo_ss7_instance_get_primary_pc(const struct osmo_ss7_instance *inst)
+{
+ return inst->cfg.primary_pc;
+}
+
+/*! \brief Set the point code format used in given SS7 instance */
+int osmo_ss7_instance_set_pc_fmt(struct osmo_ss7_instance *inst,
+ uint8_t c0, uint8_t c1, uint8_t c2)
+{
+ if (c0+c1+c2 > 32)
+ return -EINVAL;
+
+ if (c0+c1+c2 > 14)
+ LOGSS7(inst, LOGL_NOTICE, "Point Code Format %u-%u-%u "
+ "is longer than 14 bits, odd?\n", c0, c1, c2);
+
+ inst->cfg.pc_fmt.component_len[0] = c0;
+ inst->cfg.pc_fmt.component_len[1] = c1;
+ inst->cfg.pc_fmt.component_len[2] = c2;
+
+ return 0;
+}
+
+const struct osmo_ss7_pc_fmt *
+osmo_ss7_instance_get_pc_fmt(const struct osmo_ss7_instance *inst)
+{
+ return &inst->cfg.pc_fmt;
+}
+
+/*! Allocate an SCCP instance, if not present yet.
+ * \returns inst->sccp. */
+struct osmo_sccp_instance *osmo_ss7_ensure_sccp(struct osmo_ss7_instance *inst)
+{
+ if (inst->sccp)
+ return inst->sccp;
+
+ LOGSS7(inst, LOGL_NOTICE, "Creating SCCP instance\n");
+ inst->sccp = osmo_sccp_instance_create(inst, NULL);
+ return inst->sccp;
+}
+
+/*! Get the SCCP instance, if present.
+ * \param[in] inst SS7 Instance on which we operate
+ * \returns inst->sccp, may be NULL if no SCCP instance was created yet (see
osmo_ss7_ensure_sccp()).
+ */
+struct osmo_sccp_instance *osmo_ss7_get_sccp(struct osmo_ss7_instance *inst)
+{
+ return inst->sccp;
+}
+
+bool osmo_ss7_pc_is_local(const struct osmo_ss7_instance *inst, uint32_t pc)
+{
+ OSMO_ASSERT(ss7_initialized);
+ if (osmo_ss7_pc_is_valid(inst->cfg.primary_pc) && pc ==
inst->cfg.primary_pc)
+ return true;
+ if (osmo_ss7_pc_is_valid(inst->cfg.secondary_pc) && pc ==
inst->cfg.secondary_pc)
+ return true;
+ /* FIXME: Capability Point Codes */
+ return false;
+}
+
+int osmo_ss7_find_free_rctx(struct osmo_ss7_instance *inst)
+{
+ int32_t rctx;
+
+ for (rctx = next_rctx; rctx; rctx = ++next_rctx) {
+ if (!osmo_ss7_as_find_by_rctx(inst, next_rctx))
+ return rctx;
+ }
+ return -1;
+}
+
+uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst)
+{
+ uint32_t l_rk_id;
+
+ for (l_rk_id = next_l_rk_id; next_l_rk_id; l_rk_id = ++next_l_rk_id) {
+ if (!osmo_ss7_as_find_by_l_rk_id(inst, next_l_rk_id))
+ return l_rk_id;
+ }
+ return -1;
+}
+
+/***********************************************************************
+ * SS7 Application Server
+ ***********************************************************************/
+
+/*! \brief Find Application Server by given name
+ * \param[in] inst SS7 Instance on which we operate
+ * \param[in] name Name of AS
+ * \returns pointer to Application Server on success; NULL otherwise */
+struct osmo_ss7_as *
+osmo_ss7_as_find_by_name(struct osmo_ss7_instance *inst, const char *name)
+{
+ struct osmo_ss7_as *as;
+
+ OSMO_ASSERT(ss7_initialized);
+ llist_for_each_entry(as, &inst->as_list, list) {
+ if (!strcmp(name, as->cfg.name))
+ return as;
+ }
+ return NULL;
+}
+
+/*! \brief Find Application Server by given routing context
+ * \param[in] inst SS7 Instance on which we operate
+ * \param[in] rctx Routing Context
+ * \returns pointer to Application Server on success; NULL otherwise */
+struct osmo_ss7_as *
+osmo_ss7_as_find_by_rctx(struct osmo_ss7_instance *inst, uint32_t rctx)
+{
+ struct osmo_ss7_as *as;
+
+ OSMO_ASSERT(ss7_initialized);
+ llist_for_each_entry(as, &inst->as_list, list) {
+ if (as->cfg.routing_key.context == rctx)
+ return as;
+ }
+ return NULL;
+}
+
+/*! \brief Find Application Server by given local routing key ID
+ * \param[in] inst SS7 Instance on which we operate
+ * \param[in] l_rk_id Local Routing Key ID
+ * \returns pointer to Application Server on success; NULL otherwise */
+struct osmo_ss7_as *
+osmo_ss7_as_find_by_l_rk_id(struct osmo_ss7_instance *inst, uint32_t l_rk_id)
+{
+ struct osmo_ss7_as *as;
+
+ OSMO_ASSERT(ss7_initialized);
+ llist_for_each_entry(as, &inst->as_list, list) {
+ if (as->cfg.routing_key.l_rk_id == l_rk_id)
+ return as;
+ }
+ return NULL;
+}
+
+/*! \brief Find Application Server (AS) by given protocol.
+ * \param[in] inst SS7 Instance on which we operate
+ * \param[in] proto Protocol identifier that must match
+ * \returns pointer to AS on success; NULL otherwise
+ * If an AS has an ASP also matching the given protocol, that AS is preferred.
+ * If there are multiple matches, return the first matching AS. */
+struct osmo_ss7_as *osmo_ss7_as_find_by_proto(struct osmo_ss7_instance *inst,
+ enum osmo_ss7_asp_protocol proto)
+{
+ struct osmo_ss7_as *as;
+ struct osmo_ss7_as *as_without_asp = NULL;
+
+ OSMO_ASSERT(ss7_initialized);
+
+ /* Loop through the list with AS and try to find one where the proto
+ matches up */
+ llist_for_each_entry(as, &inst->as_list, list) {
+ if (as->cfg.proto != proto)
+ continue;
+
+ /* Put down the first AS that matches the proto, just in
+ * case we will not find any matching ASP */
+ if (!as_without_asp)
+ as_without_asp = as;
+
+ /* Check if the candicate we have here has any suitable ASP */
+ if (osmo_ss7_asp_find_by_proto(as, proto))
+ return as;
+ }
+
+ /* Return with the second best find, if there is any */
+ return as_without_asp;
+}
+
+/*! \brief Find or Create Application Server
+ * \param[in] inst SS7 Instance on which we operate
+ * \param[in] name Name of Application Server
+ * \param[in] proto Protocol of Application Server
+ * \returns pointer to Application Server on success; NULL otherwise */
+struct osmo_ss7_as *
+osmo_ss7_as_find_or_create(struct osmo_ss7_instance *inst, const char *name,
+ enum osmo_ss7_asp_protocol proto)
+{
+ struct osmo_ss7_as *as;
+
+ OSMO_ASSERT(ss7_initialized);
+ as = osmo_ss7_as_find_by_name(inst, name);
+
+ if (as && as->cfg.proto != proto)
+ return NULL;
+
+ if (!as) {
+ as = ss7_as_alloc(inst, name, proto);
+ if (!as)
+ return NULL;
+ LOGPAS(as, DLSS7, LOGL_INFO, "Created AS\n");
+ }
+
+ return as;
+}
+
+/***********************************************************************
+ * SS7 Application Server Process
+ ***********************************************************************/
+
+struct osmo_ss7_asp *
+osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name)
+{
+ struct osmo_ss7_asp *asp;
+
+ OSMO_ASSERT(ss7_initialized);
+ llist_for_each_entry(asp, &inst->asp_list, list) {
+ if (!strcmp(name, asp->cfg.name))
+ return asp;
+ }
+ return NULL;
+}
+
+/*! \brief Find an ASP that matches the given ASP protocol (xUA variant).
+ * \param[in] as Application Server in which to look for \ref asp
+ * \param[in] proto ASP protocol (xUA variant) to match
+ * \returns SS7 ASP in case a matching one is found; NULL otherwise */
+struct osmo_ss7_asp *
+osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
+ enum osmo_ss7_asp_protocol proto)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
+ if (as->cfg.asps[i] && as->cfg.asps[i]->cfg.proto == proto)
+ return as->cfg.asps[i];
+ }
+
+ return NULL;
+}
+
+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 *asp;
+
+ OSMO_ASSERT(ss7_initialized);
+ asp = osmo_ss7_asp_find_by_name(inst, name);
+ if (!asp)
+ return NULL;
+
+ 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)
+{
+ const int trans_proto = ss7_default_trans_proto_for_asp_proto(proto);
+
+ return osmo_ss7_asp_find_or_create2(inst, name,
+ remote_port, local_port,
+ trans_proto, proto);
+}
+
+/***********************************************************************
+ * SS7 Point Code Parsing / Printing
+ ***********************************************************************/
+
+/* like strcat() but appends a single character */
+static int strnappendchar(char *str, char c, size_t n)
+{
+ unsigned int curlen = strlen(str);
+
+ if (n < curlen + 2)
+ return -1;
+
+ str[curlen] = c;
+ str[curlen+1] = '\0';
+
+ return curlen+1;
+}
+
+/* generate a format string for formatting a point code. The result can
+ * e.g. be used with sscanf() or sprintf() */
+static const char *gen_pc_fmtstr(const struct osmo_ss7_pc_fmt *pc_fmt,
+ unsigned int *num_comp_exp)
+{
+ static char buf[MAX_PC_STR_LEN];
+ unsigned int num_comp = 0;
+
+ buf[0] = '\0';
+ strcat(buf, "%u");
+ num_comp++;
+
+ if (pc_fmt->component_len[1] == 0)
+ goto out;
+ strnappendchar(buf, pc_fmt->delimiter, sizeof(buf));
+ strcat(buf, "%u");
+ num_comp++;
+
+ if (pc_fmt->component_len[2] == 0)
+ goto out;
+ strnappendchar(buf, pc_fmt->delimiter, sizeof(buf));
+ strcat(buf, "%u");
+ num_comp++;
+out:
+ if (num_comp_exp)
+ *num_comp_exp = num_comp;
+ return buf;
+}
+
+/* get number of components we expect for a point code, depending on the
+ * configuration of this ss7_instance */
+static unsigned int num_pc_comp_exp(const struct osmo_ss7_pc_fmt *pc_fmt)
+{
+ unsigned int num_comp_exp = 1;
+
+ if (pc_fmt->component_len[1])
+ num_comp_exp++;
+ if (pc_fmt->component_len[2])
+ num_comp_exp++;
+
+ return num_comp_exp;
+}
+
+/* get the number of bits we must shift the given component of a point
+ * code in this ss7_instance */
+static unsigned int get_pc_comp_shift(const struct osmo_ss7_pc_fmt *pc_fmt,
+ unsigned int comp_num)
+{
+ uint32_t pc_width = osmo_ss7_pc_width(pc_fmt);
+ switch (comp_num) {
+ case 0:
+ return pc_width - pc_fmt->component_len[0];
+ case 1:
+ return pc_width - pc_fmt->component_len[0] - pc_fmt->component_len[1];
+ case 2:
+ return 0;
+ default:
+ /* Invalid number of components */
+ OSMO_ASSERT(false);
+ }
+}
+
+static uint32_t pc_comp_shift_and_mask(const struct osmo_ss7_pc_fmt *pc_fmt,
+ unsigned int comp_num, uint32_t pc)
+{
+ unsigned int shift = get_pc_comp_shift(pc_fmt, comp_num);
+ uint32_t mask = (1 << pc_fmt->component_len[comp_num]) - 1;
+
+ return (pc >> shift) & mask;
+}
+
+/* parse a point code according to the structure configured for this
+ * ss7_instance */
+int osmo_ss7_pointcode_parse(const struct osmo_ss7_instance *inst, const char *str)
+{
+ unsigned int component[3];
+ const struct osmo_ss7_pc_fmt *pc_fmt = inst ? &inst->cfg.pc_fmt :
&default_pc_fmt;
+ unsigned int num_comp_exp = num_pc_comp_exp(pc_fmt);
+ const char *fmtstr = gen_pc_fmtstr(pc_fmt, &num_comp_exp);
+ int i, rc;
+
+ rc = sscanf(str, fmtstr, &component[0], &component[1], &component[2]);
+ /* ensure all components were parsed */
+ if (rc != num_comp_exp)
+ goto err;
+
+ /* check none of the component values exceeds what can be
+ * represented within its bit-width */
+ for (i = 0; i < num_comp_exp; i++) {
+ if (component[i] >= (1 << pc_fmt->component_len[i]))
+ goto err;
+ }
+
+ /* shift them all together */
+ rc = (component[0] << get_pc_comp_shift(pc_fmt, 0));
+ if (num_comp_exp > 1)
+ rc |= (component[1] << get_pc_comp_shift(pc_fmt, 1));
+ if (num_comp_exp > 2)
+ rc |= (component[2] << get_pc_comp_shift(pc_fmt, 2));
+
+ return rc;
+
+err:
+ LOGSS7(inst, LOGL_NOTICE, "Error parsing Pointcode '%s'\n", str);
+ return -EINVAL;
+}
+
+const char *osmo_ss7_pointcode_print_buf(char *buf, size_t len, const struct
osmo_ss7_instance *inst, uint32_t pc)
+{
+ const struct osmo_ss7_pc_fmt *pc_fmt;
+ unsigned int num_comp_exp;
+ const char *fmtstr;
+
+ if (!osmo_ss7_pc_is_valid(pc))
+ return "(no PC)";
+
+ pc_fmt = inst ? &inst->cfg.pc_fmt : &default_pc_fmt;
+ num_comp_exp = num_pc_comp_exp(pc_fmt);
+ fmtstr = gen_pc_fmtstr(pc_fmt, &num_comp_exp);
+ OSMO_ASSERT(fmtstr);
+ snprintf(buf, len, fmtstr,
+ pc_comp_shift_and_mask(pc_fmt, 0, pc),
+ pc_comp_shift_and_mask(pc_fmt, 1, pc),
+ pc_comp_shift_and_mask(pc_fmt, 2, pc));
+
+ return buf;
+}
+
+
+/* print a pointcode according to the structure configured for this
+ * ss7_instance */
+const char *osmo_ss7_pointcode_print(const struct osmo_ss7_instance *inst, uint32_t pc)
+{
+ static char buf[MAX_PC_STR_LEN];
+ return osmo_ss7_pointcode_print_buf(buf, sizeof(buf), inst, pc);
+}
+
+/* same as osmo_ss7_pointcode_print() but using a separate buffer, useful for multiple
point codes in the
+ * same LOGP/printf. */
+const char *osmo_ss7_pointcode_print2(const struct osmo_ss7_instance *inst, uint32_t pc)
+{
+ static char buf[MAX_PC_STR_LEN];
+ return osmo_ss7_pointcode_print_buf(buf, sizeof(buf), inst, pc);
+}
+
+int osmo_ss7_pointcode_parse_mask_or_len(const struct osmo_ss7_instance *inst, const char
*in)
+{
+ unsigned int width = osmo_ss7_pc_width(inst ? &inst->cfg.pc_fmt :
&default_pc_fmt);
+
+ if (in[0] == '/') {
+ /* parse mask by length */
+ int masklen = atoi(in+1);
+ if (masklen < 0 || masklen > 32)
+ return -EINVAL;
+ if (masklen == 0)
+ return 0;
+ return (0xFFFFFFFF << (width - masklen)) & ((1 << width)-1);
+ }
+ /* parse mask as point code */
+ return osmo_ss7_pointcode_parse(inst, in);
+}
diff --git a/src/sccp_scoc.c b/src/sccp_scoc.c
index 0e1eb34..c11dddf 100644
--- a/src/sccp_scoc.c
+++ b/src/sccp_scoc.c
@@ -63,6 +63,7 @@
#include "xua_internal.h"
#include "sccp_internal.h"
+#include "ss7_instance.h"
#define S(x) (1 << (x))
#define SCU_MSGB_SIZE 1024
diff --git a/src/sccp_scrc.c b/src/sccp_scrc.c
index d9eb6df..33f0633 100644
--- a/src/sccp_scrc.c
+++ b/src/sccp_scrc.c
@@ -33,6 +33,7 @@
#include <osmocom/sigtran/protocol/mtp.h>
#include "sccp_internal.h"
+#include "ss7_instance.h"
#include "ss7_linkset.h"
#include "ss7_route.h"
#include "xua_internal.h"
diff --git a/src/sccp_vty.c b/src/sccp_vty.c
index 4bd1e4d..49f3577 100644
--- a/src/sccp_vty.c
+++ b/src/sccp_vty.c
@@ -41,6 +41,7 @@
#include "xua_internal.h"
#include "sccp_internal.h"
+#include "ss7_instance.h"
static void show_user(struct vty *vty, struct osmo_sccp_user *user)
{
diff --git a/src/ss7_instance.h b/src/ss7_instance.h
new file mode 100644
index 0000000..d76891f
--- /dev/null
+++ b/src/ss7_instance.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <osmocom/core/linuxlist.h>
+
+/***********************************************************************
+ * SS7 Instances
+ ***********************************************************************/
+
+struct osmo_ss7_user;
+struct osmo_ss7_route_table;
+struct osmo_sccp_instance;
+
+struct osmo_ss7_pc_fmt {
+ char delimiter;
+ uint8_t component_len[3];
+};
+
+struct osmo_ss7_instance {
+ /*! member of global list of instances */
+ struct llist_head list;
+ /*! list of \ref osmo_ss7_linkset */
+ struct llist_head linksets;
+ /*! list of \ref osmo_ss7_as */
+ struct llist_head as_list;
+ /*! list of \ref osmo_ss7_asp */
+ struct llist_head asp_list;
+ /*! list of \ref osmo_ss7_route_table */
+ struct llist_head rtable_list;
+ /*! list of \ref osmo_xua_servers */
+ struct llist_head xua_servers;
+ /* array for faster lookup of user (indexed by service
+ * indicator) */
+ const struct osmo_ss7_user *user[16];
+
+ struct osmo_ss7_route_table *rtable_system;
+
+ struct osmo_sccp_instance *sccp;
+
+ struct {
+ uint32_t id;
+ char *name;
+ char *description;
+ uint32_t primary_pc;
+ /* capability PCs */
+ uint8_t network_indicator;
+ struct osmo_ss7_pc_fmt pc_fmt;
+ bool permit_dyn_rkm_alloc;
+ struct llist_head sccp_address_book;
+ uint32_t secondary_pc;
+ } cfg;
+};
+
+struct osmo_ss7_instance *
+ss7_instance_alloc(void *ctx, uint32_t id);
+
+uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst);
+
+#define _LOGSS7(inst, subsys, level, fmt, args ...) \
+ LOGP(subsys, level, "%u: " fmt, inst ? (inst)->cfg.id : 0, ## args)
+#define LOGSS7(inst, level, fmt, args ...) \
+ _LOGSS7(inst, DLSS7, level, fmt, ## args)
diff --git a/src/ss7_internal.h b/src/ss7_internal.h
index 33d18a6..f85a08a 100644
--- a/src/ss7_internal.h
+++ b/src/ss7_internal.h
@@ -7,8 +7,11 @@
#include <osmocom/netif/stream.h>
#include <osmocom/sigtran/osmo_ss7.h>
+#include "ss7_instance.h"
+
+#define MAX_PC_STR_LEN 32
+
extern bool ss7_initialized;
-uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst);
bool ss7_ipv6_sctp_supported(const char *host, bool bind);
@@ -37,10 +40,5 @@
SS7_ASP_CTR_PKT_TX_TOTAL,
};
-#define _LOGSS7(inst, subsys, level, fmt, args ...) \
- LOGP(subsys, level, "%u: " fmt, inst ? (inst)->cfg.id : 0, ## args)
-#define LOGSS7(inst, level, fmt, args ...) \
- _LOGSS7(inst, DLSS7, level, fmt, ## args)
-
#define LOGPAS(as, subsys, level, fmt, args ...) \
_LOGSS7((as)->inst, subsys, level, "as-%s: " fmt, (as)->cfg.name, ##
args)
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-sigtran/+/38664?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I4562fe21535c5aa468ac0e3831d505bf08b336ec
Gerrit-Change-Number: 38664
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>