Continued rework of networking, added root check

This commit is contained in:
Banks Troutman
2019-10-06 17:26:17 -04:00
parent 7699766091
commit 3db2f30ea7
18 changed files with 607 additions and 234 deletions

View File

@@ -0,0 +1,99 @@
package com.chameleonvision.network;
import com.chameleonvision.settings.NetworkSettings;
import com.chameleonvision.settings.SettingsManager;
import com.chameleonvision.util.ShellExec;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LinuxNetworking extends SysNetworking {
private ShellExec shell = new ShellExec(true, true);
@Override
public boolean setDHCP() {
var ifaceName = networkInterface.name;
var ethResetCmd = String.format("ifconfig %s 0.0.0.0 0.0.0.0", ifaceName);
var dhclientCmd = String.format("dhclient %s", ifaceName);
// ifconfig eth0 0.0.0.0 0.0.0.0
try {
int retCode = shell.execute("ifconfig", null, true, ifaceName, "0.0.0.0", "0.0.0.0");
while (!shell.isOutputCompleted() && !shell.isErrorCompleted()) {}
var out = shell.getOutput();
var err = shell.getError();
if (retCode != 0) return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
try {
int retCode = shell.execute("dhclient", null, true, ifaceName);
while (!shell.isOutputCompleted() && !shell.isErrorCompleted()) {}
var out = shell.getOutput();
var err = shell.getError();
if (retCode != 0) return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
public boolean setHostname(String newHostname) {
var cmdString = String.format("hostnamectl set-hostname %s", newHostname);
try {
var process = Runtime.getRuntime().exec(cmdString);
var returnCode = shell.execute("hostnamectl", null, true, "set-hostname", newHostname);
return returnCode == 0;
} catch(Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
try {
int clearRetCode = shell.execute("ip addr flush dev", null, true, networkInterface.name);
int setIPRetCode = shell.execute(String.format("ip addr add %s/%s broadcast %s dev %s", ipAddress, netmask, broadcast, networkInterface.name), null, true);
int setGatewayRetCode = shell.execute(String.format("ip route replace default via %s dev %s", gateway, networkInterface.name), null, false);
return clearRetCode == 0 && setIPRetCode == 0 && setGatewayRetCode == 0;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@Override
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
List<java.net.NetworkInterface> netInterfaces;
try {
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
return null;
}
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
for (var netInterface : netInterfaces) {
if (netInterface.getDisplayName().contains("lo")) continue;
if (!netInterface.isUp()) continue;
goodInterfaces.add(netInterface);
}
return goodInterfaces;
}
}

View File

@@ -0,0 +1,7 @@
package com.chameleonvision.network;
public enum NetworkIPMode {
DHCP,
STATIC,
UNKNOWN
}

View File

@@ -0,0 +1,57 @@
package com.chameleonvision.network;
import com.chameleonvision.settings.GeneralSettings;
import java.net.InetAddress;
import java.net.InterfaceAddress;
public class NetworkInterface {
public final String name;
public final String displayName;
public final String IPAddress;
public final String Netmask;
public final String Gateway;
public final String Broadcast;
public NetworkInterface(java.net.NetworkInterface inetface, InterfaceAddress ifaceAddress) {
name = inetface.getName();
displayName = inetface.getDisplayName();
var inetAddress = ifaceAddress.getAddress();
IPAddress = inetAddress.getHostAddress();
Netmask = getIPv4LocalNetMask(ifaceAddress);
// TODO: hack to "get" gateway, this is gross and bad, pls fix
var splitIPAddr = IPAddress.split("\\.");
splitIPAddr[3] = "1";
Gateway = String.join(".", splitIPAddr);
splitIPAddr[3] = "255";
Broadcast = String.join(".", splitIPAddr);
}
private static String getIPv4LocalNetMask(InterfaceAddress interfaceAddress) {
var netPrefix = interfaceAddress.getNetworkPrefixLength();
try {
// Since this is for IPv4, it's 32 bits, so set the sign value of
// the int to "negative"...
int shiftby = (1<<31);
// For the number of bits of the prefix -1 (we already set the sign bit)
for (int i = netPrefix - 1; i > 0; i--) {
// Shift the sign right... Java makes the sign bit sticky on a shift...
// So no need to "set it back up"...
shiftby = (shiftby >> 1);
}
// Transform the resulting value in xxx.xxx.xxx.xxx format, like if
/// it was a standard address...
String maskString = ((shiftby >> 24) & 255) + "." + ((shiftby >> 16) & 255) + "." + ((shiftby >> 8) & 255) + "." + (shiftby & 255);
// Return the address thus created...
return maskString;
// return InetAddress.getByName(maskString);
}
catch(Exception e) {
e.printStackTrace();
}
// Something went wrong here...
return null;
}
}

View File

@@ -0,0 +1,122 @@
package com.chameleonvision.network;
import com.chameleonvision.settings.NetworkSettings;
import com.chameleonvision.settings.Platform;
import com.chameleonvision.settings.SettingsManager;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class NetworkManager {
private NetworkManager() {}
protected static SysNetworking networking;
protected static NetworkInterface botInterface = null;
private static boolean isManaged = false;
public static void initialize(boolean manage) {
isManaged = manage;
if (!isManaged) {
return;
}
Platform platform = Platform.getCurrentPlatform();
if (platform.isLinux()) {
networking = new LinuxNetworking();
} else if (platform.isWindows()) {
// networking = new WindowsNetworking();
System.out.println("Windows networking is not yet supported. Running unmanaged.");
return;
}
List<java.net.NetworkInterface> interfaces = new ArrayList<>();
List<NetworkInterface> goodInterfaces = new ArrayList<>();
try {
interfaces = networking.getNetworkInterfaces();
} catch (SocketException e) {
e.printStackTrace();
}
var teamBytes = NetworkSettings.GetTeamNumberIPBytes(SettingsManager.GeneralSettings.team_number);
if (interfaces.size() > 0) {
for (var inetface : interfaces) {
for (var inetfaceAddr : inetface.getInterfaceAddresses()) {
var rawAddr = inetfaceAddr.getAddress().getAddress();
if (rawAddr.length > 4) continue;
if (rawAddr[1] == teamBytes[0] && rawAddr[2] == teamBytes[1]) {
goodInterfaces.add(new NetworkInterface(inetface, inetfaceAddr));
}
}
}
if (goodInterfaces.size() == 0) {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
return;
}
botInterface = goodInterfaces.get(0);
networking.setNetworkInterface(botInterface);
} else {
isManaged = false;
System.err.println("No valid network interfaces found! Staying unmanaged.");
return;
}
if(!loadFromGeneralSettings()) {
isManaged = false;
System.err.println("Failed to load network settings. Staying unmanaged!");
}
}
private static boolean loadFromGeneralSettings() {
if (!isManaged) {
return true;
}
var genSettings = SettingsManager.GeneralSettings;
boolean isStatic = genSettings.connection_type.toLowerCase().equals("Static");
if (isStatic) {
var splitIPAddr = genSettings.ip.split("\\.");
splitIPAddr[3] = "255";
var broadcast = String.join(".", splitIPAddr);
if (!setStatic(genSettings.ip, genSettings.netmask, genSettings.gateway, broadcast)) {
return false;
}
} else {
if (!setDHCP()) {
return false;
}
}
return setHostname(genSettings.hostname);
}
private static boolean setDHCP() {
if (!isManaged) {
return true;
}
return networking.setDHCP();
}
private static boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
if (!isManaged) {
return true;
}
return networking.setStatic(ipAddress, netmask, gateway, broadcast);
}
private static boolean setHostname(String hostname) {
if (!isManaged) {
return true;
}
return networking.setHostname(hostname);
}
}

View File

@@ -0,0 +1,37 @@
package com.chameleonvision.network;
import com.chameleonvision.util.ShellExec;
import java.io.IOException;
import java.net.SocketException;
import java.util.List;
import java.util.Scanner;
public abstract class SysNetworking {
NetworkInterface networkInterface;
ShellExec shell = new ShellExec(true, true);
public String getHostname() {
try {
var retCode = shell.execute("hostname", null, true);
if (retCode == 0) {
while(!shell.isOutputCompleted()) {}
return shell.getOutput();
} else {
return null;
}
} catch (IOException e) {
return null;
}
}
public void setNetworkInterface(NetworkInterface networkInterface) {
this.networkInterface = networkInterface;
}
public abstract boolean setDHCP();
public abstract boolean setHostname(String hostname);
public abstract boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast);
public abstract List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException;
}

View File

@@ -0,0 +1,57 @@
package com.chameleonvision.network;
import com.chameleonvision.settings.NetworkSettings;
import com.chameleonvision.settings.SettingsManager;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class WindowsNetworking extends SysNetworking {
@Override
public boolean setDHCP() {
return false;
}
@Override
public boolean setHostname(String newHostname) {
var currentHostname = getHostname();
if (getHostname() == null) {
return false;
}
String command = String.format("wmic computersystem where name=\"%s\" call rename name=\"%s\"", currentHostname, newHostname);
try {
var process = Runtime.getRuntime().exec(command);
var returnCode = process.waitFor();
return returnCode == 0;
} catch(Exception e) {
return false;
}
}
@Override
public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
return false;
}
@Override
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
var netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
for (var netInterface : netInterfaces) {
if (netInterface.getDisplayName().toLowerCase().contains("bluetooth")) continue;
if (netInterface.getDisplayName().toLowerCase().contains("virtual")) continue;
if (netInterface.getDisplayName().toLowerCase().contains("loopback")) continue;
if (!netInterface.isUp()) continue;
goodInterfaces.add(netInterface);
}
return goodInterfaces;
}
}