Create libosmovty as library from OpenBSC VTY functions
diff --git a/include/osmocom/vty/Makefile.am b/include/osmocom/vty/Makefile.am
new file mode 100644
index 0000000..e51dcb8
--- /dev/null
+++ b/include/osmocom/vty/Makefile.am
@@ -0,0 +1,2 @@
+noinst_HEADERS = buffer.h command.h  vector.h vty.h \
+		telnet_interface.h
diff --git a/include/osmocom/vty/buffer.h b/include/osmocom/vty/buffer.h
new file mode 100644
index 0000000..c9467a9
--- /dev/null
+++ b/include/osmocom/vty/buffer.h
@@ -0,0 +1,102 @@
+/*
+ * Buffering to output and input.
+ * Copyright (C) 1998 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_BUFFER_H
+#define _ZEBRA_BUFFER_H
+
+#include <sys/types.h>
+
+/* Create a new buffer.  Memory will be allocated in chunks of the given
+   size.  If the argument is 0, the library will supply a reasonable
+   default size suitable for buffering socket I/O. */
+struct buffer *buffer_new(void *ctx, size_t);
+
+/* Free all data in the buffer. */
+void buffer_reset(struct buffer *);
+
+/* This function first calls buffer_reset to release all buffered data.
+   Then it frees the struct buffer itself. */
+void buffer_free(struct buffer *);
+
+/* Add the given data to the end of the buffer. */
+extern void buffer_put(struct buffer *, const void *, size_t);
+/* Add a single character to the end of the buffer. */
+extern void buffer_putc(struct buffer *, u_char);
+/* Add a NUL-terminated string to the end of the buffer. */
+extern void buffer_putstr(struct buffer *, const char *);
+
+/* Combine all accumulated (and unflushed) data inside the buffer into a
+   single NUL-terminated string allocated using XMALLOC(MTYPE_TMP).  Note
+   that this function does not alter the state of the buffer, so the data
+   is still inside waiting to be flushed. */
+char *buffer_getstr(struct buffer *);
+
+/* Returns 1 if there is no pending data in the buffer.  Otherwise returns 0. */
+int buffer_empty(struct buffer *);
+
+typedef enum {
+	/* An I/O error occurred.  The buffer should be destroyed and the
+	   file descriptor should be closed. */
+	BUFFER_ERROR = -1,
+
+	/* The data was written successfully, and the buffer is now empty
+	   (there is no pending data waiting to be flushed). */
+	BUFFER_EMPTY = 0,
+
+	/* There is pending data in the buffer waiting to be flushed.  Please
+	   try flushing the buffer when select indicates that the file descriptor
+	   is writeable. */
+	BUFFER_PENDING = 1
+} buffer_status_t;
+
+/* Try to write this data to the file descriptor.  Any data that cannot
+   be written immediately is added to the buffer queue. */
+extern buffer_status_t buffer_write(struct buffer *, int fd,
+				    const void *, size_t);
+
+/* This function attempts to flush some (but perhaps not all) of
+   the queued data to the given file descriptor. */
+extern buffer_status_t buffer_flush_available(struct buffer *, int fd);
+
+/* The following 2 functions (buffer_flush_all and buffer_flush_window)
+   are for use in lib/vty.c only.  They should not be used elsewhere. */
+
+/* Call buffer_flush_available repeatedly until either all data has been
+   flushed, or an I/O error has been encountered, or the operation would
+   block. */
+extern buffer_status_t buffer_flush_all(struct buffer *, int fd);
+
+/* Attempt to write enough data to the given fd to fill a window of the
+   given width and height (and remove the data written from the buffer).
+
+   If !no_more, then a message saying " --More-- " is appended.
+   If erase is true, then first overwrite the previous " --More-- " message
+   with spaces.
+
+   Any write error (including EAGAIN or EINTR) will cause this function
+   to return -1 (because the logic for handling the erase and more features
+   is too complicated to retry the write later).
+*/
+extern buffer_status_t buffer_flush_window(struct buffer *, int fd, int width,
+					   int height, int erase, int no_more);
+
+#endif				/* _ZEBRA_BUFFER_H */
diff --git a/include/osmocom/vty/command.h b/include/osmocom/vty/command.h
new file mode 100644
index 0000000..1db8ffe
--- /dev/null
+++ b/include/osmocom/vty/command.h
@@ -0,0 +1,392 @@
+/*
+ * Zebra configuration command interface routine
+ * Copyright (C) 1997, 98 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_COMMAND_H
+#define _ZEBRA_COMMAND_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "vector.h"
+#include "vty.h"
+
+/* Host configuration variable */
+struct host {
+	/* Host name of this router. */
+	char *name;
+
+	/* Password for vty interface. */
+	char *password;
+	char *password_encrypt;
+
+	/* Enable password */
+	char *enable;
+	char *enable_encrypt;
+
+	/* System wide terminal lines. */
+	int lines;
+
+	/* Log filename. */
+	char *logfile;
+
+	/* config file name of this host */
+	char *config;
+
+	/* Flags for services */
+	int advanced;
+	int encrypt;
+
+	/* Banner configuration. */
+	const char *motd;
+	char *motdfile;
+
+	const char *prog_name;
+	const char *prog_version;
+	const char *prog_copyright;
+};
+
+/* There are some command levels which called from command node. */
+enum node_type {
+	AUTH_NODE,		/* Authentication mode of vty interface. */
+	VIEW_NODE,		/* View node. Default mode of vty interface. */
+	AUTH_ENABLE_NODE,	/* Authentication mode for change enable. */
+	ENABLE_NODE,		/* Enable node. */
+	CONFIG_NODE,		/* Config node. Default mode of config file. */
+	SERVICE_NODE,		/* Service node. */
+	DEBUG_NODE,		/* Debug node. */
+#if 0
+	AAA_NODE,		/* AAA node. */
+	KEYCHAIN_NODE,		/* Key-chain node. */
+	KEYCHAIN_KEY_NODE,	/* Key-chain key node. */
+	INTERFACE_NODE,		/* Interface mode node. */
+	ZEBRA_NODE,		/* zebra connection node. */
+	TABLE_NODE,		/* rtm_table selection node. */
+	RIP_NODE,		/* RIP protocol mode node. */
+	RIPNG_NODE,		/* RIPng protocol mode node. */
+	BGP_NODE,		/* BGP protocol mode which includes BGP4+ */
+	BGP_VPNV4_NODE,		/* BGP MPLS-VPN PE exchange. */
+	BGP_IPV4_NODE,		/* BGP IPv4 unicast address family.  */
+	BGP_IPV4M_NODE,		/* BGP IPv4 multicast address family.  */
+	BGP_IPV6_NODE,		/* BGP IPv6 address family */
+	OSPF_NODE,		/* OSPF protocol mode */
+	OSPF6_NODE,		/* OSPF protocol for IPv6 mode */
+	ISIS_NODE,		/* ISIS protocol mode */
+	MASC_NODE,		/* MASC for multicast.  */
+	IRDP_NODE,		/* ICMP Router Discovery Protocol mode. */
+	IP_NODE,		/* Static ip route node. */
+	ACCESS_NODE,		/* Access list node. */
+	PREFIX_NODE,		/* Prefix list node. */
+	ACCESS_IPV6_NODE,	/* Access list node. */
+	PREFIX_IPV6_NODE,	/* Prefix list node. */
+	AS_LIST_NODE,		/* AS list node. */
+	COMMUNITY_LIST_NODE,	/* Community list node. */
+	RMAP_NODE,		/* Route map node. */
+	SMUX_NODE,		/* SNMP configuration node. */
+	DUMP_NODE,		/* Packet dump node. */
+	FORWARDING_NODE,	/* IP forwarding node. */
+#endif
+	VTY_NODE,		/* Vty node. */
+
+	GSMNET_NODE,
+	BTS_NODE,
+	TRX_NODE,
+	TS_NODE,
+	SUBSCR_NODE,
+	MGCP_NODE,
+	GBPROXY_NODE,
+	SGSN_NODE,
+	NS_NODE,
+	BSSGP_NODE,
+};
+
+/* Node which has some commands and prompt string and configuration
+   function pointer . */
+struct cmd_node {
+	/* Node index. */
+	enum node_type node;
+
+	/* Prompt character at vty interface. */
+	const char *prompt;
+
+	/* Is this node's configuration goes to vtysh ? */
+	int vtysh;
+
+	/* Node's configuration write function */
+	int (*func) (struct vty *);
+
+	/* Vector of this node's command list. */
+	vector cmd_vector;
+};
+
+enum {
+	CMD_ATTR_DEPRECATED = 1,
+	CMD_ATTR_HIDDEN,
+};
+
+/* Structure of command element. */
+struct cmd_element {
+	const char *string;	/* Command specification by string. */
+	int (*func) (struct cmd_element *, struct vty *, int, const char *[]);
+	const char *doc;	/* Documentation of this command. */
+	int daemon;		/* Daemon to which this command belong. */
+	vector strvec;		/* Pointing out each description vector. */
+	unsigned int cmdsize;	/* Command index count. */
+	char *config;		/* Configuration string */
+	vector subconfig;	/* Sub configuration string */
+	u_char attr;		/* Command attributes */
+};
+
+/* Command description structure. */
+struct desc {
+	const char *cmd;	/* Command string. */
+	const char *str;	/* Command's description. */
+};
+
+/* Return value of the commands. */
+#define CMD_SUCCESS              0
+#define CMD_WARNING              1
+#define CMD_ERR_NO_MATCH         2
+#define CMD_ERR_AMBIGUOUS        3
+#define CMD_ERR_INCOMPLETE       4
+#define CMD_ERR_EXEED_ARGC_MAX   5
+#define CMD_ERR_NOTHING_TODO     6
+#define CMD_COMPLETE_FULL_MATCH  7
+#define CMD_COMPLETE_MATCH       8
+#define CMD_COMPLETE_LIST_MATCH  9
+#define CMD_SUCCESS_DAEMON      10
+
+/* Argc max counts. */
+#define CMD_ARGC_MAX   25
+
+/* Turn off these macros when uisng cpp with extract.pl */
+#ifndef VTYSH_EXTRACT_PL
+
+/* helper defines for end-user DEFUN* macros */
+#define DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
+  static struct cmd_element cmdname = \
+  { \
+    .string = cmdstr, \
+    .func = funcname, \
+    .doc = helpstr, \
+    .attr = attrs, \
+    .daemon = dnum, \
+  };
+
+/* global (non static) cmd_element */
+#define gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attrs, dnum) \
+  struct cmd_element cmdname = \
+  { \
+    .string = cmdstr, \
+    .func = funcname, \
+    .doc = helpstr, \
+    .attr = attrs, \
+    .daemon = dnum, \
+  };
+
+#define DEFUN_CMD_FUNC_DECL(funcname) \
+  static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \
+
+#define DEFUN_CMD_FUNC_TEXT(funcname) \
+  static int funcname \
+    (struct cmd_element *self, struct vty *vty, int argc, const char *argv[])
+
+/* DEFUN for vty command interafce. Little bit hacky ;-). */
+#define DEFUN(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_FUNC_DECL(funcname) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
+  DEFUN_CMD_FUNC_TEXT(funcname)
+
+/* global (non static) cmd_element */
+#define gDEFUN(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_FUNC_DECL(funcname) \
+  gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) \
+  DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUN_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
+  DEFUN_CMD_FUNC_DECL(funcname) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) \
+  DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUN_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
+
+#define DEFUN_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_ATTR (funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) \
+
+/* DEFUN_NOSH for commands that vtysh should ignore */
+#define DEFUN_NOSH(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN(funcname, cmdname, cmdstr, helpstr)
+
+/* DEFSH for vtysh. */
+#define DEFSH(daemon, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(NULL, cmdname, cmdstr, helpstr, 0, daemon) \
+
+/* DEFUN + DEFSH */
+#define DEFUNSH(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_FUNC_DECL(funcname) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \
+  DEFUN_CMD_FUNC_TEXT(funcname)
+
+/* DEFUN + DEFSH with attributes */
+#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \
+  DEFUN_CMD_FUNC_DECL(funcname) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \
+  DEFUN_CMD_FUNC_TEXT(funcname)
+
+#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN)
+
+#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED)
+
+/* ALIAS macro which define existing command's alias. */
+#define ALIAS(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
+
+/* global (non static) cmd_element */
+#define gALIAS(funcname, cmdname, cmdstr, helpstr) \
+  gDEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0)
+
+#define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0)
+
+#define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0)
+
+#define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0)
+
+#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon)
+
+#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon)
+
+#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \
+  DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon)
+
+#endif				/* VTYSH_EXTRACT_PL */
+
+/* Some macroes */
+#define CMD_OPTION(S)   ((S[0]) == '[')
+#define CMD_VARIABLE(S) (((S[0]) >= 'A' && (S[0]) <= 'Z') || ((S[0]) == '<'))
+#define CMD_VARARG(S)   ((S[0]) == '.')
+#define CMD_RANGE(S)	((S[0] == '<'))
+
+#define CMD_IPV4(S)	   ((strcmp ((S), "A.B.C.D") == 0))
+#define CMD_IPV4_PREFIX(S) ((strcmp ((S), "A.B.C.D/M") == 0))
+#define CMD_IPV6(S)        ((strcmp ((S), "X:X::X:X") == 0))
+#define CMD_IPV6_PREFIX(S) ((strcmp ((S), "X:X::X:X/M") == 0))
+
+/* Common descriptions. */
+#define SHOW_STR "Show running system information\n"
+#define IP_STR "IP information\n"
+#define IPV6_STR "IPv6 information\n"
+#define NO_STR "Negate a command or set its defaults\n"
+#define CLEAR_STR "Reset functions\n"
+#define RIP_STR "RIP information\n"
+#define BGP_STR "BGP information\n"
+#define OSPF_STR "OSPF information\n"
+#define NEIGHBOR_STR "Specify neighbor router\n"
+#define DEBUG_STR "Debugging functions (see also 'undebug')\n"
+#define UNDEBUG_STR "Disable debugging functions (see also 'debug')\n"
+#define ROUTER_STR "Enable a routing process\n"
+#define AS_STR "AS number\n"
+#define MBGP_STR "MBGP information\n"
+#define MATCH_STR "Match values from routing table\n"
+#define SET_STR "Set values in destination routing protocol\n"
+#define OUT_STR "Filter outgoing routing updates\n"
+#define IN_STR  "Filter incoming routing updates\n"
+#define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n"
+#define OSPF6_NUMBER_STR "Specify by number\n"
+#define INTERFACE_STR "Interface infomation\n"
+#define IFNAME_STR "Interface name(e.g. ep0)\n"
+#define IP6_STR "IPv6 Information\n"
+#define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n"
+#define OSPF6_ROUTER_STR "Enable a routing process\n"
+#define OSPF6_INSTANCE_STR "<1-65535> Instance ID\n"
+#define SECONDS_STR "<1-65535> Seconds\n"
+#define ROUTE_STR "Routing Table\n"
+#define PREFIX_LIST_STR "Build a prefix list\n"
+#define OSPF6_DUMP_TYPE_LIST \
+"(neighbor|interface|area|lsa|zebra|config|dbex|spf|route|lsdb|redistribute|hook|asbr|prefix|abr)"
+#define ISIS_STR "IS-IS information\n"
+#define AREA_TAG_STR "[area tag]\n"
+
+#define CONF_BACKUP_EXT ".sav"
+
+/* IPv4 only machine should not accept IPv6 address for peer's IP
+   address.  So we replace VTY command string like below. */
+#ifdef HAVE_IPV6
+#define NEIGHBOR_CMD       "neighbor (A.B.C.D|X:X::X:X) "
+#define NO_NEIGHBOR_CMD    "no neighbor (A.B.C.D|X:X::X:X) "
+#define NEIGHBOR_ADDR_STR  "Neighbor address\nIPv6 address\n"
+#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|X:X::X:X|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor IPv6 address\nNeighbor tag\n"
+#else
+#define NEIGHBOR_CMD       "neighbor A.B.C.D "
+#define NO_NEIGHBOR_CMD    "no neighbor A.B.C.D "
+#define NEIGHBOR_ADDR_STR  "Neighbor address\n"
+#define NEIGHBOR_CMD2      "neighbor (A.B.C.D|WORD) "
+#define NO_NEIGHBOR_CMD2   "no neighbor (A.B.C.D|WORD) "
+#define NEIGHBOR_ADDR_STR2 "Neighbor address\nNeighbor tag\n"
+#endif				/* HAVE_IPV6 */
+
+/* Prototypes. */
+void install_node(struct cmd_node *, int (*)(struct vty *));
+void install_default(enum node_type);
+void install_element(enum node_type, struct cmd_element *);
+void install_element_ve(struct cmd_element *cmd);
+void sort_node();
+
+/* Concatenates argv[shift] through argv[argc-1] into a single NUL-terminated
+   string with a space between each element (allocated using
+   XMALLOC(MTYPE_TMP)).  Returns NULL if shift >= argc. */
+char *argv_concat(const char **argv, int argc, int shift);
+
+vector cmd_make_strvec(const char *);
+void cmd_free_strvec(vector);
+vector cmd_describe_command();
+char **cmd_complete_command();
+const char *cmd_prompt(enum node_type);
+int config_from_file(struct vty *, FILE *);
+enum node_type node_parent(enum node_type);
+int cmd_execute_command(vector, struct vty *, struct cmd_element **, int);
+int cmd_execute_command_strict(vector, struct vty *, struct cmd_element **);
+void config_replace_string(struct cmd_element *, char *, ...);
+void cmd_init(int);
+
+/* Export typical functions. */
+extern struct cmd_element config_exit_cmd;
+extern struct cmd_element config_help_cmd;
+extern struct cmd_element config_list_cmd;
+char *host_config_file();
+void host_config_set(const char *);
+
+/* This is called from main when a daemon is invoked with -v or --version. */
+void print_version(int print_copyright);
+
+extern void *tall_vty_cmd_ctx;
+
+enum node_type (*vty_go_parent_cb)(struct vty *vty);
+
+#endif				/* _ZEBRA_COMMAND_H */
diff --git a/include/osmocom/vty/logging.h b/include/osmocom/vty/logging.h
new file mode 100644
index 0000000..f8ffbc3
--- /dev/null
+++ b/include/osmocom/vty/logging.h
@@ -0,0 +1,7 @@
+#ifndef _VTY_LOGGING_H
+#define _VTY_LOGGING_H
+
+#define LOGGING_STR	"Configure log message to this terminal\n"
+#define FILTER_STR	"Filter log messages\n"
+
+#endif /* _VTY_LOGGING_H */
diff --git a/include/osmocom/vty/telnet_interface.h b/include/osmocom/vty/telnet_interface.h
new file mode 100644
index 0000000..444e649
--- /dev/null
+++ b/include/osmocom/vty/telnet_interface.h
@@ -0,0 +1,40 @@
+/* minimalistic telnet/network interface it might turn into a wire interface */
+/* (C) 2009 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 General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef TELNET_INTERFACE_H
+#define TELNET_INTERFACE_H
+
+#include <osmocore/logging.h>
+#include <osmocore/select.h>
+
+#include <osmocom/vty/vty.h>
+
+struct telnet_connection {
+	struct llist_head entry;
+	void *priv;
+	struct bsc_fd fd;
+	struct vty *vty;
+	struct log_target *dbg;
+};
+
+
+int telnet_init(void *tall_ctx, void *priv, int port);
+
+#endif
diff --git a/include/osmocom/vty/vector.h b/include/osmocom/vty/vector.h
new file mode 100644
index 0000000..22a184d
--- /dev/null
+++ b/include/osmocom/vty/vector.h
@@ -0,0 +1,64 @@
+/*
+ * Generic vector interface header.
+ * Copyright (C) 1997, 98 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_VECTOR_H
+#define _ZEBRA_VECTOR_H
+
+/* struct for vector */
+struct _vector {
+	unsigned int active;	/* number of active slots */
+	unsigned int alloced;	/* number of allocated slot */
+	void **index;		/* index to data */
+};
+typedef struct _vector *vector;
+
+#define VECTOR_MIN_SIZE 1
+
+/* (Sometimes) usefull macros.  This macro convert index expression to
+ array expression. */
+/* Reference slot at given index, caller must ensure slot is active */
+#define vector_slot(V,I)  ((V)->index[(I)])
+/* Number of active slots.
+ * Note that this differs from vector_count() as it the count returned
+ * will include any empty slots
+ */
+#define vector_active(V) ((V)->active)
+
+/* Prototypes. */
+vector vector_init(unsigned int size);
+void vector_ensure(vector v, unsigned int num);
+int vector_empty_slot(vector v);
+int vector_set(vector v, void *val);
+int vector_set_index(vector v, unsigned int i, void *val);
+void vector_unset(vector v, unsigned int i);
+unsigned int vector_count(vector v);
+void vector_only_wrapper_free(vector v);
+void vector_only_index_free(void *index);
+void vector_free(vector v);
+vector vector_copy(vector v);
+
+void *vector_lookup(vector, unsigned int);
+void *vector_lookup_ensure(vector, unsigned int);
+
+extern void *tall_vty_vec_ctx;
+
+#endif				/* _ZEBRA_VECTOR_H */
diff --git a/include/osmocom/vty/vty.h b/include/osmocom/vty/vty.h
new file mode 100644
index 0000000..f82ada1
--- /dev/null
+++ b/include/osmocom/vty/vty.h
@@ -0,0 +1,151 @@
+#ifndef _VTY_H
+#define _VTY_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* GCC have printf type attribute check.  */
+#ifdef __GNUC__
+#define VTY_PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
+#else
+#define VTY_PRINTF_ATTRIBUTE(a,b)
+#endif				/* __GNUC__ */
+
+/* Does the I/O error indicate that the operation should be retried later? */
+#define ERRNO_IO_RETRY(EN) \
+	(((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR))
+
+/* Vty read buffer size. */
+#define VTY_READ_BUFSIZ 512
+
+#define VTY_BUFSIZ 512
+#define VTY_MAXHIST 20
+
+/* Vty events */
+enum event {
+	VTY_SERV,
+	VTY_READ,
+	VTY_WRITE,
+	VTY_CLOSED,
+	VTY_TIMEOUT_RESET,
+#ifdef VTYSH
+	VTYSH_SERV,
+	VTYSH_READ,
+	VTYSH_WRITE
+#endif				/* VTYSH */
+};
+
+struct vty {
+	FILE *file;
+
+	/* private data, specified by creator */
+	void *priv;
+
+	/* File descripter of this vty. */
+	int fd;
+
+	/* Is this vty connect to file or not */
+	enum { VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV } type;
+
+	/* Node status of this vty */
+	int node;
+
+	/* Failure count */
+	int fail;
+
+	/* Output buffer. */
+	struct buffer *obuf;
+
+	/* Command input buffer */
+	char *buf;
+
+	/* Command cursor point */
+	int cp;
+
+	/* Command length */
+	int length;
+
+	/* Command max length. */
+	int max;
+
+	/* Histry of command */
+	char *hist[VTY_MAXHIST];
+
+	/* History lookup current point */
+	int hp;
+
+	/* History insert end point */
+	int hindex;
+
+	/* For current referencing point of interface, route-map,
+	   access-list etc... */
+	void *index;
+
+	/* For multiple level index treatment such as key chain and key. */
+	void *index_sub;
+
+	/* For escape character. */
+	unsigned char escape;
+
+	/* Current vty status. */
+	enum { VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE } status;
+
+	/* IAC handling: was the last character received the IAC
+	 * (interpret-as-command) escape character (and therefore the next
+	 * character will be the command code)?  Refer to Telnet RFC 854. */
+	unsigned char iac;
+
+	/* IAC SB (option subnegotiation) handling */
+	unsigned char iac_sb_in_progress;
+	/* At the moment, we care only about the NAWS (window size) negotiation,
+	 * and that requires just a 5-character buffer (RFC 1073):
+	 * <NAWS char> <16-bit width> <16-bit height> */
+#define TELNET_NAWS_SB_LEN 5
+	unsigned char sb_buf[TELNET_NAWS_SB_LEN];
+	/* How many subnegotiation characters have we received?  We just drop
+	 * those that do not fit in the buffer. */
+	size_t sb_len;
+
+	/* Window width/height. */
+	int width;
+	int height;
+
+	/* Configure lines. */
+	int lines;
+
+	int monitor;
+
+	/* In configure mode. */
+	int config;
+};
+
+/* Small macro to determine newline is newline only or linefeed needed. */
+#define VTY_NEWLINE  ((vty->type == VTY_TERM) ? "\r\n" : "\n")
+
+static inline char *vty_newline(struct vty *vty)
+{
+	return VTY_NEWLINE;
+}
+
+/* Prototypes. */
+void vty_init(const char *name, const char *version, const char *copyright);
+int vty_read_config_file(const char *file_name, void *priv);
+void vty_init_vtysh (void);
+void vty_reset (void);
+struct vty *vty_new (void);
+struct vty *vty_create (int vty_sock, void *priv);
+int vty_out (struct vty *, const char *, ...) VTY_PRINTF_ATTRIBUTE(2, 3);
+int vty_out_newline(struct vty *);
+int vty_read(struct vty *vty);
+//void vty_time_print (struct vty *, int);
+void vty_close (struct vty *);
+char *vty_get_cwd (void);
+void vty_log (const char *level, const char *proto, const char *fmt, va_list);
+int vty_config_lock (struct vty *);
+int vty_config_unlock (struct vty *);
+int vty_shell (struct vty *);
+int vty_shell_serv (struct vty *);
+void vty_hello (struct vty *);
+
+void *tall_vty_ctx;
+#endif