diff options
author | James Rayner <james@archlinux.org> | 2009-08-07 16:23:45 +0200 |
---|---|---|
committer | James Rayner <james@archlinux.org> | 2009-08-07 16:23:45 +0200 |
commit | 54e39849f1e60eb043f9d8f0904acf3c79d96a1c (patch) | |
tree | 9c10a01ea0ba58d31b3ab8282ead767da49264d3 /src-wireless | |
parent | f7168ae05837a24060b41511be6e4626cb26828a (diff) | |
download | netctl-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-auto | 43 | ||||
-rw-r--r--[-rwxr-xr-x] | src-wireless/netcfg-auto-wireless | 139 | ||||
-rw-r--r--[-rwxr-xr-x] | src-wireless/wireless-dbus | 146 |
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 |