mirror of
https://github.com/pfsense/pfsense.git
synced 2025-10-26 11:38:35 +00:00
- Remove -G parameter from pfctl since it doesn't exist anymore - Initialize $old_router - Fix sh syntax on variable assign, it couldn't have space before = - Simplify logic - Avoid flush states twice, if it was done on IP change, don't do it again if router also has changed
407 lines
11 KiB
Bash
Executable File
407 lines
11 KiB
Bash
Executable File
#!/bin/sh
|
|
# $Id$
|
|
# $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $
|
|
# $FreeBSD: src/sbin/dhclient/dhclient-script,v 1.4 2005/06/10 03:41:18 brooks Exp $
|
|
#
|
|
# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org>
|
|
#
|
|
# Permission to use, copy, modify, and distribute this software for any
|
|
# purpose with or without fee is hereby granted, provided that the above
|
|
# copyright notice and this permission notice appear in all copies.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
#
|
|
|
|
NETSTAT=/usr/bin/netstat
|
|
GREP=/usr/bin/grep
|
|
AWK=/usr/bin/awk
|
|
HOSTNAME=/bin/hostname
|
|
GREP=/usr/bin/grep
|
|
ROUTE=/sbin/route
|
|
SED=/usr/bin/sed
|
|
ARP=/usr/sbin/arp
|
|
IFCONFIG=/sbin/ifconfig
|
|
PFCTL=/sbin/pfctl
|
|
|
|
LOCALHOST=127.0.0.1
|
|
|
|
if [ -x /usr/bin/logger ]; then
|
|
LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
|
|
else
|
|
LOGGER="echo"
|
|
fi
|
|
|
|
#
|
|
# Helper functions that implement common actions.
|
|
#
|
|
|
|
check_hostname() {
|
|
current_hostname=`$HOSTNAME`
|
|
if [ -z "$current_hostname" -o \
|
|
"$current_hostname" != "$new_host_name" ]; then
|
|
$LOGGER "New Hostname ($interface): $new_host_name"
|
|
$HOSTNAME $new_host_name
|
|
fi
|
|
}
|
|
|
|
arp_flush() {
|
|
$ARP -an -i $interface | \
|
|
$SED -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' | \
|
|
/bin/sh >/dev/null 2>&1
|
|
}
|
|
|
|
delete_old_states() {
|
|
$LOGGER "Starting delete_old_states()"
|
|
_FLUSHED=0
|
|
# If the IP changed, remove states from the old one
|
|
if [ -f /var/db/${interface}_ip ]; then
|
|
OLD_IP=`cat /var/db/${interface}_ip`
|
|
$LOGGER "Comparing IPs: Old: ${OLD_IP} New: ${new_ip_address}"
|
|
if [ -n "${OLD_IP}" ] && [ "${OLD_IP}" != "${new_ip_address}" ]; then
|
|
$LOGGER "Removing states from old IP '${OLD_IP}' (new IP '${new_ip_address}')"
|
|
${PFCTL} -i $interface -Fs
|
|
${PFCTL} -K ${OLD_IP}/32
|
|
_FLUSHED=1
|
|
fi
|
|
fi
|
|
# Delete states through old gateway if it's not the same
|
|
OLD_ROUTER=""
|
|
if [ -n "${old_routers}" ]; then
|
|
OLD_ROUTER=$old_routers
|
|
elif [ -f /tmp/${interface}_router ]; then
|
|
OLD_ROUTER=`cat /tmp/${interface}_router`
|
|
fi
|
|
if [ ${_FLUSHED} -eq 0 -a -n "${OLD_ROUTER}" ]; then
|
|
$LOGGER "Comparing Routers: Old: ${OLD_ROUTER} New: ${new_routers}"
|
|
if [ "${OLD_ROUTER}" != "${new_routers}" ]; then
|
|
$LOGGER "Removing states through old gateway '${OLD_ROUTER}' (new gateway '${new_routers}')"
|
|
${PFCTL} -i $interface -Fs
|
|
fi
|
|
fi
|
|
}
|
|
|
|
delete_old_address() {
|
|
/bin/rm -f /var/db/${interface}_ip
|
|
$IFCONFIG $interface inet -alias $old_ip_address $medium
|
|
}
|
|
|
|
add_new_address() {
|
|
|
|
$LOGGER "Starting add_new_address()"
|
|
|
|
$LOGGER "ifconfig $interface inet $new_ip_address netmask $new_subnet_mask broadcast $new_broadcast_address $medium"
|
|
|
|
$IFCONFIG $interface \
|
|
inet $new_ip_address \
|
|
netmask $new_subnet_mask \
|
|
broadcast $new_broadcast_address \
|
|
$medium
|
|
$IFCONFIG $interface setfirst $new_ip_address
|
|
|
|
$LOGGER "New IP Address ($interface): $new_ip_address"
|
|
$LOGGER "New Subnet Mask ($interface): $new_subnet_mask"
|
|
$LOGGER "New Broadcast Address ($interface): $new_broadcast_address"
|
|
$LOGGER "New Routers ($interface): $new_routers"
|
|
|
|
|
|
# This is necessary otherwise apinger will try to ping all 1s address
|
|
if [ -n "$new_routers" ] && [ "$new_routers" != "255.255.255.255" ]; then
|
|
echo $new_routers > /tmp/${interface}_router
|
|
fi
|
|
echo $new_ip_address > /var/db/${interface}_ip
|
|
}
|
|
|
|
delete_old_alias() {
|
|
if [ -n "$alias_ip_address" ]; then
|
|
$IFCONFIG $interface inet -alias $alias_ip_address > /dev/null 2>&1
|
|
$ROUTE delete $alias_ip_address $LOCALHOST > /dev/null 2>&1
|
|
fi
|
|
}
|
|
|
|
add_new_alias() {
|
|
if [ -n "$alias_ip_address" ]; then
|
|
$IFCONFIG $interface inet alias $alias_ip_address netmask \
|
|
$alias_subnet_mask
|
|
$ROUTE add $alias_ip_address $LOCALHOST
|
|
fi
|
|
}
|
|
|
|
fill_classless_routes() {
|
|
set $1
|
|
while [ $# -ge 5 ]; do
|
|
if [ $1 -eq 0 ]; then
|
|
route="default"
|
|
elif [ $1 -le 8 ]; then
|
|
route="$2.0.0.0/$1"
|
|
shift
|
|
elif [ $1 -le 16 ]; then
|
|
route="$2.$3.0.0/$1"
|
|
shift; shift
|
|
elif [ $1 -le 24 ]; then
|
|
route="$2.$3.$4.0/$1"
|
|
shift; shift; shift
|
|
else
|
|
route="$2.$3.$4.$5/$1"
|
|
shift; shift; shift; shift
|
|
fi
|
|
shift
|
|
router="$1.$2.$3.$4"
|
|
classless_routes="$classless_routes $route $router"
|
|
shift; shift; shift; shift
|
|
done
|
|
}
|
|
|
|
delete_old_routes() {
|
|
$LOGGER "Deleting old routes"
|
|
|
|
if [ -n "$old_classless_routes" ]; then
|
|
fill_classless_routes "$old_classless_routes"
|
|
set $classless_routes
|
|
while [ $# -gt 1 ]; do
|
|
route delete "$1" "$2"
|
|
shift; shift
|
|
done
|
|
return 0;
|
|
fi
|
|
|
|
# Only allow the default route to be overridden if it's on our own interface
|
|
if [ -f "/tmp/${interface}_defaultgw" ]; then
|
|
for router in $old_routers; do
|
|
$ROUTE delete default $router >/dev/null 2>&1
|
|
/bin/rm -f /tmp/${interface}_router
|
|
done
|
|
fi
|
|
|
|
if [ -n "$old_static_routes" ]; then
|
|
set $old_static_routes
|
|
while [ $# -gt 1 ]; do
|
|
$ROUTE delete "$1" "$2"
|
|
shift; shift
|
|
/bin/rm -f /tmp/${interface}_router
|
|
done
|
|
fi
|
|
|
|
arp_flush
|
|
}
|
|
|
|
add_new_routes() {
|
|
$LOGGER "Adding new routes to interface: $interface"
|
|
|
|
# RFC 3442: If the DHCP server returns both a Classless Static
|
|
# Routes option and a Router option, the DHCP client MUST ignore
|
|
# the Router option.
|
|
#
|
|
# DHCP clients that support this option (Classless Static Routes)
|
|
# MUST NOT install the routes specified in the Static Routes
|
|
# option (option code 33) if both a Static Routes option and the
|
|
# Classless Static Routes option are provided.
|
|
if [ -n "$new_classless_routes" ]; then
|
|
fill_classless_routes "$new_classless_routes"
|
|
$LOGGER "New Classless Static Routes ($interface): $classless_routes"
|
|
set $classless_routes
|
|
while [ $# -gt 1 ]; do
|
|
if [ "0.0.0.0" = "$2" ]; then
|
|
route add "$1" -iface "$interface"
|
|
else
|
|
route add "$1" "$2"
|
|
fi
|
|
shift; shift
|
|
done
|
|
return
|
|
fi
|
|
|
|
ADDED_ROUTE=no
|
|
EXISTSGW=`/bin/ls -l /tmp/*_defaultgw | /usr/bin/wc -l`
|
|
# Only allow the default route to be overridden if it's on our own interface
|
|
if [ -f "/tmp/${interface}_defaultgw" -o $EXISTSGW -eq 0 ]; then
|
|
$ROUTE delete default
|
|
for router in $new_routers; do
|
|
if [ "$new_ip_address" = "$router" -o "$router" = "255.255.255.255" ]; then
|
|
$ROUTE add default -iface $interface
|
|
echo $ROUTE add default -iface $interface | $LOGGER
|
|
# NOTE: Do not activate this for all ones address since pf(4) will try to forward packets to it.
|
|
if [ "$new_ip_address" = "$router" ]; then
|
|
echo $router > /tmp/${interface}_router
|
|
fi
|
|
else
|
|
$ROUTE add default $router
|
|
echo $ROUTE add default $router | $LOGGER
|
|
echo $router > /tmp/${interface}_router
|
|
fi
|
|
ADDED_ROUTE=yes
|
|
# 2nd and subsequent default routers error out, so explicitly
|
|
# stop processing the list after the first one.
|
|
break
|
|
done
|
|
fi
|
|
|
|
if [ -n "$new_static_routes" ]; then
|
|
$LOGGER "New Static Routes ($interface): $new_static_routes"
|
|
set $new_static_routes
|
|
while [ $# -gt 1 ]; do
|
|
$ROUTE add $1 $2
|
|
if [ "$ADDED_ROUTE" = "no" ]; then
|
|
echo $2 > /tmp/${interface}_router
|
|
fi
|
|
shift; shift
|
|
done
|
|
fi
|
|
}
|
|
|
|
add_new_resolv_conf() {
|
|
$LOGGER "Creating resolv.conf"
|
|
if [ -f "/var/etc/nameserver_$interface" ]; then
|
|
# Remove old entries
|
|
for nameserver in `cat /var/etc/nameserver_$interface`; do
|
|
$ROUTE delete $nameserver >/dev/null 2>&1
|
|
done
|
|
fi
|
|
if [ -n "$new_domain_name_servers" ]; then
|
|
/bin/rm -f /var/etc/nameserver_$interface
|
|
ALLOWOVERRIDE=`/usr/bin/grep dnsallowoverride /conf/config.xml | /usr/bin/wc -l`
|
|
for nameserver in $new_domain_name_servers; do
|
|
# Add a route to the nameserver out the correct interface
|
|
# so that mulitple wans work correctly with multiple dns
|
|
# also backup the nameserver for later route removal
|
|
if [ $ALLOWOVERRIDE -gt 0 ]; then
|
|
echo $nameserver >>/var/etc/nameserver_$interface
|
|
$ROUTE add $nameserver -iface $interface
|
|
fi
|
|
done
|
|
echo $new_domain_name >/var/etc/searchdomain_$interface
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Notify rc.newwanip of changes to an interface
|
|
notify_rc_newwanip() {
|
|
/usr/local/sbin/pfSctl -c "interface newip $interface"
|
|
}
|
|
|
|
#
|
|
# Start of active code.
|
|
#
|
|
|
|
# Invoke the local dhcp client enter hooks, if they exist.
|
|
if [ -f /etc/dhclient-enter-hooks ]; then
|
|
$LOGGER "dhclient-enter-hooks"
|
|
exit_status=0
|
|
. /etc/dhclient-enter-hooks
|
|
# allow the local script to abort processing of this state
|
|
# local script must set exit_status variable to nonzero.
|
|
if [ $exit_status -ne 0 ]; then
|
|
exit $exit_status
|
|
fi
|
|
fi
|
|
|
|
#if [ -x $ROUTE ]; then
|
|
# if_defaultroute=`$ROUTE -n get -inet default | $GREP interface | $AWK '{print $2}'`
|
|
#else
|
|
# $LOGGER "if_defaultroute"
|
|
# if_defaultroute="x"
|
|
#fi
|
|
|
|
$LOGGER $reason
|
|
case $reason in
|
|
MEDIUM)
|
|
$IFCONFIG $interface $medium
|
|
$IFCONFIG $interface inet -alias 0.0.0.0 $medium >/dev/null 2>&1
|
|
/bin/sleep 1
|
|
;;
|
|
|
|
PREINIT)
|
|
delete_old_alias
|
|
$IFCONFIG $interface inet 0.0.0.0 netmask 0.0.0.0 broadcast 255.255.255.255 up
|
|
delete_old_states
|
|
/bin/rm -f /tmp/${interface}_router
|
|
;;
|
|
|
|
ARPCHECK|ARPSEND)
|
|
;;
|
|
|
|
BOUND|RENEW|REBIND|REBOOT)
|
|
check_hostname
|
|
changes="no"
|
|
if [ "$old_ip_address" != "$new_ip_address" ]; then
|
|
delete_old_states
|
|
fi
|
|
if [ -n "$old_ip_address" ]; then
|
|
if [ -n "$alias_ip_address" ] && \
|
|
[ "$old_ip_address" != "$alias_ip_address" ]; then
|
|
delete_old_alias
|
|
changes="yes"
|
|
fi
|
|
if [ "$old_ip_address" != "$new_ip_address" ]; then
|
|
delete_old_address
|
|
delete_old_routes
|
|
changes="yes"
|
|
fi
|
|
fi
|
|
if [ "$reason" = BOUND ] || \
|
|
[ "$reason" = REBOOT ] || \
|
|
[ -z "$old_ip_address" ] || \
|
|
[ "$old_ip_address" != "$new_ip_address" ]; then
|
|
add_new_address
|
|
add_new_routes
|
|
changes="yes"
|
|
fi
|
|
if [ -n "$alias_ip_address" ] && \
|
|
[ "$new_ip_address" != "$alias_ip_address" ]; then
|
|
add_new_alias
|
|
changes="yes"
|
|
fi
|
|
add_new_resolv_conf
|
|
if [ "$changes" = "yes" ] ; then
|
|
notify_rc_newwanip
|
|
fi
|
|
;;
|
|
|
|
EXPIRE|FAIL)
|
|
delete_old_alias
|
|
delete_old_states
|
|
if [ -n "$old_ip_address" ]; then
|
|
delete_old_address
|
|
delete_old_routes
|
|
fi
|
|
;;
|
|
|
|
TIMEOUT)
|
|
delete_old_alias
|
|
add_new_address
|
|
/bin/sleep 1
|
|
if [ -n "$new_routers" ]; then
|
|
$LOGGER "New Routers ($interface): $new_routers"
|
|
set "$new_routers"
|
|
if /sbin/ping -q -c 1 -t 1 "$1"; then
|
|
if [ "$new_ip_address" != "$alias_ip_address" ]; then
|
|
add_new_alias
|
|
fi
|
|
add_new_routes
|
|
if add_new_resolv_conf; then
|
|
notify_rc_newwanip
|
|
fi
|
|
fi
|
|
fi
|
|
$IFCONFIG $interface inet -alias $new_ip_address $medium
|
|
delete_old_states
|
|
delete_old_routes
|
|
;;
|
|
esac
|
|
|
|
# Invoke the local dhcp client exit hooks, if they exist.
|
|
if [ -f /etc/dhclient-exit-hooks ]; then
|
|
$LOGGER "dhclient-exit-hooks"
|
|
exit_status=0
|
|
. /etc/dhclient-exit-hooks
|
|
# allow the local script to abort processing of this state
|
|
# local script must set exit_status variable to nonzero.
|
|
exit $exit_status
|
|
fi
|