#------------------------------------------------------------------------------
# /etc/rc.d/dnsdhcp.sh - configure dnsmasq dhcp
#
# Creation:     26.09.2004  LanSpezi
# Last Update:  $Id: dnsdhcp_helper.sh 10593 2005-12-11 13:12:31Z lanspezi $
#------------------------------------------------------------------------------

# lease-file for dnsmasq - check for writeable directory
lease_file ()
{
    case "x$DNSDHCP_LEASES_DIR" in
        x) DNSDHCP_LEASES_DIR=/boot ;;
    esac

    if [ -d "$DNSDHCP_LEASES_DIR" ]
    then
        echo "echo \"test\" > ${DNSDHCP_LEASES_DIR}/dnsdhcp_testfile" > /tmp/test-$$.sh
        /bin/sh /tmp/test-$$.sh
        if [ -f "${DNSDHCP_LEASES_DIR}/dnsdhcp_testfile" ]
        then
            dnsdhcp_start_ok=yes
            rm "${DNSDHCP_LEASES_DIR}/dnsdhcp_testfile"
        else
            log_error "ERROR: cannot write to DNSDHCP_LEASES_DIR"
        fi
        rm /tmp/test-$$.sh
    else
        mkdir -p "$DNSDHCP_LEASES_DIR"
        if [ -d "$DNSDHCP_LEASES_DIR" ]
        then
            dnsdhcp_start_ok=yes
        else
            log_error "ERROR: could not create directory for the leases-file"
        fi
    fi
}

# check exists of lease-file - normaly only missing on first boot with active dhcpd
check_lease_file ()
{
    if [ ! -f "${DNSDHCP_LEASES_DIR}/dnsmasq.leases" ]
    then
        log_error "WARNING: dnsdhcp-leases was not found!"
        log_error "if this is your first boot with OPT_DNSDHCP enabled you can"
        log_error "ignore this message. otherwise your dnsdhcp-leases-file is not"
        log_error "saved permanently. in this case you should read the docu again!"
        > ${DNSDHCP_LEASES_DIR}/dnsmasq.leases
    fi
}

# set all parameters for an wins-server
dhcpd_wins ()
{
    if [ "$OPT_SAMBA" = "yes" -a "$OPT_NMBD" = "yes" ]
    then
        if [ "$NMBD_WINSSERVER" = "yes" -o -n "$NMBD_EXTWINSIP" ]
        then
            if [ "$NMBD_WINSSERVER" = "yes" ]
            then
                wins_server="ROUTER"
            fi
            if [ -n "$NMBD_EXTWINSIP" ]
            then
                wins_server=$NMBD_EXTWINSIP
            fi
        fi
    else
        if [ "$DNSDHCP_WINSSERVER_1" != "" ]
        then
            wins_server=$DNSDHCP_WINSSERVER_1
            if [ "$DNSDHCP_WINSSERVER_2" != "" ]
            then
                wins_server="$wins_server,$DNSDHCP_WINSSERVER_2"
            fi
        fi
    fi
}

# main
dnsdhcp_start_ok=no
lease_file
if [ $dnsdhcp_start_ok = yes ]
then
    check_lease_file
    {  
        echo "dhcp-leasefile=${DNSDHCP_LEASES_DIR}/dnsmasq.leases"

        if [ "$DNSDHCP_AUTHORITATIVE" = "yes" ]
        then
            echo "dhcp-authoritative"
        fi
        
        # deny-mac
        [ 0$DNSDHCP_DENY_MAC_N -eq 0 ] || for idx in `seq 1 $DNSDHCP_DENY_MAC_N`
        do
            eval macaddr='$DNSDHCP_DENY_MAC_'$idx
            echo "dhcp-host=$macaddr,ignore"
        done

        ### todo after this mark
        # list of IP_NET-indexes with a defined dhcp-range
        list_net_int=""
        # list of indexes from defined DHCP-Extra-Networks
        list_net_ext=""
		# list of IP_NET-indexes  for hosts with a static lease
		list_net_host=""
		
        # ranges for local networks
        [ 0$IP_NET_N -eq 0 ] || for idx in `seq 1 $IP_NET_N`
        do
            eval net='$IP_NET_'$idx
            ip_local=`echo $net | sed -e 's/\/.*//'`
            ip_netmask=`netcalc netmask $net`
            ip_bcast=`netcalc broadcast $net`

            dhcpd_wins

            if [ "$wins_server" = "ROUTER" ]
            then
                wins_server=$ip_local
            fi

            # range definition
            eval range_start='$DNSDHCP_RANGE_'$idx'_START'
            eval range_end='$DNSDHCP_RANGE_'$idx'_END'

            if [ -n "$range_start" -a -n "$range_end" ]
            then
                list_net_int=`echo "$list_net_int $idx"`
                echo "dhcp-range=NET$idx,$range_start,$range_end,$DNSDHCP_LS_TIME_DYN"
            fi

            # subnet-mask (option=1)
            echo "dhcp-option=NET$idx,1,$ip_netmask"

            # default-router (option=3)
            eval gateway='$DNSDHCP_RANGE_'$idx'_GATEWAY'
            case x$gateway in
                x)
                    echo "dhcp-option=NET$idx,3,$ip_local"
                ;;
                xnone)
                    echo "dhcp-option=NET$idx,3"
                ;;
                x*)
                    echo "dhcp-option=NET$idx,3,$gateway"
                ;;
            esac

            # broadcast address (option=28)
            echo "dhcp-option=NET$idx,28,$ip_bcast"

            # dns-server (option=6)
            eval dns_server='$DNSDHCP_RANGE_'$idx'_DNS_SERVER'
            case x$dns_server in
                x)
                    echo "dhcp-option=NET$idx,6,$ip_local"
                ;;
                xnone)
                    echo "dhcp-option=NET$idx,6"
                ;;
                x*)
                    echo "dhcp-option=NET$idx,6,$dns_server"
                ;;
            esac

            # Set the "all subnets are local" flag
            echo "dhcp-option=NET$idx,72,1"

            # wins-server (option=19,44,45,46,47)
            if [ "$wins_server" != "" ]
            then
                # option ip-forwarding off
                echo "dhcp-option=NET$idx,19,0"
                # set netbios-over-TCP/IP-nameserver(s) aka WINS server(s)
                echo "dhcp-option=NET$idx,44,$wins_server"
                # netbios datagram distribution server
                echo "dhcp-option=NET$idx,45,$wins_server"
                # netbios node type
                echo "dhcp-option=NET$idx,46,8"
                # empty netbios scope
                echo "dhcp-option=NET$idx,47"
            fi

            # NTP-Time-Server (option=42)
            eval ntp_server='$DNSDHCP_RANGE_'$idx'_NTP_SERVER'
            case x$ntp_server in
                x)
                    case $OPT_CHRONY in
                        yes)
                            echo "dhcp-option=NET$idx,42,$ip_local"
                        ;;
                    esac
                ;;
                xnone)
                    echo "dhcp-option=NET$idx,42"
                ;;
                x*)
                    echo "dhcp-option=NET$idx,42,$ntp_server"
                ;;
            esac
        done

        [ 0$DNSDHCP_EXTRA_RANGE_N -eq 0 ] || for idx in `seq 1 $DNSDHCP_EXTRA_RANGE_N`
        do
            # extra-range
            eval range_start='$DNSDHCP_EXTRA_RANGE_'$idx'_START'
            eval range_end='$DNSDHCP_EXTRA_RANGE_'$idx'_END'
            eval range_netmask='$DNSDHCP_EXTRA_RANGE_'$idx'_NETMASK'
            
            if [ -n "$range_start" -a -n "$range_end" ]
            then
                list_net_ext=`echo "$list_net_ext $idx"`
                echo "dhcp-range=EXT$idx,$range_start,$range_end,$range_netmask,$DNSDHCP_LS_TIME_DYN"
            fi
            
            #subnet-mask (option=1)
            echo "dhcp-option=EXT$idx,1,$range_netmask"

            # default-router (option=3)
            eval ip_gateway='$DNSDHCP_EXTRA_RANGE_'$idx'_GATEWAY'
            echo "dhcp-option=EXT$idx,3,$ip_gateway"

            # broadcast-address (option=28)
            ip_bcast=`netcalc broadcast $range_start $range_netmask`
            echo "dhcp-option=EXT$idx,28,$ip_bcast"   

            # dns-server (option=6)
            eval dns_server='$DNSDHCP_EXTRA_RANGE_'$idx'_DNS_SERVER'
            echo "dhcp-option=EXT$idx,6,$dns_server"

            # Set the "all subnets are local" flag
            echo "dhcp-option=EXT$idx,72,1"

            # wins-server (option=19,44,45,46,47)
            if [ "$wins_server" != "" ]
            then
                # option ip-forwarding off
                echo "dhcp-option=EXT$idx,19,0"
                # set netbios-over-TCP/IP-nameserver(s) aka WINS server(s)
                echo "dhcp-option=EXT$idx,44,$wins_server"
                # netbios datagram distribution server
                echo "dhcp-option=EXT$idx,45,$wins_server"
                # netbios node type
                echo "dhcp-option=EXT$idx,46,8"
                # empty netbios scope
                echo "dhcp-option=EXT$idx,47"
            fi

            # NTP-Time-Server (option=42)
            eval ntp_server='$DNSDHCP_EXTRA_RANGE_'$idx'_NTP_SERVER'
            if [ "$ntp_server" != "" ]
            then
                echo "dhcp-option=EXT$idx,42,$ntp_server"
            else
                if [ "$OPT_CHRONY" = "yes" ]
                then
                    echo "dhcp-option=EXT$idx,42,$ip_local"
                fi 
            fi
        done

        # hosts with fixed leases
        [ 0$HOSTS_N -eq 0 ] || for idx in `seq 1 $HOSTS_N`
        do
            eval macaddr='$HOST_'$idx'_MAC'
            eval dhcp_typ='$HOST_'$idx'_DHCPTYP'
            if [ "$macaddr" != ""  -o  "$dhcp_typ" = "hostname" ]
            then
                eval ipaddr='$HOST_'$idx'_IP'
                eval host='$HOST_'$idx'_NAME'
                net_found_int="NONE"
                net_found_ext="NONE"
                net_found_host="NONE"

                [ 0$IP_NET_N -eq 0 ] || for idn in `seq 1 $IP_NET_N`
                do
                    eval net='$IP_NET_'$idn
                    eval net_dev='$IP_NET_'$idn'_DEV'
                    net_ip=`netcalc network $net`
                    net_bits=`netcalc netmaskbits $net`
                    host_net=`netcalc network $ipaddr $net_bits`
                    if [ "$host_net" = "$net_ip" ]
                    then
                        list_net_host="$list_net_host $net_dev"
                        net_found_host="$idn"
		    fi
	        done
				
                for idn in $list_net_int
                do
                    eval net='$IP_NET_'$idn
                    net_ip=`netcalc network $net`
                    net_bits=`netcalc netmaskbits $net`
                    host_net=`netcalc network $ipaddr $net_bits`

                    if [ "$host_net" = "$net_ip" ]
                    then
                        net_found_int="$idn"
                    fi
                done

                for idn in $list_net_ext
                do
                    eval net='$DNSDHCP_EXTRA_RANGE_'$idn'_START'
                    eval mask='$DNSDHCP_EXTRA_RANGE_'$idn'_NETMASK'
                    net_ip=`netcalc network $net $mask`
                    net_bits=`netcalc netmaskbits $mask`
                    host_net=`netcalc network $ipaddr $net_bits`

                    if [ "$host_net" = "$net_ip" ]
                    then
                        net_found_ext="$idn"
                    fi
                done
                
                if [ "$net_found_int" != "NONE" -a "$dhcp_typ" != "hostname" ]
                then
                    echo "dhcp-host=$macaddr,$ipaddr,$host,$DNSDHCP_LS_TIME_FIX,net:NET$net_found_int"
                fi
                if [ "$net_found_ext" != "NONE" -a "$dhcp_typ" != "hostname" ]
                then
                    echo "dhcp-host=$macaddr,$ipaddr,$host,$DNSDHCP_LS_TIME_FIX,net:EXT$net_found_ext"
                fi
                if [ "$net_found_host" != "NONE" -a "$dhcp_typ" = "hostname" ]
                then
                    echo "dhcp-host=$host,$ipaddr,$host,$DNSDHCP_LS_TIME_FIX,net:NET$net_found_host"
                fi
                
                if [ "$net_found_int" = "NONE" -a "$net_found_ext" = "NONE" -a "$net_found_host" = "NONE" ] 
                then
                    log_error "WARNING: no dhcp-network are defined for host HOST_$idx"
                fi
            fi
        done
    } > /etc/dnsmasq_dhcp.conf
fi

dhcp_if_list=

dhcp_add_rule ()
{
    case x$dhcp_if_list in
        x)
            get_count INPUT
            add_chain in-dhcpd
            ins_rule filter INPUT "prot:udp 67 in-dhcpd" $res "dhcp access"
            ins_rule filter in-dhcpd DROP
            ;;
    esac
    case $dhcp_if_list in
        *$1*)
            # ignore it, its already there
            ;;
        *)
            ins_rule filter in-dhcpd "if:$1:any ACCEPT"
            dhcp_if_list="$dhcp_if_list $1"
            ;;
    esac
}
  
if [ -f /etc/dnsmasq_dhcp.conf ]
then
    chown dns:dns /etc/dnsmasq_dhcp.conf
    chmod 600 /etc/dnsmasq_dhcp.conf
    
    # add rule in "in-dhcp" for any interface with defined dhcp-ranges
    for idx in $list_net_int
    do
        eval range_dev='IP_NET_'$idx'_DEV'
        dhcp_add_rule $range_dev
	done
	#add rule in "in-dhcp" for any interfaces defiend in DNSDHCP_EXTRA_RANGE_x_DEVICE
    for idx in $list_net_ext
    do
        eval range_def='$DNSDHCP_EXTRA_RANGE_'$idx'_DEVICE'
        dhcp_add_rule $range_dev
    done
    #add rule in "in-dhcp" for any interface from IP_NET_x with no defined dhcp-range
    for idx in $list_net_host
    do
        eval range_def='$IP_NET_'$idx'_DEV'
        dhcp_add_rule $range_dev
    done
else
    log_error "WARNING: dnsmasq will only be started as DNS-Server"
fi
