From 8a5efa76009d49c126ebc1284555626e5a7052be Mon Sep 17 00:00:00 2001 From: mart Date: Mon, 9 Nov 2015 19:24:58 +0100 Subject: [PATCH] added stuff from ramon --- a2/code/client/main.py | 38 ++++++++ a2/code/client/sender.py | 150 +++++++++++++++++++++++++++++ a2/code/client/sn.txt | 1 + a2/code/server/DefaultHandler.java | 35 +++++++ a2/code/server/EchoHandler.java | 46 +++++++++ a2/code/server/Main.java | 40 ++++++++ a2/code/server/Makefile | 7 ++ a2/code/server/NetHelper.java | 94 ++++++++++++++++++ a2/code/server/TCPServer.java | 67 +++++++++++++ 9 files changed, 478 insertions(+) create mode 100644 a2/code/client/main.py create mode 100644 a2/code/client/sender.py create mode 100644 a2/code/client/sn.txt create mode 100644 a2/code/server/DefaultHandler.java create mode 100644 a2/code/server/EchoHandler.java create mode 100644 a2/code/server/Main.java create mode 100644 a2/code/server/Makefile create mode 100644 a2/code/server/NetHelper.java create mode 100644 a2/code/server/TCPServer.java diff --git a/a2/code/client/main.py b/a2/code/client/main.py new file mode 100644 index 0000000..6d109db --- /dev/null +++ b/a2/code/client/main.py @@ -0,0 +1,38 @@ +from sender import Sender +import sys + +# before running this program, be sure to run the TCPServer +# also make sure to run the below command to prevent the OS from canceling our connection +# sudo iptables -A OUTPUT -p tcp --tcp-flags PSH PSH -j ACCEPT +# sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP + +# for running tests, you may need to store information on the received sequence number for the server +# you can do that by defining new fields within the sender class/global variables to store such info + +# for non local communication, you can comment the raw sockets setting in sender.py (line 132) + +# run using sudo (!!!) from a command line terminal +# and don't mind/ignore eclipse's red markings. + +if __name__ == "__main__": + serverPort = 10000 + if len(sys.argv) > 1: + serverPort = int(sys.argv[1]) + sender = Sender(serverIP="127.0.0.1", networkInterface="lo", isLocal=True, serverPort=serverPort, waitTime=1, isVerbose=1) + # isLocal is True if the interface is a local one + response = sender.sendInput("S", 100, 100) + + # triggers the response SA _ 101 if the server is listening on the specified port + # if the server isn't listening, there are no responses + print sender.lastAckReceived + print sender.isTimeout + + # an example for the echo handling server + if sender.isTimeout == False: # in case something was received + sender.sendInput("A", 101, sender.lastSeqReceived + 1) # connection is established + sender.sendInput("A", 101, sender.lastSeqReceived + 1, data = "C") # send some data + sender.sendInput("A", 102, sender.lastSeqReceived + 1, data = "C") # send some data + sender.sendInput("FA", 103, sender.lastSeqReceived + 1) # close connection (the echo also closes) + sender.sendInput("RP", 104, 0) # reset connection + + sender.sendReset() # switch sender port diff --git a/a2/code/client/sender.py b/a2/code/client/sender.py new file mode 100644 index 0000000..e1091a3 --- /dev/null +++ b/a2/code/client/sender.py @@ -0,0 +1,150 @@ +from scapy.all import * + +verbose = 1 + +def vb_print(msg): + global verbose + if verbose == 1: + print msg + +# the sender sends packets with configurable parameters to a server and retrieves responses +class Sender: + # information on the SUT + def __init__(self, serverIP, serverPort=8000, + networkInterface="lo", isLocal=True, senderPortMinimum=20000, + senderPortMaximum=40000, portNumberFile="sn.txt", + isVerbose=0, waitTime=1): + + + # file where the last sender port used is stored + self.portNumberFile = portNumberFile; + + # when choosing a fresh port, a new port is chosen + # within boundaries defined by the parameters below + self.senderPortMinimum = senderPortMinimum + self.senderPortMaximum = senderPortMaximum + + # data on sender and server needed to send packets + self.serverIP = serverIP + self.serverPort = serverPort + self.networkInterface = networkInterface + self.senderPort = self.getNextPort() + self.isLocal = isLocal + + # time to wait for a response from the server before concluding a timeout + self.waitTime = waitTime + + # verbose or not + self.isVerbose = isVerbose + + # variables added so you can easily test the last system response + self.lastSeqReceived = None + self.lastAckReceived = None + self.isTimeout = None + self.lastFlagsReceived = None + self.lastDataReceived = None + + + # chooses a new port to send packets from + def refreshNetworkPort(self): + vb_print("previous local port: " + str(self.senderPort)) + self.senderPort = self.getNextPort() + vb_print("next local port: " + str(self.senderPort) + "\n") + return self.senderPort + + # gets a new port number, an increment of the old within the specified limits. Uses a file. + def getNextPort(self): + f = open(self.portNumberFile, "a+") + f.seek(0) + line = f.readline() + if line == '' or int(line) < self.senderPortMinimum: + networkPort = self.senderPortMinimum + else: + networkPort = (int(line) + 1) % self.senderPortMaximum + f.closed + f = open(self.portNumberFile, "w") + f.write(str(networkPort)) + f.closed + return networkPort + + # send a packet onto the network with the given parameters, and return the response packet + # in case of a timeout, returns None, otherwise, returns the tuple (flags, seqNo, ackNo) + def sendPacket(self, flagsSet, seqNr, ackNr, data = None): + packet = self.createPacket(flagsSet, seqNr, ackNr, data) + # consider adding the parameter: iface="ethx" if you don't receive a response. Also consider increasing the wait time + scapyResponse = sr1(packet, timeout=self.waitTime, verbose=self.isVerbose) + if scapyResponse is not None: + scapyResponse.show() + # ^^ in case you want to show the packet content + # here is what you store from every packet response + if Raw not in scapyResponse: + response = (self.intToFlags(scapyResponse[TCP].flags), scapyResponse[TCP].seq, scapyResponse[TCP].ack, None) + else: + response = (self.intToFlags(scapyResponse[TCP].flags), scapyResponse[TCP].seq, scapyResponse[TCP].ack, scapyResponse[Raw].load) + else: + response = "Timeout" + return response + + # function that creates packet from data strings/integers + # data is used for attaching data to the packet + def createPacket(self, tcpFlagsSet, seqNr, ackNr, data=None): + vb_print("" + tcpFlagsSet + " " + str(seqNr) + " " + str(ackNr)) + pIP = IP(dst=self.serverIP, flags="DF") + pTCP = TCP(sport=self.senderPort, + dport=self.serverPort, + seq=seqNr, + ack=ackNr, + flags=tcpFlagsSet) + if data is None: + p = pIP / pTCP + else: + p = pIP / pTCP / Raw(load=data) + return p + + # check whether there is a 1 at the given bit-position of the integer + def checkForFlag(self, x, flagPosition): + if x & 2 ** flagPosition == 0: + return False + else: + return True + + # the flags-parameter of a network packets is returned as an int, this function converts + # it to a string (such as "FA" if the Fin-flag and Ack-flag have been set) + def intToFlags(self, x): + result = "" + if self.checkForFlag(x, 0): + result = result + "F" + if self.checkForFlag(x, 1): + result = result + "S" + if self.checkForFlag(x, 2): + result = result + "R" + if self.checkForFlag(x, 3): + result = result + "P" + if self.checkForFlag(x, 4): + result = result + "A" + return result + + # sends input over the network to the server + def sendInput(self, input1, seqNr, ackNr, data = None): + conf.sniff_promisc = False + conf.iface = self.networkInterface + if self.isLocal == True: + conf.L3socket = L3RawSocket # if the connection is local/localhost, use l3 raw sockets + vb_print("sending: "+ str((input1, seqNr, ackNr, data))) + response = self.sendPacket(input1, seqNr, ackNr, data) + + # updating sender state variables + if response != "Timeout": + (self.lastFlagsReceived, self.lastSeqReceived, self.lastAckReceived, self.lastDataReceived) = response + self.isTimeout = False + else: + self.isTimeout = True + + # printing response + vb_print("received: "+ str(response)) + return response + + # resets the connection by changing the port number. On some OSes (Win 8) upon hitting a certain number of + # connections opened on a port, packets are sent to close down connections. + def sendReset(self): + self.refreshNetworkPort() diff --git a/a2/code/client/sn.txt b/a2/code/client/sn.txt new file mode 100644 index 0000000..05f3e49 --- /dev/null +++ b/a2/code/client/sn.txt @@ -0,0 +1 @@ +20233 \ No newline at end of file diff --git a/a2/code/server/DefaultHandler.java b/a2/code/server/DefaultHandler.java new file mode 100644 index 0000000..c90ff57 --- /dev/null +++ b/a2/code/server/DefaultHandler.java @@ -0,0 +1,35 @@ +import java.net.Socket; +import java.net.SocketException; + +/** + * Default connection handler. Very basic, does not read or send anything. + */ +public class DefaultHandler implements Runnable { + private Socket socket; + + public DefaultHandler(Socket socket) { + this.socket = socket; + try { + socket.setTcpNoDelay(false); + } catch (SocketException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + new Thread(this).start(); + } + + public void run() { + { + // here you can customize operations you want to test though it's not necessary + System.out.println("new socket opening on " + socket.getLocalPort()); + while (!socket.isOutputShutdown()) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } +} \ No newline at end of file diff --git a/a2/code/server/EchoHandler.java b/a2/code/server/EchoHandler.java new file mode 100644 index 0000000..e8e95c7 --- /dev/null +++ b/a2/code/server/EchoHandler.java @@ -0,0 +1,46 @@ +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.Socket; +import java.net.SocketException; + +/** + * Connection echo handler. Everything it receives is sent back. + */ +public class EchoHandler implements Runnable { + private Socket socket; + + public EchoHandler(Socket socket) { + this.socket = socket; + try { + socket.setTcpNoDelay(false); + } catch (SocketException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + new Thread(this).start(); + } + + public void run() { + { + try { + System.out.println("new socket opening on " + + socket.getLocalPort()); + InputStreamReader in = new InputStreamReader( + socket.getInputStream()); + OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream()); + int s; + while(((s=in.read()) != -1)) { + out.append((char)s); + out.flush(); + System.out.print((char)s); + } + System.out.println(); + System.out.println("Closing handler"); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + } +} \ No newline at end of file diff --git a/a2/code/server/Main.java b/a2/code/server/Main.java new file mode 100644 index 0000000..ee9bc59 --- /dev/null +++ b/a2/code/server/Main.java @@ -0,0 +1,40 @@ +import java.net.InetAddress; + +// Run the TCPServer on the the port testPort +public class Main { + private static final int DEFAULT_PORT = 10000; + private static final String DEFAULT_ADDRESS = "127.0.0.1"; + + /** + * Run the program with arguments to set a custom port and address, see the comments in the code + * @param args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + System.setProperty("java.net.preferIPv4Stack", "true"); // force ipv4 + int port; + String address; + if (args.length == 0) { + // no arguments: default port and address + port = DEFAULT_PORT; + address = DEFAULT_ADDRESS; + } else if (args.length == 1) { + // one argument for port, default address + port = Integer.valueOf(args[0]); + address = DEFAULT_ADDRESS; + } else if (args.length == 2) { + // two arguments for port and address + // for example, call it like 'java Main 10000 127.0.0.1' + port = Integer.valueOf(args[0]); + address = args[1]; + } else { + return; + } + TCPServer server = new TCPServer(port, InetAddress.getByName(address)); + + // comment this for the default handler, otherwise the echo server is used + server.setHandlerType("echo"); + + server.handleConnections(); + } +} diff --git a/a2/code/server/Makefile b/a2/code/server/Makefile new file mode 100644 index 0000000..379202a --- /dev/null +++ b/a2/code/server/Makefile @@ -0,0 +1,7 @@ +all: Main.class + +%.class: %.java + javac $< + +clean: + $(RM) *.class diff --git a/a2/code/server/NetHelper.java b/a2/code/server/NetHelper.java new file mode 100644 index 0000000..abbca1b --- /dev/null +++ b/a2/code/server/NetHelper.java @@ -0,0 +1,94 @@ +import static java.lang.System.out; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Collections; +import java.util.Enumeration; + +// this utility displays information on addresses and ports, you don't need to use it +public class NetHelper +{ + public static void main(String args[]) throws SocketException { + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + + for (NetworkInterface netIf : Collections.list(nets)) { + out.printf("Display name: %s\n", netIf.getDisplayName()); + out.printf("Name: %s\n", netIf.getName()); + displayInterfaceInformation(netIf); + displaySubInterfaces(netIf); + out.printf("\n"); + } + } + + public static NetworkInterface getNetworkInterface(String netName) { + NetworkInterface netIntf = null; + try { + for (Enumeration en = NetworkInterface + .getNetworkInterfaces(); en.hasMoreElements();) { + NetworkInterface intf = en.nextElement(); + if (intf.getName().compareToIgnoreCase(netName) == 0) { + netIntf = intf; + break; + } + } + } catch (SocketException e) { + System.out + .println("Socket Exception failed to find internet addresses!"); + e.printStackTrace(); + System.exit(0); + } + return netIntf; + } + + public static InetAddress getFirstNonLocalHost(NetworkInterface netIntf) { + Enumeration hosts = netIntf.getInetAddresses(); + InetAddress address = null; + while (hosts.hasMoreElements()) { + InetAddress host = hosts.nextElement(); + if (!host.isLinkLocalAddress() && !host.isLoopbackAddress()) { + address = host; + break; + } + } + return address; + } + + + + static String getMac(NetworkInterface netint) throws SocketException { + byte[] mac = netint.getHardwareAddress(); + String rez = "null"; + if(mac != null) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); + } + rez = sb.toString(); + } + return rez; + //System.out.println(sb.toString()); + } + + static void displayInterfaceInformation(NetworkInterface netint) throws SocketException { + out.printf("Display name: %s\n", netint.getDisplayName()); + out.printf("Name: %s\n", netint.getName()); + out.printf("MAC: %s\n", getMac(netint)); + Enumeration inetAddresses = netint.getInetAddresses(); + for (InetAddress inetAddress : Collections.list(inetAddresses)) { + out.printf("InetAddress: %s\n", inetAddress); + out.println("LOCAL:" + Boolean.toString(inetAddress.isLoopbackAddress() || inetAddress.isLinkLocalAddress())); + } + out.printf("\n"); + } + + static void displaySubInterfaces(NetworkInterface netIf) throws SocketException { + Enumeration subIfs = netIf.getSubInterfaces(); + + for (NetworkInterface subIf : Collections.list(subIfs)) { + out.printf("\tSub Interface Display name: %s\n", subIf.getDisplayName()); + out.printf("\tSub Interface Name: %s\n", subIf.getName()); + displayInterfaceInformation(subIf); + } + } +} \ No newline at end of file diff --git a/a2/code/server/TCPServer.java b/a2/code/server/TCPServer.java new file mode 100644 index 0000000..7ecd7f7 --- /dev/null +++ b/a2/code/server/TCPServer.java @@ -0,0 +1,67 @@ +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * A simple TCP server. Listens for connections, and for each incoming connection, + * it creates a 'handler' (either echo handler or default handler) which controls + * that connection + */ +public class TCPServer implements Runnable { + public ServerSocket server; + public Socket socket; + private String handler; + + public TCPServer(int port, InetAddress address) { + try { + server = new ServerSocket(port, 0, address); + server.setReuseAddress(true); + System.out.println("Listening on:\n" + + server.getInetAddress().toString() + "\nport: " + + server.getLocalPort()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public TCPServer(int port) throws UnknownHostException { + this(port,InetAddress.getLocalHost()); + } + + public void setHandlerType(String handlerClass) { + this.handler = handlerClass; + } + + private void startHandler(Socket socket) { + System.out.println("Starting handler '"+ ((handler!=null) ? handler : "default") + "'"); + if("echo".equalsIgnoreCase(handler)) { + new EchoHandler(socket); + } else { + new DefaultHandler(socket); + } + } + + public void handleConnections() { + Thread thread = new Thread(this); + thread.start(); + } + + @Override + public void run() { + System.out.println("Waiting for client messages..."); + + // accept all requests for connections + while (true) { + try { + socket = server.accept(); + startHandler(socket); + } catch (IOException e) { + //e.printStackTrace(); + System.err.println("Closed socket"); + break; + } + } + } +} -- 2.20.1