#!/bin/sh
# get prefix from peer router and set to LAN

# $0 (/etc_ro/ppp/ipv6-up)
# $1 ifname  (ppp0)
# $2 devname (eth2.2)
# $4 local  LL addr
# $5 remote LL addr

LAN=br0
WAN=$1
DHCP6C="/sbin/dhcp6.sh client"
SEND_RS="/bin/pktgen -s $WAN"
RADVD=/bin/radvd
CONF=/etc/radvd.conf

get_lan_prefix()
{
  EXCLUDE_PAT="fe80::|/128"
  LAN_STATIC_IP=`nvram_get v6_lan_ip`
  [ $LAN_STATIC_IP ] && EXCLUDE_PAT="${EXCLUDE_PAT}|${LAN_STATIC_IP}/64"
  
  ifconfig $LAN | grep "inet6 addr" | grep -vE $EXCLUDE_PAT | sed -e "s/^.*inet6 addr: //" -e "s/ Scope.*\$//"
}

config_radvd()
{
  LIFETIME=`nvram_get v6_radvd_lifetime`

  echo "interface $LAN" > $CONF
  echo "{" >> $CONF
  echo "  AdvSendAdvert on;" >> $CONF
  echo "  MinRtrAdvInterval 3;" >> $CONF
  echo "  MaxRtrAdvInterval 10;" >> $CONF
  if [ $LIFETIME ]; then
    echo "  AdvDefaultLifetime $LIFETIME;" >> $CONF
  fi

  echo "  prefix $PREFIX" >> $CONF
  echo "  {" >> $CONF
  echo "    AdvOnLink on;" >> $CONF
  echo "    AdvAutonomous on;" >> $CONF
  echo "    AdvRouterAddr on;" >> $CONF
  echo "    AdvValidLifetime 2592000;" >> $CONF
  echo "    AdvPreferredLifetime 604800;" >> $CONF
  echo "  };" >> $CONF

  echo "};" >> $CONF
  echo "" >> $CONF
  chmod 600 $CONF
}

waiting_for_lan_prefix()
{
  TIMEOUT=15    # second
  while [ $TIMEOUT -ge 0 ]; do
    sleep 1
    PREFIX=`get_lan_prefix`
    [ $PREFIX ] && break
    TIMEOUT=`expr $TIMEOUT - 1`
  done
}

init_counter()
{
  PPPD_RETRY=2
  echo $PPPD_RETRY > $COUNTER
}

dec_counter()
{
  expr $PPPD_RETRY - 1 > $COUNTER
}

exit_()
{
  rm $COUNTER
  exit $1
}

# program entry

route -A inet6 add 2000::/3 gw $5 $WAN          # add remote LL address as default gateway

# ipv6-up               +-(got prefix)-->-------->-------->---+-(got RA)-----> end (success)
#   |                   |                                     |
#   +-> A)start dhcp6c -+-(15s)-> B)stop dhcp6c -> C)send RS -+-(15s)--+---+-> end (failed)
#   |                                                                  |   |
#   +----<--------<--------<--------<--------<--------<--(loop*3)------+   +-> D)restart pppd (up to 2 times)

COUNTER=/var/pppd_retry
RADVD_EN=`nvram_get v6_radvd_en`
PPPD_RETRY=`cat $COUNTER 2>/dev/null` || init_counter
LOOP=1

while [ $LOOP -ge 0 ]; do
  WAN=$WAN $DHCP6C start iapd && waiting_for_lan_prefix     # A)
  [ $PREFIX ] && exit_ 0          # end (success)
  $DHCP6C stop                                              # B)

  # disable/enable forwarding to accept/reject RA
  echo 0 > /proc/sys/net/ipv6/conf/$WAN/forwarding
  $SEND_RS && waiting_for_lan_prefix                        # C)
  echo 1 > /proc/sys/net/ipv6/conf/$WAN/forwarding
  if [ $PREFIX ]; then
    if [ "$RADVD_EN" -eq "1" ]; then
      killall radvd 2>/dev/null
      config_radvd
      $RADVD -C $CONF
    fi
    exit_ 0                         # end (success)
  fi

  LOOP=`expr $LOOP - 1`
done

[ "$PPPD_RETRY" -eq 0 ] && exit_ 1  # end (failed)

dec_counter
killall pppd 2>/dev/null                                    # D)
pppd file /etc/options.pppoe &
