Wireless Auto-configuration for FreeBSD, Version 0.2
This hack will automatically configure a wireless network card at interface startup time provided a list of possible networks and their WEP keys in /etc/rc.conf. The attached scripts are covered by the same license as FreeBSD.
I wanted a feature similar to Wireless Zero Configuration in Windows XP. The attached scripts approximate this for FreeBSD. After you've unpacked the shell archive, you'll need to compile wi-assoc-p.c with the following command:
cc -static -o /sbin/wi-assoc-p wi-assoc-p.c
Then copy the script start_if.wiface to /etc and create symlinks to the appropriate file names with the following commands:
cp start_if.wiface /etc chmod a+x /etc/start_if.wiface ln -sf /etc/start_if.wiface /etc/start_if.ath0 ln -sf /etc/start_if.wiface /etc/start_if.wi0
Configuration data goes into /etc/rc.conf in the following format:
wiconfig_${interface}_ssid${index}="${arguments_to_ifconfig}"
For example:
wiconfig_wi0_ssid0="ssid foobar wepmode on wepkey 0xdeadbeef"
wiconfig_wi0_ssid1="ssid bazqux wepmode off"
wiconfig_ath0_ssid0="media DS11 ${wiconfig_wi0_ssid0}"
The start_if.wiface script will exit as soon as it associates, so use lower indicies for preferred configurations.
This is a shell archive. Save it in a file, remove anything before this line, and then unpack it by entering "sh file". Note, it may create directories; files and directories will be owned by you and have default permissions:
#
# This archive contains:
#
# start_if.wiface
# wi-assoc-p.c
#
echo x - start_if.wiface
sed 's/^X//' >start_if.wiface << 'END-of-start_if.wiface'
X#!/bin/sh
X#### START_IF.WIFACE --- Automagically configure wireless interfaces
X
X## The "start_if.<interface>" script is called by ifscript_up() in
X## /etc/network.subr. We get the variable "$1" from that subroutine
X## because it uses the Bourne shell operator "." to run this script.
X## This has the happy side effect of allowing you to call this
X## script from the command-line with the interface as an argument
X## and have the script Do the Right Thing.
Xwiface=$1
X
Xindex=0
Xwhile : ; do
X eval wiconfig_args=\$wiconfig_${wiface}_args${index}
X if [ -n "${wiconfig_args}" ]; then
X ifconfig ${wiface} ${wiconfig_args}
X else
X break;
X fi
X ifconfig ${wiface} up && sleep 5
X if wi-assoc-p ${wiface}; then
X ifconfig ${wiface} down
X eval showstat_${wiface}=1
X break;
X fi
X index=$((${index} + 1))
Xdone
X
X#### START_IF.WIFACE ends here.
END-of-start_if.wiface
echo x - wi-assoc-p.c
sed 's/^X//' >wi-assoc-p.c << 'END-of-wi-assoc-p.c'
X/* WI-ASSOC-P.C --- Test true if wireless card associated with AP/peers */
X
X#include <sys/param.h>
X#include <sys/ioctl.h>
X#include <sys/socket.h>
X#include <sys/sysctl.h>
X#include <sys/time.h>
X#include <sys/module.h>
X#include <sys/linker.h>
X
X#include <net/ethernet.h>
X#include <net/if.h>
X#include <net/if_var.h>
X#include <net/if_dl.h>
X#include <net/if_types.h>
X#include <net/if_media.h>
X#include <net/route.h>
X#include <net80211/ieee80211.h>
X#include <net80211/ieee80211_ioctl.h>
X
X#include <netinet/in.h>
X#include <netinet/in_var.h>
X#include <arpa/inet.h>
X#include <netdb.h>
X
X#include <ctype.h>
X#include <err.h>
X#include <errno.h>
X#include <fcntl.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <unistd.h>
X#include <ifaddrs.h>
X
Xint
Xmain (int argc, char *argv[])
X{
X char ifname[32]; /* the name of the interface,
X e.g. "wi0" */
X int ifindex = 0; /* the index of the interface */
X int s; /* datagram socket, a handle for the
X interface in calls to ioctl(2) */
X u_int8_t data[32]; /* ioctl return values */
X struct ifreq ifr;
X struct ifmediareq ifmr;
X struct ieee80211req ireq;
X
X argc--; argv++;
X if (argc < 1)
X errx (EXIT_FAILURE, "no interface specified");
X
X strncpy (ifname, *argv, sizeof (ifname));
X if ((ifindex = if_nametoindex (ifname)) == 0)
X errx (EXIT_FAILURE, "interface %s does not exist", ifname);
X
X ifr.ifr_addr.sa_family = AF_INET;
X strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
X
X if ((s = socket (ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) {
X err (EXIT_FAILURE, "socket");
X }
X
X (void) memset (&ireq, 0, sizeof (ireq));
X (void) strncpy (ireq.i_name, ifname, sizeof (ireq.i_name));
X ireq.i_data = &data;
X
X ireq.i_type = IEEE80211_IOC_SSID;
X ireq.i_val = -1;
X if (ioctl (s, SIOCG80211, &ireq) < 0) {
X /* If we can't get the SSID, then this isn't an 802.11 device. */
X exit (EXIT_FAILURE);
X }
X
X (void) memset (&ifmr, 0, sizeof (ifmr));
X (void) strncpy (ifmr.ifm_name, ifname, sizeof (ifmr.ifm_name));
X
X if (ioctl (s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
X exit (EXIT_FAILURE); /* interface doesn't support SIOC{G,S}IFMEDIA
*/
X }
X
X if (ifmr.ifm_status & IFM_ACTIVE)
X exit (EXIT_SUCCESS); /* associated */
X else
X exit (EXIT_FAILURE); /* no carrier */
X}
X
X/* WI-ASSOC-P.C ends here. */
END-of-wi-assoc-p.c
exit