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

Quick Search    Search Deep

Source code: com/voytechs/jnetstream/io/SnoopInputStream.java


1   /*
2    * File: SnoopInputStream.java
3    * Auth: Mark Bednarczyk
4    * Date: 2003-06-30
5    *   Id: $Id: SnoopInputStream.java,v 1.1.1.1 2003/09/22 16:32:09 voytechs Exp $
6    ********************************************
7    Copyright (C) 2003  Mark Bednarczyk
8   
9    This program is free software; you can redistribute it and/or
10   modify it under the terms of the GNU General Public License
11   as published by the Free Software Foundation; either version 2
12   of the License, or (at your option) any later version.
13  
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22   ********************************************
23   * $Log: SnoopInputStream.java,v $
24   * Revision 1.1.1.1  2003/09/22 16:32:09  voytechs
25   * Initial import.
26   *
27   */
28  package com.voytechs.jnetstream.io;
29  
30  import com.voytechs.jnetstream.codec.*;
31  
32  import com.voytechs.jnetstream.protocol.layer2.*;
33  import com.voytechs.jnetstream.protocol.layer3.*;
34  import com.voytechs.jnetstream.protocol.layer4.*;
35  
36  import com.voytechs.jnetanalyzer.tcp.*;
37  
38  import java.lang.*;
39  import java.util.*;
40  import java.io.*;
41  import java.io.FileNotFoundException;
42  import java.sql.Timestamp;
43  
44  /**
45   * 
46   * For structure of the Snoop file see RFC1761
47   * http://www.faqs.org/rfcs/rfc1761.html
48   */
49  public class SnoopInputStream 
50    extends PacketInputStream {
51  
52    /* Internal attributes */
53    private static final boolean debug = false;
54  
55    private static final byte[] SNOOP_MAGIC_NUMBER = {
56      0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00, 0x00, 0x00
57    };
58  
59    private byte[] snoopMagicNumber = SNOOP_MAGIC_NUMBER;
60    private long snoopMajorVer;
61    private long snoopSnaplen;
62    private long snoopLinktype;
63  
64    private long snoopPacketCaptureSecs;
65    private long snoopPacketCaptureNanos;
66    private long snoopPacketLength;
67    private long snoopRecordLength;
68    private long snoopCumulativeDrops;
69  
70    private static String[] linkNames = {
71      "Ieee802dot3",
72      "Ieee802dot4",
73      "Ieee802dot5",
74      "Ethernet2",
75      "HDLC",
76      "CharacterSynchronous",
77      "IBMChannel",
78      "FDDI"
79    };
80  
81  
82    /**
83     *
84     * @param
85     * @exception
86     */
87    public SnoopInputStream(InputStream snoopFileFormatInputStream)
88      throws 
89        IOException, 
90        EOPacketStream,
91        StreamFormatException {
92  
93      super(new BitStackInputStream(snoopFileFormatInputStream));
94      initPacketStream();
95  
96      super.captureDeviceFilename = "stream: snoopFileFormat";
97    }
98  
99    /**
100    * Opens up the given file and starts processing the data.
101    * @param filename Filename of the file in SNOOP fileformat to open.
102    * @exception
103    */
104   public SnoopInputStream(String filename) 
105     throws 
106       FileNotFoundException, 
107       IOException, 
108       EOPacketStream,
109       StreamFormatException {
110 
111     /**
112      * Open filestream for reading and pass it on.
113      */
114     super(new BitStackInputStream(new FileInputStream(filename)));
115 
116     initPacketStream();
117     super.captureDeviceFilename = "file: " + filename;
118   }
119 
120   /**
121    * Since we know we are dealing with a Snoop-file formatted stream
122    * (i.e. FileInputStream("snoop-capturefile.snoop")) we initialize
123    * the ProtocolInputStream using values extracted from the snoop stream.
124    *
125    * First we extract the "snoop_file_heaer" as specified above.
126    */
127   protected void initPacketStream()
128     throws 
129       IOException, 
130       EOPacketStream, 
131       StreamFormatException {
132 
133     /**
134      * Needed to temporarily allow reading of data from the stream so
135      * we can read in the headers.
136      */
137     setForceRead(true);
138 
139     try {
140       for(int i = 0; i < snoopMagicNumber.length; i ++) {
141         if(snoopMagicNumber[i] != readUnsignedByte())
142           throw new StreamFormatException(
143             "Stream in non-SNOOP format. Invalid magic number at the begining" +
144             " of the file." +
145             "(expected=" + snoopMagicNumber + ")"
146         );
147       }
148 
149       snoopMajorVer = readUnsignedInt();
150       snoopLinktype = readUnsignedInt();
151     }
152     catch(EOPacket eop) {
153       // Should never happen. We are not in the packet data stream at this
154       // point.
155       throw new IOException("Packet data protection exception ocurred in initPacketStream() method. Very unexpected.");
156     }
157 
158     setForceRead(false);
159 
160     /**
161      * Lastly initialize the system specific things we know.
162      */
163     captureDeviceOS = System.getProperty("os.name");
164     captureDeviceOS += " " + System.getProperty("os.version");
165     captureDeviceArch += " " + System.getProperty("os.arch");
166   }
167 
168   /**
169    * Read pre-packet header from stream. With basic info about the next
170    * packet to follow.
171    * this is called for every packet in the stream. Main purpose is to
172    * get packet-data length (or length of captured packet) and the
173    * capture time of the packet.
174    */
175   protected void readPacketPreHeader()
176     throws 
177       IOException, 
178       EOPacketStream, 
179       StreamFormatException{
180 
181     /**
182      * Needed to temporarily allow reading of data from the stream so
183      * we can read in the headers.
184      */
185     setForceRead(true);
186 
187     try {
188 
189       if(debug)
190         System.out.println("readPacketPreHeader(): " 
191           + StreamUtil.toString(position()));
192 
193       // packet length in the stream.
194 
195       /* Included Length 32bits */
196       super.packetSnaplen = (int)readUnsignedInt(); 
197 
198       /* Original Length 32bits */
199       snoopPacketLength = readUnsignedInt();
200       super.packetLength = (int)snoopPacketLength;
201 
202 
203       /* Record Length 32bits */
204       snoopRecordLength = readUnsignedInt(); 
205       this.recordLength = (int)snoopRecordLength - 24; // 24 is the length of the record header
206 
207       System.out.println("recordLength=" + recordLength);
208 
209       /* Cumulative Drops 32bits */
210       snoopCumulativeDrops = readUnsignedInt(); 
211 
212       // secs.nanos (this is time)
213       snoopPacketCaptureSecs = (long)readUnsignedInt() * 1000;
214       super.packetCaptureTimestamp = new Timestamp(snoopPacketCaptureSecs); 
215       snoopPacketCaptureNanos = readUnsignedInt() * 1000; 
216       super.packetCaptureTimestamp.setNanos((int)snoopPacketCaptureNanos); 
217 
218     }
219     catch(IllegalArgumentException iae) {
220       /*
221        * Normally caused by Timestamp.setNanos when stream does not contain
222        * right data and we use an invalid nanos value. This exception will
223        * be caused by invalid stream format. Could be corrupt stream or
224        * incomplete file.
225        */
226       throw new StreamFormatException(
227         "Invalid data in the stream. Value is outside the valid range of " + 
228         "standard primitive type timestamp.nanos. This can only be caused " +
229         " by corrupt or invalid data stream."
230       );
231     }
232     catch(EOPacket eop) {
233       /*
234        * Should never happen since we are in-between packet data and
235        * are reading packet SNOOP pre-header.
236        */
237       throw new IOException("Packet data protection exception ocurred in readPacketPreHeader() method. Very unexpected.");
238     }
239 
240     setForceRead(false);
241   }
242 
243   public String toString() {
244     String s = "";
245 
246     if(debug) {
247       s += "snoopMagicNumber=" + snoopMagicNumber;
248       s += ", snoopMajorVer=" + snoopMajorVer;
249       s += ", snoopSnaplen=" + snoopSnaplen;
250       s += ", snoopLinktype=" + snoopLinktype;
251       s += ", timestamp=" + Long.toHexString(snoopPacketCaptureSecs);
252       s += "." + Long.toHexString(snoopPacketCaptureNanos);
253     }
254       
255     return(s);
256   }
257 
258   /**
259    * Returns the magic number found at the beginning of the SNOOP file.
260    */
261   public byte[] getSnoopMagicNumber() { return(snoopMagicNumber); }
262 
263   /**
264    * Returns the major version number of the SNOOP file.
265    */
266   public long getSnoopMajorVer() { return(snoopMajorVer); }
267 
268   /**
269    * Retuns the SNAP len of the capture file. This is the number of bytes
270    * that we saved, not captured. i.e. first 128 bytes.
271    */
272   public long snoopSnaplen() { return(snoopSnaplen); }
273 
274   /**
275    * The link type of the first header in the packet. Normally this is type 2 (ethernet)
276    * but any of the others are possible as well.
277    */
278   public long snoopLinktype() { return(snoopLinktype); }
279 
280   /**
281    * Number of raw number of the capture file. JNetStream library multiplies this number
282    * by factor of 1000 before returning it.
283    * <BR><BR>
284    * This value changes from packet to packet.
285    */
286   public long snoopPacketCaptureSecs() { return(snoopPacketCaptureSecs); }
287 
288   /**
289    * Number of naono seconds found in the raw data file. This number is also
290    * multiplied by 1000.
291    * <BR><BR>
292    * This value changes from packet to packet.
293    */
294   public long snoopPacketCaptureNanos() { return(snoopPacketCaptureNanos); }
295 
296 
297 
298   /**
299    * Test function for SnoopInputStream
300    * @param args command line arguments
301    */
302   public static void main(String [] args) {
303 
304     String file = "abc";
305 
306     if(args.length > 0)
307       file = args[0];
308 
309     Hashtable perm = new Hashtable();
310     TCPAnalyzer analyzer = new TCPAnalyzer();
311 
312     try {
313       SnoopInputStream snoop;
314       
315       if(file.equals("-"))
316         snoop = new SnoopInputStream(System.in);
317       else
318         snoop = new SnoopInputStream(file);
319 
320       System.out.println("Capture Device Address: " + 
321         snoop.getCaptureDeviceAddress());
322       System.out.println("Capture Device OS: " + snoop.getCaptureDeviceOS());
323       System.out.println("Capture Device Arch: " + snoop.getCaptureDeviceArch());
324       System.out.println("Capture Device Filename: " + snoop.getCaptureDeviceFilename());
325       System.out.println("Is this capture live? " + snoop.isCaptureLive());
326       System.out.println("-------------");
327 
328 
329       for(int i = 0; ; i ++) {
330         try {
331 
332           /*
333            * The way the example is setup there are 2 ways of running this loop.
334            *
335            * 1) is to call nextPacket() on every turn at the top. This will effectively
336            * skip any unread bytes until the end of the current packet (not the stream).
337            * After all of the data has been skipped, the PacketInputStream will read any
338            * packet data description headers expected in the stream, ie. what the length
339            * of the packet will be in the stream and the capture time of the packet.
340            *
341            * 2) Second method is to not do a nextPacket() call until the first read from
342            * the packet stream will generate a EOPacket exception. The exception is caught is
343            * the catch() statement below but still within the loop and there nextPacket() call
344            * executed and the loop starts over, but on the second time around the stream
345            * is ready for reading packet data.
346            */
347 //          snoop.isReady();
348           snoop.nextPacket();
349 
350 
351 
352           System.out.println("------------- " + (i+1) + " --------------");
353 
354 
355           MutablePacket pkt = new PacketImpl(perm, snoop);
356           Ethernet2 ethernet = new Ethernet2(snoop);
357           pkt.addHeader(ethernet);
358 //          System.out.println(ethernet.getShortName() + ".proto=" + Integer.toHexString(ethernet.proto));
359 
360 
361           if(ethernet.proto == 0x800) {
362             IPv4 ip = new IPv4(snoop);
363             pkt.addHeader(ip);
364             System.out.print("[" + ip.src + "," + ip.dst + "]");
365             System.out.print("=" + ip.len);
366           
367 
368             snoop.push();
369 
370             if(ip.proto == 6) {
371               TCP tcp = new TCP(snoop);
372               pkt.addHeader(tcp);
373               System.out.print(" " + tcp.src);
374               System.out.print("->" + tcp.dst);
375               System.out.print(" S=" + tcp.seq);
376               System.out.print(" A=" + tcp.ack);
377 
378               System.out.println();
379 
380               analyzer.processPacket((Packet)pkt);
381             }
382             else {
383               System.out.println("Not TCP protocol");
384             }
385 
386             snoop.pop();
387             System.out.println(TCP.toString(snoop));
388           }
389 
390             /*
391              * Push this position within the stream onto a stack of positions.
392              * The BitStackInputStream starts buffering from the first push.
393              * (Trust me the BitStackInputStream object is in the chain of all of
394              * InputStreams. Its internally instantiated by the PacketInputStream
395              * if it was not passed in directly.)
396              */
397 //          snoop.push();
398 
399             /*
400              * For kicks printout a few headers from the stream.
401              */
402 //          System.out.println(Ethernet2.toString(snoop));
403 //          System.out.println(IPv4.toString(snoop));
404 //          System.out.println(TCP.toString(snoop));
405 
406             /*
407              * Now pop the previous pushed position off of the stack in
408              * BitStackInputStream module. The stream will be rewounded back to
409              * that position and any subsequent read() calls will read from the
410              * buffer. When all of the data is read from the buffer, addtional reads
411              * will result in data from the live stream.
412              */
413 //          snoop.pop();
414 
415             /*
416              * Use this utility static method to print the contents of the
417              * entire packet, the same one that just printed out the headers above,
418              * but this time printout raw values in HEX. Since the data is rewound
419              * the values used by this print routine are from the stream. Because
420              * of the pop() call above, you can assume that this data is comming from
421              * a buffer, but utilizing the true stream interface.
422              */
423 //          BitDataInputStream.printStream(snoop, snoop.getPacketLength());
424 
425 
426           /*
427            * Skip all the remaining bytes in the packet.
428            * Ofcournse snoop.skip(nBytes) is much more efficient.
429            */
430 //          while(snoop.readFromPacket() != -1);
431         }
432         catch(EOPacket eop) {
433           System.out.println("Unexpected EOF Packet");
434           snoop.nextPacket();
435 
436           System.out.println();
437           System.out.flush();
438         }
439       }
440     }
441     catch(StreamFormatException sfe) {
442       System.out.println(sfe);
443       System.exit(1);
444     }
445     catch(EOPacketStream eos) {
446       System.out.println();
447       System.out.println("DONE!");
448     }
449     catch(FileNotFoundException e) {
450       System.out.println(e);
451       System.exit(1);
452     }
453     catch(IOException ioe) {
454       System.out.println(ioe);
455       ioe.printStackTrace();
456       System.exit(1);
457     }
458 
459     System.out.println(analyzer.toString());
460   }
461 
462 } /* END OF: SnoopInputStream */