diff --git a/patches/openwrt/hack/0001-busybox-Provide-static-busybox-build.patch b/patches/openwrt/hack/0001-busybox-Provide-static-busybox-build.patch
index fcdc064f05815b44ec303da8dd16ec16ce4f8630..c23b88d6eb15429ba5971b5a4f89f1a58e29a5e1 100644
--- a/patches/openwrt/hack/0001-busybox-Provide-static-busybox-build.patch
+++ b/patches/openwrt/hack/0001-busybox-Provide-static-busybox-build.patch
@@ -1,4 +1,4 @@
-From e9f0f3abcd314708048b784c927209987d697e5e Mon Sep 17 00:00:00 2001
+From 841ee10970e1951bb3af23c149edd18cfe0e77c4 Mon Sep 17 00:00:00 2001
 From: Michal Hrusecky <Michal@Hrusecky.net>
 Date: Thu, 22 Feb 2018 14:46:46 +0100
 Subject: [PATCH] busybox: Provide static busybox build
@@ -7,16 +7,14 @@ Can be handy, but currently it is quite hacky.
 
 Signed-off-by: Michal Hrusecky <Michal@Hrusecky.net>
 ---
- package/utils/busybox/Makefile                    |   38 +
- package/utils/busybox/files/busybox-static.config | 1127 +++++++++++++++++++++
- 2 files changed, 1165 insertions(+)
- create mode 100644 package/utils/busybox/files/busybox-static.config
+ package/utils/busybox/Makefile | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
 
 diff --git a/package/utils/busybox/Makefile b/package/utils/busybox/Makefile
-index 4f85cc9..fc882d3 100644
+index 315dd42..1965658 100644
 --- a/package/utils/busybox/Makefile
 +++ b/package/utils/busybox/Makefile
-@@ -67,6 +67,20 @@ define Package/busybox/description
+@@ -66,6 +66,20 @@ define Package/busybox/description
   It slices, it dices, it makes Julian Fries.
  endef
  
@@ -37,8 +35,8 @@ index 4f85cc9..fc882d3 100644
  define Package/busybox/config
  	source "$(SOURCE)/Config.in"
  endef
-@@ -98,8 +112,21 @@ MAKE_INSTALL_FLAGS += CONFIG_PREFIX="$(PKG_INSTALL_DIR)"
- 
+@@ -101,11 +115,20 @@ ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
+ endif
  
  define Build/Configure
 +	cp ./files/busybox-static.config $(PKG_BUILD_DIR)/.config
@@ -48,18 +46,17 @@ index 4f85cc9..fc882d3 100644
  	grep 'CONFIG_BUSYBOX_$(BUSYBOX_SYM)' $(TOPDIR)/.config | sed -e "s,\\(# \)\\?CONFIG_BUSYBOX_$(BUSYBOX_SYM)_\\(.*\\),\\1CONFIG_\\2,g" > $(PKG_BUILD_DIR)/.config
  	yes 'n' | $(MAKE) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) oldconfig
 +	mv $(PKG_BUILD_DIR)/.config $(PKG_BUILD_DIR)/.config-regular
-+endef
-+
-+define Build/Compile
+ endef
+ 
+ define Build/Compile
 +	cp $(PKG_BUILD_DIR)/.config-static $(PKG_BUILD_DIR)/.config
 +	$(call Build/Compile/Default)
 +	cp $(PKG_BUILD_DIR)/busybox $(PKG_BUILD_DIR)/busybox-static
 +	cp $(PKG_BUILD_DIR)/.config-regular $(PKG_BUILD_DIR)/.config
-+	$(call Build/Compile/Default)
- endef
- 
- define Package/busybox/install
-@@ -115,4 +142,15 @@ endif
+ 	$(call Build/Compile/Default, \
+ 		CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \
+ 		all install \
+@@ -125,4 +148,15 @@ endif
  	-rm -rf $(1)/lib64
  endef
  
@@ -75,1139 +72,6 @@ index 4f85cc9..fc882d3 100644
 +
  $(eval $(call BuildPackage,busybox))
 +$(eval $(call BuildPackage,busybox-static))
-diff --git a/package/utils/busybox/files/busybox-static.config b/package/utils/busybox/files/busybox-static.config
-new file mode 100644
-index 0000000..c059272
---- /dev/null
-+++ b/package/utils/busybox/files/busybox-static.config
-@@ -0,0 +1,1127 @@
-+#
-+# Automatically generated make config: don't edit
-+# Busybox version: 1.27.2
-+# Fri Feb 23 14:47:40 2018
-+#
-+CONFIG_HAVE_DOT_CONFIG=y
-+
-+#
-+# Busybox Settings
-+#
-+# CONFIG_DESKTOP is not set
-+# CONFIG_EXTRA_COMPAT is not set
-+# CONFIG_FEDORA_COMPAT is not set
-+CONFIG_INCLUDE_SUSv2=y
-+# CONFIG_USE_PORTABLE_CODE is not set
-+CONFIG_SHOW_USAGE=y
-+CONFIG_FEATURE_VERBOSE_USAGE=y
-+CONFIG_FEATURE_COMPRESS_USAGE=y
-+CONFIG_BUSYBOX=y
-+# CONFIG_FEATURE_INSTALLER is not set
-+# CONFIG_INSTALL_NO_USR is not set
-+# CONFIG_PAM is not set
-+CONFIG_LONG_OPTS=y
-+CONFIG_FEATURE_DEVPTS=y
-+# CONFIG_FEATURE_CLEAN_UP is not set
-+# CONFIG_FEATURE_UTMP is not set
-+# CONFIG_FEATURE_WTMP is not set
-+CONFIG_FEATURE_PIDFILE=y
-+CONFIG_PID_FILE_PATH="/var/run"
-+CONFIG_FEATURE_SUID=y
-+# CONFIG_FEATURE_SUID_CONFIG is not set
-+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
-+# CONFIG_SELINUX is not set
-+CONFIG_FEATURE_PREFER_APPLETS=y
-+CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe"
-+# CONFIG_FEATURE_SYSLOG is not set
-+# CONFIG_FEATURE_HAVE_RPC is not set
-+CONFIG_PLATFORM_LINUX=y
-+
-+#
-+# Build Options
-+#
-+CONFIG_STATIC=y
-+# CONFIG_PIE is not set
-+# CONFIG_NOMMU is not set
-+# CONFIG_BUILD_LIBBUSYBOX is not set
-+# CONFIG_FEATURE_INDIVIDUAL is not set
-+# CONFIG_FEATURE_SHARED_BUSYBOX is not set
-+CONFIG_LFS=y
-+CONFIG_CROSS_COMPILER_PREFIX=""
-+CONFIG_SYSROOT=""
-+CONFIG_EXTRA_CFLAGS=""
-+CONFIG_EXTRA_LDFLAGS=""
-+CONFIG_EXTRA_LDLIBS=""
-+
-+#
-+# Installation Options ("make install" behavior)
-+#
-+CONFIG_INSTALL_APPLET_SYMLINKS=y
-+# CONFIG_INSTALL_APPLET_HARDLINKS is not set
-+# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set
-+# CONFIG_INSTALL_APPLET_DONT is not set
-+# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set
-+# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set
-+# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set
-+CONFIG_PREFIX="./_install"
-+
-+#
-+# Debugging Options
-+#
-+# CONFIG_DEBUG is not set
-+# CONFIG_DEBUG_PESSIMIZE is not set
-+# CONFIG_DEBUG_SANITIZE is not set
-+# CONFIG_UNIT_TEST is not set
-+# CONFIG_WERROR is not set
-+CONFIG_NO_DEBUG_LIB=y
-+# CONFIG_DMALLOC is not set
-+# CONFIG_EFENCE is not set
-+
-+#
-+# Busybox Library Tuning
-+#
-+# CONFIG_FEATURE_USE_BSS_TAIL is not set
-+# CONFIG_FEATURE_RTMINMAX is not set
-+# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set
-+CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y
-+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
-+CONFIG_PASSWORD_MINLEN=6
-+CONFIG_MD5_SMALL=1
-+CONFIG_SHA3_SMALL=1
-+CONFIG_FEATURE_FAST_TOP=y
-+# CONFIG_FEATURE_ETC_NETWORKS is not set
-+CONFIG_FEATURE_EDITING=y
-+CONFIG_FEATURE_EDITING_MAX_LEN=512
-+# CONFIG_FEATURE_EDITING_VI is not set
-+CONFIG_FEATURE_EDITING_HISTORY=256
-+# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set
-+# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set
-+CONFIG_FEATURE_REVERSE_SEARCH=y
-+CONFIG_FEATURE_TAB_COMPLETION=y
-+# CONFIG_FEATURE_USERNAME_COMPLETION is not set
-+CONFIG_FEATURE_EDITING_FANCY_PROMPT=y
-+# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set
-+# CONFIG_LOCALE_SUPPORT is not set
-+# CONFIG_UNICODE_SUPPORT is not set
-+# CONFIG_UNICODE_USING_LOCALE is not set
-+# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set
-+CONFIG_SUBST_WCHAR=0
-+CONFIG_LAST_SUPPORTED_WCHAR=0
-+# CONFIG_UNICODE_COMBINING_WCHARS is not set
-+# CONFIG_UNICODE_WIDE_WCHARS is not set
-+# CONFIG_UNICODE_BIDI_SUPPORT is not set
-+# CONFIG_UNICODE_NEUTRAL_TABLE is not set
-+# CONFIG_UNICODE_PRESERVE_BROKEN is not set
-+CONFIG_FEATURE_NON_POSIX_CP=y
-+# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set
-+# CONFIG_FEATURE_USE_SENDFILE is not set
-+CONFIG_FEATURE_COPYBUF_KB=4
-+# CONFIG_FEATURE_SKIP_ROOTFS is not set
-+# CONFIG_MONOTONIC_SYSCALL is not set
-+CONFIG_IOCTL_HEX2STR_ERROR=y
-+# CONFIG_FEATURE_HWIB is not set
-+
-+#
-+# Applets
-+#
-+
-+#
-+# Archival Utilities
-+#
-+# CONFIG_FEATURE_SEAMLESS_XZ is not set
-+# CONFIG_FEATURE_SEAMLESS_LZMA is not set
-+CONFIG_FEATURE_SEAMLESS_BZ2=y
-+CONFIG_FEATURE_SEAMLESS_GZ=y
-+# CONFIG_FEATURE_SEAMLESS_Z is not set
-+# CONFIG_AR is not set
-+# CONFIG_FEATURE_AR_LONG_FILENAMES is not set
-+# CONFIG_FEATURE_AR_CREATE is not set
-+# CONFIG_UNCOMPRESS is not set
-+CONFIG_GUNZIP=y
-+CONFIG_ZCAT=y
-+CONFIG_FEATURE_GUNZIP_LONG_OPTIONS=y
-+CONFIG_BUNZIP2=y
-+CONFIG_BZCAT=y
-+# CONFIG_UNLZMA is not set
-+CONFIG_LZCAT=y
-+# CONFIG_LZMA is not set
-+# CONFIG_FEATURE_LZMA_FAST is not set
-+# CONFIG_UNXZ is not set
-+CONFIG_XZCAT=y
-+# CONFIG_XZ is not set
-+# CONFIG_BZIP2 is not set
-+CONFIG_FEATURE_BZIP2_DECOMPRESS=y
-+# CONFIG_CPIO is not set
-+# CONFIG_FEATURE_CPIO_O is not set
-+# CONFIG_FEATURE_CPIO_P is not set
-+# CONFIG_DPKG is not set
-+# CONFIG_DPKG_DEB is not set
-+CONFIG_GZIP=y
-+# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set
-+CONFIG_GZIP_FAST=0
-+# CONFIG_FEATURE_GZIP_LEVELS is not set
-+CONFIG_FEATURE_GZIP_DECOMPRESS=y
-+# CONFIG_LZOP is not set
-+# CONFIG_UNLZOP is not set
-+# CONFIG_LZOPCAT is not set
-+# CONFIG_LZOP_COMPR_HIGH is not set
-+# CONFIG_RPM2CPIO is not set
-+# CONFIG_RPM is not set
-+CONFIG_TAR=y
-+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
-+CONFIG_FEATURE_TAR_CREATE=y
-+# CONFIG_FEATURE_TAR_AUTODETECT is not set
-+CONFIG_FEATURE_TAR_FROM=y
-+# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set
-+# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set
-+CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
-+# CONFIG_FEATURE_TAR_TO_COMMAND is not set
-+# CONFIG_FEATURE_TAR_UNAME_GNAME is not set
-+# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set
-+# CONFIG_FEATURE_TAR_SELINUX is not set
-+# CONFIG_UNZIP is not set
-+# CONFIG_FEATURE_UNZIP_CDF is not set
-+# CONFIG_FEATURE_UNZIP_BZIP2 is not set
-+# CONFIG_FEATURE_UNZIP_LZMA is not set
-+# CONFIG_FEATURE_UNZIP_XZ is not set
-+
-+#
-+# Coreutils
-+#
-+CONFIG_BASENAME=y
-+CONFIG_CAT=y
-+CONFIG_FEATURE_CATV=y
-+CONFIG_CHGRP=y
-+CONFIG_CHMOD=y
-+CONFIG_CHOWN=y
-+# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set
-+CONFIG_CHROOT=y
-+# CONFIG_CKSUM is not set
-+# CONFIG_COMM is not set
-+CONFIG_CP=y
-+# CONFIG_FEATURE_CP_LONG_OPTIONS is not set
-+CONFIG_CUT=y
-+CONFIG_DATE=y
-+CONFIG_FEATURE_DATE_ISOFMT=y
-+# CONFIG_FEATURE_DATE_NANO is not set
-+# CONFIG_FEATURE_DATE_COMPAT is not set
-+CONFIG_DD=y
-+CONFIG_FEATURE_DD_SIGNAL_HANDLING=y
-+# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set
-+CONFIG_FEATURE_DD_IBS_OBS=y
-+# CONFIG_FEATURE_DD_STATUS is not set
-+CONFIG_DF=y
-+# CONFIG_FEATURE_DF_FANCY is not set
-+CONFIG_DIRNAME=y
-+# CONFIG_DOS2UNIX is not set
-+# CONFIG_UNIX2DOS is not set
-+CONFIG_DU=y
-+CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y
-+CONFIG_ECHO=y
-+CONFIG_FEATURE_FANCY_ECHO=y
-+CONFIG_ENV=y
-+# CONFIG_FEATURE_ENV_LONG_OPTIONS is not set
-+# CONFIG_EXPAND is not set
-+# CONFIG_FEATURE_EXPAND_LONG_OPTIONS is not set
-+# CONFIG_UNEXPAND is not set
-+# CONFIG_FEATURE_UNEXPAND_LONG_OPTIONS is not set
-+CONFIG_EXPR=y
-+CONFIG_EXPR_MATH_SUPPORT_64=y
-+CONFIG_FACTOR=y
-+CONFIG_FALSE=y
-+# CONFIG_FOLD is not set
-+# CONFIG_FSYNC is not set
-+CONFIG_HEAD=y
-+CONFIG_FEATURE_FANCY_HEAD=y
-+# CONFIG_HOSTID is not set
-+CONFIG_ID=y
-+# CONFIG_GROUPS is not set
-+CONFIG_INSTALL=y
-+CONFIG_FEATURE_INSTALL_LONG_OPTIONS=y
-+CONFIG_LINK=y
-+CONFIG_LN=y
-+# CONFIG_LOGNAME is not set
-+CONFIG_LS=y
-+CONFIG_FEATURE_LS_FILETYPES=y
-+CONFIG_FEATURE_LS_FOLLOWLINKS=y
-+CONFIG_FEATURE_LS_RECURSIVE=y
-+CONFIG_FEATURE_LS_WIDTH=y
-+CONFIG_FEATURE_LS_SORTFILES=y
-+CONFIG_FEATURE_LS_TIMESTAMPS=y
-+CONFIG_FEATURE_LS_USERNAME=y
-+CONFIG_FEATURE_LS_COLOR=y
-+CONFIG_FEATURE_LS_COLOR_IS_DEFAULT=y
-+CONFIG_MD5SUM=y
-+# CONFIG_SHA1SUM is not set
-+CONFIG_SHA256SUM=y
-+CONFIG_SHA512SUM=y
-+# CONFIG_SHA3SUM is not set
-+
-+#
-+# Common options for md5sum, sha1sum, sha256sum, sha512sum, sha3sum
-+#
-+CONFIG_FEATURE_MD5_SHA1_SUM_CHECK=y
-+CONFIG_MKDIR=y
-+# CONFIG_FEATURE_MKDIR_LONG_OPTIONS is not set
-+# CONFIG_MKFIFO is not set
-+# CONFIG_MKNOD is not set
-+# CONFIG_MKTEMP is not set
-+CONFIG_MV=y
-+# CONFIG_FEATURE_MV_LONG_OPTIONS is not set
-+# CONFIG_NICE is not set
-+CONFIG_NL=y
-+# CONFIG_NOHUP is not set
-+CONFIG_NPROC=y
-+# CONFIG_OD is not set
-+CONFIG_PASTE=y
-+# CONFIG_PRINTENV is not set
-+CONFIG_PRINTF=y
-+CONFIG_PWD=y
-+CONFIG_READLINK=y
-+CONFIG_FEATURE_READLINK_FOLLOW=y
-+# CONFIG_REALPATH is not set
-+CONFIG_RM=y
-+CONFIG_RMDIR=y
-+# CONFIG_FEATURE_RMDIR_LONG_OPTIONS is not set
-+CONFIG_SEQ=y
-+CONFIG_SHRED=y
-+# CONFIG_SHUF is not set
-+CONFIG_SLEEP=y
-+CONFIG_FEATURE_FANCY_SLEEP=y
-+CONFIG_FEATURE_FLOAT_SLEEP=y
-+CONFIG_SORT=y
-+# CONFIG_FEATURE_SORT_BIG is not set
-+# CONFIG_SPLIT is not set
-+# CONFIG_FEATURE_SPLIT_FANCY is not set
-+# CONFIG_STAT is not set
-+# CONFIG_FEATURE_STAT_FORMAT is not set
-+# CONFIG_FEATURE_STAT_FILESYSTEM is not set
-+CONFIG_STTY=y
-+# CONFIG_SUM is not set
-+CONFIG_SYNC=y
-+# CONFIG_FEATURE_SYNC_FANCY is not set
-+# CONFIG_TAC is not set
-+CONFIG_TAIL=y
-+CONFIG_FEATURE_FANCY_TAIL=y
-+CONFIG_TEE=y
-+CONFIG_FEATURE_TEE_USE_BLOCK_IO=y
-+CONFIG_TEST=y
-+CONFIG_TEST1=y
-+CONFIG_TEST2=y
-+CONFIG_FEATURE_TEST_64=y
-+# CONFIG_TIMEOUT is not set
-+CONFIG_TOUCH=y
-+# CONFIG_FEATURE_TOUCH_NODEREF is not set
-+CONFIG_FEATURE_TOUCH_SUSV3=y
-+CONFIG_TR=y
-+# CONFIG_FEATURE_TR_CLASSES is not set
-+# CONFIG_FEATURE_TR_EQUIV is not set
-+CONFIG_TRUE=y
-+CONFIG_TRUNCATE=y
-+# CONFIG_TTY is not set
-+CONFIG_UNAME=y
-+CONFIG_UNAME_OSNAME="GNU/Linux"
-+CONFIG_UNIQ=y
-+# CONFIG_UNLINK is not set
-+# CONFIG_USLEEP is not set
-+# CONFIG_UUDECODE is not set
-+# CONFIG_BASE64 is not set
-+# CONFIG_UUENCODE is not set
-+CONFIG_WC=y
-+# CONFIG_FEATURE_WC_LARGE is not set
-+# CONFIG_WHOAMI is not set
-+# CONFIG_WHO is not set
-+# CONFIG_W is not set
-+# CONFIG_USERS is not set
-+CONFIG_YES=y
-+
-+#
-+# Common options
-+#
-+# CONFIG_FEATURE_VERBOSE is not set
-+
-+#
-+# Common options for cp and mv
-+#
-+CONFIG_FEATURE_PRESERVE_HARDLINKS=y
-+
-+#
-+# Common options for df, du, ls
-+#
-+# CONFIG_FEATURE_HUMAN_READABLE is not set
-+
-+#
-+# Console Utilities
-+#
-+# CONFIG_CHVT is not set
-+# CONFIG_CLEAR is not set
-+# CONFIG_DEALLOCVT is not set
-+# CONFIG_DUMPKMAP is not set
-+# CONFIG_FGCONSOLE is not set
-+# CONFIG_KBD_MODE is not set
-+# CONFIG_LOADFONT is not set
-+# CONFIG_SETFONT is not set
-+# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set
-+CONFIG_DEFAULT_SETFONT_DIR=""
-+# CONFIG_FEATURE_LOADFONT_PSF2 is not set
-+# CONFIG_FEATURE_LOADFONT_RAW is not set
-+# CONFIG_LOADKMAP is not set
-+# CONFIG_OPENVT is not set
-+# CONFIG_RESET is not set
-+# CONFIG_RESIZE is not set
-+# CONFIG_FEATURE_RESIZE_PRINT is not set
-+# CONFIG_SETCONSOLE is not set
-+# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
-+# CONFIG_SETKEYCODES is not set
-+# CONFIG_SETLOGCONS is not set
-+# CONFIG_SHOWKEY is not set
-+
-+#
-+# Debian Utilities
-+#
-+# CONFIG_PIPE_PROGRESS is not set
-+# CONFIG_RUN_PARTS is not set
-+# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_RUN_PARTS_FANCY is not set
-+# CONFIG_START_STOP_DAEMON is not set
-+# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set
-+CONFIG_WHICH=y
-+
-+#
-+# Editors
-+#
-+# CONFIG_AWK is not set
-+# CONFIG_FEATURE_AWK_LIBM is not set
-+# CONFIG_FEATURE_AWK_GNU_EXTENSIONS is not set
-+CONFIG_CMP=y
-+# CONFIG_DIFF is not set
-+# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_DIFF_DIR is not set
-+# CONFIG_ED is not set
-+# CONFIG_PATCH is not set
-+CONFIG_SED=y
-+# CONFIG_VI is not set
-+CONFIG_FEATURE_VI_MAX_LEN=0
-+# CONFIG_FEATURE_VI_8BIT is not set
-+# CONFIG_FEATURE_VI_COLON is not set
-+# CONFIG_FEATURE_VI_YANKMARK is not set
-+# CONFIG_FEATURE_VI_SEARCH is not set
-+# CONFIG_FEATURE_VI_REGEX_SEARCH is not set
-+# CONFIG_FEATURE_VI_USE_SIGNALS is not set
-+# CONFIG_FEATURE_VI_DOT_CMD is not set
-+# CONFIG_FEATURE_VI_READONLY is not set
-+# CONFIG_FEATURE_VI_SETOPTS is not set
-+# CONFIG_FEATURE_VI_SET is not set
-+# CONFIG_FEATURE_VI_WIN_RESIZE is not set
-+# CONFIG_FEATURE_VI_ASK_TERMINAL is not set
-+# CONFIG_FEATURE_VI_UNDO is not set
-+# CONFIG_FEATURE_VI_UNDO_QUEUE is not set
-+CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=0
-+# CONFIG_FEATURE_ALLOW_EXEC is not set
-+
-+#
-+# Finding Utilities
-+#
-+CONFIG_FIND=y
-+CONFIG_FEATURE_FIND_PRINT0=y
-+CONFIG_FEATURE_FIND_MTIME=y
-+# CONFIG_FEATURE_FIND_MMIN is not set
-+CONFIG_FEATURE_FIND_PERM=y
-+CONFIG_FEATURE_FIND_TYPE=y
-+CONFIG_FEATURE_FIND_XDEV=y
-+CONFIG_FEATURE_FIND_MAXDEPTH=y
-+CONFIG_FEATURE_FIND_NEWER=y
-+# CONFIG_FEATURE_FIND_INUM is not set
-+CONFIG_FEATURE_FIND_EXEC=y
-+# CONFIG_FEATURE_FIND_EXEC_PLUS is not set
-+CONFIG_FEATURE_FIND_USER=y
-+CONFIG_FEATURE_FIND_GROUP=y
-+CONFIG_FEATURE_FIND_NOT=y
-+CONFIG_FEATURE_FIND_DEPTH=y
-+CONFIG_FEATURE_FIND_PAREN=y
-+CONFIG_FEATURE_FIND_SIZE=y
-+CONFIG_FEATURE_FIND_PRUNE=y
-+# CONFIG_FEATURE_FIND_DELETE is not set
-+CONFIG_FEATURE_FIND_PATH=y
-+CONFIG_FEATURE_FIND_REGEX=y
-+# CONFIG_FEATURE_FIND_CONTEXT is not set
-+# CONFIG_FEATURE_FIND_LINKS is not set
-+CONFIG_GREP=y
-+CONFIG_EGREP=y
-+CONFIG_FGREP=y
-+CONFIG_FEATURE_GREP_CONTEXT=y
-+CONFIG_XARGS=y
-+CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION=y
-+CONFIG_FEATURE_XARGS_SUPPORT_QUOTES=y
-+CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT=y
-+CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y
-+# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set
-+
-+#
-+# Init Utilities
-+#
-+# CONFIG_BOOTCHARTD is not set
-+# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set
-+# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set
-+# CONFIG_HALT is not set
-+CONFIG_POWEROFF=y
-+CONFIG_REBOOT=y
-+# CONFIG_FEATURE_CALL_TELINIT is not set
-+CONFIG_TELINIT_PATH=""
-+# CONFIG_INIT is not set
-+# CONFIG_LINUXRC is not set
-+# CONFIG_FEATURE_USE_INITTAB is not set
-+# CONFIG_FEATURE_KILL_REMOVED is not set
-+CONFIG_FEATURE_KILL_DELAY=0
-+# CONFIG_FEATURE_INIT_SCTTY is not set
-+# CONFIG_FEATURE_INIT_SYSLOG is not set
-+# CONFIG_FEATURE_INIT_QUIET is not set
-+# CONFIG_FEATURE_INIT_COREDUMPS is not set
-+CONFIG_INIT_TERMINAL_TYPE=""
-+# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set
-+
-+#
-+# Login/Password Management Utilities
-+#
-+CONFIG_FEATURE_SHADOWPASSWDS=y
-+# CONFIG_USE_BB_PWD_GRP is not set
-+# CONFIG_USE_BB_SHADOW is not set
-+# CONFIG_USE_BB_CRYPT is not set
-+# CONFIG_USE_BB_CRYPT_SHA is not set
-+# CONFIG_ADDGROUP is not set
-+# CONFIG_FEATURE_ADDGROUP_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set
-+# CONFIG_ADD_SHELL is not set
-+# CONFIG_REMOVE_SHELL is not set
-+CONFIG_ADDUSER=y
-+CONFIG_FEATURE_ADDUSER_LONG_OPTIONS=y
-+CONFIG_FEATURE_CHECK_NAMES=y
-+CONFIG_LAST_ID=60000
-+CONFIG_FIRST_SYSTEM_ID=100
-+CONFIG_LAST_SYSTEM_ID=999
-+# CONFIG_CHPASSWD is not set
-+CONFIG_FEATURE_DEFAULT_PASSWD_ALGO=""
-+# CONFIG_CRYPTPW is not set
-+# CONFIG_MKPASSWD is not set
-+# CONFIG_DELUSER is not set
-+# CONFIG_DELGROUP is not set
-+# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set
-+# CONFIG_GETTY is not set
-+# CONFIG_LOGIN is not set
-+# CONFIG_LOGIN_SESSION_AS_CHILD is not set
-+# CONFIG_LOGIN_SCRIPTS is not set
-+# CONFIG_FEATURE_NOLOGIN is not set
-+# CONFIG_FEATURE_SECURETTY is not set
-+# CONFIG_PASSWD is not set
-+# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set
-+# CONFIG_SU is not set
-+# CONFIG_FEATURE_SU_SYSLOG is not set
-+# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set
-+# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set
-+# CONFIG_SULOGIN is not set
-+# CONFIG_VLOCK is not set
-+
-+#
-+# Linux Ext2 FS Progs
-+#
-+# CONFIG_CHATTR is not set
-+# CONFIG_FSCK is not set
-+# CONFIG_LSATTR is not set
-+# CONFIG_TUNE2FS is not set
-+
-+#
-+# Linux Module Utilities
-+#
-+# CONFIG_MODPROBE_SMALL is not set
-+# CONFIG_DEPMOD is not set
-+# CONFIG_INSMOD is not set
-+# CONFIG_LSMOD is not set
-+# CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT is not set
-+# CONFIG_MODINFO is not set
-+# CONFIG_MODPROBE is not set
-+# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
-+# CONFIG_RMMOD is not set
-+
-+#
-+# Options common to multiple modutils
-+#
-+# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set
-+# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set
-+# CONFIG_FEATURE_2_4_MODULES is not set
-+# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
-+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
-+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
-+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
-+# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set
-+# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set
-+# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
-+# CONFIG_FEATURE_MODUTILS_ALIAS is not set
-+# CONFIG_FEATURE_MODUTILS_SYMBOLS is not set
-+CONFIG_DEFAULT_MODULES_DIR=""
-+CONFIG_DEFAULT_DEPMOD_FILE=""
-+
-+#
-+# Linux System Utilities
-+#
-+# CONFIG_ACPID is not set
-+# CONFIG_FEATURE_ACPID_COMPAT is not set
-+# CONFIG_BLKDISCARD is not set
-+# CONFIG_BLKID is not set
-+# CONFIG_FEATURE_BLKID_TYPE is not set
-+# CONFIG_BLOCKDEV is not set
-+# CONFIG_CAL is not set
-+# CONFIG_CHRT is not set
-+# CONFIG_DMESG is not set
-+# CONFIG_FEATURE_DMESG_PRETTY is not set
-+# CONFIG_EJECT is not set
-+# CONFIG_FEATURE_EJECT_SCSI is not set
-+CONFIG_FALLOCATE=y
-+# CONFIG_FATATTR is not set
-+# CONFIG_FBSET is not set
-+# CONFIG_FEATURE_FBSET_FANCY is not set
-+# CONFIG_FEATURE_FBSET_READMODE is not set
-+# CONFIG_FDFORMAT is not set
-+# CONFIG_FDISK is not set
-+# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set
-+# CONFIG_FEATURE_FDISK_WRITABLE is not set
-+# CONFIG_FEATURE_AIX_LABEL is not set
-+# CONFIG_FEATURE_SGI_LABEL is not set
-+# CONFIG_FEATURE_SUN_LABEL is not set
-+# CONFIG_FEATURE_OSF_LABEL is not set
-+# CONFIG_FEATURE_GPT_LABEL is not set
-+# CONFIG_FEATURE_FDISK_ADVANCED is not set
-+# CONFIG_FINDFS is not set
-+# CONFIG_FLOCK is not set
-+# CONFIG_FDFLUSH is not set
-+# CONFIG_FREERAMDISK is not set
-+# CONFIG_FSCK_MINIX is not set
-+CONFIG_FSFREEZE=y
-+# CONFIG_FSTRIM is not set
-+# CONFIG_GETOPT is not set
-+# CONFIG_FEATURE_GETOPT_LONG is not set
-+# CONFIG_HEXDUMP is not set
-+# CONFIG_FEATURE_HEXDUMP_REVERSE is not set
-+# CONFIG_HD is not set
-+CONFIG_XXD=y
-+# CONFIG_HWCLOCK is not set
-+# CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set
-+# CONFIG_IONICE is not set
-+# CONFIG_IPCRM is not set
-+# CONFIG_IPCS is not set
-+# CONFIG_LAST is not set
-+# CONFIG_FEATURE_LAST_FANCY is not set
-+# CONFIG_LOSETUP is not set
-+# CONFIG_LSPCI is not set
-+# CONFIG_LSUSB is not set
-+# CONFIG_MDEV is not set
-+# CONFIG_FEATURE_MDEV_CONF is not set
-+# CONFIG_FEATURE_MDEV_RENAME is not set
-+# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set
-+# CONFIG_FEATURE_MDEV_EXEC is not set
-+# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set
-+# CONFIG_MESG is not set
-+# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set
-+CONFIG_MKE2FS=y
-+# CONFIG_MKFS_EXT2 is not set
-+# CONFIG_MKFS_MINIX is not set
-+# CONFIG_FEATURE_MINIX2 is not set
-+# CONFIG_MKFS_REISER is not set
-+CONFIG_MKDOSFS=y
-+# CONFIG_MKFS_VFAT is not set
-+# CONFIG_MKSWAP is not set
-+# CONFIG_FEATURE_MKSWAP_UUID is not set
-+# CONFIG_MORE is not set
-+CONFIG_MOUNT=y
-+# CONFIG_FEATURE_MOUNT_FAKE is not set
-+# CONFIG_FEATURE_MOUNT_VERBOSE is not set
-+CONFIG_FEATURE_MOUNT_HELPERS=y
-+# CONFIG_FEATURE_MOUNT_LABEL is not set
-+# CONFIG_FEATURE_MOUNT_NFS is not set
-+# CONFIG_FEATURE_MOUNT_CIFS is not set
-+CONFIG_FEATURE_MOUNT_FLAGS=y
-+CONFIG_FEATURE_MOUNT_FSTAB=y
-+CONFIG_FEATURE_MOUNT_OTHERTAB=y
-+# CONFIG_MOUNTPOINT is not set
-+# CONFIG_NSENTER is not set
-+# CONFIG_FEATURE_NSENTER_LONG_OPTS is not set
-+# CONFIG_PIVOT_ROOT is not set
-+# CONFIG_RDATE is not set
-+# CONFIG_RDEV is not set
-+# CONFIG_READPROFILE is not set
-+# CONFIG_RENICE is not set
-+# CONFIG_REV is not set
-+# CONFIG_RTCWAKE is not set
-+# CONFIG_SCRIPT is not set
-+# CONFIG_SCRIPTREPLAY is not set
-+# CONFIG_SETARCH is not set
-+CONFIG_LINUX32=y
-+CONFIG_LINUX64=y
-+CONFIG_SETPRIV=y
-+# CONFIG_SETSID is not set
-+CONFIG_SWAPON=y
-+# CONFIG_FEATURE_SWAPON_DISCARD is not set
-+# CONFIG_FEATURE_SWAPON_PRI is not set
-+CONFIG_SWAPOFF=y
-+# CONFIG_SWITCH_ROOT is not set
-+# CONFIG_TASKSET is not set
-+# CONFIG_FEATURE_TASKSET_FANCY is not set
-+# CONFIG_UEVENT is not set
-+CONFIG_UMOUNT=y
-+CONFIG_FEATURE_UMOUNT_ALL=y
-+# CONFIG_UNSHARE is not set
-+# CONFIG_WALL is not set
-+
-+#
-+# Common options for mount/umount
-+#
-+CONFIG_FEATURE_MOUNT_LOOP=y
-+# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
-+# CONFIG_FEATURE_MTAB_SUPPORT is not set
-+# CONFIG_VOLUMEID is not set
-+# CONFIG_FEATURE_VOLUMEID_BCACHE is not set
-+# CONFIG_FEATURE_VOLUMEID_BTRFS is not set
-+# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set
-+# CONFIG_FEATURE_VOLUMEID_EXFAT is not set
-+# CONFIG_FEATURE_VOLUMEID_EXT is not set
-+# CONFIG_FEATURE_VOLUMEID_F2FS is not set
-+# CONFIG_FEATURE_VOLUMEID_FAT is not set
-+# CONFIG_FEATURE_VOLUMEID_HFS is not set
-+# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set
-+# CONFIG_FEATURE_VOLUMEID_JFS is not set
-+# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set
-+# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set
-+# CONFIG_FEATURE_VOLUMEID_LUKS is not set
-+# CONFIG_FEATURE_VOLUMEID_NILFS is not set
-+# CONFIG_FEATURE_VOLUMEID_NTFS is not set
-+# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set
-+# CONFIG_FEATURE_VOLUMEID_REISERFS is not set
-+# CONFIG_FEATURE_VOLUMEID_ROMFS is not set
-+# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set
-+# CONFIG_FEATURE_VOLUMEID_SYSV is not set
-+# CONFIG_FEATURE_VOLUMEID_UBIFS is not set
-+# CONFIG_FEATURE_VOLUMEID_UDF is not set
-+# CONFIG_FEATURE_VOLUMEID_XFS is not set
-+
-+#
-+# Miscellaneous Utilities
-+#
-+# CONFIG_ADJTIMEX is not set
-+# CONFIG_BBCONFIG is not set
-+# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set
-+# CONFIG_BEEP is not set
-+CONFIG_FEATURE_BEEP_FREQ=0
-+CONFIG_FEATURE_BEEP_LENGTH_MS=0
-+# CONFIG_CHAT is not set
-+# CONFIG_FEATURE_CHAT_NOFAIL is not set
-+# CONFIG_FEATURE_CHAT_TTY_HIFI is not set
-+# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set
-+# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set
-+# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set
-+# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set
-+# CONFIG_FEATURE_CHAT_CLR_ABORT is not set
-+# CONFIG_CONSPY is not set
-+# CONFIG_CROND is not set
-+# CONFIG_FEATURE_CROND_D is not set
-+# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set
-+CONFIG_FEATURE_CROND_DIR=""
-+# CONFIG_CRONTAB is not set
-+# CONFIG_DC is not set
-+# CONFIG_FEATURE_DC_LIBM is not set
-+# CONFIG_DEVFSD is not set
-+# CONFIG_DEVFSD_MODLOAD is not set
-+# CONFIG_DEVFSD_FG_NP is not set
-+# CONFIG_DEVFSD_VERBOSE is not set
-+# CONFIG_FEATURE_DEVFS is not set
-+# CONFIG_DEVMEM is not set
-+# CONFIG_FBSPLASH is not set
-+# CONFIG_FLASHCP is not set
-+# CONFIG_FLASH_ERASEALL is not set
-+# CONFIG_FLASH_LOCK is not set
-+# CONFIG_FLASH_UNLOCK is not set
-+# CONFIG_HDPARM is not set
-+# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set
-+# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set
-+# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set
-+# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set
-+# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set
-+# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set
-+CONFIG_I2CGET=y
-+CONFIG_I2CSET=y
-+CONFIG_I2CDUMP=y
-+CONFIG_I2CDETECT=y
-+# CONFIG_INOTIFYD is not set
-+# CONFIG_LESS is not set
-+CONFIG_FEATURE_LESS_MAXLINES=0
-+# CONFIG_FEATURE_LESS_BRACKETS is not set
-+# CONFIG_FEATURE_LESS_FLAGS is not set
-+# CONFIG_FEATURE_LESS_TRUNCATE is not set
-+# CONFIG_FEATURE_LESS_MARKS is not set
-+# CONFIG_FEATURE_LESS_REGEXP is not set
-+# CONFIG_FEATURE_LESS_WINCH is not set
-+# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set
-+# CONFIG_FEATURE_LESS_DASHCMD is not set
-+# CONFIG_FEATURE_LESS_LINENUMS is not set
-+# CONFIG_LOCK is not set
-+CONFIG_LSSCSI=y
-+# CONFIG_MAKEDEVS is not set
-+# CONFIG_FEATURE_MAKEDEVS_LEAF is not set
-+# CONFIG_FEATURE_MAKEDEVS_TABLE is not set
-+# CONFIG_MAN is not set
-+# CONFIG_MICROCOM is not set
-+# CONFIG_MT is not set
-+# CONFIG_NANDWRITE is not set
-+# CONFIG_NANDDUMP is not set
-+CONFIG_PARTPROBE=y
-+# CONFIG_RAIDAUTORUN is not set
-+# CONFIG_READAHEAD is not set
-+# CONFIG_RFKILL is not set
-+# CONFIG_RUNLEVEL is not set
-+# CONFIG_RX is not set
-+# CONFIG_SETSERIAL is not set
-+# CONFIG_STRINGS is not set
-+# CONFIG_TIME is not set
-+# CONFIG_TTYSIZE is not set
-+# CONFIG_UBIRENAME is not set
-+# CONFIG_UBIATTACH is not set
-+# CONFIG_UBIDETACH is not set
-+# CONFIG_UBIMKVOL is not set
-+# CONFIG_UBIRMVOL is not set
-+# CONFIG_UBIRSVOL is not set
-+# CONFIG_UBIUPDATEVOL is not set
-+# CONFIG_VOLNAME is not set
-+# CONFIG_WATCHDOG is not set
-+
-+#
-+# Networking Utilities
-+#
-+CONFIG_FEATURE_IPV6=y
-+# CONFIG_FEATURE_UNIX_LOCAL is not set
-+CONFIG_FEATURE_PREFER_IPV4_ADDRESS=y
-+# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set
-+# CONFIG_ARP is not set
-+# CONFIG_ARPING is not set
-+# CONFIG_BRCTL is not set
-+# CONFIG_FEATURE_BRCTL_FANCY is not set
-+# CONFIG_FEATURE_BRCTL_SHOW is not set
-+# CONFIG_DNSD is not set
-+# CONFIG_ETHER_WAKE is not set
-+# CONFIG_FTPD is not set
-+# CONFIG_FEATURE_FTPD_WRITE is not set
-+# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set
-+# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set
-+# CONFIG_FTPGET is not set
-+# CONFIG_FTPPUT is not set
-+# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set
-+# CONFIG_HOSTNAME is not set
-+CONFIG_DNSDOMAINNAME=y
-+# CONFIG_HTTPD is not set
-+# CONFIG_FEATURE_HTTPD_RANGES is not set
-+# CONFIG_FEATURE_HTTPD_SETUID is not set
-+# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set
-+# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set
-+# CONFIG_FEATURE_HTTPD_CGI is not set
-+# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set
-+# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set
-+# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set
-+# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set
-+# CONFIG_FEATURE_HTTPD_PROXY is not set
-+# CONFIG_FEATURE_HTTPD_GZIP is not set
-+# CONFIG_IFCONFIG is not set
-+# CONFIG_FEATURE_IFCONFIG_STATUS is not set
-+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
-+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
-+# CONFIG_FEATURE_IFCONFIG_HW is not set
-+# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
-+# CONFIG_IFENSLAVE is not set
-+# CONFIG_IFPLUGD is not set
-+CONFIG_IFUP=y
-+CONFIG_IFDOWN=y
-+CONFIG_IFUPDOWN_IFSTATE_PATH=""
-+# CONFIG_FEATURE_IFUPDOWN_IP is not set
-+# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set
-+# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set
-+# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set
-+# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set
-+# CONFIG_INETD is not set
-+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set
-+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set
-+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set
-+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set
-+# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set
-+# CONFIG_FEATURE_INETD_RPC is not set
-+CONFIG_IP=y
-+CONFIG_IPADDR=y
-+CONFIG_IPLINK=y
-+# CONFIG_IPROUTE is not set
-+# CONFIG_IPTUNNEL is not set
-+# CONFIG_IPRULE is not set
-+# CONFIG_IPNEIGH is not set
-+CONFIG_FEATURE_IP_ADDRESS=y
-+CONFIG_FEATURE_IP_LINK=y
-+# CONFIG_FEATURE_IP_ROUTE is not set
-+CONFIG_FEATURE_IP_ROUTE_DIR=""
-+# CONFIG_FEATURE_IP_TUNNEL is not set
-+# CONFIG_FEATURE_IP_RULE is not set
-+# CONFIG_FEATURE_IP_NEIGH is not set
-+# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set
-+# CONFIG_IPCALC is not set
-+# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_IPCALC_FANCY is not set
-+# CONFIG_FAKEIDENTD is not set
-+# CONFIG_NAMEIF is not set
-+# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
-+# CONFIG_NBDCLIENT is not set
-+# CONFIG_NC is not set
-+# CONFIG_NC_SERVER is not set
-+# CONFIG_NC_EXTRA is not set
-+# CONFIG_NC_110_COMPAT is not set
-+# CONFIG_NETMSG is not set
-+# CONFIG_NETSTAT is not set
-+# CONFIG_FEATURE_NETSTAT_WIDE is not set
-+# CONFIG_FEATURE_NETSTAT_PRG is not set
-+# CONFIG_NSLOOKUP is not set
-+CONFIG_NSLOOKUP_OPENWRT=y
-+CONFIG_FEATURE_NSLOOKUP_OPENWRT_LONG_OPTIONS=y
-+# CONFIG_NTPD is not set
-+# CONFIG_FEATURE_NTPD_SERVER is not set
-+# CONFIG_FEATURE_NTPD_CONF is not set
-+CONFIG_PING=y
-+CONFIG_PING6=y
-+CONFIG_FEATURE_FANCY_PING=y
-+# CONFIG_PSCAN is not set
-+# CONFIG_ROUTE is not set
-+# CONFIG_SLATTACH is not set
-+CONFIG_SSL_CLIENT=y
-+# CONFIG_TCPSVD is not set
-+# CONFIG_UDPSVD is not set
-+# CONFIG_TELNET is not set
-+# CONFIG_FEATURE_TELNET_TTYPE is not set
-+# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set
-+# CONFIG_FEATURE_TELNET_WIDTH is not set
-+# CONFIG_TELNETD is not set
-+# CONFIG_FEATURE_TELNETD_STANDALONE is not set
-+# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set
-+# CONFIG_TFTP is not set
-+# CONFIG_TFTPD is not set
-+# CONFIG_FEATURE_TFTP_GET is not set
-+# CONFIG_FEATURE_TFTP_PUT is not set
-+# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set
-+# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set
-+# CONFIG_TFTP_DEBUG is not set
-+CONFIG_TLS=y
-+# CONFIG_TRACEROUTE is not set
-+# CONFIG_TRACEROUTE6 is not set
-+# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set
-+# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set
-+# CONFIG_TUNCTL is not set
-+# CONFIG_FEATURE_TUNCTL_UG is not set
-+# CONFIG_VCONFIG is not set
-+# CONFIG_WGET is not set
-+# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set
-+# CONFIG_FEATURE_WGET_STATUSBAR is not set
-+# CONFIG_FEATURE_WGET_AUTHENTICATION is not set
-+# CONFIG_FEATURE_WGET_TIMEOUT is not set
-+# CONFIG_FEATURE_WGET_HTTPS is not set
-+# CONFIG_FEATURE_WGET_OPENSSL is not set
-+# CONFIG_WHOIS is not set
-+# CONFIG_ZCIP is not set
-+# CONFIG_UDHCPC6 is not set
-+# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set
-+# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set
-+# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set
-+# CONFIG_UDHCPD is not set
-+# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set
-+# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set
-+CONFIG_DHCPD_LEASES_FILE=""
-+# CONFIG_DUMPLEASES is not set
-+# CONFIG_DHCPRELAY is not set
-+# CONFIG_UDHCPC is not set
-+# CONFIG_FEATURE_UDHCPC_ARPING is not set
-+# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set
-+CONFIG_UDHCPC_DEFAULT_SCRIPT=""
-+# CONFIG_FEATURE_UDHCP_PORT is not set
-+CONFIG_UDHCP_DEBUG=0
-+# CONFIG_FEATURE_UDHCP_RFC3397 is not set
-+# CONFIG_FEATURE_UDHCP_8021Q is not set
-+CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0
-+CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS=""
-+
-+#
-+# Print Utilities
-+#
-+# CONFIG_LPD is not set
-+# CONFIG_LPR is not set
-+# CONFIG_LPQ is not set
-+
-+#
-+# Mail Utilities
-+#
-+# CONFIG_MAKEMIME is not set
-+# CONFIG_POPMAILDIR is not set
-+# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set
-+# CONFIG_REFORMIME is not set
-+# CONFIG_FEATURE_REFORMIME_COMPAT is not set
-+# CONFIG_SENDMAIL is not set
-+CONFIG_FEATURE_MIME_CHARSET=""
-+
-+#
-+# Process Utilities
-+#
-+CONFIG_FREE=y
-+CONFIG_FUSER=y
-+# CONFIG_IOSTAT is not set
-+CONFIG_KILL=y
-+CONFIG_KILLALL=y
-+# CONFIG_KILLALL5 is not set
-+# CONFIG_LSOF is not set
-+# CONFIG_MPSTAT is not set
-+# CONFIG_NMETER is not set
-+CONFIG_PGREP=y
-+CONFIG_PKILL=y
-+CONFIG_PIDOF=y
-+# CONFIG_FEATURE_PIDOF_SINGLE is not set
-+# CONFIG_FEATURE_PIDOF_OMIT is not set
-+# CONFIG_PMAP is not set
-+# CONFIG_POWERTOP is not set
-+# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set
-+CONFIG_PS=y
-+CONFIG_FEATURE_PS_WIDE=y
-+# CONFIG_FEATURE_PS_LONG is not set
-+# CONFIG_FEATURE_PS_TIME is not set
-+# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set
-+# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set
-+# CONFIG_PSTREE is not set
-+# CONFIG_PWDX is not set
-+# CONFIG_SMEMCAP is not set
-+CONFIG_BB_SYSCTL=y
-+# CONFIG_TOP is not set
-+# CONFIG_FEATURE_TOP_INTERACTIVE is not set
-+# CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE is not set
-+# CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS is not set
-+# CONFIG_FEATURE_TOP_SMP_CPU is not set
-+# CONFIG_FEATURE_TOP_DECIMALS is not set
-+# CONFIG_FEATURE_TOP_SMP_PROCESS is not set
-+# CONFIG_FEATURE_TOPMEM is not set
-+CONFIG_UPTIME=y
-+# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set
-+# CONFIG_WATCH is not set
-+# CONFIG_FEATURE_SHOW_THREADS is not set
-+
-+#
-+# Runit Utilities
-+#
-+# CONFIG_CHPST is not set
-+# CONFIG_SETUIDGID is not set
-+# CONFIG_ENVUIDGID is not set
-+# CONFIG_ENVDIR is not set
-+# CONFIG_SOFTLIMIT is not set
-+# CONFIG_RUNSV is not set
-+# CONFIG_RUNSVDIR is not set
-+# CONFIG_FEATURE_RUNSVDIR_LOG is not set
-+# CONFIG_SV is not set
-+CONFIG_SV_DEFAULT_SERVICE_DIR=""
-+CONFIG_SVC=y
-+# CONFIG_SVLOGD is not set
-+# CONFIG_CHCON is not set
-+# CONFIG_FEATURE_CHCON_LONG_OPTIONS is not set
-+# CONFIG_GETENFORCE is not set
-+# CONFIG_GETSEBOOL is not set
-+# CONFIG_LOAD_POLICY is not set
-+# CONFIG_MATCHPATHCON is not set
-+# CONFIG_RUNCON is not set
-+# CONFIG_FEATURE_RUNCON_LONG_OPTIONS is not set
-+# CONFIG_SELINUXENABLED is not set
-+# CONFIG_SESTATUS is not set
-+# CONFIG_SETENFORCE is not set
-+# CONFIG_SETFILES is not set
-+# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set
-+# CONFIG_RESTORECON is not set
-+# CONFIG_SETSEBOOL is not set
-+
-+#
-+# Shells
-+#
-+CONFIG_SH_IS_ASH=y
-+# CONFIG_SH_IS_HUSH is not set
-+# CONFIG_SH_IS_NONE is not set
-+# CONFIG_BASH_IS_ASH is not set
-+# CONFIG_BASH_IS_HUSH is not set
-+CONFIG_BASH_IS_NONE=y
-+CONFIG_ASH=y
-+# CONFIG_ASH_OPTIMIZE_FOR_SIZE is not set
-+CONFIG_ASH_INTERNAL_GLOB=y
-+CONFIG_ASH_BASH_COMPAT=y
-+CONFIG_ASH_JOB_CONTROL=y
-+CONFIG_ASH_ALIAS=y
-+CONFIG_ASH_RANDOM_SUPPORT=y
-+CONFIG_ASH_EXPAND_PRMT=y
-+# CONFIG_ASH_IDLE_TIMEOUT is not set
-+# CONFIG_ASH_MAIL is not set
-+CONFIG_ASH_ECHO=y
-+CONFIG_ASH_PRINTF=y
-+CONFIG_ASH_TEST=y
-+# CONFIG_ASH_HELP is not set
-+CONFIG_ASH_GETOPTS=y
-+CONFIG_ASH_CMDCMD=y
-+# CONFIG_CTTYHACK is not set
-+# CONFIG_HUSH is not set
-+# CONFIG_HUSH_BASH_COMPAT is not set
-+# CONFIG_HUSH_BRACE_EXPANSION is not set
-+# CONFIG_HUSH_INTERACTIVE is not set
-+# CONFIG_HUSH_SAVEHISTORY is not set
-+# CONFIG_HUSH_JOB is not set
-+# CONFIG_HUSH_TICK is not set
-+# CONFIG_HUSH_IF is not set
-+# CONFIG_HUSH_LOOPS is not set
-+# CONFIG_HUSH_CASE is not set
-+# CONFIG_HUSH_FUNCTIONS is not set
-+# CONFIG_HUSH_LOCAL is not set
-+# CONFIG_HUSH_RANDOM_SUPPORT is not set
-+# CONFIG_HUSH_MODE_X is not set
-+# CONFIG_HUSH_ECHO is not set
-+# CONFIG_HUSH_PRINTF is not set
-+# CONFIG_HUSH_TEST is not set
-+# CONFIG_HUSH_HELP is not set
-+# CONFIG_HUSH_EXPORT is not set
-+# CONFIG_HUSH_EXPORT_N is not set
-+# CONFIG_HUSH_KILL is not set
-+# CONFIG_HUSH_WAIT is not set
-+# CONFIG_HUSH_TRAP is not set
-+# CONFIG_HUSH_TYPE is not set
-+# CONFIG_HUSH_READ is not set
-+# CONFIG_HUSH_SET is not set
-+# CONFIG_HUSH_UNSET is not set
-+# CONFIG_HUSH_ULIMIT is not set
-+# CONFIG_HUSH_UMASK is not set
-+# CONFIG_HUSH_MEMLEAK is not set
-+# CONFIG_MSH is not set
-+
-+#
-+# Options common to all shells
-+#
-+CONFIG_FEATURE_SH_MATH=y
-+CONFIG_FEATURE_SH_MATH_64=y
-+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
-+CONFIG_FEATURE_SH_STANDALONE=y
-+CONFIG_FEATURE_SH_NOFORK=y
-+# CONFIG_FEATURE_SH_HISTFILESIZE is not set
-+
-+#
-+# System Logging Utilities
-+#
-+# CONFIG_KLOGD is not set
-+# CONFIG_FEATURE_KLOGD_KLOGCTL is not set
-+# CONFIG_LOGGER is not set
-+# CONFIG_LOGREAD is not set
-+# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set
-+# CONFIG_SYSLOGD is not set
-+# CONFIG_FEATURE_ROTATE_LOGFILE is not set
-+# CONFIG_FEATURE_REMOTE_LOG is not set
-+# CONFIG_FEATURE_SYSLOGD_DUP is not set
-+# CONFIG_FEATURE_SYSLOGD_CFG is not set
-+CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0
-+# CONFIG_FEATURE_IPC_SYSLOG is not set
-+CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0
-+# CONFIG_FEATURE_KMSG_SYSLOG is not set
 -- 
-2.16.2
+2.18.0
 
diff --git a/patches/openwrt/hack/0001-ubus-Hackilly-add-Stepans-python-bindings.patch b/patches/openwrt/hack/0001-ubus-Hackilly-add-Stepans-python-bindings.patch
index 98110c960afa040ea32502f74c8e4db7791e2649..a23508d2b2f71fe4a975a5d1fd9ce288f62efc49 100644
--- a/patches/openwrt/hack/0001-ubus-Hackilly-add-Stepans-python-bindings.patch
+++ b/patches/openwrt/hack/0001-ubus-Hackilly-add-Stepans-python-bindings.patch
@@ -1,4 +1,4 @@
-From c6de868c3954517bc169c8ec5cb2a5bc7eaecfea Mon Sep 17 00:00:00 2001
+From 1b918d04f541d201a2fa43d371ecbb1318719d4c Mon Sep 17 00:00:00 2001
 From: Michal Hrusecky <Michal@Hrusecky.net>
 Date: Tue, 23 Jan 2018 23:55:00 +0100
 Subject: [PATCH] ubus: Hackilly add Stepans python bindings
@@ -14,16 +14,14 @@ There are currently two problems with this solution:
 
 Signed-off-by: Michal Hrusecky <Michal@Hrusecky.net>
 ---
- package/system/ubus/Makefile                 |   31 +
- package/system/ubus/patches/001-python.patch | 2443 ++++++++++++++++++++++++++
- 2 files changed, 2474 insertions(+)
- create mode 100644 package/system/ubus/patches/001-python.patch
+ package/system/ubus/Makefile | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
 
 diff --git a/package/system/ubus/Makefile b/package/system/ubus/Makefile
-index 7dc3c92..46c608b 100644
+index 523c362..d39b918 100644
 --- a/package/system/ubus/Makefile
 +++ b/package/system/ubus/Makefile
-@@ -47,10 +47,35 @@ define Package/libubus-lua
+@@ -47,11 +47,34 @@ define Package/libubus-lua
    TITLE:=Lua binding for the OpenWrt RPC client
  endef
  
@@ -35,7 +33,8 @@ index 7dc3c92..46c608b 100644
 +  DEPENDS:=+libubus +libblobmsg-json +python-light
 +endef
 +
- TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
+ TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include -flto
+ TARGET_LDFLAGS += -flto
  
 +define Build/Compile/fake_python_sh
 +	echo -e '#!/bin/sh\nLD_LIBRARY_PATH="$(STAGING_DIR_HOSTPKG)/lib" $(STAGING_DIR_HOSTPKG)/bin/python "$$$$@"' > '$(STAGING_DIR_HOSTPKG)/bin/python.sh'
@@ -44,7 +43,6 @@ index 7dc3c92..46c608b 100644
 +
 +Hooks/Configure/Pre += Build/Compile/fake_python_sh
 +
-+
 +ifdef CONFIG_PACKAGE_python-ubus
 +CMAKE_OPTIONS = \
 +	-DLUAPATH=/usr/lib/lua  \
@@ -55,11 +53,10 @@ index 7dc3c92..46c608b 100644
  CMAKE_OPTIONS = \
  	-DLUAPATH=/usr/lib/lua
 +endif
-+
  
  define Package/ubus/install
  	$(INSTALL_DIR) $(1)/bin
-@@ -72,7 +97,13 @@ define Package/libubus-lua/install
+@@ -73,7 +96,13 @@ define Package/libubus-lua/install
  	$(CP) $(PKG_BUILD_DIR)/lua/ubus.so $(1)/usr/lib/lua/
  endef
  
@@ -73,2454 +70,6 @@ index 7dc3c92..46c608b 100644
  $(eval $(call BuildPackage,ubus))
  $(eval $(call BuildPackage,ubusd))
 +$(eval $(call BuildPackage,python-ubus))
-diff --git a/package/system/ubus/patches/001-python.patch b/package/system/ubus/patches/001-python.patch
-new file mode 100644
-index 0000000..7338b2f
---- /dev/null
-+++ b/package/system/ubus/patches/001-python.patch
-@@ -0,0 +1,2442 @@
-+diff --git a/CMakeLists.txt b/CMakeLists.txt
-+index 471b38e..cc6376c 100644
-+--- a/CMakeLists.txt
-++++ b/CMakeLists.txt
-+@@ -4,6 +4,7 @@ PROJECT(ubus C)
-+ ADD_DEFINITIONS(-Os -Wall --std=gnu99 -g3 -Wmissing-declarations)
-+ 
-+ OPTION(BUILD_LUA "build Lua plugin" ON)
-++OPTION(BUILD_PYTHON "build python plugin" OFF)
-+ OPTION(BUILD_EXAMPLES "build examples" ON)
-+ 
-+ SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
-+@@ -37,6 +38,9 @@ SET_TARGET_PROPERTIES(cli PROPERTIES OUTPUT_NAME ubus)
-+ TARGET_LINK_LIBRARIES(cli ubus ${ubox_library} ${blob_library} ${json})
-+ 
-+ ADD_SUBDIRECTORY(lua)
-++if (BUILD_PYTHON)
-++	    ADD_SUBDIRECTORY(python)
-++endif ()
-+ ADD_SUBDIRECTORY(examples)
-+ 
-+ INSTALL(TARGETS ubus cli
-+diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
-+new file mode 100644
-+index 0000000..2e66f2a
-+--- /dev/null
-++++ b/python/CMakeLists.txt
-+@@ -0,0 +1,58 @@
-++cmake_minimum_required(VERSION 3.0)
-++
-++SET(CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
-++SET(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
-++SET(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
-++
-++IF(NOT PYTHON_CFLAGS)
-++	FIND_PROGRAM(PKG_CONFIG pkg-config)
-++	IF(PKG_CONFIG)
-++		EXECUTE_PROCESS(
-++			COMMAND pkg-config --silence-errors --cflags python2
-++			OUTPUT_VARIABLE PYTHON_CFLAGS
-++			OUTPUT_STRIP_TRAILING_WHITESPACE
-++		)
-++	ENDIF()
-++ENDIF()
-++
-++IF(NOT PYTHON)
-++	FIND_PROGRAM(PYTHON python)
-++ENDIF()
-++
-++SET(PYTHON_CFLAGS "-Os -Wall --std=gnu99 -g3 -I.. ${PYTHON_CFLAGS}")
-++INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..)
-++LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..)
-++
-++IF(APPLE)
-++	SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -undefined dynamic_lookup")
-++ENDIF(APPLE)
-++
-++IF(NOT PYTHONPATH)
-++	EXECUTE_PROCESS(
-++		COMMAND ${PYTHON} -c "import os; print os.path.dirname(os.__file__)"
-++		OUTPUT_VARIABLE PYTHONPATH
-++		RESULT_VARIABLE PYTHON_CHECK_RES
-++		OUTPUT_STRIP_TRAILING_WHITESPACE
-++	)
-++
-++	IF(NOT ${PYTHON_CHECK_RES} EQUAL 0 OR "${PYTHONPATH}" EQUAL "")
-++		MESSAGE(SEND_ERROR "Python was not found on your system")
-++	ENDIF()
-++ENDIF()
-++
-++CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY})
-++
-++
-++SET(PYTHON_CFLAGS "${PYTHON_CFLAGS} -DUBUS_UNIX_SOCKET=\\\\\\\"${UBUS_UNIX_SOCKET}\\\\\\\"")
-++SET_PROPERTY(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "build")
-++
-++SET(LDSHARED "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} -shared")
-++
-++ADD_CUSTOM_TARGET(python ALL
-++	COMMAND ${CMAKE_COMMAND} -E env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" "LDSHARED=${LDSHARED}" "CFLAGS=${PYTHON_CFLAGS}" ${PYTHON} ${SETUP_PY} build
-++	DEPENDS ubus "${CURRENT_SOURCE_DIR}/ubus_python.c"
-++)
-++
-++INSTALL(
-++	CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E env \"CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}\" \"LDSHARED=${LDSHARED}\" \"CFLAGS=${PYTHON_CFLAGS}\" ${PYTHON} ${SETUP_PY} install --prefix=${CMAKE_INSTALL_PREFIX})"
-++)
-+diff --git a/python/README.rst b/python/README.rst
-+new file mode 100644
-+index 0000000..8fcd7f4
-+--- /dev/null
-++++ b/python/README.rst
-+@@ -0,0 +1,97 @@
-++Python bindings for ubus
-++========================
-++Code in this directory enables a subset of libubus functions to be used directly from python.
-++
-++Examples
-++########
-++
-++connect and disconnect
-++----------------------
-++To connect you need to::
-++
-++    import ubus
-++    ubus.connect("/var/run/ubus.sock")
-++
-++To disconnect you can simply::
-++
-++    ubus.disconnect()
-++
-++Note that calling connect()/disconnect() on opened/closed connection will throw an exception.
-++
-++add
-++---
-++To add an object to ubus you can (you need to become root first)::
-++
-++    def callback(handler, data):
-++        handler.reply(data)  # this should return exactly the same data to the caller
-++
-++    ubus.add(
-++        "my_object", {
-++            "my_method": {"method": callback, "signature": {
-++                    "first": ubus.BLOBMSG_TYPE_STRING,
-++                    "second": ubus.BLOBMSG_TYPE_BOOL,
-++                    "third": ubus.BLOBMSG_TYPE_INT32,
-++            }},
-++         },
-++    )
-++
-++You need to enter the loop to serve the object methods afterwards::
-++
-++    ubus.loop()
-++
-++
-++Note that it might not be a good idea to call the callback function recursively.
-++
-++
-++objects
-++-------
-++To list the objects which are currently connected to ubus you can call::
-++
-++    ubus.objects()
-++
-++    ->
-++
-++    {u'my_object': {u'my_method': {u'first': 3, u'second': 7, u'third': 5}}}
-++
-++
-++
-++call
-++----
-++To call an actual method on an object you can use::
-++
-++    ubus.call("my_object", "my_method", {"first": "my_string", "second": True, "third": 42})
-++
-++    ->
-++
-++    [{"first": "my_string", "second": True, "third": 42}]
-++
-++
-++listen
-++------
-++To listen for an event you can::
-++
-++    def callback(event, data):
-++        print(event, data)  # just print event name and data to stdout
-++
-++    ubus.listen(("my_event", callback))
-++
-++And you need to enter the loop to start to listen::
-++
-++    ubus.loop()
-++
-++Note that it might not be a good idea to call the callback function recursively.
-++
-++send
-++----
-++This will send an event to ubus::
-++
-++    ubus.send("my_event", {"some": "data"})
-++
-++
-++Notes
-++#####
-++
-++There are some tests present ('tests/' directory). So feel free to check it for some more complex examples.
-++To run the tests you need to have ubus installed and become root::
-++
-++    sudo python setup.py test
-+diff --git a/python/setup.cfg b/python/setup.cfg
-+new file mode 100644
-+index 0000000..d1844e1
-+--- /dev/null
-++++ b/python/setup.cfg
-+@@ -0,0 +1,6 @@
-++[aliases]
-++test=pytest
-++
-++[tool:pytest]
-++addopts = --verbose -s
-++python_files = tests/*.py
-+diff --git a/python/setup.py.in b/python/setup.py.in
-+new file mode 100644
-+index 0000000..b030d87
-+--- /dev/null
-++++ b/python/setup.py.in
-+@@ -0,0 +1,18 @@
-++from setuptools import setup, Extension
-++
-++extension = Extension(
-++    'ubus',
-++    ['@CURRENT_SOURCE_DIR@/ubus_python.c'],
-++    libraries=['ubus', 'blobmsg_json', 'ubox'],
-++    include_dirs=['@PROJECT_SOURCE_DIR@'],
-++    library_dirs=['@PROJECT_BINARY_DIR@'],
-++)
-++
-++setup(
-++    name='ubus',
-++    version='@PYTHON_PACKAGE_VERSION@',
-++    description="Python bindings for libubus",
-++    ext_modules=[extension],
-++    provides=['ubus'],
-++    tests_require=['pytest'],
-++)
-+diff --git a/python/tests/__init__.py b/python/tests/__init__.py
-+new file mode 100644
-+index 0000000..e69de29
-+diff --git a/python/tests/fixtures.py b/python/tests/fixtures.py
-+new file mode 100644
-+index 0000000..e9d28b4
-+--- /dev/null
-++++ b/python/tests/fixtures.py
-+@@ -0,0 +1,226 @@
-++import os
-++from multiprocessing import Process, Value
-++import pytest
-++import subprocess
-++import time
-++
-++
-++UBUSD_TEST_SOCKET_PATH = "/tmp/ubus-test-socket"
-++
-++
-++class Guard(object):
-++
-++    def __init__(self):
-++        self.counter = Value('i', 0)
-++
-++    def __enter__(self):
-++        return self
-++
-++    def __exit__(self, *args):
-++        return True
-++
-++    def touch(self):
-++        self.counter.value += 1
-++
-++    def wait(self):
-++        while not self.counter.value > 0:
-++            time.sleep(0.05)
-++
-++
-++@pytest.fixture(scope="session")
-++def ubusd_test():
-++    ubusd_instance = subprocess.Popen(["ubusd", "-s", UBUSD_TEST_SOCKET_PATH])
-++    while not os.path.exists(UBUSD_TEST_SOCKET_PATH):
-++        time.sleep(0.2)
-++    yield ubusd_instance
-++    ubusd_instance.kill()
-++    os.unlink(UBUSD_TEST_SOCKET_PATH)
-++
-++
-++@pytest.fixture(scope="function")
-++def event_sender():
-++
-++    with Guard() as guard:
-++
-++        def process_function():
-++            import ubus
-++            ubus.connect(UBUSD_TEST_SOCKET_PATH)
-++            while True:
-++                ubus.send("event_sender", dict(a="b", c=3, d=False))
-++                guard.touch()
-++                time.sleep(0.1)
-++
-++        p = Process(target=process_function, name="event_sender")
-++        p.start()
-++        guard.wait()
-++        setattr(p, 'counter', guard.counter)
-++
-++        yield p
-++
-++        p.terminate()
-++        p.join()
-++
-++
-++@pytest.fixture(scope="function")
-++def registered_objects():
-++    with Guard() as guard:
-++
-++        def process_function():
-++
-++            def handler1(*arg):
-++                pass
-++
-++            import ubus
-++            ubus.connect(UBUSD_TEST_SOCKET_PATH)
-++            ubus.add(
-++                "registered_object1",
-++                {
-++                    "method1": {"method": handler1, "signature": {}},
-++                    "method2": {"method": handler1, "signature": {
-++                        "first": ubus.BLOBMSG_TYPE_STRING,
-++                        "second": ubus.BLOBMSG_TYPE_BOOL,
-++                        "third": ubus.BLOBMSG_TYPE_INT32,
-++                    }},
-++                },
-++            )
-++            ubus.add(
-++                "registered_object2", {},
-++            )
-++            ubus.add(
-++                "registered_object3",
-++                {
-++                    "method1": {"method": handler1, "signature": {}},
-++                }
-++            )
-++            guard.touch()
-++            ubus.loop()
-++
-++        p = Process(target=process_function)
-++        p.start()
-++        guard.wait()
-++
-++        yield p
-++
-++        p.terminate()
-++        p.join()
-++
-++
-++@pytest.fixture(scope="function")
-++def responsive_object():
-++    with Guard() as guard:
-++
-++        def process_function():
-++
-++            def handler1(handler, data):
-++                data["passed"] = True
-++                handler.reply(data)
-++
-++            def handler2(handler, data):
-++                data["passed1"] = True
-++                handler.reply(data)
-++                data["passed2"] = True
-++                handler.reply(data)
-++                data["passed3"] = True
-++                handler.reply(data)
-++
-++            def handler_fail(handler, data):
-++                raise Exception("Handler Fails")
-++
-++            import ubus
-++            ubus.connect(UBUSD_TEST_SOCKET_PATH)
-++            ubus.add(
-++                "responsive_object",
-++                {
-++                    "respond": {"method": handler1, "signature": {
-++                        "first": ubus.BLOBMSG_TYPE_STRING,
-++                        "second": ubus.BLOBMSG_TYPE_BOOL,
-++                        "third": ubus.BLOBMSG_TYPE_INT32,
-++                    }},
-++                    "fail": {"method": handler_fail, "signature": {}},
-++                    "multi_respond": {"method": handler2, "signature": {}},
-++                    "number": {"method": handler1, "signature": {
-++                        "number": ubus.BLOBMSG_TYPE_INT32,
-++                    }},
-++                },
-++            )
-++            guard.touch()
-++            ubus.loop()
-++
-++        p = Process(target=process_function)
-++        p.start()
-++        guard.wait()
-++
-++        yield p
-++
-++        p.terminate()
-++        p.join()
-++
-++
-++@pytest.fixture(scope="function")
-++def call_for_object():
-++    with Guard() as guard:
-++
-++        def process_function():
-++
-++            import ubus
-++            ubus.connect(UBUSD_TEST_SOCKET_PATH)
-++            args = [
-++                ('callee_object', 'method1', {'first': 1}),
-++                ('callee_object', 'method2', {'second': 2}),
-++                ('callee_object', 'method3', {}),
-++            ]
-++            while True:
-++                for arg in args:
-++                    try:
-++                        ubus.call(*arg)
-++                    except RuntimeError as e:
-++                        pass
-++                    guard.touch()
-++                    time.sleep(0.05)
-++
-++        p = Process(target=process_function)
-++        p.start()
-++        guard.wait()
-++
-++        yield p
-++
-++        p.terminate()
-++        p.join()
-++
-++
-++@pytest.fixture(scope="function")
-++def calls_extensive():
-++    with Guard() as guard:
-++
-++        def process_function():
-++
-++            import ubus
-++            ubus.connect(UBUSD_TEST_SOCKET_PATH)
-++            while True:
-++                for i in range(20):
-++                    try:
-++                        ubus.call('extensive_object_%d' % i, 'method', {})
-++                        time.sleep(0.1)
-++                    except RuntimeError as e:
-++                        pass
-++                    guard.touch()
-++
-++        p = Process(target=process_function)
-++        p.start()
-++        guard.wait()
-++        setattr(p, 'counter', guard.counter)
-++
-++        yield p
-++
-++        p.terminate()
-++        p.join()
-++
-++
-++@pytest.fixture(scope="function")
-++def disconnect_after():
-++    yield None
-++    import ubus
-++    try:
-++        ubus.disconnect()
-++    except:
-++        pass
-+diff --git a/python/tests/test_connection.py b/python/tests/test_connection.py
-+new file mode 100644
-+index 0000000..d5ee835
-+--- /dev/null
-++++ b/python/tests/test_connection.py
-+@@ -0,0 +1,646 @@
-++import time
-++import pytest
-++import ubus
-++import sys
-++
-++from fixtures import (
-++    event_sender,
-++    call_for_object,
-++    calls_extensive,
-++    disconnect_after,
-++    ubusd_test,
-++    registered_objects,
-++    responsive_object,
-++    UBUSD_TEST_SOCKET_PATH,
-++)
-++
-++stored_reference_counts = None
-++
-++
-++class CheckRefCount(object):
-++
-++    def __init__(self, *objects):
-++        self.objects = objects
-++
-++    def __enter__(self):
-++        self.stored_reference_counts = [sys.getrefcount(e) for e in self.objects]
-++
-++    def __exit__(self, exc_type, *args):
-++
-++        if exc_type:
-++            # don't count references when an exception occured
-++            return
-++
-++        objects = self.objects
-++        current = [sys.getrefcount(e) for e in objects]
-++        stored = self.stored_reference_counts
-++        for (obj, old, new) in zip(objects, stored, current):
-++            assert old == new, "Reference count for '%s' mismatch (%d!=%d)" % (obj, old, new)
-++
-++
-++def test_socket_missing(ubusd_test):
-++    path = "/non/existing/path"
-++
-++    with CheckRefCount(path):
-++        with pytest.raises(IOError):
-++            ubus.connect(socket_path="/non/existing/path")
-++
-++
-++def test_connect_and_disconnect(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    with CheckRefCount(path):
-++
-++        assert ubus.get_connected() is False
-++        assert ubus.get_socket_path() is None
-++
-++        ubus.connect(socket_path=path)
-++        assert ubus.get_socket_path() == path
-++        assert ubus.get_connected() is True
-++
-++        assert ubus.disconnect() is None
-++        with pytest.raises(RuntimeError):
-++            ubus.disconnect()
-++        assert ubus.get_connected() is False
-++        assert ubus.get_socket_path() is None
-++
-++        ubus.connect(socket_path=path)
-++        with pytest.raises(RuntimeError):
-++            ubus.connect(socket_path=path)
-++        assert ubus.get_socket_path() == path
-++        assert ubus.get_connected() is True
-++
-++        assert ubus.disconnect() is None
-++
-++        assert ubus.get_connected() is False
-++        assert ubus.get_socket_path() is None
-++
-++
-++def test_send_failed(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    with CheckRefCount(path):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.send("disconnected", {})
-++
-++        ubus.connect(socket_path=path)
-++        with pytest.raises(TypeError):
-++            ubus.send()
-++
-++        with pytest.raises(TypeError):
-++            ubus.send({}, {})
-++
-++        with pytest.raises(TypeError):
-++            ubus.send("", "")
-++
-++        with pytest.raises(TypeError):
-++            ubus.send("", {}, {})
-++
-++        class NonSerializable(object):
-++            pass
-++
-++        with pytest.raises(TypeError):
-++            ubus.send("", NonSerializable())
-++
-++        ubus.disconnect()
-++
-++
-++def test_send_succeeded(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++    test_dict = dict(a=5, b="True", c=False)
-++
-++    with CheckRefCount(path, test_dict):
-++
-++        ubus.connect(socket_path=path)
-++
-++        assert ubus.send("normal", test_dict)
-++        assert ubus.send("*", test_dict)
-++        assert ubus.send("", test_dict)
-++
-++        ubus.disconnect()
-++
-++
-++def test_loop(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    time1 = 200
-++    time2 = 1
-++    time3 = 50
-++    time4 = 2 ** 65
-++    time5 = None
-++    time6 = "5"
-++    time7 = 0
-++
-++    with CheckRefCount(path, time1, time2, time3, time4, time6, time7):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.loop(time1)
-++
-++        ubus.connect(socket_path=path)
-++        assert ubus.loop(time1) is None
-++        assert ubus.loop(time2) is None
-++        assert ubus.loop(time3) is None
-++
-++        with pytest.raises(OverflowError):
-++            ubus.loop(time4)
-++
-++        with pytest.raises(TypeError):
-++            ubus.loop(time5)
-++
-++        with pytest.raises(TypeError):
-++            ubus.loop(time6)
-++
-++        assert ubus.loop(time7) is None
-++
-++        ubus.disconnect()
-++
-++
-++def test_listen_failed(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    obj1 = {}
-++    obj2 = ("a", lambda x, y: (x, y))
-++    obj3 = ("b", None)
-++    obj4 = ({}, lambda x, y: (x, y))
-++    obj5 = ("b", lambda x, y: (x, y))
-++
-++    with CheckRefCount(path, obj1, obj2, obj3, obj4, obj5):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.listen(obj1, obj1)
-++
-++        ubus.connect(socket_path=path)
-++
-++        with pytest.raises(TypeError):
-++            ubus.listen(obj1, obj1)
-++
-++        with pytest.raises(TypeError):
-++            ubus.send(obj2, obj3)
-++
-++        with pytest.raises(TypeError):
-++            ubus.send(obj4, obj5)
-++
-++        with pytest.raises(TypeError):
-++            ubus.listen()
-++
-++        ubus.disconnect()
-++
-++
-++def test_listen(ubusd_test, event_sender, disconnect_after):
-++    listen_test = {"passed": False, "passed2": False}
-++
-++    def set_result(event, data):
-++        assert event == "event_sender"
-++        assert data == dict(a="b", c=3, d=False)
-++        listen_test["passed"] = True
-++
-++    def test1(event, data):
-++        assert event == "event_sender"
-++        assert data == dict(a="b", c=3, d=False)
-++        listen_test["passed2"] = True
-++
-++    path = UBUSD_TEST_SOCKET_PATH
-++    timeout = 300
-++    event_name = "event_sender"
-++
-++    with CheckRefCount(path, time, event_name, test1):
-++
-++        ubus.connect(socket_path=path)
-++        ubus.listen((event_name, test1), (event_name, set_result))
-++        ubus.listen((event_name, test1))
-++
-++        del set_result
-++
-++        ubus.loop(timeout)
-++        assert listen_test["passed"]
-++        assert listen_test["passed2"]
-++
-++        listen_test = {"passed": False, "passed2": False}
-++        ubus.loop(timeout)
-++        assert listen_test["passed"]
-++        assert listen_test["passed2"]
-++
-++        ubus.disconnect()
-++
-++
-++def test_add_object_failed(ubusd_test, registered_objects, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    def fake(*args):
-++        pass
-++
-++    type_errors = [
-++        [],
-++        ("name", ),
-++        ("name", {}, False),
-++        ("name", {"test": []}),
-++        ("name", {"test": 5}),
-++        ("name", {"test": {"method": 5, "signature": {}}}),
-++        ("name", {"test": {"method": fake}}),
-++        ("name", {"test": {"method": fake, "signature": {}, "another": 5}}),
-++    ]
-++
-++    runtime_errors = [
-++        ("registered_object1", {"test": {"method": fake, "signature": {}}}),
-++        ("registered_object2", {}),
-++    ]
-++
-++    with CheckRefCount(path, fake, *(type_errors + runtime_errors)):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.add(*type_errors[0])
-++
-++        ubus.connect(socket_path=path)
-++
-++        for wrong_args in type_errors:
-++            with pytest.raises(TypeError):
-++                ubus.add(*wrong_args)
-++
-++        for wrong_args in runtime_errors:
-++            with pytest.raises(RuntimeError):
-++                ubus.add(*wrong_args)
-++
-++        ubus.disconnect()
-++        del wrong_args
-++
-++
-++def test_add_object(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    def fake(*args):
-++        pass
-++
-++    arguments1 = ("new_object1", {})
-++    arguments2 = ("new_object2", {"test": {"method": fake, "signature": {}}})
-++    arguments3 = ("new_object3", {
-++        "test1": {"method": fake, "signature": dict(arg1=3)},
-++        "test2": {"method": fake, "signature": dict(arg2=2)},
-++    })
-++
-++    with CheckRefCount(path, fake, *(arguments1 + arguments2 + arguments3)):
-++
-++        ubus.connect(socket_path=path)
-++
-++        assert ubus.add(*arguments1) is None
-++        assert ubus.add(*arguments2) is None
-++        assert ubus.add(*arguments3) is None
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.add(*arguments1)
-++
-++        ubus.disconnect()
-++
-++
-++def test_list_objects_failed(ubusd_test, registered_objects, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    type_errors = [
-++        ("more", "than", "one"),
-++        ({}, ),
-++        (True, ),
-++        (3, ),
-++        (None, ),
-++    ]
-++
-++    with CheckRefCount(path, *(type_errors)):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.objects()
-++
-++        ubus.connect(socket_path=path)
-++
-++        for wrong_args in type_errors:
-++            with pytest.raises(TypeError):
-++                ubus.objects(*wrong_args)
-++
-++        ubus.disconnect()
-++        del wrong_args
-++
-++
-++def test_list_objects(ubusd_test, registered_objects, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    def fake(*args):
-++        pass
-++
-++    new_object = ("new_object", {"new_method": {"method": fake, "signature": {}}})
-++
-++    expected1 = {
-++        u"registered_object1": {
-++            u"method1": {},
-++            u"method2": {
-++                u"first": ubus.BLOBMSG_TYPE_STRING,
-++                u"second": ubus.BLOBMSG_TYPE_BOOL,
-++                u"third": ubus.BLOBMSG_TYPE_INT32,
-++            },
-++        },
-++        u"registered_object2": {},
-++        u"registered_object3": {
-++            u"method1": {},
-++        },
-++    }
-++
-++    expected2 = {
-++        u"registered_object2": {},
-++    }
-++
-++    expected3 = {
-++        u"registered_object1": {
-++            u"method1": {},
-++            u"method2": {
-++                u"first": ubus.BLOBMSG_TYPE_STRING,
-++                u"second": ubus.BLOBMSG_TYPE_BOOL,
-++                u"third": ubus.BLOBMSG_TYPE_INT32,
-++            },
-++        },
-++        u"registered_object2": {},
-++        u"registered_object3": {
-++            u"method1": {},
-++        },
-++        u"new_object": {
-++            u"new_method": {},
-++        },
-++    }
-++
-++    expected4 = {
-++        u"new_object": {"new_method": {}},
-++    }
-++
-++    with CheckRefCount(path, fake, expected1, expected2, expected3, expected4, *new_object):
-++
-++        ubus.connect(socket_path=path)
-++
-++        # All objects
-++        res1 = ubus.objects()
-++        assert res1 == expected1
-++
-++        # Filtered objects
-++        res2 = ubus.objects("registered_object2")
-++        assert res2 == expected2
-++
-++        # Append an object
-++        ubus.add(*new_object)
-++
-++        # All objects + new
-++        res3 = ubus.objects()
-++        assert res3 == expected3
-++
-++        # New object
-++        res4 = ubus.objects("new_object")
-++        assert res4 == expected4
-++
-++        ubus.disconnect()
-++        del res1
-++        del res2
-++        del res3
-++        del res4
-++
-++
-++def test_list_objects_empty(ubusd_test, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    with CheckRefCount(path):
-++        ubus.connect(path)
-++        assert ubus.objects() == {}
-++
-++        ubus.disconnect()
-++
-++
-++def test_reply_out_of_handler():
-++    data = {"this": "should fail"}
-++
-++    with CheckRefCount(data):
-++
-++        # should be called only within call
-++        handler = ubus.__ResponseHandler()
-++        with pytest.raises(RuntimeError):
-++            handler.reply(data)
-++
-++        del handler
-++
-++
-++def test_reply_failed(ubusd_test, call_for_object, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    results = {e: {'data': None, 'exits': False} for e in range(1, 4)}
-++
-++    def handler_fail1(handler, data):
-++        results[1]['data'] = data
-++        handler.reply()
-++        results[1]['exits'] = True
-++
-++    def handler_fail2(handler, data):
-++        results[2]['data'] = data
-++        handler.reply(6)
-++        results[2]['exits'] = True
-++
-++    def handler_fail3(handler, data):
-++        results[3]['data'] = data
-++        handler.reply({'data': 6}, {'fail': 'here'})
-++        results[3]['exits'] = True
-++
-++    with CheckRefCount(path, results, handler_fail1, handler_fail2, handler_fail3):
-++
-++        ubus.connect(path)
-++        ubus.add(
-++            "callee_object",
-++            {
-++                "method1": {"method": handler_fail1, "signature": {
-++                    "first": ubus.BLOBMSG_TYPE_INT32,
-++                }},
-++                "method2": {"method": handler_fail2, "signature": {
-++                    "second": ubus.BLOBMSG_TYPE_INT32,
-++                }},
-++                "method3": {"method": handler_fail3, "signature": {}},
-++            },
-++        )
-++        ubus.loop(500)
-++
-++        assert results == {
-++            1: {'data': {'first': 1}, 'exits': False},
-++            2: {'data': {'second': 2}, 'exits': False},
-++            3: {'data': {}, 'exits': False},
-++        }
-++
-++        ubus.disconnect()
-++
-++
-++def test_reply(ubusd_test, call_for_object, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    results = {e: {'data': None, 'exits': False} for e in range(1, 4)}
-++
-++    def handler1(handler, data):
-++        results[1]['data'] = data
-++        handler.reply(data)
-++        results[1]['exits'] = True
-++
-++    def handler2(handler, data):
-++        results[2]['data'] = data
-++        handler.reply(data)
-++        results[2]['exits'] = True
-++
-++    def handler3(handler, data):
-++        results[3]['data'] = data
-++        handler.reply(data)
-++        results[3]['exits'] = True
-++
-++    with CheckRefCount(path, results, handler1, handler2, handler3):
-++
-++        ubus.connect(path)
-++        ubus.add(
-++            "callee_object",
-++            {
-++                "method1": {"method": handler1, "signature": {
-++                    "first": ubus.BLOBMSG_TYPE_INT32,
-++                }},
-++                "method2": {"method": handler2, "signature": {
-++                    "second": ubus.BLOBMSG_TYPE_INT32,
-++                }},
-++                "method3": {"method": handler3, "signature": {}},
-++            },
-++        )
-++        ubus.loop(500)
-++
-++        assert results == {
-++            1: {'data': {'first': 1}, 'exits': True},
-++            2: {'data': {'second': 2}, 'exits': True},
-++            3: {'data': {}, 'exits': True},
-++        }
-++
-++        ubus.disconnect()
-++
-++
-++def test_call_failed(ubusd_test, responsive_object, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    args1 = (
-++        [],
-++        ("responsive_object", ),
-++        ("responsive_object", "respond", ),
-++        ("responsive_object", "respond", 4, ),
-++        ("responsive_object", "respond", {"first": "test", "second": True, "third": 56}, "x"),
-++        ("responsive_object", "respond", {"first": "test", "second": True, "third": 56}, -1),
-++    )
-++    args2 = (
-++        ("responsive_object", "respond", {"first": 6, "second": True, "third": 56}, ),
-++        ("responsive_object", "respond", {"first": "test", "third": 56}, ),
-++        ("responsive_object", "respond", {"first": "test", "second": True, "third": 56, "x": 1}),
-++        ("responsive_object", "fail", {"first": "test", "second": True, "third": 56, "x": 1}),
-++        ("responsive_object", "fail", {}),
-++    )
-++    args3 = (
-++        ("responsive_object", "respond", {"first": "test", "second": True, "third": 56}, 2 ** 64),
-++    )
-++    with CheckRefCount(path, *(args1 + args2 + args3)):
-++
-++        with pytest.raises(RuntimeError):
-++            ubus.objects(*args1[0])
-++
-++        ubus.connect(path)
-++        for arg in args1:
-++            with pytest.raises(TypeError):
-++                ubus.call(*arg)
-++
-++        for arg in args2:
-++            with pytest.raises(RuntimeError):
-++                ubus.call(*arg)
-++
-++        for arg in args3:
-++            with pytest.raises(OverflowError):
-++                ubus.call(*arg)
-++
-++        ubus.disconnect()
-++        del arg
-++
-++
-++def test_call(ubusd_test, responsive_object, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    ubus_object = "responsive_object"
-++    method1 = "respond"
-++    method2 = "multi_respond"
-++    data = {"first": "1", "second": False, "third": 22}
-++
-++    with CheckRefCount(path, ubus_object, method1, method2):
-++
-++        ubus.connect(socket_path=path)
-++        res = ubus.call(ubus_object, method1, data)
-++        assert len(res) == 1
-++        assert res[0] == {"first": "1", "second": False, "third": 22, "passed": True}
-++
-++        res = ubus.call(ubus_object, method1, data, timeout=200)
-++        assert len(res) == 1
-++        assert res[0] == {"first": "1", "second": False, "third": 22, "passed": True}
-++
-++        res = ubus.call(ubus_object, method2, {})
-++        assert len(res) == 3
-++        assert res[0] == {"passed1": True}
-++        assert res[1] == {"passed1": True, "passed2": True}
-++        assert res[2] == {"passed1": True, "passed2": True, "passed3": True}
-++
-++        del res
-++        ubus.disconnect()
-++
-++
-++def test_call_max_min_number(ubusd_test, responsive_object, disconnect_after):
-++    path = UBUSD_TEST_SOCKET_PATH
-++    data1 = {"number": 2 ** 32}
-++    data2 = {"number": -(2 ** 32)}
-++
-++    with CheckRefCount(path, data1, data2):
-++
-++        ubus.connect(socket_path=path)
-++        res = ubus.call("responsive_object", "number", data1)
-++        assert res[0] == {"number": 2 ** 31 - 1, "passed": True}
-++        res = ubus.call("responsive_object", "number", data2)
-++        assert res[0] == {"number": -(2 ** 31), "passed": True}
-++
-++        del res
-++        ubus.disconnect()
-++
-++
-++def test_multi_objects_listeners(ubusd_test, event_sender, calls_extensive, disconnect_after):
-++    counts = 20
-++    listen_test = {"pass%d" % e: False for e in range(counts)}
-++    object_test = {"pass%d" % e: False for e in range(counts)}
-++    event_name = "event_sender"
-++    timeout = 200
-++
-++    path = UBUSD_TEST_SOCKET_PATH
-++
-++    def passed_listen_gen(index):
-++        def passed(*args):
-++            listen_test["pass%d" % index] = True
-++        return passed
-++
-++    def passed_object_gen(index):
-++        def passed(*args):
-++            object_test["pass%d" % index] = True
-++        return passed
-++
-++    with CheckRefCount(path, time):
-++
-++        for _ in range(5):
-++            ubus.connect(socket_path=path)
-++
-++            for i in range(counts):
-++                ubus.listen((event_name, passed_listen_gen(i)))
-++                ubus.add(
-++                    "extensive_object_%d" % i,
-++                    {"method": {"method": passed_object_gen(i), "signature": {}}}
-++                )
-++
-++            stored_counter = calls_extensive.counter.value
-++            while calls_extensive.counter.value - stored_counter < counts:
-++                ubus.loop(timeout)
-++            ubus.disconnect()
-++
-++            for i in range(counts):
-++                current = "pass%d" % i
-++                assert listen_test[current]
-++                assert object_test[current]
-++
-++            listen_test = {"pass%d" % e: False for e in range(counts)}
-++            object_test = {"pass%d" % e: False for e in range(counts)}
-+diff --git a/python/ubus_python.c b/python/ubus_python.c
-+new file mode 100644
-+index 0000000..d51ce43
-+--- /dev/null
-++++ b/python/ubus_python.c
-+@@ -0,0 +1,1324 @@
-++
-++#include <Python.h>
-++#include <dlfcn.h>
-++#include <libubox/blobmsg_json.h>
-++#include <libubus.h>
-++#include <stdio.h>
-++
-++#ifndef UBUS_UNIX_SOCKET
-++#define UBUS_UNIX_SOCKET "/var/run/ubus.sock"
-++#endif
-++
-++#define DEFAULT_SOCKET UBUS_UNIX_SOCKET
-++#define RESPONSE_HANDLER_OBJECT_NAME "ubus.__ResponseHandler"
-++
-++#define MSG_ALLOCATION_FAILS "Failed to allocate memory!"
-++#define MSG_LISTEN_TUPLE_EXPECTED "Expected (event, callback) tuple"
-++#define MSG_ADD_SIGNATURE_INVALID \
-++"Incorrect method arguments!\n" \
-++"Expected:\n" \
-++"	(<obj_name>, { " \
-++	"<method_name>: {'signature': <method_signature>, 'method': <callable>}" \
-++", ...})"
-++#define MSG_JSON_TO_UBUS_FAILED "Failed to create json for ubus."
-++#define MSG_JSON_FROM_UBUS_FAILED "Failed to create json from ubus."
-++#define MSG_NOT_CONNECTED "You are not connected to ubus."
-++#define MSG_ALREADY_CONNECTED "You are already connected to ubus."
-++
-++typedef struct {
-++	struct ubus_object object;
-++	PyObject *methods;
-++} ubus_Object;
-++
-++typedef struct {
-++	struct ubus_event_handler handler;
-++	PyObject *callback;
-++}ubus_Listener ;
-++
-++
-++PyObject *prepare_bool(bool yes)
-++{
-++	if (yes) {
-++		Py_INCREF(Py_True);
-++		return Py_True;
-++	} else {
-++		Py_INCREF(Py_False);
-++		return Py_False;
-++	}
-++}
-++
-++/* ubus module objects */
-++static PyMethodDef ubus_methods[];
-++PyObject *python_alloc_list = NULL;
-++char *socket_path = NULL;
-++ubus_Listener **listeners = NULL;
-++size_t listerners_size = 0;
-++ubus_Object **objects = NULL;
-++size_t objects_size = 0;
-++struct blob_buf python_buf;
-++struct ubus_context *ctx = NULL;
-++
-++#define CONNECTED (ctx != NULL)
-++
-++
-++/* json module handlers */
-++PyObject *json_module = NULL;
-++
-++enum json_function {
-++	LOADS,
-++	DUMPS,
-++};
-++
-++const char *json_function_names[2] = {
-++	[LOADS] = "loads",
-++	[DUMPS] = "dumps",
-++};
-++
-++
-++PyObject *perform_json_function(enum json_function json_function, PyObject *input)
-++{
-++	PyObject *function = PyObject_GetAttrString(json_module, json_function_names[json_function]);
-++	if (!function) {
-++		return NULL;
-++	}
-++	PyObject *arglist = Py_BuildValue("(O)", input);
-++	if (!arglist) {
-++		Py_DECREF(function);
-++		return NULL;
-++	}
-++	PyObject *data_object = PyObject_CallObject(function, arglist);
-++	Py_DECREF(function);
-++	Py_DECREF(arglist);
-++
-++	return data_object;  // New reference - should be decreased by the caller
-++}
-++
-++/* ResponseHandler */
-++
-++typedef struct {
-++	PyObject_HEAD
-++	struct ubus_context *ctx;
-++	struct ubus_request_data *req;
-++	struct blob_buf buf;
-++} ubus_ResponseHandler;
-++
-++static void ubus_ResponseHandler_dealloc(ubus_ResponseHandler* self)
-++{
-++	blob_buf_free(&self->buf);
-++	Py_TYPE(self)->tp_free((PyObject*)self);
-++}
-++
-++PyDoc_STRVAR(
-++	ResponseHandler_reply_doc,
-++	"reply(data)\n"
-++	"\n"
-++	":param data: JSON to be send as a response to a ubus call.\n"
-++	":type data: dict\n"
-++);
-++
-++static PyObject *ubus_ResponseHandler_reply(ubus_ResponseHandler *self, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	PyObject *data = NULL;
-++	static char *kwlist[] = {"data",  NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &data)) {
-++		return NULL;
-++	}
-++
-++	// Call python function json.dumps
-++	PyObject *json_str = perform_json_function(DUMPS, data);
-++	if (!json_str) {
-++		return NULL;
-++	}
-++
-++	// put json string into buffer
-++	blob_buf_init(&self->buf, 0);
-++	bool res = blobmsg_add_json_from_string(&self->buf, PyString_AsString(json_str));
-++	Py_DECREF(json_str);
-++	if (!res) {
-++		PyErr_Format(PyExc_TypeError, MSG_JSON_TO_UBUS_FAILED);
-++		return NULL;
-++	}
-++
-++	// handler is not linked to a call response
-++	if (!self->req || !self->ctx) {
-++		PyErr_Format(PyExc_RuntimeError, "Handler is not linked to a call response.");
-++		return NULL;
-++	}
-++
-++	int retval = ubus_send_reply(self->ctx, self->req, self->buf.head);
-++	return prepare_bool(!retval);
-++}
-++
-++PyDoc_STRVAR(
-++	ResponseHandler_doc,
-++	"__ResponseHandler\n"
-++	"\n"
-++	"Object which is used to handle responses to ubus calls.\n"
-++);
-++
-++static PyMethodDef ubus_ResponseHandler_methods[] = {
-++	{"reply", (PyCFunction)ubus_ResponseHandler_reply, METH_VARARGS|METH_KEYWORDS, ResponseHandler_reply_doc},
-++	{NULL},
-++};
-++
-++static int ubus_ResponseHandler_init(ubus_ResponseHandler *self, PyObject *args, PyObject *kwargs)
-++{
-++	static char *kwlist[] = {NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist)){
-++		return -1;
-++	}
-++	memset(&self->buf, 0, sizeof(self->buf));
-++	self->ctx = NULL;
-++	self->req = NULL;
-++	return 0;
-++}
-++
-++static PyObject *ubus_ResponseHandler_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
-++{
-++	ubus_ResponseHandler *self = (ubus_ResponseHandler *)type->tp_alloc(type, 0);
-++	return (PyObject *)self;
-++}
-++
-++static PyTypeObject ubus_ResponseHandlerType = {
-++	PyVarObject_HEAD_INIT(NULL, 0)
-++	RESPONSE_HANDLER_OBJECT_NAME,				/* tp_name */
-++	sizeof(ubus_ResponseHandler),				/* tp_basicsize */
-++	0,											/* tp_itemsize */
-++	(destructor)ubus_ResponseHandler_dealloc,	/* tp_dealloc */
-++	0,											/* tp_print */
-++	0,											/* tp_getattr */
-++	0,											/* tp_setattr */
-++	0,											/* tp_compare */
-++	0,											/* tp_repr */
-++	0,											/* tp_as_number */
-++	0,											/* tp_as_sequence */
-++	0,											/* tp_as_mapping */
-++	0,											/* tp_hash */
-++	0,											/* tp_call */
-++	0,											/* tp_str */
-++	0,											/* tp_getattro */
-++	0,											/* tp_setattro */
-++	0,											/* tp_as_buffer */
-++	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,	/* tp_flags */
-++	ResponseHandler_doc,						/* tp_doc */
-++	0,											/* tp_traverse */
-++	0,											/* tp_clear */
-++	0,											/* tp_richcompare */
-++	0,											/* tp_weaklistoffset */
-++	0,											/* tp_iter */
-++	0,											/* tp_iternext */
-++	ubus_ResponseHandler_methods,				/* tp_methods */
-++	0,											/* tp_members */
-++	0,											/* tp_getset */
-++	0,											/* tp_base */
-++	0,											/* tp_dict */
-++	0,											/* tp_descr_get */
-++	0,											/* tp_descr_set */
-++	0,											/* tp_dictoffset */
-++	(initproc)ubus_ResponseHandler_init,		/* tp_init */
-++	0,											/* tp_alloc */
-++	ubus_ResponseHandler_new,					/* tp_new */
-++};
-++
-++typedef struct {
-++	PyObject_HEAD
-++	PyObject *socket_path;
-++	ubus_Listener **listeners;
-++	size_t listerners_size;
-++	ubus_Object **objects;
-++	size_t objects_size;
-++	PyObject *alloc_list;  // Used for easy deallocation
-++	struct blob_buf buf;
-++	struct ubus_context *ctx;
-++} ubus_Connection;
-++
-++void free_ubus_object(ubus_Object *obj)
-++{
-++	if (obj->object.methods) {
-++		for (int i = 0; i < obj->object.n_methods; i++) {
-++			if (&obj->object.methods[i] && obj->object.methods[i].policy) {
-++				free((struct blobmsg_policy *)obj->object.methods[i].policy);
-++			}
-++		}
-++		free((struct ubus_method *)obj->object.methods);
-++	}
-++
-++	if (obj->object.type) {
-++		free(obj->object.type);
-++	}
-++	free(obj);
-++}
-++
-++PyObject *ubus_python_module_init(void)
-++{
-++	PyObject *module = Py_InitModule3("ubus", ubus_methods, "Ubus bindings");
-++	return module;
-++}
-++
-++PyDoc_STRVAR(
-++	disconnect_doc,
-++	"disconnect(deregister=True)\n"
-++	"\n"
-++	":param deregister: Deregisters object and handlers from ubus as well.\n"
-++	":type deregister: bool\n"
-++	"Disconnects from ubus and disposes all connection structures.\n"
-++);
-++
-++void dispose_connection(bool deregister)
-++{
-++	if (ctx != NULL) {
-++		if (deregister) {
-++			// remove objects
-++			for (int i = 0; i < objects_size; i++) {
-++				ubus_remove_object(ctx, &objects[i]->object);
-++			}
-++
-++			// remove listeners
-++			for (int i = 0; i < listerners_size; i++) {
-++				ubus_unregister_event_handler(ctx, &listeners[i]->handler);
-++			}
-++		}
-++
-++		ubus_free(ctx);
-++		ctx = NULL;
-++	}
-++	uloop_done();
-++	blob_buf_free(&python_buf);
-++	if (python_alloc_list) {
-++		Py_DECREF(python_alloc_list);
-++		python_alloc_list = NULL;
-++	}
-++	// clear event listeners
-++	if (listeners) {
-++		for (int i = 0; i < listerners_size; i++) {
-++			free(listeners[i]);
-++		}
-++		free(listeners);
-++		listerners_size = 0;
-++		listeners = NULL;
-++	}
-++	// clear objects
-++	if (objects) {
-++		for (int i = 0; i < objects_size; i++) {
-++			free_ubus_object(objects[i]);
-++		}
-++		free(objects);
-++		objects_size = 0;
-++		objects = NULL;
-++	}
-++
-++	if (socket_path) {
-++		free(socket_path);
-++		socket_path = NULL;
-++	}
-++}
-++
-++static PyObject *ubus_python_disconnect(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	PyObject* deregister = Py_True;
-++	static char *kwlist[] = {"deregister", NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!", kwlist, &PyBool_Type, &deregister)){
-++		return NULL;
-++	}
-++
-++	dispose_connection(PyObject_IsTrue(deregister));
-++
-++	Py_INCREF(Py_None);
-++	return Py_None;
-++}
-++
-++PyDoc_STRVAR(
-++	connect_doc,
-++	"connect(socket_path='" DEFAULT_SOCKET "')\n"
-++	"\n"
-++	"Establishes a connection to ubus.\n"
-++);
-++
-++static PyObject *ubus_python_connect(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_ALREADY_CONNECTED);
-++		return NULL;
-++	}
-++
-++	static char *kwlist[] = {"socket_path", NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &socket_path)){
-++		return NULL;
-++	}
-++
-++	// Init object list
-++	python_alloc_list = PyList_New(0);
-++	if (!python_alloc_list) {
-++		return NULL;
-++	}
-++
-++	// socket path
-++	if (!socket_path) {
-++		socket_path = strdup(DEFAULT_SOCKET);
-++		if (!socket_path) {
-++			PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++			return NULL;
-++		}
-++	} else {
-++		char *tmp = strdup(socket_path);
-++		if (!tmp) {
-++			PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++			return NULL;
-++		}
-++		socket_path = tmp;
-++	}
-++
-++	// Init event listner array
-++	listeners = NULL;
-++	listerners_size = 0;
-++
-++	// Init objects array
-++	objects = NULL;
-++	objects_size = 0;
-++
-++	// Connect to ubus
-++	ctx = ubus_connect(socket_path);
-++	if (!ctx) {
-++		PyErr_Format(
-++				PyExc_IOError,
-++				"Failed to connect to the ubus socket '%s'\n", socket_path
-++		);
-++		dispose_connection(true);
-++		return NULL;
-++	}
-++	ubus_add_uloop(ctx);
-++	memset(&python_buf, 0, sizeof(python_buf));
-++
-++	return prepare_bool(true);
-++}
-++
-++PyDoc_STRVAR(
-++	get_connected_doc,
-++	"get_connected()\n"
-++	"\n"
-++	"Determines whether we are connected to ubus.\n"
-++	":return: True if connected, False otherwise.\n"
-++	":rtype: bool \n"
-++);
-++
-++static PyObject *ubus_python_get_connected(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	return prepare_bool(CONNECTED);
-++}
-++
-++PyDoc_STRVAR(
-++	get_socket_path_doc,
-++	"get_socket_path()\n"
-++	"\n"
-++	"Gets socket path for the current connection.\n"
-++	":return: path to socket if connected, None otherwise.\n"
-++	":rtype: bool or str \n"
-++);
-++
-++static PyObject *ubus_python_get_socket_path(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (socket_path) {
-++		return PyString_FromString(socket_path);
-++	} else {
-++		Py_INCREF(Py_None);
-++		return Py_None;
-++	}
-++}
-++
-++PyDoc_STRVAR(
-++	connect_send_doc,
-++	"send(event, data)\n"
-++	"\n"
-++	"Send an event via ubus.\n"
-++	"\n"
-++	":param event: ubus event which will be used \n"
-++	":type event: str\n"
-++	":param data: python object which can be serialized to json \n"
-++	":type data: dict or list \n"
-++	":return: True on success, False otherwise \n"
-++	":rtype: bool \n"
-++);
-++
-++static PyObject *ubus_python_send(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	char *event = NULL;
-++	PyObject *data = NULL;
-++	static char *kwlist[] = {"event", "data",  NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO", kwlist, &event, &data)){
-++		return NULL;
-++	}
-++
-++	// Call python function json.dumps
-++	PyObject *json_str = perform_json_function(DUMPS, data);
-++	if (!json_str) {
-++		return NULL;
-++	}
-++
-++	// put json string into buffer
-++	blob_buf_init(&python_buf, 0);
-++	bool res = blobmsg_add_json_from_string(&python_buf, PyString_AsString(json_str));
-++	Py_DECREF(json_str);
-++	if (!res) {
-++		PyErr_Format(PyExc_TypeError, MSG_JSON_TO_UBUS_FAILED);
-++		return NULL;
-++	}
-++
-++	int retval = ubus_send_event(ctx, event, python_buf.head);
-++	return prepare_bool(!retval);
-++}
-++
-++static void ubus_python_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev,
-++			const char *type, struct blob_attr *msg)
-++{
-++	PyGILState_STATE gstate = PyGILState_Ensure();
-++
-++	// Prepare event
-++	PyObject *event = PyString_FromString(type);
-++	if (!event) {
-++		goto event_handler_cleanup0;
-++	}
-++
-++	// Prepare json data
-++	char *str = blobmsg_format_json(msg, true);
-++	if (!str) {
-++		goto event_handler_cleanup1;
-++	}
-++	PyObject *data = PyString_FromString(str);
-++	free(str);
-++	if (!data) {
-++		goto event_handler_cleanup1;
-++	}
-++
-++	// Call python function json.loads
-++	PyObject *data_object = perform_json_function(LOADS, data);
-++	if (!data_object) {
-++		goto event_handler_cleanup2;
-++	}
-++	
-++	// Get PyObject callback
-++	ubus_Listener *listener = container_of(ev, ubus_Listener, handler);
-++
-++	// Trigger callback
-++	PyObject *callback_arglist = Py_BuildValue("(O, O)", event, data_object);
-++	if (!callback_arglist) {
-++		goto event_handler_cleanup3;
-++	}
-++
-++	PyObject *result = PyObject_CallObject(listener->callback, callback_arglist);
-++	if (result) {
-++		Py_DECREF(result);  // result of the callback is quite useless
-++	} else {
-++		PyErr_Print();
-++	}
-++	Py_DECREF(callback_arglist);
-++
-++event_handler_cleanup3:
-++	Py_DECREF(data_object);
-++event_handler_cleanup2:
-++	Py_DECREF(data);
-++event_handler_cleanup1:
-++	Py_DECREF(event);
-++
-++event_handler_cleanup0:
-++	// Clear python exceptions
-++	PyErr_Clear();
-++
-++	PyGILState_Release(gstate);
-++}
-++
-++PyDoc_STRVAR(
-++	connect_listen_doc,
-++	"listen(event, ...)\n"
-++	"\n"
-++	"Adds a listener on ubus events.\n"
-++	"\n"
-++	":param event: tuple contaning event string and a callback (str, callable) \n"
-++	":type event: tuple\n"
-++);
-++
-++static PyObject *ubus_python_listen(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	args = PySequence_Fast(args, "expected a sequence");
-++	int len = PySequence_Size(args);
-++	if (!len) {
-++		PyErr_Format(PyExc_TypeError, "You need to set at least one event.");
-++		goto listen_error1;
-++	}
-++
-++	if (!PyTuple_Check(args)) {
-++		PyErr_Format(PyExc_TypeError, "Tuple of (event, callback) expected.");
-++		goto listen_error1;
-++	}
-++
-++	// Test whether the arguments are valid
-++	for (int i = 0; i < len; i++) {
-++		PyObject *item = PySequence_Fast_GET_ITEM(args, i);
-++		// Test tuple
-++		if (!PyTuple_Check(item)) {
-++			PyErr_Format(PyExc_TypeError, MSG_LISTEN_TUPLE_EXPECTED);
-++			goto listen_error1;
-++		}
-++		PyObject *item_tuple = PySequence_Fast(item, MSG_LISTEN_TUPLE_EXPECTED);
-++		if (!item_tuple) {
-++			PyErr_Format(PyExc_MemoryError, "Failed to obtain tuple item");
-++			goto listen_error1;
-++		}
-++		if (!PyTuple_Check(item_tuple) || PySequence_Size(item_tuple) != 2) {
-++			PyErr_Format(PyExc_TypeError, MSG_LISTEN_TUPLE_EXPECTED);
-++			Py_DECREF(item_tuple);
-++			Py_DECREF(args);
-++			goto listen_error1;
-++		}
-++
-++		// Test types
-++		if (!PyString_Check(PyTuple_GET_ITEM(item_tuple, 0))
-++					|| !PyCallable_Check(PyTuple_GET_ITEM(item_tuple, 1))) {
-++			PyErr_Format(PyExc_TypeError, MSG_LISTEN_TUPLE_EXPECTED);
-++			Py_DECREF(item_tuple);
-++			goto listen_error1;
-++		}
-++		Py_DECREF(item_tuple);
-++	}
-++
-++	// add callbacks
-++	for (int i = 0; i < len; i++) {
-++		PyObject *item = PySequence_Fast_GET_ITEM(args, i);
-++		PyObject *item_tuple = PySequence_Fast(item, MSG_LISTEN_TUPLE_EXPECTED);
-++		if (!item_tuple) {
-++			PyErr_Format(PyExc_MemoryError, "Failed to obtain tuple item");
-++			goto listen_error1;
-++		}
-++		PyObject *event = PyTuple_GET_ITEM(item_tuple, 0);
-++		PyObject *callback = PyTuple_GET_ITEM(item_tuple, 1);
-++		// Keep event and callback references
-++		if (PyList_Append(python_alloc_list, event) || PyList_Append(python_alloc_list, callback)) {
-++			Py_DECREF(item_tuple);
-++			goto listen_error1;
-++		}
-++		Py_DECREF(item_tuple);
-++
-++		// prepare event listener
-++		ubus_Listener *listener = calloc(1, sizeof(ubus_Listener));
-++		if (!listener) {
-++			PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++			Py_DECREF(item_tuple);
-++			goto listen_error1;
-++		}
-++
-++		listener->handler.cb = ubus_python_event_handler;
-++		listener->callback = callback;
-++
-++		ubus_Listener **new_listeners = realloc(listeners,
-++			(listerners_size + 1) * sizeof(*listeners));
-++		if (!new_listeners) {
-++			free(listener);
-++			goto listen_error1;
-++		}
-++		listeners = new_listeners;
-++		listeners[listerners_size++] = listener;
-++
-++		// register event handler
-++		int retval = ubus_register_event_handler(ctx, &listener->handler, PyString_AsString(event));
-++		if (retval != UBUS_STATUS_OK) {
-++			listerners_size--;
-++			free(listener);
-++		}
-++	}
-++
-++	Py_DECREF(args);
-++
-++	Py_INCREF(Py_None);
-++	return Py_None;
-++
-++listen_error1:
-++	Py_DECREF(args);
-++	return NULL;
-++}
-++
-++static void ubus_python_timeout_handler(struct uloop_timeout *timeout) {
-++	uloop_end();
-++}
-++
-++PyDoc_STRVAR(
-++	connect_loop_doc,
-++	"loop(timeout=-1)\n"
-++	"\n"
-++	"Enters a loop and processes events.\n"
-++	"\n"
-++	":param timeout: loop timeout in ms (if lower than zero then it will run forever) \n"
-++	":type timeout: int\n"
-++);
-++
-++static PyObject *ubus_python_loop(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	int timeout = -1;
-++	static char *kwlist[] = {"timeout", NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)){
-++		return NULL;
-++	}
-++
-++	Py_BEGIN_ALLOW_THREADS
-++	if (timeout == 0) {
-++		// process events directly without uloop
-++		ubus_handle_event(ctx);
-++	} else {
-++		uloop_init();
-++		struct uloop_timeout u_timeout;
-++		if (timeout > 0) {
-++			// prepare for timeout
-++			memset(&u_timeout, 0, sizeof(u_timeout));
-++			u_timeout.cb = ubus_python_timeout_handler;
-++			uloop_timeout_set(&u_timeout, timeout);  // Timeout to seconds
-++		}
-++		uloop_run();
-++		if (timeout > 0) {
-++			uloop_timeout_cancel(&u_timeout);
-++		}
-++	}
-++	Py_END_ALLOW_THREADS
-++
-++	Py_INCREF(Py_None);
-++	return Py_None;
-++}
-++
-++bool test_policies(const struct blobmsg_policy *policies, int n_policies, struct blob_attr *args)
-++{
-++	struct blob_attr *cur;
-++	int idx = 0, passed_count = 0;
-++
-++	blob_for_each_attr(cur, args, idx) {
-++		const char *name = blobmsg_name(cur);
-++		int type = blobmsg_type(cur);
-++		int pol_idx;
-++
-++		// Iterate through policies
-++		for (pol_idx = 0; pol_idx < n_policies; pol_idx++) {
-++
-++			if (!strcmp(name, policies[pol_idx].name)) {
-++				passed_count += 1;
-++				int pol_type = policies[pol_idx].type;
-++				if (pol_type != BLOBMSG_TYPE_UNSPEC && pol_type != type) {
-++					return false;
-++				}
-++				break;
-++			}
-++		}
-++
-++		// Policy was not found
-++		if (pol_idx >= n_policies) {
-++			return false;
-++		}
-++	}
-++
-++	// All attributes are present and checked
-++	return passed_count == n_policies;
-++}
-++
-++static int ubus_python_method_handler(struct ubus_context *ctx, struct ubus_object *obj,
-++		struct ubus_request_data *req, const char *method,
-++		struct blob_attr *msg)
-++{
-++	// Check whether method signature matches
-++	int method_idx;
-++	for (method_idx = 0; method_idx < obj->n_methods; ++method_idx) {
-++		if (!strcmp(obj->methods[method_idx].name, method)) {
-++			break;
-++		}
-++	}
-++	if (method_idx >= obj->n_methods) {
-++		// Can't find method
-++		return UBUS_STATUS_UNKNOWN_ERROR;
-++	}
-++	if (!test_policies(obj->methods[method_idx].policy, obj->methods[method_idx].n_policy, msg)) {
-++		return UBUS_STATUS_INVALID_ARGUMENT;
-++	}
-++
-++	PyGILState_STATE gstate = PyGILState_Ensure();
-++
-++	int retval = UBUS_STATUS_OK;
-++	// Get python method
-++	PyObject *methods = container_of(obj, ubus_Object, object)->methods;
-++	PyObject *python_method = PyDict_GetItemString(methods, method);
-++	if (!python_method) {
-++		retval = UBUS_STATUS_METHOD_NOT_FOUND;
-++		goto method_handler_exit;
-++	}
-++
-++	// prepare json data
-++	char *str = blobmsg_format_json(msg, true);
-++	if (!str) {
-++		retval = UBUS_STATUS_UNKNOWN_ERROR;
-++		goto method_handler_exit;
-++	}
-++	PyObject *data = PyString_FromString(str);
-++	free(str);
-++	if (!data) {
-++		retval = UBUS_STATUS_UNKNOWN_ERROR;
-++		goto method_handler_exit;
-++	}
-++
-++	// Call python function json.loads
-++	PyObject *data_object = perform_json_function(LOADS, data);
-++	if (!data_object) {
-++		retval = UBUS_STATUS_UNKNOWN_ERROR;
-++		goto method_handler_cleanup1;
-++	}
-++
-++	PyObject *handler = PyObject_CallObject((PyObject *)&ubus_ResponseHandlerType, NULL);
-++	if (!handler) {
-++		PyErr_Print();
-++		goto method_handler_cleanup2;
-++	}
-++	((ubus_ResponseHandler *)handler)->req = req;
-++	((ubus_ResponseHandler *)handler)->ctx = ctx;
-++
-++	// Trigger method
-++	PyObject *callback_arglist = Py_BuildValue("(O, O)", handler, data_object);
-++	if (!callback_arglist) {
-++		retval = UBUS_STATUS_UNKNOWN_ERROR;
-++		goto method_handler_cleanup3;
-++	}
-++	PyObject *callable = PyDict_GetItemString(python_method, "method");
-++	PyObject *result = PyObject_CallObject(callable, callback_arglist);
-++	Py_DECREF(callback_arglist);
-++	if (!result) {
-++		PyErr_Print();
-++		retval = UBUS_STATUS_UNKNOWN_ERROR;
-++	} else {
-++		Py_DECREF(result);  // we don't care about the result
-++	}
-++
-++method_handler_cleanup3:
-++	// NULLify the structures so that using this structure will we useless if a reference
-++	// is left outside the callback code
-++	((ubus_ResponseHandler *)handler)->req = NULL;
-++	((ubus_ResponseHandler *)handler)->ctx = NULL;
-++	Py_DECREF(handler);
-++method_handler_cleanup2:
-++	Py_DECREF(data_object);
-++method_handler_cleanup1:
-++	Py_DECREF(data);
-++method_handler_exit:
-++
-++	// Clear python exceptions
-++	PyErr_Clear();
-++
-++	PyGILState_Release(gstate);
-++
-++	return retval;
-++}
-++
-++static bool test_methods_argument(PyObject *methods)
-++{
-++	if (!methods) {
-++		return false;
-++	}
-++
-++	PyObject *method_name = NULL, *value = NULL;
-++	Py_ssize_t pos = 0;
-++	// Iterate through methods
-++	while(PyDict_Next(methods, &pos, &method_name, &value)) {
-++		// Test name
-++		if (!PyString_Check(method_name)) {
-++			return false;
-++		}
-++		if (!PyDict_Check(value)) {
-++			return false;
-++		}
-++
-++		// Dict should contain only two elemnts - 'signature' and 'method'
-++		if (PyDict_Size(value) != 2) {
-++				return false;
-++		}
-++
-++		// Test signature
-++		PyObject *signature = PyDict_GetItemString(value, "signature");
-++		if (!signature || !PyDict_Check(signature)) {
-++			return false;
-++		}
-++		Py_ssize_t sig_pos = 0;
-++		PyObject *signature_name = NULL, *signature_type = NULL;
-++		while (PyDict_Next(signature, &sig_pos, &signature_name, &signature_type)) {
-++			if (!PyString_Check(signature_name)) {
-++				return false;
-++			}
-++			if (!PyInt_Check(signature_type)) {
-++				return false;
-++			}
-++			int type = PyInt_AsLong(signature_type);
-++			if (type < 0 || type > BLOBMSG_TYPE_LAST) {  // indexed from 0
-++				return false;
-++			}
-++		}
-++
-++		// Test callable
-++		PyObject *method = PyDict_GetItemString(value, "method");
-++		if (!method || !PyCallable_Check(method)) {
-++			return false;
-++		}
-++	}
-++
-++	return true;
-++}
-++
-++PyDoc_STRVAR(
-++	connect_add_doc,
-++	"add(object_name, methods)\n"
-++	"\n"
-++	"Adds an object to ubus.\n"
-++	"methods should look like this: \n"
-++	"{ \n"
-++	"	<method_name>: {'signature': <method_signature>, 'method': <callable>} \n"
-++	"} \n"
-++	"\n"
-++	"{ \n"
-++	"	test: {'signature': {'argument1': BLOBMSG_TYPE_STRING}, 'method': my_callback} \n"
-++	"} \n"
-++	"\n"
-++	":param object_name: the name of the object which will be present on ubus \n"
-++	":type object_name: str\n"
-++	":param methods: {<method_name>: callable} where callable signature is (request, msg) \n"
-++	":type methods: dict\n"
-++);
-++
-++static PyObject *ubus_python_add(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	// arguments
-++	PyObject *object_name = NULL;
-++	PyObject *methods= NULL;
-++	static char *kwlist[] = {"object_name", "methods",  NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO", kwlist, &object_name, &methods)){
-++		return NULL;
-++	}
-++
-++	// test arguments
-++	if (!PyString_Check(object_name)) {
-++		PyErr_Format(PyExc_TypeError, MSG_ADD_SIGNATURE_INVALID);
-++		return NULL;
-++	}
-++
-++	if (!test_methods_argument(methods)) {
-++		PyErr_Format(PyExc_TypeError, MSG_ADD_SIGNATURE_INVALID);
-++		return NULL;
-++	}
-++
-++	// allocate the object
-++	ubus_Object *object = calloc(1, sizeof(ubus_Object));
-++	if (!object) {
-++		PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++		return NULL;
-++	}
-++	object->methods = methods;
-++
-++	// set the object
-++	object->object.name = PyString_AsString(object_name);
-++	object->object.n_methods = PyDict_Size(methods);
-++
-++	if (object->object.n_methods > 0) {
-++		struct ubus_method *ubus_methods = calloc(object->object.n_methods, sizeof(struct ubus_method));
-++		if (!ubus_methods) {
-++			free(object);
-++			PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++			return NULL;
-++		}
-++
-++		PyObject *method_name = NULL, *value = NULL;
-++		Py_ssize_t pos = 0;
-++		// Iterate through methods
-++		for (int i = 0; PyDict_Next(methods, &pos, &method_name, &value); i++) {
-++			ubus_methods[i].name = PyString_AsString(method_name);
-++			ubus_methods[i].handler = ubus_python_method_handler;
-++
-++			// alocate and set policy objects
-++			PyObject *signature = PyDict_GetItemString(value, "signature");
-++			Py_ssize_t signature_size = PyDict_Size(signature);
-++			struct blobmsg_policy *policy = calloc(signature_size, sizeof(struct blobmsg_policy));
-++			if (!policy) {
-++				// dealloc allocated data
-++				free_ubus_object(object);
-++				PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++				return NULL;
-++			}
-++			Py_ssize_t sig_pos = 0;
-++			PyObject *signature_name = NULL, *signature_type = NULL;
-++			for (int j = 0; PyDict_Next(signature, &sig_pos, &signature_name, &signature_type); j++) {
-++				policy[j].name = PyString_AsString(signature_name);
-++				policy[j].type = PyInt_AsLong(signature_type);
-++			}
-++			ubus_methods[i].policy = policy;
-++			ubus_methods[i].n_policy = signature_size;
-++		}
-++
-++		// assign methods
-++		object->object.methods = ubus_methods;
-++	}
-++
-++	object->object.type = calloc(1, sizeof(struct ubus_object_type));
-++	if (!object->object.type) {
-++		free_ubus_object(object);
-++		PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++		return NULL;
-++	}
-++	object->object.type->name = PyString_AsString(object_name);
-++	object->object.type->methods = object->object.methods;
-++	object->object.type->n_methods = object->object.n_methods;
-++
-++	// add object to object array to be deallocated later
-++	ubus_Object **new_objects = realloc(objects,
-++			(objects_size + 1) * sizeof(*objects));
-++	if (!new_objects) {
-++		// dealloc the object
-++		free_ubus_object(object);
-++		PyErr_Format(PyExc_MemoryError, MSG_ALLOCATION_FAILS);
-++		return NULL;
-++	}
-++	objects = new_objects;
-++	objects[objects_size++] = object;
-++
-++	int ret = ubus_add_object(ctx, &object->object);
-++	if (ret) {
-++		// deallocate object on failure
-++		objects_size--;  // no need to realloc the whole array
-++		free_ubus_object(object);
-++
-++		PyErr_Format(
-++				PyExc_RuntimeError,
-++				"ubus error occured: %s", ubus_strerror(ret)
-++		);
-++		return NULL;
-++	}
-++
-++	// put arguments into alloc list (used for reference counting)
-++	if (PyList_Append(python_alloc_list, object_name)) {
-++		ubus_remove_object(ctx, &object->object);
-++		free_ubus_object(object);
-++		return NULL;
-++	}
-++
-++	if (PyList_Append(python_alloc_list, methods)) {
-++		ubus_remove_object(ctx, &object->object);
-++		free_ubus_object(object);
-++		PyEval_CallMethod(python_alloc_list, "pop", "");
-++		return NULL;
-++	}
-++
-++	Py_INCREF(Py_None);
-++	return Py_None;
-++}
-++
-++static void ubus_python_objects_handler(struct ubus_context *c, struct ubus_object_data *o, void *p)
-++{
-++	// should be a single instance for all the objects
-++	PyObject *objects = (PyObject *)p;
-++
-++	PyObject *str_signatures = PyString_FromString("{");
-++	if (!str_signatures) {
-++		return;
-++	}
-++
-++	bool first = true;
-++	if (o->signature) {
-++		struct blob_attr *cur;
-++		int rem = 0;
-++		blob_for_each_attr(cur, o->signature, rem) {
-++			char *s = blobmsg_format_json(cur, false);
-++			if (!s) {
-++				goto object_handler_cleanup;
-++			}
-++			PyObject *str_signature = NULL;
-++			if (first) {
-++				first = false;
-++				str_signature = PyString_FromString(s);
-++			} else {
-++				str_signature = PyString_FromFormat(" ,%s", s);
-++			}
-++			free(s);
-++			if (!str_signature) {
-++				goto object_handler_cleanup;
-++			}
-++			PyString_Concat(&str_signatures, str_signature);
-++			Py_DECREF(str_signature);
-++			if (!str_signatures) {
-++				return;  //str_signatures already discarded in PyString_Concat
-++			}
-++		}
-++	}
-++
-++	PyObject *closing_bracket = PyString_FromString("}");
-++	PyString_Concat(&str_signatures, closing_bracket);
-++	Py_DECREF(closing_bracket);
-++	if (!str_signatures) {
-++		return;
-++	}
-++
-++	// convert json string to json
-++	PyObject *json_signatures = perform_json_function(LOADS, str_signatures);
-++	if (!json_signatures) {
-++		goto object_handler_cleanup;
-++	}
-++
-++	// Add it to dict object
-++	PyObject *path = PyUnicode_FromString(o->path);
-++	if (!path) {
-++		goto object_handler_cleanup;
-++	}
-++	PyDict_SetItem(objects, path, json_signatures);  // we don't care about retval here
-++	Py_DECREF(path);
-++
-++object_handler_cleanup:
-++	Py_DECREF(str_signatures);
-++
-++	// Clear python exceptions
-++	PyErr_Clear();
-++}
-++
-++PyDoc_STRVAR(
-++	connect_objects_doc,
-++	"objects(path='*')\n"
-++	"\n"
-++	"Prints all objects present on ubus\n"
-++	"\n"
-++	":param path: only object which match the given path \n"
-++	":type path: str\n"
-++	":return: {<object_path>: {{<function_name>: <function_signature>}, ...}, ...} \n"
-++	":rtype: dict\n"
-++);
-++
-++static PyObject *ubus_python_objects(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	char *ubus_path = NULL;
-++	static char *kwlist[] = {"path", NULL};
-++	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &ubus_path)){
-++		return NULL;
-++	}
-++
-++	ubus_path = ubus_path ? ubus_path : "*";
-++
-++	PyObject *res = PyDict_New();
-++	if (!res) {
-++		return NULL;
-++	}
-++
-++	int retval = ubus_lookup(ctx, ubus_path, ubus_python_objects_handler, res);
-++	switch (retval) {
-++		case UBUS_STATUS_OK:
-++		case UBUS_STATUS_NOT_FOUND:
-++			break;
-++		default:
-++			Py_DECREF(res);
-++			PyErr_Format(
-++					PyExc_RuntimeError,
-++					"ubus error occured: %s", ubus_strerror(retval)
-++			);
-++			return NULL;
-++	}
-++
-++	return res;
-++}
-++
-++static void ubus_python_call_handler(struct ubus_request *req, int type, struct blob_attr *msg)
-++{
-++	assert(type == UBUS_MSG_DATA);
-++
-++	PyObject **results = (PyObject **)req->priv;
-++	if (!*results) {
-++		// error has occured in some previous call -> exit
-++		return;
-++	}
-++
-++	if (!msg) {
-++		PyErr_Format(PyExc_RuntimeError, "No data in call hander");
-++		goto call_handler_cleanup;
-++	}
-++
-++	// convert message do python json object
-++	char *str = blobmsg_format_json(msg, true);
-++	if (!str) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_JSON_FROM_UBUS_FAILED);
-++		goto call_handler_cleanup;
-++	}
-++	PyObject *data = PyString_FromString(str);
-++	free(str);
-++	if (!data) {
-++		goto call_handler_cleanup;
-++	}
-++	PyObject *data_object = perform_json_function(LOADS, data);
-++	Py_DECREF(data);
-++	if (!data_object) {
-++		goto call_handler_cleanup;
-++	}
-++
-++	// append to results
-++	int failed = PyList_Append(*results, data_object);
-++	Py_DECREF(data_object);
-++	if (failed) {
-++		goto call_handler_cleanup;
-++	}
-++
-++	return;
-++
-++	call_handler_cleanup:
-++
-++	// clear the result
-++	Py_DECREF(*results);
-++	results = NULL;
-++}
-++
-++PyDoc_STRVAR(
-++	connect_call_doc,
-++	"call(object, method, arguments, timeout=0)\n"
-++	"\n"
-++	"Calls object's method on ubus.\n"
-++	"\n"
-++	":param object: name of the object\n"
-++	":type object: str\n"
-++	":param method: name of the method\n"
-++	":type method: str\n"
-++	":param arguments: arguments of the method (should be JSON serialisable).\n"
-++	":type argument: dict\n"
-++	":param timeout: timeout in ms (0 = wait forever)\n"
-++	":type timeout: int\n"
-++);
-++
-++static PyObject *ubus_python_call(PyObject *module, PyObject *args, PyObject *kwargs)
-++{
-++	if (!CONNECTED) {
-++		PyErr_Format(PyExc_RuntimeError, MSG_NOT_CONNECTED);
-++		return NULL;
-++	}
-++
-++	char *object = NULL, *method = NULL;
-++	int timeout = 0;
-++	PyObject *arguments = NULL;
-++	static char *kwlist[] = {"object", "method", "arguments", "timeout", NULL};
-++	if (!PyArg_ParseTupleAndKeywords(
-++				args, kwargs, "ssO|i", kwlist, &object, &method, &arguments, &timeout)){
-++		return NULL;
-++	}
-++	if (timeout < 0) {
-++		PyErr_Format(PyExc_TypeError, "timeout can't be lower than 0");
-++		return NULL;
-++	}
-++
-++	uint32_t id = 0;
-++	int retval = ubus_lookup_id(ctx, object, &id);
-++	if (retval != UBUS_STATUS_OK) {
-++		PyErr_Format(PyExc_RuntimeError, "Object '%s' was not found.", object);
-++		return NULL;
-++	}
-++
-++	// Call python function json.dumps
-++	PyObject *json_arguments = perform_json_function(DUMPS, arguments);
-++	if (!json_arguments) {
-++		return NULL;
-++	}
-++
-++	// put data into buffer
-++	blob_buf_init(&python_buf, 0);
-++	bool res = blobmsg_add_json_from_string(&python_buf, PyString_AsString(json_arguments));
-++	Py_DECREF(json_arguments);
-++	if (!res) {
-++		PyErr_Format(PyExc_TypeError, MSG_JSON_TO_UBUS_FAILED);
-++		return NULL;
-++	}
-++
-++	PyObject *results = PyList_New(0);
-++	if (!results) {
-++		return NULL;
-++	}
-++
-++	retval = ubus_invoke(
-++			ctx, id, method, python_buf.head, ubus_python_call_handler, &results, timeout);
-++
-++	if (retval != UBUS_STATUS_OK) {
-++		Py_XDECREF(results);
-++		PyErr_Format(
-++				PyExc_RuntimeError,
-++				"ubus error occured: %s", ubus_strerror(retval)
-++		);
-++		return NULL;
-++	}
-++
-++	// Note that results might be NULL indicating that something went wrong in the handler
-++	return results;
-++}
-++
-++static PyMethodDef ubus_methods[] = {
-++	{"disconnect", (PyCFunction)ubus_python_disconnect, METH_VARARGS|METH_KEYWORDS, disconnect_doc},
-++	{"connect", (PyCFunction)ubus_python_connect, METH_VARARGS|METH_KEYWORDS, connect_doc},
-++	{"get_connected", (PyCFunction)ubus_python_get_connected, METH_NOARGS, get_connected_doc},
-++	{"get_socket_path", (PyCFunction)ubus_python_get_socket_path, METH_NOARGS, get_socket_path_doc},
-++	{"send", (PyCFunction)ubus_python_send, METH_VARARGS|METH_KEYWORDS, connect_send_doc},
-++	{"listen", (PyCFunction)ubus_python_listen, METH_VARARGS, connect_listen_doc},
-++	{"loop", (PyCFunction)ubus_python_loop, METH_VARARGS|METH_KEYWORDS, connect_loop_doc},
-++	{"add", (PyCFunction)ubus_python_add, METH_VARARGS|METH_KEYWORDS, connect_add_doc},
-++	{"objects", (PyCFunction)ubus_python_objects, METH_VARARGS|METH_KEYWORDS, connect_objects_doc},
-++	{"call", (PyCFunction)ubus_python_call, METH_VARARGS|METH_KEYWORDS, connect_call_doc},
-++	{NULL}
-++};
-++
-++PyMODINIT_FUNC initubus(void) {
-++	if (PyType_Ready(&ubus_ResponseHandlerType)) {
-++		return;
-++	}
-++
-++	json_module = PyImport_ImportModule("json");
-++	if (!json_module) {
-++		return;
-++	}
-++
-++	PyObject *module = ubus_python_module_init();
-++	if (!module) {
-++		return;
-++	}
-++
-++	Py_INCREF(&ubus_ResponseHandlerType);
-++	PyModule_AddObject(module, "__ResponseHandler", (PyObject *)&ubus_ResponseHandlerType);
-++
-++	/* export ubus json types */
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_UNSPEC);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_ARRAY);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_TABLE);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_STRING);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_INT64);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_INT32);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_INT16);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_INT8);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_DOUBLE);
-++	PyModule_AddIntMacro(module, BLOBMSG_TYPE_BOOL);
-++}
 -- 
-2.16.2
+2.18.0