Change in openbsc[master]: Remove ipaccess utils

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Max gerrit-no-reply at lists.osmocom.org
Sun Nov 25 18:27:19 UTC 2018


Max has uploaded this change for review. ( https://gerrit.osmocom.org/11921


Change subject: Remove ipaccess utils
......................................................................

Remove ipaccess utils

There's increasing gap in functionality between ipaccess utils from this
repo and from osmo-bsc due to ongoing development in new repository. To
avoid potential user confusion let's drop them similar to the way SGSN
was removed earlier.

Change-Id: I9c04f9b469e60802461a2a6e421d3ba27e6dafa1
---
M debian/control
D debian/osmocom-ipaccess-utils.install
M debian/rules
M openbsc/README
M openbsc/configure.ac
M openbsc/src/Makefile.am
D openbsc/src/ipaccess/Makefile.am
D openbsc/src/ipaccess/abisip-find.c
D openbsc/src/ipaccess/ipaccess-config.c
D openbsc/src/ipaccess/ipaccess-firmware.c
D openbsc/src/ipaccess/ipaccess-proxy.c
D openbsc/src/ipaccess/network_listen.c
12 files changed, 0 insertions(+), 2,935 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/21/11921/1

diff --git a/debian/control b/debian/control
index 0e9bb0c..a841acf 100644
--- a/debian/control
+++ b/debian/control
@@ -42,15 +42,6 @@
  components bundled together. When using osmocom-nitb, there is no need for a
  Mobile Switching Center (MSC) which is needed when using osmocom-bsc-sccplite.
 
-Package: osmocom-ipaccess-utils
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends}
-Description: Command line utilities for ip.access nanoBTS
- This package contains utilities that are specific for nanoBTS when being used
- together with OpenBSC. It contains mainly three tools: ipaccess-find,
- ipaccess-config and ipaccess-proxy.
-
 Package: osmocom-bs11-utils
 Architecture: any
 Depends: ${shlibs:Depends},
diff --git a/debian/osmocom-ipaccess-utils.install b/debian/osmocom-ipaccess-utils.install
deleted file mode 100644
index de13c18..0000000
--- a/debian/osmocom-ipaccess-utils.install
+++ /dev/null
@@ -1,3 +0,0 @@
-/usr/bin/ipaccess-config
-/usr/bin/abisip-find
-/usr/bin/ipaccess-proxy
diff --git a/debian/rules b/debian/rules
index dc609f9..0ea9b23 100755
--- a/debian/rules
+++ b/debian/rules
@@ -19,7 +19,6 @@
 override_dh_strip:
 	dh_strip -posmocom-bsc-sccplite --dbg-package=osmocom-bsc-sccplite-dbg
 	dh_strip -posmocom-nitb --dbg-package=osmocom-nitb-dbg
-	dh_strip -posmocom-ipaccess-utils --dbg-package=osmocom-ipaccess-utils-dbg
 	dh_strip -posmocom-bs11-utils --dbg-package=osmocom-bs11-utils-dbg
 	dh_strip -posmocom-bsc-nat --dbg-package=osmocom-bsc-nat-dbg
 
diff --git a/openbsc/README b/openbsc/README
index d01b2cf..bffdd81 100644
--- a/openbsc/README
+++ b/openbsc/README
@@ -14,7 +14,6 @@
  * Osmo-GbProxy - a Proxy to aggregate many Gb links as one Gb link to the SGSN
  * OsmoBSCNAT - a gateway aggregating many A links as one A link to the MSC
  * OsmoGTPHUB - a hub aggregating many GTP links (between SGSN and GGSN)
- * ipaccess-utils - some tools to discover + configure ip.access nanoBTS
  * bs11_config - a tool to configure the Siemens BS-11 microBTS
 
 Various interfaces towards the BTS are supported, among which are:
diff --git a/openbsc/configure.ac b/openbsc/configure.ac
index 75dd5d3..64285e0 100644
--- a/openbsc/configure.ac
+++ b/openbsc/configure.ac
@@ -259,7 +259,6 @@
     src/osmo-bsc/Makefile
     src/osmo-bsc_nat/Makefile
     src/osmo-bsc_mgcp/Makefile
-    src/ipaccess/Makefile
     src/utils/Makefile
     tests/Makefile
     tests/atlocal
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index e579ea0..86d6f8f 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -42,7 +42,6 @@
 	osmo-nitb \
 	osmo-bsc_mgcp \
 	utils \
-	ipaccess \
 	$(NULL)
 
 # Conditional Programs
diff --git a/openbsc/src/ipaccess/Makefile.am b/openbsc/src/ipaccess/Makefile.am
deleted file mode 100644
index 4dfe247..0000000
--- a/openbsc/src/ipaccess/Makefile.am
+++ /dev/null
@@ -1,66 +0,0 @@
-AM_CPPFLAGS = \
-	$(all_includes) \
-	-I$(top_srcdir)/include \
-	-I$(top_builddir) \
-	$(NULL)
-
-AM_CFLAGS = \
-	-Wall \
-	$(LIBOSMOCORE_CFLAGS) \
-	$(LIBOSMOGSM_CFLAGS) \
-	$(LIBOSMOABIS_CFLAGS) \
-	$(COVERAGE_CFLAGS) \
-	$(NULL)
-
-AM_LDFLAGS = \
-	$(COVERAGE_LDFLAGS) \
-	$(NULL)
-
-OSMO_LIBS = \
-	$(LIBOSMOCORE_LIBS) \
-	$(LIBOSMOGSM_LIBS) \
-	$(LIBOSMOABIS_LIBS) \
-	$(NULL)
-
-bin_PROGRAMS = \
-	abisip-find \
-	ipaccess-config \
-	ipaccess-proxy \
-	$(NULL)
-
-abisip_find_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
-
-abisip_find_SOURCES = \
-	abisip-find.c \
-	$(NULL)
-
-ipaccess_config_SOURCES = \
-	ipaccess-config.c \
-	ipaccess-firmware.c \
-	network_listen.c \
-	$(NULL)
-
-# FIXME: resolve the bogus dependencies patched around here:
-ipaccess_config_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
-
-ipaccess_proxy_SOURCES = \
-	ipaccess-proxy.c \
-	$(NULL)
-
-ipaccess_proxy_LDADD = \
-	$(top_builddir)/src/libbsc/libbsc.a \
-	$(top_builddir)/src/libtrau/libtrau.a \
-	$(top_builddir)/src/libcommon/libcommon.a \
-	$(OSMO_LIBS) \
-	$(NULL)
diff --git a/openbsc/src/ipaccess/abisip-find.c b/openbsc/src/ipaccess/abisip-find.c
deleted file mode 100644
index 21d9f22..0000000
--- a/openbsc/src/ipaccess/abisip-find.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* ip.access nanoBTS configuration tool */
-
-/* (C) 2009-2010 by Harald Welte <laforge at gnumonks.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include <osmocom/core/select.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/gsm/protocol/ipaccess.h>
-#include <osmocom/gsm/ipa.h>
-#include <openbsc/gsm_data.h>
-
-static int udp_sock(const char *ifname)
-{
-	int fd, rc, bc = 1;
-	struct sockaddr_in sa;
-
-	fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	if (fd < 0)
-		return fd;
-
-	if (ifname) {
-#ifdef __FreeBSD__
-		rc = setsockopt(fd, SOL_SOCKET, IP_RECVIF, ifname,
-				strlen(ifname));
-#else
-		rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
-				strlen(ifname));
-#endif
-		if (rc < 0)
-			goto err;
-	}
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	sa.sin_addr.s_addr = INADDR_ANY;
-
-	rc = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
-	if (rc < 0)
-		goto err;
-
-	rc = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc));
-	if (rc < 0)
-		goto err;
-
-#if 0
-	/* we cannot bind, since the response packets don't come from
-	 * the broadcast address */
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	inet_aton("255.255.255.255", &sa.sin_addr);
-
-	rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
-	if (rc < 0)
-		goto err;
-#endif
-	return fd;
-
-err:
-	close(fd);
-	return rc;
-}
-
-const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00,
-				IPAC_MSGT_ID_GET,
-					0x01, IPAC_IDTAG_MACADDR,
-					0x01, IPAC_IDTAG_IPADDR,
-					0x01, IPAC_IDTAG_UNIT,
-					0x01, IPAC_IDTAG_LOCATION1,
-					0x01, IPAC_IDTAG_LOCATION2,
-					0x01, IPAC_IDTAG_EQUIPVERS,
-					0x01, IPAC_IDTAG_SWVERSION,
-					0x01, IPAC_IDTAG_UNITNAME,
-					0x01, IPAC_IDTAG_SERNR,
-				};
-
-
-static int bcast_find(int fd)
-{
-	struct sockaddr_in sa;
-
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(3006);
-	inet_aton("255.255.255.255", &sa.sin_addr);
-
-	return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa));
-}
-
-static int parse_response(unsigned char *buf, int len)
-{
-	uint8_t t_len;
-	uint8_t t_tag;
-	uint8_t *cur = buf;
-
-	while (cur < buf + len) {
-		t_len = *cur++;
-		t_tag = *cur++;
-		
-		printf("%s='%s'  ", ipa_ccm_idtag_name(t_tag), cur);
-
-		cur += t_len;
-	}
-	printf("\n");
-	return 0;
-}
-
-static int read_response(int fd)
-{
-	unsigned char buf[255];
-	struct sockaddr_in sa;
-	int len;
-	socklen_t sa_len = sizeof(sa);
-
-	len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len);
-	if (len < 0)
-		return len;
-
-	/* 2 bytes length, 1 byte protocol */
-	if (buf[2] != IPAC_PROTO_IPACCESS)
-		return 0;
-
-	if (buf[4] != IPAC_MSGT_ID_RESP)
-		return 0;
-
-	return parse_response(buf+6, len-6);
-}
-
-static int bfd_cb(struct osmo_fd *bfd, unsigned int flags)
-{
-	if (flags & BSC_FD_READ)
-		return read_response(bfd->fd);
-	if (flags & BSC_FD_WRITE) {
-		bfd->when &= ~BSC_FD_WRITE;
-		return bcast_find(bfd->fd);
-	}
-	return 0;
-}
-
-static struct osmo_timer_list timer;
-
-static void timer_cb(void *_data)
-{
-	struct osmo_fd *bfd = _data;
-
-	bfd->when |= BSC_FD_WRITE;
-
-	osmo_timer_schedule(&timer, 5, 0);
-}
-
-int main(int argc, char **argv)
-{
-	struct osmo_fd bfd;
-	char *ifname = NULL;
-	int rc;
-
-	printf("abisip-find (C) 2009 by Harald Welte\n");
-	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
-
-	if (argc < 2) {
-		fprintf(stdout, "you might need to specify the outgoing\n"
-			" network interface, e.g. ``%s eth0''\n", argv[0]);
-	} else {
-		ifname = argv[1];
-	}
-
-	bfd.cb = bfd_cb;
-	bfd.when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd.fd = udp_sock(ifname);
-	if (bfd.fd < 0) {
-		perror("Cannot create local socket for broadcast udp");
-		exit(1);
-	}
-
-	rc = osmo_fd_register(&bfd);
-	if (rc < 0) {
-		fprintf(stderr, "Cannot register FD\n");
-		exit(1);
-	}
-
-	osmo_timer_setup(&timer, timer_cb, &bfd);
-	osmo_timer_schedule(&timer, 5, 0);
-
-	printf("Trying to find ip.access BTS by broadcast UDP...\n");
-
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	exit(0);
-}
-
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
deleted file mode 100644
index 6822c06..0000000
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ /dev/null
@@ -1,1019 +0,0 @@
-/* ip.access nanoBTS configuration tool */
-
-/* (C) 2009-2010 by Harald Welte <laforge at gnumonks.org>
- * (C) 2009-2011 by Holger Hans Peter Freyther
- * (C) 2009-2010 by On-Waves
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <errno.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-#include <osmocom/core/timer.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/common_bsc.h>
-#include <osmocom/abis/e1_input.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/network_listen.h>
-#include <osmocom/abis/ipaccess.h>
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <openbsc/network_listen.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/abis/abis.h>
-#include <osmocom/gsm/protocol/gsm_12_21.h>
-
-struct gsm_network *bsc_gsmnet;
-
-static int net_listen_testnr;
-static int restart;
-static char *prim_oml_ip;
-static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw;
-static char *unit_id;
-static uint16_t nv_flags;
-static uint16_t nv_mask;
-static char *software = NULL;
-static int sw_load_state = 0;
-static int oml_state = 0;
-static int dump_files = 0;
-static char *firmware_analysis = NULL;
-static int found_trx = 0;
-static int loop_tests = 0;
-
-static void *tall_ctx_config = NULL;
-static struct abis_nm_sw_desc *sw_load1 = NULL;
-static struct abis_nm_sw_desc *sw_load2 = NULL;
-
-/*
-static uint8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
-static uint8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 };
-*/
-
-extern int ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what);
-extern struct e1inp_line_ops ipaccess_e1inp_line_ops;
-
-/* Actively connect to a BTS.  Currently used by ipaccess-config.c */
-static int ipaccess_connect(struct e1inp_line *line, struct sockaddr_in *sa)
-{
-	struct e1inp_ts *e1i_ts = &line->ts[0];
-	struct osmo_fd *bfd = &e1i_ts->driver.ipaccess.fd;
-	int ret, on = 1;
-
-	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	bfd->cb = ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd->data = line;
-	bfd->priv_nr = E1INP_SIGN_OML;
-
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not create TCP socket.\n");
-		return -EIO;
-	}
-
-	ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not set socket option\n");
-		close(bfd->fd);
-		return -EIO;
-	}
-
-	ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not connect socket\n");
-		close(bfd->fd);
-		return ret;
-	}
-
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		close(bfd->fd);
-		return ret;
-	}
-	return ret;
-	//return e1inp_line_register(line);
-}
-
-/* configure pseudo E1 line in ip.access style and connect to BTS */
-static int ia_config_connect(struct gsm_bts *bts, struct sockaddr_in *sin)
-{
-	struct e1inp_line *line;
-	struct e1inp_ts *sign_ts, *rsl_ts;
-	struct e1inp_sign_link *oml_link, *rsl_link;
-
-	line = talloc_zero(tall_bsc_ctx, struct e1inp_line);
-	if (!line)
-		return -ENOMEM;
-
-	line->driver = e1inp_driver_find("ipa");
-	if (!line->driver) {
-		fprintf(stderr, "cannot `ipa' driver, giving up.\n");
-		return -EINVAL;
-	}
-	line->ops = &ipaccess_e1inp_line_ops;
-
-	/* create E1 timeslots for signalling and TRAU frames */
-	e1inp_ts_config_sign(&line->ts[1-1], line);
-	e1inp_ts_config_sign(&line->ts[2-1], line);
-
-	/* create signalling links for TS1 */
-	sign_ts = &line->ts[1-1];
-	rsl_ts = &line->ts[2-1];
-	oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML,
-					  bts->c0, 0xff, 0);
-	rsl_link = e1inp_sign_link_create(rsl_ts, E1INP_SIGN_RSL,
-					  bts->c0, 0, 0);
-
-	/* create back-links from bts/trx */
-	bts->oml_link = oml_link;
-	bts->c0->rsl_link = rsl_link;
-
-	/* default port at BTS for incoming connections is 3006 */
-	if (sin->sin_port == 0)
-		sin->sin_port = htons(3006);
-
-	return ipaccess_connect(line, sin);
-}
-
-/*
- * Callback function for NACK on the OML NM
- *
- * Currently we send the config requests but don't check the
- * result. The nanoBTS will send us a NACK when we did something the
- * BTS didn't like.
- */
-static int ipacc_msg_nack(uint8_t mt)
-{
-	fprintf(stderr, "Failure to set attribute. This seems fatal\n");
-	exit(-1);
-	return 0;
-}
-
-static void check_restart_or_exit(struct gsm_bts_trx *trx)
-{
-	if (restart) {
-		abis_nm_ipaccess_restart(trx);
-	} else {
-		exit(0);
-	}
-}
-
-static int ipacc_msg_ack(uint8_t mt, struct gsm_bts_trx *trx)
-{
-	if (sw_load_state == 1) {
-		fprintf(stderr, "The new software is activaed.\n");
-		check_restart_or_exit(trx);
-	} else if (oml_state == 1) {
-		fprintf(stderr, "Set the NV Attributes.\n");
-		check_restart_or_exit(trx);
-	}
-
-	return 0;
-}
-
-static const uint8_t phys_conf_min[] = { 0x02 };
-
-static uint16_t build_physconf(uint8_t *physconf_buf, const struct rxlev_stats *st)
-{
-	uint16_t *whitelist = (uint16_t *) (physconf_buf + 4);
-	int num_arfcn;
-	unsigned int arfcnlist_size;
-
-	/* Create whitelist from rxlevels */
-	physconf_buf[0] = phys_conf_min[0];
-	physconf_buf[1] = NM_IPAC_EIE_ARFCN_WHITE;
-	num_arfcn = ipac_rxlevstat2whitelist(whitelist, st, 0, 100);
-	arfcnlist_size = num_arfcn * 2;
-	*((uint16_t *) (physconf_buf+2)) = htons(arfcnlist_size);
-	DEBUGP(DNM, "physconf_buf (%s)\n", osmo_hexdump(physconf_buf, arfcnlist_size+4));
-	return arfcnlist_size+4;
-}
-
-static int nwl_sig_cb(unsigned int subsys, unsigned int signal,
-		      void *handler_data, void *signal_data)
-{
-	struct gsm_bts_trx *trx;
-	uint8_t physconf_buf[2*NUM_ARFCNS+16];
-	uint16_t physconf_len;
-
-	switch (signal) {
-	case S_IPAC_NWL_COMPLETE:
-		trx = signal_data;
-		DEBUGP(DNM, "received S_IPAC_NWL_COMPLETE signal\n");
-		switch (trx->ipaccess.test_nr) {
-		case NM_IPACC_TESTNO_CHAN_USAGE:
-			/* Dump RxLev results */
-			//rxlev_stat_dump(&trx->ipaccess.rxlev_stat);
-			/* Create whitelist from results */
-			physconf_len = build_physconf(physconf_buf,
-						      &trx->ipaccess.rxlev_stat);
-			/* Start next test abbout BCCH channel usage */
-			ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_CHAN_USAGE,
-					    physconf_buf, physconf_len);
-			break;
-		case NM_IPACC_TESTNO_BCCH_CHAN_USAGE:
-			/* Dump BCCH RxLev results */
-			//rxlev_stat_dump(&trx->ipaccess.rxlev_stat);
-			/* Create whitelist from results */
-			physconf_len = build_physconf(physconf_buf,
-						      &trx->ipaccess.rxlev_stat);
-			/* Start next test about BCCH info */
-			ipac_nwl_test_start(trx, NM_IPACC_TESTNO_BCCH_INFO,
-					    physconf_buf, physconf_len);
-			break;
-		case NM_IPACC_TESTNO_BCCH_INFO:
-			/* re-start full process with CHAN_USAGE */
-			if (loop_tests) {
-				DEBUGP(DNM, "starting next test cycle\n");
-				ipac_nwl_test_start(trx, net_listen_testnr, phys_conf_min,
-						    sizeof(phys_conf_min));
-			} else {
-				exit(0);
-			}
-			break;
-		}
-		break;
-	}
-	return 0;
-}
-
-static int nm_state_event(int evt, uint8_t obj_class, void *obj,
-			  struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
-			  struct abis_om_obj_inst *obj_inst);
-
-static int nm_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	struct ipacc_ack_signal_data *ipacc_data;
-	struct nm_statechg_signal_data *nsd;
-
-	switch (signal) {
-	case S_NM_IPACC_NACK:
-		ipacc_data = signal_data;
-		return ipacc_msg_nack(ipacc_data->msg_type);
-	case S_NM_IPACC_ACK:
-		ipacc_data = signal_data;
-		return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx);
-	case S_NM_IPACC_RESTART_ACK:
-		printf("The BTS has acked the restart. Exiting.\n");
-		exit(0);
-		break;
-	case S_NM_IPACC_RESTART_NACK:
-		printf("The BTS has nacked the restart. Exiting.\n");
-		exit(0);
-		break;
-	case S_NM_STATECHG_OPER:
-	case S_NM_STATECHG_ADM:
-		nsd = signal_data;
-		nm_state_event(signal, nsd->obj_class, nsd->obj, nsd->old_state,
-				nsd->new_state, nsd->obj_inst);
-		break;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-/* callback function passed to the ABIS OML code */
-static int percent;
-static int percent_old;
-static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
-		       void *data, void *param)
-{
-	struct msgb *msg;
-	struct gsm_bts_trx *trx;
-
-	if (hook != GSM_HOOK_NM_SWLOAD)
-		return 0;
-
-	trx = (struct gsm_bts_trx *) data;
-
-	switch (event) {
-	case NM_MT_LOAD_INIT_ACK:
-		fprintf(stdout, "Software Load Initiate ACK\n");
-		break;
-	case NM_MT_LOAD_INIT_NACK:
-		fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
-		exit(5);
-		break;
-	case NM_MT_LOAD_END_ACK:
-		fprintf(stderr, "LOAD END ACK...");
-		/* now make it the default */
-		sw_load_state = 1;
-
-		msg = msgb_alloc(1024, "sw: nvattr");
-		msg->l2h = msgb_put(msg, 3);
-		msg->l3h = &msg->l2h[3];
-
-		/* activate software */
-		if (sw_load1)
-			abis_nm_put_sw_desc(msg, sw_load1, true);
-
-		if (sw_load2)
-			abis_nm_put_sw_desc(msg, sw_load2, true);
-
-		/* fill in the data */
-		msg->l2h[0] = NM_ATT_IPACC_CUR_SW_CFG;
-		msg->l2h[1] = msgb_l3len(msg) >> 8;
-		msg->l2h[2] = msgb_l3len(msg) & 0xff;
-		printf("Foo l2h: %p l3h: %p... length l2: %u  l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg));
-		abis_nm_ipaccess_set_nvattr(trx, msg->l2h, msgb_l2len(msg));
-		msgb_free(msg);
-		break;
-	case NM_MT_LOAD_END_NACK:
-		fprintf(stderr, "ERROR: Software Load End NACK\n");
-		exit(3);
-		break;
-	case NM_MT_ACTIVATE_SW_NACK:
-		fprintf(stderr, "ERROR: Activate Software NACK\n");
-		exit(4);
-		break;
-	case NM_MT_ACTIVATE_SW_ACK:
-		break;
-	case NM_MT_LOAD_SEG_ACK:
-		percent = abis_nm_software_load_status(trx->bts);
-		if (percent > percent_old)
-			printf("Software Download Progress: %d%%\n", percent);
-		percent_old = percent;
-		break;
-	case NM_MT_LOAD_ABORT:
-		fprintf(stderr, "ERROR: Load aborted by the BTS.\n");
-		exit(6);
-		break;
-	}
-	return 0;
-}
-
-static void nv_put_ip_if_cfg(struct msgb *nmsg, uint32_t ip, uint32_t mask)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_IP_IF_CFG);
-
-	msgb_put_u32(nmsg, ip);
-	msgb_put_u32(nmsg, mask);
-}
-
-static void nv_put_gw_cfg(struct msgb *nmsg, uint32_t addr, uint32_t mask, uint32_t gw)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_IP_GW_CFG);
-	msgb_put_u32(nmsg, addr);
-	msgb_put_u32(nmsg, mask);
-	msgb_put_u32(nmsg, gw);
-}
-
-static void nv_put_unit_id(struct msgb *nmsg, const char *unit_id)
-{
-	msgb_tl16v_put(nmsg, NM_ATT_IPACC_UNIT_ID, strlen(unit_id)+1,
-			(const uint8_t *)unit_id);
-}
-
-static void nv_put_prim_oml(struct msgb *nmsg, uint32_t ip, uint16_t port)
-{
-	int len;
-
-	/* 0x88 + IP + port */
-	len = 1 + sizeof(ip) + sizeof(port);
-
-	msgb_put_u8(nmsg, NM_ATT_IPACC_PRIM_OML_CFG_LIST);
-	msgb_put_u16(nmsg, len);
-
-	msgb_put_u8(nmsg, 0x88);
-
-	/* IP address */
-	msgb_put_u32(nmsg, ip);
-
-	/* port number */
-	msgb_put_u16(nmsg, port);
-}
-
-static void nv_put_flags(struct msgb *nmsg, uint16_t nv_flags, uint16_t nv_mask)
-{
-	msgb_put_u8(nmsg, NM_ATT_IPACC_NV_FLAGS);
-	msgb_put_u16(nmsg, sizeof(nv_flags) + sizeof(nv_mask));
-	msgb_put_u8(nmsg, nv_flags & 0xff);
-	msgb_put_u8(nmsg, nv_mask & 0xff);
-	msgb_put_u8(nmsg, nv_flags >> 8);
-	msgb_put_u8(nmsg, nv_mask >> 8);
-}
-
-/* human-readable test names for the ip.access tests */
-static const struct value_string ipa_test_strs[] = {
-	{ 64, "ccch-usage" },
-	{ 65, "bcch-usage" },
-	{ 66, "freq-sync" },
-	{ 67, "rtp-usage" },
-	{ 68, "rtp-perf" },
-	{ 69, "gprs-ccch" },
-	{ 70, "pccch-usage" },
-	{ 71, "gprs-usage" },
-	{ 72, "esta-mf" },
-	{ 73, "uplink-mf" },
-	{ 74, "dolink-mf" },
-	{ 75, "tbf-details" },
-	{ 76, "tbf-usage" },
-	{ 77, "llc-data" },
-	{ 78, "pdch-usage" },
-	{ 79, "power-control" },
-	{ 80, "link-adaption" },
-	{ 81, "tch-usage" },
-	{ 82, "amr-mf" },
-	{ 83, "rtp-multiplex-perf" },
-	{ 84, "rtp-multiplex-usage" },
-	{ 85, "srtp-multiplex-usage" },
-	{ 86, "abis-traffic" },
-	{ 89, "gprs-multiplex-perf" },
-	{ 90, "gprs-multiplex-usage" },
-	{ 0, NULL },
-};
-
-/* human-readable names for the ip.access nanoBTS NVRAM Flags */
-static const struct value_string ipa_nvflag_strs[] = {
-	{ 0x0001, "static-ip" },
-	{ 0x0002, "static-gw" },
-	{ 0x0004, "no-dhcp-vsi" },
-	{ 0x0008, "dhcp-enabled" },
-	{ 0x0040, "led-disabled" },
-	{ 0x0100, "secondary-oml-enabled" },
-	{ 0x0200, "diag-enabled" },
-	{ 0x0400, "cli-enabled" },
-	{ 0x0800, "http-enabled" },
-	{ 0x1000, "post-enabled" },
-	{ 0x2000, "snmp-enabled" },
-	{ 0, NULL }
-};
-
-/* set the flags in flags/mask according to a string-identified flag and 'enable' */
-static int ipa_nvflag_set(uint16_t *flags, uint16_t *mask, const char *name, int en)
-{
-	int rc;
-	rc = get_string_value(ipa_nvflag_strs, name);
-	if (rc < 0)
-		return rc;
-
-	*mask |= rc;
-	if (en)
-		*flags |= rc;
-	else
-		*flags &= ~rc;
-
-	return 0;
-}
-
-static void bootstrap_om(struct gsm_bts_trx *trx)
-{
-	struct msgb *nmsg = msgb_alloc(1024, "nested msgb");
-	int need_to_set_attr = 0;
-	int len;
-
-	printf("OML link established using TRX %d\n", trx->nr);
-
-	if (unit_id) {
-		len = strlen(unit_id);
-		if (len > nmsg->data_len-10)
-			goto out_err;
-		printf("setting Unit ID to '%s'\n", unit_id);
-		nv_put_unit_id(nmsg, unit_id);
-		need_to_set_attr = 1;
-	}
-	if (prim_oml_ip) {
-		struct in_addr ia;
-
-		if (!inet_aton(prim_oml_ip, &ia)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				prim_oml_ip);
-			goto out_err;
-		}
-
-		printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
-		nv_put_prim_oml(nmsg, ntohl(ia.s_addr), 0);
-		need_to_set_attr = 1;
-	}
-	if (nv_mask) {
-		printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
-			nv_flags, nv_mask);
-		nv_put_flags(nmsg, nv_flags, nv_mask);
-		need_to_set_attr = 1;
-	}
-	if (bts_ip_addr && bts_ip_mask) {
-		struct in_addr ia_addr, ia_mask;
-
-		if (!inet_aton(bts_ip_addr, &ia_addr)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_addr);
-			goto out_err;
-		}
-
-		if (!inet_aton(bts_ip_mask, &ia_mask)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_mask);
-			goto out_err;
-		}
-
-		printf("setting static IP Address/Mask\n");
-		nv_put_ip_if_cfg(nmsg, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr));
-		need_to_set_attr = 1;
-	}
-	if (bts_ip_gw) {
-		struct in_addr ia_gw;
-
-		if (!inet_aton(bts_ip_gw, &ia_gw)) {
-			fprintf(stderr, "invalid IP address: %s\n",
-				bts_ip_gw);
-			goto out_err;
-		}
-
-		printf("setting static IP Gateway\n");
-		/* we only set the default gateway with zero addr/mask */
-		nv_put_gw_cfg(nmsg, 0, 0, ntohl(ia_gw.s_addr));
-		need_to_set_attr = 1;
-	}
-
-	if (need_to_set_attr) {
-		abis_nm_ipaccess_set_nvattr(trx, nmsg->head, nmsg->len);
-		oml_state = 1;
-	}
-
-	if (restart && !prim_oml_ip && !software) {
-		printf("restarting BTS\n");
-		abis_nm_ipaccess_restart(trx);
-	}
-
-out_err:
-	msgb_free(nmsg);
-}
-
-static int nm_state_event(int evt, uint8_t obj_class, void *obj,
-			  struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
-			  struct abis_om_obj_inst *obj_inst)
-{
-	if (obj_class == NM_OC_BASEB_TRANSC) {
-		if (!found_trx && obj_inst->trx_nr != 0xff) {
-			struct gsm_bts_trx *trx = container_of(obj, struct gsm_bts_trx, bb_transc);
-			bootstrap_om(trx);
-			found_trx = 1;
-		}
-	} else if (evt == S_NM_STATECHG_OPER &&
-	    obj_class == NM_OC_RADIO_CARRIER &&
-	    new_state->availability == 3) {
-		struct gsm_bts_trx *trx = obj;
-
-		if (net_listen_testnr)
-			ipac_nwl_test_start(trx, net_listen_testnr,
-					    phys_conf_min, sizeof(phys_conf_min));
-		else if (software) {
-			int rc;
-			printf("Attempting software upload with '%s'\n", software);
-			rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx);
-			if (rc < 0) {
-				fprintf(stderr, "Failed to start software load\n");
-				exit(-3);
-			}
-		}
-	}
-	return 0;
-}
-
-static struct abis_nm_sw_desc *create_swload(struct sdp_header *header)
-{
-	struct abis_nm_sw_desc *load;
-
-	load = talloc_zero(tall_ctx_config, struct abis_nm_sw_desc);
-
-	osmo_strlcpy((char *)load->file_id, header->firmware_info.sw_part,
-		     sizeof(load->file_id));
-	load->file_id_len = strlen((char*)load->file_id) + 1;
-
-	osmo_strlcpy((char *)load->file_version, header->firmware_info.version,
-		     sizeof(load->file_version));
-	load->file_version_len = strlen((char*)load->file_version) + 1;
-
-	return load;
-}
-
-static int find_sw_load_params(const char *filename)
-{
-	struct stat stat;
-	struct sdp_header *header;
-	struct llist_head *entry;
-	int fd;
-	void *tall_firm_ctx = 0;
-
-	entry = talloc_zero(tall_firm_ctx, struct llist_head);
-	INIT_LLIST_HEAD(entry);
-
-	fd = open(filename, O_RDONLY);
-	if (!fd) {
-		perror("nada");
-		return -1;
-	}
-
-	/* verify the file */
-	if (fstat(fd, &stat) == -1) {
-		perror("Can not stat the file");
-		close(fd);
-		return -1;
-	}
-
-	ipaccess_analyze_file(fd, stat.st_size, 0, entry);
-	if (close(fd) != 0) {
-		perror("Close failed.\n");
-		return -1;
-	}
-
-	/* try to find what we are looking for */
-	llist_for_each_entry(header, entry, entry) {
-		if (ntohs(header->firmware_info.more_more_magic) == 0x1000) {
-			sw_load1 = create_swload(header);
-		} else if (ntohs(header->firmware_info.more_more_magic) == 0x2001) {
-			sw_load2 = create_swload(header);
-		}
-	}
-
-	if (!sw_load1 || !sw_load2) {
-		fprintf(stderr, "Did not find data.\n");
-		talloc_free(tall_firm_ctx);
-		return -1;
-        }
-
-	talloc_free(tall_firm_ctx);
-	return 0;
-}
-
-static void dump_entry(struct sdp_header_item *sub_entry, int part, int fd)
-{
-	int out_fd;
-	int copied;
-	char filename[4096];
-	off_t target;
-
-	if (!dump_files)
-		return;
-
-	if (sub_entry->header_entry.something1 == 0)
-		return;
-
-	snprintf(filename, sizeof(filename), "part.%d", part++);
-	out_fd = open(filename, O_WRONLY | O_CREAT, 0660);
-	if (out_fd < 0) {
-		perror("Can not dump firmware");
-		return;
-	}
-
-	target = sub_entry->absolute_offset + ntohl(sub_entry->header_entry.start) + 4;
-	if (lseek(fd, target, SEEK_SET) != target) {
-		perror("seek failed");
-		close(out_fd);
-		return;
-	}
-
-	for (copied = 0; copied < ntohl(sub_entry->header_entry.length); ++copied) {
-		char c;
-		if (read(fd, &c, sizeof(c)) != sizeof(c)) {
-			perror("copy failed");
-			break;
-		}
-
-		if (write(out_fd, &c, sizeof(c)) != sizeof(c)) {
-			perror("write failed");
-			break;
-		}
-	}
-
-	close(out_fd);
-}
-
-static void analyze_firmware(const char *filename)
-{
-	struct stat stat;
-	struct sdp_header *header;
-	struct sdp_header_item *sub_entry;
-	struct llist_head *entry;
-	int fd;
-	void *tall_firm_ctx = 0;
-	int part = 0;
-
-	entry = talloc_zero(tall_firm_ctx, struct llist_head);
-	INIT_LLIST_HEAD(entry);
-
-	printf("Opening possible firmware '%s'\n", filename);
-	fd = open(filename, O_RDONLY);
-	if (!fd) {
-		perror("nada");
-		return;
-	}
-
-	/* verify the file */
-	if (fstat(fd, &stat) == -1) {
-		perror("Can not stat the file");
-		close(fd);
-		return;
-	}
-
-	ipaccess_analyze_file(fd, stat.st_size, 0, entry);
-
-	llist_for_each_entry(header, entry, entry) {
-		printf("Printing header information:\n");
-		printf("more_more_magic: 0x%x\n", ntohs(header->firmware_info.more_more_magic));
-		printf("header_length: %u\n", ntohl(header->firmware_info.header_length));
-		printf("file_length: %u\n", ntohl(header->firmware_info.file_length));
-		printf("sw_part: %.20s\n", header->firmware_info.sw_part);
-		printf("text1: %.64s\n", header->firmware_info.text1);
-		printf("time: %.12s\n", header->firmware_info.time);
-		printf("date: %.14s\n", header->firmware_info.date);
-		printf("text2: %.10s\n", header->firmware_info.text2);
-		printf("version: %.20s\n", header->firmware_info.version);
-		printf("subitems...\n");
-
-		llist_for_each_entry(sub_entry, &header->header_list, entry) {
-			printf("\tsomething1: %u\n", sub_entry->header_entry.something1);
-			printf("\ttext1: %.64s\n", sub_entry->header_entry.text1);
-			printf("\ttime: %.12s\n", sub_entry->header_entry.time);
-			printf("\tdate: %.14s\n", sub_entry->header_entry.date);
-			printf("\ttext2: %.10s\n", sub_entry->header_entry.text2);
-			printf("\tversion: %.20s\n", sub_entry->header_entry.version);
-			printf("\tlength: %u\n", ntohl(sub_entry->header_entry.length));
-			printf("\taddr1: 0x%x\n", ntohl(sub_entry->header_entry.addr1));
-			printf("\taddr2: 0x%x\n", ntohl(sub_entry->header_entry.addr2));
-			printf("\tstart: 0x%x\n", ntohl(sub_entry->header_entry.start));
-			printf("\tabs. offset: 0x%lx\n", sub_entry->absolute_offset);
-			printf("\n\n");
-
-			dump_entry(sub_entry, part++, fd);
-		}
-		printf("\n\n");
-	}
-
-	if (close(fd) != 0) {
-		perror("Close failed.\n");
-		return;
-	}
-
-	talloc_free(tall_firm_ctx);
-}
-
-static void print_usage(void)
-{
-	printf("Usage: ipaccess-config IP_OF_BTS\n");
-}
-
-static void print_help(void)
-{
-#if 0
-	printf("Commands for reading from the BTS:\n");
-	printf("  -D --dump\t\t\tDump the BTS configuration\n");
-	printf("\n");
-#endif
-	printf("Commands for writing to the BTS:\n");
-	printf("  -u --unit-id UNIT_ID\t\tSet the Unit ID of the BTS\n");
-	printf("  -o --oml-ip IP\t\tSet primary OML IP (IP of your BSC)\n");
-	printf("  -i --ip-address IP/MASK\tSet static IP address + netmask of BTS\n");
-	printf("  -g --ip-gateway IP\t\tSet static IP gateway of BTS\n");
-	printf("  -r --restart\t\t\tRestart the BTS (after other operations)\n");
-	printf("  -n --nvram-flags FLAGS/MASK\tSet NVRAM attributes\n");
-	printf("  -S --nvattr-set FLAG\tSet one additional NVRAM attribute\n");
-	printf("  -U --nvattr-unset FLAG\tSet one additional NVRAM attribute\n");
-	printf("  -l --listen TESTNR\t\tPerform specified test number\n");
-	printf("  -L --Listen TEST_NAME\t\tPerform specified test\n");
-	printf("  -s --stream-id ID\t\tSet the IPA Stream Identifier for OML\n");
-	printf("  -d --software FIRMWARE\tDownload firmware into BTS\n");
-	printf("\n");
-	printf("Miscellaneous commands:\n");
-	printf("  -h --help\t\t\tthis text\n");
-	printf("  -H --HELP\t\t\tPrint parameter details.\n");
-	printf("  -f --firmware FIRMWARE\tProvide firmware information\n");
-	printf("  -w --write-firmware\t\tThis will dump the firmware parts to the filesystem. Use with -f.\n");
-	printf("  -p --loop\t\t\tLoop the tests executed with the --listen command.\n");
-}
-
-static void print_value_string(const struct value_string *val, int size)
-{
-	int i;
-
-	for (i = 0; i < size - 1; ++i) {
-		char sep = val[i + 1].str == NULL ? '.' : ',';
-		printf("%s%c ", val[i].str, sep);
-	}
-	printf("\n");
-}
-
-static void print_options(void)
-{
-
-	printf("Options for NVRAM (-S,-U):\n  ");
-	print_value_string(&ipa_nvflag_strs[0], ARRAY_SIZE(ipa_nvflag_strs));
-
-	printf("Options for Tests (-L):\n ");
-	print_value_string(&ipa_test_strs[0], ARRAY_SIZE(ipa_test_strs));
-}
-
-extern void bts_model_nanobts_init();
-
-int main(int argc, char **argv)
-{
-	struct gsm_bts *bts;
-	struct sockaddr_in sin;
-	int rc, option_index = 0, stream_id = 0xff;
-
-	tall_ctx_config = talloc_named_const(NULL, 0, "ipaccess-config");
-	msgb_talloc_ctx_init(tall_ctx_config, 0);
-
-	osmo_init_logging(&log_info);
-	log_parse_category_mask(osmo_stderr_target, "DNM,0");
-	bts_model_nanobts_init();
-
-	printf("ipaccess-config (C) 2009-2010 by Harald Welte and others\n");
-	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
-
-	while (1) {
-		int c;
-		unsigned long ul;
-		char *slash;
-		static struct option long_options[] = {
-			{ "unit-id", 1, 0, 'u' },
-			{ "oml-ip", 1, 0, 'o' },
-			{ "ip-address", 1, 0, 'i' },
-			{ "ip-gateway", 1, 0, 'g' },
-			{ "restart", 0, 0, 'r' },
-			{ "nvram-flags", 1, 0, 'n' },
-			{ "nvattr-set", 1, 0, 'S' },
-			{ "nvattr-unset", 1, 0, 'U' },
-			{ "help", 0, 0, 'h' },
-			{ "HELP", 0, 0, 'H' },
-			{ "listen", 1, 0, 'l' },
-			{ "Listen", 1, 0, 'L' },
-			{ "stream-id", 1, 0, 's' },
-			{ "software", 1, 0, 'd' },
-			{ "firmware", 1, 0, 'f' },
-			{ "write-firmware", 0, 0, 'w' },
-			{ "disable-color", 0, 0, 'c'},
-			{ "loop", 0, 0, 'p' },
-			{ 0, 0, 0, 0 },
-		};
-
-		c = getopt_long(argc, argv, "u:o:i:g:rn:S:U:l:L:hs:d:f:wcpH", long_options,
-				&option_index);
-
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'u':
-			unit_id = optarg;
-			break;
-		case 'o':
-			prim_oml_ip = optarg;
-			break;
-		case 'i':
-			slash = strchr(optarg, '/');
-			if (!slash)
-				exit(2);
-			bts_ip_addr = optarg;
-			*slash = 0;
-			bts_ip_mask = slash+1;
-			break;
-		case 'g':
-			bts_ip_gw = optarg;
-			break;
-		case 'r':
-			restart = 1;
-			break;
-		case 'n':
-			slash = strchr(optarg, '/');
-			if (!slash)
-				exit(2);
-			ul = strtoul(optarg, NULL, 16);
-			nv_flags = ul & 0xffff;
-			ul = strtoul(slash+1, NULL, 16);
-			nv_mask = ul & 0xffff;
-			break;
-		case 'S':
-			if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 1) < 0)
-				exit(2);
-			break;
-		case 'U':
-			if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 0) < 0)
-				exit(2);
-			break;
-		case 'l':
-			net_listen_testnr = atoi(optarg);
-			break;
-		case 'L':
-			net_listen_testnr = get_string_value(ipa_test_strs,
-							     optarg);
-			if (net_listen_testnr < 0) {
-				fprintf(stderr,
-					"The test '%s' is not known. Use -H to"
-					" see available tests.\n", optarg);
-				exit(2);
-			}
-			break;
-		case 's':
-			stream_id = atoi(optarg);
-			break;
-		case 'd':
-			software = strdup(optarg);
-			if (find_sw_load_params(optarg) != 0)
-				exit(0);
-			break;
-		case 'f':
-			firmware_analysis = optarg;
-			break;
-		case 'w':
-			dump_files = 1;
-			break;
-		case 'c':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'p':
-			loop_tests = 1;
-			break;
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 'H':
-			print_options();
-			exit(0);
-		}
-	};
-
-	if (firmware_analysis)
-		analyze_firmware(firmware_analysis);
-
-	if (optind >= argc) {
-		/* only warn if we have not done anything else */
-		if (!firmware_analysis)
-			fprintf(stderr, "you have to specify the IP address of the BTS. Use --help for more information\n");
-		exit(2);
-	}
-	libosmo_abis_init(tall_ctx_config);
-
-	bsc_gsmnet = bsc_network_init(tall_bsc_ctx, 1, 1, NULL);
-	if (!bsc_gsmnet)
-		exit(1);
-
-	bts = gsm_bts_alloc_register(bsc_gsmnet, GSM_BTS_TYPE_NANOBTS,
-				     HARDCODED_BSIC);
-	/* ip.access supports up to 4 chained TRX */
-	gsm_bts_trx_alloc(bts);
-	gsm_bts_trx_alloc(bts);
-	gsm_bts_trx_alloc(bts);
-	bts->oml_tei = stream_id;
-	
-	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
-	osmo_signal_register_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
-
-	ipac_nwl_init();
-
-	printf("Trying to connect to ip.access BTS ...\n");
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(argv[optind], &sin.sin_addr);
-	rc = ia_config_connect(bts, &sin);
-	if (rc < 0) {
-		perror("Error connecting to the BTS");
-		exit(1);
-	}
-	
-	bts->oml_link->ts->sign.delay = 10;
-	bts->c0->rsl_link->ts->sign.delay = 10;
-	while (1) {
-		rc = osmo_select_main(0);
-		if (rc < 0)
-			exit(3);
-	}
-
-	exit(0);
-}
-
diff --git a/openbsc/src/ipaccess/ipaccess-firmware.c b/openbsc/src/ipaccess/ipaccess-firmware.c
deleted file mode 100644
index 5f55bb5..0000000
--- a/openbsc/src/ipaccess/ipaccess-firmware.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Routines for parsing an ipacces SDP firmware file */
-
-/* (C) 2009 by Holger Hans Peter Freyther <zecke at selfish.org>
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <osmocom/core/talloc.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define PART_LENGTH 138
-
-osmo_static_assert(sizeof(struct sdp_header_entry) == 138, right_entry);
-osmo_static_assert(sizeof(struct sdp_firmware) == 158, _right_header_length);
-
-/* more magic, the second "int" in the header */
-static char more_magic[] = { 0x10, 0x02 };
-
-int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned int base_offset, struct llist_head *list)
-{
-	struct sdp_firmware *firmware_header = 0;
-	struct sdp_header *header;
-	char buf[4096];
-	int rc, i;
-	uint16_t table_size;
-	uint16_t table_offset;
-	off_t table_start;
-
-
-	rc = read(fd, buf, sizeof(*firmware_header));
-	if (rc < 0) {
-		perror("Can not read header start.");
-		return -1;
-	}
-
-	firmware_header = (struct sdp_firmware *) &buf[0];
-	if (strncmp(firmware_header->magic, " SDP", 4) != 0) {
-		fprintf(stderr, "Wrong magic.\n");
-		return -1;
-	}
-
-	if (memcmp(firmware_header->more_magic, more_magic, 2) != 0) {
-		fprintf(stderr, "Wrong more magic. Got: 0x%x 0x%x vs. 0x%x 0x%x\n",
-			firmware_header->more_magic[0] & 0xff, firmware_header->more_magic[1] & 0xff,
-			more_magic[0], more_magic[1]);
-		return -1;
-	}
-
-
-	if (ntohl(firmware_header->file_length) != st_size) {
-		fprintf(stderr, "The filesize and the header do not match.\n");
-		return -1;
-	}
-
-	/* add the firmware */
-	header = talloc_zero(list, struct sdp_header);
-	header->firmware_info = *firmware_header;
-	INIT_LLIST_HEAD(&header->header_list);
-	llist_add(&header->entry, list);
-
-	table_offset = ntohs(firmware_header->table_offset);
-	table_start = lseek(fd, table_offset, SEEK_CUR);
-	if (table_start == -1) {
-		fprintf(stderr, "Failed to seek to the rel position: 0x%x\n", table_offset);
-		return -1;
-	}
-
-	if (read(fd, &table_size, sizeof(table_size)) != sizeof(table_size)) {
-		fprintf(stderr, "The table size could not be read.\n");
-		return -1;
-	}
-
-	table_size = ntohs(table_size);
-
-	if (table_size % PART_LENGTH != 0) {
-		fprintf(stderr, "The part length seems to be wrong: 0x%x\n", table_size);
-		return -1;
-	}
-
-	/* look into each firmware now */
-	for (i = 0; i < table_size / PART_LENGTH; ++i) {
-		struct sdp_header_entry entry;
-		struct sdp_header_item *header_entry;
-		unsigned int offset = table_start + 2;
-		offset += i * 138;
-
-		if (lseek(fd, offset, SEEK_SET) != offset) {
-			fprintf(stderr, "Can not seek to the offset: %u.\n", offset);
-			return -1;
-		}
-
-		rc = read(fd, &entry, sizeof(entry));
-		if (rc != sizeof(entry)) {
-			fprintf(stderr, "Can not read the header entry.\n");
-			return -1;
-		}
-
-		header_entry = talloc_zero(header,  struct sdp_header_item);
-		header_entry->header_entry = entry;
-		header_entry->absolute_offset = base_offset;
-		llist_add(&header_entry->entry, &header->header_list);
-
-		/* now we need to find the SDP file... */
-		offset = ntohl(entry.start) + 4 + base_offset;
-		if (lseek(fd, offset, SEEK_SET) != offset) {
-			perror("can't seek to sdp");
-			return -1;
-		}
-
-
-		ipaccess_analyze_file(fd, ntohl(entry.length), offset, list);
-	}
-
-	return 0;
-}
-
diff --git a/openbsc/src/ipaccess/ipaccess-proxy.c b/openbsc/src/ipaccess/ipaccess-proxy.c
deleted file mode 100644
index d367442..0000000
--- a/openbsc/src/ipaccess/ipaccess-proxy.c
+++ /dev/null
@@ -1,1226 +0,0 @@
-/* OpenBSC Abis/IP proxy ip.access nanoBTS */
-
-/* (C) 2009 by Harald Welte <laforge at gnumonks.org>
- * (C) 2010 by On-Waves
- * (C) 2010 by Holger Hans Peter Freyther <zecke at selfish.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <signal.h>
-#include <time.h>
-#include <sys/fcntl.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
-#define _GNU_SOURCE
-#include <getopt.h>
-
-#include <openbsc/gsm_data.h>
-#include <osmocom/core/application.h>
-#include <osmocom/core/select.h>
-#include <osmocom/gsm/tlv.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/ipa.h>
-#include <osmocom/abis/ipa.h>
-#include <osmocom/abis/ipaccess.h>
-#include <openbsc/debug.h>
-#include <openbsc/ipaccess.h>
-#include <openbsc/socket.h>
-#include <osmocom/core/talloc.h>
-
-/* one instance of an ip.access protocol proxy */
-struct ipa_proxy {
-	/* socket where we listen for incoming OML from BTS */
-	struct osmo_fd oml_listen_fd;
-	/* socket where we listen for incoming RSL from BTS */
-	struct osmo_fd rsl_listen_fd;
-	/* list of BTS's (struct ipa_bts_conn */
-	struct llist_head bts_list;
-	/* the BSC reconnect timer */
-	struct osmo_timer_list reconn_timer;
-	/* global GPRS NS data */
-	struct in_addr gprs_addr;
-	struct in_addr listen_addr;
-};
-
-/* global pointer to the proxy structure */
-static struct ipa_proxy *ipp;
-
-struct ipa_proxy_conn {
-	struct osmo_fd fd;
-	struct llist_head tx_queue;
-	struct ipa_bts_conn *bts_conn;
-};
-#define MAX_TRX 4
-
-/* represents a particular BTS in our proxy */
-struct ipa_bts_conn {
-	/* list of BTS's (ipa_proxy->bts_list) */
-	struct llist_head list;
-	/* back pointer to the proxy which we belong to */
-	struct ipa_proxy *ipp;
-	/* the unit ID as determined by CCM */
-	struct {
-		uint16_t site_id;
-		uint16_t bts_id;
-	} unit_id;
-
-	/* incoming connections from BTS */
-	struct ipa_proxy_conn *oml_conn;
-	struct ipa_proxy_conn *rsl_conn[MAX_TRX];
-
-	/* outgoing connections to BSC */
-	struct ipa_proxy_conn *bsc_oml_conn;
-	struct ipa_proxy_conn *bsc_rsl_conn[MAX_TRX];
-
-	/* UDP sockets for BTS and BSC injection */
-	struct osmo_fd udp_bts_fd;
-	struct osmo_fd udp_bsc_fd;
-
-	/* NS data */
-	struct in_addr bts_addr;
-	struct osmo_fd gprs_ns_fd;
-	int gprs_local_port;
-	uint16_t gprs_orig_port;
-	uint32_t gprs_orig_ip;
-
-	char *id_tags[256];
-	uint8_t *id_resp;
-	unsigned int id_resp_len;
-};
-
-enum ipp_fd_type {
-	OML_FROM_BTS = 1,
-	RSL_FROM_BTS = 2,
-	OML_TO_BSC = 3,
-	RSL_TO_BSC = 4,
-	UDP_TO_BTS = 5,
-	UDP_TO_BSC = 6,
-};
-
-/* some of the code against we link from OpenBSC needs this */
-void *tall_bsc_ctx;
-
-static char *listen_ipaddr;
-static char *bsc_ipaddr;
-static char *gprs_ns_ipaddr;
-
-static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what);
-
-#define PROXY_ALLOC_SIZE	1200
-
-static struct ipa_bts_conn *find_bts_by_unitid(struct ipa_proxy *ipp,
-						uint16_t site_id,
-						uint16_t bts_id)
-{
-	struct ipa_bts_conn *ipbc;
-
-	llist_for_each_entry(ipbc, &ipp->bts_list, list) {
-		if (ipbc->unit_id.site_id == site_id &&
-		    ipbc->unit_id.bts_id == bts_id)
-			return ipbc;
-	}
-
-	return NULL;
-}
-
-struct ipa_proxy_conn *alloc_conn(void)
-{
-	struct ipa_proxy_conn *ipc;
-
-	ipc = talloc_zero(tall_bsc_ctx, struct ipa_proxy_conn);
-	if (!ipc)
-		return NULL;
-
-	INIT_LLIST_HEAD(&ipc->tx_queue);
-
-	return ipc;
-}
-
-static int store_idtags(struct ipa_bts_conn *ipbc, struct tlv_parsed *tlvp)
-{
-	unsigned int i, len;
-
-	for (i = 0; i <= 0xff; i++) {
-		if (!TLVP_PRESENT(tlvp, i))
-			continue;
-
-		len = TLVP_LEN(tlvp, i);
-#if 0
-		if (!ipbc->id_tags[i])
-			ipbc->id_tags[i] = talloc_size(tall_bsc_ctx, len);
-		else
-#endif
-			ipbc->id_tags[i] = talloc_realloc_size(ipbc,
-							  ipbc->id_tags[i], len);
-		if (!ipbc->id_tags[i])
-			return -ENOMEM;
-
-		memset(ipbc->id_tags[i], 0, len);
-		//memcpy(ipbc->id_tags[i], TLVP_VAL(tlvp, i), len);
-	}
-	return 0;
-}
-
-
-static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data);
-
-#define logp_ipbc_uid(ss, lvl, ipbc, trx_id) _logp_ipbc_uid(ss, lvl, __FILE__, __LINE__, ipbc, trx_id)
-
-static void _logp_ipbc_uid(unsigned int ss, unsigned int lvl, char *file, int line,
-			   struct ipa_bts_conn *ipbc, uint8_t trx_id)
-{
-	if (ipbc)
-		logp2(ss, lvl, file, line, 0, "(%u/%u/%u) ", ipbc->unit_id.site_id,
-		     ipbc->unit_id.bts_id, trx_id);
-	else
-		logp2(ss, lvl, file, line, 0, "unknown ");
-}
-
-static int handle_udp_read(struct osmo_fd *bfd)
-{
-	struct ipa_bts_conn *ipbc = bfd->data;
-	struct ipa_proxy_conn *other_conn = NULL;
-	struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP UDP");
-	struct ipaccess_head *hh;
-	int ret;
-
-	/* with UDP sockets, we cannot read partial packets but have to read
-	 * all of it in one go */
-	hh = (struct ipaccess_head *) msg->data;
-	ret = recv(bfd->fd, msg->data, msg->data_len, 0);
-	if (ret < 0) {
-		if (errno != EAGAIN)
-			LOGP(DLINP, LOGL_ERROR, "recv error  %s\n", strerror(errno));
-		msgb_free(msg);
-		return ret;
-	}
-	if (ret == 0) {
-		DEBUGP(DLINP, "UDP peer disappeared, dead socket\n");
-		osmo_fd_unregister(bfd);
-		close(bfd->fd);
-		bfd->fd = -1;
-		msgb_free(msg);
-		return -EIO;
-	}
-	if (ret < sizeof(*hh)) {
-		DEBUGP(DLINP, "could not even read header!?!\n");
-		msgb_free(msg);
-		return -EIO;
-	}
-	msgb_put(msg, ret);
-	msg->l2h = msg->data + sizeof(*hh);
-	DEBUGP(DLMI, "UDP RX: %s\n", osmo_hexdump(msg->data, msg->len));
-
-	if (hh->len != msg->len - sizeof(*hh)) {
-		DEBUGP(DLINP, "length (%u/%u) disagrees with header(%u)\n",
-			msg->len, msg->len - 3, hh->len);
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	switch (bfd->priv_nr & 0xff) {
-	case UDP_TO_BTS:
-		/* injection towards BTS */
-		switch (hh->proto) {
-		case IPAC_PROTO_RSL:
-			/* FIXME: what to do about TRX > 0 */
-			other_conn = ipbc->rsl_conn[0];
-			break;
-		default:
-			DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to "
-				"OML FD\n", hh->proto);
-			/* fall through */
-		case IPAC_PROTO_IPACCESS:
-		case IPAC_PROTO_OML:
-			other_conn = ipbc->oml_conn;
-			break;
-		}
-		break;
-	case UDP_TO_BSC:
-		/* injection towards BSC */
-		switch (hh->proto) {
-		case IPAC_PROTO_RSL:
-			/* FIXME: what to do about TRX > 0 */
-			other_conn = ipbc->bsc_rsl_conn[0];
-			break;
-		default:
-			DEBUGP(DLINP, "Unknown protocol 0x%02x, sending to "
-				"OML FD\n", hh->proto);
-			/* fall through */
-		case IPAC_PROTO_IPACCESS:
-		case IPAC_PROTO_OML:
-			other_conn = ipbc->bsc_oml_conn;
-			break;
-		}
-		break;
-	default:
-		DEBUGP(DLINP, "Unknown filedescriptor priv_nr=%04x\n", bfd->priv_nr);
-		break;
-	}
-
-	if (other_conn) {
-		/* enqueue the message for TX on the respective FD */
-		msgb_enqueue(&other_conn->tx_queue, msg);
-		other_conn->fd.when |= BSC_FD_WRITE;
-	} else
-		msgb_free(msg);
-
-	return 0;
-}
-
-static int handle_udp_write(struct osmo_fd *bfd)
-{
-	/* not implemented yet */
-	bfd->when &= ~BSC_FD_WRITE;
-
-	return -EIO;
-}
-
-/* callback from select.c in case one of the fd's can be read/written */
-static int udp_fd_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	int rc = 0;
-
-	if (what & BSC_FD_READ)
-		rc = handle_udp_read(bfd);
-	if (what & BSC_FD_WRITE)
-		rc = handle_udp_write(bfd);
-
-	return rc;
-}
-
-
-static int ipbc_alloc_connect(struct ipa_proxy_conn *ipc, struct osmo_fd *bfd,
-			      uint16_t site_id, uint16_t bts_id,
-			      uint16_t trx_id, struct tlv_parsed *tlvp,
-			      struct msgb *msg)
-{
-	struct ipa_bts_conn *ipbc;
-	uint16_t udp_port;
-	int ret = 0;
-	struct sockaddr_in sin;
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-	DEBUGP(DLINP, "(%u/%u/%u) New BTS connection: ",
-		site_id, bts_id, trx_id);
-
-	/* OML needs to be established before RSL */
-	if ((bfd->priv_nr & 0xff) != OML_FROM_BTS) {
-		DEBUGPC(DLINP, "Not a OML connection ?!?\n");
-		return -EIO;
-	}
-
-	/* allocate new BTS connection data structure */
-	ipbc = talloc_zero(tall_bsc_ctx, struct ipa_bts_conn);
-	if (!ipbc) {
-		ret = -ENOMEM;
-		goto err_out;
-	}
-
-	DEBUGPC(DLINP, "Created BTS Conn data structure\n");
-	ipbc->ipp = ipp;
-	ipbc->unit_id.site_id = site_id;
-	ipbc->unit_id.bts_id = bts_id;
-	ipbc->oml_conn = ipc;
-	ipc->bts_conn = ipbc;
-
-	/* store the content of the ID TAGS for later reference */
-	store_idtags(ipbc, tlvp);
-	ipbc->id_resp_len = msg->len;
-	ipbc->id_resp = talloc_size(tall_bsc_ctx, ipbc->id_resp_len);
-	memcpy(ipbc->id_resp, msg->data, ipbc->id_resp_len);
-
-	/* Create OML TCP connection towards BSC */
-	sin.sin_port = htons(IPA_TCP_PORT_OML);
-	ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
-	if (!ipbc->bsc_oml_conn) {
-		ret = -EIO;
-		goto err_bsc_conn;
-	}
-
-	DEBUGP(DLINP, "(%u/%u/%u) OML Connected to BSC\n",
-		site_id, bts_id, trx_id);
-
-	/* Create UDP socket for BTS packet injection */
-	udp_port = 10000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bts_fd, IPPROTO_UDP, INADDR_ANY, udp_port,
-			UDP_TO_BTS, udp_fd_cb, ipbc);
-	if (ret < 0)
-		goto err_udp_bts;
-	DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection "
-		"towards BTS at port %u\n", site_id, bts_id, trx_id, udp_port);
-
-	/* Create UDP socket for BSC packet injection */
-	udp_port = 20000 + (site_id % 1000)*100 + (bts_id % 100);
-	ret = make_sock(&ipbc->udp_bsc_fd, IPPROTO_UDP, INADDR_ANY, udp_port,
-			UDP_TO_BSC, udp_fd_cb, ipbc);
-	if (ret < 0)
-		goto err_udp_bsc;
-	DEBUGP(DLINP, "(%u/%u/%u) Created UDP socket for injection "
-		"towards BSC at port %u\n", site_id, bts_id, trx_id, udp_port);
-
-
-	/* GPRS NS related code */
-	if (gprs_ns_ipaddr) {
-		struct sockaddr_in sock;
-		socklen_t len = sizeof(sock);
-		struct in_addr addr;
-		uint32_t ip;
-
-		inet_aton(listen_ipaddr, &addr);
-		ip = ntohl(addr.s_addr); /* make_sock() needs host byte order */
-		ret = make_sock(&ipbc->gprs_ns_fd, IPPROTO_UDP, ip, 0, 0,
-				gprs_ns_cb, ipbc);
-		if (ret < 0) {
-			LOGP(DLINP, LOGL_ERROR, "Creating the GPRS socket failed.\n");
-			goto err_udp_bsc;
-		}
-
-		ret = getsockname(ipbc->gprs_ns_fd.fd, (struct sockaddr* ) &sock, &len);
-		ipbc->gprs_local_port = ntohs(sock.sin_port);
-		LOGP(DLINP, LOGL_NOTICE,
-			"Created GPRS NS Socket. Listening on: %s:%d\n",
-			inet_ntoa(sock.sin_addr), ipbc->gprs_local_port);
-
-		ret = getpeername(bfd->fd, (struct sockaddr* ) &sock, &len);
-		ipbc->bts_addr = sock.sin_addr;
-	}
-
-	llist_add(&ipbc->list, &ipp->bts_list);
-
-	return 0;
-
-err_udp_bsc:
-	osmo_fd_unregister(&ipbc->udp_bts_fd);
-err_udp_bts:
-	osmo_fd_unregister(&ipbc->bsc_oml_conn->fd);
-	close(ipbc->bsc_oml_conn->fd.fd);
-	talloc_free(ipbc->bsc_oml_conn);
-	ipbc->bsc_oml_conn = NULL;
-err_bsc_conn:
-	talloc_free(ipbc->id_resp);
-	talloc_free(ipbc);
-#if 0
-	osmo_fd_unregister(bfd);
-	close(bfd->fd);
-	talloc_free(bfd);
-#endif
-err_out:
-	return ret;
-}
-
-static int ipaccess_rcvmsg(struct ipa_proxy_conn *ipc, struct msgb *msg,
-			   struct osmo_fd *bfd)
-{
-	struct tlv_parsed tlvp;
-	uint8_t msg_type = *(msg->l2h);
-	struct ipaccess_unit unit_data;
-	struct ipa_bts_conn *ipbc;
-	int ret = 0;
-
-	switch (msg_type) {
-	case IPAC_MSGT_PING:
-		ret = ipa_ccm_send_pong(bfd->fd);
-		break;
-	case IPAC_MSGT_PONG:
-		DEBUGP(DLMI, "PONG!\n");
-		break;
-	case IPAC_MSGT_ID_RESP:
-		DEBUGP(DLMI, "ID_RESP ");
-		/* parse tags, search for Unit ID */
-		ipa_ccm_idtag_parse(&tlvp, (uint8_t *)msg->l2h + 2,
-				     msgb_l2len(msg)-2);
-		DEBUGP(DLMI, "\n");
-
-		if (!TLVP_PRESENT(&tlvp, IPAC_IDTAG_UNIT)) {
-			LOGP(DLINP, LOGL_ERROR, "No Unit ID in ID RESPONSE !?!\n");
-			return -EIO;
-		}
-
-		/* lookup BTS, create sign_link, ... */
-		memset(&unit_data, 0, sizeof(unit_data));
-		ipa_parse_unitid((char *)TLVP_VAL(&tlvp, IPAC_IDTAG_UNIT),
-				      &unit_data);
-		ipbc = find_bts_by_unitid(ipp, unit_data.site_id, unit_data.bts_id);
-		if (!ipbc) {
-			/* We have not found an ipbc (per-bts proxy instance)
-			 * for this BTS yet.  The first connection of a new BTS must
-			 * be a OML connection.  We allocate the associated data structures,
-			 * and try to connect to the remote end */
-
-			return ipbc_alloc_connect(ipc, bfd, unit_data.site_id,
-						  unit_data.bts_id,
-						  unit_data.trx_id, &tlvp, msg);
-			/* if this fails, the caller will clean up bfd */
-		} else {
-			struct sockaddr_in sin;
-			memset(&sin, 0, sizeof(sin));
-			sin.sin_family = AF_INET;
-			inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-			DEBUGP(DLINP, "Identified BTS %u/%u/%u\n",
-				unit_data.site_id, unit_data.bts_id, unit_data.trx_id);
-
-			if ((bfd->priv_nr & 0xff) != RSL_FROM_BTS) {
-				LOGP(DLINP, LOGL_ERROR, "Second OML connection from "
-				     "same BTS ?!?\n");
-				return 0;
-			}
-
-			if (unit_data.trx_id >= MAX_TRX) {
-				LOGP(DLINP, LOGL_ERROR, "We don't support more "
-				     "than %u TRX\n", MAX_TRX);
-				return -EINVAL;
-			}
-
-			ipc->bts_conn = ipbc;
-			/* store TRX number in higher 8 bit of the bfd private number */
-			bfd->priv_nr |= unit_data.trx_id << 8;
-			ipbc->rsl_conn[unit_data.trx_id] = ipc;
-
-			/* Create RSL TCP connection towards BSC */
-			sin.sin_port = htons(IPA_TCP_PORT_RSL);
-			ipbc->bsc_rsl_conn[unit_data.trx_id] =
-				connect_bsc(&sin, RSL_TO_BSC | (unit_data.trx_id << 8), ipbc);
-			if (!ipbc->bsc_oml_conn)
-				return -EIO;
-			DEBUGP(DLINP, "(%u/%u/%u) Connected RSL to BSC\n",
-				unit_data.site_id, unit_data.bts_id, unit_data.trx_id);
-		}
-		break;
-	case IPAC_MSGT_ID_GET:
-		DEBUGP(DLMI, "ID_GET\n");
-		if ((bfd->priv_nr & 0xff) != OML_TO_BSC &&
-		    (bfd->priv_nr & 0xff) != RSL_TO_BSC) {
-			DEBUGP(DLINP, "IDentity REQuest from BTS ?!?\n");
-			return -EIO;
-		}
-		ipbc = ipc->bts_conn;
-		if (!ipbc) {
-			DEBUGP(DLINP, "ID_GET from BSC before we have ID_RESP from BTS\n");
-			return -EIO;
-		}
-		ret = write(bfd->fd, ipbc->id_resp, ipbc->id_resp_len);
-		if (ret != ipbc->id_resp_len) {
-			LOGP(DLINP, LOGL_ERROR, "Partial write: %d of %d\n",
-			     ret, ipbc->id_resp_len);
-			return -EIO;
-		}
-		ret = 0;
-		break;
-	case IPAC_MSGT_ID_ACK:
-		DEBUGP(DLMI, "ID_ACK? -> ACK!\n");
-		ret = ipa_ccm_send_id_ack(bfd->fd);
-		break;
-	default:
-		LOGP(DLMI, LOGL_ERROR, "Unhandled IPA type; %d\n", msg_type);
-		return 1;
-		break;
-	}
-	return ret;
-}
-
-struct msgb *ipaccess_proxy_read_msg(struct osmo_fd *bfd, int *error)
-{
-	struct msgb *msg = msgb_alloc(PROXY_ALLOC_SIZE, "Abis/IP");
-	struct ipaccess_head *hh;
-	int len, ret = 0;
-
-	if (!msg) {
-		*error = -ENOMEM;
-		return NULL;
-	}
-
-	/* first read our 3-byte header */
-	hh = (struct ipaccess_head *) msg->data;
-	ret = recv(bfd->fd, msg->data, 3, 0);
-	if (ret < 0) {
-		if (errno != EAGAIN)
-			LOGP(DLINP, LOGL_ERROR, "recv error: %s\n", strerror(errno));
-		msgb_free(msg);
-		*error = ret;
-		return NULL;
-	} else if (ret == 0) {
-		msgb_free(msg);
-		*error = ret;
-		return NULL;
-	}
-
-	msgb_put(msg, ret);
-
-	/* then read te length as specified in header */
-	msg->l2h = msg->data + sizeof(*hh);
-	len = ntohs(hh->len);
-	ret = recv(bfd->fd, msg->l2h, len, 0);
-	if (ret < len) {
-		LOGP(DLINP, LOGL_ERROR, "short read!\n");
-		msgb_free(msg);
-		*error = -EIO;
-		return NULL;
-	}
-	msgb_put(msg, ret);
-
-	return msg;
-}
-
-static struct ipa_proxy_conn *ipc_by_priv_nr(struct ipa_bts_conn *ipbc,
-					     unsigned int priv_nr)
-{
-	struct ipa_proxy_conn *bsc_conn;
-	unsigned int trx_id = priv_nr >> 8;
-
-	switch (priv_nr & 0xff) {
-	case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
-		bsc_conn = ipbc->bsc_oml_conn;
-		break;
-	case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
-		bsc_conn = ipbc->bsc_rsl_conn[trx_id];
-		break;
-	case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
-		bsc_conn = ipbc->oml_conn;
-		break;
-	case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
-		bsc_conn = ipbc->rsl_conn[trx_id];
-		break;
-	default:
-		bsc_conn = NULL;
-		break;
-	}
-	return bsc_conn;
-}
-
-static void reconn_tmr_cb(void *data)
-{
-	struct ipa_proxy *ipp = data;
-	struct ipa_bts_conn *ipbc;
-	struct sockaddr_in sin;
-	int i;
-
-	DEBUGP(DLINP, "Running reconnect timer\n");
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	inet_aton(bsc_ipaddr, &sin.sin_addr);
-
-	llist_for_each_entry(ipbc, &ipp->bts_list, list) {
-		/* if OML to BSC is dead, try to restore it */
-		if (ipbc->oml_conn && !ipbc->bsc_oml_conn) {
-			sin.sin_port = htons(IPA_TCP_PORT_OML);
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0);
-			LOGPC(DLINP, LOGL_NOTICE, "OML Trying to reconnect\n");
-			ipbc->bsc_oml_conn = connect_bsc(&sin, OML_TO_BSC, ipbc);
-			if (!ipbc->bsc_oml_conn)
-				goto reschedule;
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, 0);
-			LOGPC(DLINP, LOGL_NOTICE, "OML Reconnected\n");
-		}
-		/* if we (still) don't have a OML connection, skip RSL */
-		if (!ipbc->oml_conn || !ipbc->bsc_oml_conn)
-			continue;
-
-		for (i = 0; i < ARRAY_SIZE(ipbc->rsl_conn); i++) {
-			unsigned int priv_nr;
-			/* don't establish RSL links which we don't have */
-			if (!ipbc->rsl_conn[i])
-				continue;
-			if (ipbc->bsc_rsl_conn[i])
-				continue;
-			priv_nr = ipbc->rsl_conn[i]->fd.priv_nr;
-			priv_nr &= ~0xff;
-			priv_nr |= RSL_TO_BSC;
-			sin.sin_port = htons(IPA_TCP_PORT_RSL);
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "RSL Trying to reconnect\n");
-			ipbc->bsc_rsl_conn[i] = connect_bsc(&sin, priv_nr, ipbc);
-			if (!ipbc->bsc_rsl_conn[i])
-				goto reschedule;
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "RSL Reconnected\n");
-		}
-	}
-	return;
-
-reschedule:
-	osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-}
-
-static void handle_dead_socket(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;		/* local conn */
-	struct ipa_proxy_conn *bsc_conn;		/* remote conn */
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	unsigned int trx_id = bfd->priv_nr >> 8;
-	struct msgb *msg, *msg2;
-
-	osmo_fd_unregister(bfd);
-	close(bfd->fd);
-	bfd->fd = -1;
-
-	/* FIXME: clear tx_queue, remove all references, etc. */
-	llist_for_each_entry_safe(msg, msg2, &ipc->tx_queue, list)
-		msgb_free(msg);
-
-	switch (bfd->priv_nr & 0xff) {
-	case OML_FROM_BTS: /* incoming OML data from BTS, forward to BSC OML */
-		/* The BTS started a connection with us but we got no
-		 * IPAC_MSGT_ID_RESP message yet, in that scenario we did not
-		 * allocate the ipa_bts_conn structure. */
-		if (ipbc == NULL)
-			break;
-		ipbc->oml_conn = NULL;
-		bsc_conn = ipbc->bsc_oml_conn;
-		/* close the connection to the BSC */
-		osmo_fd_unregister(&bsc_conn->fd);
-		close(bsc_conn->fd.fd);
-		llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
-			msgb_free(msg);
-		talloc_free(bsc_conn);
-		ipbc->bsc_oml_conn = NULL;
-		/* FIXME: do we need to delete the entire ipbc ? */
-		break;
-	case RSL_FROM_BTS: /* incoming RSL data from BTS, forward to BSC RSL */
-		ipbc->rsl_conn[trx_id] = NULL;
-		bsc_conn = ipbc->bsc_rsl_conn[trx_id];
-		/* close the connection to the BSC */
-		osmo_fd_unregister(&bsc_conn->fd);
-		close(bsc_conn->fd.fd);
-		llist_for_each_entry_safe(msg, msg2, &bsc_conn->tx_queue, list)
-			msgb_free(msg);
-		talloc_free(bsc_conn);
-		ipbc->bsc_rsl_conn[trx_id] = NULL;
-		break;
-	case OML_TO_BSC: /* incoming OML data from BSC, forward to BTS OML */
-		ipbc->bsc_oml_conn = NULL;
-		bsc_conn = ipbc->oml_conn;
-		/* start reconnect timer */
-		osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-		break;
-	case RSL_TO_BSC: /* incoming RSL data from BSC, forward to BTS RSL */
-		ipbc->bsc_rsl_conn[trx_id] = NULL;
-		bsc_conn = ipbc->rsl_conn[trx_id];
-		/* start reconnect timer */
-		osmo_timer_schedule(&ipp->reconn_timer, 5, 0);
-		break;
-	default:
-		bsc_conn = NULL;
-		break;
-	}
-
-	talloc_free(ipc);
-}
-
-static void patch_gprs_msg(struct ipa_bts_conn *ipbc, int priv_nr, struct msgb *msg)
-{
-	uint8_t *nsvci;
-
-	if ((priv_nr & 0xff) != OML_FROM_BTS && (priv_nr & 0xff) != OML_TO_BSC)
-		return;
-
-	if (msgb_l2len(msg) != 39)
-		return;
-
-	/*
-	 * Check if this is a IPA Set Attribute or IPA Set Attribute ACK
-	 * and if the FOM Class is GPRS NSVC0 and then we will patch it.
-	 *
-	 * The patch assumes the message looks like the one from the trace
-	 * but we only match messages with a specific size anyway... So
-	 * this hack should work just fine.
-	 */
-
-	if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
-	    msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
-	    msg->l2h[18] == 0xf5 && msg->l2h[19] == 0xf2) {
-		nsvci = &msg->l2h[23];
-		ipbc->gprs_orig_port =  *(uint16_t *)(nsvci+8);
-		ipbc->gprs_orig_ip = *(uint32_t *)(nsvci+10);
-		*(uint16_t *)(nsvci+8) = htons(ipbc->gprs_local_port);
-		*(uint32_t *)(nsvci+10) = ipbc->ipp->listen_addr.s_addr;
-	} else if (msg->l2h[0] == 0x10 && msg->l2h[1] == 0x80 &&
-	    msg->l2h[2] == 0x00 && msg->l2h[3] == 0x15 &&
-	    msg->l2h[18] == 0xf6 && msg->l2h[19] == 0xf2) {
-		nsvci = &msg->l2h[23];
-		*(uint16_t *)(nsvci+8) = ipbc->gprs_orig_port;
-		*(uint32_t *)(nsvci+10) = ipbc->gprs_orig_ip;
-	}
-}
-
-static int handle_tcp_read(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	struct ipa_proxy_conn *bsc_conn;
-	struct msgb *msg;
-	struct ipaccess_head *hh;
-	int ret = 0;
-	char *btsbsc;
-
-	if ((bfd->priv_nr & 0xff) <= 2)
-		btsbsc = "BTS";
-	else
-		btsbsc = "BSC";
-
-	msg = ipaccess_proxy_read_msg(bfd, &ret);
-	if (!msg) {
-		if (ret == 0) {
-			logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
-			LOGPC(DLINP, LOGL_NOTICE, "%s disappeared, "
-			     "dead socket\n", btsbsc);
-			handle_dead_socket(bfd);
-		}
-		return ret;
-	}
-
-	msgb_put(msg, ret);
-	logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
-	DEBUGPC(DLMI, "RX<-%s: %s\n", btsbsc, osmo_hexdump(msg->data, msg->len));
-
-	hh = (struct ipaccess_head *) msg->data;
-	if (hh->proto == IPAC_PROTO_IPACCESS) {
-		ret = ipaccess_rcvmsg(ipc, msg, bfd);
-		if (ret < 0) {
-			osmo_fd_unregister(bfd);
-			close(bfd->fd);
-			bfd->fd = -1;
-			talloc_free(bfd);
-			msgb_free(msg);
-			return ret;
-		} else if (ret == 0) {
-			/* we do not forward parts of the CCM protocol
-			 * through the proxy but rather terminate it ourselves. */
-			msgb_free(msg);
-			return ret;
-		}
-	}
-
-	if (!ipbc) {
-		LOGP(DLINP, LOGL_ERROR,
-		     "received %s packet but no ipc->bts_conn?!?\n", btsbsc);
-		msgb_free(msg);
-		return -EIO;
-	}
-
-	bsc_conn = ipc_by_priv_nr(ipbc, bfd->priv_nr);
-	if (bsc_conn) {
-		if (gprs_ns_ipaddr)
-			patch_gprs_msg(ipbc, bfd->priv_nr, msg);
-		/* enqueue packet towards BSC */
-		msgb_enqueue(&bsc_conn->tx_queue, msg);
-		/* mark respective filedescriptor as 'we want to write' */
-		bsc_conn->fd.when |= BSC_FD_WRITE;
-	} else {
-		logp_ipbc_uid(DLINP, LOGL_INFO, ipbc, bfd->priv_nr >> 8);
-		LOGPC(DLINP, LOGL_INFO, "Dropping packet from %s, "
-		     "since remote connection is dead\n", btsbsc);
-		msgb_free(msg);
-	}
-
-	return ret;
-}
-
-/* a TCP socket is ready to be written to */
-static int handle_tcp_write(struct osmo_fd *bfd)
-{
-	struct ipa_proxy_conn *ipc = bfd->data;
-	struct ipa_bts_conn *ipbc = ipc->bts_conn;
-	struct llist_head *lh;
-	struct msgb *msg;
-	char *btsbsc;
-	int ret;
-
-	if ((bfd->priv_nr & 0xff) <= 2)
-		btsbsc = "BTS";
-	else
-		btsbsc = "BSC";
-
-
-	/* get the next msg for this timeslot */
-	if (llist_empty(&ipc->tx_queue)) {
-		bfd->when &= ~BSC_FD_WRITE;
-		return 0;
-	}
-	lh = ipc->tx_queue.next;
-	llist_del(lh);
-	msg = llist_entry(lh, struct msgb, list);
-
-	logp_ipbc_uid(DLMI, LOGL_DEBUG, ipbc, bfd->priv_nr >> 8);
-	DEBUGPC(DLMI, "TX %04x: %s\n", bfd->priv_nr,
-		osmo_hexdump(msg->data, msg->len));
-
-	ret = send(bfd->fd, msg->data, msg->len, 0);
-	msgb_free(msg);
-
-	if (ret == 0) {
-		logp_ipbc_uid(DLINP, LOGL_NOTICE, ipbc, bfd->priv_nr >> 8);
-		LOGP(DLINP, LOGL_NOTICE, "%s disappeared, dead socket\n", btsbsc);
-		handle_dead_socket(bfd);
-	}
-
-	return ret;
-}
-
-/* callback from select.c in case one of the fd's can be read/written */
-static int proxy_ipaccess_fd_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	int rc = 0;
-
-	if (what & BSC_FD_READ) {
-		rc = handle_tcp_read(bfd);
-		if (rc < 0)
-			return rc;
-	}
-	if (what & BSC_FD_WRITE)
-		rc = handle_tcp_write(bfd);
-
-	return rc;
-}
-
-/* callback of the listening filedescriptor */
-static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what)
-{
-	int ret;
-	struct ipa_proxy_conn *ipc;
-	struct osmo_fd *bfd;
-	struct sockaddr_in sa;
-	socklen_t sa_len = sizeof(sa);
-
-	if (!(what & BSC_FD_READ))
-		return 0;
-
-	ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len);
-	if (ret < 0) {
-		perror("accept");
-		return ret;
-	}
-	DEBUGP(DLINP, "accept()ed new %s link from %s\n",
-		(listen_bfd->priv_nr & 0xff) == OML_FROM_BTS ? "OML" : "RSL",
-		inet_ntoa(sa.sin_addr));
-
-	ipc = alloc_conn();
-	if (!ipc) {
-		close(ret);
-		return -ENOMEM;
-	}
-
-	bfd = &ipc->fd;
-	bfd->fd = ret;
-	bfd->data = ipc;
-	bfd->priv_nr = listen_bfd->priv_nr;
-	bfd->cb = proxy_ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ;
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "could not register FD\n");
-		close(bfd->fd);
-		talloc_free(ipc);
-		return ret;
-	}
-
-	/* Request ID. FIXME: request LOCATION, HW/SW VErsion, Unit Name, Serno */
-	ret = ipa_ccm_send_id_req(bfd->fd);
-
-	return 0;
-}
-
-static void send_ns(int fd, const char *buf, int size, struct in_addr ip, int port)
-{
-	int ret;
-	struct sockaddr_in addr;
-	socklen_t len = sizeof(addr);
-	memset(&addr, 0, sizeof(addr));
-
-	addr.sin_family = AF_INET;
-	addr.sin_port = htons(port);
-	addr.sin_addr = ip;
-
-	ret = sendto(fd, buf, size, 0, (struct sockaddr *) &addr, len);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to forward GPRS message.\n");
-	}
-}
-
-static int gprs_ns_cb(struct osmo_fd *bfd, unsigned int what)
-{
-	struct ipa_bts_conn *bts;
-	char buf[4096];
-	int ret;
-	struct sockaddr_in sock;
-	socklen_t len = sizeof(sock);
-
-	/* 1. get the data... */
-	ret = recvfrom(bfd->fd, buf, sizeof(buf), 0, (struct sockaddr *) &sock, &len);
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Failed to recv GPRS NS msg: %s.\n", strerror(errno));
-		return -1;
-	}
-
-	bts = bfd->data;
-
-	/* 2. figure out where to send it to */
-	if (memcmp(&sock.sin_addr, &ipp->gprs_addr, sizeof(sock.sin_addr)) == 0) {
-		LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from network.\n");
-		send_ns(bfd->fd, buf, ret, bts->bts_addr, 23000);
-	} else if (memcmp(&sock.sin_addr, &bts->bts_addr, sizeof(sock.sin_addr)) == 0) {
-		LOGP(DLINP, LOGL_DEBUG, "GPRS NS msg from BTS.\n");
-		send_ns(bfd->fd, buf, ret, ipp->gprs_addr, 23000);
-	} else {
-		LOGP(DLINP, LOGL_ERROR, "Unknown GPRS source: %s\n", inet_ntoa(sock.sin_addr));
-	}
-
-	return 0;
-}
-
-/* Actively connect to a BSC.  */
-static struct ipa_proxy_conn *connect_bsc(struct sockaddr_in *sa, int priv_nr, void *data)
-{
-	struct ipa_proxy_conn *ipc;
-	struct osmo_fd *bfd;
-	int ret, on = 1;
-
-	ipc = alloc_conn();
-	if (!ipc)
-		return NULL;
-
-	ipc->bts_conn = data;
-
-	bfd = &ipc->fd;
-	bfd->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	bfd->cb = ipaccess_fd_cb;
-	bfd->when = BSC_FD_READ | BSC_FD_WRITE;
-	bfd->data = ipc;
-	bfd->priv_nr = priv_nr;
-
-	if (bfd->fd < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not create socket: %s\n",
-			strerror(errno));
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	ret = setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not set socket option\n");
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	ret = connect(bfd->fd, (struct sockaddr *) sa, sizeof(*sa));
-	if (ret < 0) {
-		LOGP(DLINP, LOGL_ERROR, "Could not connect socket: %s\n",
-		     inet_ntoa(sa->sin_addr));
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	/* pre-fill tx_queue with identity request */
-	ret = osmo_fd_register(bfd);
-	if (ret < 0) {
-		close(bfd->fd);
-		talloc_free(ipc);
-		return NULL;
-	}
-
-	return ipc;
-}
-
-static int ipaccess_proxy_setup(void)
-{
-	int ret;
-
-	ipp = talloc_zero(tall_bsc_ctx, struct ipa_proxy);
-	if (!ipp)
-		return -ENOMEM;
-	INIT_LLIST_HEAD(&ipp->bts_list);
-	osmo_timer_setup(&ipp->reconn_timer, reconn_tmr_cb, ipp);
-
-	/* Listen for OML connections */
-	ret = make_sock(&ipp->oml_listen_fd, IPPROTO_TCP, INADDR_ANY,
-			IPA_TCP_PORT_OML, OML_FROM_BTS, listen_fd_cb, NULL);
-	if (ret < 0)
-		return ret;
-
-	/* Listen for RSL connections */
-	ret = make_sock(&ipp->rsl_listen_fd, IPPROTO_TCP, INADDR_ANY,
-			IPA_TCP_PORT_RSL, RSL_FROM_BTS, listen_fd_cb, NULL);
-
-	if (ret < 0)
-		return ret;
-
-	/* Connect the GPRS NS Socket */
-	if (gprs_ns_ipaddr) {
-		inet_aton(gprs_ns_ipaddr, &ipp->gprs_addr);
-		inet_aton(listen_ipaddr, &ipp->listen_addr);
-	}
-
-	return ret;
-}
-
-static void signal_handler(int signal)
-{
-	fprintf(stdout, "signal %u received\n", signal);
-
-	switch (signal) {
-	case SIGABRT:
-		/* in case of abort, we want to obtain a talloc report
-		 * and then return to the caller, who will abort the process */
-	case SIGUSR1:
-		talloc_report_full(tall_bsc_ctx, stderr);
-		break;
-	default:
-		break;
-	}
-}
-
-static void print_help(void)
-{
-	printf(" ipaccess-proxy is a proxy BTS.\n");
-	printf(" -h --help. This help text.\n");
-	printf(" -l --listen IP. The ip to listen to.\n");
-	printf(" -b --bsc IP. The BSC IP address.\n");
-	printf(" -g --gprs IP. Take GPRS NS from that IP.\n");
-	printf("\n");
-	printf(" -s --disable-color. Disable the color inside the logging message.\n");
-	printf(" -e --log-level number. Set the global loglevel.\n");
-	printf(" -T --timestamp. Prefix every log message with a timestamp.\n");
-	printf(" -V --version. Print the version of OpenBSC.\n");
-}
-
-static void print_usage(void)
-{
-	printf("Usage: ipaccess-proxy [options]\n");
-}
-
-enum {
-	IPA_PROXY_OPT_LISTEN_NONE	= 0,
-	IPA_PROXY_OPT_LISTEN_IP		= (1 << 0),
-	IPA_PROXY_OPT_BSC_IP		= (1 << 1),
-};
-
-static void handle_options(int argc, char** argv)
-{
-	int options_mask = 0;
-
-	/* disable explicit missing arguments error output from getopt_long */
-	opterr = 0;
-
-	while (1) {
-		int option_index = 0, c;
-		static struct option long_options[] = {
-			{"help", 0, 0, 'h'},
-			{"disable-color", 0, 0, 's'},
-			{"timestamp", 0, 0, 'T'},
-			{"log-level", 1, 0, 'e'},
-			{"listen", 1, 0, 'l'},
-			{"bsc", 1, 0, 'b'},
-			{0, 0, 0, 0}
-		};
-
-		c = getopt_long(argc, argv, "hsTe:l:b:g:",
-				long_options, &option_index);
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-			print_usage();
-			print_help();
-			exit(0);
-		case 'l':
-			listen_ipaddr = optarg;
-			options_mask |= IPA_PROXY_OPT_LISTEN_IP;
-			break;
-		case 'b':
-			bsc_ipaddr = optarg;
-			options_mask |= IPA_PROXY_OPT_BSC_IP;
-			break;
-		case 'g':
-			gprs_ns_ipaddr = optarg;
-			break;
-		case 's':
-			log_set_use_color(osmo_stderr_target, 0);
-			break;
-		case 'T':
-			log_set_print_timestamp(osmo_stderr_target, 1);
-			break;
-		case 'e':
-			log_set_log_level(osmo_stderr_target, atoi(optarg));
-			break;
-		case '?':
-			if (optopt) {
-				printf("ERROR: missing mandatory argument "
-				       "for `%s' option\n", argv[optind-1]);
-			} else {
-				printf("ERROR: unknown option `%s'\n",
-					argv[optind-1]);
-			}
-			print_usage();
-			print_help();
-			exit(EXIT_FAILURE);
-			break;
-		default:
-			/* ignore */
-			break;
-		}
-	}
-	if ((options_mask & (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP))
-		 != (IPA_PROXY_OPT_LISTEN_IP | IPA_PROXY_OPT_BSC_IP)) {
-		printf("ERROR: You have to specify `--listen' and `--bsc' "
-		       "options at least.\n");
-		print_usage();
-		print_help();
-		exit(EXIT_FAILURE);
-	}
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	tall_bsc_ctx = talloc_named_const(NULL, 1, "ipaccess-proxy");
-	msgb_talloc_ctx_init(tall_bsc_ctx, 0);
-
-	osmo_init_logging(&log_info);
-	log_parse_category_mask(osmo_stderr_target, "DLINP:DLMI");
-
-	handle_options(argc, argv);
-
-	rc = ipaccess_proxy_setup();
-	if (rc < 0)
-		exit(1);
-
-	signal(SIGUSR1, &signal_handler);
-	signal(SIGABRT, &signal_handler);
-	osmo_init_ignore_signals();
-
-	while (1) {
-		osmo_select_main(0);
-	}
-}
diff --git a/openbsc/src/ipaccess/network_listen.c b/openbsc/src/ipaccess/network_listen.c
deleted file mode 100644
index 43d82a9..0000000
--- a/openbsc/src/ipaccess/network_listen.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* ip.access nanoBTS network listen mode */
-
-/* (C) 2009-2010 by Harald Welte <laforge at gnumonks.org>
- *
- * All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <arpa/inet.h>
-
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/gsm/rxlev_stat.h>
-#include <osmocom/gsm/gsm48_ie.h>
-
-#include <openbsc/gsm_data.h>
-#include <openbsc/abis_nm.h>
-#include <openbsc/signal.h>
-#include <openbsc/debug.h>
-#include <osmocom/abis/e1_input.h>
-
-#define WHITELIST_MAX_SIZE ((NUM_ARFCNS*2)+2+1)
-
-int ipac_rxlevstat2whitelist(uint16_t *buf, const struct rxlev_stats *st, uint8_t min_rxlev,
-			     uint16_t max_num_arfcns)
-{
-	int i;
-	unsigned int num_arfcn = 0;
-
-	for (i = NUM_RXLEVS-1; i >= min_rxlev; i--) {
-		int16_t arfcn = -1;
-
-		while ((arfcn = rxlev_stat_get_next(st, i, arfcn)) >= 0) {
-			*buf++ = htons(arfcn);
-			num_arfcn++;
-
-		}
-
-		if (num_arfcn > max_num_arfcns)
-			break;
-	}
-
-	return num_arfcn;
-}
-
-enum ipac_test_state {
-	IPAC_TEST_S_IDLE,
-	IPAC_TEST_S_RQD,
-	IPAC_TEST_S_EXEC,
-	IPAC_TEST_S_PARTIAL,
-};
-
-int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr,
-			const uint8_t *phys_conf, unsigned int phys_conf_len)
-{
-	struct msgb *msg;
-
-	if (trx->ipaccess.test_state != IPAC_TEST_S_IDLE) {
-		fprintf(stderr, "Cannot start test in state %u\n", trx->ipaccess.test_state);
-		return -EINVAL;
-	}
-
-	switch (testnr) {
-	case NM_IPACC_TESTNO_CHAN_USAGE:
-	case NM_IPACC_TESTNO_BCCH_CHAN_USAGE:
-		rxlev_stat_reset(&trx->ipaccess.rxlev_stat);
-		break;
-	}
-
-	msg = msgb_alloc_headroom(phys_conf_len+256, 128, "OML");
-
-	if (phys_conf && phys_conf_len) {
-		uint8_t *payload;
-		/* first put the phys conf header */
-		msgb_tv16_put(msg, NM_ATT_PHYS_CONF, phys_conf_len);
-		payload = msgb_put(msg, phys_conf_len);
-		memcpy(payload, phys_conf, phys_conf_len);
-	}
-
-	abis_nm_perform_test(trx->bts, NM_OC_RADIO_CARRIER, 0, trx->nr, 0xff,
-			     testnr, 1, msg);
-	trx->ipaccess.test_nr = testnr;
-
-	/* FIXME: start safety timer until when test is supposed to complete */
-
-	return 0;
-}
-
-static uint16_t last_arfcn;
-static struct gsm_sysinfo_freq nwl_si_freq[1024];
-#define FREQ_TYPE_NCELL_2	0x04 /* sub channel of SI 2 */
-#define FREQ_TYPE_NCELL_2bis	0x08 /* sub channel of SI 2bis */
-#define FREQ_TYPE_NCELL_2ter	0x10 /* sub channel of SI 2ter */
-
-struct ipacc_ferr_elem {
-	int16_t freq_err;
-	uint8_t freq_qual;
-	uint8_t arfcn;
-} __attribute__((packed));
-
-struct ipacc_cusage_elem {
-	uint16_t arfcn:10,
-		  rxlev:6;
-} __attribute__ ((packed));
-
-static int test_rep(void *_msg)
-{
-	struct msgb *msg = _msg;
-	struct abis_om_fom_hdr *foh = msgb_l3(msg);
-	uint16_t test_rep_len, ferr_list_len;
-	struct ipacc_ferr_elem *ife;
-	struct ipac_bcch_info binfo;
-	struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst;
-	int i, rc;
-
-	DEBUGP(DNM, "TEST REPORT: ");
-
-	if (foh->data[0] != NM_ATT_TEST_NO ||
-	    foh->data[2] != NM_ATT_TEST_REPORT)
-		return -EINVAL;
-
-	DEBUGPC(DNM, "test_no=0x%02x ", foh->data[1]);
-	/* data[2] == NM_ATT_TEST_REPORT */
-	/* data[3..4]: test_rep_len */
-	memcpy(&test_rep_len, &foh->data[3], sizeof(uint16_t));
-	test_rep_len = ntohs(test_rep_len);
-	/* data[5]: ip.access test result */
-	DEBUGPC(DNM, "tst_res=%s\n", ipacc_testres_name(foh->data[5]));
-
-	/* data[6]: ip.access nested IE. 3 == freq_err_list */
-	switch (foh->data[6]) {
-	case NM_IPAC_EIE_FREQ_ERR_LIST:
-		/* data[7..8]: length of ferr_list */
-		memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t));
-		ferr_list_len = ntohs(ferr_list_len);
-
-		/* data[9...]: frequency error list elements */
-		for (i = 0; i < ferr_list_len; i+= sizeof(*ife)) {
-			ife = (struct ipacc_ferr_elem *) (foh->data + 9 + i);
-			DEBUGP(DNM, "==> ARFCN %4u, Frequency Error %6hd\n",
-			ife->arfcn, ntohs(ife->freq_err));
-		}
-		break;
-	case NM_IPAC_EIE_CHAN_USE_LIST:
-		/* data[7..8]: length of ferr_list */
-		memcpy(&ferr_list_len, &foh->data[7], sizeof(uint16_t));
-		ferr_list_len = ntohs(ferr_list_len);
-
-		/* data[9...]: channel usage list elements */
-		for (i = 0; i < ferr_list_len; i+= 2) {
-			uint16_t *cu_ptr = (uint16_t *)(foh->data + 9 + i);
-			uint16_t cu = ntohs(*cu_ptr);
-			uint16_t arfcn = cu & 0x3ff;
-			uint8_t rxlev = cu >> 10;
-			DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n", arfcn, rxlev);
-			rxlev_stat_input(&sign_link->trx->ipaccess.rxlev_stat,
-					 arfcn, rxlev);
-		}
-		break;
-	case NM_IPAC_EIE_BCCH_INFO_TYPE:
-		break;
-	case NM_IPAC_EIE_BCCH_INFO:
-		rc = ipac_parse_bcch_info(&binfo, foh->data+6);
-		if (rc < 0) {
-			DEBUGP(DNM, "BCCH Info parsing failed\n");
-			break;
-		}
-		DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %s, LAC %d CI %d BSIC %u\n",
-			binfo.arfcn, binfo.rx_lev, binfo.rx_qual,
-			osmo_plmn_name(&binfo.cgi.lai.plmn),
-			binfo.cgi.lai.lac, binfo.cgi.cell_identity, binfo.bsic);
-
-		if (binfo.arfcn != last_arfcn) {
-			/* report is on a new arfcn, need to clear channel list */
-			memset(nwl_si_freq, 0, sizeof(nwl_si_freq));
-			last_arfcn = binfo.arfcn;
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2) {
-			DEBUGP(DNM, "BA SI2: %s\n", osmo_hexdump(binfo.ba_list_si2, sizeof(binfo.ba_list_si2)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2, sizeof(binfo.ba_list_si2),
-						0x8c, FREQ_TYPE_NCELL_2);
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2bis) {
-			DEBUGP(DNM, "BA SI2bis: %s\n", osmo_hexdump(binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2bis, sizeof(binfo.ba_list_si2bis),
-						0x8e, FREQ_TYPE_NCELL_2bis);
-		}
-		if (binfo.info_type & IPAC_BINF_NEIGH_BA_SI2ter) {
-			DEBUGP(DNM, "BA SI2ter: %s\n", osmo_hexdump(binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter)));
-			gsm48_decode_freq_list(nwl_si_freq, binfo.ba_list_si2ter, sizeof(binfo.ba_list_si2ter),
-						0x8e, FREQ_TYPE_NCELL_2ter);
-		}
-		for (i = 0; i < ARRAY_SIZE(nwl_si_freq); i++) {
-			if (nwl_si_freq[i].mask)
-				DEBUGP(DNM, "Neighbor Cell on ARFCN %u\n", i);
-		}
-		break;
-	default:
-		break;
-	}
-
-	switch (foh->data[5]) {
-	case NM_IPACC_TESTRES_SUCCESS:
-	case NM_IPACC_TESTRES_STOPPED:
-	case NM_IPACC_TESTRES_TIMEOUT:
-	case NM_IPACC_TESTRES_NO_CHANS:
-		sign_link->trx->ipaccess.test_state = IPAC_TEST_S_IDLE;
-		/* Send signal to notify higher layers of test completion */
-		DEBUGP(DNM, "dispatching S_IPAC_NWL_COMPLETE signal\n");
-		osmo_signal_dispatch(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE,
-					sign_link->trx);
-		break;
-	case NM_IPACC_TESTRES_PARTIAL:
-		sign_link->trx->ipaccess.test_state = IPAC_TEST_S_PARTIAL;
-		break;
-	}
-
-	return 0;
-}
-
-static int nwl_sig_cb(unsigned int subsys, unsigned int signal,
-		     void *handler_data, void *signal_data)
-{
-	switch (signal) {
-	case S_NM_TEST_REP:
-		return test_rep(signal_data);
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-void ipac_nwl_init(void)
-{
-	osmo_signal_register_handler(SS_NM, nwl_sig_cb, NULL);
-}

-- 
To view, visit https://gerrit.osmocom.org/11921
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I9c04f9b469e60802461a2a6e421d3ba27e6dafa1
Gerrit-Change-Number: 11921
Gerrit-PatchSet: 1
Gerrit-Owner: Max <msuraev at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20181125/c41019f4/attachment.htm>


More information about the gerrit-log mailing list