Encapsulates ICMP interface that can be used to ping or trace route remote hosts. More...
Classes | |
interface | Context |
Provides message presentation context to instance of Traceroute . More... | |
Public Member Functions | |
Traceroute (Context context) | |
Creates new instance of Traceroute | |
void | startPinging (int deviceNo, String hostName, int initialTTL) |
Starts thread that will trace route to given host. | |
void | stopTrace () |
Stops on-going trace route or ping. | |
boolean | isIdle () |
Returns if IDLE, i.e. | |
void | dumpInterfaceInfo (String title, NetworkInterface ni) |
Dumps details about particular Jpcap network interface into log area. | |
String[] | getInterfaceList () |
Gets array of interface descriptions (suitable for the JComboBox) | |
boolean | tcpPortScan (int localPort, String remoteHost, int rp1, int rp2) throws UnknownHostException, IOException |
Scan TCP ports. | |
void | run () |
Traces route to given host. | |
Private Member Functions | |
void | println (String str) |
Prints line to log area prefixed with timestamp. | |
void | println () |
Advances to new line in log area. | |
void | print (String str, boolean timestamp) |
Prints characters to log area optionally prefixed with timestamp. | |
void | openDeviceOnInterface (int deviceNo) |
void | interruptibleSleep (int millis) |
Interruptible sleep (replacement for Thread.sleep ). | |
byte[] | obtainDefaultGatewayMac (String httpHostToCheck) |
Obtains MAC address of the default gateway for captor interface. | |
Private Attributes | |
Thread | tracingThread |
Instance of the thread that sends ICMP packets. | |
volatile boolean | running = false |
Indicates if thread is (or should be) running. | |
volatile boolean | completed |
Indicates that thread has been completed. | |
int | deviceCount = 0 |
Jpcap NetworkInterface device count. | |
JpcapCaptor | captor = null |
Instance of the Jpcap capturing class. | |
NetworkInterface | device = null |
Instance of the Jpcap network interface used for sending and receiving ICMP packets. | |
InetAddress | localIP = null |
Local IP address. | |
boolean | resolveNames = false |
Indicates whether to resolve addresses to names or not. | |
String | hostName |
Host name or IP address to ping. | |
int | initialTTL |
Initial TTL (time to live or hop count). | |
Context | context |
Presentation context for messages. |
Encapsulates ICMP interface that can be used to ping or trace route remote hosts.
Definition at line 27 of file Traceroute.java.
Traceroute.Traceroute | ( | Context | context ) |
Creates new instance of Traceroute
context | where to log messages |
Definition at line 120 of file Traceroute.java.
References completed, context, deviceCount, running, and tracingThread.
{ this.context = context; this.running = false; this.completed = true; this.tracingThread = null; deviceCount = JpcapCaptor.getDeviceList ().length; }
void Traceroute.dumpInterfaceInfo | ( | String | title, |
NetworkInterface | ni | ||
) |
Dumps details about particular Jpcap network interface into log area.
title | title line |
ni | network interface to show |
Definition at line 223 of file Traceroute.java.
References println().
Referenced by getInterfaceList().
String [] Traceroute.getInterfaceList | ( | ) |
Gets array of interface descriptions (suitable for the JComboBox)
Definition at line 239 of file Traceroute.java.
References deviceCount, and dumpInterfaceInfo().
Referenced by TraceroutePane.TraceroutePane().
{ this.deviceCount = JpcapCaptor.getDeviceList ().length; String[] devList = new String[ this.deviceCount ]; int ni_index = 0; for( NetworkInterface ni : JpcapCaptor.getDeviceList () ) { String ourDescription = ni.description; for( NetworkInterfaceAddress addr : ni.addresses ) { if( addr.address instanceof Inet4Address ) { ourDescription = addr.address.toString () + " -- " + ni.description; break; } } devList[ ni_index ] = " iface" + ni_index + " -- " + ourDescription; dumpInterfaceInfo( "Interface " + (ni_index++), ni ); } return devList; }
void Traceroute.interruptibleSleep | ( | int | millis ) | [private] |
Interruptible sleep (replacement for Thread.sleep
).
millis | - the length of time to sleep in milliseconds. |
Definition at line 306 of file Traceroute.java.
References running.
Referenced by obtainDefaultGatewayMac(), run(), and tcpPortScan().
{ synchronized( this ) { try { this.wait( millis ); } catch( InterruptedException ie ) { running = false; // kills the thread } } }
boolean Traceroute.isIdle | ( | ) |
Returns if IDLE, i.e.
if tracing thread does not exist or previous thread has been completed.
Definition at line 212 of file Traceroute.java.
References completed.
Referenced by TraceroutePane.parseCommand().
{ return completed; }
byte [] Traceroute.obtainDefaultGatewayMac | ( | String | httpHostToCheck ) | [private] |
Obtains MAC address of the default gateway for captor interface.
Definition at line 324 of file Traceroute.java.
References captor, device, interruptibleSleep(), print(), println(), and running.
Referenced by run(), and tcpPortScan().
{ print( "Obtaining default gateway MAC address... ", true ); byte[] gatewayMAC = null; if ( captor != null ) try { InetAddress hostAddr = InetAddress.getByName( httpHostToCheck ); captor.setFilter( "tcp and dst host " + hostAddr.getHostAddress(), true ); int timeoutTimer = 0; new URL("http://" + httpHostToCheck ).openStream().close(); while( running ) { Packet ping = captor.getPacket (); if( ping == null ) { if ( timeoutTimer < 20 ) { // max 2 sec interruptibleSleep( 100 /*millis*/ ); ++timeoutTimer; continue; } /* else: Timeout exceeded */ print( "<timeout>", /*timestamp*/ false ); println( "ERROR: Cannot obtain MAC address for default gateway." ); println( "Maybe there is no default gateway on selected interface?" ); return gatewayMAC; } byte[] destinationMAC = ((EthernetPacket)ping.datalink).dst_mac; if( ! Arrays.equals( destinationMAC, device.mac_address ) ) { gatewayMAC = destinationMAC; break; } timeoutTimer = 0; // restart timer new URL("http://" + httpHostToCheck ).openStream().close(); } } catch( MalformedURLException e ) { println( "Invalid URL: " + e.toString () ); } catch( UnknownHostException e ) { println( "Unknown host: " + httpHostToCheck ); } catch( IOException e ) { println( "ERROR: " + e.toString () ); } print( " OK.", /*timestamp*/ false ); println (); return gatewayMAC; }
void Traceroute.openDeviceOnInterface | ( | int | deviceNo ) | [private] |
Definition at line 269 of file Traceroute.java.
References captor, device, and localIP.
Referenced by startPinging().
{ // Open specified device from the list // device = JpcapCaptor.getDeviceList()[ deviceNo ]; localIP = null; captor = null; try { captor = JpcapCaptor.openDevice( device, /*MTU*/ 2000, /*promiscuous*/ false, /*timeout*/ 1 ); // captor.setNonBlockingMode( true ); // captor.setPacketReadTimeout( 1000 ); for( NetworkInterfaceAddress addr : device.addresses ) { if( addr.address instanceof Inet4Address ) { localIP = addr.address; break; } } } catch ( IOException e ) { device = null; localIP = null; captor = null; } }
void Traceroute.print | ( | String | str, |
boolean | timestamp | ||
) | [private] |
Prints characters to log area optionally prefixed with timestamp.
str | message to log |
timestamp | whether to prefix message with timestamp or not |
Definition at line 153 of file Traceroute.java.
References context, and Traceroute.Context.logMessage().
Referenced by obtainDefaultGatewayMac(), run(), stopTrace(), and tcpPortScan().
{ context.logMessage( str,timestamp ); }
void Traceroute.println | ( | ) | [private] |
Advances to new line in log area.
Definition at line 142 of file Traceroute.java.
References context, and Traceroute.Context.logNewLine().
Referenced by dumpInterfaceInfo(), obtainDefaultGatewayMac(), run(), and tcpPortScan().
{ context.logNewLine (); }
void Traceroute.println | ( | String | str ) | [private] |
Prints line to log area prefixed with timestamp.
Definition at line 133 of file Traceroute.java.
References context, Traceroute.Context.logMessage(), and Traceroute.Context.logNewLine().
{ context.logMessage( str, /*timestamp*/ true ); context.logNewLine (); }
void Traceroute.run | ( | ) |
Traces route to given host.
The instance is locked during in the mean time so other trace routes could not start (completed == false suppresses other threads).
Definition at line 514 of file Traceroute.java.
References captor, completed, context, device, hostName, initialTTL, interruptibleSleep(), localIP, obtainDefaultGatewayMac(), Traceroute.Context.onTracerouteCompleted(), print(), println(), resolveNames, and running.
{ /* Release instance to other threads */ if ( ! running ) { completed = true; context.onTracerouteCompleted (); return; } /* Make sure that capturing device is configured */ if ( captor == null ) { println( "Capturing device is not configured..." ); running = false; completed = true; context.onTracerouteCompleted (); return; } /* Starts sending ICMP packets and tracing route... */ try { /* if ( ! tcpPortScan( 15000, hostName, 1, 1000 ) ) { completed = true; context.onTracerouteCompleted (); return; } */ println( "-------------------------------------------------" ); print( "Looking up " + hostName + "...", /*timestamp*/ true ); InetAddress remoteIP = InetAddress.getByName( hostName ); print( " " + remoteIP.getHostAddress (), /*timestamp*/ false ); println (); byte[] defaultGatewayMAC = obtainDefaultGatewayMac( "dsv.su.se" ); if ( defaultGatewayMAC == null ) { running = false; completed = true; context.onTracerouteCompleted (); return; } if ( initialTTL == 0 ) { println( "Tracing route to " + remoteIP + "..." ); } else { println( "Pinging host " + remoteIP + "..." ); } /* Create ICMP packet */ ICMPPacket icmp = new ICMPPacket (); icmp.type = ICMPPacket.ICMP_ECHO; icmp.seq = 100; icmp.id = 0; icmp.data = "data".getBytes (); icmp.setIPv4Parameter( 0, // int priority - Priority false, // boolean: IP flag bit: Delay false, // boolean: IP flag bit: Through false, // boolean: IP flag bit: Reliability 0, // int: Type of Service (TOS) false, // boolean: Fragmentation Reservation flag false, // boolean: Don't fragment flag false, // boolean: More fragment flag 0, // int: Offset 0, // int: Identifier 0, // int: Time To Live IPPacket.IPPROTO_ICMP, // Protocol localIP, // Source IP address remoteIP // Destination IP address ); EthernetPacket ether = new EthernetPacket (); ether.frametype = EthernetPacket.ETHERTYPE_IP; ether.src_mac = device.mac_address; ether.dst_mac = defaultGatewayMAC; icmp.datalink = ether; /* Send ICMP packets... */ JpcapSender sender = captor.getJpcapSenderInstance (); captor.setFilter( "icmp and dst host " + localIP.getHostAddress(), true ); icmp.hop_limit = (short)initialTTL; print( icmp.hop_limit + ": ", /*timestamp*/ true ); int timeoutTimer = 0; int timeoutCounter = 0; long tStart = System.nanoTime (); sender.sendPacket( icmp ); while( running ) { ICMPPacket p = (ICMPPacket)captor.getPacket (); int tDelay = (int)( ( System.nanoTime () - tStart ) / 1000000l ); if( p == null ) // TIMEOUT { /* Continue waiting until ~2 sec elapses */ if ( timeoutTimer < 30 ) { interruptibleSleep( timeoutTimer < 10 ? 1 : 100 ); ++timeoutTimer; if ( timeoutTimer >= 10 ) { print( ".", /*timestamp*/ false ); } continue; } /* Increase timeout counter and either retry or advance Hop limit */ ++timeoutCounter; print( " Timeout #" + timeoutCounter, /*timestamp*/ false ); if ( timeoutCounter < 3 ) // Retry send to the same Hop { print( icmp.hop_limit + ": ", /*timestamp*/ true ); tStart = System.nanoTime (); timeoutTimer = 0; sender.sendPacket( icmp ); } else // Advance Hop limit and send to next hop { ++icmp.hop_limit; print( icmp.hop_limit + ": ", /*timestamp*/ true ); timeoutTimer = 0; timeoutCounter = 0; tStart = System.nanoTime (); sender.sendPacket( icmp ); } continue; } /* We are here because we got some ICMP packet... resolve name first. */ String hopID = p.src_ip.getHostAddress (); if ( resolveNames ) { p.src_ip.getHostName (); hopID = p.src_ip.toString (); } /* Now, in case if we received 'time exceeded' packet we should advance * to the next Hop limit. Otherwise if host is either unreachable or * we got echo reply, we should quit. */ if( p.type == ICMPPacket.ICMP_TIMXCEED ) // Time exceeded { print( hopID + ", " + tDelay + " ms", /*ts*/ false ); ++icmp.hop_limit; print( icmp.hop_limit + ": ", /*timestamp*/ true ); timeoutTimer = 0; timeoutCounter = 0; tStart = System.nanoTime (); sender.sendPacket( icmp ); } else if( p.type == ICMPPacket.ICMP_UNREACH ) // Host unreachable { print( hopID + " unreachable", /*ts*/ false ); running = false; } else if( p.type == ICMPPacket.ICMP_ECHOREPLY ) // Echo reply (pong) { print( hopID + ", " + tDelay + " ms", /*ts*/ false ); if ( initialTTL != 0 ) { println( hopID + " is alive." ); } running = false; } } } catch( UnknownHostException e ) { println( "Unknown host: " + hostName ); completed = true; context.onTracerouteCompleted (); return; } catch( IOException e ) { println( "ERROR: " + e.toString () ); completed = true; context.onTracerouteCompleted (); return; } /* Release instance to other threads */ println( initialTTL == 0 ? "Traceroute completed." : "Ping completed." ); completed = true; context.onTracerouteCompleted (); }
void Traceroute.startPinging | ( | int | deviceNo, |
String | hostName, | ||
int | initialTTL | ||
) |
Starts thread that will trace route to given host.
The instance is locked in the mean time, so other trace routes could not start in parallel. To start trace-route initialTTL
must be set to 0. To start ping instead, set initialTTL
to 64.
deviceNo | network interface on which to start pinging |
hostName | target host address or host name |
initialTTL | initial hop limit (or time-to-live) |
Definition at line 168 of file Traceroute.java.
References completed, hostName, initialTTL, openDeviceOnInterface(), running, and tracingThread.
Referenced by TraceroutePane.parseCommand().
{ synchronized( this ) { if ( ! completed ) { // Allows only one thread per instance return; } /* Set thread parameters */ openDeviceOnInterface( deviceNo ); this.hostName = hostName; this.initialTTL = initialTTL; /* Enable thread */ running = true; completed = false; /* Start thread */ tracingThread = new Thread( this ); tracingThread.start (); } }
void Traceroute.stopTrace | ( | ) |
Stops on-going trace route or ping.
Definition at line 197 of file Traceroute.java.
References print(), and running.
Referenced by TraceroutePane.parseCommand().
boolean Traceroute.tcpPortScan | ( | int | localPort, |
String | remoteHost, | ||
int | rp1, | ||
int | rp2 | ||
) | throws UnknownHostException, IOException |
Scan TCP ports.
UnknownHostException |
Definition at line 391 of file Traceroute.java.
References captor, completed, context, device, hostName, interruptibleSleep(), localIP, obtainDefaultGatewayMac(), Traceroute.Context.onTracerouteCompleted(), print(), println(), resolveNames, and running.
{ println( "-------------------------------------------------" ); print( "Looking up " + hostName + "...", /*timestamp*/ true ); InetAddress remoteIP = InetAddress.getByName( remoteHost ); print( " " + remoteIP.getHostAddress (), /*timestamp*/ false ); println (); byte[] defaultGatewayMAC = obtainDefaultGatewayMac( "dsv.su.se" ); if ( defaultGatewayMAC == null ) { running = false; completed = true; context.onTracerouteCompleted (); return running; } TCPPacket tcp = new TCPPacket( localPort, // int src_port 0, // int dst_port 701, // long sequence 0, // long ack_num false, // boolean urg false, // boolean ack false, // boolean psh false, // boolean rst true, // boolean syn false, // boolean fin true, // boolean rsv1 true, // boolean rsv2 10, // int window 10 // int urgent ); tcp.setIPv4Parameter( 0, // int priority - Priority false, // boolean: IP flag bit: Delay false, // boolean: IP flag bit: Through false, // boolean: IP flag bit: Reliability 0, // int: Type of Service (TOS) false, // boolean: Fragmentation Reservation flag false, // boolean: Don't fragment flag false, // boolean: More fragment flag 0, // int: Offset (int)(Math.random () * 65000), // int: Identifier 100, // int: Time To Live IPPacket.IPPROTO_TCP, // Protocol localIP, // Source IP address remoteIP // Destination IP address ); tcp.data=("").getBytes(); EthernetPacket ether = new EthernetPacket (); ether.frametype = EthernetPacket.ETHERTYPE_IP; ether.src_mac = device.mac_address; ether.dst_mac = defaultGatewayMAC; tcp.datalink = ether; /* Send TCP packets... */ JpcapSender sender = captor.getJpcapSenderInstance (); captor.setFilter( "tcp and dst port " + localPort + " and dst host " + localIP.getHostAddress(), true ); for ( int remotePort = rp1; remotePort <= rp2; ++remotePort ) { tcp.src_port = localPort; tcp.dst_port = remotePort; sender.sendPacket( tcp ); //println( "SENT: " + tcp ); } while( running ) { TCPPacket p = (TCPPacket)captor.getPacket (); if( p == null ) // TIMEOUT { interruptibleSleep( 100 ); continue; } /* We are here because we got some ICMP packet... resolve name first. */ String hopID = p.src_ip.getHostAddress (); if ( resolveNames ) { p.src_ip.getHostName (); hopID = p.src_ip.toString (); } // println( "---------------------------------------------------------" ); // println( "RECEIVED: " + p.toString () ); if ( ! p.rst ) { if ( p.ack_num == 702 ) { println( "---- " + hopID + " : " + p.src_port ); } tcp.dst_port = p.src_port; tcp.fin = p.ack_num == 702 ? true : false; tcp.ack = true; tcp.rst = false; tcp.syn = false; tcp.sequence = p.ack_num; tcp.ack_num = p.sequence + 1; sender.sendPacket( tcp ); //println( "SENT: " + tcp ); } // running = false; } return running; }
JpcapCaptor Traceroute.captor = null [private] |
Instance of the Jpcap capturing class.
Definition at line 78 of file Traceroute.java.
Referenced by obtainDefaultGatewayMac(), openDeviceOnInterface(), run(), and tcpPortScan().
volatile boolean Traceroute.completed [private] |
Indicates that thread has been completed.
Definition at line 68 of file Traceroute.java.
Referenced by isIdle(), run(), startPinging(), tcpPortScan(), and Traceroute().
Context Traceroute.context [private] |
Presentation context for messages.
Definition at line 111 of file Traceroute.java.
Referenced by print(), println(), run(), tcpPortScan(), and Traceroute().
NetworkInterface Traceroute.device = null [private] |
Instance of the Jpcap network interface used for sending and receiving ICMP packets.
Definition at line 84 of file Traceroute.java.
Referenced by obtainDefaultGatewayMac(), openDeviceOnInterface(), run(), and tcpPortScan().
int Traceroute.deviceCount = 0 [private] |
Jpcap NetworkInterface
device count.
Definition at line 73 of file Traceroute.java.
Referenced by getInterfaceList(), and Traceroute().
String Traceroute.hostName [private] |
Host name or IP address to ping.
Definition at line 100 of file Traceroute.java.
Referenced by run(), startPinging(), and tcpPortScan().
int Traceroute.initialTTL [private] |
Initial TTL (time to live or hop count).
When set to 0, thread will do trace route. When set to e.g. 64, thread will do ping.
Definition at line 106 of file Traceroute.java.
Referenced by run(), and startPinging().
InetAddress Traceroute.localIP = null [private] |
Local IP address.
Definition at line 89 of file Traceroute.java.
Referenced by openDeviceOnInterface(), run(), and tcpPortScan().
boolean Traceroute.resolveNames = false [private] |
Indicates whether to resolve addresses to names or not.
By default disabled, because resolving will slow down trace route presentation.
Definition at line 95 of file Traceroute.java.
Referenced by run(), and tcpPortScan().
volatile boolean Traceroute.running = false [private] |
Indicates if thread is (or should be) running.
Definition at line 63 of file Traceroute.java.
Referenced by interruptibleSleep(), obtainDefaultGatewayMac(), run(), startPinging(), stopTrace(), tcpPortScan(), and Traceroute().
Thread Traceroute.tracingThread [private] |
Instance of the thread that sends ICMP packets.
Definition at line 58 of file Traceroute.java.
Referenced by startPinging(), and Traceroute().