Date: Fri, 13 Sep 2002 14:34:29 -0700 From: Lars Eggert <larse@ISI.EDU> To: current <current@FreeBSD.ORG> Subject: Comments requested: rc_ng per-location config script Message-ID: <3D8259E5.7020601@isi.edu>
next in thread | raw e-mail | index | archive | help
This is a cryptographically signed message in MIME format.
--------------ms000000080503080805000209
Content-Type: multipart/mixed;
boundary="------------060906060609030902080004"
This is a multi-part message in MIME format.
--------------060906060609030902080004
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Hi,
I'm slowly porting some local rc scripts we've been using for a few
years on -STABLE to rc_ng and -CURRENT. Some of them may be useful to
others, and I'd appreciate any comments.
The attached script changes a machine's /etc configuration based on
auto-probed network locations. It's mostly useful for laptops that you
move between a few well-known locations (office, home, Starbucks.)
Please see the script itself for a more detailed explanation.
Under -STABLE, we have a local /etc/netstop and an extended
/etc/netstart that I've not yet ported. With these two, I can do
"/etc/netstop && location && /etc/netstart" when I move between
locations, without rebooting. They're also hacked into apm.conf, so the
location detection happens on standby/resume. I'll hopefully get around
to port this sometime - or maybe this script'll make others help out :-)
Lars
PS: I'll be away from email until Sunday, so if I you send comments,
chances are I won't reply until then.
--
Lars Eggert <larse@isi.edu> USC Information Sciences Institute
--------------060906060609030902080004
Content-Type: text/plain;
name="location"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="location"
#!/bin/sh
#
# PROVIDE: location
# REQUIRE: root
# BEFORE: mountcritlocal
# KEYWORD: FreeBSD
# This script changes the machine configuration under /etc based on
# "known network locations" (KNL). Each KNL has a set of files and directories
# associated with it. If the scripts detects that the machine is connected
# to a KNL, it will create symlinks for all files and directories for the KNL
# under /etc.
#
# To detect a KNL, the script will use a variety of network probes to detect a
# well-known peer machine for the given KNL on the LAN. This well-known peer
# can be any directly-connected (i.e. no router hop) machine at a location.
# The script will probe for KNLs on all network interfaces.
#
# Location-specific configurations files are kept under in subdirectories
# under /etc/locations/<KNL>/, where <KNL> is the IP address of the well-known
# peer at that KNL. If no KNL is detected, the default configuration will
# be symlinked into place.
#
# The script will pay attention to location-specific configuration files
# that may be required for the probes to succeed. For example, it will make
# sure to execute start_if.* scripts before probing, etc. The script will
# also make sure to not remove files under /etc that are not location-specific.
#
# Example: This example uses two KNLs, "home" with a well-known peer
# of 10.0.0.1, and "work" with a well-known peer of 192.168.123.254,
# each with several configuration files. Also present is the
# fallback default configuration.
#
# /etc/
# locations/
# 10.0.0.1/
# rc.conf
# printcap
# hosts
#
# 192.168.123.254/
# rc.conf
# start_if.an0
# dhclient.conf
#
# unknown
# rc.conf
#
# Suppose the machine has two interfaces, xl0 and an0. Upon execution,
# this script would first probe for location "home" looking for the
# well-known peer 10.0.0.1 on both interfaces. If the probes fail,
# it would then probe for location "work", looking for well-known
# peer 192.168.123.254. Should that probe also fail, it would pick
# the default configuration.
#
# Assuming the probe for 192.168.123.254 succeeded, the script would
# create symlinks for rc.conf, start_if.an0 and dhclient.conf under
# /etc, and then exit.
#
# Comments to Lars Eggert <larse@isi.edu>, please.
. /etc/rc.subr
name="location"
rcvar=`set_rcvar`
start_cmd="probe_location"
# XXX local configuration variables, they should move to rc.conf eventually
location_dir="/etc/locations"
probe_ip="10.11.12.13"
probe_count=1
default="unknown"
start_if_delay=1
probes="dhcp arping ping"
# set after a probe has successfully detected a known location
found_loc=""
found_iface=""
found_probe=""
configure_location() {
# Create symlinks in /etc for each file or directory under $loc,
# unless the symlink would overwrite an existing file or directory.
# (Symlinks from an earlier invocatrion of this script will have
# been removed before this function is called.)
local loc=$1
# link location files into place
echo -n "Configuring for $loc:"
for file in `ls -A $location_dir/$loc`; do
# check if we would overwrite an existing file under /etc
if [ -f /etc/$file ]; then
echo -n " (skipped $file, would overwrite existing)"
continue
fi
# create symlink
ln -s $location_dir/$loc/$file /etc/$file
echo -n " $file"
done
echo
}
probe_ping () {
# This probe sends some ICMP ping requests to the representative
# address for the location that is currently probed for. The TTL
# of the pings is set to 1, so it will only probe the local LAN.
# The IP source address of the pings is fake (inside RFC 1918 space).
local loc=$1
local iface=$2
# assign fake, temporary RFC 1918 to the interface and route though it
ifconfig $iface $probe_ip/24 up
route -q add default -interface $iface
# do the probe
traceroute -i $iface -P icmp -M 1 -m 1 -n -q $probe_count $loc \
2> /dev/null | grep "$loc.*ms" > /dev/null
# did we detect the location?
if [ "$?" -eq "0" ]; then
# yes, we did
found_iface=$iface
found_loc=$loc
fi
# remove temporary IP address and route
route -q delete default
ifconfig $iface delete $probe_ip
}
probe_arping () {
# This probe uses the net/arping port to generate ARP lookups for the
# representative address of the location currently probed. The IP
# source address of the ARP queries is fake (inside RFC 1918 space).
local loc=$1
local iface=$2
# since arping is a port, only proceed if it's installed
if [ -x /usr/local/sbin/arping ]; then
# assign temporary RFC 1918 to interface and route though it
ifconfig $iface $probe_ip/24 up
route -q add default -interface $iface
# do the probe
arping -i $iface -S $probe_ip -c $probe_count $loc > /dev/null
# did we detect the location?
if [ "$?" -eq "0" ]; then
# yes, we did
found_iface=$iface
found_loc=$loc
fi
# remove temporary IP address and route
route -q delete default
ifconfig $iface delete $probe_ip
fi
}
probe_dhcp () {
# This probe will try to acquire an IP address via DHCP on the
# interface in question. If DHCP succeeds, the IP address of the
# DHCP server that allocated the address and the IP address of the
# default gateway DHCP gave us are checked against the location.
# (This means that the name of the location directory must be
# one or the other for this probe to work.)
local loc=$1
local iface=$2
# shorthands
leases="/var/db/dhclient.leases"
pid="/var/run/dhclient.probe.pid"
# save existing leases
if [ -f $leases ]; then
mv -f $leases $leases.bak
fi
# use the dhclient.conf for the given location, or a global one
conf=""
if [ -f $loc_dir/$loc/dhclient.conf ]; then
conf="-cf $loc_dir/$loc/dhclient.conf"
elif [ -f /etc/dhclient.conf ]; then
conf="-cf /etc/dhclient.conf"
fi
# start dhclient
rm -f $pid
dhclient $conf -pf $pid $iface &
# probe each second if we got an address
try=0
while [ 1 ]; do
# give dhclient some time to run
sleep 2
# see if we got a lease
for field in dhcp-server-identifier routers; do
# XXX pattern match this is sed or awk?
for ip in `grep "option $field " $leases | \
sort | uniq | cut -d' ' -f5 | \
cut -d';' -f1`; do
# did we detect the location?
if [ "$ip" = "$loc" ]; then
# yes, we did, stop the loop
found_iface=$iface
found_loc=$loc
break 3
fi
done
done
# stop the loop after a number of tries
try=`expr $try + 1`
if [ "$try" -gt "$probe_count" ]; then
break
fi
done
# kill dhclient
if [ -f $pid ]; then
kill `cat $pid`
rm -f $pid
fi
# restore existing leases
if [ -f $leases.bak ]; then
mv -f $leases.bak $leases
fi
}
probe_location () {
# This is the main function of this script. It will remove the exiting
# per-location configuration, and then probe for each location on
# each interface (unless the interface is loopback or has no carrier.)
# If a known location is detected, its configuration is symlinked
# into place. If no known configuration is detected, the default
# configuration is symlinked into place.
# first, remove all symlinks under /etc that point into /etc/locations
for link in `find /etc -type l`; do
ls -l $link | grep -- "-> $location_dir" > /dev/null
if [ "$?" -eq "0" ]; then
rm -f $link
fi
done
# create a list of known locations
locations=""
for loc in `ls $location_dir | \
awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/'`; do
if [ ! -d $location_dir/$loc ]; then continue; fi
locations="$loc $locations"
done
found_loc=$default
for loc in $locations; do
# find set of interfaces to probe at this location
interfaces=""
for iface in `ifconfig -l`; do
# don't probe on loopback
case $iface in
lo*) continue
;;
*)
;;
esac
# if a start_if.$iface script exists, run it
if [ -r $location_dir/$loc/start_if.$iface ]; then
. $location_dir/$loc/start_if.$iface
# XXX delay a bit (e.g. wireless NICs need
# some time to associate)
sleep $start_if_delay
else
# pull the interface up
ifconfig $iface up
fi
# don't probe on interfaces that have no carrier
status=`ifconfig $iface | grep status: | cut -d: -f2`
if [ "$status" != " no carrier" ]; then
# interface is a candidate, include in list
interfaces="$iface $interfaces"
fi
# XXX weed out more interfaces? gif, ng, tun, stf?
# if a stop_if.$iface script exists, run it
if [ -r $location_dir/$loc/stop_if.$iface ]; then
. $location_dir/$loc/stop_if.$iface
fi
# pull the interface down
ifconfig $iface down
done
# we now either have a set of interfaces to probe for the
# current location, or we don't
if [ "$interfaces" ]; then
# we have some candidate interfaces, so probe
echo -n "Probing for $loc on "
for iface in $interfaces; do
echo -n "$iface "
# try all probes
for probe in $probes; do
probe_$probe $loc $iface
if [ "$found_loc" ]; then
echo "- found via $probe."
found_probe=$probe
break 3
fi
done
done
# if we get here, we couldn't detect the location
echo "- not found."
fi
done
# create the symlinks
configure_location $found_loc
# save current location info (XXX probe this first next time)
echo "$found_loc $found_iface $found_probe" > /var/run/location
}
load_rc_config $name
run_rc_command "$1"
--------------060906060609030902080004--
--------------ms000000080503080805000209
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
Content-Description: S/MIME Cryptographic Signature
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJtjCC
AzgwggKhoAMCAQICEGZFcrfMdPXPY3ZFhNAukQEwDQYJKoZIhvcNAQEEBQAwgdExCzAJBgNV
BAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEaMBgG
A1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2Vydmlj
ZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBGcmVlbWFpbCBDQTErMCkG
CSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhhd3RlLmNvbTAeFw0wMDA4MzAwMDAw
MDBaFw0wNDA4MjcyMzU5NTlaMIGSMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBD
YXBlMRIwEAYDVQQHEwlDYXBlIFRvd24xDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUQ2Vy
dGlmaWNhdGUgU2VydmljZXMxKDAmBgNVBAMTH1BlcnNvbmFsIEZyZWVtYWlsIFJTQSAyMDAw
LjguMzAwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAN4zMqZjxwklRT7SbngnZ4HF2ogZ
gpcO40QpimM1Km1wPPrcrvfudG8wvDOQf/k0caCjbZjxw0+iZdsN+kvx1t1hpfmFzVWaNRqd
knWoJ67Ycvm6AvbXsJHeHOmr4BgDqHxDQlBRh4M88Dm0m1SKE4f/s5udSWYALQmJ7JRr6aFp
AgMBAAGjTjBMMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFQcml2YXRlTGFiZWwxLTI5NzAS
BgNVHRMBAf8ECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQQFAAOBgQAxsUtH
XfkBceX1U2xdedY9mMAmE2KBIqcS+CKV6BtJtyd7BDm6/ObyJOuR+r3sDSo491BVqGz3Da1M
G7wD9LXrokefbKIMWI0xQgkRbLAaadErErJAXWr5edDqLiXdiuT82w0fnQLzWtvKPPZE6iZp
h39Ins6ln+eE2MliYq0FxjCCAzkwggKioAMCAQICAwglQTANBgkqhkiG9w0BAQQFADCBkjEL
MAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3du
MQ8wDQYDVQQKEwZUaGF3dGUxHTAbBgNVBAsTFENlcnRpZmljYXRlIFNlcnZpY2VzMSgwJgYD
VQQDEx9QZXJzb25hbCBGcmVlbWFpbCBSU0EgMjAwMC44LjMwMB4XDTAyMDgyNDE4NTMzOVoX
DTAzMDgyNDE4NTMzOVowVDEPMA0GA1UEBBMGRWdnZXJ0MQ0wCwYDVQQqEwRMYXJzMRQwEgYD
VQQDEwtMYXJzIEVnZ2VydDEcMBoGCSqGSIb3DQEJARYNbGFyc2VAaXNpLmVkdTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBANI2Rrt4ggaQ/IrOsDeOm2H4/R5FRIL6JjDY3StE
aogp1r23WKniQ1Vj98Nu5WxlaZ3Iam3Jen5T66H8u7rtMNpK4qAeAGoBsVeyVr1+CTFeuv+m
xCh7BvBJwhLdm0zDaoDT05YKYZaqtsT+F286FWJQg31Xtf+vTKLVVrHcsafnteyal2NEt7Ac
yZZfjsVLwxp2Lq3cwYfRQRoo7/yCVzS7HsgM6jmbO4taEMo4yC2rpnUbWEUCDTaCYgpAXzAl
oiNk7GDh0wz2s5ZSnHRvNSBMAjCmpNtSYHfXFI1ANwrrrHIJ7Ei83+XN32PWY4OPzO3iown9
VR+vM+8lNx9OX28CAwEAAaNWMFQwKgYFK2UBBAEEITAfAgEAMBowGAIBBAQTTDJ1TXlmZkJO
VWJOSkpjZFoyczAYBgNVHREEETAPgQ1sYXJzZUBpc2kuZWR1MAwGA1UdEwEB/wQCMAAwDQYJ
KoZIhvcNAQEEBQADgYEAXcrIlKmPLM/r8r3oz2ZLPLaT1AyMjYTZY2qq/R7SUtFa9BNlTIFh
DG78QKfJ9lo2LMzTPQqMZgNLmj95GbNPI8P8OIq2K6MeCZWz08ROackqTFP6xWbIFIfXcBVR
1dZnDDyDKBBh05KkvyTPawSQyOBUeNBfQUyO4TE+3o58U8UwggM5MIICoqADAgECAgMIJUEw
DQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUx
EjAQBgNVBAcTCUNhcGUgVG93bjEPMA0GA1UEChMGVGhhd3RlMR0wGwYDVQQLExRDZXJ0aWZp
Y2F0ZSBTZXJ2aWNlczEoMCYGA1UEAxMfUGVyc29uYWwgRnJlZW1haWwgUlNBIDIwMDAuOC4z
MDAeFw0wMjA4MjQxODUzMzlaFw0wMzA4MjQxODUzMzlaMFQxDzANBgNVBAQTBkVnZ2VydDEN
MAsGA1UEKhMETGFyczEUMBIGA1UEAxMLTGFycyBFZ2dlcnQxHDAaBgkqhkiG9w0BCQEWDWxh
cnNlQGlzaS5lZHUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSNka7eIIGkPyK
zrA3jpth+P0eRUSC+iYw2N0rRGqIKda9t1ip4kNVY/fDbuVsZWmdyGptyXp+U+uh/Lu67TDa
SuKgHgBqAbFXsla9fgkxXrr/psQoewbwScIS3ZtMw2qA09OWCmGWqrbE/hdvOhViUIN9V7X/
r0yi1Vax3LGn57XsmpdjRLewHMmWX47FS8Madi6t3MGH0UEaKO/8glc0ux7IDOo5mzuLWhDK
OMgtq6Z1G1hFAg02gmIKQF8wJaIjZOxg4dMM9rOWUpx0bzUgTAIwpqTbUmB31xSNQDcK66xy
CexIvN/lzd9j1mODj8zt4qMJ/VUfrzPvJTcfTl9vAgMBAAGjVjBUMCoGBStlAQQBBCEwHwIB
ADAaMBgCAQQEE0wydU15ZmZCTlViTkpKY2RaMnMwGAYDVR0RBBEwD4ENbGFyc2VAaXNpLmVk
dTAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBBAUAA4GBAF3KyJSpjyzP6/K96M9mSzy2k9QM
jI2E2WNqqv0e0lLRWvQTZUyBYQxu/ECnyfZaNizM0z0KjGYDS5o/eRmzTyPD/DiKtiujHgmV
s9PETmnJKkxT+sVmyBSH13AVUdXWZww8gygQYdOSpL8kz2sEkMjgVHjQX0FMjuExPt6OfFPF
MYIDJzCCAyMCAQEwgZowgZIxCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUx
EjAQBgNVBAcTCUNhcGUgVG93bjEPMA0GA1UEChMGVGhhd3RlMR0wGwYDVQQLExRDZXJ0aWZp
Y2F0ZSBTZXJ2aWNlczEoMCYGA1UEAxMfUGVyc29uYWwgRnJlZW1haWwgUlNBIDIwMDAuOC4z
MAIDCCVBMAkGBSsOAwIaBQCgggFhMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI
hvcNAQkFMQ8XDTAyMDkxMzIxMzQzMFowIwYJKoZIhvcNAQkEMRYEFCQ2bqoExuhTzxYJaZMG
7QhVMTxBMFIGCSqGSIb3DQEJDzFFMEMwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMA0G
CCqGSIb3DQMCAgFAMAcGBSsOAwIHMA0GCCqGSIb3DQMCAgEoMIGtBgsqhkiG9w0BCRACCzGB
naCBmjCBkjELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ
Q2FwZSBUb3duMQ8wDQYDVQQKEwZUaGF3dGUxHTAbBgNVBAsTFENlcnRpZmljYXRlIFNlcnZp
Y2VzMSgwJgYDVQQDEx9QZXJzb25hbCBGcmVlbWFpbCBSU0EgMjAwMC44LjMwAgMIJUEwDQYJ
KoZIhvcNAQEBBQAEggEAn6u6MSlrQECXzRgJywLuoNBiPPtmBTTTTdNXpqZ0Aw8nvj535Q2o
Z9IKEn8EWxfo1J8iQuWq1CYGIOp7zCsNV1KvyqgI0RULZCL8t6kIHCvvaCKE37Atxm8WxeMo
VPOUYPXNw5NktG+/IePtizP93Y0qhxxMpNXaAl5si93lpBEJbHAEJVMF3D930pPAvek70Jkf
yKNM7/y/9x/7Sn8VjKfG2AVZYXnBFNelRj+Py0sbmKJFqaPPSr8FyD4riM17m+Is3F8kU2/y
XnhhjTxnN4yXoeByaIqBqQ2gPjqO1ZXshBmpSkCr2EpYTSLF831QXE+DYlSPZrafM4wlvZZz
ngAAAAAAAA==
--------------ms000000080503080805000209--
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D8259E5.7020601>
