aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-04-29 19:30:58 +0200
committerHarald Welte <laforge@osmocom.org>2021-04-29 20:07:34 +0200
commit40c4461c3af8c76de14dfb5d2e4ef7668a8f91b9 (patch)
tree0fa0fd89e8e9958c2111efe3bf1672ff677c3b38
parent5b0ec1ce67ede894d2fc8f96422f915280d07611 (diff)
osmo_ss7: Truncate route 'mask' to point code bit length
Otherwise we run into the problem that a route with mask 0xffffff differs from one with a mask of 0x3fff despite having only 14 bit point code length and them being logically equal. Change-Id: I5d5c828de45724d93a0461bb0dd7858fd8378acd Related: SYS#5422
-rw-r--r--include/osmocom/sigtran/osmo_ss7.h1
-rw-r--r--src/osmo_ss7.c20
2 files changed, 21 insertions, 0 deletions
diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h
index b717d53..a278b59 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -114,6 +114,7 @@ int osmo_ss7_instance_set_pc_fmt(struct osmo_ss7_instance *inst,
struct osmo_sccp_instance *osmo_ss7_ensure_sccp(struct osmo_ss7_instance *inst);
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);
/***********************************************************************
* MTP Users (Users of MTP, such as SCCP or ISUP)
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index 98dfc0c..de072b4 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -196,6 +196,15 @@ uint8_t osmo_ss7_pc_width(const struct osmo_ss7_pc_fmt *pc_fmt)
return pc_fmt->component_len[0] + pc_fmt->component_len[1] + pc_fmt->component_len[2];
}
+/* truncate pc or mask to maximum permitted length. This solves
+ * callers specifying arbitrary large masks which then evade duplicate
+ * detection with longer mask lengths */
+uint32_t osmo_ss7_pc_normalize(const struct osmo_ss7_pc_fmt *pc_fmt, uint32_t pc)
+{
+ uint32_t mask = (1 << osmo_ss7_pc_width(pc_fmt))-1;
+ 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,
@@ -702,6 +711,9 @@ osmo_ss7_route_find_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc)
struct osmo_ss7_route *rt;
OSMO_ASSERT(ss7_initialized);
+
+ dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);
+
/* we assume the routes are sorted by mask length, i.e. more
* specific routes first, and less specific routes with shorter
* mask later */
@@ -720,6 +732,9 @@ osmo_ss7_route_find_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc,
struct osmo_ss7_route *rt;
OSMO_ASSERT(ss7_initialized);
+ mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask);
+ dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc);
+
/* we assume the routes are sorted by mask length, i.e. more
* specific routes first, and less specific routes with shorter
* mask later */
@@ -775,6 +790,11 @@ osmo_ss7_route_create(struct osmo_ss7_route_table *rtbl, uint32_t pc,
struct osmo_ss7_linkset *lset;
struct osmo_ss7_as *as = NULL;
+ /* truncate mask to maximum. Let's avoid callers specifying arbitrary large
+ * masks to ensure we don't fail duplicate detection with longer mask lengths */
+ mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask);
+ pc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, pc);
+
OSMO_ASSERT(ss7_initialized);
lset = osmo_ss7_linkset_find_by_name(rtbl->inst, linkset_name);
if (!lset) {