mirror of
				https://github.com/billz/raspap-webgui.git
				synced 2025-03-01 10:31:47 +00:00 
			
		
		
		
	Merge pull request #1443 from RaspAP/feat/iw-parser
Refactor ISO countries + create IW parsing class
This commit is contained in:
		| @@ -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
									
								
								ajax/networking/get_nl80211_band.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								ajax/networking/get_nl80211_band.php
									
									
									
									
									
										Normal file
									
								
							| @@ -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); | ||||
| } | ||||
|  | ||||
| @@ -42,7 +42,7 @@ body { | ||||
|   background-color: #fff; | ||||
| } | ||||
|  | ||||
| .btn-primary.disabled { | ||||
| .btn-primary:disabled { | ||||
|   color: <?php echo $color; ?> !important; | ||||
|   border-color: <?php echo $color; ?> !important; | ||||
|   background-color: #fff !important; | ||||
|   | ||||
							
								
								
									
										122
									
								
								app/js/custom.js
									
									
									
									
									
								
							
							
						
						
									
										122
									
								
								app/js/custom.js
									
									
									
									
									
								
							| @@ -185,7 +185,7 @@ function contentLoaded() { | ||||
|             setupBtns(); | ||||
|             break; | ||||
|         case "hostapd_conf": | ||||
|             loadChannel(); | ||||
|             getChannel(); | ||||
|             setHardwareModeTooltip(); | ||||
|             break; | ||||
|         case "dhcpd_conf": | ||||
| @@ -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){ | ||||
| @@ -391,53 +384,76 @@ $(".custom-file-input").on("change", function() { | ||||
|   $(this).siblings(".custom-file-label").addClass("selected").html(fileName); | ||||
| }); | ||||
|  | ||||
| /* | ||||
| 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 | ||||
| */ | ||||
| function loadChannelSelect(selected) { | ||||
|     // Fetch wireless regulatory data | ||||
|     $.getJSON("config/wireless.json", function(json) { | ||||
|         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; | ||||
|  | ||||
|         // Map selected hw_mode and country to determine channel list | ||||
|         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; | ||||
|         } | ||||
|  | ||||
|         // 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); | ||||
|  // 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 hardware mode tooltip text for selected interface. | ||||
| /* | ||||
|  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) { | ||||
|     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 btn_save = $('#btnSaveHostapd'); | ||||
|         var data = JSON.parse(response); | ||||
|         var selectableChannels = []; | ||||
|  | ||||
|         // Map selected hw_mode to available channels | ||||
|         if (hw_mode === 'a') { | ||||
|             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 | ||||
|         channel_select.empty(); | ||||
|         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 | ||||
|  * and calls loadChannelSelect() | ||||
|  */ | ||||
| function setHardwareModeTooltip() { | ||||
|     var iface = $('#cbxinterface').val(); | ||||
| @@ -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 ); | ||||
|     }); | ||||
|   | ||||
| @@ -31,9 +31,8 @@ define('RASPI_LIGHTTPD_CONFIG', '/etc/lighttpd/lighttpd.conf'); | ||||
| 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); | ||||
|   | ||||
| @@ -1,17 +0,0 @@ | ||||
| {"wireless_regdb": { | ||||
|     "debug": "off", | ||||
|     "2_4GHz_max11ch": { | ||||
|         "countries": [ "AG", "BS", "BB", "BZ", "CR", "CU", "DM", "DO", "SV", "GD", "GT", | ||||
|         "HT", "HN", "JM", "MX", "NI", "PA", "KN", "LC", "VC", "TT", "US", "CA", "UZ", "CO" ], | ||||
|         "channels": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] | ||||
|     }, | ||||
|     "2_4GHz_max14ch": {  | ||||
|         "countries": [ "JP", "NL" ], | ||||
|         "channels": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ] | ||||
|     }, | ||||
|     "5Ghz_max48ch": { | ||||
|         "countries": [ "NL","US" ], | ||||
|         "channels": [ 36, 40, 44, 48 ] | ||||
|     } | ||||
| }}  | ||||
|  | ||||
| @@ -36,9 +36,11 @@ $defaults = [ | ||||
|   '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, | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,9 @@ function DisplayHostAPDConfig() | ||||
|         'n' => '802.11n - 2.4 GHz', | ||||
|         'ac' => '802.11ac - 5 GHz' | ||||
|     ]; | ||||
|     $languageCode = strtok($_SESSION['locale'], '_'); | ||||
|     $countryCodes = getCountryCodes($languageCode); | ||||
|  | ||||
|     $arrSecurity = array(1 => 'WPA', 2 => 'WPA2', 3 => 'WPA+WPA2', 'none' => _("None")); | ||||
|     $arrEncType = array('TKIP' => 'TKIP', 'CCMP' => 'CCMP', 'TKIP CCMP' => 'TKIP+CCMP'); | ||||
|     $arrTxPower = getDefaultNetOpts('txpower','dbm'); | ||||
| @@ -29,7 +32,7 @@ function DisplayHostAPDConfig() | ||||
|     exec("ip -o link show | awk -F': ' '{print $2}'", $interfaces); | ||||
|     sort($interfaces); | ||||
|  | ||||
|     exec("iw reg get | awk '/country / { sub(/:/,\"\",$2); print $2 }'", $country_code); | ||||
|     $reg_domain = shell_exec("iw reg get | grep -o 'country [A-Z]\{2\}' | awk 'NR==1{print $2}'"); | ||||
|  | ||||
|     $cmd = "iw dev ".$_SESSION['ap_interface']." info | awk '$1==\"txpower\" {print $2}'"; | ||||
|     exec($cmd, $txpower); | ||||
| @@ -40,7 +43,7 @@ function DisplayHostAPDConfig() | ||||
|     } | ||||
|     if (!RASPI_MONITOR_ENABLED) { | ||||
|         if (isset($_POST['SaveHostAPDSettings'])) { | ||||
|             SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $status); | ||||
|             SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $reg_domain, $status); | ||||
|         } | ||||
|     } | ||||
|     $arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini'); | ||||
| @@ -95,10 +98,12 @@ function DisplayHostAPDConfig() | ||||
|     } else { | ||||
|         $arrConfig['disassoc_low_ack_bool'] = 0; | ||||
|     } | ||||
|  | ||||
|     // assign country_code from iw reg if not set in config | ||||
|     if (empty($arrConfig['country_code']) && isset($country_code[0])) { | ||||
|         $arrConfig['country_code'] = $country_code[0]; | ||||
|     } | ||||
|  | ||||
|     // set txpower with iw if value is non-default ('auto') | ||||
|     if (isset($_POST['txpower'])) { | ||||
|         if ($_POST['txpower'] != 'auto') { | ||||
| @@ -114,7 +119,6 @@ function DisplayHostAPDConfig() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     $countries_5Ghz_max48ch = RASPI_5GHZ_ISO_ALPHA2; | ||||
|     $selectedHwMode = $arrConfig['hw_mode']; | ||||
|     if (isset($arrConfig['ieee80211n'])) { | ||||
|         if (strval($arrConfig['ieee80211n']) === '1') { | ||||
| @@ -131,14 +135,6 @@ function DisplayHostAPDConfig() | ||||
|             $selectedHwMode = 'w'; | ||||
|         } | ||||
|     } | ||||
|     if (!in_array($arrConfig['country_code'], $countries_5Ghz_max48ch)) { | ||||
|         $hwModeDisabled = 'ac'; | ||||
|         if ($selectedHwMode === $hwModeDisabled) { | ||||
|             unset($selectedHwMode); | ||||
|         } | ||||
|     } else { | ||||
|         $hwModeDisabled = null; | ||||
|     } | ||||
|  | ||||
|     echo renderTemplate( | ||||
|         "hostapd", compact( | ||||
| @@ -157,7 +153,7 @@ function DisplayHostAPDConfig() | ||||
|             "arrHostapdConf", | ||||
|             "operatingSystem", | ||||
|             "selectedHwMode", | ||||
|             "hwModeDisabled" | ||||
|             "countryCodes" | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
| @@ -169,10 +165,11 @@ function DisplayHostAPDConfig() | ||||
|  * @param array $enc_types | ||||
|  * @param array $modes | ||||
|  * @param string $interface | ||||
|  * @param string $reg_domain | ||||
|  * @param object $status | ||||
|  * @return boolean | ||||
|  */ | ||||
| function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $status) | ||||
| function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_domain, $status) | ||||
| { | ||||
|     // It should not be possible to send bad data for these fields.  | ||||
|     // If wpa fields are absent, return false and log securely. | ||||
| @@ -301,6 +298,8 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $status) | ||||
|     if (strlen($_POST['country_code']) !== 0 && strlen($_POST['country_code']) != 2) { | ||||
|         $status->addMessage('Country code must be blank or two characters', 'danger'); | ||||
|         $good_input = false; | ||||
|     } else { | ||||
|         $country_code = $_POST['country_code']; | ||||
|     } | ||||
|     if (isset($_POST['beaconintervalEnable'])) { | ||||
|         if (!is_numeric($_POST['beacon_interval'])) { | ||||
| @@ -318,6 +317,10 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $status) | ||||
|     if ($good_input) { | ||||
|         $return = updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable); | ||||
|  | ||||
|         if (trim($country_code) != trim($reg_domain)) { | ||||
|             $return = iwRegSet($country_code, $status); | ||||
|         } | ||||
|  | ||||
|         // Fetch dhcp-range, lease time from system config | ||||
|         $syscfg = parse_ini_file(RASPI_DNSMASQ_PREFIX.$ap_iface.'.conf', false, INI_SCANNER_RAW); | ||||
|  | ||||
| @@ -440,6 +443,14 @@ function updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable | ||||
|     } | ||||
|     $config.= 'ssid='.$_POST['ssid'].PHP_EOL; | ||||
|     $config.= 'channel='.$_POST['channel'].PHP_EOL; | ||||
|  | ||||
|     // Set VHT center frequency segment value | ||||
|     if ((int)$_POST['channel'] < HOSTAPD_5GHZ_CHANNEL_MIN) { | ||||
|         $vht_freq_idx = 42; | ||||
|     } else { | ||||
|         $vht_freq_idx =  155; | ||||
|     } | ||||
|  | ||||
|     if ($_POST['hw_mode'] === 'n') { | ||||
|         $config.= 'hw_mode=g'.PHP_EOL; | ||||
|         $config.= 'ieee80211n=1'.PHP_EOL; | ||||
| @@ -458,7 +469,7 @@ function updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable | ||||
|         $config.= 'ieee80211h=0'.PHP_EOL; | ||||
|         $config.= 'vht_capab=[MAX-AMSDU-3839][SHORT-GI-80]'.PHP_EOL; | ||||
|         $config.= 'vht_oper_chwidth=1'.PHP_EOL; | ||||
|         $config.= 'vht_oper_centr_freq_seg0_idx=42'.PHP_EOL.PHP_EOL; | ||||
|         $config.= 'vht_oper_centr_freq_seg0_idx='.$vht_freq_idx.PHP_EOL.PHP_EOL; | ||||
|     } elseif ($_POST['hw_mode'] === 'w') { | ||||
|         $config.= 'ieee80211w=2'.PHP_EOL; | ||||
|         $config.= 'wpa_key_mgmt=WPA-EAP-SHA256'.PHP_EOL; | ||||
| @@ -489,3 +500,18 @@ function updateHostapdConfig($ignore_broadcast_ssid,$wifiAPEnable,$bridgedEnable | ||||
|     return $result; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Executes iw to set the specified ISO 2-letter country code | ||||
|  * | ||||
|  * @param string $country_code | ||||
|  * @param object $status | ||||
|  * @return boolean $result | ||||
|  */ | ||||
| function iwRegSet(string $country_code, $status) | ||||
| { | ||||
|     $country_code = escapeshellarg($country_code); | ||||
|     $result = shell_exec("sudo iw reg set $country_code"); | ||||
|     $status->addMessage(sprintf(_('Setting wireless regulatory domain to %s'), $country_code, 'success')); | ||||
|     return $result; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -241,7 +241,7 @@ function _install_dependencies() { | ||||
|     # Set dconf-set-selections | ||||
|     echo iptables-persistent iptables-persistent/autosave_v4 boolean true | sudo debconf-set-selections | ||||
|     echo iptables-persistent iptables-persistent/autosave_v6 boolean true | sudo debconf-set-selections | ||||
|     sudo apt-get install -y lighttpd git hostapd dnsmasq iptables-persistent $php_package $dhcpcd_package $iw_package vnstat qrencode jq || _install_status 1 "Unable to install dependencies" | ||||
|     sudo apt-get install -y lighttpd git hostapd dnsmasq iptables-persistent $php_package $dhcpcd_package $iw_package vnstat qrencode jq isoquery || _install_status 1 "Unable to install dependencies" | ||||
|     _install_status 0 | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -709,6 +709,9 @@ msgstr "Routing table" | ||||
| msgid "raw output" | ||||
| msgstr "raw output" | ||||
|  | ||||
| msgid "Setting wireless regulatory domain to %s" | ||||
| msgstr "Setting wireless regulatory domain to %s" | ||||
|  | ||||
| #: includes/system.php | ||||
| msgid "System Information" | ||||
| msgstr "System Information" | ||||
|   | ||||
							
								
								
									
										100
									
								
								src/RaspAP/Parsers/IwParser.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/RaspAP/Parsers/IwParser.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Linux iw parser class | ||||
|  * | ||||
|  * @description Parses output of iw to determine properties of a given physical device (phy) | ||||
|  * @author      Bill Zimmerman <billzimmerman@gmail.com> | ||||
|  * @license     https://github.com/raspap/raspap-webgui/blob/master/LICENSE | ||||
|  * @see         https://wireless.wiki.kernel.org/en/users/Documentation/iw | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace RaspAP\Parsers; | ||||
|  | ||||
| class IwParser | ||||
| { | ||||
|     private $iw_output; | ||||
|  | ||||
|     public function __construct(string $interface = 'wlan0') | ||||
|     { | ||||
|  | ||||
|         // Resolve physical device for selected interface | ||||
|         $iface = escapeshellarg($interface); | ||||
|         $pattern = "iw dev | awk -v iface=".$iface." '/^phy#/ { phy = $0 } $1 == \"Interface\" { interface = $2 } interface == iface { print phy }'"; | ||||
|         exec($pattern, $return); | ||||
|         $phy = $return[0]; | ||||
|  | ||||
|         // Fetch 'iw info' output for phy | ||||
|         $this->iw_output = shell_exec("iw $phy info"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses raw output of 'iw info' command, filtering supported frequencies. | ||||
|      * | ||||
|      * Frequencies with the following regulatory restrictions are excluded: | ||||
|      * (no IR): the AP won't Initiate Radiation until a DFS scan (or similar) is complete on these bands. | ||||
|      * (radar detection): the specified channels are shared with radar equipment. | ||||
|      * (disabled): self-explanatory. | ||||
|      */ | ||||
|     public function parseIwInfo() | ||||
|     { | ||||
|         $excluded = [ | ||||
|             "(no IR, radar detection)", | ||||
|             "(radar detection)", | ||||
|             "(disabled)", | ||||
|             "(no IR)" | ||||
|         ]; | ||||
|         $excluded_pattern = implode('|', array_map('preg_quote', $excluded)); | ||||
|         $pattern = '/\*\s+(\d+)\s+MHz \[(\d+)\] \(([\d.]+) dBm\)\s(?!' .$excluded_pattern. ')/'; | ||||
|         $supportedFrequencies = []; | ||||
|  | ||||
|         // Match iw_output containing supported frequencies | ||||
|         preg_match_all($pattern, $this->iw_output, $matches, PREG_SET_ORDER, 0); | ||||
|  | ||||
|         /* For frequencies > 5500 MHz only the following "channels" are allowed: | ||||
|          * 100 108 116 124 132 140 149 157 184 192 | ||||
|          * @see https://w1.fi/cgit/hostap/tree/src/common/hw_features_common.c | ||||
|          */ | ||||
|         $allowed = [100, 108, 116, 124, 132, 140, 149, 157, 184, 192]; | ||||
|  | ||||
|         foreach ($matches as $match) { | ||||
|             $frequency = [ | ||||
|                 'MHz' => (int)$match[1], | ||||
|                 'Channel' => (int)$match[2], | ||||
|                 'dBm' => (float)$match[3], | ||||
|             ]; | ||||
|             if ( ($frequency['MHz'] >= 5500 && in_array($frequency['Channel'], $allowed)) | ||||
|                 || $frequency['MHz'] < 5500 ) { | ||||
|                 $supportedFrequencies[] = $frequency; | ||||
|             } | ||||
|         } | ||||
|         return $supportedFrequencies; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Converts an ieee80211 frequency to a channel value | ||||
|      * Adapted from iw source | ||||
|      * @param int $freq | ||||
|      * @see https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c  | ||||
|      */ | ||||
|     public function ieee80211_frequency_to_channel(int $freq) | ||||
|     { | ||||
|         /* see 802.11-2007 17.3.8.3.2 and Annex J */ | ||||
|         if ($freq == 2484) { | ||||
|             return 14; | ||||
|         } else if ($freq < 2484) { | ||||
|             return ($freq - 2407) / 5; | ||||
|         } else if ($freq >= 4910 && $freq <= 4980) { | ||||
|             return ($freq - 4000) / 5; | ||||
|         } else if ($freq <= 45000) { /* DMG band lower limit */ | ||||
|             return ($freq - 5000) / 5; | ||||
|         } else if ($freq >= 58320 && $freq <= 64800) { | ||||
|             return ($freq - 56160) / 2160; | ||||
|         } else { | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?php ob_start() ?> | ||||
|   <?php if (!RASPI_MONITOR_ENABLED) : ?> | ||||
|     <input type="submit" class="btn btn-outline btn-primary" name="SaveHostAPDSettings" value="<?php echo _("Save settings"); ?>" /> | ||||
|     <input type="submit" class="btn btn-outline btn-primary" id="btnSaveHostapd" name="SaveHostAPDSettings" value="<?php echo _("Save settings"); ?>" /> | ||||
|     <?php if ($hostapdstatus[0] == 0) : ?> | ||||
|       <input type="submit" class="btn btn-success" name="StartHotspot" value="<?php echo  _("Start hotspot"); $msg=_("Starting hotspot"); ?>" data-toggle="modal" data-target="#hostapdModal"/> | ||||
|     <?php else : ?> | ||||
|   | ||||
| @@ -73,257 +73,7 @@ | ||||
|       <div class="form-group col-md-6"> | ||||
|       <label for="cbxcountries"><?php echo _("Country Code"); ?></label> | ||||
|       <input type="hidden" id="selected_country" value="<?php echo htmlspecialchars($arrConfig['country_code'], ENT_QUOTES); ?>"> | ||||
|       <select  class="form-control" id="cbxcountries" name="country_code" onchange="loadChannelSelect()"> | ||||
|         <option value="AF">Afghanistan</option> | ||||
|         <option value="AX">Åland Islands</option> | ||||
|         <option value="AL">Albania</option> | ||||
|         <option value="DZ">Algeria</option> | ||||
|         <option value="AS">American Samoa</option> | ||||
|         <option value="AD">Andorra</option> | ||||
|         <option value="AO">Angola</option> | ||||
|         <option value="AI">Anguilla</option> | ||||
|         <option value="AQ">Antarctica</option> | ||||
|         <option value="AG">Antigua and Barbuda</option> | ||||
|         <option value="AR">Argentina</option> | ||||
|         <option value="AM">Armenia</option> | ||||
|         <option value="AW">Aruba</option> | ||||
|         <option value="AU">Australia</option> | ||||
|         <option value="AT">Austria</option> | ||||
|         <option value="AZ">Azerbaijan</option> | ||||
|         <option value="BS">Bahamas</option> | ||||
|         <option value="BH">Bahrain</option> | ||||
|         <option value="BD">Bangladesh</option> | ||||
|         <option value="BB">Barbados</option> | ||||
|         <option value="BY">Belarus</option> | ||||
|         <option value="BE">Belgium</option> | ||||
|         <option value="BZ">Belize</option> | ||||
|         <option value="BJ">Benin</option> | ||||
|         <option value="BM">Bermuda</option> | ||||
|         <option value="BT">Bhutan</option> | ||||
|         <option value="BO">Bolivia, Plurinational State of</option> | ||||
|         <option value="BQ">Bonaire, Sint Eustatius and Saba</option> | ||||
|         <option value="BA">Bosnia and Herzegovina</option> | ||||
|         <option value="BW">Botswana</option> | ||||
|         <option value="BV">Bouvet Island</option> | ||||
|         <option value="BR">Brazil</option> | ||||
|         <option value="IO">British Indian Ocean Territory</option> | ||||
|         <option value="BN">Brunei Darussalam</option> | ||||
|         <option value="BG">Bulgaria</option> | ||||
|         <option value="BF">Burkina Faso</option> | ||||
|         <option value="BI">Burundi</option> | ||||
|         <option value="KH">Cambodia</option> | ||||
|         <option value="CM">Cameroon</option> | ||||
|         <option value="CA">Canada</option> | ||||
|         <option value="CV">Cape Verde</option> | ||||
|         <option value="KY">Cayman Islands</option> | ||||
|         <option value="CF">Central African Republic</option> | ||||
|         <option value="TD">Chad</option> | ||||
|         <option value="CL">Chile</option> | ||||
|         <option value="CN">China</option> | ||||
|         <option value="CX">Christmas Island</option> | ||||
|         <option value="CC">Cocos (Keeling) Islands</option> | ||||
|         <option value="CO">Colombia</option> | ||||
|         <option value="KM">Comoros</option> | ||||
|         <option value="CG">Congo</option> | ||||
|         <option value="CD">Congo, the Democratic Republic of the</option> | ||||
|         <option value="CK">Cook Islands</option> | ||||
|         <option value="CR">Costa Rica</option> | ||||
|         <option value="CI">Côte d'Ivoire</option> | ||||
|         <option value="HR">Croatia</option> | ||||
|         <option value="CU">Cuba</option> | ||||
|         <option value="CW">Curaçao</option> | ||||
|         <option value="CY">Cyprus</option> | ||||
|         <option value="CZ">Czech Republic</option> | ||||
|         <option value="DK">Denmark</option> | ||||
|         <option value="DJ">Djibouti</option> | ||||
|         <option value="DM">Dominica</option> | ||||
|         <option value="DO">Dominican Republic</option> | ||||
|         <option value="EC">Ecuador</option> | ||||
|         <option value="EG">Egypt</option> | ||||
|         <option value="SV">El Salvador</option> | ||||
|         <option value="GQ">Equatorial Guinea</option> | ||||
|         <option value="ER">Eritrea</option> | ||||
|         <option value="EE">Estonia</option> | ||||
|         <option value="ET">Ethiopia</option> | ||||
|         <option value="FK">Falkland Islands (Malvinas)</option> | ||||
|         <option value="FO">Faroe Islands</option> | ||||
|         <option value="FJ">Fiji</option> | ||||
|         <option value="FI">Finland</option> | ||||
|         <option value="FR">France</option> | ||||
|         <option value="GF">French Guiana</option> | ||||
|         <option value="PF">French Polynesia</option> | ||||
|         <option value="TF">French Southern Territories</option> | ||||
|         <option value="GA">Gabon</option> | ||||
|         <option value="GM">Gambia</option> | ||||
|         <option value="GE">Georgia</option> | ||||
|         <option value="DE">Germany</option> | ||||
|         <option value="GH">Ghana</option> | ||||
|         <option value="GI">Gibraltar</option> | ||||
|         <option value="GR">Greece</option> | ||||
|         <option value="GL">Greenland</option> | ||||
|         <option value="GD">Grenada</option> | ||||
|         <option value="GP">Guadeloupe</option> | ||||
|         <option value="GU">Guam</option> | ||||
|         <option value="GT">Guatemala</option> | ||||
|         <option value="GG">Guernsey</option> | ||||
|         <option value="GN">Guinea</option> | ||||
|         <option value="GW">Guinea-Bissau</option> | ||||
|         <option value="GY">Guyana</option> | ||||
|         <option value="HT">Haiti</option> | ||||
|         <option value="HM">Heard Island and McDonald Islands</option> | ||||
|         <option value="VA">Holy See (Vatican City State)</option> | ||||
|         <option value="HN">Honduras</option> | ||||
|         <option value="HK">Hong Kong</option> | ||||
|         <option value="HU">Hungary</option> | ||||
|         <option value="IS">Iceland</option> | ||||
|         <option value="IN">India</option> | ||||
|         <option value="ID">Indonesia</option> | ||||
|         <option value="IR">Iran, Islamic Republic of</option> | ||||
|         <option value="IQ">Iraq</option> | ||||
|         <option value="IE">Ireland</option> | ||||
|         <option value="IM">Isle of Man</option> | ||||
|         <option value="IL">Israel</option> | ||||
|         <option value="IT">Italy</option> | ||||
|         <option value="JM">Jamaica</option> | ||||
|         <option value="JP">Japan</option> | ||||
|         <option value="JE">Jersey</option> | ||||
|         <option value="JO">Jordan</option> | ||||
|         <option value="KZ">Kazakhstan</option> | ||||
|         <option value="KE">Kenya</option> | ||||
|         <option value="KI">Kiribati</option> | ||||
|         <option value="KP">Korea, Democratic People's Republic of</option> | ||||
|         <option value="KR">Korea, Republic of</option> | ||||
|         <option value="KW">Kuwait</option> | ||||
|         <option value="KG">Kyrgyzstan</option> | ||||
|         <option value="LA">Lao People's Democratic Republic</option> | ||||
|         <option value="LV">Latvia</option> | ||||
|         <option value="LB">Lebanon</option> | ||||
|         <option value="LS">Lesotho</option> | ||||
|         <option value="LR">Liberia</option> | ||||
|         <option value="LY">Libya</option> | ||||
|         <option value="LI">Liechtenstein</option> | ||||
|         <option value="LT">Lithuania</option> | ||||
|         <option value="LU">Luxembourg</option> | ||||
|         <option value="MO">Macao</option> | ||||
|         <option value="MK">Macedonia, the former Yugoslav Republic of</option> | ||||
|         <option value="MG">Madagascar</option> | ||||
|         <option value="MW">Malawi</option> | ||||
|         <option value="MY">Malaysia</option> | ||||
|         <option value="MV">Maldives</option> | ||||
|         <option value="ML">Mali</option> | ||||
|         <option value="MT">Malta</option> | ||||
|         <option value="MH">Marshall Islands</option> | ||||
|         <option value="MQ">Martinique</option> | ||||
|         <option value="MR">Mauritania</option> | ||||
|         <option value="MU">Mauritius</option> | ||||
|         <option value="YT">Mayotte</option> | ||||
|         <option value="MX">Mexico</option> | ||||
|         <option value="FM">Micronesia, Federated States of</option> | ||||
|         <option value="MD">Moldova, Republic of</option> | ||||
|         <option value="MC">Monaco</option> | ||||
|         <option value="MN">Mongolia</option> | ||||
|         <option value="ME">Montenegro</option> | ||||
|         <option value="MS">Montserrat</option> | ||||
|         <option value="MA">Morocco</option> | ||||
|         <option value="MZ">Mozambique</option> | ||||
|         <option value="MM">Myanmar</option> | ||||
|         <option value="NA">Namibia</option> | ||||
|         <option value="NR">Nauru</option> | ||||
|         <option value="NP">Nepal</option> | ||||
|         <option value="NL">Netherlands</option> | ||||
|         <option value="NC">New Caledonia</option> | ||||
|         <option value="NZ">New Zealand</option> | ||||
|         <option value="NI">Nicaragua</option> | ||||
|         <option value="NE">Niger</option> | ||||
|         <option value="NG">Nigeria</option> | ||||
|         <option value="NU">Niue</option> | ||||
|         <option value="NF">Norfolk Island</option> | ||||
|         <option value="MP">Northern Mariana Islands</option> | ||||
|         <option value="NO">Norway</option> | ||||
|         <option value="OM">Oman</option> | ||||
|         <option value="PK">Pakistan</option> | ||||
|         <option value="PW">Palau</option> | ||||
|         <option value="PS">Palestinian Territory</option> | ||||
|         <option value="PA">Panama</option> | ||||
|         <option value="PG">Papua New Guinea</option> | ||||
|         <option value="PY">Paraguay</option> | ||||
|         <option value="PE">Peru</option> | ||||
|         <option value="PH">Philippines</option> | ||||
|         <option value="PN">Pitcairn</option> | ||||
|         <option value="PL">Poland</option> | ||||
|         <option value="PT">Portugal</option> | ||||
|         <option value="PR">Puerto Rico</option> | ||||
|         <option value="QA">Qatar</option> | ||||
|         <option value="RE">Réunion</option> | ||||
|         <option value="RO">Romania</option> | ||||
|         <option value="RU">Russian Federation</option> | ||||
|         <option value="RW">Rwanda</option> | ||||
|         <option value="BL">Saint Barthélemy</option> | ||||
|         <option value="SH">Saint Helena, Ascension and Tristan da Cunha</option> | ||||
|         <option value="KN">Saint Kitts and Nevis</option> | ||||
|         <option value="LC">Saint Lucia</option> | ||||
|         <option value="MF">Saint Martin (French part)</option> | ||||
|         <option value="PM">Saint Pierre and Miquelon</option> | ||||
|         <option value="VC">Saint Vincent and the Grenadines</option> | ||||
|         <option value="WS">Samoa</option> | ||||
|         <option value="SM">San Marino</option> | ||||
|         <option value="ST">Sao Tome and Principe</option> | ||||
|         <option value="SA">Saudi Arabia</option> | ||||
|         <option value="SN">Senegal</option> | ||||
|         <option value="RS">Serbia</option> | ||||
|         <option value="SC">Seychelles</option> | ||||
|         <option value="SL">Sierra Leone</option> | ||||
|         <option value="SG">Singapore</option> | ||||
|         <option value="SX">Sint Maarten (Dutch part)</option> | ||||
|         <option value="SK">Slovakia</option> | ||||
|         <option value="SI">Slovenia</option> | ||||
|         <option value="SB">Solomon Islands</option> | ||||
|         <option value="SO">Somalia</option> | ||||
|         <option value="ZA">South Africa</option> | ||||
|         <option value="GS">South Georgia and the South Sandwich Islands</option> | ||||
|         <option value="SS">South Sudan</option> | ||||
|         <option value="ES">Spain</option> | ||||
|         <option value="LK">Sri Lanka</option> | ||||
|         <option value="SD">Sudan</option> | ||||
|         <option value="SR">Suriname</option> | ||||
|         <option value="SJ">Svalbard and Jan Mayen</option> | ||||
|         <option value="SZ">Swaziland</option> | ||||
|         <option value="SE">Sweden</option> | ||||
|         <option value="CH">Switzerland</option> | ||||
|         <option value="SY">Syrian Arab Republic</option> | ||||
|         <option value="TW">Taiwan</option> | ||||
|         <option value="TJ">Tajikistan</option> | ||||
|         <option value="TZ">Tanzania, United Republic of</option> | ||||
|         <option value="TH">Thailand</option> | ||||
|         <option value="TL">Timor-Leste</option> | ||||
|         <option value="TG">Togo</option> | ||||
|         <option value="TK">Tokelau</option> | ||||
|         <option value="TO">Tonga</option> | ||||
|         <option value="TT">Trinidad and Tobago</option> | ||||
|         <option value="TN">Tunisia</option> | ||||
|         <option value="TR">Turkey</option> | ||||
|         <option value="TM">Turkmenistan</option> | ||||
|         <option value="TC">Turks and Caicos Islands</option> | ||||
|         <option value="TV">Tuvalu</option> | ||||
|         <option value="UG">Uganda</option> | ||||
|         <option value="UA">Ukraine</option> | ||||
|         <option value="AE">United Arab Emirates</option> | ||||
|         <option value="GB">United Kingdom</option> | ||||
|         <option value="US">United States</option> | ||||
|         <option value="UM">United States Minor Outlying Islands</option> | ||||
|         <option value="UY">Uruguay</option> | ||||
|         <option value="UZ">Uzbekistan</option> | ||||
|         <option value="VU">Vanuatu</option> | ||||
|         <option value="VE">Venezuela, Bolivarian Republic of</option> | ||||
|         <option value="VN">Viet Nam</option> | ||||
|         <option value="VG">Virgin Islands, British</option> | ||||
|         <option value="VI">Virgin Islands, U.S.</option> | ||||
|         <option value="WF">Wallis and Futuna</option> | ||||
|         <option value="EH">Western Sahara</option> | ||||
|         <option value="YE">Yemen</option> | ||||
|         <option value="ZM">Zambia</option> | ||||
|         <option value="ZW">Zimbabwe</option> | ||||
|       </select> | ||||
|       <?php SelectorOptions('country_code', $countryCodes, $arrConfig['country_code'], 'cbxcountries', 'loadChannelSelect'); ?> | ||||
|       <script type="text/javascript"> | ||||
|       var country = document.getElementById("selected_country").value; | ||||
|       var countries = document.getElementById("cbxcountries"); | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|   <div class="row"> | ||||
|     <div class="form-group col-md-6"> | ||||
|       <label for="cbxinterface"><?php echo _("Interface") ;?></label> | ||||
|       <?php SelectorOptions('interface', $interfaces, $arrConfig['interface'], 'cbxinterface', 'setHardwareModeTooltip'); ?> | ||||
|       <?php SelectorOptions('interface', $interfaces, $arrConfig['interface'], 'cbxinterface', 'getChannel'); ?> | ||||
|     </div> | ||||
|   </div> | ||||
|   <div class="row"> | ||||
| @@ -16,7 +16,7 @@ | ||||
|     <div class="form-group col-md-6"> | ||||
|       <label for="cbxhwmode"><?php echo _("Wireless Mode") ;?></label> | ||||
|       <?php getTooltip(null, 'tiphwmode', true); ?> | ||||
|       <?php SelectorOptions('hw_mode', $arr80211Standard, $selectedHwMode, 'cbxhwmode', 'loadChannelSelect', $hwModeDisabled); ?> | ||||
|       <?php SelectorOptions('hw_mode', $arr80211Standard, $selectedHwMode, 'cbxhwmode', 'getChannel'); ?> | ||||
|       <div id="hwmode" data-tooltip="<?php echo _("The 802.11ac 5 GHz option is disabled until a compatible wireless regulatory domain is set."); ?>"></div> | ||||
|     </div> | ||||
|   </div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user