gb_proxy: Add ctrl interface and nsvc-state, gbproxy-state commands

This patch adds a control interface to osmo-gbproxy as well as the first
two commands to query the state of each NSVC and gbproxy peer.

The "nsvc-state" command replies with
nsei, nsvci, local state, role, remote state of all NSVCs.

The "gbproxy-state" command replies with
nsei, bvci, mcc, mnc, lac, rac, and state of each peer.

Entries are separated by a newline '\n' character. If there are no
entries an empty list is returned. This behaviour is similar to that of
the subscriber-list-active-v1 command in osmo-sgsn.

$ ./osmo_ctrl.py -d 127.0.0.1 -p 4263 -g nsvc-state
Got message: b'GET_REPLY 23 nsvc-state 101,101,DEAD,BLOCKED,SGSN,DEAD,UNBLOCKED\n'
$ ./osmo_ctrl.py -d 127.0.0.1 -p 4263 -g gbproxy-state
Got message: b'GET_REPLY 4871085901306801158 gbproxy-state '

Change-Id: I82c74fd0bfcb9ba4ec3619d9fdaa0cae201b3177
Ticket: OS#3281, SYS#4235
Sponsored-by: On-Waves ehf
diff --git a/src/gprs/gb_proxy_main.c b/src/gprs/gb_proxy_main.c
index 474aa52..97e6342 100644
--- a/src/gprs/gb_proxy_main.c
+++ b/src/gprs/gb_proxy_main.c
@@ -46,6 +46,10 @@
 #include <osmocom/sgsn/vty.h>
 #include <osmocom/sgsn/gb_proxy.h>
 
+#include <osmocom/ctrl/control_vty.h>
+#include <osmocom/ctrl/control_if.h>
+#include <osmocom/ctrl/ports.h>
+
 #include <osmocom/vty/command.h>
 #include <osmocom/vty/telnet_interface.h>
 #include <osmocom/vty/logging.h>
@@ -263,6 +267,7 @@
 int main(int argc, char **argv)
 {
 	int rc;
+	struct ctrl_handle *ctrl;
 
 	tall_bsc_ctx = talloc_named_const(NULL, 0, "nsip_proxy");
 	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
@@ -334,6 +339,19 @@
 	if (rc < 0)
 		exit(1);
 
+	/* Start control interface after getting config for
+	 * ctrl_vty_get_bind_addr() */
+	ctrl = ctrl_interface_setup_dynip(gbcfg, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_GBPROXY, NULL);
+	if (!ctrl) {
+		LOGP(DGPRS, LOGL_FATAL, "Failed to create CTRL interface.\n");
+		exit(1);
+	}
+
+	if (gb_ctrl_cmds_install() != 0) {
+		LOGP(DGPRS, LOGL_FATAL, "Failed to install CTRL commands.\n");
+		exit(1);
+	}
+
 	if (!gprs_nsvc_by_nsei(gbcfg->nsi, gbcfg->nsip_sgsn_nsei)) {
 		LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
 			"without creating that NSEI before\n",