diff --git a/MikroTikAPI/nbproject/private/private.xml b/MikroTikAPI/nbproject/private/private.xml
index 6b5984a..e5c84c3 100644
--- a/MikroTikAPI/nbproject/private/private.xml
+++ b/MikroTikAPI/nbproject/private/private.xml
@@ -3,8 +3,11 @@
+ file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/Utils.java
+ file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/ops/AccessListEntry.java
file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/ops/Wireless.java
- file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/sample/TestApp.java
+ file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/ApiConnection.java
+ file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/MtSentence.java
file:/home/mh/Dvp/prj/MtUtils/MikroTikAPI/src/com/eightOceans/mikroTik/ops/OPs.java
diff --git a/MikroTikAPI/src/com/eightOceans/mikroTik/ApiConnection.java b/MikroTikAPI/src/com/eightOceans/mikroTik/ApiConnection.java
index c2fd085..304efab 100644
--- a/MikroTikAPI/src/com/eightOceans/mikroTik/ApiConnection.java
+++ b/MikroTikAPI/src/com/eightOceans/mikroTik/ApiConnection.java
@@ -26,14 +26,12 @@ import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
-
/**
*
* @author mh TODO: Improve listen/getData/readin
*/
public class ApiConnection {
-
private Socket sock;
private boolean isAuthenticated;
@@ -53,11 +51,9 @@ public class ApiConnection {
return null;
}
-
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
-
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
@@ -68,7 +64,6 @@ public class ApiConnection {
// return true;
// }
// };
-
private void ensureSockClosed() {
try {
if (sock != null) {
@@ -84,13 +79,11 @@ public class ApiConnection {
}
}
-
private String getData() throws InterruptedException {
String s = (String) queue.take();
return s;
}
-
private void listen() {
if (this.isConnected()) {
if (readCommand == null) {
@@ -104,7 +97,6 @@ public class ApiConnection {
}
}
-
public Future close() {
return pool.submit(new Callable() {
@@ -119,17 +111,14 @@ public class ApiConnection {
});
}
-
public boolean isAuthenticated() {
return isAuthenticated;
}
-
public boolean isConnected() {
return sock != null;
}
-
public Future login(String user, String password) {
return pool.submit(new Callable() {
@@ -190,7 +179,6 @@ public class ApiConnection {
);
}
-
public Future open(String host, int port, SSLMode sslMode) {
return pool.submit(new Callable() {
@@ -249,7 +237,6 @@ public class ApiConnection {
});
}
-
/**
* sets and exectues command (sends it to RouterOS host connected)
*
@@ -261,7 +248,6 @@ public class ApiConnection {
return writeCommand.setCommand(s).runCommand();
}
-
public Future readData() {
return pool.submit(new Callable() {
@@ -272,7 +258,6 @@ public class ApiConnection {
});
}
-
public ReadDataResult readDataSync() {
try {
String g = getData();
@@ -288,5 +273,73 @@ public class ApiConnection {
}
}
+ public static interface IReadGetReplyCb {
+ /**
+ * Sentence with data (getWords())
+ * @param dataSentence
+ */
+ public void handle(MtSentence dataSentence);
+ }
+
+ /**
+ * Read the reply to an find/get command
+ * @return Result
+ */
+ public Result readGetReplySync(IReadGetReplyCb cb) {
+ Result res = new Result();
+ res.Success = true;
+ ReadDataResult r = readDataSync();
+ while (true) {
+ if (!r.Success) {
+ res.Success = false;
+ res.ResultMessage = "Error reading reply" + r.ResultMessage;
+ break;
+ } else {
+ res.Success = true;
+ MtSentence ms = MtSentence.from(r.Data);
+ if (ms.isTrap()) {
+ res.Success = false;
+ res.ResultMessage = "Remote sent trap: " + ms.getTrapMsg();
+ break;
+ } else if (ms.isDone()) {
+ break;
+ } else {
+ cb.handle(ms);
+ }
+ }
+ }
+ return res;
+ }
+
+
+ /**
+ * Read the reply to an set/add/delete command
+ * @return Result
+ */
+ public Result readUpdateReplySync() {
+ Result res = new Result();
+ res.Success = true;
+ ReadDataResult r = readDataSync();
+ while (true) {
+ if (!r.Success) {
+ res.Success = false;
+ res.ResultMessage = "Error reading reply" + r.ResultMessage;
+ break;
+ } else {
+ MtSentence ms = MtSentence.from(r.Data);
+ if (ms.isTrap()) {
+ res.Success = false;
+ res.ResultMessage = "Failed, remote sent trap: " + ms.getTrapMsg();
+ break;
+ } else if (ms.isDone()) {
+ break;
+ } else {
+ res.Success = false;
+ res.ResultMessage = "Failed, remote sent unexpected result";
+ }
+ }
+ }
+ return res;
+ }
}
diff --git a/MikroTikAPI/src/com/eightOceans/mikroTik/MtSentence.java b/MikroTikAPI/src/com/eightOceans/mikroTik/MtSentence.java
index 0e374fd..f8fb04b 100644
--- a/MikroTikAPI/src/com/eightOceans/mikroTik/MtSentence.java
+++ b/MikroTikAPI/src/com/eightOceans/mikroTik/MtSentence.java
@@ -39,12 +39,10 @@ public class MtSentence {
} else {
throw new UnsupportedOperationException("Unsupported word in rawString: " + w);
}
-
-
}
- if ((!s.isDone) /*&& (!s.isTrap)*/) {
+ // if ((!s.isDone) /*&& (!s.isTrap)*/) {
s.words = newWords;
- }
+ //}
return s;
}
diff --git a/MikroTikAPI/src/com/eightOceans/mikroTik/ops/AccessListEntry.java b/MikroTikAPI/src/com/eightOceans/mikroTik/ops/AccessListEntry.java
index 057be4a..3566fd2 100644
--- a/MikroTikAPI/src/com/eightOceans/mikroTik/ops/AccessListEntry.java
+++ b/MikroTikAPI/src/com/eightOceans/mikroTik/ops/AccessListEntry.java
@@ -15,8 +15,11 @@ public class AccessListEntry {
e.forwarding = true;
e.minSigStrength = -120;
e.maxSigStrength = 120;
- e.algo = "aes-ccm";
- e.privateKey = Utils.createPrivateWifiKey();
+ e.iface = "all";
+ //e.algo = "aes-ccm";
+ //e.privateKey = Utils.createPrivateWifiKey();
+ e.algo = "none";
+ e.privateKey = "";
e.preSharedKey = Utils.createPresharedWifiKey(12,14,1,2);
return e;
@@ -24,13 +27,28 @@ public class AccessListEntry {
public String id;
public String comment;
+ public String iface;
public String macAddress;
public int minSigStrength;
public int maxSigStrength;
public boolean forwarding;
public boolean authentication;
+ /**
+ * Unclear purpose, not used in our scenario. Propably for old-style WEP.
+ * We enforce strong crypto via the wifi-security-profiles,
+ *and override only the specific password per client
+ */
public String algo;
+ /**
+ * Unclear purpose, not used in our scenario. Propably for old-style WEP.
+ * We enforce strong crypto via the wifi-security-profiles,
+ *and override only the specific password per client
+ */
public String privateKey;
+ /**
+ * Insert password here, to override the one set in the
+ * wifi-security-profiles
+ */
public String preSharedKey;
public String managementProtectionKey;
public boolean disabled;
diff --git a/MikroTikAPI/src/com/eightOceans/mikroTik/ops/Wireless.java b/MikroTikAPI/src/com/eightOceans/mikroTik/ops/Wireless.java
index 463d962..2485264 100644
--- a/MikroTikAPI/src/com/eightOceans/mikroTik/ops/Wireless.java
+++ b/MikroTikAPI/src/com/eightOceans/mikroTik/ops/Wireless.java
@@ -39,8 +39,18 @@ public class Wireless {
sb.append("set\n");
}
- sb.append("=comment=" + e.comment + "\n");
- sb.append("=mac-address=" + e.macAddress + "\n");
+ sb.append("=comment=" + N2E(e.comment) + "\n");
+ sb.append("=authentication=" + (e.authentication ? "true" : "false") + "\n");
+
+ sb.append("=disabled=" + (e.disabled ? "true" : "false") + "\n");
+ sb.append("=forwarding=" + (e.forwarding ? "true" : "false") + "\n");
+ sb.append("=interface=" + N2E(e.iface) + "\n");
+ sb.append("=mac-address=" + N2E(e.macAddress) + "\n");
+ sb.append("=management-protection-key=" + N2E(e.managementProtectionKey) + "\n");
+ sb.append("=signal-range=" + e.minSigStrength + ".." + e.maxSigStrength + "\n");
+ sb.append("=private-pre-shared-key=" + N2E(e.preSharedKey) + "\n");
+ sb.append("=private-algo=" + N2E(e.algo) + "\n");
+ sb.append("=private-key=" + N2E(e.privateKey) + "\n");
if ((e.id != null) && (!"".equals(e.id))) {
sb.append("=.id=" + e.id + "\n");
@@ -49,34 +59,52 @@ public class Wireless {
conn.sendCommand(sb.toString());
- Result res = new Result();
- ReadDataResult r = conn.readDataSync();
- while (true) {
- if (!r.Success) {
- res.Success = false;
- res.ResultMessage = "AccessList update failed: " + r.ResultMessage;
- break;
- } else {
- MtSentence ms = MtSentence.from(r.Data);
- if (ms.isTrap()) {
- res.Success = false;
- res.ResultMessage = "AccessList update failed, remote sent trap: " + ms.getTrapMsg();
- break;
- } else if (ms.isDone()) {
- res.Success = true;
- break;
- } else {
- res.Success = false;
- res.ResultMessage = "AccessList update failed, remote sent unexpected result";
- }
-
- }
+ Result res = conn.readUpdateReplySync();
+ if (!res.Success) {
+ res.ResultMessage = "AccessList update: " + res.ResultMessage;
}
return res;
}
});
}
+ public Future remove(AccessListEntry e) {
+
+ return pool.submit(new Callable() {
+
+ @Override
+ public Result call() throws Exception {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("/interface/wireless/access-list/");
+ if ((e.id == null) || ("".equals(e.id))) {
+ throw new IllegalArgumentException("Can't del entry w/o ID");
+ } else {
+ sb.append("remove\n");
+ }
+
+ sb.append("=.id=" + e.id + "\n");
+
+ sb.append("!done");
+
+ conn.sendCommand(sb.toString());
+
+ Result res = conn.readUpdateReplySync();
+ if (!res.Success) {
+ res.ResultMessage = "AccessList delete: " + res.ResultMessage;
+ }
+ return res;
+ }
+ });
+ }
+
+ private static String N2E(String s) {
+ if (s == null) {
+ return "";
+ }
+ return s;
+ }
+
public Future>> getAccessListEntries() {
return pool.submit(new Callable>>() {
@@ -104,6 +132,8 @@ public class Wireless {
} else if (ms.isDone()) {
break;
} else {
+ res.Success = false;
+ res.ResultMessage = "AccessList update failed, remote sent unexpected result";
/*
.id=*1B
=mac-address=00:00:00:00:00:01
@@ -120,13 +150,16 @@ public class Wireless {
=disabled=false
=comment=#GEND0001# Vla
*/
+
AccessListEntry ale = AccessListEntry.createWithDefault();
ale.comment = ms.getWordAsMap().get("comment");
ale.algo = ms.getWordAsMap().get("private-algo");
+ ale.privateKey = ms.getWordAsMap().get("private-key");
ale.authentication = "true".equals(ms.getWordAsMap().get("authentication"));
ale.disabled = "true".equals(ms.getWordAsMap().get("disabled"));
ale.forwarding = "true".equals(ms.getWordAsMap().get("forwarding"));
ale.id = ms.getWordAsMap().get(".id");
+ ale.iface = ms.getWordAsMap().get("interface");
ale.macAddress = ms.getWordAsMap().get("mac-address");
ale.managementProtectionKey = ms.getWordAsMap().get("management-protection-key");
String sigRange = ms.getWordAsMap().get("signal-range");
@@ -148,8 +181,7 @@ public class Wireless {
break;
}
}
- ale.preSharedKey = ms.getWordAsMap().get("private-pre-shared-key");
- ale.privateKey = ms.getWordAsMap().get("private-key");
+ ale.preSharedKey = ms.getWordAsMap().get("private-pre-shared-key");
resLst.add(ale);
}
}
diff --git a/MtWifiUserConfig/config.properties b/MtWifiUserConfig/config.properties
index 862bce9..4292961 100644
--- a/MtWifiUserConfig/config.properties
+++ b/MtWifiUserConfig/config.properties
@@ -3,8 +3,27 @@ AP_1_PORT=8729
AP_1_USER=rcfg
AP_1_PWPREF=0a
+#AP_2=192.168.61.220
+#AP_2_PORT=8729
+#AP_2_USER=rcfg
+#AP_2_PWPREF=0a
+
DEV_1=MK Iphone 7
DEV_1_MAC=01:01:01:01:01:02
DEV_1_KEY=saldk9012LLada
+DEV_1_IFACE=wlan2
DEV_1_MINDB=-70
+
+DEV_2=MH IPAD
+DEV_2_MAC=9C:04:EB:98:A5:67
+DEV_2_KEY=lalalala
+DEV_2_IFACE=wlan2
+DEV_2_MINDB=-73
+
+DEV_3=MH Notebook
+DEV_3_MAC=03:01:01:01:01:08
+DEV_3_KEY=lalalala
+DEV_3_IFACE=wlan2
+DEV_3_MINDB=-75
+
diff --git a/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/DevDef.java b/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/DevDef.java
index 2a03100..c4e30fb 100644
--- a/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/DevDef.java
+++ b/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/DevDef.java
@@ -9,6 +9,7 @@ package com.eightOceans.mtWifiUserConfig;
public class DevDef {
public int index;
public String name;
+ public String iface;
public String mac;
public String preshareKey;
public int minDbAllowed;
diff --git a/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/Main.java b/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/Main.java
index ba2704f..2a56e35 100644
--- a/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/Main.java
+++ b/MtWifiUserConfig/src/com/eightOceans/mtWifiUserConfig/Main.java
@@ -19,6 +19,7 @@ import java.util.concurrent.TimeoutException;
*
* @author mh
*/
+// Restliche Features: Multiple Iface support, Output-Optimierung
public class Main {
private final static String VERS = "0.0.1";
@@ -57,16 +58,29 @@ public class Main {
// load
i = 0;
- while (true) {
+ int e = 0;
+ while (e < 100) {
i++;
_currOp = "Checking Device " + i + " config";
DevDef dev = new DevDef();
dev.index = i;
dev.name = props.getProperty("DEV_" + i, null);
if (dev.name == null) {
- break;
+ e++;
+ continue;
+ }
+ e = 0;
+ if (dev.name.length() > 16) {
+ throw new RuntimeException("Length of naem must be 1-16");
}
dev.mac = props.getProperty("DEV_" + i + "_MAC", null);
+ if ((dev.mac == null) || (dev.mac.length() != 3 * 6 - 1)) {
+ throw new RuntimeException("Length of mac must be 17");
+ }
+ dev.iface = props.getProperty("DEV_" + i + "_IFACE", null);
+ if ((dev.iface == null) || (dev.iface.length() > 16)) {
+ throw new RuntimeException("Length of iface must be 1-16");
+ }
dev.preshareKey = props.getProperty("DEV_" + i + "_KEY", null);
if ((dev.preshareKey == null) || (dev.preshareKey.length() < 8)) {
throw new RuntimeException("Preshared key too short. must min 8 chars!");
@@ -99,10 +113,13 @@ public class Main {
} catch (Exception ex) {
System.out.println("! While " + _currOp + ": " + ex.getMessage());
+ System.out.println("* Done");
+ System.exit(1);
}
_currOp = "Done";
System.out.println("* Done");
+ System.exit(0);
}
private static Properties loadProps() {
@@ -123,6 +140,7 @@ public class Main {
GETENTRIES,
UPDATEENTRIES,
FAILED,
+ RECONNECT,
EXIT,
DONE
}
@@ -140,12 +158,21 @@ public class Main {
OPs mtOps = new OPs(conn);
List entries = null;
+ List toDel = new ArrayList();
+ List toUpd = new ArrayList();
+
CommState cs = CommState.CONNECT;
while (cs != CommState.DONE) {
try {
Result r;
switch (cs) {
+ case RECONNECT:
+ conn.close();
+ conn = new ApiConnection();
+ mtOps = new OPs(conn);
+ cs = CommState.CONNECT;
+ break;
case CONNECT:
setCurrOp("Connecting to ap " + ap.host);
r = conn.open(ap.host, ap.port, SSLMode.Weak).get(to, TimeUnit.SECONDS);
@@ -160,7 +187,11 @@ public class Main {
setCurrOp("Login to " + ap.host);
r = conn.login(ap.user, ap.pwPrefix + remPw).get(to, TimeUnit.SECONDS);
if (r.Success) {
- cs = cs.GETENTRIES;
+ if (entries == null) {
+ cs = cs.GETENTRIES;
+ } else {
+ cs = CommState.UPDATEENTRIES;
+ }
} else {
errMsg = "Login Failed: " + r.ResultMessage;
cs = CommState.FAILED;
@@ -171,6 +202,7 @@ public class Main {
Result> getRes = mtOps.getWireless().getAccessListEntries().get(to, TimeUnit.SECONDS);
if (getRes.Success) {
entries = getRes.Result;
+ findChanges(devs, entries, toDel, toUpd);
cs = cs.UPDATEENTRIES;
} else {
errMsg = "Getting access entries failed: " + getRes.ResultMessage;
@@ -178,19 +210,34 @@ public class Main {
}
break;
case UPDATEENTRIES:
- List toDel = new ArrayList();
- List toUpd = new ArrayList();
- findChanges(devs, entries, toDel, toUpd);
- for (AccessListEntry e : toUpd) {
- setCurrOp("Updating '" + e.comment + "' on " + ap.host);
+ while (toUpd.size() > 0) {
+ AccessListEntry e = toUpd.remove(0);
+ setCurrOp("Updating '" + e.comment + "' on " + ap.host);
Result uRes = mtOps.getWireless().createOrUpdate(e).get(to, TimeUnit.SECONDS);
if (!uRes.Success) {
System.out.println(".... Update failed:" + uRes.ResultMessage);
+ cs = CommState.RECONNECT;
+ break;
}
}
- setCurrOp("Updating ended");
- cs = CommState.EXIT;
+ if (cs != CommState.RECONNECT) {
+ while (toDel.size() > 0) {
+ AccessListEntry e = toDel.remove(0);
+ setCurrOp("Deleting '" + e.comment + "' on " + ap.host);
+ Result uRes = mtOps.getWireless().remove(e).get(to, TimeUnit.SECONDS);
+ if (!uRes.Success) {
+ System.out.println(".... Delete failed:" + uRes.ResultMessage);
+ cs = CommState.RECONNECT;
+ break;
+ }
+ }
+ }
+ if (cs != CommState.RECONNECT) {
+ setCurrOp("Updating ended");
+ cs = CommState.EXIT;
+ }
break;
+
case FAILED:
System.out.println(" ! " + (errMsg != null ? errMsg : (_currOp + " Failed")) + "! Skipping this AP");
cs = CommState.EXIT;
@@ -261,6 +308,10 @@ public class Main {
t.preSharedKey = dev.preshareKey;
chg = true;
}
+ if (!Objects.equals(dev.iface, t.iface)) {
+ t.iface = dev.iface;
+ chg = true;
+ }
if (chg) {
toUpd.add(t);