From 2f8fc8b9a1b6617ed03072d8a0f0028d823d6d49 Mon Sep 17 00:00:00 2001
From: Ludovic Pouzenc <ludovic@pouzenc.fr>
Date: Mon, 26 Sep 2016 22:31:16 +0200
Subject: Add uftp-multicast + sinkdo/sinkcat + bug hunting.

Problem leaved : uftpd listens on IPv4 only. Net conf only done in IPv6.
---
 make-boot-image.sh | 229 +++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 188 insertions(+), 41 deletions(-)

diff --git a/make-boot-image.sh b/make-boot-image.sh
index c6728cf..25301c2 100755
--- a/make-boot-image.sh
+++ b/make-boot-image.sh
@@ -1,18 +1,21 @@
 #!/bin/bash -xe
+PS4='+ ($LINENO) '
+
 # Config #
 ##########
 WORKDIR=./work
 DLDIR=./downloads
 OUTDIR=./out
-OUTUSB=/dev/sdb1
+#OUTUSB=/dev/sdb1
 KERNEL_TOOLS=y
 RUN_QEMU=y
 ROOTCMD=sudo
-WGET="wget --no-check-certificate"
+WGET="wget" #"wget --no-check-certificate"
 KERNEL_TARBALL_URL=https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.6.tar.xz
 KCONFIGLIB_MAIN_URL=https://raw.githubusercontent.com/ulfalizer/Kconfiglib/7eace27993ad3aa1d6911866d9c60a11f32d36d9/kconfiglib.py
 KCONFIGLIB_PATCH_URL=https://raw.githubusercontent.com/ulfalizer/Kconfiglib/7eace27993ad3aa1d6911866d9c60a11f32d36d9/makefile.patch
 NIC_FIRMWARE_URL=http://fr.archive.ubuntu.com/ubuntu/pool/main/l/linux-firmware/nic-firmware_1.157_all.udeb
+UFTP_TARBALL_URL=http://downloads.sourceforge.net/project/uftp-multicast/source-tar/uftp-4.9.2.tar.gz
 BUSYBOX_BIN_URL=https://busybox.net/downloads/binaries/busybox-x86_64
 PCI_IDS_URL=https://pci-ids.ucw.cz/v2.2/pci.ids
 USB_IDS_URL=https://usb-ids.gowdy.us/usb.ids
@@ -69,7 +72,7 @@ fi
 if [ ! -e "$WORKDIR/apt-done" ]
 then	$ROOTCMD apt-get update
 	# Dependencies of this script (assuming default debian install or live)
-	$ROOTCMD apt-get install wget libncurses5-dev
+	$ROOTCMD apt-get install wget libncurses5-dev coreutils
 	# Dependencies for kernel building
 	$ROOTCMD apt-get build-dep linux-source
 	# Dependancies for kernel tools
@@ -183,13 +186,30 @@ chmod +x "$WORKDIR/kernel/scripts/Kconfiglib/customize.py"
 	fi
 )
 
-if [ "x$KERNEL_TOOLS" == "xy" ]
+p="$WORKDIR/kernel/tools/perf/perf"
+if [ "x$KERNEL_TOOLS" == "xy" -a ! -f "$p" ]
 then	(
 		cd "$WORKDIR/kernel"
 		make tools/perf
 	)
 fi
 
+# Build additionnal tools from source #
+#######################################
+uftp_tarball=$DLDIR/$(basename "$UFTP_TARBALL_URL")
+[ -f "$uftp_tarball" ] || $WGET -O "$uftp_tarball" "$UFTP_TARBALL_URL"
+if [ ! -d "$WORKDIR/uftp" ]
+then	mkdir "$WORKDIR/uftp"
+	tar xf "$uftp_tarball" --strip-components=1 -C "$WORKDIR/uftp"
+fi
+
+if [ ! -f "$WORKDIR/uftp/uftpd" ]
+then	(
+		cd "$WORKDIR/uftp/"
+		make NO_ENCRYPTION=1
+	)
+fi
+
 # Initial Ram Disk building (embed in kernel) #
 ###############################################
 if [ ! -d "$WORKDIR/initrd" ]
@@ -207,28 +227,24 @@ then	[ -f "$DLDIR/busybox" ] || $WGET -O "$DLDIR/busybox" "$BUSYBOX_BIN_URL"
 fi
 
 if [ ! -f "$WORKDIR/initrd/etc/keys.bmap" ]
-then	$ROOTCMD dumpkeys | $ROOTCMD loadkeys -b > "$WORKDIR/initrd/etc/keys.bmap"
+then	# When using sudo with password auth, ask and cache pass first
+	$ROOTCMD true
+       	# The following compound command will suck at asking pass
+	$ROOTCMD dumpkeys | $ROOTCMD loadkeys -b > "$WORKDIR/initrd/etc/keys.bmap"
 fi
 
-(
-	set +x
-	PATH="$WORKDIR/kernel/tools/perf:/usr/sbin:/usr/bin:/sbin:/bin"
-	# Diagnostic tools
-	mkchroot "$WORKDIR/initrd" dmidecode iftop iostat lshw lspci lsusb mpstat tcpdump
-	# Manpage display
-	mkchroot "$WORKDIR/initrd" strace groff nroff troff grotty gtbl
-	# Cloning tools
-	mkchroot "$WORKDIR/initrd" /usr/sbin/partclone* efibootmgr gdisk udp-receiver
-	# Some dyn-loaded libraries (ldd will not display them)
-	mkchroot "$WORKDIR/initrd" /lib/x86_64-linux-gnu/libusb-1.0.so.0
-)
-
-if [ "x$KERNEL_TOOLS" == "xy" ]
+if [ ! -f "$WORKDIR/initrd/partclone-restore" ]
 then	(
-		p="$WORKDIR/kernel/tools/perf/perf"
-		cp -a "$p" "$WORKDIR/initrd/sbin/"
 		set +x
-		mkchroot "$WORKDIR/initrd" $(ldd "$p" | egrep -o '/.* ')
+		PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+		# Diagnostic tools
+		mkchroot "$WORKDIR/initrd" dmidecode iftop iostat lshw lspci lsusb mpstat tcpdump
+		# Manpage display
+		mkchroot "$WORKDIR/initrd" strace groff nroff troff grotty gtbl
+		# Cloning tools
+		mkchroot "$WORKDIR/initrd" /usr/sbin/partclone* efibootmgr gdisk udp-receiver
+		# Some dyn-loaded libraries (ldd will not display them)
+		mkchroot "$WORKDIR/initrd" /lib/x86_64-linux-gnu/libusb-1.0.so.0
 	)
 fi
 
@@ -241,6 +257,27 @@ then	mkdir -p "$WORKDIR"/initrd/usr/man/man{1,8} "$WORKDIR"/initrd/usr/share/gro
 	cp /etc/groff/man.local "$WORKDIR/initrd/usr/share/groff/1.22.2/"
 fi
 
+p="$WORKDIR/initrd/bin/uftp"
+if [ ! -f "$p" ]
+then	(
+		cd "$WORKDIR/uftp/"
+		make DESTDIR="../initrd" install
+	)
+	(
+		set +x
+		mkchroot "$WORKDIR/initrd" $(ldd "$p" | egrep -o '/.* ')
+	)
+fi
+
+p="$WORKDIR/kernel/tools/perf/perf"
+if [ "x$KERNEL_TOOLS" == "xy" -a ! -f "$p" ]
+then	(
+		cp -a "$p" "$WORKDIR/initrd/sbin/"
+		set +x
+		mkchroot "$WORKDIR/initrd" $(ldd "$p" | egrep -o '/.* ')
+	)
+fi
+
 if [ ! -d "$WORKDIR/initrd/var/lib" ]
 then	[ -f "$DLDIR/pci.ids" ] || $WGET -O "$DLDIR/pci.ids" "$PCI_IDS_URL"
 	[ -f "$DLDIR/usb.ids" ] || $WGET -O "$DLDIR/usb.ids" "$USB_IDS_URL"
@@ -255,7 +292,7 @@ then	[ -f "$DLDIR/nic-firmware.deb" ] || $WGET -O "$DLDIR/nic-firmware.deb" "$NI
 	find "$WORKDIR/initrd/lib/firmware/" \( -name 'ipw*' -o -name 'brcmfmac*' -o -name '*wifi*' \) -print0 | xargs -r0 rm -v
 fi
 
-cat > "$WORKDIR/initrd/funcs" <<"EOT"
+cat > "$WORKDIR/initrd/funcs" <<"EOF"
 rescue_shell() {
 	echo "Something went wrong. Dropping to a shell."
 	setsid cttyhack sh
@@ -268,8 +305,8 @@ tty_prog() {
 	tty=/dev/tty$1; shift
 	while true
 	do
-		echo "(re)spawning $@ on $tty" >$tty
-		setsid sh -c "exec $@ <$tty >$tty 2>&1"
+		echo "(re)spawning $* on $tty" >$tty
+		setsid sh -c "exec $* <$tty >$tty 2>&1"
 		sleep 2
 	done
 }
@@ -280,6 +317,7 @@ network_up() {
 		echo ip link set dev $iface up
 		ip link set dev $iface up
 	done
+	sleep 8 # PHY link det. + IPv6 DAD & Autoconf
 }
 
 machine_info() {
@@ -294,9 +332,17 @@ machine_info() {
 	ip -o l | sed -ne 's/[0-9]*: \([^:]*\):[^\\]*\\\s*link\/ether\s/network-mac-\1: /p'
 	lsusb 2>/dev/null | grep -vE hub$ | cut -d: -f2- | sed 's/^ ID/usb-device:/'
 }
-EOT
 
-cat > "$WORKDIR/initrd/init" <<"EOT"
+network_show() {
+	ip -o addr show | sed -ne 's/[0-9]*:\s*\(\S*\)\s*inet6*\s\(\S*\)\s.*$/\1: \2/p'
+}
+start_uftpd() {
+	uftpd -q -B 2097152 -x2 -F /run/uftpd.csv -L /run/uftpd.log -T /tmp -D /run/uftpd # -M ff02::1:2:3 -P ff02::4:5:6 Marche pas ???
+	[ $? -eq 0 ] && netstat -nlu | grep -q ':1044 ' && echo -e '\033[42m' ----- UFTPD ready ----- '\033[40m'
+}
+EOF
+
+cat > "$WORKDIR/initrd/init" <<"EOF"
 #!/bin/busybox sh
 echo "Initrd started"
 # Load helper functions
@@ -310,32 +356,133 @@ set -v
 # Mount pseudo-filesystems
 mount -t proc none /proc || rescue_shell
 mount -t sysfs none /sys || rescue_shell
-mount -t devtmpfs none /dev || rescue_shell
+mount -t devtmpfs -o size=1m none /dev || rescue_shell
+
+# Allow using most of the RAM for rootfs
+mount -o remount -o size=80% /
 
 # Load keyboard map
 loadkmap < /etc/keys.bmap || rescue_shell
 
+# Starting sinkdo trojan on tty2 (feed data to uploaded scripts via uftp)
+mkdir /run/uftpd && tty_prog 2 sinkdo /run/uftpd /run/sink &
+
 # Start some debug shells (background)
-for i in 2 3 4 5 6; do tty_prog $i sh & done
+for i in 3 4 5 6; do tty_prog $i sh & done
 
-# Activate networking interfaces
 network_up
-sleep 8 # PHY link detection + IPv6 Duplicate Address Detection & Autoconf
-
-# Dump EFIvars if available
 efibootmgr -v
-
-# Machine basic informations
 machine_info
-
-# You could press Alt+F2 to have a shell. Remote control on telnet port (TCP 23)
+network_show
+start_uftpd
+# Remote control on telnet port (23). You could press Alt+F3 to have a shell.
 nc -ll -p 23 -e /bin/sh -i
+EOF
+chmod +x "$WORKDIR/initrd/init"
 
-# Network IP adresses
-ip -o addr show | sed -ne 's/[0-9]*:\s*\(\S*\)\s*inet6*\s\(\S*\)\s.*$/\1: \2/p'
+cat > "$WORKDIR/initrd/bin/sinkcat" <<"EOF"
+#!/bin/busybox sh
 
+if [ $# -ne 1 ]
+then	cat <<EOT
+Usage: $(basename $0) <sink-dir>
+  Concatenate then delete files as soon they appear in sink-dir to stdout.
+  If multiple files are found in sink, the first in alphabetical order is choosen.
+  <sink-dir> must not exists, this program must create it (avoiding mistakes).
+  Dropping an empty file in dir-sink will clean exit this program.
 EOT
-chmod +x "$WORKDIR/initrd/init"
+	exit 1
+fi
+
+SINKDIR=$1
+mkdir "$SINKDIR" && cd "$SINKDIR"
+if [ $? -ne 0 ]
+then	echo "Cannot mkdir/chdir to '$SINKDIR'" >&2
+	exit 2
+fi
+
+while true
+do
+	f=$(ls | head -n1)
+	if [ -n "$f" ]
+	then	if [ -f "$f" -a -r "$f" ]
+		then	size=$(stat -c'%s' -- "$f")
+			# Do the actual work on the following line
+			cat -- "$f" && rm -v -- "$f" >&2
+			# Normal exit condition
+			if [ $size -eq 0 ]
+			then	cd / && rmdir -v -- "$SINKDIR" >&2
+				exit 0
+			fi
+		else	echo "'$SINKDIR/$f' is not a readable file" >&2
+			exit 3
+		fi
+	fi
+	sleep 1
+done
+EOF
+chmod +x "$WORKDIR/initrd/bin/sinkcat"
+
+cat > "$WORKDIR/initrd/bin/sinkdo" <<"EOF"
+#!/bin/busybox sh
+
+if [ $# -ne 2 ]
+then	cat <<EOT
+Usage: $(basename $0) <land-dir> <sink-dir>
+EOT
+	exit 1
+fi
+
+LANDDIR=$1
+SINKDIR=$2
+cd "$LANDDIR" || exit 2
+
+curtask="(start)"
+while true
+do
+	f=$(ls | head -n1)
+	if [ -z "$f" ]
+	then	sleep 1
+		continue
+	fi
+	if [ ! -f "$f" -o ! -r "$f" ]
+	then	echo "'$LANDDIR/$f' is not a readable file" >&2
+		exit 2
+	fi
+	size=$(stat -c'%s' -- "$f")
+	task=${f:0:2}
+	if [ "$curtask" == "$task" ]
+	then	# Next file of an already started task
+		mv "$f" "$SINKDIR/"
+	else	# Switch to the next task
+		if [ -d "$SINKDIR" ]
+		then	# Inform sinkcat about end-of-data
+			touch -- "$SINKDIR/zz"
+			wait
+			# sinkcat always rmdir "$SINKDIR" on normal exit
+			if [ -d "$SINKDIR" ]
+			then	echo "Task $task has ran into troubles" >&2
+				exit 3
+			fi
+		fi
+		echo "Switching from task $curtask to $task" >&2
+		curtask=$task
+		if [ "$task" == "99" ]
+		then	# Normal exit condition
+			rm -v "$f" >&2
+			# reset # Usefull if ncurses on bg, anoying when destroying useful messages
+			echo "All task completed sucessfully" >&2
+			exit 0
+		else	# Start a new task
+			chmod +x -- "$f" # XXX Checks on $f (is a script ?) 
+			sinkcat $SINKDIR | "./$f" &
+			while [ ! -d "$SINKDIR" ]; do sleep 1; done
+			rm -v "$f" >&2
+		fi
+	fi
+done
+EOF
+chmod +x "$WORKDIR/initrd/bin/sinkdo"
 
 # Kernel build (with embed initramfs) #
 #######################################
@@ -343,7 +490,7 @@ chmod +x "$WORKDIR/initrd/init"
 	cd "$WORKDIR/kernel"
 	# Workaround : some kernel version forget to update embed initramfs in certain cases
 	[ -f usr/initramfs_data.cpio.gz ] && rm usr/initramfs_data.cpio.gz
-	make
+	make -j $(($(nproc)+1))
 )
 
 # Copy / run result EFI file #
-- 
cgit v1.2.3