Skip to content

Commit

Permalink
Merge pull request #1443 from RaspAP/feat/iw-parser
Browse files Browse the repository at this point in the history
Refactor ISO countries + create IW parsing class
  • Loading branch information
billz authored Nov 7, 2023
2 parents b24c0ff + f131c84 commit fbec450
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 367 deletions.
37 changes: 4 additions & 33 deletions ajax/networking/get_frequencies.php
Original file line number Diff line number Diff line change
@@ -1,43 +1,14 @@
<?php

require '../../includes/csrf.php';
require_once '../../includes/config.php';
require_once '../../includes/locale.php';
require '../../src/RaspAP/Parsers/IwParser.php';

if (isset($_POST['interface'])) {

define( 'NL80211_BAND_24GHZ', 0x1 );
define( 'NL80211_BAND_5GHZ', 0x2 );
$iface = escapeshellcmd($_POST['interface']);
$flags = 0;
$parser = new \RaspAP\Parsers\IwParser($iface);
$supportedFrequencies = $parser->parseIwInfo($iface);

// get physical device for selected interface
exec("iw dev | awk -v iface=".$iface." '/^phy#/ { phy = $0 } $1 == \"Interface\" { interface = $2 } interface == iface { print phy }'", $return);
$phy = $return[0];

// get frequencies supported by device
exec('iw '.$phy.' info | sed -rn "s/^.*\*\s([0-9]{4})\sMHz.*/\1/p"', $frequencies);

if (count(preg_grep('/^24[0-9]{2}/i', $frequencies)) >0) {
$flags += NL80211_BAND_24GHZ;
}
if (count(preg_grep('/^5[0-9]{3}/i', $frequencies)) >0) {
$flags += NL80211_BAND_5GHZ;
}

switch ($flags) {
case NL80211_BAND_24GHZ:
$msg = sprintf(_("The selected interface (%s) has support for the 2.4 GHz wireless band only."), $iface);
break;
case NL80211_BAND_5GHZ:
$msg = sprintf(_("The selected interface (%s) has support for the 5 GHz wireless band only."), $iface);
break;
case NL80211_BAND_24GHZ | NL80211_BAND_5GHZ:
$msg = sprintf(_("The selected interface (%s) has support for both the 2.4 and 5 GHz wireless bands."), $iface);
break;
default:
$msg = sprintf(_("The selected interface (%s) does not support wireless mode operation."), $iface);
}
echo json_encode($msg);
echo json_encode($supportedFrequencies);
}

43 changes: 43 additions & 0 deletions ajax/networking/get_nl80211_band.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

require '../../includes/csrf.php';
require_once '../../includes/config.php';
require_once '../../includes/locale.php';

if (isset($_POST['interface'])) {

define( 'NL80211_BAND_24GHZ', 0x1 );
define( 'NL80211_BAND_5GHZ', 0x2 );
$iface = escapeshellcmd($_POST['interface']);
$flags = 0;

// get physical device for selected interface
exec("iw dev | awk -v iface=".$iface." '/^phy#/ { phy = $0 } $1 == \"Interface\" { interface = $2 } interface == iface { print phy }'", $return);
$phy = $return[0];

// get frequencies supported by device
exec('iw '.$phy.' info | sed -rn "s/^.*\*\s([0-9]{4})\sMHz.*/\1/p"', $frequencies);

if (count(preg_grep('/^24[0-9]{2}/i', $frequencies)) >0) {
$flags += NL80211_BAND_24GHZ;
}
if (count(preg_grep('/^5[0-9]{3}/i', $frequencies)) >0) {
$flags += NL80211_BAND_5GHZ;
}

switch ($flags) {
case NL80211_BAND_24GHZ:
$msg = sprintf(_("The selected interface (%s) has support for the 2.4 GHz wireless band only."), $iface);
break;
case NL80211_BAND_5GHZ:
$msg = sprintf(_("The selected interface (%s) has support for the 5 GHz wireless band only."), $iface);
break;
case NL80211_BAND_24GHZ | NL80211_BAND_5GHZ:
$msg = sprintf(_("The selected interface (%s) has support for both the 2.4 and 5 GHz wireless bands."), $iface);
break;
default:
$msg = sprintf(_("The selected interface (%s) does not support wireless mode operation."), $iface);
}
echo json_encode($msg);
}

2 changes: 1 addition & 1 deletion app/css/custom.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
background-color: #fff;
}

.btn-primary.disabled {
.btn-primary:disabled {
color: <?php echo $color; ?> !important;
border-color: <?php echo $color; ?> !important;
background-color: #fff !important;
Expand Down
98 changes: 57 additions & 41 deletions app/js/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ function contentLoaded() {
setupBtns();
break;
case "hostapd_conf":
loadChannel();
getChannel();
setHardwareModeTooltip();
break;
case "dhcpd_conf":
Expand Down Expand Up @@ -264,13 +264,6 @@ function setDHCPToggles(state) {
$('#dhcp-iface').prop('disabled', !state);
}

function loadChannel() {
$.get('ajax/networking/get_channel.php',function(data){
jsonData = JSON.parse(data);
loadChannelSelect(jsonData);
});
}

$('#debugModal').on('shown.bs.modal', function (e) {
var csrfToken = $('meta[name=csrf_token]').attr('content');
$.post('ajax/system/sys_debug.php',{'csrf_token': csrfToken},function(data){
Expand Down Expand Up @@ -391,53 +384,76 @@ $(".custom-file-input").on("change", function() {
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
});

// Retrieves the 'channel' value specified in hostapd.conf
function getChannel() {
$.get('ajax/networking/get_channel.php',function(data){
jsonData = JSON.parse(data);
loadChannelSelect(jsonData);
});
}

/*
Sets the wirelss channel select options based on hw_mode and country_code.
Methodology: In North America up to channel 11 is the maximum allowed WiFi 2.4Ghz channel,
except for the US that allows channel 12 & 13 in low power mode with additional restrictions.
Canada allows channel 12 in low power mode. Because it's unsure if low powered mode can be
supported the channels are not selectable for those countries. Also Uzbekistan and Colombia
allow up to channel 11 as maximum channel on the 2.4Ghz WiFi band.
Source: https://en.wikipedia.org/wiki/List_of_WLAN_channels
Additional: https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
Sets the wirelss channel select options based on frequencies reported by iw.
See: https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
Also: https://en.wikipedia.org/wiki/List_of_WLAN_channels
*/
function loadChannelSelect(selected) {
// Fetch wireless regulatory data
$.getJSON("config/wireless.json", function(json) {
var iface = $('#cbxinterface').val();
var hwmodeText = '';
var csrfToken = $('meta[name=csrf_token]').attr('content');

// update hardware mode tooltip
setHardwareModeTooltip();

$.post('ajax/networking/get_frequencies.php',{'interface': iface, 'csrf_token': csrfToken, 'selected': selected},function(response){
var hw_mode = $('#cbxhwmode').val();
var country_code = $('#cbxcountries').val();
var channel_select = $('#cbxchannel');
var data = json["wireless_regdb"];
var selectablechannels = Array.range(1,14);

// Assign array of countries to valid frequencies (channels)
var countries_2_4Ghz_max11ch = data["2_4GHz_max11ch"].countries;
var countries_2_4Ghz_max14ch = data["2_4GHz_max14ch"].countries;
var countries_5Ghz_max48ch = data["5Ghz_max48ch"].countries;
var btn_save = $('#btnSaveHostapd');
var data = JSON.parse(response);
var selectableChannels = [];

// Map selected hw_mode and country to determine channel list
// Map selected hw_mode to available channels
if (hw_mode === 'a') {
selectablechannels = data["5Ghz_max48ch"].channels;
} else if (($.inArray(country_code, countries_2_4Ghz_max11ch) !== -1) && (hw_mode !== 'ac') ) {
selectablechannels = data["2_4GHz_max11ch"].channels;
} else if (($.inArray(country_code, countries_2_4Ghz_max14ch) !== -1) && (hw_mode === 'b')) {
selectablechannels = data["2_4GHz_max14ch"].channels;
} else if (($.inArray(country_code, countries_5Ghz_max48ch) !== -1) && (hw_mode === 'ac')) {
selectablechannels = data["5Ghz_max48ch"].channels;
selectableChannels = data.filter(item => item.MHz.toString().startsWith('5'));
} else if (hw_mode !== 'ac') {
selectableChannels = data.filter(item => item.MHz.toString().startsWith('24'));
} else if (hw_mode === 'b') {
selectableChannels = data.filter(item => item.MHz.toString().startsWith('24'));
} else if (hw_mode === 'ac') {
selectableChannels = data.filter(item => item.MHz.toString().startsWith('5'));
}

// If selected channel doeesn't exist in allowed channels, set default or null (unsupported)
if (!selectableChannels.find(item => item.Channel === selected)) {
if (selectableChannels.length === 0) {
selectableChannels[0] = { Channel: null };
} else {
defaultChannel = selectableChannels[0].Channel;
selected = defaultChannel
}
}

// Set channel select with available values
selected = (typeof selected === 'undefined') ? selectablechannels[0] : selected;
channel_select.empty();
$.each(selectablechannels, function(key,value) {
channel_select.append($("<option></option>").attr("value", value).text(value));
});
channel_select.val(selected);
if (selectableChannels[0].Channel === null) {
channel_select.append($("<option></option>").attr("value", "").text("---"));
channel_select.prop("disabled", true);
btn_save.prop("disabled", true);
} else {
channel_select.prop("disabled", false);
btn_save.prop("disabled", false);
$.each(selectableChannels, function(key,value) {
channel_select.append($("<option></option>").attr("value", value.Channel).text(value.Channel));
});
channel_select.val(selected);
}
});
}

/* Sets hardware mode tooltip text for selected interface.
/* Sets hardware mode tooltip text for selected interface
* and calls loadChannelSelect()
*/
function setHardwareModeTooltip() {
var iface = $('#cbxinterface').val();
Expand All @@ -447,7 +463,7 @@ function setHardwareModeTooltip() {
if ($('#cbxhwmode').find('option[value="ac"]').prop('disabled') == true ) {
var hwmodeText = $('#hwmode').attr('data-tooltip');
}
$.post('ajax/networking/get_frequencies.php?',{'interface': iface, 'csrf_token': csrfToken},function(data){
$.post('ajax/networking/get_nl80211_band.php?',{'interface': iface, 'csrf_token': csrfToken},function(data){
var responseText = JSON.parse(data);
$('#tiphwmode').attr('data-original-title', responseText + '\n' + hwmodeText );
});
Expand Down
5 changes: 2 additions & 3 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
define('RASPI_ACCESS_CHECK_IP', '1.1.1.1');
define('RASPI_ACCESS_CHECK_DNS', 'one.one.one.one');

// Constants for the 5GHz wireless regulatory domain.
define('RASPI_5GHZ_ISO_ALPHA2', array('NL','US'));
define('RASPI_5GHZ_MAX_CHANNEL', 165);
// Constant for the 5GHz wireless regulatory domain
define("HOSTAPD_5GHZ_CHANNEL_MIN", 100);

// Enable basic authentication for the web admin.
define('RASPI_AUTH_ENABLED', true);
Expand Down
17 changes: 0 additions & 17 deletions config/wireless.json

This file was deleted.

8 changes: 5 additions & 3 deletions includes/defaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@
'RASPI_ACCESS_CHECK_IP' => '1.1.1.1',
'RASPI_ACCESS_CHECK_DNS' => 'one.one.one.one',

// Constants for the 5GHz wireless regulatory domain
'RASPI_5GHZ_ISO_ALPHA2' => array('NL','US'),
'RASPI_5GHZ_MAX_CHANNEL' => 165,
// Constant for the 5GHz wireless regulatory domain
'HOSTAPD_5GHZ_CHANNEL_MIN' => 100,

// Enable basic authentication for the web admin.
'RASPI_AUTH_ENABLED' => true,

// Optional services, set to true to enable.
'RASPI_WIFICLIENT_ENABLED' => true,
Expand Down
30 changes: 30 additions & 0 deletions includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -862,3 +862,33 @@ function loadFooterScripts($extraFooterScripts)
}
}

/**
* Returns ISO standard 2-letter country codes
*
* @param string $locale
* @param boolean $flag
*/
function getCountryCodes($locale = 'en', $flag = true) {
$output = [];
if ($flag) {
$opt = '--flag';
}
exec("isoquery $opt --locale $locale | awk -F'\t' '{print $5 \"\t\" $0}' | sort | cut -f2-", $output);

$countryData = [];
foreach ($output as $line) {
$parts = explode("\t", $line);
if (count($parts) >= 2) {
$countryCode = $parts[0];
if ($flag) {
$countryFlag = $parts[3];
$countryName = $parts[4] .' ';
} else {
$countryName = $parts[3];
}
$countryData[$countryCode] = $countryName.$countryFlag;
}
}
return $countryData;
}

Loading

0 comments on commit fbec450

Please sign in to comment.