#!/bin/sh
#*******************************************************************
#* Copyright Avaya Inc.
#*******************************************************************

# Avaya DHCP procedures and option handling

ROOT="/var/run/dhcp"
mkdir -p $ROOT
if [[ $ipv6 == 1 ]]; then
    avaya_opt_file="${ROOT}/avaya_opts6.${interface}"
    avaya_reason_file="${ROOT}/avaya_reason6.${interface}"
else
    avaya_opt_file="${ROOT}/avaya_opts.${interface}"
    avaya_reason_file="${ROOT}/avaya_reason.${interface}"
fi

# Debugging ...
echo $reason > /tmp/dhcpcd-reason
if [[ $ipv6 == 1 ]];then
    set | sort > /tmp/dhcpcd-rawdata6.${interface}
else
    set | sort > /tmp/dhcpcd-rawdata.${interface}
fi

# TODO move this to application
validate_ipv6_addr()
{
    x16=0x`echo $1 | cut -f1 -d:` # 1st 16 bits

    # MSB4 bits 0?
    x4=`printf '%x' "$((x16 & 0xF000))"` # 1st bit 4, in hex
    if [[ "$x4" == "0" ]];then
       echo "Invalid ipv6 address: $1 \"MSB4 0\" ";
       rc=1;
       return
    fi

    if ( echo "$1" | egrep -i "^:.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"Unspecified or Loopback\" ";
       rc=1;
       return
    fi
    
    if ( echo "$1" | egrep -i "^FF.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"Multicast\"";
       rc=1;
       return
    fi

    # Get 1st 10 bits
    x10=`printf '%X' "$((x16 & 0xffc0))"` # 1st 10 bits, converted to hex

    # FE80/10 or '1111 1100 1000 0000'
    if ( echo "$x10" | egrep -i "^FE80.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"Link-local/Link-local Unicast\"";
       rc=1;
       return
    fi

    # FEC0/10 or '1111 1110 1100 0000'
    if ( echo "$x10" | egrep -i "^FEC0*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"Site-local\"";
       rc=1;
       return
    fi

    if ( echo "$1" | egrep -i "^::FFFF.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"IPv4 mapped\""
       rc=1;
       return
    fi

    if ( echo "$1" | egrep -i "^::[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"IPv4-compatible (obselete)\"";
       #example, ::ffff:192.0.2.128
       rc = 1;
       return
    fi

    if ( echo "$1" | egrep -i "^.*:FFFE.*" ); then
       echo "Invalid ipv6 address: $1 \"Anycast\"";
       rc=1;
       return
    fi

    if ( echo "$1" | egrep -i "^2002.*" >/dev/null 2>&1 );then
       echo "Invalid ipv6 address: $1 \"6to4 Mapped\""
       rc=1;
       return
    fi

    rc=0;
    return

}

make_opt_file()
{
    set | sed -ne 's/^new_//p' | sort > ${avaya_opt_file}
    if [[ $ipv6 == 1 ]]; then
        set | sed -ne 's/^nd_//p' | sort >> ${avaya_opt_file}
    fi
}

remove_opt_file()
{
    rm -f "${avaya_opt_file}"
}

make_reason_file()
{
  # create reason file if it doesnt exist, or if there is an actual change
  if [[ ! -e ${avaya_reason_file} ]] || !( grep $reason ${avaya_reason_file} > /dev/null 2>&1 ); then
     echo "${reason}" > "${avaya_reason_file}"
  fi
}

## Set user+group ownership so user 'craft' can read those
set_ownership()
{
    chown root:craft ${avaya_reason_file} ${avaya_opt_file} /tmp/dhcpcd-rawdata.${interface}
}

## validate ipv6 address
if [[ $ipv6 == 1 ]] && [[ "$reason" == "BOUND6" ]]; then
    rc=0
    ## Validate
    if [[ ! -z ${new_dhcp6_ia_na1_ia_addr1} ]]; then
       validate_ipv6_addr ${new_dhcp6_ia_na1_ia_addr1}
       if [[ $rc == 1 ]]; then
          echo "[$0] Rejecting invalid IP v6 address ${new_dhcp6_ia_na1_ia_addr1}"
          echo "DECLINE6" > "${avaya_reason_file}"
          exit 0;
       fi
    fi
fi

case "${reason}" in
        BOUND*|INFORM*|REBIND*|REBOOT*|RENEW*|TIMEOUT)
            make_opt_file;;
        PREINIT*|EXPIRE*|FAIL|IPV4LL|RELEASE*|STOP|EXPIRE6)
            remove_opt_file;;
esac

make_reason_file
set_ownership

