diff options
Diffstat (limited to 'app/src/fil/libre/repwifiapp/network/Engine6p0.java')
-rw-r--r-- | app/src/fil/libre/repwifiapp/network/Engine6p0.java | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/app/src/fil/libre/repwifiapp/network/Engine6p0.java b/app/src/fil/libre/repwifiapp/network/Engine6p0.java new file mode 100644 index 0000000..c6475e2 --- /dev/null +++ b/app/src/fil/libre/repwifiapp/network/Engine6p0.java @@ -0,0 +1,315 @@ +// +// Copyright 2017, 2018 Filippo "Fil" Bergamo <fil.bergamo@riseup.net> +// +// This file is part of RepWifiApp. +// +// RepWifiApp is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// RepWifiApp is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with RepWifiApp. If not, see <http://www.gnu.org/licenses/>. +// +// ******************************************************************** + +package fil.libre.repwifiapp.network; + +import fil.libre.repwifiapp.Commons; +import fil.libre.repwifiapp.helpers.Logger; +import fil.libre.repwifiapp.helpers.RootCommand; +import fil.libre.repwifiapp.helpers.ShellCommand; +import org.apache.http.conn.util.InetAddressUtils; + +public class Engine6p0 extends Engine { + + private Object abortFlagSync = new Object(); + private boolean abortConnectionSignaled = false; + + @Override + public int connect(AccessPointInfo info) { + + WpaSupplicant.kill(); + + + if (info == null) { + Logger.logDebug("Engine's connect() received a null AccessPointInfo"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // clear any previously set network + if (!destroyNetwork()) { + Logger.logDebug("Unable to ndc destroy network"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // clear interface's ip + if (!clearAddrs()) { + Logger.logDebug("Unable to ndc clearaddrs"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // bring up interface + if (!interfaceUp()) { + Logger.logDebug("Unable to bring up interface."); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // launch wpa_supplicant specifying our custom configuration and the + // socket file + if (!WpaSupplicant.start()) { + Logger.logDebug("Unable to run wpa start"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // create new network and get network id + String netID = WpaCli.createNetworkGetId(); + if (netID == null) { + Logger.logDebug("Unable to fetch network id"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // set network SSID + if (!WpaCli.setNetworkSSID(info.getSsid(), netID)) { + Logger.logDebug("Failed to set network ssid"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + if (info.isHidden() && !WpaCli.setNetworkScanSSID(netID)) { + Logger.logDebug("Failed to set scan_ssid 1 for hidden network."); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // set password (if any) + if (!WpaCli.setNetworkPSK(info, netID)) { + Logger.logDebug("Failed to set network psk"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // select the network we just created + if (!WpaCli.selectNetwork(netID)) { + Logger.logDebug("Unable to wpa_cli select network"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // enable the newtork + if (!WpaCli.enableNetwork(netID)) { + Logger.logDebug("Unable to wpa_cli enable_newtork"); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // kill previous dhchcd instances + if (!killDhcpcd()) { + Logger.logError("Unable to kill previous instances of dhcpcd"); + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // get DHCP + Logger.logDebug("Attempt to run dhcpcd.."); + try { + + int retcode = runDhcpcd(info.getDhcpConfiguration()); + if (retcode == 1) { + Logger.logDebug("Dhcpcd exited on timeout exceeded."); + return ConnectionResult.CONN_TIMEOUT; + + } else if (retcode != 0) { + Logger.logDebug("Dhcpcd exited with unknown code: " + retcode); + return ConnectionResult.CONN_FAILED; + + } + } catch (Exception e) { + Logger.logError("Exception while executing dhcpcd: ", e); + return ConnectionResult.CONN_FAILED; + } + + if (!checkAbortSignal()) + return ConnectionResult.CONN_ABORTED; + + // try to fetch gateway + String gw = getGateWayTimeout(Commons.WAIT_FOR_GATEWAY); + if (gw == null || !InetAddressUtils.isIPv4Address(gw)) { + // failed to get gateway + Logger.logDebug("Failed to get gateway"); + return ConnectionResult.CONN_GW_FAIL; + } + + /* + * Calls to ndc to set gateway and dns were removed 2018-04-09 + * Starting from 2018-04-20, RepWifi registers itself as a NetworkAgent. + * When we register, all the following steps are performed by + * ConnectivityService itself: + * - creating a new network + * - setting the gateway + * - setting DNS + * There is no reason to perform those actions on our side via the command line; + * it would conflict with ConnectivityService's calls to "ndc" + */ + + return ConnectionResult.CONN_OK; + + } + + public void abortConnection() { + synchronized (abortFlagSync) { + this.abortConnectionSignaled = true; + } + } + + @Override + public ConnectionStatus getConnectionStatus() { + ConnectionStatus s = super.getConnectionStatus(); + if (s == null) { + return null; + } + + s.gateway = this.getGateway(); + + return s; + } + + private boolean checkAbortSignal() { + + synchronized (abortFlagSync) { + if (abortConnectionSignaled) { + abortConnectionSignaled = false; + Logger.logDebug("Engine received abort connection signal. Aborting connection..."); + killDhcpcd(); + disconnect(); + return false; + } else { + return true; + } + } + } + + private boolean destroyNetwork() { + + // needs root (tested) + return RootCommand.executeRootCmd("ndc network destroy 1"); + } + + private String getGateWayTimeout(int timeoutMillis) { + + String gw = getGateway(); + if (gw != null && !gw.trim().isEmpty()) { + return gw; + } + + Logger.logDebug("Gateway not available.. going into wait loop.."); + + // gateway not (yet) available + // waits for a maximum of timeoutMillis milliseconds + // to let the interface being registered. + int msWaited = 0; + while (msWaited < timeoutMillis) { + + try { + Thread.sleep(100); + } catch (Exception e) { + return null; + } + msWaited += 100; + + gw = getGateway(); + if (gw != null && !gw.trim().isEmpty()) { + Logger.logDebug("Gateway found after wait loop!"); + return gw; + } + } + + // unable to get gateway + Logger.logError("Gateway not found after wait loop."); + return null; + + } + + private String getGateway() { + + try { + + // doesn't need root (tested) + ShellCommand cmd = new ShellCommand("ip route show dev " + WpaSupplicant.INTERFACE_NAME); + if (cmd.execute() != 0) { + Logger.logDebug("command failed show route"); + return null; + } + + // read command output + String out = cmd.getOutput(); + if (out == null) { + return null; + } + + String[] lines = out.split("\n"); + + for (String l : lines) { + + if (l.contains("default via")) { + + String[] f = l.split(" "); + if (f.length > 2) { + + // found route's address: + return f[2]; + + } + } + } + + return null; + + } catch (Exception e) { + Logger.logError("Error while trying to fetch route", e); + return null; + } + + } + + private boolean clearAddrs() { + // needs root (tested) + return RootCommand.executeRootCmd("ndc interface clearaddrs " + + WpaSupplicant.INTERFACE_NAME); + } + +}
\ No newline at end of file |