#!/bin/sh

# If you add files to root.tgz, please supply the "gen-openwrt -v XXX"
# to mark your additions/changes with a version identifier.
#
# g = Firmware for Wrt54g 1.0, 1.1, 2.0, 2.2, 3.0, 3.1, 4.0 and Wrt54gl
# gs = Firmware for Wrt54gs 1.0 und 1.1 (for gs 3.0 use gs40, unverified)
# gs40 = Firmware for Wrt54gs 4.0 only
# g3g = Firmware for Wrt54g3g (device with UMTS)
# a = Firmware for Allnet All0277
# moto = Firmware for Motorola WR850G
# se505 = Firmware for Siemens SE-505
# trx = Firmware for wap54g/wl500 or update via Freifunk Web-UI

# Default settings can be set in the *.conf files

# There should be no need to edit this file (gen-openwrt) for normal usage

. ${0%/*}/functions.sh

readconf ${0%/*}/defaults.network.conf
readconf ${0%/*}/defaults.node.conf

usage() {
	cat >&2 <<EOF
Usage: $0 [Options]... (g|gs|gs40|g3g|a|moto|se505|trx) [ip] > outfile.ext

Options:
  -m  netmask		Specify netmask (default: $(echo `varget wifi_netmask`))
  -s  ssid		Specify ESSID (default: $(echo `varget wl0_ssid`))
  -b  bssid		Specify BSSID (default: `def=$(varget ff_bssid); echo ${def:-random join}`)
  -c  channel		Specify channel (default: $(echo `varget wl0_channel`))
  -f  frag		Specify fragmentation (default: `def=$(varget wl0_frag); echo ${def:-off}`)
  -r  rts		Specify RTS (default: `def=$(varget wl0_rts); echo ${def:-off}`)
  -a  antdiv		Specify antenna (`def=$(varget wl0_antdiv); echo ${def:-diversity}`)
  -n  name		Specify node name (chars a-z,0-9, dash "-" and dot "." only)
  -d  dhcp net addr	Specify wifi dhcp range network address
  -g  dhcp range prefix Specify wifi dhcp range size as a CIDR subnet prefix (without slash)
  -j  dhcp client mask	Specify netmask assigned to wifi dhcp clients (as dotted quad)
  -p  password		Specify default password (in cleartext, alphanumeric chars only)
  -q  confirm password	Specify default password again for confirmation
  -N  nvram set		Specify nvram variable to set (name=value)
  -v  version		Specify version identifier
  -W			Generate WEP/WPA capable firmware (needs > 2Mb Flash)
  -F			Generate Failsafe Edition
  -M			Generate Micro Edition

Example: $0 trx > code.trx (generates generic trx for mtd write to flash)
	 $0 g 10.0.0.1 > code.bin (generates bin file for wrt54g ver1-4)

Non-alphanumeric characters are not allowed in parameter values, except for
dots ".", dashes "-", and underscores "_".

Spaces are not allowed as command-line parameters but are allowed inside the
defaults.*.conf config files, or via the ff.cgi web interface.

Note:	Older devices with PMON (wrt54g-v1) need "code.bin" for TFTP

This script generates freifunk binaries. It will need some space to extract
the files from root.tgz in the /tmp dir. The script will output a new bin or
trx file on stdout. If you supply an IP address, the IP address is configured
on the first start or when doing "reset to defaults". A firmware with an IP
default will be marked in the version string on the main router web page
and is not downloadable through that web page.

The defaults for these and more options can be set by editing
defaults.network.conf and defaults.node.conf

EOF
	exit 1
}

while getopts "m:s:b:c:f:r:a:n:d:g:j:p:q:N:v:WMF" flag; do
	case $flag in
	m)
		varset wifi_netmask=$(filter "$OPTARG")
	;;
	s)
		varset wl0_ssid=$(filter "$OPTARG")
	;;
	b)
		varset ff_bssid=$(filter "$OPTARG")
	;;
	c)
		varset wl0_channel=$(filter "$OPTARG")
	;;
	f)
		varset wl0_frag=$(filter "$OPTARG")
	;;
	r)
		varset wl0_rts=$(filter "$OPTARG")
	;;
	a)
		varset wl0_antdiv=$(filter "$OPTARG")
	;;
	n)
		varset wan_hostname=$(namefilter "$OPTARG")
	;;
	d)
		varset dhcp_net=$(filter "$OPTARG")
	;;
	g)
		varset dhcp_pre=$(filter "$OPTARG")
	;;
	j)
		varset dhcp_mask=$(filter "$OPTARG")
	;;
	p)
		varset password=$(filter "$OPTARG")
	;;
	q)
		varset confpassword="$OPTARG"
	;;
	N)
		varset $(unescape $(nvfilter "$OPTARG"))
	;;
	v)
		vers=$(filter "$OPTARG")
	;;
	W)
		wep=yes
	;;
	M)
		micro=yes
	;;
	F)
		failsafe=yes
	;;
	*)
		usage
	;;
	esac
done
shift $(($OPTIND - 1))

if [ ! -z $2 ]; then
    varset wifi_ipaddr=$(filter "$2")
fi

if [ "yes" = "$wep" ]; then
	# WEP/WPA version to generate
	vers="$vers+WEP"
fi

TMPDIR=/tmp
MYPATH=${0%/*}
MKSQASHFS=$MYPATH/mksquashfs-lzma
KERNEL="$MYPATH/loader.gz $MYPATH/vmlinux.lzma"

LEGACY_VARS='wifi_ipaddr
wifi_netmask
wl0_ssid
ff_bssid
wl0_channel
wl0_frag
wl0_rts
wl0_antdiv
wan_hostname'

case $1 in
	g|gs|gs40|g3g|a|moto|se505|trx)
		test -f $MYPATH/root.tgz || ! echo "No root sys $MYPATH/root.tgz">&2 || exit 1
		test -f $MYPATH/vmlinux.lzma || ! echo "No kernel image $MYPATH/vmlinux.lzma">&2 || exit 1

		# custom password validty check
		password="$(varget password)"; confpassword="$(varget confpassword)"
		if [ -n "$password" ] || [ -n "$confpassword" ] && [ "$password" != "$confpassword" ]; then
			! echo "Password and Confirm Password do not match or are non-alphanumeric characters!">&2
			! echo "Once the firmware has been loaded, the password can be changed to a stronger one">&2
			exit 1
		fi

		mkdir $TMPDIR/openwrt-root.$$
		tar -C $TMPDIR/openwrt-root.$$ -xzf $MYPATH/root.tgz
		if [ "yes" = "$micro" ]; then
			rm $(find $TMPDIR/openwrt-root.$$ -name "*olsr*") >&2
			rm $(find $TMPDIR/openwrt-root.$$ -name "*dropbear*") >&2
			rm $TMPDIR/openwrt-root.$$/usr/bin/dbclient $TMPDIR/openwrt-root.$$/usr/bin/scp $TMPDIR/openwrt-root.$$/usr/bin/ssh >&2
			rm $TMPDIR/openwrt-root.$$/etc/local.fw $TMPDIR/openwrt-root.$$/etc/init.d/S45firewall >&2
			rm -r $TMPDIR/openwrt-root.$$/usr/lib/iptables $TMPDIR/openwrt-root.$$/usr/sbin/iptables >&2
			rm $TMPDIR/openwrt-root.$$/usr/bin/wl $TMPDIR/openwrt-root.$$/usr/lib/ipkg/info/wl.list >&2
			rm $TMPDIR/openwrt-root.$$/www/*>/dev/null 2>&1
			rm $TMPDIR/openwrt-root.$$/www/cgi-bin/* $TMPDIR/openwrt-root.$$/www/images/* >&2
			rm $TMPDIR/openwrt-root.$$/etc/init.d/S51crond >&2
			# Pthread is optional (e.g. if OLSR-BMF is included)
			rm -f $TMPDIR/openwrt-root.$$/lib/libpthread* >&2
			rm $TMPDIR/openwrt-root.$$/usr/lib/ipkg/info/*.list >&2
			rm $TMPDIR/openwrt-root.$$/usr/bin/netparam $TMPDIR/openwrt-root.$$/usr/bin/edit >&2
			rm $TMPDIR/openwrt-root.$$/usr/sbin/cron.* $TMPDIR/openwrt-root.$$/usr/sbin/wl $TMPDIR/openwrt-root.$$/usr/sbin/tc >&2
			${0%/*}/removeipkg.pl $TMPDIR/openwrt-root.$$/usr/lib/ipkg/status freifunk-webadmin\
			    dropbear freifunk-mtdkill wl freifunk-olsrd freifunk-upload libptread
		fi
		if [ "yes" = "$failsafe" ]; then
			test -f $TMPDIR/openwrt-root.$$/etc/preinit || ! echo "No preinit">&2 || exit 1
			cp $TMPDIR/openwrt-root.$$/etc/preinit $TMPDIR/openwrt-in.$$
			sed -e "s/^ff_reset=\\\$.*\$/ff_reset=failsafe/" \
			    -e "s/^if \[ \"\$checksum\" != \"\$ff_reset\" \] || /if false \&\&/" \
			    $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/etc/preinit
			rm $TMPDIR/openwrt-in.$$
		fi
		if [ -f $TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram ] && [ -n "$(varget wifi_ipaddr)" ]; then
			# Caller has issued default IP address
			wifi_ipaddr="$(varget wifi_ipaddr)"
			if [ -n "$vers" ];then
				vers="$vers/$wifi_ipaddr"
			else
				vers="$wifi_ipaddr"
			fi

			# process non-nvram variables
			## create ff_wldhcp
			dhcp_flag=0
			dhcp_net="$(varget dhcp_net)"
			dhcp_pre="$(varget dhcp_pre)"
			dhcp_mask="$(varget dhcp_mask)"
			ff_wldhcp="$(varget ff_wldhcp)"
			[ -n "$dhcp_net" ] && [ -n "$dhcp_pre" ] && [ -n "$dhcp_mask" ] && dhcp_flag=1
			if [ -z "$ff_wldhcp" ] && [ "$dhcp_flag" = "1" ]; then
			    ff_wldhcp="$dhcp_net"'/'"$dhcp_pre"','"$dhcp_mask"
			    varset ff_wldhcp="$ff_wldhcp"
			fi
			varunset dhcp_net; varunset dhcp_pre; varunset dhcp_mask

			## create ff_adm_gps
			# we do this because ff_adm_gps has a semicolon in it
			# and we don't want to allow semicolons in values as input
			# in a cgi script
			gps_lat="$(varget gps_lat)"
			gps_lon="$(varget gps_lon)"
			if [ -n "$gps_lat" ] && [ -n "$gps_lon" ]; then
			    ff_adm_gps="$gps_lat;$gps_lon"
			    varset ff_adm_gps="$ff_adm_gps"
			fi
			varunset gps_lat; varunset gps_lon

			## edit S53olsrd if nameservice_suffix != .olsr
			nameservice_suffix="$(varget nameservice_suffix)"
			if [ -f $TMPDIR/openwrt-root.$$/etc/init.d/S53olsrd ] && [ "$nameservice_suffix" != ".olsr" ]; then
			    cp $TMPDIR/openwrt-root.$$/etc/init.d/S53olsrd $TMPDIR/openwrt-in.$$
			    sed -e "/\"suffix\"/s/.olsr/$nameservice_suffix/" \
			    $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/etc/init.d/S53olsrd
			    rm $TMPDIR/openwrt-in.$$
			fi
			varunset nameservice_suffix

			## re-create /etc/passwd and set up ff_pw if password is set,
			## and remove download firmware option
			if [ -n "$password" ]; then
			    ff_pw=$(${0%/*}/busybox httpd -m "$password")
			    varset ff_pw="$ff_pw"
			    cp $TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram $TMPDIR/openwrt-in.$$
			    sed -e "/# For nvram erase:/""i\ \techo \'root:$ff_pw:0:0:root:/tmp:/bin/ash\'>/etc/passwd" \
				-e "/# For nvram erase:/""i\ \tcommand nvram set ff_pw=\'$ff_pw\'" \
				$TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram
			    rm $TMPDIR/openwrt-in.$$
			    if [ "yes" != "$micro" ]; then
				# downloading a clone of a firmware image with a customised password is a security risk
				# so this we disable this feature
				cp $TMPDIR/openwrt-root.$$/www/cgi-bin-index.html $TMPDIR/openwrt-in.$$
				sed -e "/Firmware download from this device/d" \
				$TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/www/cgi-bin-index.html
				rm $TMPDIR/openwrt-in.$$
			    fi
			    varunset ff_pw; varunset password; varunset confpassword
			fi

			# we still handle the legacy variables the "old" way
			cp $TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram $TMPDIR/openwrt-in.$$
			sed -e "s/^\(DEF_ADR\)[^#$]\+/\1=\"$(varget wifi_ipaddr)\"/" \
			    -e "s/^\(DEF_MSK\)[^#$]\+/\1=\"$(varget wifi_netmask)\"/" \
			    -e "s/^\(DEF_SSID\)[^#$]\+/\1=\"$(varget wl0_ssid)\"/" \
			    -e "s/^\(DEF_BSSID\)[^#$]\+/\1=\"$(varget ff_bssid)\"/" \
			    -e "s/^\(DEF_CHAN\)[^#$]\+/\1=\"$(varget wl0_channel)\"/" \
			    -e "s/^\(DEF_FRAG\)[^#$]\+/\1=\"$(varget wl0_frag)\"/" \
			    -e "s/^\(DEF_RTS\)[^#$]\+/\1=\"$(varget wl0_rts)\"/" \
			    -e "s/^\(DEF_ANTDIV\)[^#$]\+/\1=\"$(varget wl0_antdiv)\"/" \
			    -e "s/^\(DEF_HOSTNAME\)[^#$]\+/\1=\"$(varget wan_hostname)\"/" \
			    $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram
			rm $TMPDIR/openwrt-in.$$
			for deletethis in $LEGACY_VARS; do
			    varunset $deletethis
			done

			# add all remaining variables as "nvram set" statements in S14ffnvram
			# we're not bothering to add "DEF_*" declarations because S14ffnvram is read-only
			# and we don't want to add extra bytes unnecessarily
			(( count=${#varvalue[@]} - 1 ))
			for ((indx=0; indx <= count ; indx++)) ;do
				cp $TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram $TMPDIR/openwrt-in.$$
				sed -e "/# For nvram erase:/""i\ \tcommand nvram set ${varname[$indx]}=\"${varvalue[$indx]}\"" \
				    $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/etc/init.d/S14ffnvram
				rm $TMPDIR/openwrt-in.$$
			done

			if [ "yes" != "$micro" ]; then
			    test -f $TMPDIR/openwrt-root.$$/www/cgi-bin-index.html || ! echo "No cgi-bin-index.html">&2 || exit 1
			    cp $TMPDIR/openwrt-root.$$/www/cgi-bin-index.html $TMPDIR/openwrt-in.$$
			    sed -e "s/STYLE=\"firmwarelinks:0\;display:list-item\;\"/STYLE=\"firmwarelinks:0\;display:none\;\"/" \
				-e "s^<!--%KIT_IPADDR%-->^($vers)^" $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/www/cgi-bin-index.html
			    rm $TMPDIR/openwrt-in.$$
			fi
		elif [ "yes" != "$micro" ]; then
			test -f $TMPDIR/openwrt-root.$$/www/cgi-bin-index.html || ! echo "No cgi-bin-index.html">&2 || exit 1
			cp $TMPDIR/openwrt-root.$$/www/cgi-bin-index.html $TMPDIR/openwrt-in.$$
			if [ -n "$vers" ]; then
				sed -e "s^<!--%KIT_IPADDR%-->^($vers)^" $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/www/cgi-bin-index.html
			else
				sed -e "s/<!--%KIT_IPADDR%-->//" $TMPDIR/openwrt-in.$$>$TMPDIR/openwrt-root.$$/www/cgi-bin-index.html
			fi
			rm $TMPDIR/openwrt-in.$$
		fi

		mkdir -p $TMPDIR/openwrt-root.$$/lib/modules/
		cp -a $MYPATH/2.4.30 $TMPDIR/openwrt-root.$$/lib/modules/
		if [ "yes" = "$wep" ]; then
			cp -f $MYPATH/wep/wl.o $TMPDIR/openwrt-root.$$/lib/modules/2.4.30/
			cp -f $MYPATH/wep/wifi $TMPDIR/openwrt-root.$$/sbin
			cp -f $MYPATH/wep/libiw*.so* $TMPDIR/openwrt-root.$$/usr/lib
		fi

		# The -nopad parameter is required if fix-crc-error.patch is applied to buildroot
		# That patch is an old one published by mtakahar in the openwrt forum in feb 2005
		# Because I have sporadic "attempt to access beyond end of device" errors with
		# trx/bin files if they reach a 0x10000 boundary I disabled the -nopad here.
		$MKSQASHFS $TMPDIR/openwrt-root.$$ $TMPDIR/openwrt-fs.$$ -noappend -root-owned -le>/dev/null

		rm -rf $TMPDIR/openwrt-root.$$
		case "$1" in
		g)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$|$MYPATH/addpattern -4 -g|sed -e "1s,^W54S,W54G,"
		;;
		gs)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$|$MYPATH/addpattern -4 -g
		;;
		gs40)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$|$MYPATH/addpattern -4 -g|sed -e "1s,^W54S,W54s,"
		;;
		g3g)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$|$MYPATH/addpattern -4 -g|sed -e "1s,^W54S,W54F,"
		;;
		a)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$|$MYPATH/addpattern -4 -g|sed -e "1s,^W54S,W54A,"
		;;
		se505|moto)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$>$TMPDIR/openwrt-fs.$$.trx
			$MYPATH/freifunk-upload -$1 $TMPDIR/openwrt-fs.$$.trx
			rm -f $TMPDIR/openwrt-fs.$$.trx
		;;
		trx)
			$MYPATH/trx $KERNEL $TMPDIR/openwrt-fs.$$
		;;
		esac
		rm -f $TMPDIR/openwrt-fs.$$
	;;
	*)
		usage
	;;
esac
