summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Rayner <james@archlinux.org>2008-12-18 06:33:31 +0100
committerJames Rayner <james@archlinux.org>2008-12-18 06:33:31 +0100
commit164df2fdcc8ac4286c7f8f04f1e7c9004ade6960 (patch)
tree50e56f8711d4c7e9db7981c3c6282a994213acca /src
parent300cd2c73b599c2a58463ce75e1aa2cb19ac2414 (diff)
downloadnetctl-164df2fdcc8ac4286c7f8f04f1e7c9004ade6960.tar.gz
netctl-164df2fdcc8ac4286c7f8f04f1e7c9004ade6960.tar.xz
fix libify
Diffstat (limited to 'src')
-rw-r--r--src/8021x32
-rw-r--r--src/connections/ethernet122
-rw-r--r--src/connections/ppp18
-rw-r--r--src/connections/wireless119
-rw-r--r--src/network297
-rw-r--r--src/wireless61
6 files changed, 649 insertions, 0 deletions
diff --git a/src/8021x b/src/8021x
new file mode 100644
index 0000000..cce66cd
--- /dev/null
+++ b/src/8021x
@@ -0,0 +1,32 @@
+# Uses wpa_supplicant to check for association to a network
+# wpa_check interface [timeout]
+wpa_check()
+{
+ local timeout=0 INTERFACE=$1 TIMEOUT=${2:-15}
+
+ while [[ $timeout -lt $TIMEOUT ]]; do
+ (
+ eval `wpa_cli status|grep wpa_state`
+ [[ "$wpa_state" = "COMPLETED" ]]
+ ) && return 0
+ sleep 1
+ let timeout++
+ done
+
+ wpa_cli terminate >/dev/null 2>&1
+ err_append "Authentication/association failed"
+ return 1
+}
+
+start_wpa()
+{
+ INTERFACE="$1"; WPA_CONF="$2"; WPA_OPTS="$3"
+
+ wpa_supplicant -wB -P/var/run/wpa_supplicant_${INTERFACE}.pid -i"${INTERFACE}" -c "$WPA_CONF" $WPA_OPTS
+ sleep 1
+
+ if [[ ! -f "/var/run/wpa_supplicant_${INTERFACE}.pid" ]]; then
+ err_append "wpa_supplicant did not start, possible configuration error"
+ return 1
+ fi
+}
diff --git a/src/connections/ethernet b/src/connections/ethernet
new file mode 100644
index 0000000..3605663
--- /dev/null
+++ b/src/connections/ethernet
@@ -0,0 +1,122 @@
+#! /bin/bash
+
+
+ethernet_up() {
+ if [[ ! -e /sys/class/net/$INTERFACE ]]; then
+ if ! echo "$INTERFACE"|grep ":"; then
+ err_append "Interface $INTERFACE does not exist"
+ fi
+ fi
+
+ if ip link show $INTERFACE|grep -q "NO-CARRIER"; then
+ err_append "No connection available"
+ return 1
+ fi
+
+ ifconfig $INTERFACE up
+
+ if checkyesno ${AUTH8021X:-no}; then
+ . ${SUBR_DIR}/8021x
+ [[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf"
+ [[ -z "$WPA_OPTS" ]] && WPA_OPTS="-Dwired"
+ start_wpa "$INTERFACE" "$WPA_CONF" "$WPA_OPTS"
+ if ! wpa_check "$INTERFACE"; then
+ ifconfig $INTERFACE down
+ return 1
+ fi
+ fi
+
+ case $IP in
+ dhcp)
+ # Check if DHCP_TIMEOUT was set if not set a default value
+ [[ -z "$DHCP_TIMEOUT" ]] && DHCP_TIMEOUT=10
+
+ if checkyesno $DHCLIENT; then
+ rm -r /var/run/dhclient-${INTERFACE}.pid >/dev/null 2>&1
+ if ! dhclient -q -e TIMEOUT=$DHCP_TIMEOUT -pf /var/run/dhclient-${INTERFACE}.pid $INTERFACE; then
+ err_append "DHCP IP lease attempt failed"
+ return 1
+ fi
+ else
+ # Clear remaining pid files.
+ rm -f /var/run/dhcpcd-${INTERFACE}.{pid,cache} >/dev/null 2>&1
+ # If using own dns, tell dhcpcd to NOT replace resolv.conf
+ [[ -n "$DNS1" ]] && DHCP_OPTIONS="-C resolv.conf $DHCP_OPTIONS"
+ # Start dhcpcd
+ if ! dhcpcd -qL -t $DHCP_TIMEOUT $DHCP_OPTIONS $INTERFACE; then
+ err_append "DHCP IP lease attempt failed"
+ return 1
+ fi
+ fi
+ # TODO: add support for $section:ifconfig for other stuff, like mtu or mac?
+ ;;
+ static)
+ if ! ifconfig $INTERFACE $IFOPTS up; then
+ err_append "Could not bring interface up"
+ return 1
+ fi
+
+ # bring up the default route (gateway)
+ if [[ -n "$GATEWAY" ]]; then
+ if ! route add default gw $GATEWAY; then
+ err_append "Adding gateway $GATEWAY failed"
+ return 1
+ fi
+ fi
+ ;;
+ *)
+ err_append "Profile error: IP must be either 'dhcp' or 'static'"
+ return 1
+ ;;
+ esac
+
+ # set the hostname
+ if [[ -n "$HOSTNAME" ]]; then
+ if ! hostname $HOSTNAME; then
+ err_append "Cannot set hostname"
+ return 1
+ fi
+ fi
+
+ # Generate a new resolv.conf
+ if [[ -n "$DNS1" ]] || [[ -n "$DNS" ]]; then
+
+ : >/etc/resolv.conf
+ [[ -n "$DOMAIN" ]] && echo "domain $DOMAIN" >>/etc/resolv.conf
+ [[ -n "$SEARCH" ]] && echo "search $SEARCH" >>/etc/resolv.conf
+ [[ -n "$DNS1" ]] && echo "nameserver $DNS1" >>/etc/resolv.conf
+ [[ -n "$DNS2" ]] && echo "nameserver $DNS2" >>/etc/resolv.conf
+
+ if [[ -n "$DNS" ]]; then
+ for dns in ${DNS[@]}; do
+ echo "nameserver $dns" >>/etc/resolv.conf
+ done
+ fi
+ fi
+ return 0
+}
+
+ethernet_down() {
+ case $IP in
+ dhcp)
+ if checkyesno $DHCLIENT; then
+ if [[ -f /var/run/dhclient-${INTERFACE}.pid ]]; then
+ kill `cat /var/run/dhclient-${INTERFACE}.pid`
+ fi
+ else
+ if [[ -f /var/run/dhcpcd-${INTERFACE}.pid ]]; then
+ dhcpcd -qx $INTERFACE
+ fi
+ fi
+ ;;
+ static)
+ [[ -n "$GATEWAY" ]] && route del default gw $GATEWAY
+ ;;
+ esac
+ ifconfig $INTERFACE 0.0.0.0
+
+ quirk "nodown" || ifconfig $INTERFACE down
+
+}
+
+# vim: set ts=4 et sw=4:
diff --git a/src/connections/ppp b/src/connections/ppp
new file mode 100644
index 0000000..ecefd63
--- /dev/null
+++ b/src/connections/ppp
@@ -0,0 +1,18 @@
+#! /bin/bash
+ppp_up() {
+ [[ -z "$PEER" ]] && PEER="provider"
+ [[ -z "$PPP_TIMEOUT" ]] && PPP_TIMEOUT=30
+
+ /usr/sbin/pppd call $PEER updetach child-timeout $PPP_TIMEOUT linkname $PEER
+
+ if [[ $? -ne 0 ]]; then
+ err_append "pppd connection failed"
+ exit 1
+ fi
+}
+
+ppp_down() {
+ kill $(head -1 /var/run/ppp-$(basename $PEER).pid)
+}
+
+# vim: set ts=4 et sw=4:
diff --git a/src/connections/wireless b/src/connections/wireless
new file mode 100644
index 0000000..dbc2a29
--- /dev/null
+++ b/src/connections/wireless
@@ -0,0 +1,119 @@
+#! /bin/bash
+
+wireless_up() {
+
+ load_profile $1
+
+ . ${SUBR_DIR}/wireless
+
+ if [[ ! -d /sys/class/net/$INTERFACE/wireless ]]; then
+ err_append "Interface $INTERFACE is not a wireless interface"
+ return 1
+ fi
+
+ # Required by atheros and others (mac80211?) to enable device
+ ifconfig $INTERFACE up
+
+ # Hack that has been required by some broadcom
+ quirk "prescan" && iwlist $INTERFACE scan &> /dev/null
+
+ # Required by ipw3945 to properly re-associate
+ quirk "preessid" && eval "iwconfig $INTERFACE mode managed essid \"$ESSID\""
+
+ # Kill any lingering wpa_supplicants.
+ if [[ -f /var/run/wpa_supplicant_$INTERFACE.pid ]]; then
+ kill $(cat /var/run/wpa_supplicant_$INTERFACE.pid)
+ fi
+
+ # Default scan off as it won't see hidden networks and some hardware's scanning is dodgy
+ [[ ! "$SCAN" ]] && SCAN="no"
+ if checkyesno $SCAN; then
+ if ! find_essid $INTERFACE "$ESSID"; then
+ err_append "Network unavailable"
+ return 1
+ fi
+ fi
+
+ # Manually set iwconfig options
+ if [[ "$IWCONFIG" ]]; then
+ iwconfig $INTERFACE $IWCONFIG
+ fi
+
+ case $SECURITY in
+ wep|none)
+ # 'none' security uses iwconfig, like wep, so use same code, minus keysetting.
+ # Use sane default if no alternative is specified
+ if [[ "$SECURITY" = "wep" && "$WEP_OPTS" = "" ]]; then
+ WEP_OPTS="mode managed essid \"$ESSID\" key $KEY"
+ elif [[ "$SECURITY" = "none" && "$WEP_OPTS" = "" ]]; then
+ WEP_OPTS="mode managed essid \"$ESSID\""
+ fi
+
+ # Add wierd quirk for some Atheros in response to FS#10585
+ quirk "predown" && ifconfig $INTERFACE down
+
+ if ! eval iwconfig $INTERFACE $WEP_OPTS; then
+ err_append "Could not set wireless configuration"
+ return 1
+ fi
+
+ quirk "postsleep" && sleep 1
+ quirk "postscan" && sleep 1 && iwlist $INTERFACE scan &>/dev/null
+ quirk "predown" && ifconfig $INTERFACE up
+
+ wep_check $INTERFACE $TIMEOUT|| return 1
+ ;;
+ wpa)
+ . ${SUBR_DIR}/8021x
+
+ # Quirk for broken drivers... http://bbs.archlinux.org/viewtopic.php?id=36384
+ quirk "wpaessid" && eval iwconfig $INTERFACE mode managed essid "\"$ESSID\""
+
+ local WPA_CONF="/tmp/wpa.${1// /}" # substitute spaces out
+ echo "ctrl_interface=/var/run/wpa_supplicant" >> $WPA_CONF
+ echo "ctrl_interface_group=0" >> $WPA_CONF
+ chmod 600 $WPA_CONF
+
+ # Generate configuration
+ if [[ "${#KEY}" == "64" ]]; then
+ echo -e 'network={ \nssid="$ESSID" \npsk=$KEY \n}'> $WPA_CONF
+ elif ! wpa_passphrase "$ESSID" "$KEY" >> $WPA_CONF; then
+ err_append "Configuration generation failed: `cat $WPA_CONF`"
+ return 1
+ fi
+
+ # Connect!
+ [[ "$WPA_OPTS" == "" ]] && WPA_OPTS="-Dwext"
+ start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
+ wpa_check $INTERFACE $TIMEOUT || return 1
+ ;;
+ wpa-config)
+ . ${SUBR_DIR}/8021x
+ # If user hasnt defined one, use stock config.
+ [[ -z "$WPA_CONF" ]] && WPA_CONF="/etc/wpa_supplicant.conf"
+ [[ "$WPA_OPTS" == "" ]] && WPA_OPTS="-Dwext"
+ start_wpa $INTERFACE $WPA_CONF $WPA_OPTS || return 1
+ wpa_check $INTERFACE $TIMEOUT || return 1
+ ;;
+ esac
+
+ . $CONN_DIR/ethernet
+ if ! ethernet_up $1; then
+ wireless_down $1 YES
+ return 1
+ fi
+}
+
+wireless_down() {
+ PROFILE=$1 NOETHERNETDOWN=$2
+ if ! checkyesno $2; then
+ . $CONN_DIR/ethernet
+ ethernet_down $1
+ fi
+ wpa_cli terminate &> /dev/null
+ [[ "$SECURITY" == "wpa" ]] && rm -f "/tmp/wpa.${1// /}" # remove wpa config
+ iwconfig $INTERFACE essid off key off &> /dev/null
+
+}
+
+# vim: set ts=4 et sw=4:
diff --git a/src/network b/src/network
new file mode 100644
index 0000000..88f689e
--- /dev/null
+++ b/src/network
@@ -0,0 +1,297 @@
+### Globals
+PROFILE_DIR="/etc/network.d/"
+SUBR_DIR="/usr/lib/network/"
+CONN_DIR="${SUBR_DIR}/connections/"
+STATE_DIR="/var/run/network/"
+
+### Messages
+##
+# err msg
+# output specified message
+err_append() {
+echo -n $*
+}
+
+err() {
+echo $*
+}
+
+### Profile loading
+##
+# load_profile profile
+# source the profile
+load_profile() {
+ validate_profile $1 || return 1
+ . $PROFILE_DIR/$1
+}
+# validate_profile profile
+# check whether profile exists and is usable
+validate_profile()
+{
+ [[ -z "$1" ]] && return 1
+ if [[ ! -f $PROFILE_DIR/$1 ]]; then
+ err "Profile \"$1\" does not exist"
+ return 1
+ fi
+ . $PROFILE_DIR/$1
+ if [[ -z "$INTERFACE" ]]; then
+ err "Profile missing an interface to configure"
+ return 1
+ fi
+ if [[ ! -f $CONN_DIR/$CONNECTION ]]; then
+ err "$CONNECTION is not a valid connection, check spelling or look at examples"
+ return 1
+ fi
+}
+
+### Profile up/down
+##
+# all_down
+# take all profiles down
+#
+all_down()
+{
+ ls -1 $STATE_DIR/profiles/ | while read prof; do
+ profile_down $prof
+ done
+ rm_daemon net-profiles
+}
+
+# all_suspend
+# store a list of running profiles and take them down
+#
+all_suspend()
+{
+ [[ ! -d $STATE_DIR ]] && mkdir -p $STATE_DIR/{interfaces,profiles}
+ [[ ! -d $STATE_DIR/suspend ]] && mkdir $STATE_DIR/suspend
+
+ ls -1 $STATE_DIR/profiles/ | while read prof; do
+ cp $STATE_DIR/profiles/$prof $STATE_DIR/suspend/
+ profile_down $prof
+ done
+}
+
+# all_suspend
+# store a list of running profiles and take them down
+#
+all_resume()
+{
+ ls -1 $STATE_DIR/suspend/ | while read prof; do
+ profile_up $prof
+ rm $STATE_DIR/suspend/$prof
+ done
+}
+
+# profile_up profile
+# put all profiles up
+#
+profile_up()
+{
+
+ [[ ! -d $STATE_DIR ]] && mkdir -p $STATE_DIR/{interfaces,profiles}
+
+ load_profile $1 || return 1
+
+ check_profile $1 && err "$1 already connected" && return 1
+
+ # NETWORKS_EXCLUSIVE, rc.conf: Profiles are globally mutually exclusive
+ # EXCLUSIVE, network.d/profile: Individual profile is mutually exclusive
+ if checkyesno $NETWORKS_EXCLUSIVE || checkyesno $EXCLUSIVE; then
+ all_down
+ fi
+
+ stat_busy "$1 up"
+
+ if check_iface $INTERFACE; then
+ if checkyesno $CHECK; then
+ err_append "Interface $INTERFACE already in use"
+ stat_fail && return 1
+ else
+ interface_down $INTERFACE || return 1
+ load_profile $1
+ fi
+ fi
+
+
+ eval $PRE_UP || return 1
+
+ . $CONN_DIR/${CONNECTION}
+ if ! ${CONNECTION}_up $1; then
+ stat_fail
+ return 1
+ fi
+
+ eval $POST_UP || return 1
+
+ set_profile up $1
+ unset EXCLUSIVE
+
+ add_daemon net-profiles
+ stat_done
+}
+
+# profile_down profile
+# take profile down
+#
+profile_down()
+{
+
+ [[ ! -d $STATE_DIR ]] && mkdir -p $STATE_DIR/{interfaces,profiles}
+
+ load_profile $1 || return 1
+
+ if ! check_profile $1; then
+ err "Profile not connected"
+ return 1
+ fi
+
+ stat_busy "$1 down"
+ if [[ "$(get_iface_prof $INTERFACE)" == "external" ]]; then
+ err_append "$interface was connected by another application"
+ stat_fail
+ return 1
+ fi
+
+ eval $PRE_DOWN || return 1
+
+ . $CONN_DIR/${CONNECTION}
+ if ! ${CONNECTION}_down $1; then
+ stat_fail
+ return 1
+ fi
+
+ eval $POST_DOWN || return 1
+
+ set_profile down $1
+ stat_done
+}
+
+# Check if variable is a member of an array
+inarray()
+{
+search=$1
+shift
+for item in $*; do
+ if [[ "$item" == "$search" ]]; then
+ return 0
+ fi
+done
+return 1
+}
+
+quirk() {
+inarray $1 ${QUIRKS[@]}
+return $?
+}
+
+# interface_down interface
+# take interface down
+#
+interface_down()
+{
+ local prof=$(get_iface_prof $1)
+ profile_down $prof
+ return $?
+}
+
+
+### Query functions
+##
+# check_iface interface
+# Return 0 if interface up
+# Return 1 if interface down
+#
+check_iface() {
+ [[ -f $STATE_DIR/interfaces/$1 ]] && return 0
+ return 1
+}
+
+# get_iface_prof interface
+# Echo interface profile and return 0 if up
+# Return 1 if down.
+#
+get_iface_prof() {
+ if check_iface $1; then
+ . $STATE_DIR/interfaces/$1
+ echo $PROFILE
+ else
+ return 1
+ fi
+}
+
+# list_profiles
+# Outputs a list of all profiles
+list_profiles() {
+ find $PROFILE_DIR/ -maxdepth 1 -type f -printf "%f\n"
+}
+
+# check_profile profile
+# Return 0 if profile up
+# Return 1 if profile down
+#
+check_profile() {
+ [[ -f $STATE_DIR/profiles/$1 ]] && return 0
+ return 1
+}
+
+### Status setting functions
+##
+# set_profile up/down profile
+# Set profile state, either up or down
+#
+set_profile() {
+ if [[ "$1" == "up" ]]; then
+ . $PROFILE_DIR/$2
+ cp $PROFILE_DIR/$2 $STATE_DIR/profiles/
+ echo $2 > $STATE_DIR/last_profile
+ set_iface up $INTERFACE $2
+
+ elif [[ "$1" == "down" ]]; then
+ . $STATE_DIR/profiles/$2
+ rm $STATE_DIR/profiles/$2
+ set_iface down $INTERFACE $2
+ fi
+}
+
+# set_iface up/down interface [profile]
+# Set interface status to up/down
+# optionally link it to a profile.
+#
+set_iface() {
+ PROFILE=$3
+ [[ -z "$PROFILE" ]] && PROFILE=external
+ if [[ "$1" == "up" ]]; then
+ echo "PROFILE=$PROFILE" > $STATE_DIR/interfaces/$2
+ elif [[ "$1" == "down" ]]; then
+ rm $STATE_DIR/interfaces/$2
+ fi
+}
+
+
+### From FreeBSD's /etc/rc.subr
+##
+# checkyesno var
+# Test $1 variable, and warn if not set to YES or NO.
+# Return 0 if it's "yes" (et al), nonzero otherwise.
+#
+checkyesno()
+{
+ _value=${1}
+ #debug "checkyesno: $1 is set to $_value."
+ case $_value in
+
+ # "yes", "true", "on", or "1"
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ return 0
+ ;;
+
+ # "no", "false", "off", or "0"
+ [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
+ return 1
+ ;;
+ *)
+ #warn "\$${1} is not set properly - see ${rcvar_manpage}."
+ return 1
+ ;;
+ esac
+}
diff --git a/src/wireless b/src/wireless
new file mode 100644
index 0000000..405b86b
--- /dev/null
+++ b/src/wireless
@@ -0,0 +1,61 @@
+# Uses wireless_tools, to check for association to a network.
+# wep_check interface [timeout]
+wep_check()
+{
+ INTERFACE=$1; TIMEOUT=$2
+
+ [[ -z "$TIMEOUT" ]] && TIMEOUT=15
+ let timeout=0
+ while [[ $timeout -ne $TIMEOUT ]]; do
+ bssid=`iwgetid $INTERFACE -ra`
+ [[ ! "$bssid" = "00:00:00:00:00:00" ]] && return 0
+ sleep 1
+ let timeout++
+ done
+
+ err_append "Wireless association failed"
+ return 1
+}
+
+# Check if a particular network is within range
+# find_essid interface essid
+find_essid()
+{
+ INTERFACE=$1; ESSID=$2; RETRIES=5
+ try=0;
+ while [[ $try -ne $RETRIES ]]; do
+ if iwlist $INTERFACE scan|sed "s/ESSID://g"|grep -q "\"$ESSID\""; then
+ return 0 # network found
+ fi
+ sleep 1
+ let try++
+ done
+ return 1
+}
+
+# Return a filename containing a list of network ESSID's found.
+# list_networks interface
+list_networks()
+{
+ # temp file used, as keeping ESSID's with spaces in their name in arrays
+ # is hard, obscure and kinda nasty. This is simpler and clearer.
+
+ [[ -z "$1" ]] && return 1
+ essids=$(mktemp /tmp/essid.XXXXX)
+
+ let try=0;
+ RETRIES=6;
+ while [[ $try -ne $RETRIES ]]; do
+ iwlist $1 scan 2> /dev/null|grep ESSID|sed 's/.*ESSID:"\([^"]\+\)".*/\1/' > $essids
+ sleep 0.5; let try++
+ done
+ sort -u $essids -o $essids
+
+ # File of 0 length, ie. no ssid's.
+ if [[ ! -s $essids ]]; then
+ return 1
+ fi
+
+ echo $essids
+ return 0
+}