Class: Mu::Pcap::Pkthdr

Inherits:
Object
  • Object
show all
Defined in:
lib/mu/pcap/pkthdr.rb

Constant Summary collapse

FMT_NNNN =
'NNNN'
FMT_VVVV =
'VVVV'
BSD_AF_INET6 =

See wiki.wireshark.org/NullLoopback and epan/aftypes.h in wireshark code.

[
    OPENBSD_AF_INET6 = 24,
    FREEBSD_AF_INET6 = 28,
    DARWIN_AF_INET6 = 30
]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(endian = BIG_ENDIAN, ts_sec = 0, ts_usec = 0, caplen = 0, len = 0, pkt = nil) ⇒ Pkthdr

Returns a new instance of Pkthdr.



11
12
13
14
15
16
17
18
19
# File 'lib/mu/pcap/pkthdr.rb', line 11

def initialize endian=BIG_ENDIAN, ts_sec=0, ts_usec=0, caplen=0, len=0, pkt=nil
    @endian = endian
    @ts_sec = ts_sec
    @ts_usec = ts_usec
    @caplen = caplen
    @len = len
    @pkt = pkt
    @pkt_raw = pkt
end

Instance Attribute Details

#caplenObject

Returns the value of attribute caplen.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def caplen
  @caplen
end

#endianObject

Returns the value of attribute endian.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def endian
  @endian
end

#lenObject

Returns the value of attribute len.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def len
  @len
end

#pktObject

Returns the value of attribute pkt.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def pkt
  @pkt
end

#pkt_rawObject

Returns the value of attribute pkt_raw.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def pkt_raw
  @pkt_raw
end

#ts_secObject

Returns the value of attribute ts_sec.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def ts_sec
  @ts_sec
end

#ts_usecObject

Returns the value of attribute ts_usec.



9
10
11
# File 'lib/mu/pcap/pkthdr.rb', line 9

def ts_usec
  @ts_usec
end

Class Method Details

.decode_en10mb(bytes) ⇒ Object



115
116
117
# File 'lib/mu/pcap/pkthdr.rb', line 115

def self.decode_en10mb bytes
    return Ethernet.from_bytes(bytes)
end

.decode_linux_sll(bytes) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/mu/pcap/pkthdr.rb', line 119

def self.decode_linux_sll bytes
    Pcap.assert bytes.length >= 16, 'Truncated PCAP packet header: ' +
        "expected at least 16 bytes, got #{bytes.length} bytes"
    packet_type, link_type, addr_len = bytes.unpack('nnn')
    type = bytes[14, 2].unpack('n')[0]
    bytes = bytes[16..-1]
    ethernet = Ethernet.new
    ethernet.type = type
    ethernet.src = '00:01:01:00:00:01'
    ethernet.dst = '00:01:01:00:00:02'
    ethernet.payload = ethernet.payload_raw = bytes 
    begin
        case type
        when Ethernet::ETHERTYPE_IP
            ethernet.payload = IPv4.from_bytes ethernet.payload
        when Ethernet::ETHERTYPE_IP6
            ethernet.payload = IPv6.from_bytes ethernet.payload
        end
    rescue ParseError => e
        Pcap.warning e
    end
    return ethernet
end

.decode_null(endian, bytes) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/mu/pcap/pkthdr.rb', line 80

def self.decode_null endian, bytes
    Pcap.assert bytes.length >= 4, 'Truncated PCAP packet header: ' +
        "expected at least 4 bytes, got #{bytes.length} bytes"
    if endian == BIG_ENDIAN
        format = 'N'
    elsif endian == LITTLE_ENDIAN
        format = 'V'
    end
    family = bytes[0, 4].unpack(format)[0]
    bytes = bytes[4..-1]
    ethernet = Ethernet.new
    ethernet.src = '00:01:01:00:00:01'
    ethernet.dst = '00:01:01:00:00:02'
    ethernet.payload = ethernet.payload_raw = bytes
    if family != Socket::AF_INET and family != Socket::AF_INET6 and
            not BSD_AF_INET6.include?(family)
        raise ParseError, "Unknown PCAP packet header family: #{family}"
    end
    begin
        case family
        when Socket::AF_INET
            ethernet.type = Ethernet::ETHERTYPE_IP
            ethernet.payload = IPv4.from_bytes ethernet.payload
        when Socket::AF_INET6, FREEBSD_AF_INET6, OPENBSD_AF_INET6, DARWIN_AF_INET6
            ethernet.type = Ethernet::ETHERTYPE_IP6
            ethernet.payload = IPv6.from_bytes ethernet.payload
        else
            raise NotImplementedError
        end
    rescue ParseError => e
        Pcap.warning e
    end
    return ethernet
end

.read(io, endian = BIG_ENDIAN) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/mu/pcap/pkthdr.rb', line 23

def self.read io, endian=BIG_ENDIAN
    if endian == BIG_ENDIAN
        format = FMT_NNNN
    elsif endian == LITTLE_ENDIAN
        format = FMT_VVVV
    end
    bytes = io.read 16
    if not bytes 
        raise EOFError, 'Missing PCAP packet header'
    end
    if not bytes.length == 16
        raise ParseError, "Truncated PCAP packet header: expected 16 bytes, got #{bytes.length} bytes"
    end
    ts_sec, ts_usec, caplen, len = bytes.unpack format
    pkt = io.read(caplen)
    if not pkt 
        raise ParseError, 'Missing PCAP packet header packet'
    end
    if not pkt.length == caplen
        raise ParseError, "Truncated PCAP packet header: expected #{pkthdr.caplen} bytes, got #{pkthdr.pkt.length} bytes"
    end
    pkthdr = Pkthdr.new endian, ts_sec, ts_usec, caplen, len, pkt
    return pkthdr
end

Instance Method Details

#==(other) ⇒ Object



143
144
145
146
147
148
149
150
151
# File 'lib/mu/pcap/pkthdr.rb', line 143

def == other
    return self.class == other.class &&
        self.endian   == other.endian &&
        self.ts_sec   == other.ts_sec &&
        self.ts_usec  == other.ts_usec &&
        self.caplen   == other.caplen &&
        self.len      == other.len &&
        self.pkt      == other.pkt
end

#decode!(endian, linktype) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/mu/pcap/pkthdr.rb', line 62

def decode! endian, linktype
    @pkt = case linktype
    when DLT_NULL;      Pkthdr.decode_null endian, @pkt
    when DLT_EN10MB;    Pkthdr.decode_en10mb @pkt
    when DLT_RAW;       raise NotImplementedError
    when DLT_LINUX_SLL; Pkthdr.decode_linux_sll @pkt
    else raise ParseError, "Unknown PCAP linktype: #{linktype}"
    end
end

#write(io) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/mu/pcap/pkthdr.rb', line 48

def write io
    if @pkt.is_a? String
        pkt = @pkt
    else
        string_io = StringIO.new
        @pkt.write string_io
        pkt = string_io.string
    end
    len = pkt.length
    bytes = [@ts_sec, @ts_usec, len, len].pack FMT_NNNN
    io.write bytes
    io.write pkt
end