#!/bin/sh /etc/rc.common

START=90
USE_PROCD=1
EXTRA_COMMANDS="setup block_net conf_net"

boot()
{
    grep -q 'pi_preinit_no_failsafe="y"' /lib/preinit/00_preinit.conf || (
       echo "OpenWrt failsafe is on, the device will leak it's MAC address during early boot"
       echo "See https://github.com/nccgroup/phantap/blob/master/README.md#limitations-or-how-it-can-be-detected-"
    )
    uci get network.phantap &>/dev/null || setup
}

start_service()
{
    procd_open_instance "phantap"
    procd_set_param command /usr/sbin/phantap-learn -i br-phantap -v1
    procd_append_param command -b '/etc/init.d/phantap block_net'
    procd_append_param command -c '/etc/init.d/phantap conf_net'
    procd_set_param stdout 1
    procd_set_param stderr 1
    procd_close_instance
}

block_net() {
    # block local output on br-phantap
    ebtables -t filter -A phantap-drop -j DROP
}

conf_net() {
    # P_VICTIM_MAC P_VICTIM_IP P_NETMASK P_GATEWAY_MAC P_GATEWAY_IP P_DNS P_NTP
    echo "conf_net: P_VICTIM_MAC=$P_VICTIM_MAC P_VICTIM_IP=$P_VICTIM_IP P_GATEWAY_MAC=$P_GATEWAY_MAC P_GATEWAY_IP=$P_GATEWAY_IP P_DNS=$P_DNS"
    . /lib/functions.sh

    _config_firewall

    config_load phantap
    # Run all commands in onnetconfig list
    config_list_foreach main onnetconfig _handle_onconfig

    if [ "$P_DNS" != "0.0.0.0" ]; then
        _config_dns
        # Run all commands in ondnsconfig list
        config_list_foreach main ondnsconfig _handle_onconfig
    fi
}

setup() {

uci set system.ntp.enabled=0
uci set system.ntp.server=''

np=network.phantap
uci batch <<EOF
set $np=interface
set $np.type='bridge'
set $np.proto='static'
set $np.ipaddr='169.254.66.100'
set $np.netmask='255.255.255.254'
set $np.gateway='169.254.66.101'
set $np.dns=''
set $np.ifname=''
set $np.ipv6='0'
EOF
echo "To finish phantap configuration, start by setting up wifi,"
echo "then get the interface names from the device"
echo "uci show network | grep ifname"
echo "If the interfaces are part of an interface already, remove them (assuming we are using a GL-AR150)"
echo "uci delete network.lan.ifname"
echo "uci delete network.wan.ifname"
echo "uci delete network.wan6.ifname"
echo "Add the interfaces to the phantap bridge and restart the network service (assuming we are using a GL-AR150)"
echo "uci set network.phantap.ifname='eth0 eth1'"
echo "uci commit network"
echo "/etc/init.d/network reload"

fp=firewall.phantapz
uci batch <<EOF
set $fp=zone
set $fp.name='phantap'
set $fp.input='DROP'
set $fp.output='ACCEPT'
set $fp.forward='ACCEPT'
set $fp.network='phantap'
EOF

fp=firewall.phantapi
uci batch <<EOF
set $fp=include
set $fp.path='/tmp/phantap.firewall'
set $fp.reload=1
EOF

dp=dhcp.phantap
uci batch <<EOF
set $dp=dhcp
set $dp.interface='phantap'
set $dp.ignore='1'
EOF

uci commit

}

_config_dns() {
    resolvfile=$(uci -q get dhcp.@dnsmasq[0].resolvfile)
    [ -z "$resolvfile" ] && { echo "Resolvfile not set"; exit; }
    echo "nameserver $P_DNS" > "$resolvfile"
    /etc/init.d/dnsmasq reload
}

_config_firewall() {
. /lib/functions/network.sh

P_INTF=phantap
network_get_device P_BRIDGE $P_INTF
[ -z "$P_BRIDGE" ] && { echo "Bridge not ready"; exit; }
P_BR_MAC=$(cat /sys/class/net/$P_BRIDGE/address)
network_get_ipaddr P_BR_IP $P_INTF
network_get_gateway P_GW_FAKEIP $P_INTF true

# Integrate with OpenWRT firewall
cat > /tmp/phantap.firewall.$$ <<EOF
# block local output on br-phantap
ebtables -t filter -A phantap-drop -j DROP

ebtables -t nat -N phantap-snat -P RETURN 2>/dev/null \
&& ebtables -t nat -I POSTROUTING -j phantap-snat
iptables -t nat -N phantap-snat 2>/dev/null
iptables -t nat -C POSTROUTING -o br-phantap -j phantap-snat \
|| iptables -t nat -I POSTROUTING -o br-phantap -j phantap-snat

# Cleanup old rules if exist
ebtables -t nat -F phantap-snat
iptables -t nat -F phantap-snat
$(if [ "$P_GATEWAY_IP" != "0.0.0.0" ]; then
cat <<EOS
# We have detected the gateway ip, impersonate the gateway when talking to the victim
ebtables -t nat -A phantap-snat -s $P_BR_MAC -d $P_VICTIM_MAC --logical-out $P_BRIDGE -j snat --to-source $P_GATEWAY_MAC
iptables -t nat -A phantap-snat -s $P_BR_IP -d $P_VICTIM_IP -j SNAT --to-source $P_GATEWAY_IP
EOS
else
cat <<EOS
# We have not detected the gateway ip, drop all traffic from phantap to the victim
ebtables -t nat -A phantap-snat -s $P_BR_MAC -d $P_VICTIM_MAC --logical-out $P_BRIDGE -j DROP
EOS
fi
)
# Replace our local mac with the victim mac
ebtables -t nat -A phantap-snat -s $P_BR_MAC --logical-out $P_BRIDGE -j snat --to-source $P_VICTIM_MAC
# Replace our local ip with the victim ip
iptables -t nat -A phantap-snat -s $P_BR_IP -j SNAT --to-source $P_VICTIM_IP

# Add mac for the fake gateway
ip neigh replace $P_GW_FAKEIP lladdr $P_GATEWAY_MAC dev $P_BRIDGE

# allow local output on br-phantap again, we now have internet access
ebtables -t filter -F phantap-drop

echo "PhanTap firewall rules reloaded, you now have internet"
EOF
mv /tmp/phantap.firewall.$$ /tmp/phantap.firewall

ebtables -t filter -A phantap-drop -j DROP
/etc/init.d/firewall reload
}

_handle_onconfig() {
    /bin/sh -c "$1" || echo "'$1' failed"
}
