Class: Capp::Packet
- Inherits:
-
Object
- Object
- Capp::Packet
- Defined in:
- lib/capp/packet.rb
Overview
Capp::Packet provides convenient extraction of data from packets.
Packet objects are automatically created when a packet is read from the opened interface. Unfortunately Capp does not understand every type of packet. If Capp doesn’t understand your packet the layer 3 payload can be retrieved from unknown_layer3_header.
If Capp doesn’t understand your packets you can extract the data by editing capp.c and submitting a patch. See README for the source code location.
To look up IP source and destination names Resolv (from the ruby standard library, require ‘resolv’) to avoid blocking on name lookups in a cross-platform manner.
Defined Under Namespace
Classes: ARPHeader, EthernetHeader, ICMPHeader, IPv4Header, IPv6Header, TCPHeader, UDPHeader, UnknownLayer3Header
Constant Summary collapse
- ADDRESS_CACHE =
:nodoc:
{}
Instance Attribute Summary collapse
-
#arp_header ⇒ Object
readonly
The ARP header if this is an ARP packet.
-
#capture_length ⇒ Object
readonly
Length of packet that was captured.
-
#captured ⇒ Object
readonly
Captured portion of the entire packet including datalink layer.
-
#ethernet_header ⇒ Object
readonly
The Ethernet header if this is an Ethernet packet.
-
#icmp_header ⇒ Object
readonly
ICMP header if this is an ICMP (v4) packet.
-
#ipv4_header ⇒ Object
readonly
IPv4 header if this is an IPv4 packet.
-
#ipv6_header ⇒ Object
readonly
IPv6 header if this is an IPv6 packet.
-
#length ⇒ Object
readonly
Total length of packet including the portion not captured.
-
#protocols ⇒ Object
readonly
Array of protocol names in this packet.
-
#tcp_header ⇒ Object
readonly
TCP header if this is a TCP packet.
-
#timestamp ⇒ Object
readonly
Packet capture timestamp.
-
#udp_header ⇒ Object
readonly
UDP header if this is a UDP packet.
-
#unknown_layer3_header ⇒ Object
readonly
Fake header for unknown layer 3 protocols.
Instance Method Summary collapse
-
#destination(resolver = nil) ⇒ Object
Returns the destination of the packet regardless of protocol.
-
#dump ⇒ Object
Returns the captured bytes with non-printing characters replaced by “.”.
-
#hexdump(offset = 0) ⇒ Object
Dumps the captured packet from
offset
with offsets, hexadecimal output for the bytes and the ASCII content with non-printing characters replaced by “.”. -
#initialize(timestamp, length, capture_length, captured, datalink, headers) ⇒ Packet
constructor
Creates a new packet.
-
#ipv4? ⇒ Boolean
Is this an IPv4 packet?.
-
#ipv6? ⇒ Boolean
Is this an IPv6 packet?.
-
#payload ⇒ Object
The payload of the packet.
-
#payload_offset ⇒ Object
The offset into the captured data where the payload starts.
-
#resolve(address, resolver) ⇒ Object
:nodoc:.
-
#source(resolver = nil) ⇒ Object
Returns the source of the packet regardless of protocol.
-
#tcp? ⇒ Boolean
Is this a TCP packet?.
-
#udp? ⇒ Boolean
Is this a UDP packet?.
Constructor Details
#initialize(timestamp, length, capture_length, captured, datalink, headers) ⇒ Packet
Creates a new packet. Ordinarily this is performed from Capp#loop. The timestamp
is the packet capture timestamp, length
is the total length of the packet, capture_length
is the number of captured bytes from the packet. The datalink
is the type of link the packet was captured on. headers
is a Hash of parsed headers.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'lib/capp/packet.rb', line 217 def initialize , length, capture_length, captured, datalink, headers @capture_length = capture_length @captured = captured @datalink = datalink @length = length @protocols = headers.keys @timestamp = @arp_header = headers[:arp] @ethernet_header = headers[:ethernet] @icmp_header = headers[:icmp] @ipv4_header = headers[:ipv4] @ipv6_header = headers[:ipv6] @tcp_header = headers[:tcp] @udp_header = headers[:udp] @unknown_layer3_header = headers[:unknown_layer3] end |
Instance Attribute Details
#arp_header ⇒ Object (readonly)
The ARP header if this is an ARP packet.
154 155 156 |
# File 'lib/capp/packet.rb', line 154 def arp_header @arp_header end |
#capture_length ⇒ Object (readonly)
Length of packet that was captured
144 145 146 |
# File 'lib/capp/packet.rb', line 144 def capture_length @capture_length end |
#captured ⇒ Object (readonly)
Captured portion of the entire packet including datalink layer.
149 150 151 |
# File 'lib/capp/packet.rb', line 149 def captured @captured end |
#ethernet_header ⇒ Object (readonly)
The Ethernet header if this is an Ethernet packet.
159 160 161 |
# File 'lib/capp/packet.rb', line 159 def ethernet_header @ethernet_header end |
#icmp_header ⇒ Object (readonly)
ICMP header if this is an ICMP (v4) packet.
170 171 172 |
# File 'lib/capp/packet.rb', line 170 def icmp_header @icmp_header end |
#ipv4_header ⇒ Object (readonly)
IPv4 header if this is an IPv4 packet.
175 176 177 |
# File 'lib/capp/packet.rb', line 175 def ipv4_header @ipv4_header end |
#ipv6_header ⇒ Object (readonly)
IPv6 header if this is an IPv6 packet.
180 181 182 |
# File 'lib/capp/packet.rb', line 180 def ipv6_header @ipv6_header end |
#length ⇒ Object (readonly)
Total length of packet including the portion not captured.
185 186 187 |
# File 'lib/capp/packet.rb', line 185 def length @length end |
#protocols ⇒ Object (readonly)
Array of protocol names in this packet. This list is ordered from lowest to highest level.
165 166 167 |
# File 'lib/capp/packet.rb', line 165 def protocols @protocols end |
#tcp_header ⇒ Object (readonly)
TCP header if this is a TCP packet.
190 191 192 |
# File 'lib/capp/packet.rb', line 190 def tcp_header @tcp_header end |
#timestamp ⇒ Object (readonly)
Packet capture timestamp
195 196 197 |
# File 'lib/capp/packet.rb', line 195 def @timestamp end |
#udp_header ⇒ Object (readonly)
UDP header if this is a UDP packet.
200 201 202 |
# File 'lib/capp/packet.rb', line 200 def udp_header @udp_header end |
#unknown_layer3_header ⇒ Object (readonly)
Fake header for unknown layer 3 protocols. The datalink type will indicate the layer 3 protocol. For an Ethernet packet see the ethernet_header for the type, etc. This method only provides the payload offset of the packet content.
208 209 210 |
# File 'lib/capp/packet.rb', line 208 def unknown_layer3_header @unknown_layer3_header end |
Instance Method Details
#destination(resolver = nil) ⇒ Object
Returns the destination of the packet regardless of protocol
If a Resolv-compatible resolver
is given the name will be looked up.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/capp/packet.rb', line 240 def destination resolver = nil destination = if ipv4? then @ipv4_header elsif ipv6? then @ipv6_header else raise NotImplementedError end.destination destination = resolve destination, resolver if tcp? then destination << ".#{@tcp_header.destination_port}" elsif udp? then destination << ".#{@udp_header.destination_port}" end destination end |
#dump ⇒ Object
Returns the captured bytes with non-printing characters replaced by “.”
264 265 266 |
# File 'lib/capp/packet.rb', line 264 def dump @captured.tr "\000-\037\177-\377", "." end |
#hexdump(offset = 0) ⇒ Object
Dumps the captured packet from offset
with offsets, hexadecimal output for the bytes and the ASCII content with non-printing characters replaced by “.”
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/capp/packet.rb', line 273 def hexdump offset = 0 data = @captured[offset, @capture_length] data.scan(/.{,16}/m).map.with_index do |chunk, index| next nil if chunk.empty? hex = chunk.unpack('C*').map { |byte| '%02x' % byte } dump = chunk.tr "\000-\037\177-\377", "." length = hex.length hex.fill ' ', length, 16 - length if length < 16 "\t0x%04x: %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s%s %s" % [ index * 16, *hex, dump ] end.join "\n" end |
#ipv4? ⇒ Boolean
Is this an IPv4 packet?
376 377 378 |
# File 'lib/capp/packet.rb', line 376 def ipv4? @ipv4_header end |
#ipv6? ⇒ Boolean
Is this an IPv6 packet?
383 384 385 |
# File 'lib/capp/packet.rb', line 383 def ipv6? @ipv6_header end |
#payload ⇒ Object
The payload of the packet.
For example, for a UDP packet captured from an Ethernet interface this is payload after the Ethernet, IP and UDP headers
296 297 298 |
# File 'lib/capp/packet.rb', line 296 def payload @captured[payload_offset, @capture_length] end |
#payload_offset ⇒ Object
The offset into the captured data where the payload starts.
Note that this method does not work properly for IPv6 packets with options set, but I have yet to encounter such an example in the wild.
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/capp/packet.rb', line 306 def payload_offset offset = case @datalink when Capp::DLT_NULL then 4 when Capp::DLT_EN10MB then 14 end case when ipv4? then offset += @ipv4_header.ihl * 4 when ipv6? then offset += 40 else raise NotImplementedError end case when tcp? then offset += @tcp_header.offset * 4 when udp? then offset += 8 else raise NotImplementedError end offset end |
#resolve(address, resolver) ⇒ Object
:nodoc:
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/capp/packet.rb', line 330 def resolve address, resolver # :nodoc: return address.dup unless resolver if name = ADDRESS_CACHE[address] then return name.dup end name = resolver.getname address ADDRESS_CACHE[address] = name name.dup rescue Resolv::ResolvError ADDRESS_CACHE[address] = address address.dup end |
#source(resolver = nil) ⇒ Object
Returns the source of the packet regardless of protocol.
If a Resolv-compatible resolver
is given the name will be looked up.
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'lib/capp/packet.rb', line 352 def source resolver = nil source = if ipv4? then @ipv4_header elsif ipv6? then @ipv6_header else raise NotImplementedError end.source.dup source = resolve source, resolver if tcp? then source << ".#{@tcp_header.source_port}" elsif udp? then source << ".#{@udp_header.source_port}" end source end |
#tcp? ⇒ Boolean
Is this a TCP packet?
390 391 392 |
# File 'lib/capp/packet.rb', line 390 def tcp? @tcp_header end |
#udp? ⇒ Boolean
Is this a UDP packet?
397 398 399 |
# File 'lib/capp/packet.rb', line 397 def udp? @udp_header end |