bluetooth: mesh: brg_cfg_srv: ignore message with invalid parameters

When a message with invalid parameters is received, we must ignore it.

In this commit we check invalid parameters first.

Signed-off-by: Pavel Vasilyev <pavel.vasilyev@nordicsemi.no>
diff --git a/subsys/bluetooth/mesh/brg_cfg.c b/subsys/bluetooth/mesh/brg_cfg.c
index c6974b9..d13e1a5 100644
--- a/subsys/bluetooth/mesh/brg_cfg.c
+++ b/subsys/bluetooth/mesh/brg_cfg.c
@@ -14,6 +14,7 @@
 #include "net.h"
 #include "settings.h"
 #include "brg_cfg.h"
+#include "foundation.h"
 
 #define LOG_LEVEL CONFIG_BT_MESH_BRG_LOG_LEVEL
 #include <zephyr/logging/log.h>
@@ -219,26 +220,38 @@
 	return bt_mesh_brg_cfg_row_cnt;
 }
 
+static bool netkey_check(uint16_t net_idx1, uint16_t net_idx2)
+{
+	return bt_mesh_subnet_get(net_idx1) && bt_mesh_subnet_get(net_idx2);
+}
+
 int bt_mesh_brg_cfg_tbl_add(enum bt_mesh_brg_cfg_dir direction, uint16_t net_idx1,
-			    uint16_t net_idx2, uint16_t addr1, uint16_t addr2)
+			    uint16_t net_idx2, uint16_t addr1, uint16_t addr2, uint8_t *status)
 {
 	/* Sanity checks */
-	if (!BT_MESH_ADDR_IS_UNICAST(addr1) || net_idx1 == net_idx2 || addr1 == addr2 ||
-	    net_idx1 > BT_MESH_BRG_CFG_KEY_INDEX_MAX || net_idx2 > BT_MESH_BRG_CFG_KEY_INDEX_MAX) {
+	if (!BT_MESH_ADDR_IS_UNICAST(addr1) || net_idx1 == net_idx2 ||
+	    addr1 == addr2 || net_idx1 > BT_MESH_BRG_CFG_KEY_INDEX_MAX ||
+	    net_idx2 > BT_MESH_BRG_CFG_KEY_INDEX_MAX) {
 		return -EINVAL;
 	}
 
-	if (direction != BT_MESH_BRG_CFG_DIR_ONEWAY && direction != BT_MESH_BRG_CFG_DIR_TWOWAY) {
+	if (direction != BT_MESH_BRG_CFG_DIR_ONEWAY &&
+	    direction != BT_MESH_BRG_CFG_DIR_TWOWAY) {
 		return -EINVAL;
 	}
 
 	if ((direction == BT_MESH_BRG_CFG_DIR_ONEWAY &&
-		(addr2 == BT_MESH_ADDR_UNASSIGNED || addr2 == BT_MESH_ADDR_ALL_NODES)) ||
+	     (addr2 == BT_MESH_ADDR_UNASSIGNED || addr2 == BT_MESH_ADDR_ALL_NODES)) ||
 	    (direction == BT_MESH_BRG_CFG_DIR_TWOWAY &&
-		!BT_MESH_ADDR_IS_UNICAST(addr2))) {
+	     !BT_MESH_ADDR_IS_UNICAST(addr2))) {
 		return -EINVAL;
 	}
 
+	if (!netkey_check(net_idx1, net_idx2)) {
+		*status = STATUS_INVALID_NETKEY;
+		return 0;
+	}
+
 	/* Check if entry already exists, if yes, then, update the direction field and it is a
 	 * success.
 	 * "If a Bridging Table state entry corresponding to the received message exists, the
@@ -256,7 +269,8 @@
 
 	/* Empty element, is the current table row counter */
 	if (bt_mesh_brg_cfg_row_cnt == CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
-		return -ENOMEM;
+		*status = STATUS_INSUFF_RESOURCES;
+		return 0;
 	}
 
 	/* Update the row */
@@ -273,6 +287,7 @@
 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
 	}
 
+	*status = STATUS_SUCCESS;
 	return 0;
 }
 
@@ -294,12 +309,13 @@
 }
 
 int bt_mesh_brg_cfg_tbl_remove(uint16_t net_idx1, uint16_t net_idx2, uint16_t addr1,
-				uint16_t addr2)
+			       uint16_t addr2, uint8_t *status)
 {
 	bool store = false;
 
 	/* Sanity checks */
 	if ((!BT_MESH_ADDR_IS_UNICAST(addr1) && addr1 != BT_MESH_ADDR_UNASSIGNED) ||
+	    (BT_MESH_ADDR_IS_UNICAST(addr1) && addr1 == addr2) ||
 	    addr2 == BT_MESH_ADDR_ALL_NODES) {
 		return -EINVAL;
 	}
@@ -309,11 +325,16 @@
 		return -EINVAL;
 	}
 
+	if (!netkey_check(net_idx1, net_idx2)) {
+		*status = STATUS_INVALID_NETKEY;
+		return 0;
+	}
 
 	/* Iterate over items and set matching row to 0, if nothing exist, or nothing matches, then
 	 * it is success (similar to add)
 	 */
 	if (bt_mesh_brg_cfg_row_cnt == 0) {
+		*status = STATUS_SUCCESS;
 		return 0;
 	}
 
@@ -341,5 +362,6 @@
 		bt_mesh_settings_store_schedule(BT_MESH_SETTINGS_BRG_PENDING);
 	}
 
+	*status = STATUS_SUCCESS;
 	return 0;
 }
diff --git a/subsys/bluetooth/mesh/brg_cfg.h b/subsys/bluetooth/mesh/brg_cfg.h
index 033572e..95455c4 100644
--- a/subsys/bluetooth/mesh/brg_cfg.h
+++ b/subsys/bluetooth/mesh/brg_cfg.h
@@ -51,10 +51,10 @@
 int bt_mesh_brg_cfg_tbl_get(const struct bt_mesh_brg_cfg_row **rows);
 
 int bt_mesh_brg_cfg_tbl_add(enum bt_mesh_brg_cfg_dir direction, uint16_t net_idx1,
-			    uint16_t net_idx2, uint16_t addr1, uint16_t addr2);
+			    uint16_t net_idx2, uint16_t addr1, uint16_t addr2, uint8_t *status);
 
 int bt_mesh_brg_cfg_tbl_remove(uint16_t net_idx1, uint16_t net_idx2, uint16_t addr1,
-				uint16_t addr2);
+			       uint16_t addr2, uint8_t *status);
 
 typedef void (*bt_mesh_brg_cfg_cb_t)(uint16_t new_netidx, void *user_data);
 
diff --git a/subsys/bluetooth/mesh/brg_cfg_srv.c b/subsys/bluetooth/mesh/brg_cfg_srv.c
index adfe5de..581dd98 100644
--- a/subsys/bluetooth/mesh/brg_cfg_srv.c
+++ b/subsys/bluetooth/mesh/brg_cfg_srv.c
@@ -78,28 +78,19 @@
 {
 	struct bt_mesh_bridging_table_entry entry;
 	uint8_t status = STATUS_SUCCESS;
+	int err;
 
 	entry.directions = net_buf_simple_pull_u8(buf);
 	key_idx_unpack_pair(buf, &entry.net_idx1, &entry.net_idx2);
 	entry.addr1 = net_buf_simple_pull_le16(buf);
 	entry.addr2 = net_buf_simple_pull_le16(buf);
 
-	if (!netkey_check(entry.net_idx1, entry.net_idx2)) {
-		status = STATUS_INVALID_NETKEY;
-		goto add_respond;
-	}
-
-	int err = bt_mesh_brg_cfg_tbl_add(entry.directions, entry.net_idx1, entry.net_idx2,
-					  entry.addr1, entry.addr2);
-	if (err == -ENOMEM) {
-		status = STATUS_INSUFF_RESOURCES;
-	} else if (err) {
-		/* Per spec, do not respond if parameters values are invalid. */
+	err = bt_mesh_brg_cfg_tbl_add(entry.directions, entry.net_idx1, entry.net_idx2, entry.addr1,
+				      entry.addr2, &status);
+	if (err) {
 		return err;
 	}
 
-add_respond:
-
 	bridging_table_status_send(model, ctx, status, &entry);
 
 	return 0;
@@ -110,27 +101,19 @@
 {
 	struct bt_mesh_bridging_table_entry entry;
 	uint8_t status = STATUS_SUCCESS;
+	int err;
 
 	entry.directions = 0;
 	key_idx_unpack_pair(buf, &entry.net_idx1, &entry.net_idx2);
 	entry.addr1 = net_buf_simple_pull_le16(buf);
 	entry.addr2 = net_buf_simple_pull_le16(buf);
 
-	if (!netkey_check(entry.net_idx1, entry.net_idx2)) {
-		status = STATUS_INVALID_NETKEY;
-		goto rmv_respond;
-	}
-
-	int err = bt_mesh_brg_cfg_tbl_remove(entry.net_idx1, entry.net_idx2, entry.addr1,
-						entry.addr2);
-
-	/* Per spec, do not respond if parameters values are invalid. */
+	err = bt_mesh_brg_cfg_tbl_remove(entry.net_idx1, entry.net_idx2, entry.addr1, entry.addr2,
+					 &status);
 	if (err) {
 		return err;
 	}
 
-rmv_respond:
-
 	bridging_table_status_send(model, ctx, status, &entry);
 
 	return 0;
diff --git a/tests/bluetooth/mesh/brg/src/main.c b/tests/bluetooth/mesh/brg/src/main.c
index 68103c9..15d964f 100644
--- a/tests/bluetooth/mesh/brg/src/main.c
+++ b/tests/bluetooth/mesh/brg/src/main.c
@@ -11,6 +11,7 @@
 
 #include "settings.h"
 #include "brg_cfg.h"
+#include "foundation.h"
 
 #define TEST_VECT_SZ (CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX + 1)
 
@@ -36,7 +37,6 @@
 		test_vector[i].net_idx2 = (i/8) + 16;
 		test_vector[i].addr2 = ADDR2_BASE + i;
 	}
-
 }
 
 /**** Mocked functions ****/
@@ -60,10 +60,17 @@
 	return 0;
 }
 
+struct bt_mesh_subnet *bt_mesh_subnet_get(uint16_t net_idx)
+{
+	/* Return anything non-zero. */
+	return (struct bt_mesh_subnet *) 1;
+}
+
 /**** Mocked functions - end ****/
 
 static void check_fill_all_bt_entries(void)
 {
+	uint8_t status;
 	int err;
 
 	for (int i = 0; i < TEST_VECT_SZ; i++) {
@@ -74,18 +81,23 @@
 		}
 
 		err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
-			test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2);
+			test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2,
+			&status);
+
+		zassert_equal(err, 0);
 
 		if (i != CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
-			zassert_equal(err, 0);
+			zassert_equal(status, STATUS_SUCCESS);
 		} else {
-			zassert_equal(err, -ENOMEM);
+			zassert_equal(status, STATUS_INSUFF_RESOURCES);
 		}
 	}
 }
 
 static void check_delete_all_bt_entries(void)
 {
+	uint8_t status;
+
 	for (int i = 0; i < TEST_VECT_SZ; i++) {
 
 		if (i < CONFIG_BT_MESH_BRG_TABLE_ITEMS_MAX) {
@@ -95,9 +107,10 @@
 
 		int err = bt_mesh_brg_cfg_tbl_remove(test_vector[i].net_idx1,
 				test_vector[i].net_idx2, test_vector[i].addr1,
-				test_vector[i].addr2);
+				test_vector[i].addr2, &status);
 
 		zassert_equal(err, 0);
+		zassert_equal(status, STATUS_SUCCESS);
 	}
 }
 
@@ -132,6 +145,7 @@
 	check_bt_mesh_brg_cfg_tbl_reset();
 	check_fill_all_bt_entries();
 
+	uint8_t status;
 	int err;
 	uint16_t net_idx1 = test_vector[TEST_VECT_SZ - 1].net_idx1;
 	uint16_t net_idx2 = test_vector[TEST_VECT_SZ - 1].net_idx2;
@@ -140,27 +154,27 @@
 	/* Try removing entries with invalid params */
 	uint16_t addr2 = BT_MESH_ADDR_ALL_NODES;
 
-	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
+	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
 	zassert_equal(err, -EINVAL);
 
 	addr2 = BT_MESH_ADDR_UNASSIGNED;
 	addr1 = BT_MESH_ADDR_RELAYS;
-	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
+	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
 	zassert_equal(err, -EINVAL);
 
 	addr1 = BT_MESH_ADDR_UNASSIGNED;
 	net_idx1 = 4096;
-	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
+	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
 	zassert_equal(err, -EINVAL);
 
 	net_idx1 = test_vector[TEST_VECT_SZ - 1].net_idx1;
 	net_idx2 = 4096;
-	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
+	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
 	zassert_equal(err, -EINVAL);
 
 	/* Test remove entries matching netkey1, and netkey2 */
 	net_idx2 = test_vector[TEST_VECT_SZ - 1].net_idx2;
-	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2);
+	err = bt_mesh_brg_cfg_tbl_remove(net_idx1, net_idx2, addr1, addr2, &status);
 	zassert_equal(err, 0);
 
 	const struct bt_mesh_brg_cfg_row *brg_tbl;
@@ -255,6 +269,7 @@
 /* Test if pending store works correctly by adding one entry to the table. */
 ZTEST(bt_mesh_brg_cfg, test_brg_tbl_pending_store)
 {
+	uint8_t status;
 	int n, err;
 	struct bt_mesh_brg_cfg_row test_vec = {
 		.direction = BT_MESH_BRG_CFG_DIR_ONEWAY,
@@ -268,8 +283,9 @@
 	ztest_expect_value(bt_mesh_settings_store_schedule, flag,
 				BT_MESH_SETTINGS_BRG_PENDING);
 	err = bt_mesh_brg_cfg_tbl_add(test_vec.direction, test_vec.net_idx1,
-		test_vec.net_idx2, test_vec.addr1, test_vec.addr2);
+		test_vec.net_idx2, test_vec.addr1, test_vec.addr2, &status);
 	zassert_equal(err, 0);
+	zassert_equal(status, STATUS_SUCCESS);
 
 	const struct bt_mesh_brg_cfg_row *tbl;
 
@@ -285,6 +301,7 @@
 /* Test if invalid entries are not added to the table. */
 ZTEST(bt_mesh_brg_cfg, test_tbl_add_invalid_ip)
 {
+	uint8_t status;
 	int err;
 	/* Create test vector array of test_brg_cfg_row iteams with invalid values.
 	 * Each vector has only one invalid field value, rest all are valid values.
@@ -337,7 +354,8 @@
 	for (int i = 0; i < ARRAY_SIZE(inv_test_vector); i++) {
 		err = bt_mesh_brg_cfg_tbl_add(inv_test_vector[i].direction,
 					inv_test_vector[i].net_idx1, inv_test_vector[i].net_idx2,
-					inv_test_vector[i].addr1, inv_test_vector[i].addr2);
+					inv_test_vector[i].addr1, inv_test_vector[i].addr2,
+					&status);
 		zassert_equal(err, -EINVAL, "Test vector index: %zu", i);
 	}
 }
@@ -362,27 +380,32 @@
 
 static void check_fill_all_bt_entries_reversed(void)
 {
+	uint8_t status;
 	int err;
 
 	for (int i = TEST_VECT_SZ - 2; i >= 0 ; i--) {
 		ztest_expect_value(bt_mesh_settings_store_schedule, flag,
 				BT_MESH_SETTINGS_BRG_PENDING);
 		err = bt_mesh_brg_cfg_tbl_add(test_vector[i].direction, test_vector[i].net_idx1,
-			test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2);
+			test_vector[i].net_idx2, test_vector[i].addr1, test_vector[i].addr2,
+			&status);
 		zassert_equal(err, 0);
 	}
 
 	int last = TEST_VECT_SZ - 1;
 
 	err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
-	test_vector[last].net_idx2, test_vector[last].addr1, test_vector[last].addr2);
-	zassert_equal(err, -ENOMEM);
+				      test_vector[last].net_idx2, test_vector[last].addr1,
+				      test_vector[last].addr2, &status);
+	zassert_equal(err, 0);
+	zassert_equal(status, STATUS_INSUFF_RESOURCES);
 }
 
 static struct test_brg_cfg_row test_vector_copy[TEST_VECT_SZ - 1];
 
 static void check_fill_all_bt_entries_randomly(void)
 {
+	uint8_t status;
 	int err;
 	int copy_cnt = ARRAY_SIZE(test_vector_copy);
 
@@ -401,15 +424,18 @@
 				BT_MESH_SETTINGS_BRG_PENDING);
 		err = bt_mesh_brg_cfg_tbl_add(test_vector_copy[i].direction,
 			test_vector_copy[i].net_idx1, test_vector_copy[i].net_idx2,
-			test_vector_copy[i].addr1, test_vector_copy[i].addr2);
+			test_vector_copy[i].addr1, test_vector_copy[i].addr2, &status);
 		zassert_equal(err, 0);
+		zassert_equal(status, STATUS_SUCCESS);
 	}
 
 	int last = TEST_VECT_SZ - 1;
 
 	err = bt_mesh_brg_cfg_tbl_add(test_vector[last].direction, test_vector[last].net_idx1,
-		test_vector[last].net_idx2, test_vector[last].addr1, test_vector[last].addr2);
-	zassert_equal(err, -ENOMEM);
+		test_vector[last].net_idx2, test_vector[last].addr1, test_vector[last].addr2,
+		&status);
+	zassert_equal(err, 0);
+	zassert_equal(status, STATUS_INSUFF_RESOURCES);
 }
 
 static void subnet_relay_cb_check(uint16_t new_net_idx, void *user_data)