You are not logged in.
Wpa_supplicant is very powerful, and when coupled with dhcpcd it can serve as an automatic network connection daemon that's both extremely simple and very reliable. So I decided to write a simple script that could take advantage of what wpa_supplicant is capable of -- if you define your networks using wpa_supplicant.conf then you might find this script interesting. The script is inspired by what I found on this ubuntu wiki page: https://help.ubuntu.com/community/WifiDocs/WPAHowTo
The philosophy is simple:
x networks are defined in wpa_supplicant configuration file
x daemon is started on boot, and uses wpa_supplicant to automatically associate the wifi card with available networks
x once wpa_supplicant finds a network it can connect to it runs a simple script that basically deals with talking to the dhcp server
x deamon is capable of roaming between different networks and it will disconncet/reconnect automatically depending on whether which networks are available
I've been using this script for a while now, and it works perfectly on both my computers, so I thought I'd share it... It comes in the form of three files:
1) rc daemon (/etc/rc.d/wpa_auto):
#!/bin/bash
. /etc/rc.conf
. /etc/rc.d/functions
. /etc/wpa_auto.conf
DAEMON_NAME=wpa_auto
WPA_SUPPLICANT=/usr/sbin/wpa_supplicant
WPA_CLI=/usr/sbin/wpa_cli
IFCONFIG=/sbin/ifconfig
DHCPCD=/sbin/dhcpcd
ACTION_SCRIPT=/usr/bin/wpa_auto_action
case "$1" in
start)
stat_busy "Starting $DAEMON_NAME daemon"
if [ ! -f /var/run/daemons/$DAEMON_NAME ]; then
$IFCONFIG $INTERFACE up &&\
$WPA_SUPPLICANT -D$WPA_DRIVER -i$INTERFACE -c$WPA_CONFIG $WPA_OPTIONS -B &&\
$WPA_CLI -i$INTERFACE -a$ACTION_SCRIPT $WPA_CLI_OPTIONS -B
if [ $? -gt 0 ]; then
stat_fail
exit 1
else
add_daemon $DAEMON_NAME
stat_done
fi
else
stat_fail
exit 1
fi
;;
stop)
stat_busy "Stopping $DAEMON_NAME daemon"
if [ -f /var/run/daemons/$DAEMON_NAME ]; then
rm_daemon $DAEMON_NAME
$DHCPCD -qx $INTERFACE &>/dev/null
$WPA_CLI -i$INTERFACE terminate &>/dev/null &&\
$IFCONFIG $INTERFACE down
if [ $? -gt 0 ]; then
stat_fail
exit 1
else
stat_done
fi
else
stat_fail
exit 1
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
reset)
stat_busy "Reseting $DAEMON_NAME daemon"
if [ -f /var/run/daemons/$DAEMON_NAME ]; then
$WPA_CLI -i$INTERFACE reassociate &>/dev/null
if [ $? -gt 0 ]; then
stat_fail
exit 1
else
stat_done
fi
else
stat_fail
exit 1
fi
;;
*)
echo "usage: $0 {start|stop|restart|reset}"
;;
esac
exit 0
2) Helper script for wpa_cli (/usr/bin/wpa_auto_action):
#!/bin/bash
. /etc/wpa_auto.conf
if [ "$2" = "CONNECTED" ]; then
[ -f /var/run/dhcpcd-$1.pid ] && /sbin/dhcpcd -qx $1
/sbin/dhcpcd -q $DHCPCD_OPTIONS $1
elif [ "$2" = "DISCONNECTED" ]; then
/sbin/dhcpcd -qx $1
fi
exit 0
3) Last but not least -- the configuration file: (/etc/wpa_auto.conf)
WPA_CONFIG="/etc/wpa_supplicant.conf"
WPA_DRIVER="wext"
WPA_OPTIONS=""
WPA_CLI_OPTIONS=""
DHCPCD_OPTIONS=""
INTERFACE="wlan0"
EDIT3: Updated to 9.0.1-1
AUR LINK -- also good for viewing the scripts (via the "sources" box)
Last edited by fwojciec (2009-01-07 18:00:23)
Offline
I also made an AUR package out of this: http://aur.archlinux.org/packages.php?ID=21491
Also, feel free to let me know if you have ideas for improving the script. My bash scripting skills are still pretty rudimentary, so this is a kind of learning experience for me.
Offline
An example of wpa_supplicant.conf file:
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
network={
ssid="WPA2_network"
key_mgmt=WPA-PSK
proto=WPA2
pairwise=CCMP
group=CCMP
psk="xxxxxxxxxxxxxxxxxx"
priority=1
}
network={
key_mgmt=NONE
}
This basically means that the daemon will always prefer my wpa2 connection at home, but if it can't find it it will associate with any available open network it finds.
And here is an example of wpa_supplicant.conf configuration for a WEP network (yes, wpa_supplicant, despite it's name, can be used for WEP networks as well):
network={
ssid="WEP_network"
key_mgmt=NONE
scan_ssid=1
# don't use quotes for wep_keyX fields
wep_key0=abcdefabcdefabcdefabcdefab
wep_tx_keyidx=0
# Add this option for "shared" wep mode
#auth_alg=SHARED
}
EDIT: Added WEP configuration example.
Last edited by fwojciec (2009-02-07 15:35:27)
Offline
Looks cool. Very similar to brain0's autowifi.
Last edited by iphitus (2008-11-14 22:28:46)
Offline
Looks cool. Very similar to brain0's autowifi.
Thanks I've used autowifi for a while, and in a way this script is very much inspired by it. I wanted something that's not coded in C (because I don't understand it), and something more streamlined for my use. Also, autowifi uses dhclient rather than dhcpcd, and dhclient for some reason will not work reliably with the wifi network at my university...
Offline
New version of the daemon (0.7) -- with mostly cosmetic improvements -- is available.
http://aur.archlinux.org/packages.php?ID=21491
Offline
More changes to the script:
Version 0.8
-------------
* further cleaned up the script and made coding style more consistent
* removed logging with logger: dhcpcd logs everything anyways, so logger was completely redundant
* some changes to the configuration file
Version 0.9
-------------
* mostly cosmetic changes, a couple of bug fixes
* removed "-C resolv.conf" from default dhcpcd configuration -- it's better to use resolv.conf.{head,tail} files
Version 0.9.1
---------------
* changed behavior of "reset" daemon option; instead of disconnecting and reconnecting it is now using the "reassociate" command
Last edited by fwojciec (2009-01-07 17:57:22)
Offline
Thanks for sharing this. I prefer using only wpa_supplicant over netcfg / wpasupplicant.
Offline
Thanks for sharing this. I prefer using only wpa_supplicant over netcfg / wpasupplicant.
Thanks for trying it
Offline
Wow, thanks for making this. I've been looking for ways to start wpa_supplicant.conf for using it with wpa_gui.
Tried netcfg net-auto-wireless from netcfg2 but failed to figure the wpa-configsection thingy. So I just started a normal wpa profile
using net-profiles. But I still had to set it manually if I change places.
Your wpa_auto is just perfect for what I need. Thank you.
Offline
Wow, thanks for making this. I've been looking for ways to start wpa_supplicant.conf for using it with wpa_gui.
Tried netcfg net-auto-wireless from netcfg2 but failed to figure the wpa-configsection thingy. So I just started a normal wpa profile
using net-profiles. But I still had to set it manually if I change places.
Your wpa_auto is just perfect for what I need. Thank you.
Thanks! I'm glad you like it
Offline
I have no problems editing the script to get it to do what I want, but could you add POST_UP and POST_DOWN variables like netcfg has so network-specific daemons/programs can be triggered to turn up or down, if the the network connection is on or off, respectively. Thanks for the wonderful script.
Registed Linux User 483618
Offline
So simple, but just works! I love it, thank you. It connects super fast comparing to wicd.
Only thing that is missing, in my opinion, is the hability to know what is going on. If it fails to connect to the network, I don't know why.
Offline
This is really great. I had also found that page on the Ubuntu wiki, together with this link http://redkommie.net/doku.php?id=slackware_wpa_wireless, and had cooked up a half-baked script that I was launching from rc.local.
I had a nagging feeling it might be better as a daemon, but didn't know exactly how to go about making that happen, and then there - well, here - it was. Thanks a lot.
Offline
I just converted from netcfg, and I already love this little thing.
Two suggestions:
1. Could you perhaps make it use the $WIRELESS_INTERFACE or $INTERFACE variable from /etc/rc.conf? I think this would jibe well with the idea of having a single configuration file.
2. Maybe change the configuration file from /etc/wpa_auto.conf to /etc/conf.d/wpa_auto.conf since it only contains configuration settings for the daemon itself.
Offline
Hi guys! Thanks for the nice comment and all the suggestions.
I'm a little busy at the moment, but I should have some free time this weekend -- I'll see if I'm able to come up with a new versions that includes at least some of your suggestions.
Sara -- POST_UP / POST_DOWN -- I like that idea, and it should be easy to implement.
tvale -- some sort of (error) logging mechanism would be good -- it's something I'll have to read up on though, so it might take me some time to implement this properly but I like the idea in principle.
Runiq -- hmm, it never occurred to me to try and re-use the configurations in arch's core config files... I'll have to think about that -- I see your point, but since people sometimes have quite unique network configurations involving multiple network interfaces (wired and wireless), it might still be more practical to define the wireless interface in the wpa_auto conf file. For a long time I had my wired connection defined in rc.conf and my wireless config through wpa_auto, so my wireless interface was never even mentioned in my rc.conf, for example...
Offline
It's working for me! Thanks! One thing I would like to know is, does anybody know if there is a way to automatically reconnect after using the rfkill switch? I mean, if I use the switch to turn wifi off (to save power) and then turn it back on, I need to issue the command
sudo /etc/rc.d/wpa_auto restart
Could this be done automatically?
Offline
@mrbrich
I guess it depends on how the hardware on your system works. On my laptop I have a key (Fn+F9) used to toggle the wifi card, so I can bind this key combination to a script using xbindkeys. The script looks like this:
#!/bin/sh
if [ -f /var/run/daemons/wpa_auto ]; then
sudo /etc/rc.d/wpa_auto stop
else
sudo /etc/rc.d/wpa_auto start
fi
I also have /etc/rc.d/wpa_auto in my sudoers file, so that running the command with sudo doesn't require the password. Not sure if it helps...
Offline
Great job. Fast and easy to use as i like.
Could you make a simple hook in /etc/pm/sleep.d for pm-utils on resume because it don't work for me :
~ $ cat /etc/pm/sleep.d/40wpa_auto
#!/bin/sh
. "${PM_FUNCTIONS}"
DAEMON_NAME=wpa_auto
case "$1" in
hibernate|suspend)
if [ -f /var/run/daemons/$DAEMON_NAME ] ; then /etc/rc.d/wpa_auto stop ; fi
logger "Wpa_auto Suspend" ;;
thaw|resume)
if [ ! -f /var/run/daemons/$DAEMON_NAME ] ; then /etc/rc.d/wpa_auto start ; fi
logger "Wpa_auto Resume" ;;
*) exit $NA ;;
esac
Last edited by coolaman (2010-11-27 13:47:10)
Offline
@fwojciec
Your tip didn't help me directly because my laptop has a hardware kill switch. However, it inspired my to put together a small Perl script, here posted:
#!/usr/bin/perl
open (RFKILL, "rfkill event |") || die "Unable to call rfkill\n";
while (<RFKILL>) {
if (/idx 0 type 1 op 2 soft 0 hard 0/) {
print "Wifi ON\n";
system("sudo /etc/rc.d/wpa_auto restart");
}
if (/idx 0 type 1 op 2 soft 1 hard 1/) {
print "Wifi OFF\n";
system("sudo /etc/rc.d/wpa_auto stop");
}
}
I called this script wpa_rfkill_restart.pl. It makes use of the rfkill tool to receive event notifications. As long as this script is running, WiFi reconnects automatically.
Last edited by mrbrich (2010-11-30 18:59:30)
Offline
I've been using a minimal setup a friend handed to me:
~/bin/wifi
#! /bin/bash
if [[ -n $(ls /var/run/wpa_supplicant 2>/dev/null) ]]; then
echo "Already connected"
else
sudo wpa_supplicant -B -Dwext -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan0
sudo wpa_cli -B -a /home/maca/bin/wpa_cli-action
fi
~/bin/wpa_cli-action
#! /bin/bash
case $2 in
CONNECTED)
sudo dhcpcd -x >/dev/null
sudo dhcpcd >/dev/null
;;
esac
And running the script from /etc/rc.local
It works flawlessly for me.
Maybe I can get some guidance here:
Is there a way to perform an action based on the BSSID?
I wan't to do an automated backup when I connect to my house or work network but not when I connect to my phone's AP.
Last edited by vermelho (2012-08-22 07:50:47)
Offline
@vermelho
Yes, it should be possible. You'd need to modify the wpa_cli-action script slightly and add, after the dhcpcd commands, an if/then statement that executes the backup command(s) if the bssid of the connected network matches a given value.
You can get the bssid of the AP you're connected to with something like this, for example:
wpa_cli status | grep bssid | sed 's/bssid=//'
I hope this helps.
Offline