DIY-pcap 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -4
- data/DIY-pcap.gemspec +17 -17
- data/Gemfile +3 -3
- data/Rakefile +1 -1
- data/lib/DIY-pcap.rb +2 -2
- data/lib/diy/command.rb +7 -1
- data/lib/diy/controller.rb +10 -15
- data/lib/diy/live.rb +9 -2
- data/lib/diy/parser/mu/pcap/ethernet.rb +148 -148
- data/lib/diy/parser/mu/pcap/header.rb +75 -75
- data/lib/diy/parser/mu/pcap/io_pair.rb +67 -67
- data/lib/diy/parser/mu/pcap/io_wrapper.rb +76 -76
- data/lib/diy/parser/mu/pcap/ip.rb +61 -61
- data/lib/diy/parser/mu/pcap/ipv4.rb +257 -257
- data/lib/diy/parser/mu/pcap/ipv6.rb +148 -148
- data/lib/diy/parser/mu/pcap/packet.rb +104 -104
- data/lib/diy/parser/mu/pcap/pkthdr.rb +155 -155
- data/lib/diy/parser/mu/pcap/reader.rb +61 -61
- data/lib/diy/parser/mu/pcap/reader/http_family.rb +170 -170
- data/lib/diy/parser/mu/pcap/sctp.rb +367 -367
- data/lib/diy/parser/mu/pcap/sctp/chunk.rb +123 -123
- data/lib/diy/parser/mu/pcap/sctp/chunk/data.rb +134 -134
- data/lib/diy/parser/mu/pcap/sctp/chunk/init.rb +100 -100
- data/lib/diy/parser/mu/pcap/sctp/chunk/init_ack.rb +68 -68
- data/lib/diy/parser/mu/pcap/sctp/parameter.rb +110 -110
- data/lib/diy/parser/mu/pcap/sctp/parameter/ip_address.rb +48 -48
- data/lib/diy/parser/mu/pcap/stream_packetizer.rb +72 -72
- data/lib/diy/parser/mu/pcap/tcp.rb +505 -505
- data/lib/diy/parser/mu/pcap/udp.rb +69 -69
- data/lib/diy/parser/mu/scenario/pcap.rb +172 -172
- data/lib/diy/parser/mu/scenario/pcap/fields.rb +50 -50
- data/lib/diy/parser/mu/scenario/pcap/rtp.rb +71 -71
- data/lib/diy/parser/pcap.rb +109 -109
- data/lib/diy/version.rb +1 -1
- metadata +7 -9
| @@ -1,50 +1,50 @@ | |
| 1 | 
            -
            # http://www.mudynamics.com
         | 
| 2 | 
            -
            # http://labs.mudynamics.com
         | 
| 3 | 
            -
            # http://www.pcapr.net
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            require 'mu/scenario/pcap'
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            module Mu
         | 
| 8 | 
            -
            class Scenario
         | 
| 9 | 
            -
            module Pcap
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            class Fields
         | 
| 12 | 
            -
                FIELDS = [
         | 
| 13 | 
            -
                    :rtp,
         | 
| 14 | 
            -
                    :"rtp.setup-frame"
         | 
| 15 | 
            -
                ].freeze
         | 
| 16 | 
            -
                FIELD_COUNT = FIELDS.length
         | 
| 17 | 
            -
                SEPARATOR   = "\xff".freeze
         | 
| 18 | 
            -
                TSHARK_OPTS = "-Eseparator='#{SEPARATOR}'" 
         | 
| 19 | 
            -
                FIELDS.each do |field|
         | 
| 20 | 
            -
                    TSHARK_OPTS << " -e #{field}"
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
                TSHARK_OPTS.freeze
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                def self.readline io
         | 
| 25 | 
            -
                    if ::IO.select [ io ], nil, nil, Pcap::TSHARK_READ_TIMEOUT
         | 
| 26 | 
            -
                        return io.readline.chomp
         | 
| 27 | 
            -
                    end 
         | 
| 28 | 
            -
                    
         | 
| 29 | 
            -
                    raise Errno::ETIMEDOUT, "read timed out"
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                def self.next_from_io io
         | 
| 33 | 
            -
                    if line = readline(io)
         | 
| 34 | 
            -
                        fields = line.split SEPARATOR, FIELD_COUNT
         | 
| 35 | 
            -
                        hash = {}
         | 
| 36 | 
            -
                        FIELDS.each do |key|
         | 
| 37 | 
            -
                            val = fields.shift
         | 
| 38 | 
            -
                            hash[key] = val.empty? ? nil : val
         | 
| 39 | 
            -
                        end
         | 
| 40 | 
            -
                        return hash
         | 
| 41 | 
            -
                    end
         | 
| 42 | 
            -
                rescue Exception => e
         | 
| 43 | 
            -
                    Pcap.warning e.message
         | 
| 44 | 
            -
                    return nil
         | 
| 45 | 
            -
                end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
            end
         | 
| 48 | 
            -
            end
         | 
| 49 | 
            -
            end
         | 
| 50 | 
            -
            end
         | 
| 1 | 
            +
            # http://www.mudynamics.com
         | 
| 2 | 
            +
            # http://labs.mudynamics.com
         | 
| 3 | 
            +
            # http://www.pcapr.net
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'mu/scenario/pcap'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module Mu
         | 
| 8 | 
            +
            class Scenario
         | 
| 9 | 
            +
            module Pcap
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            class Fields
         | 
| 12 | 
            +
                FIELDS = [
         | 
| 13 | 
            +
                    :rtp,
         | 
| 14 | 
            +
                    :"rtp.setup-frame"
         | 
| 15 | 
            +
                ].freeze
         | 
| 16 | 
            +
                FIELD_COUNT = FIELDS.length
         | 
| 17 | 
            +
                SEPARATOR   = "\xff".freeze
         | 
| 18 | 
            +
                TSHARK_OPTS = "-Eseparator='#{SEPARATOR}'" 
         | 
| 19 | 
            +
                FIELDS.each do |field|
         | 
| 20 | 
            +
                    TSHARK_OPTS << " -e #{field}"
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                TSHARK_OPTS.freeze
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def self.readline io
         | 
| 25 | 
            +
                    if ::IO.select [ io ], nil, nil, Pcap::TSHARK_READ_TIMEOUT
         | 
| 26 | 
            +
                        return io.readline.chomp
         | 
| 27 | 
            +
                    end 
         | 
| 28 | 
            +
                    
         | 
| 29 | 
            +
                    raise Errno::ETIMEDOUT, "read timed out"
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def self.next_from_io io
         | 
| 33 | 
            +
                    if line = readline(io)
         | 
| 34 | 
            +
                        fields = line.split SEPARATOR, FIELD_COUNT
         | 
| 35 | 
            +
                        hash = {}
         | 
| 36 | 
            +
                        FIELDS.each do |key|
         | 
| 37 | 
            +
                            val = fields.shift
         | 
| 38 | 
            +
                            hash[key] = val.empty? ? nil : val
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                        return hash
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                rescue Exception => e
         | 
| 43 | 
            +
                    Pcap.warning e.message
         | 
| 44 | 
            +
                    return nil
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            end
         | 
| 48 | 
            +
            end
         | 
| 49 | 
            +
            end
         | 
| 50 | 
            +
            end
         | 
| @@ -1,71 +1,71 @@ | |
| 1 | 
            -
            # http://www.mudynamics.com
         | 
| 2 | 
            -
            # http://labs.mudynamics.com
         | 
| 3 | 
            -
            # http://www.pcapr.net
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            module Mu
         | 
| 6 | 
            -
            class Scenario
         | 
| 7 | 
            -
            module Pcap
         | 
| 8 | 
            -
            module Rtp
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                TRUNC_COUNT = 5
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                def self.preprocess packets, fields_per_packet
         | 
| 13 | 
            -
                    signaled_by = []
         | 
| 14 | 
            -
                    prev_signal_frame = {}
         | 
| 15 | 
            -
                    packets.each_with_index do |packet, idx|
         | 
| 16 | 
            -
                        fields = fields_per_packet[idx]
         | 
| 17 | 
            -
                        if fields and fields[:rtp]
         | 
| 18 | 
            -
                            flow_id = packet.flow_id
         | 
| 19 | 
            -
                            if frame = fields[:"rtp.setup-frame"]
         | 
| 20 | 
            -
                                prev_signal_frame[flow_id] = frame
         | 
| 21 | 
            -
                            else
         | 
| 22 | 
            -
                                if frame = prev_signal_frame[flow_id]
         | 
| 23 | 
            -
                                    fields[:"rtp.setup-frame"] = frame
         | 
| 24 | 
            -
                                else
         | 
| 25 | 
            -
                                    packets[idx] = nil
         | 
| 26 | 
            -
                                    fields_per_packet[idx] = nil
         | 
| 27 | 
            -
                                    next
         | 
| 28 | 
            -
                               end
         | 
| 29 | 
            -
                            end
         | 
| 30 | 
            -
                            sig_idx = frame.to_i 
         | 
| 31 | 
            -
                            signaled_by[idx] = sig_idx
         | 
| 32 | 
            -
                        end
         | 
| 33 | 
            -
                    end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                    flow_to_count = Hash.new 0
         | 
| 36 | 
            -
                    prev_setup_frame = {} 
         | 
| 37 | 
            -
                    keep_frames = []
         | 
| 38 | 
            -
                    packets.each_with_index do |packet, idx|
         | 
| 39 | 
            -
                        if setup_frame = signaled_by[idx]
         | 
| 40 | 
            -
                            flow = packet.flow_id
         | 
| 41 | 
            -
                            count = flow_to_count[flow]
         | 
| 42 | 
            -
                            if setup_frame != prev_setup_frame[flow]
         | 
| 43 | 
            -
                                prev_setup_frame[flow] = setup_frame
         | 
| 44 | 
            -
                                count = 1
         | 
| 45 | 
            -
                            else
         | 
| 46 | 
            -
                                count += 1 
         | 
| 47 | 
            -
                            end
         | 
| 48 | 
            -
                            if count <= TRUNC_COUNT
         | 
| 49 | 
            -
                                keep_frames << idx + 1
         | 
| 50 | 
            -
                            else
         | 
| 51 | 
            -
                                packets[idx] = nil
         | 
| 52 | 
            -
                                fields_per_packet[idx] = nil
         | 
| 53 | 
            -
                            end
         | 
| 54 | 
            -
                            flow_to_count[flow] = count
         | 
| 55 | 
            -
                        end
         | 
| 56 | 
            -
                    end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                    packets.reject! {|p| not p }
         | 
| 59 | 
            -
                    fields_per_packet.reject! {|p| not p }
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                    filter = "not rtp"
         | 
| 62 | 
            -
                    keep_frames.each do |frame|
         | 
| 63 | 
            -
                        filter << " or frame.number == #{frame}"
         | 
| 64 | 
            -
                    end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                    return filter
         | 
| 67 | 
            -
                end
         | 
| 68 | 
            -
            end
         | 
| 69 | 
            -
            end
         | 
| 70 | 
            -
            end
         | 
| 71 | 
            -
            end
         | 
| 1 | 
            +
            # http://www.mudynamics.com
         | 
| 2 | 
            +
            # http://labs.mudynamics.com
         | 
| 3 | 
            +
            # http://www.pcapr.net
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Mu
         | 
| 6 | 
            +
            class Scenario
         | 
| 7 | 
            +
            module Pcap
         | 
| 8 | 
            +
            module Rtp
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                TRUNC_COUNT = 5
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def self.preprocess packets, fields_per_packet
         | 
| 13 | 
            +
                    signaled_by = []
         | 
| 14 | 
            +
                    prev_signal_frame = {}
         | 
| 15 | 
            +
                    packets.each_with_index do |packet, idx|
         | 
| 16 | 
            +
                        fields = fields_per_packet[idx]
         | 
| 17 | 
            +
                        if fields and fields[:rtp]
         | 
| 18 | 
            +
                            flow_id = packet.flow_id
         | 
| 19 | 
            +
                            if frame = fields[:"rtp.setup-frame"]
         | 
| 20 | 
            +
                                prev_signal_frame[flow_id] = frame
         | 
| 21 | 
            +
                            else
         | 
| 22 | 
            +
                                if frame = prev_signal_frame[flow_id]
         | 
| 23 | 
            +
                                    fields[:"rtp.setup-frame"] = frame
         | 
| 24 | 
            +
                                else
         | 
| 25 | 
            +
                                    packets[idx] = nil
         | 
| 26 | 
            +
                                    fields_per_packet[idx] = nil
         | 
| 27 | 
            +
                                    next
         | 
| 28 | 
            +
                               end
         | 
| 29 | 
            +
                            end
         | 
| 30 | 
            +
                            sig_idx = frame.to_i 
         | 
| 31 | 
            +
                            signaled_by[idx] = sig_idx
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    flow_to_count = Hash.new 0
         | 
| 36 | 
            +
                    prev_setup_frame = {} 
         | 
| 37 | 
            +
                    keep_frames = []
         | 
| 38 | 
            +
                    packets.each_with_index do |packet, idx|
         | 
| 39 | 
            +
                        if setup_frame = signaled_by[idx]
         | 
| 40 | 
            +
                            flow = packet.flow_id
         | 
| 41 | 
            +
                            count = flow_to_count[flow]
         | 
| 42 | 
            +
                            if setup_frame != prev_setup_frame[flow]
         | 
| 43 | 
            +
                                prev_setup_frame[flow] = setup_frame
         | 
| 44 | 
            +
                                count = 1
         | 
| 45 | 
            +
                            else
         | 
| 46 | 
            +
                                count += 1 
         | 
| 47 | 
            +
                            end
         | 
| 48 | 
            +
                            if count <= TRUNC_COUNT
         | 
| 49 | 
            +
                                keep_frames << idx + 1
         | 
| 50 | 
            +
                            else
         | 
| 51 | 
            +
                                packets[idx] = nil
         | 
| 52 | 
            +
                                fields_per_packet[idx] = nil
         | 
| 53 | 
            +
                            end
         | 
| 54 | 
            +
                            flow_to_count[flow] = count
         | 
| 55 | 
            +
                        end
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                    packets.reject! {|p| not p }
         | 
| 59 | 
            +
                    fields_per_packet.reject! {|p| not p }
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    filter = "not rtp"
         | 
| 62 | 
            +
                    keep_frames.each do |frame|
         | 
| 63 | 
            +
                        filter << " or frame.number == #{frame}"
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    return filter
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
            end
         | 
| 69 | 
            +
            end
         | 
| 70 | 
            +
            end
         | 
| 71 | 
            +
            end
         | 
    
        data/lib/diy/parser/pcap.rb
    CHANGED
    
    | @@ -1,113 +1,113 @@ | |
| 1 | 
            -
            # http://www.mudynamics.com
         | 
| 2 | 
            -
            # http://labs.mudynamics.com
         | 
| 1 | 
            +
            # http://www.mudynamics.com
         | 
| 2 | 
            +
            # http://labs.mudynamics.com
         | 
| 3 3 | 
             
            # http://www.pcapr.net
         | 
| 4 4 |  | 
| 5 5 | 
             
            $LOAD_PATH.unshift File.dirname(__FILE__)
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            require 'socket'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            require 'socket'
         | 
| 8 8 | 
             
            require 'stringio'
         | 
| 9 | 
            -
            require 'mu/fixnum_ext'
         | 
| 10 | 
            -
             | 
| 11 | 
            -
            module Mu
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            class Pcap
         | 
| 14 | 
            -
                class ParseError < StandardError ; end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                LITTLE_ENDIAN = 0xd4c3b2a1
         | 
| 17 | 
            -
                BIG_ENDIAN    = 0xa1b2c3d4
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                DLT_NULL      = 0
         | 
| 20 | 
            -
                DLT_EN10MB    = 1
         | 
| 21 | 
            -
                DLT_RAW       = 12 # DLT_LOOP in OpenBSD
         | 
| 22 | 
            -
                DLT_LINUX_SLL = 113
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                attr_accessor :header, :pkthdrs
         | 
| 25 | 
            -
                
         | 
| 26 | 
            -
                def initialize
         | 
| 27 | 
            -
                    @header = Header.new
         | 
| 28 | 
            -
                    @pkthdrs = []
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                # Read PCAP file from IO and return Mu::Pcap.  If decode is true, also
         | 
| 32 | 
            -
                # decode the Pkthdr packet contents to Mu::Pcap objects.
         | 
| 33 | 
            -
                def self.read io, decode=true
         | 
| 34 | 
            -
                    pcap = Pcap.new
         | 
| 35 | 
            -
                    pcap.header = each_pkthdr(io, decode) do |pkthdr|
         | 
| 36 | 
            -
                        pcap.pkthdrs << pkthdr
         | 
| 37 | 
            -
                    end
         | 
| 38 | 
            -
                    return pcap
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                # Create PCAP from list of packets.
         | 
| 42 | 
            -
                def self.from_packets packets
         | 
| 43 | 
            -
                    pcap = Pcap.new
         | 
| 44 | 
            -
                    packets.each do |packet|
         | 
| 45 | 
            -
                        pkthdr = Mu::Pcap::Pkthdr.new
         | 
| 46 | 
            -
                        pkthdr.pkt = packet
         | 
| 47 | 
            -
                        pcap.pkthdrs << pkthdr
         | 
| 48 | 
            -
                    end
         | 
| 49 | 
            -
                    return pcap
         | 
| 50 | 
            -
                end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                # Write PCAP file to IO.  Uses big-endian and linktype EN10MB.
         | 
| 53 | 
            -
                def write io
         | 
| 54 | 
            -
                    @header.write io
         | 
| 55 | 
            -
                    @pkthdrs.each do |pkthdr|
         | 
| 56 | 
            -
                        pkthdr.write io
         | 
| 57 | 
            -
                    end
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                # Read PCAP packet headers from IO and return Mu::Pcap::Header.  If decode
         | 
| 61 | 
            -
                # is true, also decode the Pkthdr packet contents to Mu::Pcap objects.  Use
         | 
| 62 | 
            -
                # this for large files when each packet header can processed independently
         | 
| 63 | 
            -
                # - it will perform better.
         | 
| 64 | 
            -
                def self.each_pkthdr io, decode=true
         | 
| 65 | 
            -
                    header = Header.read io
         | 
| 66 | 
            -
                    while not io.eof?
         | 
| 67 | 
            -
                        pkthdr = Pkthdr.read io, header.magic
         | 
| 68 | 
            -
                        if decode
         | 
| 69 | 
            -
                            pkthdr.decode! header.magic, header.linktype
         | 
| 70 | 
            -
                        end
         | 
| 71 | 
            -
                        yield pkthdr
         | 
| 72 | 
            -
                    end
         | 
| 73 | 
            -
                    return header
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                # Read packets from PCAP
         | 
| 77 | 
            -
                def self.read_packets io, decode=true
         | 
| 78 | 
            -
                    packets = []
         | 
| 79 | 
            -
                    each_pkthdr(io) { |pkthdr| packets << pkthdr.pkt }
         | 
| 80 | 
            -
                    return packets
         | 
| 81 | 
            -
                end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
                # Assertion used during Pcap parsing
         | 
| 84 | 
            -
                def self.assert cond, msg
         | 
| 85 | 
            -
                    if not cond
         | 
| 86 | 
            -
                        raise ParseError, msg
         | 
| 87 | 
            -
                    end
         | 
| 88 | 
            -
                end
         | 
| 89 | 
            -
             | 
| 90 | 
            -
                # Warnings from Pcap parsing are printed using this method.
         | 
| 91 | 
            -
                def self.warning msg
         | 
| 92 | 
            -
                    $stderr.puts "WARNING: #{msg}"
         | 
| 93 | 
            -
                end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                def == other
         | 
| 96 | 
            -
                    return self.class == other.class &&
         | 
| 97 | 
            -
                        self.header   == other.header &&
         | 
| 98 | 
            -
                        self.pkthdrs  == other.pkthdrs
         | 
| 99 | 
            -
                end
         | 
| 100 | 
            -
            end
         | 
| 101 | 
            -
             | 
| 102 | 
            -
            end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
            require 'mu/pcap/header'
         | 
| 105 | 
            -
            require 'mu/pcap/pkthdr'
         | 
| 106 | 
            -
            require 'mu/pcap/packet'
         | 
| 107 | 
            -
            require 'mu/pcap/ethernet'
         | 
| 108 | 
            -
            require 'mu/pcap/ip'
         | 
| 109 | 
            -
            require 'mu/pcap/ipv4'
         | 
| 110 | 
            -
            require 'mu/pcap/ipv6'
         | 
| 111 | 
            -
            require 'mu/pcap/tcp'
         | 
| 112 | 
            -
            require 'mu/pcap/udp'
         | 
| 113 | 
            -
            require 'mu/pcap/sctp'
         | 
| 9 | 
            +
            require 'mu/fixnum_ext'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            module Mu
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            class Pcap
         | 
| 14 | 
            +
                class ParseError < StandardError ; end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                LITTLE_ENDIAN = 0xd4c3b2a1
         | 
| 17 | 
            +
                BIG_ENDIAN    = 0xa1b2c3d4
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                DLT_NULL      = 0
         | 
| 20 | 
            +
                DLT_EN10MB    = 1
         | 
| 21 | 
            +
                DLT_RAW       = 12 # DLT_LOOP in OpenBSD
         | 
| 22 | 
            +
                DLT_LINUX_SLL = 113
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                attr_accessor :header, :pkthdrs
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                def initialize
         | 
| 27 | 
            +
                    @header = Header.new
         | 
| 28 | 
            +
                    @pkthdrs = []
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                # Read PCAP file from IO and return Mu::Pcap.  If decode is true, also
         | 
| 32 | 
            +
                # decode the Pkthdr packet contents to Mu::Pcap objects.
         | 
| 33 | 
            +
                def self.read io, decode=true
         | 
| 34 | 
            +
                    pcap = Pcap.new
         | 
| 35 | 
            +
                    pcap.header = each_pkthdr(io, decode) do |pkthdr|
         | 
| 36 | 
            +
                        pcap.pkthdrs << pkthdr
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                    return pcap
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                # Create PCAP from list of packets.
         | 
| 42 | 
            +
                def self.from_packets packets
         | 
| 43 | 
            +
                    pcap = Pcap.new
         | 
| 44 | 
            +
                    packets.each do |packet|
         | 
| 45 | 
            +
                        pkthdr = Mu::Pcap::Pkthdr.new
         | 
| 46 | 
            +
                        pkthdr.pkt = packet
         | 
| 47 | 
            +
                        pcap.pkthdrs << pkthdr
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                    return pcap
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                # Write PCAP file to IO.  Uses big-endian and linktype EN10MB.
         | 
| 53 | 
            +
                def write io
         | 
| 54 | 
            +
                    @header.write io
         | 
| 55 | 
            +
                    @pkthdrs.each do |pkthdr|
         | 
| 56 | 
            +
                        pkthdr.write io
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # Read PCAP packet headers from IO and return Mu::Pcap::Header.  If decode
         | 
| 61 | 
            +
                # is true, also decode the Pkthdr packet contents to Mu::Pcap objects.  Use
         | 
| 62 | 
            +
                # this for large files when each packet header can processed independently
         | 
| 63 | 
            +
                # - it will perform better.
         | 
| 64 | 
            +
                def self.each_pkthdr io, decode=true
         | 
| 65 | 
            +
                    header = Header.read io
         | 
| 66 | 
            +
                    while not io.eof?
         | 
| 67 | 
            +
                        pkthdr = Pkthdr.read io, header.magic
         | 
| 68 | 
            +
                        if decode
         | 
| 69 | 
            +
                            pkthdr.decode! header.magic, header.linktype
         | 
| 70 | 
            +
                        end
         | 
| 71 | 
            +
                        yield pkthdr
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                    return header
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                # Read packets from PCAP
         | 
| 77 | 
            +
                def self.read_packets io, decode=true
         | 
| 78 | 
            +
                    packets = []
         | 
| 79 | 
            +
                    each_pkthdr(io) { |pkthdr| packets << pkthdr.pkt }
         | 
| 80 | 
            +
                    return packets
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                # Assertion used during Pcap parsing
         | 
| 84 | 
            +
                def self.assert cond, msg
         | 
| 85 | 
            +
                    if not cond
         | 
| 86 | 
            +
                        raise ParseError, msg
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                # Warnings from Pcap parsing are printed using this method.
         | 
| 91 | 
            +
                def self.warning msg
         | 
| 92 | 
            +
                    $stderr.puts "WARNING: #{msg}"
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def == other
         | 
| 96 | 
            +
                    return self.class == other.class &&
         | 
| 97 | 
            +
                        self.header   == other.header &&
         | 
| 98 | 
            +
                        self.pkthdrs  == other.pkthdrs
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
            end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            require 'mu/pcap/header'
         | 
| 105 | 
            +
            require 'mu/pcap/pkthdr'
         | 
| 106 | 
            +
            require 'mu/pcap/packet'
         | 
| 107 | 
            +
            require 'mu/pcap/ethernet'
         | 
| 108 | 
            +
            require 'mu/pcap/ip'
         | 
| 109 | 
            +
            require 'mu/pcap/ipv4'
         | 
| 110 | 
            +
            require 'mu/pcap/ipv6'
         | 
| 111 | 
            +
            require 'mu/pcap/tcp'
         | 
| 112 | 
            +
            require 'mu/pcap/udp'
         | 
| 113 | 
            +
            require 'mu/pcap/sctp'
         |