From 85729ed2f7fd06bb1c002625b147ae9eb56e140c Mon Sep 17 00:00:00 2001
From: Bob Mottram <bob@freedombone.net>
Date: Wed, 4 Oct 2017 16:19:57 +0100
Subject: [PATCH] Get secondary wifi adapter working on mesh

---
 src/freedombone-mesh-batman | 185 ++++++++++++++++++++----------------
 src/freedombone-utils-wifi  |   4 +
 2 files changed, 107 insertions(+), 82 deletions(-)

diff --git a/src/freedombone-mesh-batman b/src/freedombone-mesh-batman
index 69b443d09..5d121d284 100755
--- a/src/freedombone-mesh-batman
+++ b/src/freedombone-mesh-batman
@@ -30,7 +30,9 @@
 
 PROJECT_NAME='freedombone'
 COMPLETION_FILE=/root/${PROJECT_NAME}-completed.txt
-HOTSPOT_PASSPHRASE='mesh'
+
+# hotspot passphrase must be 5 characters or longer
+HOTSPOT_PASSPHRASE="${PROJECT_NAME}"
 
 source /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-wifi
 
@@ -114,16 +116,14 @@ function stop {
     fi
     if [ "$EIFACE" ]; then
         brctl delif $BRIDGE bat0
-        brctl delif $BRIDGE $EIFACE
         ifconfig $BRIDGE down || true
+        ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier)
+        if [[ "$ethernet_connected" != "0" ]]; then
+            systemctl stop hostapd
+            brctl delif $BRIDGE $EIFACE
+            ifconfig $EIFACE down -promisc
+        fi
         brctl delbr $BRIDGE
-        ifconfig $EIFACE down -promisc
-    fi
-    if [ $IFACE_SECONDARY ]; then
-        systemctl stop hostapd
-        brctl delif $BRIDGE_HOTSPOT bat0
-        ifconfig $BRIDGE_HOTSPOT down || true
-        brctl delbr $BRIDGE_HOTSPOT
     fi
 
     avahi-autoipd -k $BRIDGE
@@ -131,11 +131,21 @@ function stop {
     ifconfig bat0 down -promisc
 
     batctl if del $IFACE
-    rmmod batman-adv
     ifconfig $IFACE mtu 1500
     ifconfig $IFACE down
     iwconfig $IFACE mode managed
 
+    if [ $IFACE_SECONDARY ]; then
+        systemctl stop hostapd
+        systemctl disable hostapd
+        batctl if del $IFACE_SECONDARY
+        ifconfig $IFACE_SECONDARY mtu 1500
+        ifconfig $IFACE_SECONDARY down
+        iwconfig $IFACE_SECONDARY mode managed
+    fi
+
+    rmmod batman-adv
+
     iptables -D INPUT -p tcp --dport $TRACKER_PORT -j ACCEPT
     iptables -D INPUT -p udp --dport $TRACKER_PORT -j ACCEPT
     iptables -D INPUT -p tcp --dport 80 -j ACCEPT
@@ -205,6 +215,37 @@ function assign_peer_address {
     done
 }
 
+function add_wifi_interface {
+    ifname=$1
+    ifssid=$WIFI_SSID
+    if [ $2 ]; then
+        ifssid=$2
+    fi
+    ifmode=ad-hoc
+    if [ $3 ]; then
+        ifmode=$3
+    fi
+    ifchannel=$CHANNEL
+    if [ $4 ]; then
+        ifchannel=$4
+    fi
+
+    ifconfig $ifname down
+    ifconfig $ifname mtu 1532
+    peermac=$(assign_peer_address)
+    if [ ! $peermac ]; then
+        echo $"Unable to obtain MAC address for $peermac on $ifname"
+        return
+    fi
+    ifconfig $ifname hw ether $peermac
+    echo $"$ifname assigned MAC address $peermac"
+    iwconfig $ifname enc off
+    iwconfig $ifname mode $ifmode essid $ifssid channel $ifchannel
+
+    batctl if add $ifname
+    ifconfig $ifname up
+}
+
 function start {
     if [ -z "$IFACE" ] ; then
         echo 'error: unable to find wifi interface, not enabling batman-adv mesh'
@@ -225,87 +266,67 @@ function start {
     # Might have to re-enable wifi
     rfkill unblock $(rfkill list|awk -F: "/phy/ {print $1}") || true
 
-    ifconfig $IFACE down
-    ifconfig $IFACE mtu 1532
-    peermac=$(assign_peer_address)
-    if [ ! $peermac ]; then
-        echo $"Unable to obtain MAC address for $peermac"
-        return
+    secondary_wifi_available=
+    if [ $IFACE_SECONDARY ]; then
+        if [[ $IFACE != $IFACE_SECONDARY ]]; then
+            if [ -d /etc/hostapd ]; then
+                if [ ${#HOTSPOT_PASSPHRASE} -gt 4 ]; then
+                    secondary_wifi_available=1
+                else
+                    echo $'Hotspot passphrase is too short'
+                fi
+            fi
+        fi
     fi
-    ifconfig $IFACE hw ether $peermac
-    echo $"$IFACE assigned MAC address $peermac"
-    iwconfig $IFACE enc off
-    iwconfig $IFACE mode ad-hoc essid $WIFI_SSID channel $CHANNEL
 
     modprobe batman-adv
-    batctl if add $IFACE
-    ifconfig $IFACE up
+
+    add_wifi_interface $IFACE $WIFI_SSID ad-hoc $CHANNEL
     avahi-autoipd --force-bind --daemonize --wait $IFACE
+
+    # NOTE: Don't connect the secondary wifi device. hostapd will handle that by itself
+
     ifconfig bat0 up promisc
 
+    brctl addbr $BRIDGE
+    brctl addif $BRIDGE bat0
+    ifconfig bat0 0.0.0.0
     if [ "$EIFACE" ] ; then
-        echo $'Trying ethernet bridge to the internet'
-        brctl addbr $BRIDGE
-        brctl addif $BRIDGE bat0
-        brctl addif $BRIDGE $EIFACE
-        ifconfig bat0 0.0.0.0
-        ifconfig $EIFACE 0.0.0.0
-        ifconfig $EIFACE up promisc
-        ifconfig $BRIDGE up
-        dhclient $BRIDGE
-        echo $'End of ethernet bridge'
-    fi
-
-    hotspot_enabled=
-    if [ $IFACE_SECONDARY ]; then
-        if [[ $IFACE != $IFACE_SECONDARY ]]; then
-            if [ -d /etc/hostapd ]; then
-                # bridge between mesh and wifi hotspot for mobile
-                HOTSPOT_NAME=$"${WIFI_SSID}-hotspot"
-                ifconfig $IFACE_SECONDARY down
-                ifconfig $IFACE_SECONDARY mtu 1500
-                CELLID=$(assign_peer_address)
-                if [ $CELLID ]; then
-                    ifconfig $IFACE_SECONDARY hw ether $CELLID
-                    echo $"Secondary wifi adaptor $IFACE_SECONDARY assigned to MAC address $CELLID"
-                    iwconfig $IFACE_SECONDARY enc open
-                    iwconfig $IFACE_SECONDARY mode managed essid $HOTSPOT_NAME channel ${HOTSPOT_CHANNEL}
-                    iwconfig $IFACE_SECONDARY ap $CELLID
-                    iwconfig $IFACE ap $CELLID
-
-                    brctl addbr $BRIDGE_HOTSPOT
-                    brctl addif $BRIDGE_HOTSPOT bat0
-                    brctl addif $BRIDGE_HOTSPOT $IFACE_SECONDARY
-                    ifconfig bat0 0.0.0.0
-                    ifconfig $IFACE_SECONDARY 0.0.0.0
-
-                    sed -i 's|#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|g' /etc/default/hostapd
-
-                    echo "interface=${IFACE_SECONDARY}" > /etc/hostapd/hostapd.conf
-                    echo "bridge=${BRIDGE_HOTSPOT}" >> /etc/hostapd/hostapd.conf
-                    echo 'driver=nl80211' >> /etc/hostapd/hostapd.conf
-                    echo "country_code=UK" >> /etc/hostapd/hostapd.conf
-                    echo "ssid=$HOTSPOT_NAME" >> /etc/hostapd/hostapd.conf
-                    echo 'hw_mode=g' >> /etc/hostapd/hostapd.conf
-                    echo "channel=${HOTSPOT_CHANNEL}" >> /etc/hostapd/hostapd.conf
-                    echo 'wpa=2' >> /etc/hostapd/hostapd.conf
-                    echo "wpa_passphrase=$HOTSPOT_PASSPHRASE" >> /etc/hostapd/hostapd.conf
-                    echo 'wpa_key_mgmt=WPA-PSK' >> /etc/hostapd/hostapd.conf
-                    echo 'wpa_pairwise=TKIP' >> /etc/hostapd/hostapd.conf
-                    echo 'rsn_pairwise=CCMP' >> /etc/hostapd/hostapd.conf
-                    echo 'auth_algs=1' >> /etc/hostapd/hostapd.conf
-                    echo 'macaddr_acl=0' >> /etc/hostapd/hostapd.conf
-
-                    ifconfig $BRIDGE_HOTSPOT up
-                    avahi-autoipd --force-bind --daemonize --wait $BRIDGE_HOTSPOT
-                    ifconfig $IFACE_SECONDARY up promisc
-                    #ifconfig $IFACE_SECONDARY auto-dhcp start
-                    systemctl start hostapd
-                    hotspot_enabled=1
-                fi
-            fi
+        ethernet_connected=$(cat /sys/class/net/$EIFACE/carrier)
+        if [[ "$ethernet_connected" != "0" ]]; then
+            echo $'Trying ethernet bridge to the internet'
+            brctl addif $BRIDGE $EIFACE
+            ifconfig $EIFACE 0.0.0.0
+            ifconfig $EIFACE up promisc
+            echo $'End of ethernet bridge'
+        else
+            echo $"$EIFACE is not connected"
         fi
     fi
+    ifconfig $BRIDGE up
+    dhclient $BRIDGE
+
+    if [ $secondary_wifi_available ]; then
+        sed -i 's|#DAEMON_CONF=.*|DAEMON_CONF="/etc/hostapd/hostapd.conf"|g' /etc/default/hostapd
+
+        echo "interface=${IFACE_SECONDARY}" > /etc/hostapd/hostapd.conf
+        echo "bridge=${BRIDGE}" >> /etc/hostapd/hostapd.conf
+        echo 'driver=nl80211' >> /etc/hostapd/hostapd.conf
+        echo "country_code=UK" >> /etc/hostapd/hostapd.conf
+        echo "ssid=${WIFI_SSID}-${HOSTNAME}" >> /etc/hostapd/hostapd.conf
+        echo 'hw_mode=g' >> /etc/hostapd/hostapd.conf
+        echo "channel=${HOTSPOT_CHANNEL}" >> /etc/hostapd/hostapd.conf
+        echo 'wpa=2' >> /etc/hostapd/hostapd.conf
+        echo "wpa_passphrase=$HOTSPOT_PASSPHRASE" >> /etc/hostapd/hostapd.conf
+        echo 'wpa_key_mgmt=WPA-PSK' >> /etc/hostapd/hostapd.conf
+        echo 'wpa_pairwise=TKIP' >> /etc/hostapd/hostapd.conf
+        echo 'rsn_pairwise=CCMP' >> /etc/hostapd/hostapd.conf
+        echo 'auth_algs=1' >> /etc/hostapd/hostapd.conf
+        echo 'macaddr_acl=0' >> /etc/hostapd/hostapd.conf
+
+        systemctl enable hostapd
+        systemctl restart hostapd
+    fi
 
     iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
     iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
diff --git a/src/freedombone-utils-wifi b/src/freedombone-utils-wifi
index 2e3bfb387..dc7aa34ff 100755
--- a/src/freedombone-utils-wifi
+++ b/src/freedombone-utils-wifi
@@ -215,6 +215,10 @@ function update_wifi_adaptors {
     IFACE=
     IFACE_SECONDARY=
 
+    for i in $(seq 10 -1 0); do
+        ifdown --force wlan${i}
+    done
+
     for i in $(seq 10 -1 0); do
         if grep -q "wlan${i}" /proc/net/dev; then
             if [ ! $IFACE ]; then
-- 
GitLab