mgcp: Introduce a mgcp_trunk_config enum for endpoint configs

We want to support real trunks in the MGCP code and we need to
have some better book keeping for those. Move the code around.
diff --git a/openbsc/include/openbsc/mgcp.h b/openbsc/include/openbsc/mgcp.h
index 04643c5..df84979 100644
--- a/openbsc/include/openbsc/mgcp.h
+++ b/openbsc/include/openbsc/mgcp.h
@@ -1,8 +1,8 @@
 /* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -63,6 +63,7 @@
  */
 struct mgcp_endpoint;
 struct mgcp_config;
+struct mgcp_trunk_config;
 
 #define MGCP_ENDP_CRCX 1
 #define MGCP_ENDP_DLCX 2
@@ -78,9 +79,9 @@
 #define MGCP_POLICY_REJECT	5
 #define MGCP_POLICY_DEFER	6
 
-typedef int (*mgcp_realloc)(struct mgcp_config *cfg, int endpoint);
-typedef int (*mgcp_change)(struct mgcp_config *cfg, int endpoint, int state);
-typedef int (*mgcp_policy)(struct mgcp_config *cfg, int endpoint, int state, const char *transactio_id);
+typedef int (*mgcp_realloc)(struct mgcp_trunk_config *cfg, int endpoint);
+typedef int (*mgcp_change)(struct mgcp_trunk_config *cfg, int endpoint, int state);
+typedef int (*mgcp_policy)(struct mgcp_trunk_config *cfg, int endpoint, int state, const char *transactio_id);
 typedef int (*mgcp_reset)(struct mgcp_config *cfg);
 
 #define PORT_ALLOC_STATIC	0
@@ -101,18 +102,31 @@
 	int last_port;
 };
 
+struct mgcp_trunk_config {
+	struct mgcp_config *cfg;
+
+	int trunk_nr;
+	int trunk_type;
+
+	char *audio_name;
+	int audio_payload;
+	int audio_loop;
+
+	/* spec handling */
+	int force_realloc;
+
+	unsigned int number_endpoints;
+	struct mgcp_endpoint *endpoints;
+};
+
 struct mgcp_config {
 	int source_port;
 	char *local_ip;
 	char *source_addr;
-	unsigned int number_endpoints;
 	char *bts_ip;
 	char *call_agent_addr;
 
 	struct in_addr bts_in;
-	char *audio_name;
-	int audio_payload;
-	int audio_loop;
 
 	/* transcoder handling */
 	char *transcoder_ip;
@@ -126,17 +140,16 @@
 	struct mgcp_port_range transcoder_ports;
 	int endp_dscp;
 
-	/* spec handling */
-	int force_realloc;
-
 	mgcp_change change_cb;
 	mgcp_policy policy_cb;
 	mgcp_reset reset_cb;
 	mgcp_realloc realloc_cb;
 	void *data;
 
-	struct mgcp_endpoint *endpoints;
 	uint32_t last_call_id;
+
+	/* trunk handling */
+	struct mgcp_trunk_config trunk;
 };
 
 /* config management */
diff --git a/openbsc/include/openbsc/mgcp_internal.h b/openbsc/include/openbsc/mgcp_internal.h
index a1db9cb..cefbc3e 100644
--- a/openbsc/include/openbsc/mgcp_internal.h
+++ b/openbsc/include/openbsc/mgcp_internal.h
@@ -1,8 +1,8 @@
 /* MGCP Private Data */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -35,6 +35,11 @@
 	MGCP_CONN_LOOPBACK  = 4,
 };
 
+enum mgcp_trunk_type {
+	MGCP_TRUNK_VIRTUAL,
+	MGCP_TRUNK_E1,
+};
+
 struct mgcp_rtp_state {
 	int initialized;
 	int patch;
@@ -93,6 +98,7 @@
 
 	/* backpointer */
 	struct mgcp_config *cfg;
+	struct mgcp_trunk_config *tcfg;
 
 	/* port status for bts/net */
 	struct mgcp_rtp_end bts_end;
@@ -118,7 +124,7 @@
 	struct mgcp_rtp_tap taps[MGCP_TAP_COUNT];
 };
 
-#define ENDPOINT_NUMBER(endp) abs(endp - endp->cfg->endpoints)
+#define ENDPOINT_NUMBER(endp) abs(endp - endp->tcfg->endpoints)
 
 struct mgcp_msg_ptr {
 	unsigned int start;
diff --git a/openbsc/src/mgcp/mgcp_main.c b/openbsc/src/mgcp/mgcp_main.c
index 091d7bd..c8d9a62 100644
--- a/openbsc/src/mgcp/mgcp_main.c
+++ b/openbsc/src/mgcp/mgcp_main.c
@@ -126,7 +126,7 @@
 	return 0;
 }
 
-static int mgcp_change_cb(struct mgcp_config *cfg, int endpoint, int state)
+static int mgcp_change_cb(struct mgcp_trunk_config *cfg, int endpoint, int state)
 {
 	if (state != MGCP_ENDP_MDCX)
 		return 0;
@@ -172,8 +172,8 @@
 		reset_endpoints = 0;
 
 		/* is checking in_addr.s_addr == INADDR_LOOPBACK making it more secure? */
-		for (i = 1; i < cfg->number_endpoints; ++i)
-			mgcp_free_endp(&cfg->endpoints[i]);
+		for (i = 1; i < cfg->trunk.number_endpoints; ++i)
+			mgcp_free_endp(&cfg->trunk.endpoints[i]);
 	}
 
 	return 0;
diff --git a/openbsc/src/mgcp/mgcp_network.c b/openbsc/src/mgcp/mgcp_network.c
index e238d26..51c08d1 100644
--- a/openbsc/src/mgcp/mgcp_network.c
+++ b/openbsc/src/mgcp/mgcp_network.c
@@ -2,8 +2,8 @@
 /* The protocol implementation */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -196,9 +196,9 @@
 static int send_to(struct mgcp_endpoint *endp, int dest, int is_rtp,
 		   struct sockaddr_in *addr, char *buf, int rc)
 {
-	struct mgcp_config *cfg = endp->cfg;
+	struct mgcp_trunk_config *tcfg = endp->tcfg;
 	/* For loop toggle the destination and then dispatch. */
-	if (cfg->audio_loop)
+	if (tcfg->audio_loop)
 		dest = !dest;
 
 	/* Loop based on the conn_mode, maybe undoing the above */
diff --git a/openbsc/src/mgcp/mgcp_protocol.c b/openbsc/src/mgcp/mgcp_protocol.c
index 91c4d0c..aa028c3 100644
--- a/openbsc/src/mgcp/mgcp_protocol.c
+++ b/openbsc/src/mgcp/mgcp_protocol.c
@@ -105,8 +105,8 @@
 
 	/* callstack can only be of size number_of_endpoints */
 	/* verify that the call id is free, e.g. in case of overrun */
-	for (i = 1; i < cfg->number_endpoints; ++i)
-		if (cfg->endpoints[i].ci == cfg->last_call_id)
+	for (i = 1; i < cfg->trunk.number_endpoints; ++i)
+		if (cfg->trunk.endpoints[i].ci == cfg->last_call_id)
 			return generate_call_id(cfg);
 
 	return cfg->last_call_id;
@@ -187,7 +187,7 @@
 			"a=rtpmap:%d %s\r\n",
 			endp->ci, addr, endp->net_end.local_port,
 			endp->bts_end.payload_type, endp->bts_end.payload_type,
-		        endp->cfg->audio_name);
+		        endp->tcfg->audio_name);
 	return mgcp_create_response_with_data(200, " OK", msg, trans_id, sdp_record);
 }
 
@@ -290,12 +290,12 @@
 		return NULL;
 
 	mgcp_endp = mgcp_timeslot_to_endpoint(trunk - 1, endp);
-	if (mgcp_endp < 1 || mgcp_endp >= cfg->number_endpoints) {
+	if (mgcp_endp < 1 || mgcp_endp >= cfg->trunk.number_endpoints) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to find endpoint '%s'\n", mgcp);
 		return NULL;
 	}
 
-	return &cfg->endpoints[mgcp_endp];
+	return &cfg->trunk.endpoints[mgcp_endp];
 }
 
 static struct mgcp_endpoint *find_endpoint(struct mgcp_config *cfg, const char *mgcp)
@@ -307,8 +307,8 @@
 		return find_e1_endpoint(cfg, mgcp);
 	} else {
 		gw = strtoul(mgcp, &endptr, 16);
-		if (gw > 0 && gw < cfg->number_endpoints && strcmp(endptr, "@mgw") == 0)
-			return &cfg->endpoints[gw];
+		if (gw > 0 && gw < cfg->trunk.number_endpoints && strcmp(endptr, "@mgw") == 0)
+			return &cfg->trunk.endpoints[gw];
 	}
 
 	LOGP(DMGCP, LOGL_ERROR, "Not able to find endpoint: '%s'\n", mgcp);
@@ -494,6 +494,7 @@
 	struct mgcp_msg_ptr data_ptrs[6];
 	int found, i, line_start;
 	const char *trans_id;
+	struct mgcp_trunk_config *tcfg;
 	struct mgcp_endpoint *endp;
 	int error_code = 400;
 
@@ -501,13 +502,15 @@
 	if (found != 0)
 		return create_err_response(510, "CRCX", trans_id);
 
+	tcfg = endp->tcfg;
+
 	if (endp->allocated) {
-		if (cfg->force_realloc) {
+		if (tcfg->force_realloc) {
 			LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
 			    ENDPOINT_NUMBER(endp));
 			mgcp_free_endp(endp);
 			if (cfg->realloc_cb)
-				cfg->realloc_cb(cfg, ENDPOINT_NUMBER(endp));
+				cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp));
 		} else {
 			LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
 			     ENDPOINT_NUMBER(endp));
@@ -519,11 +522,11 @@
 	MSG_TOKENIZE_START
 	switch (msg->l3h[line_start]) {
 	case 'L':
-		endp->local_options = talloc_strdup(cfg->endpoints,
+		endp->local_options = talloc_strdup(tcfg->endpoints,
 			(const char *)&msg->l3h[line_start + 3]);
 		break;
 	case 'C':
-		endp->callid = talloc_strdup(cfg->endpoints,
+		endp->callid = talloc_strdup(tcfg->endpoints,
 			(const char *)&msg->l3h[line_start + 3]);
 		break;
 	case 'M':
@@ -559,11 +562,11 @@
 		goto error2;
 
 	endp->allocated = 1;
-	endp->bts_end.payload_type = cfg->audio_payload;
+	endp->bts_end.payload_type = tcfg->audio_payload;
 
 	/* policy CB */
 	if (cfg->policy_cb) {
-		switch (cfg->policy_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX, trans_id)) {
+		switch (cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX, trans_id)) {
 		case MGCP_POLICY_REJECT:
 			LOGP(DMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n",
 			     ENDPOINT_NUMBER(endp));
@@ -585,7 +588,7 @@
 		ENDPOINT_NUMBER(endp), endp->ci,
 		endp->net_end.local_port, endp->bts_end.local_port);
 	if (cfg->change_cb)
-		cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);
+		cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);
 
 	create_transcoder(endp);
 	return create_response_with_sdp(endp, "CRCX", trans_id);
@@ -686,7 +689,7 @@
 
 	/* policy CB */
 	if (cfg->policy_cb) {
-		switch (cfg->policy_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, trans_id)) {
+		switch (cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, trans_id)) {
 		case MGCP_POLICY_REJECT:
 			LOGP(DMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n",
 			     ENDPOINT_NUMBER(endp));
@@ -708,7 +711,7 @@
 	LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n",
 		ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
 	if (cfg->change_cb)
-		cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX);
+		cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX);
 	if (silent)
 		goto out_silent;
 
@@ -771,7 +774,7 @@
 
 	/* policy CB */
 	if (cfg->policy_cb) {
-		switch (cfg->policy_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, trans_id)) {
+		switch (cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, trans_id)) {
 		case MGCP_POLICY_REJECT:
 			LOGP(DMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n",
 			     ENDPOINT_NUMBER(endp));
@@ -797,7 +800,7 @@
 	delete_transcoder(endp);
 	mgcp_free_endp(endp);
 	if (cfg->change_cb)
-		cfg->change_cb(cfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX);
+		cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX);
 
 	if (silent)
 		goto out_silent;
@@ -858,13 +861,19 @@
 
 	cfg->source_port = 2427;
 	cfg->source_addr = talloc_strdup(cfg, "0.0.0.0");
-	cfg->audio_name = talloc_strdup(cfg, "AMR/8000");
-	cfg->audio_payload = 126;
+
 	cfg->transcoder_remote_base = 4000;
 
 	cfg->bts_ports.base_port = RTP_PORT_DEFAULT;
 	cfg->net_ports.base_port = RTP_PORT_NET_DEFAULT;
 
+	/* default trunk handling */
+	cfg->trunk.cfg = cfg;
+	cfg->trunk.trunk_nr = 0;
+	cfg->trunk.trunk_type = MGCP_TRUNK_VIRTUAL;
+	cfg->trunk.audio_name = talloc_strdup(cfg, "AMR/8000");
+	cfg->trunk.audio_payload = 126;
+
 	return cfg;
 }
 
@@ -891,22 +900,26 @@
 
 int mgcp_endpoints_allocate(struct mgcp_config *cfg)
 {
+	struct mgcp_trunk_config *tcfg;
 	int i;
 
+	tcfg = &cfg->trunk;
+
 	/* Initialize all endpoints */
-	cfg->endpoints = _talloc_zero_array(cfg,
+	tcfg->endpoints = _talloc_zero_array(cfg,
 				       sizeof(struct mgcp_endpoint),
-				       cfg->number_endpoints, "endpoints");
-	if (!cfg->endpoints)
+				       tcfg->number_endpoints, "endpoints");
+	if (!tcfg->endpoints)
 		return -1;
 
-	for (i = 0; i < cfg->number_endpoints; ++i) {
-		cfg->endpoints[i].ci = CI_UNUSED;
-		cfg->endpoints[i].cfg = cfg;
-		mgcp_rtp_end_init(&cfg->endpoints[i].net_end);
-		mgcp_rtp_end_init(&cfg->endpoints[i].bts_end);
-		mgcp_rtp_end_init(&cfg->endpoints[i].trans_net);
-		mgcp_rtp_end_init(&cfg->endpoints[i].trans_bts);
+	for (i = 0; i < tcfg->number_endpoints; ++i) {
+		tcfg->endpoints[i].ci = CI_UNUSED;
+		tcfg->endpoints[i].cfg = cfg;
+		tcfg->endpoints[i].tcfg = tcfg;
+		mgcp_rtp_end_init(&tcfg->endpoints[i].net_end);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].bts_end);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_net);
+		mgcp_rtp_end_init(&tcfg->endpoints[i].trans_bts);
 	}
 
 	return 0;
@@ -971,8 +984,8 @@
 			"m=audio %d RTP/AVP %d\r\n"
 			"a=rtpmap:%d %s\r\n",
 			msg, endpoint, mode, endp->cfg->source_addr,
-			port, endp->cfg->audio_payload,
-			endp->cfg->audio_payload, endp->cfg->audio_name);
+			port, endp->tcfg->audio_payload,
+			endp->tcfg->audio_payload, endp->tcfg->audio_name);
 
 	if (len < 0)
 		return;
diff --git a/openbsc/src/mgcp/mgcp_vty.c b/openbsc/src/mgcp/mgcp_vty.c
index b6301d8..bf8b7d4 100644
--- a/openbsc/src/mgcp/mgcp_vty.c
+++ b/openbsc/src/mgcp/mgcp_vty.c
@@ -2,8 +2,8 @@
 /* The protocol implementation */
 
 /*
- * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
- * (C) 2009-2010 by On-Waves
+ * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2011 by On-Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -69,12 +69,14 @@
 			g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
 
 	vty_out(vty, "  rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
-	if (g_cfg->audio_payload != -1)
-		vty_out(vty, "  sdp audio payload number %d%s", g_cfg->audio_payload, VTY_NEWLINE);
-	if (g_cfg->audio_name)
-		vty_out(vty, "  sdp audio payload name %s%s", g_cfg->audio_name, VTY_NEWLINE);
-	vty_out(vty, "  loop %u%s", !!g_cfg->audio_loop, VTY_NEWLINE);
-	vty_out(vty, "  number endpoints %u%s", g_cfg->number_endpoints - 1, VTY_NEWLINE);
+	if (g_cfg->trunk.audio_payload != -1)
+		vty_out(vty, "  sdp audio payload number %d%s",
+			g_cfg->trunk.audio_payload, VTY_NEWLINE);
+	if (g_cfg->trunk.audio_name)
+		vty_out(vty, "  sdp audio payload name %s%s",
+			g_cfg->trunk.audio_name, VTY_NEWLINE);
+	vty_out(vty, "  loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
+	vty_out(vty, "  number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
 	if (g_cfg->call_agent_addr)
 		vty_out(vty, "  call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
 	if (g_cfg->transcoder_ip)
@@ -95,9 +97,10 @@
 {
 	int i;
 
-	vty_out(vty, "MGCP is up and running with %u endpoints:%s", g_cfg->number_endpoints - 1, VTY_NEWLINE);
-	for (i = 1; i < g_cfg->number_endpoints; ++i) {
-		struct mgcp_endpoint *endp = &g_cfg->endpoints[i];
+	vty_out(vty, "MGCP is up and running with %u endpoints:%s",
+		g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
+	for (i = 1; i < g_cfg->trunk.number_endpoints; ++i) {
+		struct mgcp_endpoint *endp = &g_cfg->trunk.endpoints[i];
 		vty_out(vty, " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s traffic received bts: %u/%u  remote: %u/%u transcoder: %u/%u%s",
 			i, endp->ci,
 			ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
@@ -265,7 +268,7 @@
       "Set the audio codec to use")
 {
 	unsigned int payload = atoi(argv[0]);
-	g_cfg->audio_payload = payload;
+	g_cfg->trunk.audio_payload = payload;
 	return CMD_SUCCESS;
 }
 
@@ -274,7 +277,7 @@
       "sdp audio payload name NAME",
       "Set the audio name to use")
 {
-	bsc_replace_string(g_cfg, &g_cfg->audio_name, argv[0]);
+	bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
 	return CMD_SUCCESS;
 }
 
@@ -283,7 +286,7 @@
       "loop (0|1)",
       "Loop the audio")
 {
-	g_cfg->audio_loop = atoi(argv[0]);
+	g_cfg->trunk.audio_loop = atoi(argv[0]);
 	return CMD_SUCCESS;
 }
 
@@ -293,7 +296,7 @@
       "The number of endpoints to allocate. This is not dynamic.")
 {
 	/* + 1 as we start counting at one */
-	g_cfg->number_endpoints = atoi(argv[0]) + 1;
+	g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
 	return CMD_SUCCESS;
 }
 
@@ -351,14 +354,14 @@
 	struct mgcp_endpoint *endp;
 
 	int endp_no = strtoul(argv[0], NULL, 16);
-	if (endp_no < 1 || endp_no >= g_cfg->number_endpoints) {
+	if (endp_no < 1 || endp_no >= g_cfg->trunk.number_endpoints) {
 		vty_out(vty, "Loopback number %s/%d is invalid.%s",
 		argv[0], endp_no, VTY_NEWLINE);
 		return CMD_WARNING;
 	}
 
 
-	endp = &g_cfg->endpoints[endp_no];
+	endp = &g_cfg->trunk.endpoints[endp_no];
 	int loop = atoi(argv[1]);
 
 	if (loop)
@@ -386,13 +389,13 @@
 	int port = 0;
 
 	int endp_no = strtoul(argv[0], NULL, 16);
-	if (endp_no < 1 || endp_no >= g_cfg->number_endpoints) {
+	if (endp_no < 1 || endp_no >= g_cfg->trunk.number_endpoints) {
 		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
 		argv[0], endp_no, VTY_NEWLINE);
 		return CMD_WARNING;
 	}
 
-	endp = &g_cfg->endpoints[endp_no];
+	endp = &g_cfg->trunk.endpoints[endp_no];
 
 	if (strcmp(argv[1], "bts-in") == 0) {
 		port = MGCP_TAP_BTS_IN;
@@ -422,13 +425,13 @@
 	struct mgcp_endpoint *endp;
 
 	int endp_no = strtoul(argv[0], NULL, 16);
-	if (endp_no < 1 || endp_no >= g_cfg->number_endpoints) {
+	if (endp_no < 1 || endp_no >= g_cfg->trunk.number_endpoints) {
 		vty_out(vty, "Endpoint number %s/%d is invalid.%s",
 		argv[0], endp_no, VTY_NEWLINE);
 		return CMD_WARNING;
 	}
 
-	endp = &g_cfg->endpoints[endp_no];
+	endp = &g_cfg->trunk.endpoints[endp_no];
 	mgcp_free_endp(endp);
 	return CMD_SUCCESS;
 }
@@ -492,13 +495,14 @@
 	}
 
 	if (mgcp_endpoints_allocate(g_cfg) != 0) {
-		fprintf(stderr, "Failed to allocate endpoints: %d. Quitting.\n", g_cfg->number_endpoints);
+		fprintf(stderr, "Failed to allocate endpoints: %d. Quitting.\n",
+		g_cfg->trunk.number_endpoints);
 		return -1;
 	}
 
 	/* early bind */
-	for (i = 1; i < g_cfg->number_endpoints; ++i) {
-		struct mgcp_endpoint *endp = &g_cfg->endpoints[i];
+	for (i = 1; i < g_cfg->trunk.number_endpoints; ++i) {
+		struct mgcp_endpoint *endp = &g_cfg->trunk.endpoints[i];
 		int rtp_port;
 
 		if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
diff --git a/openbsc/src/nat/bsc_mgcp_utils.c b/openbsc/src/nat/bsc_mgcp_utils.c
index 3637349..9eac00b 100644
--- a/openbsc/src/nat/bsc_mgcp_utils.c
+++ b/openbsc/src/nat/bsc_mgcp_utils.c
@@ -156,7 +156,7 @@
 
 	endp = mgcp_timeslot_to_endpoint(multiplex, timeslot);
 
-	if (endp >= con->bsc->nat->mgcp_cfg->number_endpoints) {
+	if (endp >= con->bsc->nat->mgcp_cfg->trunk.number_endpoints) {
 		LOGP(DNAT, LOGL_ERROR,
 			"MSC attempted to assign bad endpoint 0x%x\n",
 			endp);
@@ -207,9 +207,9 @@
 {
 	int i;
 
-	for (i = 1; i < nat->mgcp_cfg->number_endpoints; ++i){
+	for (i = 1; i < nat->mgcp_cfg->trunk.number_endpoints; ++i){
 		bsc_mgcp_free_endpoint(nat, i);
-		mgcp_free_endp(&nat->mgcp_cfg->endpoints[i]);
+		mgcp_free_endp(&nat->mgcp_cfg->trunk.endpoints[i]);
 	}
 }
 
@@ -294,7 +294,7 @@
 	return NULL;
 }
 
-int bsc_mgcp_policy_cb(struct mgcp_config *cfg, int endpoint, int state, const char *transaction_id)
+int bsc_mgcp_policy_cb(struct mgcp_trunk_config *tcfg, int endpoint, int state, const char *transaction_id)
 {
 	struct bsc_nat *nat;
 	struct bsc_endpoint *bsc_endp;
@@ -302,9 +302,9 @@
 	struct mgcp_endpoint *mgcp_endp;
 	struct msgb *bsc_msg;
 
-	nat = cfg->data;
+	nat = tcfg->cfg->data;
 	bsc_endp = &nat->bsc_endpoints[endpoint];
-	mgcp_endp = &nat->mgcp_cfg->endpoints[endpoint];
+	mgcp_endp = &nat->mgcp_cfg->trunk.endpoints[endpoint];
 
 	if (bsc_endp->transaction_id) {
 		LOGP(DMGCP, LOGL_ERROR, "Endpoint 0x%x had pending transaction: '%s'\n",
@@ -434,7 +434,7 @@
 		return;
 	}
 
-	for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
+	for (i = 1; i < bsc->nat->mgcp_cfg->trunk.number_endpoints; ++i) {
 		if (bsc->nat->bsc_endpoints[i].bsc != bsc)
 			continue;
 		/* no one listening? a bug? */
@@ -443,7 +443,7 @@
 		if (strcmp(transaction_id, bsc->nat->bsc_endpoints[i].transaction_id) != 0)
 			continue;
 
-		endp = &bsc->nat->mgcp_cfg->endpoints[i];
+		endp = &bsc->nat->mgcp_cfg->trunk.endpoints[i];
 		bsc_endp = &bsc->nat->bsc_endpoints[i];
 		break;
 	}
@@ -713,7 +713,7 @@
 	/* some more MGCP config handling */
 	cfg->data = nat;
 	cfg->policy_cb = bsc_mgcp_policy_cb;
-	cfg->force_realloc = 1;
+	cfg->trunk.force_realloc = 1;
 
 	if (cfg->bts_ip)
 		talloc_free(cfg->bts_ip);
@@ -721,7 +721,7 @@
 
 	nat->bsc_endpoints = talloc_zero_array(nat,
 					       struct bsc_endpoint,
-					       cfg->number_endpoints + 1);
+					       cfg->trunk.number_endpoints + 1);
 	if (!nat->bsc_endpoints) {
 		LOGP(DMGCP, LOGL_ERROR, "Failed to allocate nat endpoints\n");
 		close(cfg->gw_fd.bfd.fd);
@@ -749,7 +749,7 @@
 	if (bsc->cfg)
 		ctr = &bsc->cfg->stats.ctrg->ctr[BCFG_CTR_DROPPED_CALLS];
 
-	for (i = 1; i < bsc->nat->mgcp_cfg->number_endpoints; ++i) {
+	for (i = 1; i < bsc->nat->mgcp_cfg->trunk.number_endpoints; ++i) {
 		struct bsc_endpoint *bsc_endp = &bsc->nat->bsc_endpoints[i];
 
 		if (bsc_endp->bsc != bsc)
@@ -759,6 +759,6 @@
 			rate_ctr_inc(ctr);
 
 		bsc_mgcp_free_endpoint(bsc->nat, i);
-		mgcp_free_endp(&bsc->nat->mgcp_cfg->endpoints[i]);
+		mgcp_free_endp(&bsc->nat->mgcp_cfg->trunk.endpoints[i]);
 	}
 }
diff --git a/openbsc/tests/bsc-nat/bsc_nat_test.c b/openbsc/tests/bsc-nat/bsc_nat_test.c
index 3e943cf..504b691 100644
--- a/openbsc/tests/bsc-nat/bsc_nat_test.c
+++ b/openbsc/tests/bsc-nat/bsc_nat_test.c
@@ -446,7 +446,7 @@
 					       struct bsc_endpoint,
 					       65);
 	nat->mgcp_cfg = mgcp_config_alloc();
-	nat->mgcp_cfg->number_endpoints = 64;
+	nat->mgcp_cfg->trunk.number_endpoints = 64;
 
 	bsc = bsc_connection_alloc(nat);
 	bsc->cfg = bsc_config_alloc(nat, "foo");
@@ -491,7 +491,7 @@
 					       struct bsc_endpoint,
 					       33);
 	nat->mgcp_cfg = mgcp_config_alloc();
-	nat->mgcp_cfg->number_endpoints = 64;
+	nat->mgcp_cfg->trunk.number_endpoints = 64;
 
 	bsc = bsc_connection_alloc(nat);
 	bsc->cfg = bsc_config_alloc(nat, "foo");
diff --git a/openbsc/tests/mgcp/mgcp_test.c b/openbsc/tests/mgcp/mgcp_test.c
index c039365..c63a786 100644
--- a/openbsc/tests/mgcp/mgcp_test.c
+++ b/openbsc/tests/mgcp/mgcp_test.c
@@ -47,7 +47,7 @@
 	struct msgb *inp;
 	struct msgb *msg;
 	struct mgcp_config *cfg = mgcp_config_alloc();
-	cfg->number_endpoints = 64;
+	cfg->trunk.number_endpoints = 64;
 	mgcp_endpoints_allocate(cfg);
 
 	inp = create_auep1();