pespin has submitted this change. ( 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, 695 insertions(+), 614 deletions(-)
Approvals: osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved
diff --git a/TODO-RELEASE b/TODO-RELEASE index a8b60f1..101d9cd 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -15,3 +15,4 @@ libosmo-sigtran add API osmo_ss7_instances_llist_entry() libosmo-sigtran add API osmo_ss7_as_get_asp_protocol(), osmo_ss7_as_select_asp() libosmo-sigtran add API osmo_ss7_user: create(), get_instance(), set_prim_cb(), set_priv(), get_priv() +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 5ce9206..0067841 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(const 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);
@@ -118,6 +77,7 @@ ***********************************************************************/
struct osmo_ss7_user; +struct osmo_mtp_prim;
struct osmo_ss7_user *osmo_ss7_user_create(struct osmo_ss7_instance *inst, const char *name); @@ -137,6 +97,15 @@ int osmo_ss7_user_mtp_xfer_req(struct osmo_ss7_instance *inst, struct osmo_mtp_prim *omp);
+ +/*********************************************************************** + * SCCP Instance + ***********************************************************************/ + +struct osmo_sccp_instance; + +void osmo_sccp_set_max_optional_data(struct osmo_sccp_instance *inst, int val); + /*********************************************************************** * SS7 Links ***********************************************************************/ @@ -386,8 +355,6 @@ int local_port, int remote_port, const char *remote_ip);
-void osmo_sccp_set_max_optional_data(struct osmo_sccp_instance *inst, int val); - enum osmo_ss7_as_traffic_mode osmo_ss7_tmode_from_xua(uint32_t in); int osmo_ss7_tmode_to_xua(enum osmo_ss7_as_traffic_mode tmod);
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 0284890..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(const 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..60a8829 --- /dev/null +++ b/src/osmo_ss7_instance.c @@ -0,0 +1,601 @@ +/* (C) 2015-2017 by Harald Welte laforge@gnumonks.org + * (C) 2023-2024 by sysmocom s.f.m.c. GmbH info@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(const 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 db8f198..27bd54f 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);
@@ -31,10 +34,5 @@ SS7_AS_CTR_TX_MSU_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)