From 40c4461c3af8c76de14dfb5d2e4ef7668a8f91b9 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 29 Apr 2021 19:30:58 +0200 Subject: 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 --- include/osmocom/sigtran/osmo_ss7.h | 1 + src/osmo_ss7.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) 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) { -- cgit v1.2.3