Browse code

lcr: improve binary search to support a match including src port

Improve binary search in the lcr module and add a possibility
to do a matching not only based on an IP address of a GW, but also using a source port.

When a possibility to use 'src_port' parameter in from_gw() and from_any_gw()
was introduced here: 14e6fc80b3d2389567c73c4a2196bf8e6d92d8d2
the bsearch() remained untouched, and hence the matching (iteration through existing GWs)
is now done only based on an IP address.

This leads to the issue, when there are more than one GW with the same IP address in gws table,
and from_gw() and from_any_gw() functions are used with the 'src_port' parameter,
it can happen that a wrong GW is picked out by bsearch() from gws table (lcr_gw) and
a check by from_gw() and from_any_gw() returns False.

Hence the matching based on IP address and source port is required for bsearch(),
when from_gw() and from_any_gw() functions are used with the 'src_port' parameter.

This means backwards compatibility is still present (when one uses functions without 'src_port').

Donat Zenichev authored on 17/09/2021 09:56:39
Showing 1 changed files
... ...
@@ -921,6 +921,30 @@ static int comp_gws(const void *_g1, const void *_g2)
921 921
 	return memcmp(g1->ip_addr.u.addr, g2->ip_addr.u.addr, g1->ip_addr.len);
922 922
 }
923 923
 
924
+/*
925
+ * Compare gateways based on their IP address and port
926
+ */
927
+static int comp_gws_include_port(const void *_g1, const void *_g2)
928
+{
929
+	struct gw_info *g1 = (struct gw_info *)_g1;
930
+	struct gw_info *g2 = (struct gw_info *)_g2;
931
+
932
+	/* first address family comparison */
933
+	if(g1->ip_addr.af < g2->ip_addr.af)
934
+		return -1;
935
+	if(g1->ip_addr.af > g2->ip_addr.af)
936
+		return 1;
937
+	if(g1->ip_addr.len < g2->ip_addr.len)
938
+		return -1;
939
+	if(g1->ip_addr.len > g2->ip_addr.len)
940
+		return 1;
941
+
942
+	/* secondly ports comparison */
943
+	if(g1->port != g2->port)
944
+		return -1;
945
+
946
+	return memcmp(g1->ip_addr.u.addr, g2->ip_addr.u.addr, g1->ip_addr.len);
947
+}
924 948
 
925 949
 /* 
926 950
  * Insert gw info into index i or gws table
... ...
@@ -2997,10 +3021,17 @@ static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id,
2997 3021
 		return -1;
2998 3022
 	}
2999 3023
 
3000
-	/* Search for gw ip address */
3001 3024
 	gw.ip_addr = *src_addr;
3002
-	res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
3003
-			sizeof(struct gw_info), comp_gws);
3025
+	if (src_port != 0) {
3026
+		/* Search for gw based on its ip address and port */
3027
+		gw.port = src_port;
3028
+		res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
3029
+				sizeof(struct gw_info), comp_gws_include_port);
3030
+	} else {
3031
+		/* Search for gw based on its ip address */
3032
+		res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
3033
+				sizeof(struct gw_info), comp_gws);
3034
+	}
3004 3035
 
3005 3036
 	/* Store tag and flags and return result */
3006 3037
 	if((res != NULL)