aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/fil/libre/repwifiapp/network/Engine6p0.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/fil/libre/repwifiapp/network/Engine6p0.java')
-rw-r--r--app/src/fil/libre/repwifiapp/network/Engine6p0.java315
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