Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/act365/net/ping/Traceroute.java


1   /*
2     * JSocket Wrench
3     * 
4     * Copyright (C) act365.com October 2003
5     * 
6     * Web site: http://www.act365.com/wrench
7     * E-mail: developers@act365.com
8     * 
9     * The JSocket Wrench library adds support for low-level Internet protocols
10    * to the Java programming language.
11    * 
12    * This program is free software; you can redistribute it and/or modify it 
13    * under the terms of the GNU General Public License as published by the Free 
14    * Software Foundation; either version 2 of the License, or (at your option) 
15    * any later version.
16    *  
17    * This program is distributed in the hope that it will be useful, 
18    * but WITHOUT ANY WARRANTY; without even the implied warranty of 
19    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
20    * Public License for more details.
21    * 
22    * You should have received a copy of the GNU General Public License along with 
23    * this program; if not, write to the Free Software Foundation, Inc., 
24    * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25    */
26  
27  package com.act365.net.ping ;
28  
29  import com.act365.net.*;
30  import com.act365.net.icmp.*;
31  import com.act365.net.ip.*;
32  import com.act365.net.udp.*;
33  
34  import java.net.*;
35  import java.util.*;
36  
37  /**
38   Implements the well-known Traceroute network utility. The app supports
39   the broadcast of UDP or ICMP ECHO_REQUEST packets.
40  */
41  
42  public class Traceroute {
43     
44    /**
45     Executes the Traceroute service.
46     <p>Usage: <code>Traceroute -p protocol -l localhost -d host</code>
47     <p><code>protocol</code> is the protocol to be used for broadcast. The default 
48     is ICMP - the alternative is UDP.
49     <p><code>localhost</code> is the local host address, which should be specified
50     if UDP is used. (The information is used to calculate the UDP checksum).
51     <p><code>-d</code> should be specified if debug is required.
52     <p><code>host</code> is the remote hostname and is mandatory.
53    */
54  
55    public static void main( String[] args ){
56  
57      final String errortext = "Usage: Traceroute -p protocol -l localhost -d host";
58      
59      if( args.length == 0 ){
60        System.err.println( errortext );
61        System.exit( 1 );
62      }
63      
64      String hostname = args[ args.length - 1 ] ,
65             localhost = null ;
66  
67      String protocollabel = null ;
68     
69      boolean debug = false ;
70  
71      int i = 0 ;
72  
73      while( i < args.length - 1 ){
74        if( args[ i ].equals("-p") && i < args.length - 2 ){
75          protocollabel = args[ ++ i ];
76          if( ! protocollabel.equalsIgnoreCase("ICMP") && 
77              ! protocollabel.equalsIgnoreCase("UDP") ){
78            System.err.println("Unsupported protocol");
79            System.exit( 2 );
80          }
81        } else if( args[ i ].equals("-l") && i < args.length - 2 ){
82          localhost = args[ ++ i ]; 
83        } else if( args[ i ].equals("-d") ){
84          debug = true ;
85        } else {
86          System.err.println( errortext );
87          System.exit( 1 );
88        }
89        ++ i ;
90      }
91  
92      try {
93      SocketUtils.setProtocol("RawICMP");
94      } catch ( java.io.IOException e ) {
95        System.err.println("Unsupported protocol");
96        System.exit( 4 );
97      }
98  
99      int protocol = protocollabel instanceof String && protocollabel.equalsIgnoreCase("UDP") 
100                                ? SocketConstants.IPPROTO_UDP : SocketConstants.IPPROTO_ICMP ;
101     
102     new SocketWrenchSession();
103 
104     InetAddress hostaddr = null ,
105                 localaddr = null ;
106 
107     try {
108       hostaddr = InetAddress.getByName( hostname );
109       if( localhost instanceof String ){
110         localaddr = InetAddress.getByName( localhost );
111       }
112     } catch ( UnknownHostException e ) {
113       System.err.println( e.getMessage() );
114       System.exit( 5 );
115     }
116 
117     if( protocol == SocketConstants.IPPROTO_UDP && localaddr == null ){
118       System.err.println("localhost must be defined if RawUDP is to be used");
119       System.exit( 6 );
120     }
121 
122     DatagramSocket socket = null ;
123 
124     try {
125       socket = new DatagramSocket();
126     } catch ( SocketException e ) {
127       System.err.println( e.getMessage() );
128       System.exit( 7 );
129     }
130 
131     try {
132 
133       final int maxdatagramlength = 512 ;
134 
135       byte[] recvbuffer = new byte[ maxdatagramlength ] ,
136              timebuffer = new byte[ 8 ] ,
137              messagebuffer ,
138              sendbuffer ;
139 
140       DatagramPacket packet ;
141 
142       ICMPWriter writer = new ICMPWriter( (short) socket.hashCode() );
143 
144       ICMPReader reader = new ICMPReader( (short) socket.hashCode() );
145 
146       ICMPMessage message = null ;
147 
148       float sumdt = 0 ,
149             mindt = Float.MAX_VALUE ,
150             maxdt = Float.MIN_VALUE ;
151 
152       short ttl = 0 ;
153 
154       int sourceport = 42000 ,
155           destinationport = 64000 ;
156 
157       while( message == null || message.type != ICMP.ICMP_ECHOREPLY || message.type != ICMP.ICMP_DEST_UNREACH ){
158 
159         SocketUtils.longToBytes( new Date().getTime() , timebuffer , 0 );
160 
161         switch( protocol ){
162     
163         case SocketConstants.IPPROTO_ICMP:
164           messagebuffer = writer.write( ICMP.ICMP_ECHO , (byte) 0 , timebuffer );
165           break;
166 
167         case SocketConstants.IPPROTO_UDP:
168           messagebuffer = UDPWriter.write( localaddr.getAddress() , 
169                                            (short) sourceport ++ , 
170                                            hostaddr.getAddress() , 
171                                            (short) destinationport ++ ,
172                                            timebuffer ,
173                                            timebuffer.length );
174           break;
175 
176         default:
177           messagebuffer = new byte[0];
178         }
179 
180 
181         sendbuffer = IP4Writer.write( IP4.TOS_ICMP , 
182                                       ++ ttl , 
183                                       (byte) protocol , 
184                                       localaddr != null ? localaddr.getAddress() : new byte[ 4 ] , 
185                                       hostaddr.getAddress() , 
186                                       messagebuffer );
187 
188         if( debug ){
189           System.err.println("SEND:");
190           SocketUtils.dump( System.err , sendbuffer , 0 , sendbuffer.length );
191         }
192 
193         socket.send( new DatagramPacket( sendbuffer , sendbuffer.length , hostaddr , 0 ) );
194 
195         packet = new DatagramPacket( recvbuffer , maxdatagramlength );
196 
197         socket.receive( packet );
198 
199         if( ( message = reader.read( packet.getData() , packet.getLength() , 20 , false ) ) != null ){ 
200 
201           if( debug ){
202             System.err.println("RECEIVE:");
203             SocketUtils.dump( System.err , packet.getData() , 0 , packet.getLength() );
204           }  
205 
206           if( message.type == ICMP.ICMP_TIME_EXCEEDED ||
207               message.type == ICMP.ICMP_ECHOREPLY || 
208               message.type == ICMP.ICMP_DEST_UNREACH ){
209             System.out.println( packet.getAddress() );
210           } else {
211             System.out.println( ICMP.typelabels[ message.type ] );
212           }
213         }
214       }
215 
216     } catch ( Exception e ) {
217       System.err.println( e.getMessage() );
218       System.exit( 8 );
219     }
220   }
221 }
222