switch vty implementation over to talloc
diff --git a/openbsc/src/vty/buffer.c b/openbsc/src/vty/buffer.c
index 6366100..be6623d 100644
--- a/openbsc/src/vty/buffer.c
+++ b/openbsc/src/vty/buffer.c
@@ -28,9 +28,12 @@
 #include <stddef.h>
 #include <sys/uio.h>
 
+#include <openbsc/talloc.h>
 #include <vty/buffer.h>
 #include <vty/vty.h>
 
+static void *tall_vbuf_ctx;
+
 /* Buffer master. */
 struct buffer {
 	/* Data list. */
@@ -61,14 +64,14 @@
    next page boundery. */
 #define BUFFER_SIZE_DEFAULT		4096
 
-#define BUFFER_DATA_FREE(D) free((D))
+#define BUFFER_DATA_FREE(D) talloc_free((D))
 
 /* Make new buffer. */
 struct buffer *buffer_new(size_t size)
 {
 	struct buffer *b;
 
-	b = calloc(1, sizeof(struct buffer));
+	b = talloc_zero(tall_vbuf_ctx, struct buffer);
 
 	if (size)
 		b->size = size;
@@ -89,7 +92,7 @@
 void buffer_free(struct buffer *b)
 {
 	buffer_reset(b);
-	free(b);
+	talloc_free(b);
 }
 
 /* Make string clone. */
@@ -102,7 +105,7 @@
 
 	for (data = b->head; data; data = data->next)
 		totlen += data->cp - data->sp;
-	if (!(s = malloc(totlen + 1)))
+	if (!(s = _talloc_zero(tall_vbuf_ctx, (totlen + 1), "buffer_getstr")))
 		return NULL;
 	p = s;
 	for (data = b->head; data; data = data->next) {
@@ -137,7 +140,9 @@
 {
 	struct buffer_data *d;
 
-	d = malloc(offsetof(struct buffer_data, data[b->size]));
+	d = _talloc_zero(tall_vbuf_ctx,
+			 offsetof(struct buffer_data, data[b->size]),
+			 "buffer_add");
 	if (!d)
 		return NULL;
 	d->cp = d->sp = 0;
@@ -458,3 +463,8 @@
 	}
 	return b->head ? BUFFER_PENDING : BUFFER_EMPTY;
 }
+
+static __attribute__((constructor)) void on_dso_load_vty_buf(void)
+{
+	tall_vbuf_ctx = talloc_named_const(NULL, 1, "vty_buffer");
+}
diff --git a/openbsc/src/vty/command.c b/openbsc/src/vty/command.c
index 44bdf26..9841343 100644
--- a/openbsc/src/vty/command.c
+++ b/openbsc/src/vty/command.c
@@ -47,6 +47,9 @@
 
 #include <openbsc/gsm_data.h>
 #include <openbsc/gsm_subscriber.h>
+#include <openbsc/talloc.h>
+
+static void *tall_vcmd_ctx;
 
 /* Command vector which includes some level of command lists. Normally
    each daemon maintains each own cmdvec. */
@@ -172,7 +175,7 @@
 		len += strlen(argv[i]) + 1;
 	if (!len)
 		return NULL;
-	p = str = malloc(len);
+	p = str = _talloc_zero(tall_vcmd_ctx, len, "arvg_concat");
 	for (i = shift; i < argc; i++) {
 		size_t arglen;
 		memcpy(p, argv[i], (arglen = strlen(argv[i])));
@@ -274,7 +277,7 @@
 		       *cp != '\0')
 			cp++;
 		strlen = cp - start;
-		token = malloc(strlen + 1);
+		token = _talloc_zero(tall_vcmd_ctx, strlen + 1, "make_strvec");
 		memcpy(token, start, strlen);
 		*(token + strlen) = '\0';
 		vector_set(strvec, token);
@@ -299,7 +302,7 @@
 
 	for (i = 0; i < vector_active(v); i++)
 		if ((cp = vector_slot(v, i)) != NULL)
-			free(cp);
+			talloc_free(cp);
 
 	vector_free(v);
 }
@@ -330,7 +333,7 @@
 		cp++;
 
 	strlen = cp - start;
-	token = malloc(strlen + 1);
+	token = _talloc_zero(tall_vcmd_ctx, strlen + 1, "cmd_desc_str");
 	memcpy(token, start, strlen);
 	*(token + strlen) = '\0';
 
@@ -401,11 +404,11 @@
 
 		len = cp - sp;
 
-		token = malloc(len + 1);
+		token = _talloc_zero(tall_vcmd_ctx, len + 1, "cmd_make_descvec");
 		memcpy(token, sp, len);
 		*(token + len) = '\0';
 
-		desc = calloc(1, sizeof(struct desc));
+		desc = talloc_zero(tall_vcmd_ctx, struct desc);
 		desc->cmd = token;
 		desc->str = cmd_desc_str(&dp);
 
@@ -1852,7 +1855,8 @@
 			if (len < lcd) {
 				char *lcdstr;
 
-				lcdstr = malloc(lcd + 1);
+				lcdstr = _talloc_zero(tall_vcmd_ctx, lcd + 1,
+						      "complete-lcdstr");
 				memcpy(lcdstr, matchvec->index[0], lcd);
 				lcdstr[lcd] = '\0';
 
@@ -1861,7 +1865,7 @@
 				/* Free matchvec. */
 				for (i = 0; i < vector_active(matchvec); i++) {
 					if (vector_slot(matchvec, i))
-						free(vector_slot(matchvec, i));
+						talloc_free(vector_slot(matchvec, i));
 				}
 				vector_free(matchvec);
 
@@ -2472,11 +2476,14 @@
 	config_file = host.config;
 
 	config_file_sav =
-	    malloc(strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1);
+	    _talloc_zero(tall_vcmd_ctx,
+			 strlen(config_file) + strlen(CONF_BACKUP_EXT) + 1,
+			 "config_file_sav");
 	strcpy(config_file_sav, config_file);
 	strcat(config_file_sav, CONF_BACKUP_EXT);
 
-	config_file_tmp = malloc(strlen(config_file) + 8);
+	config_file_tmp = _talloc_zero(tall_vcmd_ctx, strlen(config_file) + 8,
+					"config_file_tmp");
 	sprintf(config_file_tmp, "%s.XXXXXX", config_file);
 
 	/* Open file to configuration write. */
@@ -2484,8 +2491,8 @@
 	if (fd < 0) {
 		vty_out(vty, "Can't open configuration file %s.%s",
 			config_file_tmp, VTY_NEWLINE);
-		free(config_file_tmp);
-		free(config_file_sav);
+		talloc_free(config_file_tmp);
+		talloc_free(config_file_sav);
 		return CMD_WARNING;
 	}
 
@@ -2495,7 +2502,7 @@
 	file_vty->type = VTY_FILE;
 
 	/* Config file header print. */
-	vty_out(file_vty, "!\n! Zebra configuration saved from vty\n!   ");
+	vty_out(file_vty, "!\n! OpenBSC configuration saved from vty\n!   ");
 	//vty_time_print (file_vty, 1);
 	vty_out(file_vty, "!\n");
 
@@ -2511,16 +2518,16 @@
 			vty_out(vty,
 				"Can't unlink backup configuration file %s.%s",
 				config_file_sav, VTY_NEWLINE);
-			free(config_file_sav);
-			free(config_file_tmp);
+			talloc_free(config_file_sav);
+			talloc_free(config_file_tmp);
 			unlink(config_file_tmp);
 			return CMD_WARNING;
 		}
 	if (link(config_file, config_file_sav) != 0) {
 		vty_out(vty, "Can't backup old configuration file %s.%s",
 			config_file_sav, VTY_NEWLINE);
-		free(config_file_sav);
-		free(config_file_tmp);
+		talloc_free(config_file_sav);
+		talloc_free(config_file_tmp);
 		unlink(config_file_tmp);
 		return CMD_WARNING;
 	}
@@ -2528,24 +2535,24 @@
 	if (unlink(config_file) != 0) {
 		vty_out(vty, "Can't unlink configuration file %s.%s",
 			config_file, VTY_NEWLINE);
-		free(config_file_sav);
-		free(config_file_tmp);
+		talloc_free(config_file_sav);
+		talloc_free(config_file_tmp);
 		unlink(config_file_tmp);
 		return CMD_WARNING;
 	}
 	if (link(config_file_tmp, config_file) != 0) {
 		vty_out(vty, "Can't save configuration file %s.%s", config_file,
 			VTY_NEWLINE);
-		free(config_file_sav);
-		free(config_file_tmp);
+		talloc_free(config_file_sav);
+		talloc_free(config_file_tmp);
 		unlink(config_file_tmp);
 		return CMD_WARNING;
 	}
 	unlink(config_file_tmp);
 	sync();
 
-	free(config_file_sav);
-	free(config_file_tmp);
+	talloc_free(config_file_sav);
+	talloc_free(config_file_tmp);
 
 	if (chmod(config_file, CONFIGFILE_MASK) != 0) {
 		vty_out(vty, "Can't chmod configuration file %s: %s (%d).%s",
@@ -2654,7 +2661,7 @@
 	}
 
 	if (host.name)
-		free(host.name);
+		talloc_free(host.name);
 
 	host.name = strdup(argv[0]);
 	return CMD_SUCCESS;
@@ -2666,7 +2673,7 @@
       NO_STR "Reset system's network name\n" "Host name of this router\n")
 {
 	if (host.name)
-		free(host.name);
+		talloc_free(host.name);
 	host.name = NULL;
 	return CMD_SUCCESS;
 }
@@ -2687,10 +2694,10 @@
 	if (argc == 2) {
 		if (*argv[0] == '8') {
 			if (host.password)
-				free(host.password);
+				talloc_free(host.password);
 			host.password = NULL;
 			if (host.password_encrypt)
-				free(host.password_encrypt);
+				talloc_free(host.password_encrypt);
 			host.password_encrypt = strdup(strdup(argv[1]));
 			return CMD_SUCCESS;
 		} else {
@@ -2707,13 +2714,13 @@
 	}
 
 	if (host.password)
-		free(host.password);
+		talloc_free(host.password);
 	host.password = NULL;
 
 #ifdef VTY_CRYPT_PW
 	if (host.encrypt) {
 		if (host.password_encrypt)
-			free(host.password_encrypt);
+			talloc_free(host.password_encrypt);
 		host.password_encrypt = strdup(zencrypt(argv[0]));
 	} else
 #endif
@@ -2745,11 +2752,11 @@
 	if (argc == 2) {
 		if (*argv[0] == '8') {
 			if (host.enable)
-				free(host.enable);
+				talloc_free(host.enable);
 			host.enable = NULL;
 
 			if (host.enable_encrypt)
-				free(host.enable_encrypt);
+				talloc_free(host.enable_encrypt);
 			host.enable_encrypt = strdup(argv[1]);
 
 			return CMD_SUCCESS;
@@ -2767,14 +2774,14 @@
 	}
 
 	if (host.enable)
-		free(host.enable);
+		talloc_free(host.enable);
 	host.enable = NULL;
 
 	/* Plain password input. */
 #ifdef VTY_CRYPT_PW
 	if (host.encrypt) {
 		if (host.enable_encrypt)
-			free(host.enable_encrypt);
+			talloc_free(host.enable_encrypt);
 		host.enable_encrypt = strdup(zencrypt(argv[0]));
 	} else
 #endif
@@ -2798,11 +2805,11 @@
       "Assign the privileged level password\n")
 {
 	if (host.enable)
-		free(host.enable);
+		talloc_free(host.enable);
 	host.enable = NULL;
 
 	if (host.enable_encrypt)
-		free(host.enable_encrypt);
+		talloc_free(host.enable_encrypt);
 	host.enable_encrypt = NULL;
 
 	return CMD_SUCCESS;
@@ -2821,12 +2828,12 @@
 
 	if (host.password) {
 		if (host.password_encrypt)
-			free(host.password_encrypt);
+			talloc_free(host.password_encrypt);
 		host.password_encrypt = strdup(zencrypt(host.password));
 	}
 	if (host.enable) {
 		if (host.enable_encrypt)
-			free(host.enable_encrypt);
+			talloc_free(host.enable_encrypt);
 		host.enable_encrypt = strdup(zencrypt(host.enable));
 	}
 
@@ -2844,11 +2851,11 @@
 	host.encrypt = 0;
 
 	if (host.password_encrypt)
-		free(host.password_encrypt);
+		talloc_free(host.password_encrypt);
 	host.password_encrypt = NULL;
 
 	if (host.enable_encrypt)
-		free(host.enable_encrypt);
+		talloc_free(host.enable_encrypt);
 	host.enable_encrypt = NULL;
 
 	return CMD_SUCCESS;
@@ -2924,7 +2931,7 @@
 		((message =
 		  argv_concat(argv, argc, 0)) ? message : ""), VTY_NEWLINE);
 	if (message)
-		free(message);
+		talloc_free(message);
 	return CMD_SUCCESS;
 }
 
@@ -2944,7 +2951,7 @@
 	zlog(NULL, level,
 	     ((message = argv_concat(argv, argc, 1)) ? message : ""));
 	if (message)
-		free(message);
+		talloc_free(message);
 	return CMD_SUCCESS;
 }
 
@@ -3076,7 +3083,9 @@
 			return CMD_WARNING;
 		}
 
-		if ((p = malloc(strlen(cwd) + strlen(fname) + 2))
+		if ((p = _talloc_zero(tall_vcmd_ctx,
+				      strlen(cwd) + strlen(fname) + 2),
+				      "set_log_file")
 		    == NULL) {
 			zlog_err("config_log_file: Unable to alloc mem!");
 			return CMD_WARNING;
@@ -3089,7 +3098,7 @@
 	ret = zlog_set_file(NULL, fullpath, loglevel);
 
 	if (p)
-		free(p);
+		talloc_free(p);
 
 	if (!ret) {
 		vty_out(vty, "can't open logfile %s\n", fname);
@@ -3097,7 +3106,7 @@
 	}
 
 	if (host.logfile)
-		free(host.logfile);
+		talloc_free(host.logfile);
 
 	host.logfile = strdup(fname);
 
@@ -3134,7 +3143,7 @@
 	zlog_reset_file(NULL);
 
 	if (host.logfile)
-		free(host.logfile);
+		talloc_free(host.logfile);
 
 	host.logfile = NULL;
 
@@ -3288,7 +3297,7 @@
       "Set banner\n" "Banner for motd\n" "Banner from a file\n" "Filename\n")
 {
 	if (host.motdfile)
-		free(host.motdfile);
+		talloc_free(host.motdfile);
 	host.motdfile = strdup(argv[0]);
 
 	return CMD_SUCCESS;
@@ -3309,7 +3318,7 @@
 {
 	host.motd = NULL;
 	if (host.motdfile)
-		free(host.motdfile);
+		talloc_free(host.motdfile);
 	host.motdfile = NULL;
 	return CMD_SUCCESS;
 }
@@ -3412,3 +3421,8 @@
 	}
 	srand(time(NULL));
 }
+
+static __attribute__((constructor)) void on_dso_load_vty_command(void)
+{
+	tall_vcmd_ctx = talloc_named_const(NULL, 1, "vty_command");
+}
diff --git a/openbsc/src/vty/vector.c b/openbsc/src/vty/vector.c
index 7687010..c8885a4 100644
--- a/openbsc/src/vty/vector.c
+++ b/openbsc/src/vty/vector.c
@@ -23,12 +23,15 @@
 #include <unistd.h>
 
 #include <vty/vector.h>
+#include <openbsc/talloc.h>
 #include <memory.h>
 
+static void *tall_vvec_ctx;
+
 /* Initialize vector : allocate memory and return vector. */
 vector vector_init(unsigned int size)
 {
-	vector v = calloc(1, sizeof(struct _vector));
+	vector v = talloc_zero(tall_vvec_ctx, struct _vector);
 	if (!v)
 		return NULL;
 
@@ -38,9 +41,10 @@
 
 	v->alloced = size;
 	v->active = 0;
-	v->index = calloc(1, sizeof(void *) * size);
+	v->index = _talloc_zero(tall_vvec_ctx, sizeof(void *) * size,
+				"vector_init:index");
 	if (!v->index) {
-		free(v);
+		talloc_free(v);
 		return NULL;
 	}
 	return v;
@@ -48,24 +52,24 @@
 
 void vector_only_wrapper_free(vector v)
 {
-	free(v);
+	talloc_free(v);
 }
 
 void vector_only_index_free(void *index)
 {
-	free(index);
+	talloc_free(index);
 }
 
 void vector_free(vector v)
 {
-	free(v->index);
-	free(v);
+	talloc_free(v->index);
+	talloc_free(v);
 }
 
 vector vector_copy(vector v)
 {
 	unsigned int size;
-	vector new = calloc(1, sizeof(struct _vector));
+	vector new = talloc_zero(tall_vvec_ctx, struct _vector);
 	if (!new)
 		return NULL;
 
@@ -73,9 +77,9 @@
 	new->alloced = v->alloced;
 
 	size = sizeof(void *) * (v->alloced);
-	new->index = calloc(1, size);
+	new->index = _talloc_zero(tall_vvec_ctx, size, "vector_copy:index");
 	if (!new->index) {
-		free(new);
+		talloc_free(new);
 		return NULL;
 	}
 	memcpy(new->index, v->index, size);
@@ -89,7 +93,8 @@
 	if (v->alloced > num)
 		return;
 
-	v->index = realloc(v->index, sizeof(void *) * (v->alloced * 2));
+	v->index = talloc_realloc_size(tall_vvec_ctx, v->index,
+				       sizeof(void *) * (v->alloced * 2));
 	memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
 	v->alloced *= 2;
 
@@ -184,3 +189,8 @@
 
 	return count;
 }
+
+static __attribute__((constructor)) void on_dso_load_vty_vec(void)
+{
+	tall_vvec_ctx = talloc_named_const(NULL, 1, "vty_vector");
+}
diff --git a/openbsc/src/vty/vty.c b/openbsc/src/vty/vty.c
index c461631..0549914 100644
--- a/openbsc/src/vty/vty.c
+++ b/openbsc/src/vty/vty.c
@@ -17,6 +17,7 @@
 #include <vty/vty.h>
 #include <vty/command.h>
 #include <vty/buffer.h>
+#include <openbsc/talloc.h>
 
 extern struct host host;
 
@@ -32,6 +33,8 @@
 
 static int no_password_check = 1;
 
+static void *tall_vty_ctx;
+
 static void vty_clear_buf(struct vty *vty)
 {
 	memset(vty->buf, 0, vty->max);
@@ -40,7 +43,7 @@
 /* Allocate new vty struct. */
 struct vty *vty_new()
 {
-	struct vty *new = malloc(sizeof(struct vty));
+	struct vty *new = talloc_zero(tall_vty_ctx, struct vty);
 
 	if (!new)
 		goto out;
@@ -48,7 +51,7 @@
 	new->obuf = buffer_new(0);	/* Use default buffer size. */
 	if (!new->obuf)
 		goto out_new;
-	new->buf = calloc(1, VTY_BUFSIZ);
+	new->buf = _talloc_zero(tall_vty_ctx, VTY_BUFSIZ, "vty_new->buf");
 	if (!new->buf)
 		goto out_obuf;
 
@@ -57,9 +60,9 @@
 	return new;
 
 out_obuf:
-	free(new->obuf);
+	buffer_free(new->obuf);
 out_new:
-	free(new);
+	talloc_free(new);
 	new = NULL;
 out:
 	return new;
@@ -135,16 +138,19 @@
 {
 	int i;
 
-	/* Flush buffer. */
-	buffer_flush_all(vty->obuf, vty->fd);
+	if (vty->obuf)  {
+		/* Flush buffer. */
+		buffer_flush_all(vty->obuf, vty->fd);
 
-	/* Free input buffer. */
-	buffer_free(vty->obuf);
+		/* Free input buffer. */
+		buffer_free(vty->obuf);
+		vty->obuf = NULL;
+	}
 
 	/* Free command history. */
 	for (i = 0; i < VTY_MAXHIST; i++)
 		if (vty->hist[i])
-			free(vty->hist[i]);
+			talloc_free(vty->hist[i]);
 
 	/* Unset vector. */
 	vector_unset(vtyvec, vty->fd);
@@ -153,17 +159,20 @@
 	if (vty->fd > 0)
 		close(vty->fd);
 
-	if (vty->buf)
-		free(vty->buf);
+	if (vty->buf) {
+		talloc_free(vty->buf);
+		vty->buf = NULL;
+	}
 
 	/* Check configure. */
 	vty_config_unlock(vty);
 
-	/* OK free vty. */
-	free(vty);
-
 	/* FIXME: memory leak. We need to call telnet_close_client() but don't
 	 * have bfd */
+	vty_event(VTY_CLOSED, vty->fd, vty);
+
+	/* OK free vty. */
+	talloc_free(vty);
 }
 
 int vty_shell(struct vty *vty)
@@ -199,7 +208,7 @@
 				else
 					size = size * 2;
 
-				p = realloc(p, size);
+				p = talloc_realloc_size(tall_vty_ctx, p, size);
 				if (!p)
 					return -1;
 
@@ -221,7 +230,7 @@
 
 		/* If p is not different with buf, it is allocated buffer.  */
 		if (p != buf)
-			free(p);
+			talloc_free(p);
 	}
 
 	return len;
@@ -344,7 +353,7 @@
 {
 	if (vty->max <= length) {
 		vty->max *= 2;
-		vty->buf = realloc(vty->buf, vty->max);
+		vty->buf = talloc_realloc_size(tall_vty_ctx, vty->buf, vty->max);
 		// FIXME: check return
 	}
 }
@@ -444,8 +453,8 @@
 
 	/* Insert history entry. */
 	if (vty->hist[vty->hindex])
-		free(vty->hist[vty->hindex]);
-	vty->hist[vty->hindex] = strdup(vty->buf);
+		talloc_free(vty->hist[vty->hindex]);
+	vty->hist[vty->hindex] = talloc_strdup(tall_vty_ctx, vty->buf);
 
 	/* History index rotation. */
 	vty->hindex++;
@@ -918,14 +927,14 @@
 		vty_backward_pure_word(vty);
 		vty_insert_word_overwrite(vty, matched[0]);
 		vty_self_insert(vty, ' ');
-		free(matched[0]);
+		//talloc_free(matched[0]);
 		break;
 	case CMD_COMPLETE_MATCH:
 		vty_prompt(vty);
 		vty_redraw_line(vty);
 		vty_backward_pure_word(vty);
 		vty_insert_word_overwrite(vty, matched[0]);
-		free(matched[0]);
+		talloc_free(matched[0]);
 		vector_only_index_free(matched);
 		return;
 		break;
@@ -934,7 +943,7 @@
 			if (i != 0 && ((i % 6) == 0))
 				vty_out(vty, "%s", VTY_NEWLINE);
 			vty_out(vty, "%-10s ", matched[i]);
-			free(matched[i]);
+			talloc_free(matched[i]);
 		}
 		vty_out(vty, "%s", VTY_NEWLINE);
 
@@ -968,7 +977,7 @@
 		return;
 	}
 
-	buf = calloc(1, strlen(desc->str) + 1);
+	buf = _talloc_zero(tall_vty_ctx, strlen(desc->str) + 1, "describe_fold");
 	if (!buf)
 		return;
 
@@ -989,7 +998,7 @@
 
 	vty_out(vty, "  %-*s  %s%s", cmd_width, cmd, p, VTY_NEWLINE);
 
-	free(buf);
+	talloc_free(buf);
 }
 
 /* Describe matched command function. */
@@ -1588,7 +1597,7 @@
 		getcwd(cwd, MAXPATHLEN);
 	}
 
-	vty_cwd = malloc(strlen(cwd) + 1);
+	vty_cwd = _talloc_zero(tall_vty_ctx, strlen(cwd) + 1, "save_cwd");
 	strcpy(vty_cwd, cwd);
 }
 
@@ -1613,6 +1622,8 @@
 	/* For further configuration read, preserve current directory. */
 	vty_save_cwd();
 
+	host.config = "openbsc.cfg";
+
 	vtyvec = vector_init(VECTOR_MIN_SIZE);
 
 	/* Install bgp top node. */
@@ -1635,3 +1646,8 @@
 	install_element(VTY_NODE, &no_vty_login_cmd);
 #endif
 }
+
+static __attribute__((constructor)) void on_dso_load_vty(void)
+{
+	tall_vty_ctx = talloc_named_const(NULL, 1, "vty");
+}