I had been using FreeBSD on laptops for a while, but I used an old one from work (strictly) at home, and used a newer one (strictly) at work. (Well, except when I took a laptop to the USENIX conference in San Diego.)
Basically, I thus avoided the issue of coping with environmental
changes, such as switching between ``BSS'' and ``ad-hoc'' modes, or
changing SSIDs, or selecting different WEP keys... and to the extent
that it was still necessary, it was infrequent enough that I could just
hack /etc/pccard.conf directly to put
``ancontrol'' commands directly in the ``an'' stanza (for
example).
Well, now that I have my very own laptop, I'm actually taking it with me, with the expectation that it will be able to be useful in different environments. And this experience provided the requisite catalyst for me to finally try to do something constructive about it.
One of my colleagues had mentioned putting together a script that
would try different settings for the Cisco/Aironet card until it found
one that worked. This seemed like a fairly promising direction, though
I got the impression that his script was rather dependent on the
particular capabilities of the Cisco/Aironet cards, and would need to be
tweaked to cope with the Lucent/WaveLan/Orinoco cards (for example).
Another colleague put together a script that would ask him to select a
location, and it would go off and ``do the right thing'' for that
location. I found this approach rather more problematical, since I fire
up xdm from /usr/local/etc/rc.d, and although
it would have been possible to call such a script from withing the xdm
initialization script, that wouldn't necessarily handle an environment
change without a re-boot.
So I put together a script to be invoked from within the appropriate stanza(s) in /etc/pccard.conf. Its sole required argument is the one that identifies with interface is being used, and that is known at the time that the stanza is being parsed, so that should be easy. Here's a sample:
(The line in boldface is the one I added. The rest of the stanza is copied directly from########## an ########## # Aironet 340/342 Series 11Mbps 802.11 wireless NIC card "Cisco Systems" "340 Series Wireless LAN Adapter" config auto "an" ? insert /usr/local/sbin/pccard_hook -i $device insert /etc/pccard_ether $device start remove /etc/pccard_ether $device stop
/etc/defaults/pccard.conf.)
So, as I was writing this page, the thought occurred to me that the
above approach -- copying stanzas from
/etc/defaults/pccard.conf to /etc/pccard.conf,
with the addition of the above bold-faced line -- is really ugly.
So I started looking at other ways to accomplish this. I see that in
/etc/pccard_ether, there is provision to source
/etc/start_if.${interface} if it exists. That would be OK,
except that I'd need to create one of these for each possible device.
And each of them would look like all the others (which leads to the
question ``why can't we just invoke a single one?'').
Given that, I tried hacking /etc/pccard_ether directly:
--- /usr/src/etc/pccard_ether Sat Feb 3 20:41:34 2001 +++ /etc/pccard_ether Thu Mar 15 11:48:08 2001 @@ -58,6 +58,9 @@ case ${startstop} in [Ss][Tt][Aa][Rr][Tt] | '') + if [ -x /usr/local/sbin/pccard_hook ]; then + /usr/local/sbin/pccard_hook -i ${interface} + fi if [ -r /etc/start_if.${interface} ]; then . /etc/start_if.${interface} fi
I'm not real happy with that, either... but it does seem to work, with a minimum of hassle.
Postscript: Adapting a suggestion from Doug Ambrisko, I ditched the above, and created:
dhcp-135[1] ls /etc/st*_if.* /etc/start_if.an0 /etc/start_if.wi1 /etc/stop_if.ed1 /etc/start_if.an1 /etc/stop_if.an0 /etc/stop_if.wi0 /etc/start_if.wi0 /etc/stop_if.an1 /etc/stop_if.wi1
They contain:
which is arguably rather clumsy, at best. But it does work, without hacking existing system files.dhcp-135[2] more !$ /usr/local/sbin/pccard_hook -i an0 ...skipping... /usr/local/sbin/pccard_hook -i an1 ...skipping... /usr/local/sbin/pccard_hook -i wi0 ...skipping... /usr/local/sbin/pccard_hook -i wi1 ...skipping... hostname localhost [ -f /var/run/ntpd.pid ] && kill `cat /var/run/ntpd.pid` /bin/rm -f /etc/ntp.conf /var/run/ntpd.pid ...skipping... hostname localhost [ -f /var/run/ntpd.pid ] && kill `cat /var/run/ntpd.pid` /bin/rm -f /etc/ntp.conf /var/run/ntpd.pid ...skipping... hostname localhost [ -f /var/run/ntpd.pid ] && kill `cat /var/run/ntpd.pid` /bin/rm -f /etc/ntp.conf /var/run/ntpd.pid ...skipping... hostname localhost [ -f /var/run/ntpd.pid ] && kill `cat /var/run/ntpd.pid` /bin/rm -f /etc/ntp.conf /var/run/ntpd.pid ...skipping... hostname localhost [ -f /var/run/ntpd.pid ] && kill `cat /var/run/ntpd.pid` /bin/rm -f /etc/ntp.conf /var/run/ntpd.pid
Anyway, here's a directory where copies of the files involved (except for the /etc/st*_if.* files; you see those above) may be found; alternatively, here's a gzipped tarball of the set.
The approach I took was to implement ipfw in the
laptop's kernel, using a set of rules that blocks everything except
DHCP. Then, once a lease is granted, I already have a bit of code (/etc/dhclient-exit-hooks) that
gets control, so I use that point to invoke a script that replaces the
firewall rules with ones that
The relevant lines from /etc/rc.conf are
firewall_enable="YES" firewall_script="/etc/rc.firewall-pre-dhcp" firewall_quiet="NO" firewall_logging="YES"
As you can see, I am not using the supplied
/etc/rc.firewall, though I did use it as a starting-point.
One note, should you choose to do this on your own: placing an
exit 0 (or any other form of ``exit'' statement) in your
firewall rule-generation script is very unlikely to generate results
that you want: there is quite a bit of network (and other)
initialization that takes place after the firewall rules are set up, and
the ``exit'' statement will prevent that.
In any case, a copy of the above-referenced /etc/rc.firewall-pre-dhcp script may be found here. And here is another link to the /etc/dhclient-exit-hooks script.
Finally, here is a link to the /etc/rc.firewall-post-dhcp script.