Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor ISO countries + create IW parsing class #1443

Merged
merged 18 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading