#! /bin/bash
. /usr/lib/network/network
. $SUBR_DIR/8021x
. $SUBR_DIR/wireless


iwconfig_up() {

    quirk prescan && iwlist "$INTERFACE" scan &> /dev/null # bcm43xx

    # 'none' uses iwconfig like wep. Use sane default if WEP_OPTS=""
    if [[ -z "$WEP_OPTS" ]]; then
        if [[ "$SECURITY" = "wep-old" ]]; then
            if [[ -n "$AP" ]]; then
                WEP_OPTS="ap \"$AP\" key $KEY"
            else
                WEP_OPTS="essid \"$ESSID\" key $KEY"
            fi
        elif [[ "$SECURITY" = "none-old" ]]; then
            if [[ -n "$AP" ]]; then
                WEP_OPTS="ap \"$AP\""
            else
                WEP_OPTS="essid \"$ESSID\""
            fi
        fi
    fi

    quirk "predown" && bring_interface down "$INTERFACE" # madwifi FS#10585

    report_debug wireless_up iwconfig "$INTERFACE" $WEP_OPTS

    if ! iwconfig "$INTERFACE" $WEP_OPTS; then
        report_fail "Could not set wireless configuration."
        return 1
    fi

    quirk "predown" && bring_interface up "$INTERFACE" # madwifi FS#10585

    report_debug ethernet_up wep_check
    if ! wep_check "$INTERFACE" "$TIMEOUT"; then
        report_fail "WEP Association Failed"
        return 1
    fi
}

wireless_up() {

    PROFILE="$1"
    load_profile "$PROFILE"

    enable_rf $INTERFACE $RFKILL $RFKILL_NAME || return 1

    # Check if interface exists
    is_interface "$INTERFACE" || { report_fail "interface $INTERFACE does not exist"; return 1; }

    # Kill any lingering wpa_supplicants.
    report_debug wireless_up stop_wpa "$INTERFACE"
    stop_wpa "$INTERFACE"

    # Most drivers (mac80211) need mode set before device is brought up
    if [[ $(iwgetid -sm "$INTERFACE") -ne Managed ]]; then
        report_debug wireless_up iwconfig "$INTERFACE" mode managed
        iwconfig "$INTERFACE" mode managed
    fi

    report_debug wireless_up ifup
    bring_interface up "$INTERFACE" || return 1

    # Scan for network's existence first
    if checkyesno "${SCAN:-no}"; then
        report_debug wireless_up scanning
        local OLDESSID="$ESSID"
        if [[ -n "$AP" ]]; then
            ESSID=$(find_ap "$INTERFACE" "$AP")
        else
            ESSID=$(find_essid "$INTERFACE" "$ESSID")
        fi
        if [[ $? -gt 0 ]]; then
            report_fail "Wireless network \"$OLDESSID\" not present."
            return 1
        fi
    fi

    # Manually set iwconfig options
    if [[ -n "$IWCONFIG" ]]; then
        report_debug wireless_up iwconfig "$INTERFACE" $IWCONFIG
        iwconfig "$INTERFACE" $IWCONFIG
    fi

    # Set to 'none' if not set
    [[ -z "$SECURITY" ]] && SECURITY="none"

    case "$SECURITY" in
        *-old)
            report_debug "Using older iwconfig based path"
            iwconfig_up || return 1
            ;;
        wpa-config)
            [[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf" # defaults
            ;;
        none|wep|wpa|wpa-configsection)
            WPA_CONF="$(make_wpa_config_file $INTERFACE)"
            echo -e "network={ \n$(make_wpa_config) \n}">> "$WPA_CONF"
            ;;
        *)
            report_fail "Invalid SECURITY setting: $SECURITY"
            ;;
    esac

    if  [[ ${SECURITY:(-4)} != "-old" ]]; then
        report_debug wireless_up "Configuration generated at $WPA_CONF"
        [[ -z "$WPA_DRIVER" ]] && WPA_DRIVER="wext"
        report_debug wireless_up start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_DRIVER" "$WPA_OPTS"
        if ! start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_DRIVER" "$WPA_OPTS"; then
            report_fail "wpa_supplicant did not start, possible configuration error"
            return 1
        fi
        report_debug wireless_up wpa_check
        if ! wpa_check "$INTERFACE" "$TIMEOUT"; then
            report_fail "WPA Authentication/Association Failed"
            return 1
        fi
    fi

    if ! "$CONN_DIR/ethernet" up "$PROFILE"; then
        wireless_down "$PROFILE" YES
        return 1
    fi
}

# wireless_down PROFILE [ LEAVE ifconfig up? default no ]
wireless_down() {
    local PROFILE="$1"
    load_profile "$PROFILE"

    "$CONN_DIR/ethernet" down "$PROFILE"

    if [[ ${SECURITY:(-4)} == "-old" ]]; then
        report_debug wireless_down iwconfig "$INTERFACE" essid off key off
        iwconfig "$INTERFACE" essid off key off &> /dev/null
    else
        report_debug wireless_down stop_wpa "$INTERFACE"
        stop_wpa "$INTERFACE"
        rm -rf "${TMPDIR:-/tmp}/wpa.$INTERFACE"
    fi

    bring_interface down "$INTERFACE"

    # Handle wireless kill switches
    # Any reason why a hardware switch should be considered on interface down?
    if [[ "$RFKILL" == "soft" ]]; then
        . "$SUBR_DIR/wireless"
        set_rf_state "$INTERFACE" disabled $RFKILL_NAME || return 1
    fi
}

# Returns status of profile - is it still functional?
wireless_status() {
    load_profile "$1"
    if [[ "$(iwgetid -r)" -ne "$ESSID" ]]; then
        return 1
    elif ! ip link show dev "$INTERFACE" | fgrep -q "state UP"; then
        return 1
    fi

}

wireless_$1 "$2" "$3"
exit $?

# vim: ft=sh ts=4 et sw=4:

