nat: Allocate the endpoint status dynamically

Allocate the status for an endpoint dynamically. We will support
BSCs with different amount of multiplexes and need to have this
flexibility in the future. Add the proper null checks to the
current users of this code.
diff --git a/openbsc/include/openbsc/bsc_nat.h b/openbsc/include/openbsc/bsc_nat.h
index 62db17a..13d1b09 100644
--- a/openbsc/include/openbsc/bsc_nat.h
+++ b/openbsc/include/openbsc/bsc_nat.h
@@ -78,7 +78,7 @@
 	struct timer_list pong_timeout;
 
 	/* mgcp related code */
-	int endpoint_status[32];
+	char *_endpoint_status;
 	int last_endpoint;
 
 	/* a back pointer */
@@ -124,6 +124,9 @@
 
 	int forbid_paging;
 
+	/* audio handling */
+	int number_multiplexes;
+
 	/* backpointer */
 	struct bsc_nat *nat;
 
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index aacfce6..d814f0d 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -38,18 +38,33 @@
 #include <errno.h>
 #include <unistd.h>
 
+static int bsc_init_endps_if_needed(struct bsc_connection *con)
+{
+	/* we have done that */
+	if (con->_endpoint_status)
+		return 0;
+
+	/* we have no config... */
+	if (!con->cfg)
+		return -1;
+
+	con->_endpoint_status = talloc_zero_array(con, char,
+						  (32 * con->cfg->number_multiplexes) + 1);
+	return con->_endpoint_status == NULL;
+}
+
 static int bsc_assign_endpoint(struct bsc_connection *bsc, struct sccp_connections *con)
 {
-	const int number_endpoints = ARRAY_SIZE(bsc->endpoint_status);
+	const int number_endpoints = 31 * bsc->cfg->number_multiplexes;
 	int i;
 
-	for (i = 1; i < number_endpoints; ++i) {
+	for (i = 1; i <= number_endpoints; ++i) {
 		int endpoint = (bsc->last_endpoint + i) % number_endpoints;
 		if (endpoint == 0)
 			endpoint = 1;
 
-		if (bsc->endpoint_status[endpoint] == 0) {
-			bsc->endpoint_status[endpoint] = 1;
+		if (bsc->_endpoint_status[endpoint] == 0) {
+			bsc->_endpoint_status[endpoint] = 1;
 			con->bsc_endp = endpoint;
 			bsc->last_endpoint = endpoint;
 			return 0;
@@ -119,6 +134,8 @@
 	}
 
 	con->msc_endp = endp;
+	if (bsc_init_endps_if_needed(con->bsc) != 0)
+		return -1;
 	if (bsc_assign_endpoint(con->bsc, con) != 0)
 		return -1;
 
@@ -202,10 +219,10 @@
 void bsc_mgcp_dlcx(struct sccp_connections *con)
 {
 	/* send a DLCX down the stream */
-	if (con->bsc_endp != -1) {
-		if (con->bsc->endpoint_status[con->bsc_endp] != 1)
+	if (con->bsc_endp != -1 && con->bsc->_endpoint_status) {
+		if (con->bsc->_endpoint_status[con->bsc_endp] != 1)
 			LOGP(DNAT, LOGL_ERROR, "Endpoint 0x%x was not in use\n", con->bsc_endp);
-		con->bsc->endpoint_status[con->bsc_endp] = 0;
+		con->bsc->_endpoint_status[con->bsc_endp] = 0;
 		bsc_mgcp_send_dlcx(con->bsc, con->bsc_endp);
 		bsc_mgcp_free_endpoint(con->bsc->nat, con->msc_endp);
 	}
diff --git a/openbsc/src/nat/bsc_nat_utils.c b/openbsc/src/nat/bsc_nat_utils.c
index 7b75fa5..0470387 100644
--- a/openbsc/src/nat/bsc_nat_utils.c
+++ b/openbsc/src/nat/bsc_nat_utils.c
@@ -126,6 +126,7 @@
 	conf->token = talloc_strdup(conf, token);
 	conf->nr = nat->num_bsc;
 	conf->nat = nat;
+	conf->number_multiplexes = 1;
 
 	INIT_LLIST_HEAD(&conf->lac_list);
 
diff --git a/openbsc/src/nat/bsc_nat_vty.c b/openbsc/src/nat/bsc_nat_vty.c
index 532e790..01bee74 100644
--- a/openbsc/src/nat/bsc_nat_vty.c
+++ b/openbsc/src/nat/bsc_nat_vty.c
@@ -172,15 +172,21 @@
 	int i;
 
 	llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
+		int endpoints;
 		if (!con->cfg)
 			continue;
 		if (con->cfg->nr != nr)
 			continue;
 
+		/* this bsc has no audio endpoints yet */
+		if (!con->_endpoint_status)
+			continue;
+
 		vty_out(vty, "MGCP Status for %d%s", con->cfg->nr, VTY_NEWLINE);
-		for (i = 1; i < ARRAY_SIZE(con->endpoint_status); ++i)
+		endpoints = 31 * con->cfg->number_multiplexes;
+		for (i = 1; i <= endpoints; ++i)
 			vty_out(vty, " Endpoint 0x%x %s%s", i,
-				con->endpoint_status[i] == 0 ? "free" : "allocated",
+				con->_endpoint_status[i] == 0 ? "free" : "allocated",
 				VTY_NEWLINE);
 		break;
 	}
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index c5edbfe..d5b1ab1 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -479,7 +479,7 @@
 		fprintf(stderr, "Assigned timeslot should have been 1.\n");
 		abort();
 	}
-	if (con.bsc->endpoint_status[0x1b] != 1) {
+	if (con.bsc->_endpoint_status[0x1b] != 1) {
 		fprintf(stderr, "The status on the BSC is wrong.\n");
 		abort();
 	}
@@ -498,7 +498,7 @@
 
 	bsc_mgcp_dlcx(&con);
 	if (con.bsc_endp != -1 || con.msc_endp != -1 ||
-	    con.bsc->endpoint_status[1] != 0 || con.bsc->last_endpoint != 0x1b) {
+	    con.bsc->_endpoint_status[1] != 0 || con.bsc->last_endpoint != 0x1b) {
 		fprintf(stderr, "Clearing should remove the mapping.\n");
 		abort();
 	}