NAT: reload BSCs config dynamically

Add vty tests for BSC configuration reloading.
Load BSCs configuration on bscs-config-file command:
* remove all runtime configured BSC not in the config file
* close connections to all BSC with updated token value

Fixes: OS#1670
Sponsored-by: On-Waves ehf
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
index b7b49e6..55f3dbf 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat_vty.c
@@ -39,6 +39,7 @@
 #include <osmocom/sccp/sccp.h>
 
 #include <stdlib.h>
+#include <stdbool.h>
 
 static struct bsc_nat *_nat;
 
@@ -513,6 +514,8 @@
 {
 	char *path;
 	int rc;
+	struct bsc_config *cf1, *cf2;
+	struct bsc_connection *con1, *con2;
 
 	if ('/' == argv[0][0])
 		bsc_replace_string(_nat, &_nat->resolved_path, argv[0]);
@@ -523,13 +526,32 @@
 		talloc_free(path);
 	}
 
+	llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
+		cf1->remove = true;
+		cf1->token_updated = false;
+	}
+
 	rc = vty_read_config_file(_nat->resolved_path, NULL);
 	if (rc < 0) {
 		vty_out(vty, "Failed to parse the config file %s: %s%s",
 			_nat->resolved_path, strerror(-rc), VTY_NEWLINE);
 		return CMD_WARNING;
 	}
+
 	bsc_replace_string(_nat, &_nat->include_file, argv[0]);
+
+	llist_for_each_entry_safe(con1, con2, &_nat->bsc_connections,
+				  list_entry) {
+		if (con1->cfg)
+			if (con1->cfg->token_updated || con1->cfg->remove)
+				bsc_close_connection(con1);
+	}
+
+	llist_for_each_entry_safe(cf1, cf2, &_nat->bsc_configs, entry) {
+		if (cf1->remove)
+			bsc_config_free(cf1);
+	}
+
 	return CMD_SUCCESS;
 }
 
@@ -846,6 +868,7 @@
 	if (!bsc)
 		return CMD_WARNING;
 
+	bsc->remove = false;
 	vty->index = bsc;
 	vty->node = NAT_BSC_NODE;
 
@@ -858,6 +881,12 @@
 {
 	struct bsc_config *conf = vty->index;
 
+	if (strncmp(conf->token, argv[0], 128) != 0) {
+		vty_out(vty, "updated token: %s -> %s%s", conf->token, argv[0],
+			VTY_NEWLINE);
+		conf->token_updated = true;
+	}
+
 	bsc_replace_string(conf, &conf->token, argv[0]);
 	return CMD_SUCCESS;
 }