Cross compile smbclient for Dafang Hacks
Dafang Hacks is a 3rd party firmware for Ingenic T20 based IP cameras (i.e., Xiaomi Dafang/Wyzecam V2, etc.) The smbclient
comes with the firmware is a very old version (2.2.7) which is incompatible with modern Samba protocols (SMB2/SMB3), but only LANMAN1
/LANMAN2
, which have serious security issues.
Samba supports SMB2 and durable handles from version 4.0, however, smbclient
does not support SMB2 until 4.1. From version 4.0, Samba uses waf
for build system but still keeps autoconf
, but since version 4.1
autoconf
is removed and waf
became the only choice, which makes cross-compiling rather challenging.
I have tested several versions of Samba from 4.0 to 4.9 (versions above 4.9 requires gnutls, which is not compatible with mips uClibc that Dafang rootfs uses, according to here). It appears that Samba 4.7.12 can build a single binary of smbclient
so we don’t need to copy over a bunch of libraries and mess with LD_LIBRARY_PATH
. Yet, Samba 4.7.12 still needs some tweaks and patches to make it cross-compile using the Ingenic T20 toolchain.
I did the cross compilation with WSL2 and Void Linux, although other distros should work as well.
Assuming basic development tools are installed, the first thing is to grab Ingenic T20 toolchain:
git clone https://github.com/Dafang-Hacks/mips-gcc472-glibc216-64bit
which will provide the compilers we need for Dafang.
Before compiling Samba, several other packages needs to be installed. I’m using Void so package names may vary.
sudo xbps-install -S qemu qemu-user-static libtirpc-devel
We need qemu-mipsel-static
for --cross-execute
of Samba according to the doc, and libtirpc-devel
is still needed for host arch since we will need to compile asn1_compile
and compile_et
for host. Also, we need source code of libtirpc
so we can build it for target as well.
After grabbing source of libtirpc
from https://sourceforge.net/projects/libtirpc/, we can write a script to do cross compiling of that:
#!/bin/bash
TOOLCHAIN=~/mips-gcc472-glibc216-64bit/bin
INSTALLPATH=$(pwd)/../_install
CROSS_COMPILE=$TOOLCHAIN/mips-linux-gnu-
export CC=${CROSS_COMPILE}gcc
export CPP=${CROSS_COMPILE}cpp
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export RANLIB=${CROSS_COMPILE}ranlib
export READELF=${CROSS_COMPILE}readelf
export LDFLAGS="-muclibc -O3 -L${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/lib"
export CFLAGS="-muclibc -O3 -I${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/usr/include"
export CPPFLAGS="-muclibc -O3 -I${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/usr/include"
./configure --host=mips-linux-gnu --prefix=${INSTALLPATH} \
--disable-gssapi --disable-ipv6 \
&& make -j16 && make install
assuming toolchain was cloned to home folder.
Then we can build Samba on host to get binaries of asn1_compile
and compile_et
, and save it somewhere else (in my case samba-4.7.12/hostbin
).
./buildtools/bin/waf configure --prefix=/system/sdcard \
--without-gettext --disable-tdb-mutex-locking --disable-gnutls --disable-python \
--without-gpgme --without-winbind --without-ads --without-ldap --disable-cups \
--disable-iprint --without-pam --without-quotas --disable-avahi --without-iconv --without-acl-support \
--without-dnsupdate --without-syslog --without-automount --without-dmapi --without-fam --without-libarchive \
--without-regedit --without-fake-kaserver --disable-glusterfs --disable-cephfs --disable-fault-handling \
--without-systemd --without-lttng --accel-aes=none --disable-pthreadpool --without-ad-dc --nopyc --nopyo \
--without-ntvfs-fileserver --disable-rpath --disable-rpath-install --disable-rpath-private-install
./buildtools/bin/waf build --targets=asn1_compile,compile_et
mkdir -p hostbin
mv bin/default/source4/heimdal_build/asn1_compile ./hostbin/asn1_compile_host
mv bin/default/source4/heimdal_build/compile_et ./hostbin/compile_et_host
make distclean
The GCC in toolchain is old (gcc 4.7.2), and it will run into issues when compiling Samba with errors like:
mips-linux-gnu-gcc: error: void: No such file or directory
It’s because gcc in toolchain does not take macro definitions with whitespace in it, namely, anything like -DSTRING="abc def"
will result in mips-linux-gnu-gcc: error: def: No such file or directory
. To solve this, we need to patch samba-deps.py
to escape all whitespaces into \x20
:
--- a/buildtools/wafsamba/samba_deps.py 2017-07-04 06:05:25.000000000 -0400
+++ b/buildtools/wafsamba/samba_deps.py 2021-03-14 18:01:22.730000000 -0400
@@ -235,3 +235,3 @@
if sentinel == 'NULL':
- proto = "extern void __%s_dummy_module_proto(void)" % (sname)
+ proto = "\'\"extern\\x20void\\x20__%s_dummy_module_proto(void)\"\'" % (sname)
cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (sname, proto))
@@ -250,3 +250,3 @@
if sentinel == 'NULL':
- proto = "extern void __%s_dummy_module_proto(void)" % (m)
+ proto = "\'\"extern\\x20void\\x20__%s_dummy_module_proto(void)\"\'" % (m)
cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto))
@@ -257,3 +257,3 @@
proto += '_MODULE_PROTO(%s)' % f
- proto += "extern void __%s_dummy_module_proto(void)" % (m)
+ proto += "\'\"extern\\x20void\\x20__%s_dummy_module_proto(void)\"\'" % (m)
cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto))
Assuming libtirpc
was installed into _install
folder at the same level as Samba source, we can use the cross compile script to build Samba:
#!/bin/bash
TOOLCHAIN=~/mips-gcc472-glibc216-64bit/bin
INSTALLPATH=$(pwd)/../_install
CROSS_COMPILE=$TOOLCHAIN/mips-linux-uclibc-gnu-
export CC=${CROSS_COMPILE}gcc
export CPP=${CROSS_COMPILE}cpp
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export RANLIB=${CROSS_COMPILE}ranlib
export READELF=${CROSS_COMPILE}readelf
export LD=${CROSS_COMPILE}ld
export STRIP=${CROSS_COMPILE}strip
export LDFLAGS="-muclibc -O3 -L${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/lib -L${INSTALLPATH}/lib"
export CFLAGS="-muclibc -O3 -I${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/usr/include -I${INSTALLPATH}/include -I${INSTALLPATH}/include/tirpc"
export CPPFLAGS="-muclibc -O3 -I${TOOLCHAIN}/../mips-linux-gnu/libc/uclibc/usr/include -I${INSTALLPATH}/include -I${INSTALLPATH}/include/tirpc"
export USING_SYSTEM_ASN1_COMPILE=1
export ASN1_COMPILE=$(pwd)/hostbin/asn1_compile_host
export USING_SYSTEM_COMPILE_ET=1
export COMPILE_ET=$(pwd)/hostbin/compile_et_host
./buildtools/bin/waf configure --prefix=/system/sdcard \
--without-gettext --disable-tdb-mutex-locking --disable-gnutls --disable-python \
--without-gpgme --without-winbind --without-ads --without-ldap --disable-cups \
--disable-iprint --without-pam --without-quotas --disable-avahi --without-iconv --without-acl-support \
--without-dnsupdate --without-syslog --without-automount --without-dmapi --without-fam --without-libarchive \
--without-regedit --without-fake-kaserver --disable-glusterfs --disable-cephfs --disable-fault-handling \
--without-systemd --without-lttng --accel-aes=none --disable-pthreadpool --without-ad-dc --nopyc --nopyo \
--without-ntvfs-fileserver --disable-rpath --disable-rpath-install --disable-rpath-private-install \
--bundled-libraries=!asn1_compile,!compile_et --nonshared-binary=client/smbclient \
--without-utmp \
--cross-compile --cross-execute 'qemu-mipsel-static -L /home/username/mips-gcc472-glibc216-64bit/mips-linux-gnu/libc/uclibc'
./buildtools/bin/waf --targets=client/smbclient && ${STRIP} -s bin/smbclient
Note that the library path for qemu-mispel-static
must be absolute.
Copy the compiled binary (~15M) to Dafang’s /system/sdcard/bin
, create a simple config file at /system/sdcard/etc/smb.conf
with content:
[global]
max protocol = SMB3
and smbclient --version
should show Version 4.7.12
. To connect to SMB3 share, use
/system/sdcard/bin/smbclient -m SMB3 "//path/to/your/share" -U username -D "dir"
To verify the connection is using SMB3, use smbstatus
from server, it should say something like
...
pid dafang users dafang.ip.addr (ipv4:dafang.ip.addr:port) SMB3_11 - partial(AES-128-CMAC)
...
You can use SMB2 instead if you wish.