Support uplink network management when two wlan devices are available
authorJoey Schulze <joey@infodrom.org>
Wed, 4 Mar 2020 13:23:04 +0000 (14:23 +0100)
committerJoey Schulze <joey@infodrom.org>
Wed, 4 Mar 2020 13:23:04 +0000 (14:23 +0100)
bin/musiikki-essid [new file with mode: 0755]
bin/musiikki-wlan [new file with mode: 0755]
class/ajax.class.php
config-templates/musiikki.conf.template
html/admin/admin.js
install-system
templates/admin.phtml
templates/network.phtml [new file with mode: 0644]

diff --git a/bin/musiikki-essid b/bin/musiikki-essid
new file mode 100755 (executable)
index 0000000..8988383
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+
+uplink=$(grep ^uplink= /etc/musiikki.conf|sed 's/.*=\(.*\)/\1/')
+
+if [ -z "$uplink" ]
+then
+    exit
+fi
+
+read name
+read essid
+read password
+
+logger -t musiikki "New ESSID $essid"
+
+ifdown ${uplink} > /dev/null 2>&1
+
+rm -f /etc/network/interfaces.d/uplink.conf
+
+cat <<EOS > /etc/network/interfaces.d/upstream_${name}.conf
+auto ${uplink}
+iface ${uplink} inet dhcp
+   wpa-driver wext
+   wpa-scan-ssid 1
+   wpa-proto WPA RSN
+   wpa-key-mgmt WPA-PSK
+   wpa-pairwise CCMP TKIP
+   wpa-group CCMP TKIP
+   wpa-ssid ${essid}
+   wpa-psk ${psk}
+   up iptables-restore < /srv/musiikki/iptables_nat.conf
+EOS
+
+cd /etc/network/interfaces.d
+ln -s upstream_${name}.conf uplink.conf
+ifup ${uplink} > /dev/null 2>&1
diff --git a/bin/musiikki-wlan b/bin/musiikki-wlan
new file mode 100755 (executable)
index 0000000..e8c416c
--- /dev/null
@@ -0,0 +1,25 @@
+#! /bin/sh
+
+PATH=/sbin:$PATH
+
+uplink=$(grep ^uplink= /etc/musiikki.conf|sed 's/.*=\(.*\)/\1/')
+
+if [ -z "$uplink" ]
+then
+    exit
+fi
+
+read wlan
+
+logger -t musiikki "WLAN: $wlan"
+
+ifdown ${uplink} > /dev/null 2>&1
+
+rm -f /etc/network/interfaces.d/uplink.conf
+
+if [ -n "$wlan" ]
+then
+    cd /etc/network/interfaces.d
+    ln -s upstream_${wlan}.conf uplink.conf
+    ifup ${uplink} > /dev/null 2>&1
+fi
index ec34f5e..45bf06e 100644 (file)
@@ -69,6 +69,66 @@ class AJAX {
        return $ok;
     }
 
        return $ok;
     }
 
+    public static function getnetworkAction()
+    {
+       $name = NULL;
+       $conf = '/etc/network/interfaces.d/uplink.conf';
+       if (file_exists($conf)) {
+           $dest = readlink($conf);
+           $name = substr($dest, 9, -5);
+       }
+
+       $upstream = [];
+       foreach (new DirectoryIterator(dirname($conf)) as $fileInfo) {
+           if (substr($fileInfo->getBasename(), 0, 9) != 'upstream_') continue;
+           $upstream[] = substr($fileInfo->getBasename('.conf'), 9);
+       }
+       sort($upstream);
+
+       $ip = NULL;
+       $lines = [];
+       $f = popen("ip -f inet addr show wlan0", 'r');
+       while (($line = fgets($f)) !== false)
+           $lines[] = rtrim($line);
+       pclose($f);
+       if (count($lines)) {
+           if (preg_match('/inet (\d+\.\d+\.\d+\.\d+)\/.*/', $lines[1], $matches))
+               $ip = $matches[1];
+       }
+
+       $networks = [];
+       $f = popen("iwlist wlan0 scan", 'r');
+       while (($line = fgets($f)) !== false) {
+           if (preg_match('/ESSID:"(.*?)"/', $line, $matches))
+               if (strlen($matches[1]))
+                   $networks[] = $matches[1];
+       }
+       pclose($f);
+       sort($networks);
+
+       return ['name' => $name,
+               'ip' => $ip,
+               'networks' => $networks,
+               'upstream' => $upstream];
+    }
+
+    public static function networkAction()
+    {
+       $ok = self::callCommand("super musiikki-wlan", array($_POST['wlan']));
+
+       return $ok;
+    }
+
+    public static function essidAction()
+    {
+       if (!preg_match('/^[A-Za-z0-9_-]+$/', $_POST['name']))
+           return;
+
+       $ok = self::callCommand("super musiikki-essid", array($_POST['name'], $_POST['essid'], $_POST['psk']));
+
+       return $ok;
+    }
+
     public static function getsharesAction()
     {
        return array('ro_name' => '\\\\' . $_SERVER['SERVER_ADDR'] .'\\'. Config::SHARE_READ,
     public static function getsharesAction()
     {
        return array('ro_name' => '\\\\' . $_SERVER['SERVER_ADDR'] .'\\'. Config::SHARE_READ,
@@ -110,6 +170,7 @@ class AJAX {
 
     public static function haltAction()
     {
 
     public static function haltAction()
     {
+       $ok = self::callCommand("super musiikki-wlan", array(''));
        $ok = self::callCommand("super musiikki-halt");
 
        return $ok;
        $ok = self::callCommand("super musiikki-halt");
 
        return $ok;
index 16b2bae..9bf6341 100644 (file)
@@ -26,3 +26,8 @@ favicon=/favicon.ico
 #
 password={htpasswd}
 
 #
 password={htpasswd}
 
+# Uplink WLAN interface
+#
+# Warning: wlan0/wlan1 could be mixed up
+#
+#uplink=wlan1
index 44838b3..8b9b2ec 100644 (file)
@@ -61,3 +61,57 @@ function submit_halt() {
 
     return false;
 }
 
     return false;
 }
+
+function network_process(data)
+{
+    if (data.ip === null)
+       $('#network h1:nth-child(1) b').text('WLAN.');
+    else
+       $('#network h1:nth-child(1) b').text(data.ip);
+
+    $('#network select[name="wlan"]').empty();
+    var option = $('<option value="">-- select --</option>');
+    $('#network select[name="wlan"]').append(option);
+    for (var i=0; i < data.upstream.length; i++) {
+       var option = $('<option value="'+data.upstream[i]+'">'+data.upstream[i]+'</option>');
+       if (data.name !== null && data.name == data.upstream[i]) option.attr('selected','selected');
+       $('#network select[name="wlan"]').append(option);
+    }
+
+    $('#network select[name="essid"]').empty();
+    var option = $('<option value="">-- select --</option>');
+    $('#network select[name="essid"]').append(option);
+    for (var i=0; i < data.networks.length; i++) {
+       var option = $('<option value="'+data.networks[i]+'">'+data.networks[i]+'</option>');
+       $('#network select[name="essid"]').append(option);
+    }
+
+    $('#network input[name="name"]').val('');
+    $('#network input[name="psk"]').val('');
+}
+
+function submit_network()
+{
+    $.post('index.php',
+          'action=network&wlan=' + $('#network select[name="wlan"]').val());
+    response('Netzwerk gespeichert.');
+
+    return false;
+}
+
+function submit_essid()
+{
+    if (!$('#network input[name="name"]').val().length) return false;
+    if (!$('#network select[name="essid"]').val().length) return false;
+    if (!$('#network input[name="psk"]').val().length) return false;
+
+    $.post('index.php',
+          'action=essid&' + $('div.w3-container#network form#new_essid').serialize());
+    response('Netzwerk gespeichert.');
+
+    return false;
+}
+
+$(function(){
+    register_callback('network', network_process);
+});
index 710319e..1696cd1 100755 (executable)
@@ -371,6 +371,28 @@ assert_hostapd()
     fi
 }
 
     fi
 }
 
+assert_network()
+{
+    if ! grep -q '^source /etc/network/interfaces.d/wlan1.conf' /etc/network/interfaces
+    then
+       echo >> /etc/network/interfaces
+       echo 'source /etc/network/interfaces.d/wlan1.conf' >> /etc/network/interfaces
+       echo >> /etc/network/interfaces
+    fi
+
+    sed -i 's!#net.ipv4.ip_forward=1!net.ipv4.ip_forward=1!' /etc/sysctl.conf
+    if ! grep -q '^net.ipv4.ip_forward=1' /etc/sysctl.conf
+    then
+       echo >> /etc/sysctl.conf
+       echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
+    fi
+
+    # iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
+    # iptables -A FORWARD -i wlan0 -o wlan1 -m state --state RELATED,ESTABLISHED -j ACCEPT
+    # iptables -A FORWARD -i wlan1 -o wlan0 -j ACCEPT
+    # iptables-save > /srv/musiikki/iptables_nat.conf
+}
+
 assert_dhcpd()
 {
     assert_system_subnet
 assert_dhcpd()
 {
     assert_system_subnet
@@ -547,6 +569,7 @@ assert_packages || exit 2
 
 assert_musiikki
 assert_hostapd
 
 assert_musiikki
 assert_hostapd
+assert_network
 assert_dhcpd
 assert_super
 assert_minidlna
 assert_dhcpd
 assert_super
 assert_minidlna
index f704e5c..8880788 100644 (file)
@@ -26,6 +26,7 @@
     <a href="/" class="w3-bar-item w3-button w3-hover-white">Public</a>
     <a href="#" onclick="open_page('datetime')" class="w3-bar-item w3-button w3-hover-white">Date/Time</a>
     <a href="#" onclick="open_page('wifi')" class="w3-bar-item w3-button w3-hover-white">WiFi</a>
     <a href="/" class="w3-bar-item w3-button w3-hover-white">Public</a>
     <a href="#" onclick="open_page('datetime')" class="w3-bar-item w3-button w3-hover-white">Date/Time</a>
     <a href="#" onclick="open_page('wifi')" class="w3-bar-item w3-button w3-hover-white">WiFi</a>
+    <a href="#" onclick="open_page('network')" class="w3-bar-item w3-button w3-hover-white">Network</a>
     <a href="#" onclick="open_page('shares')" class="w3-bar-item w3-button w3-hover-white">Shares</a>
     <a href="#" onclick="open_page('rescan')" class="w3-bar-item w3-button w3-hover-white">Rescan</a>
     <a href="#" onclick="open_page('passwd')" class="w3-bar-item w3-button w3-hover-white">Admin</a>
     <a href="#" onclick="open_page('shares')" class="w3-bar-item w3-button w3-hover-white">Shares</a>
     <a href="#" onclick="open_page('rescan')" class="w3-bar-item w3-button w3-hover-white">Rescan</a>
     <a href="#" onclick="open_page('passwd')" class="w3-bar-item w3-button w3-hover-white">Admin</a>
@@ -48,6 +49,7 @@
 <?php echo Template::html('home'); ?>
 <?php echo Template::html('datetime'); ?>
 <?php echo Template::html('wifi'); ?>
 <?php echo Template::html('home'); ?>
 <?php echo Template::html('datetime'); ?>
 <?php echo Template::html('wifi'); ?>
+<?php echo Template::html('network'); ?>
 <?php echo Template::html('shares'); ?>
 <?php echo Template::html('passwd'); ?>
 <?php echo Template::html('rescan'); ?>
 <?php echo Template::html('shares'); ?>
 <?php echo Template::html('passwd'); ?>
 <?php echo Template::html('rescan'); ?>
diff --git a/templates/network.phtml b/templates/network.phtml
new file mode 100644 (file)
index 0000000..a0dc449
--- /dev/null
@@ -0,0 +1,29 @@
+<!-- Network -->
+<div class="w3-container" id="network" style="margin-top:75px" data-fetch="true" style="display:none;">
+  <h1 class="w3-xlarge w3-text-blue"><b>WLAN.</b></h1>
+  <hr style="width:50px;border:5px solid blue" class="w3-round">
+  <form>
+    <div class="w3-section">
+      <label>Upstream WLAN</label>
+      <select class="w3-input w3-border" name="wlan" requiblue=""></select>
+    </div>
+    <button type="submit" class="w3-button w3-block w3-padding-large w3-blue w3-margin-bottom" onclick="return submit_network()">Auswählen</button>
+  </form>
+  <div style="margin-bottom:4rem;"></div>
+  <h1 class="w3-xlarge w3-text-blue"><b>New Network.</b></h1>
+  <form id="new_essid">
+    <div class="w3-section">
+      <label>New Name</label>
+      <input class="w3-input w3-border" name="name" requiblue="" type="text">
+    </div>
+    <div class="w3-section">
+      <label>Available Networks</label>
+      <select class="w3-input w3-border" name="essid" requiblue=""></select>
+    </div>
+    <div class="w3-section">
+      <label>WLAN Code</label>
+      <input class="w3-input w3-border" name="psk" requiblue="" type="text">
+    </div>
+    <button type="submit" class="w3-button w3-block w3-padding-large w3-blue w3-margin-bottom" onclick="return submit_essid()">Speichern</button>
+  </form>
+</div>