Merge commit 'har/master'
diff --git a/hlrsync/hlrsync.py b/hlrsync/hlrsync.py
index 4ff720b..e4a4955 100755
--- a/hlrsync/hlrsync.py
+++ b/hlrsync/hlrsync.py
@@ -27,12 +27,17 @@
 	web_tokens = web.execute("""
 		SELECT * FROM reg_tokens
 	""").fetchall()
+	web_sms = web.execute("""
+		SELECT * FROM sms_queue
+	""").fetchall()
 
 # index by subscr id
 hlr_subscrs_by_id = {}
+hlr_subscrs_by_ext = {}
 hlr_tokens_by_subscr_id = {}
 for x in hlr_subscrs:
 	hlr_subscrs_by_id[x['id']] = x
+	hlr_subscrs_by_ext[x['extension']] = x
 del hlr_subscrs
 for x in hlr_tokens:
 	hlr_tokens_by_subscr_id[x['subscriber_id']] = x
@@ -95,6 +100,26 @@
 				      WHERE id = ?
 				   """, (x['subscriber_id'],))
 
+# Sync SMS from web to hlr
+with hlr:
+	for sms in web_sms:
+		subscr = hlr_subscrs_by_ext.get(sms['receiver_ext'])
+		if subscr is None:
+			print '%s not found' % sms['receiver_ext']
+			continue
+		hlr.execute("""
+				      INSERT INTO SMS
+				      (created, sender_id, receiver_id, reply_path_req, status_rep_req, protocol_id, data_coding_scheme, ud_hdr_ind, text)
+				      VALUES
+				      (?, 1, ?, 0, 0, 0, 0, 0, ?)
+				   """, (sms['created'], subscr['id'], sms['text']))
+with web:
+	for sms in web_sms:
+		web.execute("""
+				      DELETE FROM sms_queue WHERE id = ?
+				   """, (sms['id'],))
+
+
 hlr.close()
 web.close()
 
diff --git a/openbsc/src/Makefile.am b/openbsc/src/Makefile.am
index d7a8462..cbfeeaa 100644
--- a/openbsc/src/Makefile.am
+++ b/openbsc/src/Makefile.am
@@ -9,7 +9,7 @@
 		gsm_subscriber.c msgb.c select.c chan_alloc.c timer.c debug.c db.c \
 		gsm_04_11.c telnet_interface.c subchan_demux.c \
 		trau_frame.c trau_mux.c paging.c e1_config.c e1_input.c tlv_parser.c \
-		input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c \
+		input/misdn.c input/ipaccess.c signal.c gsm_utils.c talloc.c talloc_ctx.c \
 		transaction.c rtp_proxy.c bsc_rll.c token_auth.c
 
 libvty_a_SOURCES = vty/buffer.c vty/command.c vty/vector.c vty/vty.c
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index a75ef7a..abf073c 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -2199,7 +2199,7 @@
 
 /* BS11 SWL */
 
-static void *tall_fle_ctx;
+void *tall_fle_ctx;
 
 struct abis_nm_bs11_sw {
 	struct gsm_bts *bts;
@@ -2564,10 +2564,3 @@
 {
 	return __simple_cmd(bts, NM_MT_IPACC_RESTART);
 }
-
-
-static __attribute__((constructor)) void on_dso_load_abis_nm(void)
-{
-	tall_fle_ctx = talloc_named_const(tall_bsc_ctx, 1, 
-					  "bs11_file_list_entry");
-}
diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c
index 4253959..5f84513 100644
--- a/openbsc/src/bsc_hack.c
+++ b/openbsc/src/bsc_hack.c
@@ -1029,11 +1029,10 @@
 	}
 
 	/* Control Channel Description */
-	memset(&bts->chan_desc, 0, sizeof(struct gsm48_control_channel_descr));
 	bts->chan_desc.att = 1;
 	bts->chan_desc.ccch_conf = RSL_BCCH_CCCH_CONF_1_C;
 	bts->chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5;
-	bts->chan_desc.t3212 = 0;
+	/* T3212 is set from vty/config */
 
 	paging_init(bts);
 
@@ -1218,6 +1217,7 @@
 	int rc;
 
 	tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
+	talloc_ctx_init();
 	on_dso_load_token();
 
 	/* parse options */
diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c
index dc2bd19..e5ab49d 100644
--- a/openbsc/src/gsm_04_08.c
+++ b/openbsc/src/gsm_04_08.c
@@ -56,7 +56,7 @@
 #define GSM_MAX_SSVERSION      128
 #define GSM_MAX_USERUSER       128
 
-static void *tall_locop_ctx;
+void *tall_locop_ctx;
 
 /* should ip.access BTS use direct RTP streams between each other (1),
  * or should OpenBSC always act as RTP relay/proxy in between (0) ? */
@@ -3896,8 +3896,6 @@
  */
 static __attribute__((constructor)) void on_dso_load_0408(void)
 {
-	tall_locop_ctx = talloc_named_const(tall_bsc_ctx, 1,
-					    "loc_updating_oper");
 	register_signal_handler(SS_LCHAN, gsm0408_handle_lchan_signal, NULL);
 	register_signal_handler(SS_ABISIP, handle_abisip_signal, NULL);
 }
diff --git a/openbsc/src/gsm_04_11.c b/openbsc/src/gsm_04_11.c
index 8ac596d..a7f69d1 100644
--- a/openbsc/src/gsm_04_11.c
+++ b/openbsc/src/gsm_04_11.c
@@ -53,7 +53,7 @@
 
 #define UM_SAPI_SMS 3	/* See GSM 04.05/04.06 */
 
-static void *tall_gsms_ctx;
+void *tall_gsms_ctx;
 static u_int32_t new_callref = 0x40000001;
 
 struct value_string {
@@ -262,7 +262,7 @@
 		if (cgbits & 2)
 			DEBUGP(DSMS, "Compressed SMS not supported yet\n");
 
-		switch (dcs & 3) {
+		switch ((dcs >> 2)&0x03) {
 		case 0:
 			alpha = DCS_7BIT_DEFAULT;
 			break;
@@ -389,8 +389,8 @@
 	*smsp = sms->user_data_len;
 
 	/* generate TP-UD */
-	/* FIXME: Handle DSC of UCS2 or 8/bit default */
-	if (gsm338_get_sms_alphabet(sms->data_coding_scheme) == DCS_7BIT_DEFAULT) {
+	switch (gsm338_get_sms_alphabet(sms->data_coding_scheme)) {
+	case DCS_7BIT_DEFAULT:
 		octet_len = sms->user_data_len*7/8;
 		if (sms->user_data_len*7%8 != 0)
 			octet_len++;
@@ -398,6 +398,15 @@
 		 * (characters), we need amount of octets occupied */
 		smsp = msgb_put(msg, octet_len);
 		memcpy(smsp, sms->user_data, octet_len);
+		break;
+	case DCS_UCS2:
+	case DCS_8BIT_DATA:
+		smsp = msgb_put(msg, sms->user_data_len);
+		memcpy(smsp, sms->user_data, sms->user_data_len);
+		break;
+	default:
+		DEBUGP(DSMS, "Unhandled Data Coding Scheme: 0x%02X\n", sms->data_coding_scheme);
+		break;
 	}
 
 	return msg->len - old_msg_len;
@@ -1079,7 +1088,5 @@
 
 static __attribute__((constructor)) void on_dso_load_sms(void)
 {
-	tall_gsms_ctx = talloc_named_const(tall_bsc_ctx, 1, "sms");
-
 	register_signal_handler(SS_SUBSCR, subscr_sig_cb, NULL);
 }
diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c
index d91298e..297b8c8 100644
--- a/openbsc/src/gsm_subscriber.c
+++ b/openbsc/src/gsm_subscriber.c
@@ -36,8 +36,8 @@
 #include <openbsc/db.h>
 
 LLIST_HEAD(active_subscribers);
-static void *tall_subscr_ctx;
-static void *tall_sub_req_ctx;
+void *tall_subscr_ctx;
+void *tall_sub_req_ctx;
 
 /*
  * Struct for pending channel requests. This is managed in the
@@ -282,12 +282,3 @@
 	if (lchan->subscr && !llist_empty(&lchan->subscr->requests))
 		subscr_send_paging_request(lchan->subscr);
 }
-
-
-static __attribute__((constructor)) void on_dso_load_subscr(void)
-{
-	tall_subscr_ctx = talloc_named_const(tall_bsc_ctx, 1, "subscriber");
-
-	tall_sub_req_ctx = talloc_named_const(tall_bsc_ctx, 1,
-						      "subscr_request");
-}
diff --git a/openbsc/src/mncc.c b/openbsc/src/mncc.c
index 8cd62f6..f62541c 100644
--- a/openbsc/src/mncc.c
+++ b/openbsc/src/mncc.c
@@ -30,7 +30,7 @@
 #include <openbsc/talloc.h>
 #include <openbsc/gsm_data.h>
 
-static void *tall_call_ctx;
+void *tall_call_ctx;
 
 static struct mncc_names {
 	char *name;
@@ -389,8 +389,3 @@
 
 	return rc;
 }
-
-static __attribute__((constructor)) void on_dso_load_trau_mncc(void)
-{
-	tall_call_ctx = talloc_named_const(tall_bsc_ctx, 1, "gsm_call");
-}
diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c
index 062eca8..f7ee81d 100644
--- a/openbsc/src/paging.c
+++ b/openbsc/src/paging.c
@@ -49,7 +49,7 @@
 #define PAGING_TIMEOUT 1, 75000
 #define MAX_PAGING_REQUEST 750
 
-static void *tall_paging_ctx;
+void *tall_paging_ctx;
 
 static unsigned int calculate_group(struct gsm_bts *bts, struct gsm_subscriber *subscr)
 {
@@ -316,8 +316,3 @@
 {
 	bts->paging.available_slots = free_slots;
 }
-
-static __attribute__((constructor)) void on_dso_load_paging(void)
-{
-	tall_paging_ctx = talloc_named_const(NULL, 1, "paging_request");
-}
diff --git a/openbsc/src/signal.c b/openbsc/src/signal.c
index bf5671e..e04cadf 100644
--- a/openbsc/src/signal.c
+++ b/openbsc/src/signal.c
@@ -24,7 +24,7 @@
 #include <string.h>
 
 
-static void *tall_sigh_ctx;
+void *tall_sigh_ctx;
 static LLIST_HEAD(signal_handler_list);
 
 struct signal_handler {
@@ -81,8 +81,3 @@
 		(*handler->cbfn)(subsys, signal, handler->data, signal_data);
 	}
 }
-
-static __attribute__((constructor)) void on_dso_load_signal(void)
-{
-	tall_sigh_ctx = talloc_named_const(NULL, 1, "signal_handler");
-}
diff --git a/openbsc/src/subchan_demux.c b/openbsc/src/subchan_demux.c
index 368b985..63be533 100644
--- a/openbsc/src/subchan_demux.c
+++ b/openbsc/src/subchan_demux.c
@@ -31,7 +31,7 @@
 #include <openbsc/talloc.h>
 #include <openbsc/gsm_data.h>
 
-static void *tall_tqe_ctx;
+void *tall_tqe_ctx;
 
 static inline void append_bit(struct demux_subch *sch, u_int8_t bit)
 {
@@ -320,9 +320,3 @@
 
 	return 0;
 }
-
-static __attribute__((constructor)) void on_dso_load_ss_demux(void)
-{
-	tall_tqe_ctx = talloc_named_const(tall_bsc_ctx, 1,
-					  "subch_txq_entry");
-}
diff --git a/openbsc/src/talloc_ctx.c b/openbsc/src/talloc_ctx.c
new file mode 100644
index 0000000..aa9f0b4
--- /dev/null
+++ b/openbsc/src/talloc_ctx.c
@@ -0,0 +1,32 @@
+#include <openbsc/talloc.h>
+#include <openbsc/gsm_data.h>
+
+extern void *tall_fle_ctx;
+extern void *tall_locop_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;
+
+void talloc_ctx_init(void)
+{
+	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_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");
+}
diff --git a/openbsc/src/transaction.c b/openbsc/src/transaction.c
index 5e55665..8e2b0b6 100644
--- a/openbsc/src/transaction.c
+++ b/openbsc/src/transaction.c
@@ -29,7 +29,7 @@
 #include <openbsc/mncc.h>
 #include <openbsc/paging.h>
 
-static void *tall_trans_ctx;
+void *tall_trans_ctx;
 
 void _gsm48_cc_trans_free(struct gsm_trans *trans);
 
diff --git a/openbsc/src/trau_mux.c b/openbsc/src/trau_mux.c
index 9ff7001..6a19f0c 100644
--- a/openbsc/src/trau_mux.c
+++ b/openbsc/src/trau_mux.c
@@ -47,7 +47,7 @@
 static LLIST_HEAD(ss_map);
 static LLIST_HEAD(ss_upqueue);
 
-static void *tall_map_ctx, *tall_upq_ctx;
+void *tall_map_ctx, *tall_upq_ctx;
 
 /* map one particular subslot to another subslot */
 int trau_mux_map(const struct gsm_e1_subslot *src,
@@ -235,12 +235,3 @@
 	return subchan_mux_enqueue(mx, dst_e1_ss->e1_ts_ss, trau_bits_out,
 				   TRAU_FRAME_BITS);
 }
-
-static __attribute__((constructor)) void on_dso_load_trau_mux(void)
-{
-	tall_map_ctx = talloc_named_const(tall_bsc_ctx, 1,
-					  "trau_map_entry");
-
-	tall_upq_ctx = talloc_named_const(tall_bsc_ctx, 1,
-					  "trau_upq_entry");
-}
diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c
index 53800d1..affe28d 100644
--- a/openbsc/src/vty/vty.c
+++ b/openbsc/src/vty/vty.c
@@ -1630,7 +1630,7 @@
 /* Install vty's own commands like `who' command. */
 void vty_init()
 {
-	tall_vty_ctx = talloc_named_const(tall_bsc_ctx, 1, "vty");
+	tall_vty_ctx = talloc_named_const(NULL, 0, "vty");
 
 	/* For further configuration read, preserve current directory. */
 	vty_save_cwd();
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index 8fc26e2..527d436 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -234,6 +234,9 @@
 	vty_out(vty, "  training_sequence_code %u%s", bts->tsc, VTY_NEWLINE);
 	vty_out(vty, "  base_station_id_code %u%s", bts->bsic, VTY_NEWLINE);
 	vty_out(vty, "  ms max power %u%s", bts->ms_max_power, VTY_NEWLINE);
+	if (bts->chan_desc.t3212)
+		vty_out(vty, "  periodic location update %u%s",
+			bts->chan_desc.t3212 * 10, VTY_NEWLINE);
 	vty_out(vty, "  channel allocator %s%s",
 		bts->chan_alloc_reverse ? "descending" : "ascending",
 		VTY_NEWLINE);
@@ -430,7 +433,7 @@
 	if (subscr->imsi)
 		vty_out(vty, "    IMSI: %s%s", subscr->imsi, VTY_NEWLINE);
 	if (subscr->tmsi)
-		vty_out(vty, "    TMSI: %s%s", subscr->tmsi, VTY_NEWLINE);
+		vty_out(vty, "    TMSI: %08X", subscr->tmsi, VTY_NEWLINE);
 	vty_out(vty, "    Use count: %u%s", subscr->use_count, VTY_NEWLINE);
 }
 
@@ -988,6 +991,17 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
+      "periodic location update <0-1530>",
+      "Periodic Location Updating Interval in Minutes")
+{
+	struct gsm_bts *bts = vty->index;
+
+	bts->chan_desc.t3212 = atoi(argv[0]) / 10;
+
+	return CMD_SUCCESS;
+}
+
 
 /* per TRX configuration */
 DEFUN(cfg_trx,
@@ -1406,6 +1420,7 @@
 	install_element(BTS_NODE, &cfg_bts_challoc_cmd);
 	install_element(BTS_NODE, &cfg_bts_cell_barred_cmd);
 	install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
+	install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
 
 
 	install_element(BTS_NODE, &cfg_trx_cmd);