netcardconfig: don't fail with bash >=4.4 when scanning for networks
[grml-network.git] / sbin / netcardconfig
index 0107ab1..c9dd5a9 100755 (executable)
@@ -4,7 +4,6 @@
 # Authors:       Michael Prokop <mika@grml.org>, Marcel Wichern 2006, Klaus Knopper 2002, Niall Walsh + Stefan Lippers-Hollmann 2004-2007
 # Bug-Reports:   see http://grml.org/bugs/
 # License:       This file is licensed under the GPL v2.
-# Latest change: Sam Jän 27 19:28:54 CET 2007 [mika]
 ################################################################################
 # Changes have been merged from Kanotix's and Sidux's netcardconfig:
 # http://kanotix.com/files/debian/pool/main/n/netcardconfig-kanotix/
@@ -16,7 +15,7 @@ LANGUAGE=C LANG=C
 export PATH LANGUAGE LANG
 
 . /etc/grml/script-functions
-check4root
+check4root || exit 1
 
 TMP=$(mktemp)
 
@@ -82,6 +81,32 @@ writeiwline() {
   #echo "DEBUG: for interfaces $IWOURLINE"
 }
 
+generate_udev_entry() {
+  interface=''
+  mkdir -p /etc/udev/scripts
+  echo "# Auto generated script from netcardconfig on $(date)
+# Executing this script generates an entry in /etc/udev/rules.d/z25_persistent-net.rules
+# for you, please check z25_persistent-net.rules for existing entries before
+# running this script (once more)." > /etc/udev/scripts/netcardconfig
+  for interface in `ifconfig | awk '/^[a-z]/ &&!/^lo/{ print $1} '` ; do
+      echo -n "INTERFACE=$interface /lib/udev/write_net_rules " >> /etc/udev/scripts/netcardconfig && \
+      if which udevadm >/dev/null 2>&1; then
+        udevadm info -a -p /sys/class/net/$interface | awk -F'==' '/address/ {print $2}' >> /etc/udev/scripts/netcardconfig
+      else
+        udevinfo -a -p /sys/class/net/$interface | awk -F'==' '/address/ {print $2}' >> /etc/udev/scripts/netcardconfig
+      fi
+  done
+  # send errors to /dev/null as well because the sed line inside the /lib/udev/write_net_rules
+  # script outputs a sed warning which might unsettle users
+  chmod +x /etc/udev/scripts/netcardconfig && /etc/udev/scripts/netcardconfig 1>/dev/null 2>&1
+}
+
+disable_config_dhcp() {
+  if grep -q CONFIG_DHCP /etc/grml/autoconfig ; then
+     sed -i "s|^CONFIG_DHCP.*|CONFIG_DHCP='no'|" /etc/grml/autoconfig
+  fi
+}
+
 device2props() {
   PARTCOUNT=0
   isauto=0
@@ -126,11 +151,25 @@ remauto(){
   fi
 }
 
+scanwlan(){
+  i=0
+  ifconfig $DV up
+  iwlist $DV scanning | grep "ESSID\|Quality" | sed -e "s/^.*ESSID:\"\|\"$//g" | tac > "$TMP"
+  while read line
+  do
+    WARRAY[i++]=$line
+  done < "$TMP"
+  unset i
+  rm -f "$TMP"
+}
+
 configiface() {
   [ ! -r /etc/network/interfaces ] && touch /etc/network/interfaces
   DEVICE=${NETDEVICES[$DV]}
   device2props
   DV=$DEVICENAME
+  ifdown $DV
+  sleep 3
   # wireless config
   WLDEVICE="$(LANG=C LC_MESSAGEWS=C iwconfig $DV 2>/dev/null | awk '/802\.11|READY|ESSID/{print $1}')"
   WLDEVICECOUNT="$(LANG=C LC_MESSAGEWS=C iwconfig $DV 2>/dev/null | wc -l)"
@@ -215,23 +254,50 @@ configiface() {
       rm -f "$TMP"
     fi
 
-    $DIALOG --inputbox "$MESSAGEW4 $DEVICENAME $MESSAGEW5" 15 50 "$ESSID" 2>"$TMP" || bailout 1
-    read ESSID <"$TMP" ; rm -f "$TMP"
-    [ -z "$ESSID" ] && ESSID="any"
+    # ask to scan or manually set wireless network
+    if $DIALOG --yesno "$MESSAGEWSCAN1" 8 45 ; then
+      RESCAN=1
+
+      while [ $RESCAN -eq 1 ]
+      do
+        scanwlan
+        $DIALOG --extra-button --extra-label "Rescan" --menu "$MESSAGEWSCAN2" 20 70 15 "${WARRAY[@]}" 2>"$TMP"
+        case $? in
+          0)
+            RESCAN=0
+            ;;
+          3)
+            ;;
+          *)
+            bailout 1
+            ;;
+        esac
+      done
+
+      read ESSID <"$TMP" ; rm -f "$TMP"
+      [ -z "$MODE" ] && MODE="Managed"
+
+    else
+
+      $DIALOG --inputbox "$MESSAGEW4 $DEVICENAME $MESSAGEW5" 15 50 "$ESSID" 2>"$TMP" || bailout 1
+      read ESSID <"$TMP" ; rm -f "$TMP"
+      [ -z "$ESSID" ] && ESSID="any"
+
+      $DIALOG --inputbox "$MESSAGEW6 $DEVICENAME $MESSAGEW7" 15 50 "$NWID" 2>"$TMP" || bailout 1
+      read NWID <"$TMP" ; rm -f "$TMP"
 
-    $DIALOG --inputbox "$MESSAGEW6 $DEVICENAME $MESSAGEW7" 15 50 "$NWID" 2>"$TMP" || bailout 1
-    read NWID <"$TMP" ; rm -f "$TMP"
+      $DIALOG --inputbox "$MESSAGEW8 $DEVICENAME $MESSAGEW9" 15 50 "$MODE" 2>"$TMP" || bailout 1
+      read MODE <"$TMP" ; rm -f "$TMP"
+      [ -z "$MODE" ] && MODE="Managed"
 
-    $DIALOG --inputbox "$MESSAGEW8 $DEVICENAME $MESSAGEW9" 15 50 "$MODE" 2>"$TMP" || bailout 1
-    read MODE <"$TMP" ; rm -f "$TMP"
-    [ -z "$MODE" ] && MODE="Managed"
+      $DIALOG --inputbox "$MESSAGEW10 $DEVICENAME $MESSAGEW11" 15 50 "$CHANNEL" 2>"$TMP" || bailout 1
+      read CHANNEL <"$TMP" ; rm -f "$TMP"
 
-    $DIALOG --inputbox "$MESSAGEW10 $DEVICENAME $MESSAGEW11" 15 50 "$CHANNEL" 2>"$TMP" || bailout 1
-    read CHANNEL <"$TMP" ; rm -f "$TMP"
+      if [ -z "$CHANNEL" ]; then
+        $DIALOG --inputbox "$MESSAGEW12 $DEVICENAME $MESSAGEW13" 15 50 "$FREQ" 2>"$TMP" || bailout 1
+        read FREQ <"$TMP" ; rm -f "$TMP"
+      fi
 
-    if [ -z "$CHANNEL" ]; then
-      $DIALOG --inputbox "$MESSAGEW12 $DEVICENAME $MESSAGEW13" 15 50 "$FREQ" 2>"$TMP" || bailout 1
-      read FREQ <"$TMP" ; rm -f "$TMP"
     fi
 
     WPAON=0
@@ -300,10 +366,17 @@ configiface() {
                           }
                   }
                   ' /etc/network/interfaces)
-          $DIALOG --inputbox "$MESSAGEW23 $ESSID" 15 50 "$WPASECRET" 2>"$TMP" || bailout 1
-
-          # make sure backslashes inside passphrase are handled correct
-          WPASECRET=$(sed -e 's/\\/\\/g' "$TMP") && rm -r "$TMP"
+          FIRST_RUN=0  # show the wpasecret input box at least once
+          while ( [ -z "$WPASECRET" ] || [ "$FIRST_RUN" ] ) ; do
+            $DIALOG --inputbox "$MESSAGEW23 $ESSID" 15 50 "$WPASECRET" 2>"$TMP" || bailout 1
+            read WPASECRET <"$TMP"
+            if [ -z "$WPASECRET" ] ; then
+              $DIALOG --msgbox "Sorry, empty password not allowed, please retry." 0 0 || bailout 1
+            fi
+            FIRST_RUN=""
+          done
+
+          rm -f "$TMP"
 
           case $WPA_DEV in
                hostap)
@@ -364,9 +437,9 @@ configiface() {
         /netmask/{if(found){netmask=$NF}}
         /broadcast/{if(found){broadcast=$NF}}
         /gateway/{if(found){gateway=$NF}}
-        /dns-nameservers/{if(found){dns-nameservers=$NF}}
-        END{print address" "netmask" "broadcast" "gateway" "dns-nameservers}' /etc/network/interfaces >"$TMP"
-      read IP NM BC DG <"$TMP"
+        /dns-nameservers/{if(found){dnsnameservers=$NF}}
+        END{print address" "netmask" "broadcast" "gateway" "dnsnameservers}' /etc/network/interfaces >"$TMP"
+      read IP NM BC DG NS <"$TMP"
       rm -f "$TMP"
     fi
 
@@ -379,14 +452,14 @@ configiface() {
     $DIALOG --inputbox "$MESSAGE8 $DV" 10 45 "${BC:-${IP%.*}.255}" 2>"$TMP" || bailout 1
     read BC <"$TMP" ; rm -f "$TMP"
 
-    $DIALOG --inputbox "$MESSAGE9" 10 45 "${DG:-${IP%.*}.254}" 2>"$TMP"
+    $DIALOG --inputbox "$MESSAGE9" 10 45 "${DG:-${IP%.*}.1}" 2>"$TMP"
     read DG <"$TMP" ; rm -f "$TMP"
 
     if [ -f "/etc/resolv.conf" ]; then
       NS="$(awk '/^nameserver/{printf "%s ",$2}' /etc/resolv.conf)"
     fi
 
-    $DIALOG --inputbox "$MESSAGE10" 10 45 "${NS:-${IP%.*}.254}" 2>"$TMP"
+    $DIALOG --inputbox "$MESSAGE10" 10 45 "${NS:-$DG}" 2>"$TMP"
     read NS <"$TMP" ; rm -f "$TMP"
 
     if [ -w /etc/network/interfaces ]; then
@@ -453,12 +526,29 @@ MESSAGEW22="Enable WPA support?"
 MESSAGEW23="Enter the WPA passphrase (passphrase must be 8..63 characters) for"
 MESSAGEW25="Would you like to store your wep key in it's own private file ("
 MESSAGEW26=")?   If you say no, your wep key will be stored in /etc/network/interfaces and will be readable by any account on your system.  You may want to 'chmod 600 /etc/network/interfaces' if you answer no to this question"
-
+MESSAGEWSCAN1="Scan for available wireless networks?"
+MESSAGEWSCAN2="Please choose a wireless network from below:"
 
 NETDEVICESCOUNT=0
-LAN=$(tail -n +3 /proc/net/dev|awk -F: '{print $1}'|sed "s/\s*//"|grep -v -e ^lo -e ^vmnet|sort)
-[ -n "$WLAN" ] || WLAN=$(tail -n +3 /proc/net/wireless 2>/dev/null|awk -F: '{print $1}'|sort)
-unset LAN_DEVICES WLAN_DEVICES FIREWIRE_DEVICES NETDEVICES
+if [ -r /proc/net/dev ] ; then
+   LAN=$(tail -n +3 /proc/net/dev | awk -F: '{print $1}'| sed "s/\s*//" | grep -v -e ^lo -e ^vmnet | sort)
+else
+   LAN=""
+fi
+
+if [ -z "$WLAN" ] ; then
+  WLAN_OLD=$(tail -n +3 /proc/net/wireless 2>/dev/null|awk -F: '{print $1}')
+  # /proc/net/wireless does not work e.g. with iwl3945 on kernel 2.6.33 anymore
+  WLAN_NEW=$(for i in /sys/class/net/* ; do ( [ -d $i/wireless ] || [ -d $i/phy80211 ] ) && basename $i ; done)
+  set -a WLAN_IWCONFIG
+  for DEV in $LAN ; do
+    iwconfig $DEV 2>/dev/null 1>&2 && WLAN_IWCONFIG+=($DEV)
+  done
+  WLAN=$(echo $WLAN_OLD $WLAN_NEW ${WLAN_IWCONFIG[@]} | tr ' ' '\n' | sort -u)
+fi
+
+unset LAN_DEVICES WLAN_DEVICES FIREWIRE_DEVICES NETDEVICES WLAN_IWCONFIG
+
 while read dev mac; do
 #echo "Making NETDEVICES $NETDEVICESCOUNT $dev"
   iswlan=$(echo $dev $WLAN|tr ' ' '\n'|sort|uniq -d)
@@ -480,7 +570,7 @@ while read dev mac; do
   fi
 #echo "Made to ${NETDEVICES[$NETDEVICESCOUNT]}"
   ((NETDEVICESCOUNT++))
-done < <(ifconfig -a|grep Ethernet|grep -v ^vmnet|awk '! /^\s/{print $1" "$5}')
+done < <(ip link show | awk ' !/^\s/{sub(/:/,"",$2);IFACE=$2} /link.ether/{if (IFACE !~/^vmnet/) print IFACE" "$2}')
 for dev in $LAN; do
   if [ "$(ethtool -i $dev 2>/dev/null|awk '/^bus-info:/{print $2}')" == "ieee1394" ]; then
     isauto="0"
@@ -535,12 +625,18 @@ while (true); do
   IFACEDONE=""
   while [ -n "$DV" -a -z "$IFACEDONE" ]; do
     configiface
-    ifdown $DV
-    sleep 3
     if ! ifup $DV; then
       $DIALOG --yesno "$MESSAGE14" 15 50 || IFACEDONE="DONE"
     else
-      $DIALOG --yesno "$MESSAGE15" 15 50 && addauto || remauto
+      if $DIALOG --yesno "$MESSAGE15" 12 50 ; then
+         addauto
+         # get persistent interface names across reboots
+         generate_udev_entry
+        # make sure we don't run the dhcp stuff when using /etc/network/interfaces
+        disable_config_dhcp
+      else
+         remauto
+      fi
       IFACEDONE="DONE"
     fi
   done