Added processing of connections.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @author Aaron Moser
|
||||
* @date 28.12.2023
|
||||
*/
|
||||
package controller.src.DataProcessing.ConnectionsProcessing;
|
||||
|
||||
/**
|
||||
* Record displays packed information about one connection at the agent side.
|
||||
*/
|
||||
public final record ConnectionInformation(
|
||||
int fileDescriptor,
|
||||
String addressFamily,
|
||||
String socketKind,
|
||||
String localAddress,
|
||||
int localPort,
|
||||
String remoteAddress,
|
||||
int remotePort,
|
||||
String status,
|
||||
int pid) {
|
||||
|
||||
public boolean equals(ConnectionInformation other) {
|
||||
return this.fileDescriptor == other.fileDescriptor && this.pid == other.pid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/**
|
||||
* @author Aaron Moser
|
||||
* @date 28.12.2023
|
||||
*/
|
||||
package controller.src.DataProcessing.ConnectionsProcessing;
|
||||
|
||||
/**
|
||||
* Provides a function to retrieve information from a connection string.
|
||||
* sconn(fd=9, family=<AddressFamily.AF_UNIX: 1>, type=<SocketKind.SOCK_STREAM: 1>, laddr='', raddr='', status='NONE', pid=1789)
|
||||
* fd stands for file descriptor
|
||||
* laddr: local address
|
||||
* raddr: remote address
|
||||
* pid stands for process id
|
||||
*/
|
||||
public final class ConnectionsProcessor {
|
||||
private static final int HEAD_LENGTH = 6;
|
||||
private static final int TAIL_LENGTH = 1;
|
||||
|
||||
private static final String[] ADDRESS_FAMILIES = {
|
||||
"AF_UNIX", // Unix domain sockets
|
||||
"AF_LOCAL", // Unix domain sockets
|
||||
"AF_INET", // IPv4 communication
|
||||
"AF_INET6", // IPv6 communication
|
||||
"AF_NETLINK", // Used for communication with the Linux kernel using the Netlink protocol
|
||||
"AF_PACKET", // Low-level packet manipulation
|
||||
"AF_BLUETOOTH", // Bluetooth communication
|
||||
"AF_CAN", // Controller Area Network (CAN) communication
|
||||
"AF_RDS", // Reliable Datagram Sockets (RDS) communication
|
||||
"AF_ALG", // Cryptographic socket support
|
||||
"AF_VSOCK", // Virtual Socket (vsock) communication for hypervisor-based applications
|
||||
"AF_XDP" // eXpress Data Path (XDP) socket family for high-performance packet processing
|
||||
};
|
||||
|
||||
private static final String[] SOCKET_KINDS = {
|
||||
"SOCK_STREAM", // provides a reliable, stream-oriented connection, typically used for TCP sockets
|
||||
"SOCK_DGRAM", // provides a connectionless, unreliable communication method, typically used for UDP sockets
|
||||
"SOCK_RAW", // allows low-level access to network protocols, often used for custom packet manipulation
|
||||
"SOCK_SEQPACKET", // similar to SOCK_STREAM but provides a record-oriented, connection-based socket
|
||||
"SOCK_RDM", // reliable datagram sockets
|
||||
"SOCK_PACKET" // used for low-level packet capture and injection
|
||||
};
|
||||
|
||||
private static final String[] CONNECTION_STATUSES = {
|
||||
"NONE",
|
||||
"ESTABLISHED", // socket connection is established and data can be exchanged
|
||||
"LISTEN", // socket is listening for incoming connections
|
||||
"CLOSE_WAIT", // socket is waiting for the remote end to close the connection
|
||||
"TIME_WAIT", // socket is waiting for any remaining packets to arrive after the connection is closed
|
||||
"CLOSED", // socket is closed and no longer in use
|
||||
"SYN_SENT", // socket has sent a SYN packet to initiate a connection
|
||||
"SYN_RECEIVED", // socket has received a SYN packet and is waiting for an ACK to complete the connection establishment
|
||||
"FIN_WAIT1", // socket is in the process of closing the connection
|
||||
"FIN_WAIT2" // socket is in the process of closing the connection
|
||||
};
|
||||
|
||||
/**
|
||||
* Processes a data string which contains the information about one connection at the agents side.
|
||||
* @param dataString the string which contains the information.
|
||||
* @return an object of type ConnectionInformation.
|
||||
*/
|
||||
public static ConnectionInformation processDataString(String dataString) {
|
||||
String[] dataStringParts = removeHeadAndTail(dataString).split(" ");
|
||||
|
||||
int fileDescriptor = -1;
|
||||
String addressFamily = "";
|
||||
String socketKind = "";
|
||||
String localAddress = "";
|
||||
int localPort = -1;
|
||||
String remoteAddress = "";
|
||||
int remotePort = -1;
|
||||
String status = "";
|
||||
int pid = -1;
|
||||
|
||||
for (int i = 0; i < dataStringParts.length; i++) {
|
||||
String part = dataStringParts[i];
|
||||
|
||||
if (part.startsWith("fd")) {
|
||||
fileDescriptor = processFileDescriptor(part);
|
||||
|
||||
} else if (part.startsWith("family")) {
|
||||
addressFamily = processAddressFamily(part);
|
||||
|
||||
} else if (part.startsWith("type")) {
|
||||
socketKind = processSocketKind(part);
|
||||
|
||||
} else if (part.startsWith("laddr")) {
|
||||
localAddress = processAddress(part);
|
||||
// Check if entry after is of type port
|
||||
if (dataStringParts[i+1].startsWith("port")) {
|
||||
localPort = processPort(dataStringParts[i+1]);
|
||||
i++;
|
||||
}
|
||||
} else if (part.startsWith("raddr")) {
|
||||
remoteAddress = processAddress(part);
|
||||
// CHeck if entry after is of type port
|
||||
if (dataStringParts[i+1].startsWith("port")) {
|
||||
remotePort = processPort(dataStringParts[i+1]);
|
||||
i++;
|
||||
}
|
||||
} else if (part.startsWith("status")) {
|
||||
status = processStatus(part);
|
||||
|
||||
} else if (part.startsWith("pid")) {
|
||||
pid = processPID(part);
|
||||
|
||||
} else {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
return new ConnectionInformation(fileDescriptor, addressFamily, socketKind, localAddress, localPort, remoteAddress, remotePort, status, pid);
|
||||
}
|
||||
|
||||
private static String removeHeadAndTail(String input) {
|
||||
return input.substring(HEAD_LENGTH, input.length()-TAIL_LENGTH);
|
||||
}
|
||||
|
||||
private static int processFileDescriptor(String fileDescriptorString) {
|
||||
int fileDescriptor = 0;
|
||||
try {
|
||||
fileDescriptor = Integer.valueOf(fileDescriptorString.substring(3, fileDescriptorString.length()-1));
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
private static String processAddressFamily(String addressFamilyString) {
|
||||
for (String addressFamily : ADDRESS_FAMILIES) {
|
||||
if (addressFamilyString.contains(addressFamily)) {
|
||||
return addressFamily;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String processSocketKind(String socketKindString) {
|
||||
for (String socketKind : SOCKET_KINDS) {
|
||||
if (socketKindString.contains(socketKind)) {
|
||||
return socketKind;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String processAddress(String addressString) {
|
||||
if (addressString.contains("''")) {
|
||||
// If it's an empty address, it contains ''
|
||||
return "";
|
||||
|
||||
} else if (addressString.contains("ip") && addressString.contains("[")) {
|
||||
String ipv6Head = "xaddr=addr(ip='[";
|
||||
// If it's an ipv6 address, since format is xaddr=addr(ip='[ipv6 address]',
|
||||
return addressString.substring(ipv6Head.length(), addressString.length()-3);
|
||||
|
||||
} else if (addressString.contains("ip")) {
|
||||
String ipv4Head = "xaddr=addr(ip='";
|
||||
// If it's an ipv4 address, since format is xaddr=addr(ip='ipv4 address',
|
||||
return addressString.substring(ipv4Head.length(), addressString.length()-2);
|
||||
|
||||
} else {
|
||||
String head = "xaddr='";
|
||||
// If it's not an empty or ip address, it is xaddr='path'
|
||||
return addressString.substring(head.length(), addressString.length()-1);
|
||||
}
|
||||
}
|
||||
|
||||
private static int processPort(String portString) {
|
||||
int port = 0;
|
||||
try {
|
||||
port = Integer.valueOf(portString.substring(5, portString.length()-2));
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
private static String processStatus(String statusString) {
|
||||
return statusString.substring(8, statusString.length()-2);
|
||||
}
|
||||
|
||||
private static int processPID(String pidString) {
|
||||
int processID = -1;
|
||||
try {
|
||||
processID = Integer.valueOf(pidString.substring(4));
|
||||
} catch (Exception e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return processID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* @author Aaron Moser
|
||||
* @date 28.12.2023
|
||||
*/
|
||||
package controller.src.DataProcessing;
|
||||
|
||||
import controller.src.DataProcessing.ConnectionsProcessing.ConnectionsProcessor;
|
||||
import queues.src.ReceivingQueue;
|
||||
|
||||
public final class DataProcessorThread extends Thread {
|
||||
private static DataProcessorThread instance = null;
|
||||
|
||||
private DataProcessorThread() {}
|
||||
|
||||
private enum DataKind {
|
||||
Connection,
|
||||
NFTablesConfiguration,
|
||||
Undefined
|
||||
}
|
||||
|
||||
private boolean dataProcessorRunning = false;
|
||||
|
||||
public static DataProcessorThread getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DataProcessorThread();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
dataProcessorRunning = true;
|
||||
while (getDataProcessorRunning()) {
|
||||
try {
|
||||
String data = ReceivingQueue.getInstance().take();
|
||||
//System.out.println("Took " + data + " from receiving queue.");
|
||||
DataKind dataKind = getKindOfData(data.substring(0, 10));
|
||||
processDependingOnDataKind(dataKind, data);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopThread() {
|
||||
this.dataProcessorRunning = false;
|
||||
}
|
||||
|
||||
public synchronized boolean getDataProcessorRunning() {
|
||||
return this.dataProcessorRunning;
|
||||
}
|
||||
|
||||
private DataKind getKindOfData(String headOfData) {
|
||||
if (headOfData.startsWith("sconn")) {
|
||||
return DataKind.Connection;
|
||||
}
|
||||
if (headOfData.startsWith("{\"nft")) {
|
||||
return DataKind.NFTablesConfiguration;
|
||||
}
|
||||
return DataKind.Undefined;
|
||||
}
|
||||
|
||||
private void processDependingOnDataKind(DataKind dataKind, String data) {
|
||||
switch (dataKind) {
|
||||
case Connection: {
|
||||
System.out.println(ConnectionsProcessor.processDataString(data));
|
||||
}break;
|
||||
case NFTablesConfiguration: {
|
||||
|
||||
}break;
|
||||
case Undefined: // intended fall through
|
||||
default: {
|
||||
System.out.println("Unknown data kind.");
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,5 @@
|
||||
package model.src;
|
||||
|
||||
public interface Model {
|
||||
public void addNetworkConnection(String networkConnection);
|
||||
|
||||
}
|
||||
|
||||
10
src/main/java/model/src/ModelConstants.java
Normal file
10
src/main/java/model/src/ModelConstants.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package model.src;
|
||||
|
||||
public class ModelConstants {
|
||||
public enum AccessModifier {
|
||||
ReadAllEntries,
|
||||
WriteEntry,
|
||||
DeleteEntry,
|
||||
DeleteAllEntries
|
||||
}
|
||||
}
|
||||
@@ -15,19 +15,15 @@ public class ModelRepresentation implements Model {
|
||||
this.connectionModel = new ConnectionModel();
|
||||
}
|
||||
|
||||
public NetworkModel getNetworkModel() {
|
||||
public synchronized NetworkModel getNetworkModel() {
|
||||
return this.networkModel;
|
||||
}
|
||||
|
||||
public NFTablesModel getNFTablesModel() {
|
||||
public synchronized NFTablesModel getNFTablesModel() {
|
||||
return this.nfTablesModel;
|
||||
}
|
||||
|
||||
public ConnectionModel getConnectionModel() {
|
||||
public synchronized ConnectionModel getConnectionModel() {
|
||||
return this.connectionModel;
|
||||
}
|
||||
|
||||
public void addNetworkConnection(String networkConnection) {
|
||||
networkModel.addNetworkConnection(networkConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,76 +4,47 @@
|
||||
*/
|
||||
package model.src;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import controller.src.DataProcessing.ConnectionsProcessing.ConnectionInformation;
|
||||
import model.src.ModelConstants.AccessModifier;
|
||||
|
||||
public class NetworkModel {
|
||||
private LinkedList<String> ipv4NetworkConnections;
|
||||
private LinkedList<String> ipv6NetworkConnections;
|
||||
|
||||
private LinkedList<String> tcpOverIPv4NetworkConnections;
|
||||
private LinkedList<String> tcpOverIPv6NetworkConnections;
|
||||
|
||||
private LinkedList<String> udpOverIPv4NetworkConnections;
|
||||
private LinkedList<String> udpOverIPv6NetworkConnections;
|
||||
|
||||
private LinkedList<String> unixNetworkConnections;
|
||||
|
||||
private Set<ConnectionInformation> connections;
|
||||
|
||||
public NetworkModel() {
|
||||
ipv4NetworkConnections = new LinkedList<String>();
|
||||
ipv6NetworkConnections = new LinkedList<String>();
|
||||
|
||||
tcpOverIPv4NetworkConnections = new LinkedList<String>();
|
||||
tcpOverIPv6NetworkConnections = new LinkedList<String>();
|
||||
|
||||
udpOverIPv6NetworkConnections = new LinkedList<String>();
|
||||
udpOverIPv6NetworkConnections = new LinkedList<String>();
|
||||
|
||||
unixNetworkConnections = new LinkedList<String>();
|
||||
connections = new HashSet<ConnectionInformation>();
|
||||
}
|
||||
|
||||
public void addNetworkConnection(String networkConnection) {
|
||||
|
||||
public synchronized Set<ConnectionInformation> getConnections() {
|
||||
return new HashSet<ConnectionInformation>(connections);
|
||||
}
|
||||
|
||||
private void addIPv4NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != ipv4NetworkConnections) {
|
||||
ipv4NetworkConnections.add(networkConnection);
|
||||
public synchronized Set<ConnectionInformation> accessConnections(AccessModifier accessModifier, ConnectionInformation connection) {
|
||||
switch (accessModifier) {
|
||||
case ReadAllEntries: {
|
||||
return new HashSet<ConnectionInformation>(connections);
|
||||
}//break;
|
||||
case WriteEntry: {
|
||||
connections.add(connection);
|
||||
return null;
|
||||
}//break;
|
||||
case DeleteEntry: {
|
||||
connections.remove(connection);
|
||||
return new HashSet<ConnectionInformation>(connections);
|
||||
}//break;
|
||||
case DeleteAllEntries: {
|
||||
connections = new HashSet<ConnectionInformation>();
|
||||
return null;
|
||||
}//break;
|
||||
default: {
|
||||
return null;
|
||||
}//break;
|
||||
}
|
||||
}
|
||||
|
||||
private void addIPv6NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != ipv6NetworkConnections) {
|
||||
ipv6NetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
public void clearConnections() {
|
||||
|
||||
private void addTCPOverIPv4NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != tcpOverIPv4NetworkConnections) {
|
||||
tcpOverIPv4NetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void addTCPOverIPv6NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != tcpOverIPv6NetworkConnections) {
|
||||
tcpOverIPv6NetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void addUDPOverIPv4NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != udpOverIPv4NetworkConnections) {
|
||||
udpOverIPv4NetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void addUDPOverIPv6NetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != udpOverIPv6NetworkConnections) {
|
||||
udpOverIPv6NetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
|
||||
private void addUnixNetworkConnection(String networkConnection) {
|
||||
if (null != networkConnection && null != unixNetworkConnections) {
|
||||
unixNetworkConnections.add(networkConnection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user