summaryrefslogtreecommitdiffstats
path: root/src-wireless
diff options
context:
space:
mode:
authorJames Rayner <james@archlinux.org>2009-08-07 16:23:45 +0200
committerJames Rayner <james@archlinux.org>2009-08-07 16:23:45 +0200
commit54e39849f1e60eb043f9d8f0904acf3c79d96a1c (patch)
tree9c10a01ea0ba58d31b3ab8282ead767da49264d3 /src-wireless
parentf7168ae05837a24060b41511be6e4626cb26828a (diff)
downloadnetctl-54e39849f1e60eb043f9d8f0904acf3c79d96a1c.tar.gz
netctl-54e39849f1e60eb043f9d8f0904acf3c79d96a1c.tar.xz
Patch from Jim Pryor
Diffstat (limited to 'src-wireless')
-rw-r--r--[-rwxr-xr-x]src-wireless/net-auto43
-rw-r--r--[-rwxr-xr-x]src-wireless/netcfg-auto-wireless139
-rw-r--r--[-rwxr-xr-x]src-wireless/wireless-dbus146
3 files changed, 249 insertions, 79 deletions
diff --git a/src-wireless/net-auto b/src-wireless/net-auto
index 8b724a5..98bb91d 100755..100644
--- a/src-wireless/net-auto
+++ b/src-wireless/net-auto
@@ -2,12 +2,16 @@
. /etc/rc.conf
. /etc/rc.d/functions
+. /usr/lib/network/globals
case "$1" in
start)
+ if ! ck_daemon net-auto; then # JP: check if it's already running
+ exit_stderr "net-auto has already been started: try \"/etc/rc.d/net-auto restart\""
+ fi
# Ensure any device renaming has occurred as intended
for daemon in "${DAEMONS[@]}"; do
- if [ "$daemon" = "${daemon#!}" -a "$daemon" = "net-rename" ]; then
+ if [[ "$daemon" = "${daemon#!}" && "$daemon" = net-rename ]]; then
if ck_daemon net-rename; then
/etc/rc.d/net-rename start
fi
@@ -15,28 +19,43 @@ case "$1" in
done
# TODO: check if any way of using 'stacks' in bash
- for iface in ${AUTO_NETWORKS[@]}; do
- if [[ "${iface:0:4}" = "auto" ]]; then
- auto=$iface
- elif [[ "$auto" ]]; then
- /usr/bin/netcfg-$auto $iface
- [[ $? -eq 0 ]] && echo $iface >> /var/run/daemons/net-auto
+
+ rm -f "$STATE_DIR/net-auto"
+ for iface in "${AUTO_NETWORKS[@]}"; do
+ if [[ "${iface:0:4}" = auto ]]; then
+ auto="$iface"
+ elif [[ -n "$auto" ]]; then
+ if /usr/bin/netcfg-"$auto" "$iface"; then
+ echo "$iface" >> "$STATE_DIR/net-auto"
+ add_daemon net-auto # JP: was this forgotten?
+ fi
unset auto
+ else
+ true # JP: can AUTO_NETWORKS contain elements other than ...auto-CONNECTION INTERFACE...?
+ # JP: for example, what do we do with AUTO_NETWORKS=(auto-wireless wlan0 eth0)?
+ # JP: or with AUTO_NETWORKS=(eth0 auto-wireless wlan0)?
fi
done
;;
stop)
- [[ ! -e /var/run/daemons/net-auto ]] && exit 0
- for iface in $(cat /var/run/daemons/net-auto); do
- netcfg iface-down $iface
+ if ck_daemon net-auto; then
+ exit_stderr "net-auto not running"
+ fi
+
+ for iface in $(cat "$STATE_DIR/net-auto"); do # JP: note that we may have written "wlan0 wlan1" to net-auto
+ # e.g. if the user did AUTO_NETWORKS=(auto-wireless "wlan0 wlan1")
+ # and now we're unpacking and handling wlan0, wlan1 one by one
+ # that's not necessarily a problem...I'm just calling attention to it
+ /usr/bin/netcfg iface-down "$iface"
done
+ rm -f "$STATE_DIR/net-auto"
rm_daemon net-auto
;;
restart)
- $0 stop; sleep 1; $0 start
+ "$0" stop; sleep 1; "$0" start
;;
*)
- echo "usage: $0 {start|stop|restart}"
+ exit_stderr "Usage: $0 {start|stop|restart}"
esac
# vim: set ts=4 et sw=4:
diff --git a/src-wireless/netcfg-auto-wireless b/src-wireless/netcfg-auto-wireless
index e77eb0e..a17232c 100755..100644
--- a/src-wireless/netcfg-auto-wireless
+++ b/src-wireless/netcfg-auto-wireless
@@ -1,59 +1,128 @@
#! /bin/bash
# Originally contributed by Neuro: http://bbs.archlinux.org/viewtopic.php?pid=278148#p278148
-. /usr/lib/network/network
-. /usr/lib/network/wireless
. /etc/rc.conf
. /etc/rc.d/functions
+. /usr/lib/network/network
+. /usr/lib/network/wireless_utils
# wifi_auto
# autoconnect wireless interface
# $1 - wireless interface
wifi_auto()
{
- interface=$1;
- stat_busy "Scanning for networks"
+ local interface="$1" connection="$2"
+
+ if [[ ! -f "$CONN_DIR/$connection" ]]; then
+ exit_err "$connection is not a valid connection."
+ elif ! "$CONN_DIR/$connection" verify "$interface"; then
+ exit_err "$interface is not a wireless interface."
+ fi
+
+ report_try "Scanning for networks"
- ifconfig $interface up
- networks="$(list_networks $interface)"
+ local status=$(query_iface "$interface" "$connection") # supply $connection as hint
+ case "$status" in
+ disabled)
+ exit_fail "INTERFACE $interface is disabled."
+ ;;
+ external)
+ exit_fail "INTERFACE $interface was configured by another application."
+ ;;
+ "")
+ #ifconfig "$interface" up 2>/dev/null # $? is 255 when radio-switched-off
+ "$CONN_DIR/$connection" control "$interface" up
+ if [[ $? -gt 0 ]]; then
+ # interface is really disabled
+ "$CONN_DIR/$connection" control "$interface" disable
+ exit_fail "INTERFACE $interface is disabled."
+ fi
+ ;;
+ *)
+ # interface already up and controlled by a profile
+ ;;
+ esac
- if [[ ! "$networks" ]]; then
- stat_append "- No networks available."
- stat_fail
- exit 1
+ networks=$(list_networks "$interface")
+
+ if [[ -z "$networks" ]]; then
+ # disconnect interface if it wasn't already up
+ [[ -z "$status" ]] && "$CONN_DIR/$connection" control "$interface" forcedown
+ exit_fail "No local networks."
fi
+ [[ -z "$status" ]] && "$CONN_DIR/$connection" control "$interface" down # take iface down here so that query_iface doesn't perceive it as externally controlled
+ # unclear what should happen if $status set to an already-connected profile...?
+
# Loop through all the found essid's, then find a matching profile.
- while read essid; do
- for network in $(list_profiles); do
- load_profile $network
- case "$CONNECTION" in
- wireless-old|wireless|wireless-dbus)
- if [[ "$essid" = "$ESSID" && "$interface" = "$INTERFACE" ]]; then
- found=$network
- fi
- ;;
- esac
- done
- done < $networks
+
+ local found_profile found_essid
+
+ # JP: add ability to use AP instead of ESSID
+ # JP: also, make ESSIDs in wireless-dbus CONNECTIONS a regexp instead of a literal
+ while read ap essid; do
+ while read network; do
+ (
+ unset CONNECTION INTERFACE AP
+ load_profile "$network"
+ case "$CONNECTION" in
+ wireless-old|wireless|wireless-dbus)
+ if [[ "$interface" = "$INTERFACE" ]]; then
+ if [[ "$ap" == "$AP" ]]; then
+ exit 2
+ elif [[ -z "$found_profile" ]]; then
+ if [[ "$CONNECTION" == wireless-dbus ]]; then
+ if expr match "$essid" "^$ESSID\$" 1>/dev/null; then
+ exit 1
+ fi
+ elif [[ "$essid" == "$ESSID" ]]; then
+ exit 1
+ fi
+ fi
+ fi
+ ;;
+ esac
+ exit 0
+ )
+ case $? in
+ 2) found_profile="$network"
+ found_essid="$essid"
+ break 2;;
+ 1) found_profile="$network"
+ found_essid="$essid"
+ ;;
+ esac
+ done < <(list_profiles) # avoid subshell
+ done < "$networks" # avoid subshell; list_networks returns name of a tmp file
+ # JP: now each line of that file is of format: ap essid...
- if [[ "$found" ]]; then
- netcfg $found
- exit $?
+ rm -f "$networks" # shouldn't we delete the tmp file?
+
+ if [[ -n "$found_profile" ]]; then
+ report_success
+ if profile_up "$found_profile" "$found_essid"; then # we pass literal essid to profile_up as $2
+ exit 0
+ else
+
+
+
+ "$CONN_DIR/$connection" control "$interface" forcedown # take down interface?
+ exit_fail "Couldn't connect profile $found_profile."
+ fi
+ else
+ [[ -z "$status" ]] && "$CONN_DIR/$connection" control "$interface" forcedown
+ exit_fail "No profiles matched the local networks."
fi
- stat_append "- No profiles matched the found networks"
- stat_fail
- exit 1
}
if [[ $(id -u) -ne 0 ]]; then
- err "This script needs to be run with root priviledges"
- exit 1
+ exit_stderr "This script should be run as root."
fi
-if [[ -z $1 ]]; then
- err "Please supply an interface to connect"
- exit 1
+if [[ -z "$1" ]]; then
+ exit_stderr "Must supply an interface to connect."
fi
-wifi_auto $1
-
+
+SELF=$(basename $0)
+wifi_auto "$1" "${SELF#netcfg-auto-}" # we assume this script is named netcfg-auto-CONNECTIONTYPE
+
diff --git a/src-wireless/wireless-dbus b/src-wireless/wireless-dbus
index 6f53a6c..f1c1cd8 100755..100644
--- a/src-wireless/wireless-dbus
+++ b/src-wireless/wireless-dbus
@@ -4,7 +4,7 @@ import dbus
import shlex
import subprocess
from signal import SIGTERM
-from os import kill
+from os import kill,path
from time import sleep
# dbus constants.
@@ -21,16 +21,20 @@ def read_config(config):
cfg = shlex.split(open(config, "r").read())
options = {}
for line in cfg:
- (var, delim, value) = line.partition('=')
- if delim and var.lstrip()[0] != "#":
- options[var] = value
+ (var, delim, value) = line.partition('=')
+ if delim:
+ var = var.lstrip()
+ if var[0] != '#':
+ value = value.partition("#")[0].rstrip()
+ if value[0] == value[-1] and value[0] in ('"',"'"):
+ value=value[1:-1]
+ options[var] = value
return options
def wep_hex2dec(key):
if len(key) not in [10, 26]:
- print "Bad key"
- raise SyntaxError
+ fail("Profile error: invalid KEY.", report_type="err")
x=0
new_key=[]
@@ -40,14 +44,24 @@ def wep_hex2dec(key):
return new_key
-def fail(msg=None):
+# JP: connect to our hookable reporting functions in /usr/lib/network/globals
+
+def report(report_type, *args):
+ report_handler.stdin.write('report_%s %s\n' % (report_type, ' '.join(map(repr,args))))
+
+def fail(msg=None, report_type="fail"):
if msg:
- print " -", msg
- kill(int(open("/var/run/wpa_supplicant.pid").read()),SIGTERM)
+ report(report_type, msg)
+ try:
+ pid = open("/var/run/wpa_supplicant.pid").read()
+ except IOError:
+ pass
+ else:
+ kill(int(pid),SIGTERM)
sys.exit(1)
-def start(profile):
+def start(profile, essid):
# TODO: Add check if it's even a wireless interface
# Interface up - probably redundant, should be 'ip' instead.
#try:
@@ -68,22 +82,25 @@ def start(profile):
except KeyError:
args.append("-Dwext")
- if profile['SECURITY'] == "wpa-config":
+ security = profile.get('SECURITY','none')
+ if security == "wpa-config":
try:
args.append("-c" + profile["WPA_CONF"])
except KeyError:
args.append("-c/etc/wpa_supplicant.conf")
- elif not profile['SECURITY'] in ['wpa', 'wep', 'none']:
- fail("Invalid security chosen")
+ elif not security in ['wpa', 'wep', 'none']:
+ fail("Profile error: invalid SECURITY.", report_type="err")
# Start wpa_supplicant
+ report('debug', 'wireless_dbus', 'starting wpa_supplicant')
supplicant = subprocess.Popen(args,stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
output = supplicant.communicate()[0]
if supplicant.returncode not in [255,0]:
- print output
- fail("Could not start wpa_supplicant")
+ print >>sys.stderr, output # JP: print to stderr
+ fail("Couldn't start wpa_supplicant.")
# Connect to wpa_supplicant
+ report('debug', 'wireless_dbus', 'connecting to wpa_supplicant')
bus = dbus.SystemBus()
wpas_obj = bus.get_object(WPAS_DBUS_SERVICE, WPAS_DBUS_OPATH)
wpas = dbus.Interface(wpas_obj, WPAS_DBUS_INTERFACE)
@@ -104,20 +121,26 @@ def start(profile):
iface = dbus.Interface(if_obj, WPAS_DBUS_INTERFACES_INTERFACE);
# Add and select the network. Networks already specified for wpa-config
- if profile['SECURITY'] in ['wpa','wep','none']:
+ if security in ['wpa','wep','none']:
+ report('debug', 'wireless_dbus', 'add and select network')
path = iface.addNetwork()
net_obj = bus.get_object(WPAS_DBUS_SERVICE, path)
rnet = dbus.Interface(net_obj, WPAS_DBUS_NETWORKS_INTERFACE)
iface.selectNetwork(rnet)
+ if not essid:
+ essid = profile["ESSID"]
- if profile['SECURITY'] == "wpa":
- opts = dbus.Dictionary({"ssid": dbus.ByteArray(profile['ESSID']),
+ if security == "wpa":
+ opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid),
"psk": dbus.String(profile['KEY'])},
signature="sv")
+ report('debug', 'wireless_dbus', 'connect to network with security=wpa')
+ # next line crashes with
+ # dbus.exceptions.DBusException: fi.epitest.hostap.WPASupplicant.InvalidOptions: Did not receive correct message arguments
rnet.set(opts)
- elif profile['SECURITY'] == "wep":
+ elif security == "wep":
key=profile['KEY']
if key[:2] == "s:": # String key prefixed by "s:"
keydbus=key[2:]
@@ -127,15 +150,17 @@ def start(profile):
for l in key:
keydbus+=chr(l)
- opts = dbus.Dictionary({"ssid": dbus.ByteArray(profile['ESSID']),
+ opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid),
"key_mgmt": dbus.String("NONE"),
"wep_tx_keyidx": dbus.Int32(1),
"wep_key0": dbus.ByteArray(keydbus)},
signature="sv")
+ report('debug', 'wireless_dbus', 'connect to network with security=wep')
rnet.set(opts)
- elif profile['SECURITY'] == "none":
- opts = dbus.Dictionary({"ssid": dbus.ByteArray(profile['ESSID'])},
+ elif security == "none":
+ opts = dbus.Dictionary({"ssid": dbus.ByteArray(essid)},
signature="sv")
+ report('debug', 'wireless_dbus', 'connect to network with security=none')
rnet.set(opts)
# Determine timeout
@@ -154,24 +179,81 @@ def start(profile):
break
if n == timeout:
- fail("Association/Authentication failed:" + state)
+ # fail("Association/Authentication failed:" + state)
+ fail("Couldn't associate/authenticate with wireless network.")
# Run ethernet and get an ip.
try:
- subprocess.check_call(["/usr/lib/network/connections/ethernet-iproute", "up", sys.argv[2]])
+ subprocess.check_call([ETHERNET_IPROUTE, "up", sys.argv[2]])
except subprocess.CalledProcessError:
fail()
sys.exit(0)
def stop(profile):
- subprocess.call(["/usr/lib/network/connections/ethernet", "down", sys.argv[2]])
+ ret = subprocess.call([ETHERNET_IPROUTE, "down", sys.argv[2]])
kill(int(open("/var/run/wpa_supplicant.pid").read()),SIGTERM)
- sys.exit(0)
+ sys.exit(ret)
+
+def query(interface,request):
+ if request == 'profile' or request=='enabled':
+ ret = subprocess.call([WIRELESS, "query", interface, request, "-iproute"]) # JP: left some of the new query functionality in the wireless file because it's so bash-heavy
+ elif request=='associated':
+ ret = subprocess.call([WIRELESS, "query", interface, request, "-iproute", sys.argv[5], sys.argv[6]]) # JP: left some of the new query functionality in the wireless file because it's so bash-heavy
+ else:
+ ret = subprocess.call([ETHERNET_IPROUTE, "query", interface, request]) # JP: for these requests, we can call the ethernet-iproute functions directly and save some process overhead
+ sys.exit(ret)
+
+def control(interface,action):
+ if action == 'enable' or action == 'disable':
+ ret = subprocess.call([WIRELESS, "control", interface, action])
+ else:
+ ret = subprocess.call([ETHERNET_IPROUTE, "control", interface, action]) # JP: for these actions, we can call the ethernet-iproute functions directly and save some process overhead
+ sys.exit(ret)
+
+def verify(interface):
+ ret = subprocess.call([WIRELESS, "verify", interface])
+ sys.exit(ret)
if __name__ == "__main__":
- profile = read_config("/etc/network.d/"+sys.argv[2])
-
- if sys.argv[1] == "up":
- start(profile)
- elif sys.argv[1] == "down":
- stop(profile)
+
+ CONN_DIR = path.abspath(path.dirname(sys.argv[0]))
+ ETHERNET_IPROUTE = path.join(CONN_DIR,"ethernet-iproute")
+ WIRELESS = path.join(CONN_DIR,"wireless")
+
+ if sys.argv[1] == "query":
+ interface,request = sys.argv[2:4]
+ query(interface,request)
+
+ elif sys.argv[1] == "control":
+ interface,action = sys.argv[2:4]
+ control(interface,action)
+
+ elif sys.argv[1] == "verify":
+ interface = sys.argv[2]
+ verify(interface)
+
+ else:
+ # setup bash report_* handler
+ report_handler_script = 'source /etc/rc.conf; source /etc/rc.d/functions; source %s/../globals; while read cmd args; do eval $cmd "$args"; done' % (CONN_DIR,)
+ report_handler = subprocess.Popen(report_handler_script, executable='/bin/bash', stdin=subprocess.PIPE, shell=True)
+
+ try:
+ profile_name = sys.argv[2]
+ profile = read_config("/etc/network.d/"+profile_name)
+
+ essid = sys.argv[3] if len(sys.argv)>3 else "" # JP: pass literal ESSID as an argument, so that we can have entry in profile be a regexp
+
+ if 'INTERFACE' not in profile:
+ fail("Profile error: no INTERFACE to configure.", report_type="err")
+
+ if sys.argv[1] == "up":
+ start(profile, essid)
+ elif sys.argv[1] == "down":
+ stop(profile)
+
+
+ finally:
+ report_handler.stdin.close()
+ report_handler.wait()
+
+# vim: et ts=4