From 670b103023cf84c404e5dd33a2017ed89651e7fd Mon Sep 17 00:00:00 2001 From: Mark Solters Date: Sat, 2 Jul 2016 00:17:17 -0400 Subject: [PATCH 1/4] Linux now auto-finds interfaces using iwconfig --- src/linux.coffee | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/linux.coffee b/src/linux.coffee index b959c32..56cbef2 100644 --- a/src/linux.coffee +++ b/src/linux.coffee @@ -1,5 +1,5 @@ parsePatterns = - nmcli_line: new RegExp /([^:]+):\s+(.+)/ + iwconfig_line: new RegExp /([^ ]+)/ connectionStateMap = connected: "connected" # Win32 & Linux @@ -13,13 +13,16 @@ powerStateMap = module.exports = autoFindInterface: -> @WiFiLog "Host machine is Linux." - # On linux, we use the results of `nmcli device status` and parse for - # active `wlan*` interfaces. - findInterfaceCom = "nmcli -m multiline device status | grep wlan" + # On linux, we use the results of `iwconfig` and parse for + # active 802.11 radios. + # There could be more than one choice, but we always just grab the first + # result. + findInterfaceCom = "iwconfig | grep 802.11" @WiFiLog "Executing: #{findInterfaceCom}" _interfaceLine = @execSync findInterfaceCom - parsedLine = parsePatterns.nmcli_line.exec( _interfaceLine.trim() ) - _interface = parsedLine[2] + parsedLine = parsePatterns.iwconfig_line.exec( _interfaceLine.trim() ) + _interface = parsedLine[0] + console.log _interface if _interface _iface = _interface.trim() _msg = "Automatically located wireless interface #{_iface}." From 735e56746397549a9cdf0cbeaf0c404b89b793c1 Mon Sep 17 00:00:00 2001 From: Mark Solters Date: Sat, 2 Jul 2016 01:01:52 -0400 Subject: [PATCH 2/4] Linux now gets Iface state using iw --- src/linux.coffee | 74 +++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 51 deletions(-) diff --git a/src/linux.coffee b/src/linux.coffee index 56cbef2..b5f8f1d 100644 --- a/src/linux.coffee +++ b/src/linux.coffee @@ -1,5 +1,6 @@ parsePatterns = iwconfig_line: new RegExp /([^ ]+)/ + iw_dev_link_line: new RegExp /([^:]+): ([^\n]+)/ connectionStateMap = connected: "connected" # Win32 & Linux @@ -22,7 +23,6 @@ module.exports = _interfaceLine = @execSync findInterfaceCom parsedLine = parsePatterns.iwconfig_line.exec( _interfaceLine.trim() ) _interface = parsedLine[0] - console.log _interface if _interface _iface = _interface.trim() _msg = "Automatically located wireless interface #{_iface}." @@ -46,57 +46,29 @@ module.exports = # getIfaceState: -> interfaceState = {} - # - # (1) Get Interface Power State - # - powerData = @execSync "nmcli networking" - interfaceState.power = powerStateMap[ powerData.trim() ] - if interfaceState.power - # - # (2) First, we get connection name & state - # - foundInterface = false - connectionData = @execSync "nmcli -m multiline device status" - connectionName = null - for ln, k in connectionData.split '\n' - try - parsedLine = parsePatterns.nmcli_line.exec( ln.trim() ) - KEY = parsedLine[1] - VALUE = parsedLine[2] - VALUE = null if VALUE is "--" - catch error - continue # this line was not a key: value pair! - switch KEY - when "DEVICE" - foundInterface = true if VALUE is @WiFiControlSettings.iface - when "STATE" - interfaceState.connection = connectionStateMap[ VALUE ] if foundInterface - when "CONNECTION" - connectionName = VALUE if foundInterface - break if KEY is "CONNECTION" and foundInterface # we have everything we need! - # If we didn't find anything... - unless foundInterface - return { - success: false - msg: "Unable to retrieve state of network interface #{@WiFiControlSettings.iface}." - } - if connectionName - # - # (3) Next, we get the actual SSID - # - try - ssidData = @execSync "nmcli -m multiline connection show \"#{connectionName}\" | grep 802-11-wireless.ssid" - parsedLine = parsePatterns.nmcli_line.exec( ssidData.trim() ) - interfaceState.ssid = parsedLine[2] - catch error - return { - success: false - msg: "Error while retrieving SSID information of network interface #{@WiFiControlSettings.iface}: #{error.stderr}" - } - else - interfaceState.ssid = null + connectionState = @execSync "iw dev #{@WiFiControlSettings.iface} link" + if connectionState.indexOf("command failed: no such device") == -1 + interfaceState.power = true + connectionStateLines = connectionState.split("\n") + if connectionStateLines[0].indexOf("Not connected") > -1 + interfaceState.connection = "disconnected" + else if connectionStateLines[0].indexOf("Connected to") > -1 + interfaceState.connection = "connected" + for ln, k in connectionStateLines.slice(1) + try + parsedLine = parsePatterns.iw_dev_link_line.exec( ln.trim() ) + KEY = parsedLine[1] + VALUE = parsedLine[2] + catch error + continue + switch KEY + when "SSID" + interfaceState.ssid = VALUE + break + interfaceState.ssid = null if !interfaceState.ssid? else - interfaceState.connection = connectionStateMap[ VALUE ] + interfaceState.power = false + interfaceState.connection = "disconnected" interfaceState.ssid = null return interfaceState From 9697a2f9e0762c911ad3d4e2de2f165a34913852 Mon Sep 17 00:00:00 2001 From: Mark Solters Date: Sat, 2 Jul 2016 01:21:13 -0400 Subject: [PATCH 3/4] Linux uses iw to scan for APs --- src/linux.coffee | 69 +++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 24 deletions(-) diff --git a/src/linux.coffee b/src/linux.coffee index b5f8f1d..2cf49d4 100644 --- a/src/linux.coffee +++ b/src/linux.coffee @@ -1,6 +1,12 @@ parsePatterns = iwconfig_line: new RegExp /([^ ]+)/ iw_dev_link_line: new RegExp /([^:]+): ([^\n]+)/ + iwlist: + new_cell: new RegExp /.*BSS [0-9a-z]{2}:.*/ + ssid: new RegExp /.*SSID: (.*).*/ + encryption: new RegExp /.*Privacy.*/ + signal: new RegExp /.*signal: (-[0-9\.]+).*/ + channel: new RegExp /.*DS Parameter set: channel ([0-9]+)/ connectionStateMap = connected: "connected" # Win32 & Linux @@ -42,7 +48,7 @@ module.exports = } # - # For Linux, parse nmcli to acquire networking interface data. + # For Linux, parse iw dev link to acquire networking interface data. # getIfaceState: -> interfaceState = {} @@ -77,34 +83,49 @@ module.exports = # scanForWiFi: -> # - # Use nmcli to list visible wifi networks. + # Use iw to list visible wifi networks. # - scanResults = @execSync "nmcli -m multiline device wifi list" + scanResults = @execSync "sudo iw dev #{@WiFiControlSettings.iface} scan ap-force" + networks = [] # # Parse the results into an array of AP objects to match # the structure found in node-wifiscanner2 for win32 and MacOS. # - networks = [] - for nwk, c in scanResults.split '*:' - continue if c is 0 - _network = {} - for ln, k in nwk.split '\n' - try - parsedLine = parsePatterns.nmcli_line.exec( ln.trim() ) - KEY = parsedLine[1] - VALUE = parsedLine[2] - catch error - continue # this line was not a key: value pair! - switch KEY - when "SSID" - _network.ssid = String VALUE - when "CHAN" - _network.channel = String VALUE - when "SIGNAL" - _network.signal_level = String VALUE - when "SECURITY" - _network.security = String VALUE - networks.push _network unless _network.ssid is "--" + _network = + ssid: null + security: false + signal: null + channel: null + for ln, k in scanResults.split("\n") + line = ln.trim() + if parsePatterns.iwlist.new_cell.test ln + # This is a new cell, reset the current scan result object. + _network = + ssid: null + security: false + signal_level: null + channel: null + continue + + ssid_parse = parsePatterns.iwlist.ssid.exec ln + if ssid_parse + _network.ssid = ssid_parse[1] + # This is the last line of the current cell! + if _network.ssid.length + networks.push _network + continue + + if parsePatterns.iwlist.encryption.test ln + _network.security = true + + channel_parse = parsePatterns.iwlist.channel.exec ln + if channel_parse + console.log channel_parse + _network.channel = parseInt channel_parse[1] + + signal_parse = parsePatterns.iwlist.signal.exec ln + if signal_parse + _network.signal = parseInt signal_parse[1] return networks # From 53f6f8115c80b14857a373ac227789a3887bc247 Mon Sep 17 00:00:00 2001 From: Mark Solters Date: Sat, 2 Jul 2016 01:35:02 -0400 Subject: [PATCH 4/4] Linux uses ifconfig to accomplish wifi reset. No more references to nmcli networking --- lib/linux.js | 175 +++++++++++++++++++++-------------------------- src/linux.coffee | 6 +- 2 files changed, 81 insertions(+), 100 deletions(-) diff --git a/lib/linux.js b/lib/linux.js index 8852a53..0d0284a 100644 --- a/lib/linux.js +++ b/lib/linux.js @@ -3,7 +3,15 @@ var connectionStateMap, parsePatterns, powerStateMap; parsePatterns = { - nmcli_line: new RegExp(/([^:]+):\s+(.+)/) + iwconfig_line: new RegExp(/([^ ]+)/), + iw_dev_link_line: new RegExp(/([^:]+): ([^\n]+)/), + iwlist: { + new_cell: new RegExp(/.*BSS [0-9a-z]{2}:.*/), + ssid: new RegExp(/.*SSID: (.*).*/), + encryption: new RegExp(/.*Privacy.*/), + signal: new RegExp(/.*signal: (-[0-9\.]+).*/), + channel: new RegExp(/.*DS Parameter set: channel ([0-9]+)/) + } }; connectionStateMap = { @@ -21,11 +29,11 @@ autoFindInterface: function() { var _iface, _interface, _interfaceLine, _msg, findInterfaceCom, parsedLine; this.WiFiLog("Host machine is Linux."); - findInterfaceCom = "nmcli -m multiline device status | grep wlan"; + findInterfaceCom = "iwconfig | grep 802.11"; this.WiFiLog("Executing: " + findInterfaceCom); _interfaceLine = this.execSync(findInterfaceCom); - parsedLine = parsePatterns.nmcli_line.exec(_interfaceLine.trim()); - _interface = parsedLine[2]; + parsedLine = parsePatterns.iwconfig_line.exec(_interfaceLine.trim()); + _interface = parsedLine[0]; if (_interface) { _iface = _interface.trim(); _msg = "Automatically located wireless interface " + _iface + "."; @@ -46,113 +54,86 @@ } }, getIfaceState: function() { - var KEY, VALUE, connectionData, connectionName, error, error1, error2, foundInterface, i, interfaceState, k, len, ln, parsedLine, powerData, ref, ssidData; + var KEY, VALUE, connectionState, connectionStateLines, error, error1, i, interfaceState, k, len, ln, parsedLine, ref; interfaceState = {}; - powerData = this.execSync("nmcli networking"); - interfaceState.power = powerStateMap[powerData.trim()]; - if (interfaceState.power) { - foundInterface = false; - connectionData = this.execSync("nmcli -m multiline device status"); - connectionName = null; - ref = connectionData.split('\n'); - for (k = i = 0, len = ref.length; i < len; k = ++i) { - ln = ref[k]; - try { - parsedLine = parsePatterns.nmcli_line.exec(ln.trim()); - KEY = parsedLine[1]; - VALUE = parsedLine[2]; - if (VALUE === "--") { - VALUE = null; + connectionState = this.execSync("iw dev " + this.WiFiControlSettings.iface + " link"); + if (connectionState.indexOf("command failed: no such device") === -1) { + interfaceState.power = true; + connectionStateLines = connectionState.split("\n"); + if (connectionStateLines[0].indexOf("Not connected") > -1) { + interfaceState.connection = "disconnected"; + } else if (connectionStateLines[0].indexOf("Connected to") > -1) { + interfaceState.connection = "connected"; + ref = connectionStateLines.slice(1); + for (k = i = 0, len = ref.length; i < len; k = ++i) { + ln = ref[k]; + try { + parsedLine = parsePatterns.iw_dev_link_line.exec(ln.trim()); + KEY = parsedLine[1]; + VALUE = parsedLine[2]; + } catch (error1) { + error = error1; + continue; + } + switch (KEY) { + case "SSID": + interfaceState.ssid = VALUE; + break; } - } catch (error1) { - error = error1; - continue; - } - switch (KEY) { - case "DEVICE": - if (VALUE === this.WiFiControlSettings.iface) { - foundInterface = true; - } - break; - case "STATE": - if (foundInterface) { - interfaceState.connection = connectionStateMap[VALUE]; - } - break; - case "CONNECTION": - if (foundInterface) { - connectionName = VALUE; - } - } - if (KEY === "CONNECTION" && foundInterface) { - break; } - } - if (!foundInterface) { - return { - success: false, - msg: "Unable to retrieve state of network interface " + this.WiFiControlSettings.iface + "." - }; - } - if (connectionName) { - try { - ssidData = this.execSync("nmcli -m multiline connection show \"" + connectionName + "\" | grep 802-11-wireless.ssid"); - parsedLine = parsePatterns.nmcli_line.exec(ssidData.trim()); - interfaceState.ssid = parsedLine[2]; - } catch (error2) { - error = error2; - return { - success: false, - msg: "Error while retrieving SSID information of network interface " + this.WiFiControlSettings.iface + ": " + error.stderr - }; + if (interfaceState.ssid == null) { + interfaceState.ssid = null; } - } else { - interfaceState.ssid = null; } } else { - interfaceState.connection = connectionStateMap[VALUE]; + interfaceState.power = false; + interfaceState.connection = "disconnected"; interfaceState.ssid = null; } return interfaceState; }, scanForWiFi: function() { - var KEY, VALUE, _network, c, error, error1, i, j, k, len, len1, ln, networks, nwk, parsedLine, ref, ref1, scanResults; - scanResults = this.execSync("nmcli -m multiline device wifi list"); + var _network, channel_parse, i, k, len, line, ln, networks, ref, scanResults, signal_parse, ssid_parse; + scanResults = this.execSync("sudo iw dev " + this.WiFiControlSettings.iface + " scan ap-force"); networks = []; - ref = scanResults.split('*:'); - for (c = i = 0, len = ref.length; i < len; c = ++i) { - nwk = ref[c]; - if (c === 0) { + _network = { + ssid: null, + security: false, + signal: null, + channel: null + }; + ref = scanResults.split("\n"); + for (k = i = 0, len = ref.length; i < len; k = ++i) { + ln = ref[k]; + line = ln.trim(); + if (parsePatterns.iwlist.new_cell.test(ln)) { + _network = { + ssid: null, + security: false, + signal_level: null, + channel: null + }; continue; } - _network = {}; - ref1 = nwk.split('\n'); - for (k = j = 0, len1 = ref1.length; j < len1; k = ++j) { - ln = ref1[k]; - try { - parsedLine = parsePatterns.nmcli_line.exec(ln.trim()); - KEY = parsedLine[1]; - VALUE = parsedLine[2]; - } catch (error1) { - error = error1; - continue; - } - switch (KEY) { - case "SSID": - _network.ssid = String(VALUE); - break; - case "CHAN": - _network.channel = String(VALUE); - break; - case "SIGNAL": - _network.signal_level = String(VALUE); - break; - case "SECURITY": - _network.security = String(VALUE); + ssid_parse = parsePatterns.iwlist.ssid.exec(ln); + if (ssid_parse) { + _network.ssid = ssid_parse[1]; + if (_network.ssid.length) { + networks.push(_network); } + continue; + } + if (parsePatterns.iwlist.encryption.test(ln)) { + _network.security = true; + } + channel_parse = parsePatterns.iwlist.channel.exec(ln); + if (channel_parse) { + console.log(channel_parse); + _network.channel = parseInt(channel_parse[1]); } - if (_network.ssid !== "--") { - networks.push(_network); + signal_parse = parsePatterns.iwlist.signal.exec(ln); + if (signal_parse) { + _network.signal = parseInt(signal_parse[1]); } } return networks; @@ -217,8 +198,8 @@ resetWiFi: function() { var COMMANDS, _msg, com, i, len, resetWiFiChain, results, stdout; COMMANDS = { - disableNetworking: "nmcli networking off", - enableNetworking: "nmcli networking on" + disableNetworking: "sudo ifconfig " + this.WiFiControlSettings.iface + " down", + enableNetworking: "sudo ifconfig " + this.WiFiControlSettings.iface + " up" }; resetWiFiChain = ["disableNetworking", "enableNetworking"]; results = []; diff --git a/src/linux.coffee b/src/linux.coffee index 2cf49d4..a83912d 100644 --- a/src/linux.coffee +++ b/src/linux.coffee @@ -129,7 +129,7 @@ module.exports = return networks # - # With Linux, we can use nmcli to do the heavy lifting. + # With Linux, we can use iw to do the heavy lifting. # connectToAP: ( _ap ) -> # @@ -205,8 +205,8 @@ module.exports = # the Network Manager service # COMMANDS = - disableNetworking: "nmcli networking off" - enableNetworking: "nmcli networking on" + disableNetworking: "sudo ifconfig #{@WiFiControlSettings.iface} down" + enableNetworking: "sudo ifconfig #{@WiFiControlSettings.iface} up" resetWiFiChain = [ "disableNetworking", "enableNetworking" ] #