#!/bin/sh
. /etc/functions.sh

start_ppp() {
	config_get username $ifn username
	config_get password $ifn password
	config_get keepalive $ifn keepalive
	config_get mtu $ifn mtu
	config_get demand $ifn demand
	mtu="${mtu:-1480}"
	/usr/sbin/pppd "$@" \
		lcp-echo-interval 5 \
		lcp-echo-failure ${keepalive:-5} \
		${demand:+precompiled-active-filter /etc/ppp/filter idle demand }${demand:-persist} \
		usepeerdns \
		defaultroute \
		replacedefaultroute \
		user "$username" \
		password "$password" \
		linkname "$ifn" \
		mtu $mtu mru $mtu \
		ipparam "$ifn"
}

setup_interface() {
	local ifn="$1"
	local dev="$2"
	dhcp_enabled=
	
	config_get mode $ifn mode
	config_get ipaddr $ifn ipaddr
	touch /tmp/resolv.conf
	case "$mode" in
		static)
			config_get netmask $ifn netmask
			config_get dhcp $ifn dhcp
			netmask=${netmask:-255.255.255.0}
			ifconfig "$dev" $ipaddr netmask $netmask up
			
			config_get gateway $ifn gateway
			[ -n "$gateway" ] && {
				while route del default >&- 2>&- ; do :; done
				route add default gw "$gateway"
			}
			
			config_get dns "$ifn" dns
			[ -n "$dns" ] && {
				echo > /tmp/resolv.conf
				for server in "$dns"; do
					echo "nameserver $dns" >> /tmp/resolv.conf
				done
			}
			case "$dhcp" in
				0|off|disabled);;
				*)dhcp_enabled=1;;
			esac
			env -i ACTION=ifup INTERFACE="$ifn" /sbin/hotplug iface
		;;
		dhcp)
			ifconfig "$dev" up
			udhcpc -i "$dev" ${ipaddr:+ -r $ipaddr} -R &
		;;
		pppoe|pptp)
			ifconfig "$dev" up
			case "$mode" in
				pppoe)
					for module in slhc ppp_generic pppox pppoe; do
						/sbin/insmod $module 2>&- >&-
					done
					start_ppp \
						plugin rp-pppoe.so \
						nic-$dev
				;;
				pptp)
					config_get server $ifn pptp_server
					udhcpc -i "$dev" ${ipaddr:+ -r $ipaddr} -n -q
					for module in slhc ppp_generic ppp_async ip_gre; do
						/sbin/insmod $module 2>&- >&-
					done
					start_ppp \
						pty "/usr/sbin/pptp $server --loglevel 0 --nolaunchpppd" \
						file /etc/ppp/options.pptp \
						$PPPOPTS
				;;
			esac
		;;
	esac
	[ -n "$dhcp_enabled" ] && {
		# calculate the dhcp pool settings
		config_get start $ifn dhcp_start
		config_get num $ifn dhcp_num
		config_get time $ifn dhcp_leasetime
		eval $(ipcalc $ipaddr $netmask ${start:-100} ${num:-150})
		
		dhcpopts="${dhcpopts:+$dhcpopts } --dhcp-range=$START,$END,$NETMASK,${time:-12h}"
	}
}

setup_wifi_common() {
	local vif="$1"

	config_get bgmode advanced bgmode
	config_get channel advanced channel
	
	case "$bgmode" in
		b|B) bgmode=11b; pureg=0;;
		g|G) bgmode=11g; pureg=1;;
		*) bgmode=0; pureg=0;; # auto
	esac
	
	iwconfig $vif channel 0
	ifconfig $vif up
	iwpriv $vif mode $bgmode
	iwpriv $vif pureg $pureg
	[ -n "$channel" -a -z "${channel%%[0-9][0-9]}" ] && {
		iwconfig $vif channel "$channel"
	} || {
		# auto
		iwconfig $vif channel 0
	}
}

setup_hotspot_wifi() {
	wlanconfig ath0 create wlandev wifi0 wlanmode ap >&- 2>&-
	setup_wifi_common ath0

	config_get ssid public essid
	iwconfig ath0 essid "FON_${ssid:-AP}"
	ifconfig eth0 up
	ifconfig ath0 up
}

setup_lan_wifi() {
	config_get ssid private essid
	[ -n "$ssid" ] && {
		config_get enc private encryption
		config_get crypto private wpa_crypto
		config_get passwd private password
		config_get auth private shared_auth
		sh_auth=1
		case "$enc" in
			open)
				[ "$auth" = 1 ] && sh_auth=2
			;;
			wep)
				[ "$auth" = 1 ] && sh_auth=2
				config_get wep private wepkey
			;;
			WPA|WPA1|wpa|wpa1) wpa=1; crypt=TKIP;;
			WPA2|wpa2) wpa=2; crypt="CCMP TKIP";;
			mixed|Mixed) wpa=3; crypt="CCMP TKIP";;
		esac
		case "$crypto" in
			aes|AES|ccmp|CCMP) crypt=CCMP;;
			tkip|TKIP) crypt=TKIP;;
			tkip+aes|TKIP+AES|aes+tkip|AES+TKIP) crypt="TKIP CCMP";;
		esac
		wlanconfig ath1 create wlandev wifi0 wlanmode ap >&- 2>&-
		setup_wifi_common ath1
		iwconfig ath1 essid "$ssid"
		iwpriv ath0 authmode $sh_auth

		[ -z "$wep" ] || {
			for k in 1 2 3 4; do
				config_get key private key$k
				[ -z "$key" ] || iwconfig ath1 enc "[$k]" "$key"
			done
			iwconfig ath1 enc "[$wep]"
		}
		[ -z "$crypt" -o -z "$wpa" ] || (
			killall hostapd 2>/dev/null >/dev/null && sleep 1
			cat > /tmp/hostapd.conf <<EOF
interface=ath1
driver=madwifi
debug=0
eapol_key_index_workaround=1
wpa=$wpa
wpa_pairwise=$crypt
wpa_passphrase=$passwd
wpa_group_rekey=3600
EOF
			hostapd -B /tmp/hostapd.conf || {
				# hostapd setup failed. destroy the interface rather than leaving it open
				wlanconfig ath1 destroy
			}
		) > /dev/null 2>/dev/null </dev/null &
	}
}

# Set up a default mangement IP in case something goes wrong
setup_management() {
	local ifn="$1"
	
	ifconfig "$ifn:1" 127.1.6.8 up # use an invalid address as source for arping
	
	local ip=169.254.255.1
	while :; do
		if arping -c 1 -I "$ifn" -s 127.1.6.8 "$ip" >/dev/null 2>/dev/null; then
			# already taken
			ip="169.254.255.$((${ip##*\.} + 1))"
		else
			break;
		fi
		
		# this should never happen:
		[ "${ip##*\.}" = "254" ] && {
			ifconfig "$ifn:1" 0.0.0.0 down
			return 1
		}
	done
	ifconfig "$ifn:1" "$ip" netmask 255.255.0.0
}	

config_load fon

config_get proto wan mode
case "$proto" in
	pppoe|pptp) wan_ifname=ppp0;;
esac

cat > /tmp/network-config <<EOF
wan_ifname=${wan_ifname:-eth0}
lan_ifname=ath1
wifi_ifname=ath0
config_ifname=eth0
EOF


case "$1" in
	mgmt)
		setup_management eth0
	;;
	lan|lan_noinet)
		ifdown lan
		setup_lan_wifi
		ifconfig ath1 >/dev/null 2>/dev/null && {
			setup_interface lan ath1
		}
		[ "$1" = lan_noinet ] && dhcpopts="${dhcpopts:+$dhcpopts }--address=/#/213.134.45.154 -T 1"
		dnsmasq -C /etc/dnsmasq.conf $dhcpopts &
	;;
	wan)
		ifdown wan
		setup_interface wan eth0
		config_get mode wan mode
		rm -f /etc/resolv.conf
		case "$mode" in
			static) ln -s /tmp/resolv.conf /etc/resolv.conf;;
			*) ln -s /etc/resolv.conf.fon /etc/resolv.conf;;
		esac
	;;
	hotspot)
		ifdown hotspot
		setup_hotspot_wifi
	;;
esac

