aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/common
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-03-03 23:29:05 +0100
committerHarald Welte <laforge@gnumonks.org>2011-03-03 23:29:05 +0100
commit31c00f7d6fa63937f2c973157d196a427f6eef95 (patch)
tree6b7c81d92b6a8b83d0588b2b59d47fd0cca7a052 /openbsc/src/common
parent9349d7ff7c5866110a1f2421ccc68a487e4030be (diff)
re-structure the OpenBSC directory layout
The new structure divides the code into a number of libraries for the BSC core functionality, MSC core functionality, Abis transport, TRAU and other bits. This doesn't introduce any functional code change but simply moves around files and alters Makefile.am accordingly. Next step would be to disentangle a lot of the inter-library dependencies and make the individual bits of code more independent.
Diffstat (limited to 'openbsc/src/common')
-rw-r--r--openbsc/src/common/Makefile.am7
-rw-r--r--openbsc/src/common/bsc_version.c30
-rw-r--r--openbsc/src/common/common_vty.c225
-rw-r--r--openbsc/src/common/debug.c249
-rw-r--r--openbsc/src/common/gsm_data.c589
-rw-r--r--openbsc/src/common/socket.c108
-rw-r--r--openbsc/src/common/talloc_ctx.c38
7 files changed, 1246 insertions, 0 deletions
diff --git a/openbsc/src/common/Makefile.am b/openbsc/src/common/Makefile.am
new file mode 100644
index 000000000..2895452ea
--- /dev/null
+++ b/openbsc/src/common/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)
+AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS)
+AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS)
+
+noinst_LIBRARIES = libcommon.a
+
+libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c
diff --git a/openbsc/src/common/bsc_version.c b/openbsc/src/common/bsc_version.c
new file mode 100644
index 000000000..cc1e76449
--- /dev/null
+++ b/openbsc/src/common/bsc_version.c
@@ -0,0 +1,30 @@
+/* Hold the copyright and version string */
+/* (C) 2010 by Harald Welte <laforge@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 "bscconfig.h"
+
+const char *openbsc_copyright =
+ "Copyright (C) 2008-2010 Harald Welte, Holger Freyther\r\n"
+ "Contributions by Daniel Willmann, Jan Lübbe, Stefan Schmidt\r\n"
+ "Dieter Spaar, Andreas Eversberg, Sylvain Munaut\r\n\r\n"
+ "License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
+ "This is free software: you are free to change and redistribute it.\r\n"
+ "There is NO WARRANTY, to the extent permitted by law.\r\n";
+
+
diff --git a/openbsc/src/common/common_vty.c b/openbsc/src/common/common_vty.c
new file mode 100644
index 000000000..84375a22d
--- /dev/null
+++ b/openbsc/src/common/common_vty.c
@@ -0,0 +1,225 @@
+/* OpenBSC VTY common helpers */
+/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009-2010 by Holger Hans Peter Freyther
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <osmocore/talloc.h>
+
+#include <openbsc/vty.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/debug.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/bsc_nat.h>
+
+#include <osmocom/vty/telnet_interface.h>
+#include <osmocom/vty/command.h>
+#include <osmocom/vty/buffer.h>
+#include <osmocom/vty/vty.h>
+
+
+enum node_type bsc_vty_go_parent(struct vty *vty)
+{
+ switch (vty->node) {
+ case GSMNET_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case BTS_NODE:
+ vty->node = GSMNET_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts *bts = vty->index;
+ vty->index = bts->network;
+ }
+ break;
+ case TRX_NODE:
+ vty->node = BTS_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx *trx = vty->index;
+ vty->index = trx->bts;
+ }
+ break;
+ case TS_NODE:
+ vty->node = TRX_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx_ts *ts = vty->index;
+ vty->index = ts->trx;
+ }
+ break;
+ case OML_NODE:
+ case OM2K_NODE:
+ vty->node = ENABLE_NODE;
+ talloc_free(vty->index);
+ vty->index = NULL;
+ break;
+ case NAT_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case NAT_BSC_NODE:
+ vty->node = NAT_NODE;
+ {
+ struct bsc_config *bsc_config = vty->index;
+ vty->index = bsc_config->nat;
+ }
+ break;
+ case MSC_NODE:
+ vty->node = GSMNET_NODE;
+ break;
+ case TRUNK_NODE:
+ vty->node = MGCP_NODE;
+ break;
+ default:
+ vty->node = CONFIG_NODE;
+ }
+
+ return vty->node;
+}
+
+/* Down vty node level. */
+gDEFUN(ournode_exit,
+ ournode_exit_cmd, "exit", "Exit current mode and down to previous mode\n")
+{
+ switch (vty->node) {
+ case GSMNET_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case BTS_NODE:
+ vty->node = GSMNET_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts *bts = vty->index;
+ vty->index = bts->network;
+ vty->index_sub = NULL;
+ }
+ break;
+ case TRX_NODE:
+ vty->node = BTS_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx *trx = vty->index;
+ vty->index = trx->bts;
+ vty->index_sub = &trx->bts->description;
+ }
+ break;
+ case TS_NODE:
+ vty->node = TRX_NODE;
+ {
+ /* set vty->index correctly ! */
+ struct gsm_bts_trx_ts *ts = vty->index;
+ vty->index = ts->trx;
+ vty->index_sub = &ts->trx->description;
+ }
+ break;
+ case NAT_BSC_NODE:
+ vty->node = NAT_NODE;
+ {
+ struct bsc_config *bsc_config = vty->index;
+ vty->index = bsc_config->nat;
+ }
+ break;
+ case MGCP_NODE:
+ case GBPROXY_NODE:
+ case SGSN_NODE:
+ case NS_NODE:
+ case BSSGP_NODE:
+ case NAT_NODE:
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+ break;
+ case OML_NODE:
+ case OM2K_NODE:
+ vty->node = ENABLE_NODE;
+ talloc_free(vty->index);
+ vty->index = NULL;
+ break;
+ case MSC_NODE:
+ vty->node = GSMNET_NODE;
+ break;
+ case TRUNK_NODE:
+ vty->node = MGCP_NODE;
+ vty->index = NULL;
+ break;
+ default:
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+/* End of configuration. */
+gDEFUN(ournode_end,
+ ournode_end_cmd, "end", "End current mode and change to enable mode.")
+{
+ switch (vty->node) {
+ case VIEW_NODE:
+ case ENABLE_NODE:
+ /* Nothing to do. */
+ break;
+ case CONFIG_NODE:
+ case GSMNET_NODE:
+ case BTS_NODE:
+ case TRX_NODE:
+ case TS_NODE:
+ case MGCP_NODE:
+ case TRUNK_NODE:
+ case GBPROXY_NODE:
+ case SGSN_NODE:
+ case NS_NODE:
+ case VTY_NODE:
+ case NAT_NODE:
+ case NAT_BSC_NODE:
+ case MSC_NODE:
+ vty_config_unlock(vty);
+ vty->node = ENABLE_NODE;
+ vty->index = NULL;
+ vty->index_sub = NULL;
+ break;
+ default:
+ break;
+ }
+ return CMD_SUCCESS;
+}
+
+int bsc_vty_is_config_node(struct vty *vty, int node)
+{
+ switch (node) {
+ /* add items that are not config */
+ case OML_NODE:
+ case OM2K_NODE:
+ case SUBSCR_NODE:
+ case CONFIG_NODE:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
+/* a talloc string replace routine */
+void bsc_replace_string(void *ctx, char **dst, const char *newstr)
+{
+ if (*dst)
+ talloc_free(*dst);
+ *dst = talloc_strdup(ctx, newstr);
+}
diff --git a/openbsc/src/common/debug.c b/openbsc/src/common/debug.c
new file mode 100644
index 000000000..ea5db49e5
--- /dev/null
+++ b/openbsc/src/common/debug.c
@@ -0,0 +1,249 @@
+/* OpenBSC Debugging/Logging support code */
+
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2008 by Holger Hans Peter Freyther <zecke@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 <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <errno.h>
+
+#include <osmocore/talloc.h>
+#include <osmocore/utils.h>
+#include <osmocore/logging.h>
+#include <openbsc/gsm_data.h>
+#include <openbsc/gsm_subscriber.h>
+#include <openbsc/debug.h>
+
+/* default categories */
+static const struct log_info_cat default_categories[] = {
+ [DRLL] = {
+ .name = "DRLL",
+ .description = "A-bis Radio Link Layer (RLL)",
+ .color = "\033[1;31m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DCC] = {
+ .name = "DCC",
+ .description = "Layer3 Call Control (CC)",
+ .color = "\033[1;32m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DMM] = {
+ .name = "DMM",
+ .description = "Layer3 Mobility Management (MM)",
+ .color = "\033[1;33m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DRR] = {
+ .name = "DRR",
+ .description = "Layer3 Radio Resource (RR)",
+ .color = "\033[1;34m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DRSL] = {
+ .name = "DRSL",
+ .description = "A-bis Radio Siganlling Link (RSL)",
+ .color = "\033[1;35m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DNM] = {
+ .name = "DNM",
+ .description = "A-bis Network Management / O&M (NM/OML)",
+ .color = "\033[1;36m",
+ .enabled = 1, .loglevel = LOGL_INFO,
+ },
+ [DMNCC] = {
+ .name = "DMNCC",
+ .description = "MNCC API for Call Control application",
+ .color = "\033[1;39m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DSMS] = {
+ .name = "DSMS",
+ .description = "Layer3 Short Message Service (SMS)",
+ .color = "\033[1;37m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DPAG] = {
+ .name = "DPAG",
+ .description = "Paging Subsystem",
+ .color = "\033[1;38m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DMEAS] = {
+ .name = "DMEAS",
+ .description = "Radio Measurement Processing",
+ .enabled = 0, .loglevel = LOGL_NOTICE,
+ },
+ [DMI] = {
+ .name = "DMI",
+ .description = "A-bis Input Driver for Signalling",
+ .enabled = 0, .loglevel = LOGL_NOTICE,
+ },
+ [DMIB] = {
+ .name = "DMIB",
+ .description = "A-bis Input Driver for B-Channels (voice)",
+ .enabled = 0, .loglevel = LOGL_NOTICE,
+ },
+ [DMUX] = {
+ .name = "DMUX",
+ .description = "A-bis B-Subchannel TRAU Frame Multiplex",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DINP] = {
+ .name = "DINP",
+ .description = "A-bis Intput Subsystem",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DSCCP] = {
+ .name = "DSCCP",
+ .description = "SCCP Protocol",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DMSC] = {
+ .name = "DMSC",
+ .description = "Mobile Switching Center",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DMGCP] = {
+ .name = "DMGCP",
+ .description = "Media Gateway Control Protocol",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DHO] = {
+ .name = "DHO",
+ .description = "Hand-Over",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DDB] = {
+ .name = "DDB",
+ .description = "Database Layer",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DREF] = {
+ .name = "DREF",
+ .description = "Reference Counting",
+ .enabled = 0, .loglevel = LOGL_NOTICE,
+ },
+ [DGPRS] = {
+ .name = "DGPRS",
+ .description = "GPRS Packet Service",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DNS] = {
+ .name = "DNS",
+ .description = "GPRS Network Service (NS)",
+ .enabled = 1, .loglevel = LOGL_INFO,
+ },
+ [DBSSGP] = {
+ .name = "DBSSGP",
+ .description = "GPRS BSS Gateway Protocol (BSSGP)",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DLLC] = {
+ .name = "DLLC",
+ .description = "GPRS Logical Link Control Protocol (LLC)",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DSNDCP] = {
+ .name = "DSNDCP",
+ .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+ [DNAT] = {
+ .name = "DNAT",
+ .description = "GSM 08.08 NAT/Multipkexer",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+};
+
+enum log_filter {
+ _FLT_ALL = LOG_FILTER_ALL, /* libosmocore */
+ FLT_IMSI = 1,
+ FLT_NSVC = 2,
+ FLT_BVC = 3,
+};
+
+static int filter_fn(const struct log_context *ctx,
+ struct log_target *tar)
+{
+ struct gsm_subscriber *subscr = ctx->ctx[BSC_CTX_SUBSCR];
+ const struct gprs_nsvc *nsvc = ctx->ctx[BSC_CTX_NSVC];
+ const struct gprs_nsvc *bvc = ctx->ctx[BSC_CTX_BVC];
+
+ if ((tar->filter_map & (1 << FLT_IMSI)) != 0
+ && subscr && strcmp(subscr->imsi, tar->filter_data[FLT_IMSI]) == 0)
+ return 1;
+
+ /* Filter on the NS Virtual Connection */
+ if ((tar->filter_map & (1 << FLT_NSVC)) != 0
+ && nsvc && (nsvc == tar->filter_data[FLT_NSVC]))
+ return 1;
+
+ /* Filter on the NS Virtual Connection */
+ if ((tar->filter_map & (1 << FLT_BVC)) != 0
+ && bvc && (bvc == tar->filter_data[FLT_BVC]))
+ return 1;
+
+ return 0;
+}
+
+const struct log_info log_info = {
+ .filter_fn = filter_fn,
+ .cat = default_categories,
+ .num_cat = ARRAY_SIZE(default_categories),
+};
+
+void log_set_imsi_filter(struct log_target *target, const char *imsi)
+{
+ if (imsi) {
+ target->filter_map |= (1 << FLT_IMSI);
+ target->filter_data[FLT_IMSI] = talloc_strdup(target, imsi);
+ } else if (target->filter_data[FLT_IMSI]) {
+ target->filter_map &= ~(1 << FLT_IMSI);
+ talloc_free(target->filter_data[FLT_IMSI]);
+ target->filter_data[FLT_IMSI] = NULL;
+ }
+}
+
+void log_set_nsvc_filter(struct log_target *target, struct gprs_nsvc *nsvc)
+{
+ if (nsvc) {
+ target->filter_map |= (1 << FLT_NSVC);
+ target->filter_data[FLT_NSVC] = nsvc;
+ } else if (target->filter_data[FLT_NSVC]) {
+ target->filter_map = ~(1 << FLT_NSVC);
+ target->filter_data[FLT_NSVC] = NULL;
+ }
+}
+
+void log_set_bvc_filter(struct log_target *target, struct bssgp_bvc_ctx *bctx)
+{
+ if (bctx) {
+ target->filter_map |= (1 << FLT_BVC);
+ target->filter_data[FLT_BVC] = bctx;
+ } else if (target->filter_data[FLT_NSVC]) {
+ target->filter_map = ~(1 << FLT_BVC);
+ target->filter_data[FLT_BVC] = NULL;
+ }
+}
diff --git a/openbsc/src/common/gsm_data.c b/openbsc/src/common/gsm_data.c
new file mode 100644
index 000000000..f181fd162
--- /dev/null
+++ b/openbsc/src/common/gsm_data.c
@@ -0,0 +1,589 @@
+/* (C) 2008-2010 by Harald Welte <laforge@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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+
+#include <osmocore/linuxlist.h>
+#include <osmocore/talloc.h>
+#include <osmocore/gsm_utils.h>
+#include <osmocore/statistics.h>
+
+#include <openbsc/gsm_data.h>
+#include <openbsc/osmo_msc_data.h>
+#include <openbsc/abis_nm.h>
+
+void *tall_bsc_ctx;
+
+static LLIST_HEAD(bts_models);
+
+void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
+ u_int8_t e1_ts, u_int8_t e1_ts_ss)
+{
+ ts->e1_link.e1_nr = e1_nr;
+ ts->e1_link.e1_ts = e1_ts;
+ ts->e1_link.e1_ts_ss = e1_ts_ss;
+}
+
+static const struct value_string pchan_names[] = {
+ { GSM_PCHAN_NONE, "NONE" },
+ { GSM_PCHAN_CCCH, "CCCH" },
+ { GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" },
+ { GSM_PCHAN_TCH_F, "TCH/F" },
+ { GSM_PCHAN_TCH_H, "TCH/H" },
+ { GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" },
+ { GSM_PCHAN_PDCH, "PDCH" },
+ { GSM_PCHAN_TCH_F_PDCH, "TCH/F_PDCH" },
+ { GSM_PCHAN_UNKNOWN, "UNKNOWN" },
+ { 0, NULL }
+};
+
+const char *gsm_pchan_name(enum gsm_phys_chan_config c)
+{
+ return get_value_string(pchan_names, c);
+}
+
+enum gsm_phys_chan_config gsm_pchan_parse(const char *name)
+{
+ return get_string_value(pchan_names, name);
+}
+
+static const struct value_string lchant_names[] = {
+ { GSM_LCHAN_NONE, "NONE" },
+ { GSM_LCHAN_SDCCH, "SDCCH" },
+ { GSM_LCHAN_TCH_F, "TCH/F" },
+ { GSM_LCHAN_TCH_H, "TCH/H" },
+ { GSM_LCHAN_UNKNOWN, "UNKNOWN" },
+ { 0, NULL }
+};
+
+const char *gsm_lchant_name(enum gsm_chan_t c)
+{
+ return get_value_string(lchant_names, c);
+}
+
+static const struct value_string lchan_s_names[] = {
+ { LCHAN_S_NONE, "NONE" },
+ { LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" },
+ { LCHAN_S_ACTIVE, "ACTIVE" },
+ { LCHAN_S_INACTIVE, "INACTIVE" },
+ { LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
+ { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" },
+ { 0, NULL }
+};
+
+const char *gsm_lchans_name(enum gsm_lchan_state s)
+{
+ return get_value_string(lchan_s_names, s);
+}
+
+static const struct value_string chreq_names[] = {
+ { GSM_CHREQ_REASON_EMERG, "EMERGENCY" },
+ { GSM_CHREQ_REASON_PAG, "PAGING" },
+ { GSM_CHREQ_REASON_CALL, "CALL" },
+ { GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" },
+ { GSM_CHREQ_REASON_OTHER, "OTHER" },
+ { 0, NULL }
+};
+
+const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
+{
+ return get_value_string(chreq_names, c);
+}
+
+static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ llist_for_each_entry(model, &bts_models, list) {
+ if (model->type == type)
+ return model;
+ }
+
+ return NULL;
+}
+
+int gsm_bts_model_register(struct gsm_bts_model *model)
+{
+ if (bts_model_find(model->type))
+ return -EEXIST;
+
+ tlv_def_patch(&model->nm_att_tlvdef, &nm_att_tlvdef);
+ llist_add_tail(&model->list, &bts_models);
+ return 0;
+}
+
+
+struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
+ int k;
+
+ if (!trx)
+ return NULL;
+
+ trx->bts = bts;
+ trx->nr = bts->num_trx++;
+ trx->nm_state.administrative = NM_STATE_UNLOCKED;
+
+ for (k = 0; k < TRX_NR_TS; k++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[k];
+ int l;
+
+ ts->trx = trx;
+ ts->nr = k;
+ ts->pchan = GSM_PCHAN_NONE;
+
+ ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data);
+ ts->hopping.arfcns.data = ts->hopping.arfcns_data;
+ ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data);
+ ts->hopping.ma.data = ts->hopping.ma_data;
+
+ for (l = 0; l < TS_MAX_LCHAN; l++) {
+ struct gsm_lchan *lchan;
+ lchan = &ts->lchan[l];
+
+ lchan->ts = ts;
+ lchan->nr = l;
+ lchan->type = GSM_LCHAN_NONE;
+ }
+ }
+
+ if (trx->nr != 0)
+ trx->nominal_power = bts->c0->nominal_power;
+
+ llist_add_tail(&trx->list, &bts->trx_list);
+
+ return trx;
+}
+
+static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 };
+static const uint8_t bts_cell_timer_default[] =
+ { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 };
+
+struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
+ u_int8_t tsc, u_int8_t bsic)
+{
+ struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
+ struct gsm_bts_model *model = bts_model_find(type);
+ int i;
+
+ if (!bts)
+ return NULL;
+
+ if (!model && type != GSM_BTS_TYPE_UNKNOWN) {
+ talloc_free(bts);
+ return NULL;
+ }
+
+ bts->network = net;
+ bts->nr = net->num_bts++;
+ bts->type = type;
+ bts->model = model;
+ bts->tsc = tsc;
+ bts->bsic = bsic;
+ bts->num_trx = 0;
+ INIT_LLIST_HEAD(&bts->trx_list);
+ bts->ms_max_power = 15; /* dBm */
+
+ bts->neigh_list_manual_mode = 0;
+ bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */
+ bts->si_common.cell_sel_par.rxlev_acc_min = 0;
+ bts->si_common.neigh_list.data = bts->si_common.data.neigh_list;
+ bts->si_common.neigh_list.data_len =
+ sizeof(bts->si_common.data.neigh_list);
+ bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list;
+ bts->si_common.si5_neigh_list.data_len =
+ sizeof(bts->si_common.data.si5_neigh_list);
+ bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
+ bts->si_common.cell_alloc.data_len =
+ sizeof(bts->si_common.data.cell_alloc);
+ bts->si_common.rach_control.re = 1; /* no re-establishment */
+ bts->si_common.rach_control.tx_integer = 9; /* 12 slots spread - 217/115 slots delay */
+ bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
+ bts->si_common.rach_control.t2 = 4; /* no emergency calls */
+
+ for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
+ bts->gprs.nsvc[i].bts = bts;
+ bts->gprs.nsvc[i].id = i;
+ }
+ memcpy(&bts->gprs.nse.timer, bts_nse_timer_default,
+ sizeof(bts->gprs.nse.timer));
+ memcpy(&bts->gprs.cell.timer, bts_cell_timer_default,
+ sizeof(bts->gprs.cell.timer));
+
+ /* create our primary TRX */
+ bts->c0 = gsm_bts_trx_alloc(bts);
+ if (!bts->c0) {
+ talloc_free(bts);
+ return NULL;
+ }
+ bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4;
+
+ bts->rach_b_thresh = -1;
+ bts->rach_ldavg_slots = -1;
+ bts->paging.free_chans_need = -1;
+ INIT_LLIST_HEAD(&bts->abis_queue);
+
+ llist_add_tail(&bts->list, &net->bts_list);
+
+ return bts;
+}
+
+struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
+ int (*mncc_recv)(struct gsm_network *, struct msgb *))
+{
+ struct gsm_network *net;
+
+ net = talloc_zero(tall_bsc_ctx, struct gsm_network);
+ if (!net)
+ return NULL;
+
+ net->msc_data = talloc_zero(net, struct osmo_msc_data);
+ if (!net->msc_data) {
+ talloc_free(net);
+ return NULL;
+ }
+
+ net->country_code = country_code;
+ net->network_code = network_code;
+ net->num_bts = 0;
+ net->reject_cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
+ net->T3101 = GSM_T3101_DEFAULT;
+ net->T3113 = GSM_T3113_DEFAULT;
+ /* FIXME: initialize all other timers! */
+
+ /* default set of handover parameters */
+ net->handover.win_rxlev_avg = 10;
+ net->handover.win_rxqual_avg = 1;
+ net->handover.win_rxlev_avg_neigh = 10;
+ net->handover.pwr_interval = 6;
+ net->handover.pwr_hysteresis = 3;
+ net->handover.max_distance = 9999;
+
+ INIT_LLIST_HEAD(&net->trans_list);
+ INIT_LLIST_HEAD(&net->upqueue);
+ INIT_LLIST_HEAD(&net->bts_list);
+
+ net->stats.chreq.total = counter_alloc("net.chreq.total");
+ net->stats.chreq.no_channel = counter_alloc("net.chreq.no_channel");
+ net->stats.handover.attempted = counter_alloc("net.handover.attempted");
+ net->stats.handover.no_channel = counter_alloc("net.handover.no_channel");
+ net->stats.handover.timeout = counter_alloc("net.handover.timeout");
+ net->stats.handover.completed = counter_alloc("net.handover.completed");
+ net->stats.handover.failed = counter_alloc("net.handover.failed");
+ net->stats.loc_upd_type.attach = counter_alloc("net.loc_upd_type.attach");
+ net->stats.loc_upd_type.normal = counter_alloc("net.loc_upd_type.normal");
+ net->stats.loc_upd_type.periodic = counter_alloc("net.loc_upd_type.periodic");
+ net->stats.loc_upd_type.detach = counter_alloc("net.imsi_detach.count");
+ net->stats.loc_upd_resp.reject = counter_alloc("net.loc_upd_resp.reject");
+ net->stats.loc_upd_resp.accept = counter_alloc("net.loc_upd_resp.accept");
+ net->stats.paging.attempted = counter_alloc("net.paging.attempted");
+ net->stats.paging.detached = counter_alloc("net.paging.detached");
+ net->stats.paging.completed = counter_alloc("net.paging.completed");
+ net->stats.paging.expired = counter_alloc("net.paging.expired");
+ net->stats.sms.submitted = counter_alloc("net.sms.submitted");
+ net->stats.sms.no_receiver = counter_alloc("net.sms.no_receiver");
+ net->stats.sms.delivered = counter_alloc("net.sms.delivered");
+ net->stats.sms.rp_err_mem = counter_alloc("net.sms.rp_err_mem");
+ net->stats.sms.rp_err_other = counter_alloc("net.sms.rp_err_other");
+ net->stats.call.mo_setup = counter_alloc("net.call.mo_setup");
+ net->stats.call.mo_connect_ack = counter_alloc("net.call.mo_connect_ack");
+ net->stats.call.mt_setup = counter_alloc("net.call.mt_setup");
+ net->stats.call.mt_connect = counter_alloc("net.call.mt_connect");
+ net->stats.chan.rf_fail = counter_alloc("net.chan.rf_fail");
+ net->stats.chan.rll_err = counter_alloc("net.chan.rll_err");
+ net->stats.bts.oml_fail = counter_alloc("net.bts.oml_fail");
+ net->stats.bts.rsl_fail = counter_alloc("net.bts.rsl_fail");
+
+ net->mncc_recv = mncc_recv;
+
+ net->msc_data->msc_ip = talloc_strdup(net, "127.0.0.1");
+ net->msc_data->msc_port = 5000;
+ net->msc_data->ping_timeout = 20;
+ net->msc_data->pong_timeout = 5;
+ net->msc_data->core_ncc = -1;
+ net->msc_data->core_mcc = -1;
+ net->msc_data->rtp_base = 4000;
+
+ gsm_net_update_ctype(net);
+
+ return net;
+}
+
+struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num)
+{
+ struct gsm_bts *bts;
+
+ if (num >= net->num_bts)
+ return NULL;
+
+ llist_for_each_entry(bts, &net->bts_list, list) {
+ if (bts->nr == num)
+ return bts;
+ }
+
+ return NULL;
+}
+
+/* Get reference to a neighbor cell on a given BCCH ARFCN */
+struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
+ u_int16_t arfcn, u_int8_t bsic)
+{
+ struct gsm_bts *neigh;
+ /* FIXME: use some better heuristics here to determine which cell
+ * using this ARFCN really is closest to the target cell. For
+ * now we simply assume that each ARFCN will only be used by one
+ * cell */
+
+ llist_for_each_entry(neigh, &bts->network->bts_list, list) {
+ if (neigh->c0->arfcn == arfcn &&
+ neigh->bsic == bsic)
+ return neigh;
+ }
+
+ return NULL;
+}
+
+struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num)
+{
+ struct gsm_bts_trx *trx;
+
+ if (num >= bts->num_trx)
+ return NULL;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (trx->nr == num)
+ return trx;
+ }
+
+ return NULL;
+}
+
+static char ts2str[255];
+
+char *gsm_trx_name(struct gsm_bts_trx *trx)
+{
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
+ trx->bts->nr, trx->nr);
+
+ return ts2str;
+}
+
+
+char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
+{
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
+ ts->trx->bts->nr, ts->trx->nr, ts->nr);
+
+ return ts2str;
+}
+
+char *gsm_lchan_name(struct gsm_lchan *lchan)
+{
+ struct gsm_bts_trx_ts *ts = lchan->ts;
+
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
+ ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
+
+ return ts2str;
+}
+
+static const struct value_string bts_types[] = {
+ { GSM_BTS_TYPE_UNKNOWN, "unknown" },
+ { GSM_BTS_TYPE_BS11, "bs11" },
+ { GSM_BTS_TYPE_NANOBTS, "nanobts" },
+ { GSM_BTS_TYPE_RBS2000, "rbs2000" },
+ { 0, NULL }
+};
+
+enum gsm_bts_type parse_btstype(const char *arg)
+{
+ return get_string_value(bts_types, arg);
+}
+
+const char *btstype2str(enum gsm_bts_type type)
+{
+ return get_value_string(bts_types, type);
+}
+
+struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (trx->nr == nr)
+ return trx;
+ }
+ return NULL;
+}
+
+/* Search for a BTS in the given Location Area; optionally start searching
+ * with start_bts (for continuing to search after the first result) */
+struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
+ struct gsm_bts *start_bts)
+{
+ int i;
+ struct gsm_bts *bts;
+ int skip = 0;
+
+ if (start_bts)
+ skip = 1;
+
+ for (i = 0; i < net->num_bts; i++) {
+ bts = gsm_bts_num(net, i);
+
+ if (skip) {
+ if (start_bts == bts)
+ skip = 0;
+ continue;
+ }
+
+ if (lac == GSM_LAC_RESERVED_ALL_BTS || bts->location_area_code == lac)
+ return bts;
+ }
+ return NULL;
+}
+
+static const struct value_string auth_policy_names[] = {
+ { GSM_AUTH_POLICY_CLOSED, "closed" },
+ { GSM_AUTH_POLICY_ACCEPT_ALL, "accept-all" },
+ { GSM_AUTH_POLICY_TOKEN, "token" },
+ { 0, NULL }
+};
+
+enum gsm_auth_policy gsm_auth_policy_parse(const char *arg)
+{
+ return get_string_value(auth_policy_names, arg);
+}
+
+const char *gsm_auth_policy_name(enum gsm_auth_policy policy)
+{
+ return get_value_string(auth_policy_names, policy);
+}
+
+void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
+{
+ raid->mcc = bts->network->country_code;
+ raid->mnc = bts->network->network_code;
+ raid->lac = bts->location_area_code;
+ raid->rac = bts->gprs.rac;
+}
+
+int gsm48_ra_id_by_bts(u_int8_t *buf, struct gsm_bts *bts)
+{
+ struct gprs_ra_id raid;
+
+ gprs_ra_id_by_bts(&raid, bts);
+
+ return gsm48_construct_ra(buf, &raid);
+}
+
+static const struct value_string rrlp_mode_names[] = {
+ { RRLP_MODE_NONE, "none" },
+ { RRLP_MODE_MS_BASED, "ms-based" },
+ { RRLP_MODE_MS_PREF, "ms-preferred" },
+ { RRLP_MODE_ASS_PREF, "ass-preferred" },
+ { 0, NULL }
+};
+
+enum rrlp_mode rrlp_mode_parse(const char *arg)
+{
+ return get_string_value(rrlp_mode_names, arg);
+}
+
+const char *rrlp_mode_name(enum rrlp_mode mode)
+{
+ return get_value_string(rrlp_mode_names, mode);
+}
+
+static const struct value_string bts_gprs_mode_names[] = {
+ { BTS_GPRS_NONE, "none" },
+ { BTS_GPRS_GPRS, "gprs" },
+ { BTS_GPRS_EGPRS, "egprs" },
+ { 0, NULL }
+};
+
+enum bts_gprs_mode bts_gprs_mode_parse(const char *arg)
+{
+ return get_string_value(bts_gprs_mode_names, arg);
+}
+
+const char *bts_gprs_mode_name(enum bts_gprs_mode mode)
+{
+ return get_value_string(bts_gprs_mode_names, mode);
+}
+
+struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
+{
+ struct gsm_meas_rep *meas_rep;
+
+ meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
+ memset(meas_rep, 0, sizeof(*meas_rep));
+ meas_rep->lchan = lchan;
+ lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
+ % ARRAY_SIZE(lchan->meas_rep);
+
+ return meas_rep;
+}
+
+int gsm_btsmodel_set_feature(struct gsm_bts_model *bts, enum gsm_bts_features feat)
+{
+ return bitvec_set_bit_pos(&bts->features, feat, 1);
+}
+
+int gsm_bts_has_feature(struct gsm_bts *bts, enum gsm_bts_features feat)
+{
+ return bitvec_get_bit_pos(&bts->model->features, feat);
+}
+
+int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ model = bts_model_find(type);
+ if (!model)
+ return -EINVAL;
+
+ bts->type = type;
+ bts->model = model;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ /* Set the default OML Stream ID to 0xff */
+ bts->oml_tei = 0xff;
+ bts->c0->nominal_power = 23;
+ break;
+ case GSM_BTS_TYPE_BS11:
+ case GSM_BTS_TYPE_UNKNOWN:
+ break;
+ case GSM_BTS_TYPE_RBS2000:
+ INIT_LLIST_HEAD(&bts->rbs2000.is.conn_groups);
+ INIT_LLIST_HEAD(&bts->rbs2000.con.conn_groups);
+ break;
+ }
+
+ return 0;
+}
diff --git a/openbsc/src/common/socket.c b/openbsc/src/common/socket.c
new file mode 100644
index 000000000..47778e746
--- /dev/null
+++ b/openbsc/src/common/socket.c
@@ -0,0 +1,108 @@
+/* OpenBSC sokcet code, taken from Abis input driver for ip.access */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2010 by Holger Hans Peter Freyther
+ * (C) 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 <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+
+#include <osmocore/select.h>
+#include <osmocore/tlv.h>
+#include <osmocore/msgb.h>
+#include <openbsc/debug.h>
+#include <openbsc/gsm_data.h>
+#include <osmocore/talloc.h>
+
+int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port,
+ int (*cb)(struct bsc_fd *fd, unsigned int what))
+{
+ struct sockaddr_in addr;
+ int ret, on = 1;
+ int type = SOCK_STREAM;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ type = SOCK_STREAM;
+ break;
+ case IPPROTO_UDP:
+ type = SOCK_DGRAM;
+ break;
+ case IPPROTO_GRE:
+ type = SOCK_RAW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ bfd->fd = socket(AF_INET, type, proto);
+ bfd->cb = cb;
+ bfd->when = BSC_FD_READ;
+ //bfd->data = line;
+
+ if (bfd->fd < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not create socket.\n");
+ return -EIO;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ if (ip)
+ addr.sin_addr.s_addr = htonl(ip);
+ else
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ setsockopt(bfd->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+ ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
+ if (ret < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not bind socket %s\n",
+ strerror(errno));
+ close(bfd->fd);
+ return -EIO;
+ }
+
+ if (proto == IPPROTO_TCP) {
+ ret = listen(bfd->fd, 1);
+ if (ret < 0) {
+ perror("listen");
+ close(bfd->fd);
+ return ret;
+ }
+ }
+
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register_listen_fd");
+ close(bfd->fd);
+ return ret;
+ }
+ return 0;
+}
diff --git a/openbsc/src/common/talloc_ctx.c b/openbsc/src/common/talloc_ctx.c
new file mode 100644
index 000000000..8e7ec230f
--- /dev/null
+++ b/openbsc/src/common/talloc_ctx.c
@@ -0,0 +1,38 @@
+#include <osmocore/talloc.h>
+#include <openbsc/gsm_data.h>
+
+extern void *tall_msgb_ctx;
+extern void *tall_fle_ctx;
+extern void *tall_locop_ctx;
+extern void *tall_authciphop_ctx;
+extern void *tall_gsms_ctx;
+extern void *tall_subscr_ctx;
+extern void *tall_sub_req_ctx;
+extern void *tall_call_ctx;
+extern void *tall_paging_ctx;
+extern void *tall_sigh_ctx;
+extern void *tall_tqe_ctx;
+extern void *tall_trans_ctx;
+extern void *tall_map_ctx;
+extern void *tall_upq_ctx;
+extern void *tall_ctr_ctx;
+
+void talloc_ctx_init(void)
+{
+ tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
+ tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 0,
+ "bs11_file_list_entry");
+ tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 0, "loc_updating_oper");
+ tall_authciphop_ctx = talloc_named_const(tall_bsc_ctx, 0, "auth_ciph_oper");
+ tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 0, "sms");
+ tall_subscr_ctx = talloc_named_const(tall_bsc_ctx, 0, "subscriber");
+ tall_sub_req_ctx = talloc_named_const(tall_bsc_ctx, 0, "subscr_request");
+ tall_call_ctx = talloc_named_const(tall_bsc_ctx, 0, "gsm_call");
+ tall_paging_ctx = talloc_named_const(tall_bsc_ctx, 0, "paging_request");
+ tall_sigh_ctx = talloc_named_const(tall_bsc_ctx, 0, "signal_handler");
+ tall_tqe_ctx = talloc_named_const(tall_bsc_ctx, 0, "subch_txq_entry");
+ tall_trans_ctx = talloc_named_const(tall_bsc_ctx, 0, "transaction");
+ tall_map_ctx = talloc_named_const(tall_bsc_ctx, 0, "trau_map_entry");
+ tall_upq_ctx = talloc_named_const(tall_bsc_ctx, 0, "trau_upq_entry");
+ tall_ctr_ctx = talloc_named_const(tall_bsc_ctx, 0, "counter");
+}