Fix static IP and network settings on Pi

This commit is contained in:
Matt
2020-09-15 11:34:27 -07:00
committed by GitHub
parent 71fc8a7017
commit 44bfc3ea6c
10 changed files with 160 additions and 318 deletions

View File

@@ -162,7 +162,7 @@ public class Main {
// Force load the hardware manager
HardwareManager.getInstance();
NetworkManager.getInstance().initialize(false);
NetworkManager.getInstance().reinitialize();
NetworkTablesManager.getInstance()
.setConfig(ConfigManager.getInstance().getConfig().getNetworkConfig());

View File

@@ -26,7 +26,6 @@ public class NetworkConfig {
public int teamNumber = 0;
public NetworkMode connectionType = NetworkMode.DHCP;
public String staticIp = "";
public String netmask = "";
public String hostname = "photonvision";
public boolean runNTServer = false;
@@ -38,18 +37,16 @@ public class NetworkConfig {
int teamNumber,
NetworkMode connectionType,
String staticIp,
String netmask,
String hostname,
boolean runNTServer,
boolean shouldManage) {
this.teamNumber = teamNumber;
this.connectionType = connectionType;
this.staticIp = staticIp;
this.netmask = netmask;
this.hostname = hostname;
this.runNTServer = runNTServer;
this.shouldManage = shouldManage || Platform.isRaspberryPi();
this.shouldManage = shouldManage;
}
public static NetworkConfig fromHashMap(Map<String, Object> map) {
@@ -60,7 +57,6 @@ public class NetworkConfig {
ret.shouldManage = (Boolean) map.get("supported");
ret.connectionType = NetworkMode.values()[(Integer) map.get("connectionType")];
ret.staticIp = (String) map.get("staticIp");
ret.netmask = (String) map.get("netmask");
ret.hostname = (String) map.get("hostname");
ret.runNTServer = (Boolean) map.get("runNTServer");
return ret;
@@ -69,12 +65,15 @@ public class NetworkConfig {
public HashMap<String, Object> toHashMap() {
HashMap<String, Object> tmp = new HashMap<>();
tmp.put("teamNumber", teamNumber);
tmp.put("supported", shouldManage);
tmp.put("supported", shouldManage());
tmp.put("connectionType", connectionType.ordinal());
tmp.put("staticIp", staticIp);
tmp.put("netmask", netmask);
tmp.put("hostname", hostname);
tmp.put("runNTServer", runNTServer);
return tmp;
}
public boolean shouldManage() {
return this.shouldManage || Platform.isRaspberryPi();
}
}

View File

@@ -46,8 +46,6 @@ public class NetworkTablesManager {
private static final Logger logger = new Logger(NetworkTablesManager.class, LogGroup.General);
public boolean isServer = false;
private static class NTLogger implements Consumer<LogMessage> {
private boolean hasReportedConnectionFailure = false;
@@ -77,7 +75,6 @@ public class NetworkTablesManager {
}
private void setClientMode(int teamNumber) {
isServer = false;
logger.info("Starting NT Client");
ntInstance.stopServer();
@@ -91,7 +88,6 @@ public class NetworkTablesManager {
}
private void setServerMode() {
isServer = true;
logger.info("Starting NT Server");
ntInstance.stopClient();
ntInstance.startServer();

View File

@@ -1,121 +0,0 @@
/*
* Copyright (C) 2020 Photon Vision.
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.photonvision.common.networking;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
public class LinuxNetworking extends SysNetworking {
private static final String PATH = "/etc/dhcpcd.conf";
private Logger logger = new Logger(LinuxNetworking.class, LogGroup.General);
@Override
public boolean setDHCP() {
File dhcpConf = new File(PATH);
logger.debug("Removing static IP from " + PATH);
if (dhcpConf.exists()) {
try {
List<String> lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8);
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (line.startsWith("interface " + networkInterface.name)) {
lines.remove(i);
for (int j = i; j < lines.size(); j++) {
String subInterface = lines.get(j);
if (subInterface.contains("static ip_address")
|| subInterface.contains("static routers")) {
lines.remove(j);
j--;
}
if (subInterface.contains("interface")) {
break;
}
}
FileUtils.writeLines(dhcpConf, lines);
return true;
}
}
} catch (IOException e) {
logger.error("Failed to set DHCP!", e);
return false;
}
} else {
logger.error("dhcpcd5 is not installed, unable to set IP.");
return false;
}
return true;
}
@Override
public boolean setHostname(String newHostname) {
try {
var setHostnameRetCode = shell.execute("hostnamectl", "set-hostname", newHostname);
return setHostnameRetCode == 0;
} catch (Exception e) {
logger.error("Failed to set hostname!", e);
return false;
}
}
@Override
public boolean setStatic(String ipAddress, String netmask) {
setDHCP(); // clean up old static interface
File dhcpConf = new File(PATH);
try {
List<String> lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8);
lines.add("interface " + networkInterface.name);
InetAddress iNetMask = InetAddress.getByName(netmask);
int prefix = convertNetmaskToCIDR(iNetMask);
lines.add("static ip_address=" + ipAddress + "/" + prefix);
FileUtils.writeLines(dhcpConf, lines);
return true;
} catch (IOException e) {
logger.error("Failed to set Static IP!", e);
}
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

@@ -76,12 +76,20 @@ public class NetworkManager {
}
if (config.connectionType == NetworkMode.DHCP) {
return; // TODO do we need to reconnect or something?
var shell = new ShellExec();
try {
if (config.staticIp != "") {
shell.executeBashCommand("ip addr del " + config.staticIp + "/8 dev eth0");
}
shell.executeBashCommand("dhclient eth0");
} catch (Exception e) {
logger.error("Exception while setting DHCP!");
}
} else if (config.connectionType == NetworkMode.STATIC) {
var shell = new ShellExec();
if (config.staticIp.length() > 0) {
try {
shell.executeBashCommand("ip addr add " + config.staticIp + "/24" + " dev eth0");
shell.executeBashCommand("ip addr add " + config.staticIp + "/8" + " dev eth0");
} catch (Exception e) {
logger.error("Error while setting static IP!", e);
}
@@ -95,6 +103,6 @@ public class NetworkManager {
}
public void reinitialize() {
initialize(ConfigManager.getInstance().getConfig().getNetworkConfig().shouldManage);
initialize(ConfigManager.getInstance().getConfig().getNetworkConfig().shouldManage());
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2020 Photon Vision.
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.photonvision.common.networking;
import java.io.IOException;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.List;
import org.photonvision.common.util.ShellExec;
public abstract class SysNetworking {
NetworkInterface networkInterface;
ShellExec shell = new ShellExec(true, true);
private String hostname = getHostname();
public String getHostname() {
if (hostname == null) {
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;
}
} else return hostname;
}
// code belongs to
// https://stackoverflow.com/questions/19531411/calculate-cidr-from-a-given-netmask-java
public static int convertNetmaskToCIDR(InetAddress netmask) {
byte[] netmaskBytes = netmask.getAddress();
int cidr = 0;
boolean zero = false;
for (byte b : netmaskBytes) {
int mask = 0x80;
for (int i = 0; i < 8; i++) {
int result = b & mask;
if (result == 0) {
zero = true;
} else if (zero) {
throw new IllegalArgumentException("Invalid netmask.");
} else {
cidr++;
}
mask >>>= 1;
}
}
return cidr;
}
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);
public abstract List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException;
}

View File

@@ -73,15 +73,8 @@ public class RequestHandler {
public static void onGeneralSettings(Context context) throws JsonProcessingException {
Map<String, Object> map =
(Map<String, Object>) kObjectMapper.readValue(context.body(), Map.class);
var networking =
(Map<String, Object>)
map.get("networkSettings"); // teamNumber (int), supported (bool), connectionType (int),
// staticIp (str), netmask (str), gateway (str), hostname (str)
var lighting =
(Map<String, Object>) map.get("lighting"); // supported (true/false), brightness (int)
// TODO do stuff with lighting
var networkConfig = NetworkConfig.fromHashMap(networking);
var networkConfig = NetworkConfig.fromHashMap(map);
ConfigManager.getInstance().setNetworkSettings(networkConfig);
ConfigManager.getInstance().requestSave();
NetworkManager.getInstance().reinitialize();