/* ** This file is part of Filius, a network construction and simulation software. ** ** Originally created at the University of Siegen, Institute "Didactics of ** Informatics and E-Learning" by a students' project group: ** members (2006-2007): ** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding, ** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer ** supervisors: ** Stefan Freischlad (maintainer until 2009), Peer Stechert ** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de> ** and Stefan Freischlad ** Filius 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 2 of the License, or ** (at your option) version 3. ** ** Filius 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 Filius. If not, see <http://www.gnu.org/licenses/>. */ package filius.rahmenprogramm.nachrichten; import java.util.Calendar; import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import java.util.Vector; import filius.Main; import filius.rahmenprogramm.I18n; import filius.software.netzzugangsschicht.EthernetFrame; import filius.software.transportschicht.TcpSegment; import filius.software.transportschicht.UdpSegment; import filius.software.vermittlungsschicht.ArpPaket; import filius.software.vermittlungsschicht.IcmpPaket; import filius.software.vermittlungsschicht.IpPaket; public class Lauscher implements I18n { public static final String ETHERNET = "", ARP = "ARP", IP = "IP", ICMP="ICMP", TCP = "TCP", UDP = "UDP"; public static final String HTTP = "HTTP", SMTP = "SMTP", POP = "POP3", DNS = "DNS", DHCP = "DHCP"; public static final String[] SPALTEN = { messages.getString("rp_lauscher_msg1"), messages.getString("rp_lauscher_msg2"), messages.getString("rp_lauscher_msg3"), messages.getString("rp_lauscher_msg4"), messages.getString("rp_lauscher_msg5"), messages.getString("rp_lauscher_msg6"), messages.getString("rp_lauscher_msg7") }; public static final String[] PROTOKOLL_SCHICHTEN = { messages.getString("rp_lauscher_msg8"), messages.getString("rp_lauscher_msg9"), messages.getString("rp_lauscher_msg10"), messages.getString("rp_lauscher_msg11") }; /** Singleton */ private static Lauscher lauscher = null; private HashMap<String, LinkedList<LauscherBeobachter>> beobachter; private HashMap<String, LinkedList<Object[]>> datenEinheiten; private Lauscher() { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", constr: Lauscher()"); beobachter = new HashMap<String, LinkedList<LauscherBeobachter>>(); reset(); } public void reset() { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", reset()"); //lauscher = null; datenEinheiten = new HashMap<String, LinkedList<Object[]>>(); this.benachrichtigeBeobachter(null); } public static Lauscher getLauscher() { if (lauscher == null) { lauscher = new Lauscher(); } return lauscher; } public void addBeobachter(String rechnerId, LauscherBeobachter beobachter) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", addBeobachter("+rechnerId+","+beobachter+")"); LinkedList<LauscherBeobachter> liste; liste = this.beobachter.get(rechnerId); if (liste == null) { liste = new LinkedList<LauscherBeobachter>(); this.beobachter.put(rechnerId, liste); } liste.add(beobachter); } private void benachrichtigeBeobachter(String rechnerId) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", benachrichtigeBeobachter("+rechnerId+")"); LinkedList<LauscherBeobachter> liste; Collection<LinkedList<LauscherBeobachter>> collection; ListIterator<LauscherBeobachter> it; Iterator<LinkedList<LauscherBeobachter>> valueIt; if (rechnerId == null) { collection = this.beobachter.values(); liste = new LinkedList<LauscherBeobachter>(); valueIt = collection.iterator(); while (valueIt.hasNext()) { liste.addAll((LinkedList<LauscherBeobachter>)valueIt.next()); } } else { liste = this.beobachter.get(rechnerId); } // Main.debug.println("\tbenachrichtigeBeobachter for "+rechnerId+" gave list "+(liste==null ? "<null>" : liste.toString())); if (liste != null) { it = liste.listIterator(); while (it.hasNext()) { ((LauscherBeobachter) it.next()).update(); } } } /** * Hinzufuegen von einem EthernetFrame zu den Daten * * @param interfaceId * Uebergeben wird der String des NetzwerkInterface nach Aufruf * von toString() * @param frame */ public void addDatenEinheit(String interfaceId, EthernetFrame frame) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", addDatenEinheit("+interfaceId+","+frame+")"); LinkedList<Object[]> liste; Object[] frameMitZeitstempel; //Main.debug.println("Lauscher: neuer Frame von " + interfaceId // + " hinzugefuegt"); frameMitZeitstempel = new Object[2]; frameMitZeitstempel[0] = new Long(System.currentTimeMillis()); frameMitZeitstempel[1] = frame; liste = (LinkedList<Object[]>) datenEinheiten.get(interfaceId); if (liste == null) { liste = new LinkedList<Object[]>(); liste.add(frameMitZeitstempel); } else { liste.addLast(frameMitZeitstempel); } datenEinheiten.put(interfaceId, liste); benachrichtigeBeobachter(interfaceId); } public Object[][] getDaten(String interfaceId) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", getDaten("+interfaceId+")"); Vector<Object[]> vector; Object[][] daten; vector = datenVorbereiten(interfaceId); if (vector == null) { daten = new Object[0][SPALTEN.length]; return daten; } else { daten = new Object[vector.size()][SPALTEN.length]; for (int i = 0; i < vector.size(); i++) { daten[i] = (Object[]) vector.elementAt(i); } return daten; } } public void print(String interfaceId) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", print("+interfaceId+")"); Object[][] daten; daten = getDaten(interfaceId); for (int i = 0; i < daten.length; i++) { for (int j = 0; j < daten[i].length; j++) { Main.debug.print("\t" + daten[i][j]); } Main.debug.println(); } } private Vector<Object[]> datenVorbereiten(String interfaceId) { Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+", datenVorbereiten("+interfaceId+")"); Vector<Object[]> daten; LinkedList<Object[]> liste; Object[] frameMitZeitstempel, neuerEintrag; ListIterator<Object[]> it; Calendar zeit; EthernetFrame frame; IpPaket ipPaket; IcmpPaket icmpPaket; ArpPaket arpPaket; TcpSegment tcpSeg = null; UdpSegment udpSeg = null; String timestampStr = ""; liste = datenEinheiten.get(interfaceId); if (liste == null) { return null; } else { daten = new Vector<Object[]>(); it = liste.listIterator(); for (int i = 1; it.hasNext(); i++) { frameMitZeitstempel = (Object[]) it.next(); neuerEintrag = new Object[SPALTEN.length]; neuerEintrag[0] = "" + i; zeit = new GregorianCalendar(); zeit.setTimeInMillis(((Long) frameMitZeitstempel[0]) .longValue()); timestampStr = (zeit.get(Calendar.HOUR_OF_DAY)<10 ? "0"+zeit.get(Calendar.HOUR_OF_DAY) : zeit.get(Calendar.HOUR_OF_DAY)) + ":" + (zeit.get(Calendar.MINUTE)<10 ? "0"+zeit.get(Calendar.MINUTE) : zeit.get(Calendar.MINUTE)) + ":" + (zeit.get(Calendar.SECOND)<10 ? "0"+zeit.get(Calendar.SECOND) : zeit.get(Calendar.SECOND)) + "." + (zeit.get(Calendar.MILLISECOND)<10 ? "00"+zeit.get(Calendar.MILLISECOND) : (zeit.get(Calendar.MILLISECOND)<100 ? "0"+zeit.get(Calendar.MILLISECOND) : zeit.get(Calendar.MILLISECOND))); neuerEintrag[1] = timestampStr; frame = (EthernetFrame) frameMitZeitstempel[1]; neuerEintrag[2] = frame.getQuellMacAdresse(); neuerEintrag[3] = frame.getZielMacAdresse(); neuerEintrag[4] = ETHERNET; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[0]; neuerEintrag[6] = frame.getTyp(); daten.addElement(neuerEintrag); neuerEintrag = new Object[SPALTEN.length]; neuerEintrag[0] = "" + i; neuerEintrag[1] = timestampStr; if (frame.getTyp().equals(EthernetFrame.IP) && !frame.isICMP()) { ipPaket = (IpPaket) frame.getDaten(); neuerEintrag[2] = ipPaket.getSender(); neuerEintrag[3] = ipPaket.getEmpfaenger(); neuerEintrag[4] = IP; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[1]; neuerEintrag[6] = messages.getString("rp_lauscher_msg12") + ipPaket.getProtocol() + ", TTL: " + ipPaket.getTtl(); daten.addElement(neuerEintrag); neuerEintrag = new Object[SPALTEN.length]; neuerEintrag[0] = "" + i; neuerEintrag[1] = timestampStr; if (ipPaket.getProtocol() == IpPaket.TCP) { tcpSeg = (TcpSegment) ipPaket.getSegment(); neuerEintrag[2] = tcpSeg.getQuellPort(); neuerEintrag[3] = tcpSeg.getZielPort(); neuerEintrag[4] = TCP; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[2]; if (tcpSeg.isAck() && !tcpSeg.isSyn() && !tcpSeg.isFin()) { neuerEintrag[6] = "ACK: " + tcpSeg.getAckNummer(); } else { if (tcpSeg.isSyn()) { neuerEintrag[6] = "SYN"; } else if (tcpSeg.isFin()) { neuerEintrag[6] = "FIN"; } if (tcpSeg.isAck()) { neuerEintrag[6] = neuerEintrag[6] + ", ACK:" + tcpSeg.getAckNummer(); } // Sequenznummer nur, wenn SYN-Segment // oder Nutzdaten-Segment if (tcpSeg.isSyn() || (!tcpSeg.isAck() && !tcpSeg.isFin())) { neuerEintrag[6] = ((neuerEintrag[6] == null) ? "" : neuerEintrag[6]) + (tcpSeg.isSyn() ? ", " : "") + "SEQ: " + tcpSeg.getSeqNummer(); } } } else if (ipPaket.getProtocol() == IpPaket.UDP) { udpSeg = (UdpSegment) ipPaket.getSegment(); neuerEintrag[2] = udpSeg.getQuellPort(); neuerEintrag[3] = udpSeg.getZielPort(); neuerEintrag[4] = UDP; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[2]; neuerEintrag[6] = ""; } else { Main.debug.println("ERROR ("+this.hashCode()+"): Protokoll der Transportschicht (" + ipPaket.getProtocol() + ") nicht bekannt."); } daten.addElement(neuerEintrag); neuerEintrag = new Object[SPALTEN.length]; neuerEintrag[0] = "" + i; neuerEintrag[1] = timestampStr; neuerEintrag[2] = ""; neuerEintrag[3] = ""; neuerEintrag[4] = ""; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[3]; if (ipPaket.getProtocol() == IpPaket.TCP) { neuerEintrag[6] = tcpSeg.getDaten(); if(neuerEintrag[6] != null) neuerEintrag[6] = ((String) neuerEintrag[6]).replace('\n', ' '); } else if (ipPaket.getProtocol() == IpPaket.UDP) { neuerEintrag[6] = udpSeg.getDaten(); if(neuerEintrag[6] != null) neuerEintrag[6] = ((String) neuerEintrag[6]).replace('\n', ' '); } if (neuerEintrag[6] != null && !((String) neuerEintrag[6]).trim().equals("")) daten.addElement(neuerEintrag); } else if (frame.getTyp().equals(EthernetFrame.ARP)) { arpPaket = (ArpPaket) frame.getDaten(); neuerEintrag[2] = arpPaket.getQuellIp(); neuerEintrag[3] = arpPaket.getZielIp(); neuerEintrag[4] = ARP; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[1]; if (arpPaket.getZielMacAdresse() .equalsIgnoreCase("ff:ff:ff:ff:ff:ff")) { neuerEintrag[6] = messages.getString("rp_lauscher_msg13") + " " + arpPaket.getZielIp() + ", "; } else { neuerEintrag[6] = ""; } neuerEintrag[6] = neuerEintrag[6] + arpPaket.getQuellIp() + ": " + arpPaket.getQuellMacAdresse(); daten.addElement(neuerEintrag); } else if (frame.getTyp().equals(EthernetFrame.IP) && frame.isICMP()) { icmpPaket = (IcmpPaket) frame.getDaten(); neuerEintrag[2] = icmpPaket.getQuellIp(); neuerEintrag[3] = icmpPaket.getZielIp(); neuerEintrag[4] = ICMP; neuerEintrag[5] = PROTOKOLL_SCHICHTEN[1]; switch (icmpPaket.getIcmpType()) { case 0: neuerEintrag[6] = "ICMP Echo Reply (pong)"; break; case 3: switch (icmpPaket.getIcmpCode()) { case 0: neuerEintrag[6] = "ICMP Network Unreachable"; break; case 1: neuerEintrag[6] = "ICMP Host Unreachable"; break; default: neuerEintrag[6] = "ICMP Destination Unreachable (code " + icmpPaket.getIcmpCode() + ")"; break; } break; case 8: neuerEintrag[6] = "ICMP Echo Request (ping)"; break; case 11: neuerEintrag[6] = "ICMP Time Exeeded (poof)"; break; default: neuerEintrag[6] = "ICMP unknown: " + icmpPaket.getIcmpType() + " / " + icmpPaket.getIcmpCode(); break; } daten.addElement(neuerEintrag); } } } return daten; } }