packet_via_dmem 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/README.md +15 -2
- data/lib/packet_via_dmem.rb +8 -67
- data/lib/packet_via_dmem/cli.rb +14 -5
- data/lib/packet_via_dmem/packet.rb +54 -0
- data/lib/packet_via_dmem/packets.rb +33 -0
- data/lib/packet_via_dmem/received.rb +38 -0
- data/lib/packet_via_dmem/sent.rb +30 -0
- data/packet_via_dmem.gemspec +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef2cad0361ca93db4bedc5a4ba817c091bb7caae
|
4
|
+
data.tar.gz: 3a15a48484054db79bba1014ec008d5147e9427c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d54500d03397a67b058c9cf94cbf5b74efa81800a2a87eb2231691a223509a5584178470c603a972d49d4c630bf65818cc6f098ab3bc41d79060eca75778c66
|
7
|
+
data.tar.gz: a06ffee647a7f386a716c9bddf9bfa10dd796d691d7f02e1446d7bba2f5046f2bfcf6c921215eaf690de68a964ac78addddf9a54e7ba76217239ee599cc43d95
|
data/README.md
CHANGED
@@ -58,15 +58,22 @@ To capture say packets with IP address 10.11.12.13
|
|
58
58
|
% ./bin/packet-via-dmem --help
|
59
59
|
usage: ./bin/packet-via-dmem [options]
|
60
60
|
-d, --debug turn on debugging
|
61
|
+
--headers print headers to stderr
|
62
|
+
-o, --original print original frames
|
61
63
|
-r, --received pop BYTES from received frames, default 6
|
62
64
|
-s, --sent pop BYTES from senti frames, default is not to show sent frames
|
63
65
|
-h, --help
|
64
|
-
%
|
65
66
|
|
66
67
|
## Library
|
67
68
|
require 'packet_via_dmem'
|
68
69
|
dmem = PacketViaDMEM.new
|
69
|
-
|
70
|
+
packets = dmem.parse File.read(ARGF[0])
|
71
|
+
packets.each do |capture|
|
72
|
+
p capture.type
|
73
|
+
p capture.packet
|
74
|
+
p capture.header
|
75
|
+
p capture.original
|
76
|
+
end
|
70
77
|
|
71
78
|
|
72
79
|
## Header format
|
@@ -85,6 +92,12 @@ To capture say packets with IP address 10.11.12.13
|
|
85
92
|
|
86
93
|
* Sixth byte is perhaps source NPU? If it is zero, we get what seems to be trash (internal stuff)
|
87
94
|
|
95
|
+
* value of fift+sixth seems to sometime indicate special cases
|
96
|
+
* 0x1fff - Packet missing everything before IPv4 TTL, yet has some extra. I saw BGP from control-plane with this and also TCP/SMB2 with Seq1, it was transit, but perhaps it was via ARP resolve/punt and thus coming from control-plane?
|
97
|
+
* 0x2000 - BFD frames from control-plane, missing L2
|
98
|
+
* 0x4220 - Was traffic for AE/802.1AX, no L2 included, but something extra aadded
|
99
|
+
* 0x8000 - I need to pop 14 bytes extra
|
100
|
+
|
88
101
|
* 00 (22) (33) (44) \<src\> (66)
|
89
102
|
* 10 (22) (33) (44) \<si\> \<ze\> \<src\> (66)
|
90
103
|
|
data/lib/packet_via_dmem.rb
CHANGED
@@ -16,92 +16,31 @@ class PacketViaDMEM
|
|
16
16
|
class Error < StandardError; end
|
17
17
|
|
18
18
|
def initialize opts={}
|
19
|
-
@received
|
20
|
-
@sent
|
19
|
+
@received = opts.delete :received
|
20
|
+
@sent = opts.delete :sent
|
21
21
|
@received ||= HEADER_SIZE[:received]
|
22
|
-
@sc
|
22
|
+
@sc = StringScanner.new ''
|
23
23
|
end
|
24
24
|
|
25
25
|
def parse str
|
26
|
-
packets =
|
27
|
-
headers = []
|
26
|
+
packets = Packets.new
|
28
27
|
@sc.string = str
|
29
28
|
while @sc.scan_until PACKET
|
30
29
|
match = @sc.matched.split(/\s+/)
|
31
30
|
type = match.first.downcase.to_sym
|
32
|
-
next if type == :received and (not @received or @received < 1)
|
33
|
-
next if type == :sent and (not @sent or @sent < 1)
|
34
31
|
@sc.scan_until(/\n/) if type == :received
|
35
32
|
pkt = ''
|
36
33
|
while @sc.match?(/^0x/)
|
37
34
|
pkt << @sc.scan_until(/\n/).strip
|
38
35
|
end
|
39
36
|
pkt = parse_packet pkt
|
40
|
-
|
41
|
-
header = pkt[0..pop-1]
|
42
|
-
pkt = pkt[pop..-1]
|
43
|
-
if pkt
|
44
|
-
packets << '000000 ' + [push, pkt].flatten.join(' ')
|
45
|
-
headers << header.join(' ')
|
46
|
-
end
|
37
|
+
packets.add pkt, type
|
47
38
|
end
|
48
|
-
|
39
|
+
packets
|
49
40
|
end
|
50
41
|
|
51
42
|
private
|
52
43
|
|
53
|
-
def get_pop_push type, pkt
|
54
|
-
if type == :sent
|
55
|
-
get_pop_push_sent pkt
|
56
|
-
else
|
57
|
-
get_pop_push_received pkt
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def get_pop_push_sent pkt
|
62
|
-
pop, push = nil, []
|
63
|
-
case pkt.first.to_i(16)
|
64
|
-
when 0x00 # we're sending to fabric
|
65
|
-
# we may send MAC to fabric,byte 6, 7, 9, 11, 21?
|
66
|
-
if pkt[5].to_i(16) == 0xf0 # we don't send MAC to fabric
|
67
|
-
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_mpls]
|
68
|
-
pop = 24
|
69
|
-
else # we send MAC to fabric
|
70
|
-
pop = 33
|
71
|
-
end
|
72
|
-
when 0x08 then pop = 13
|
73
|
-
else pop = @sent
|
74
|
-
end
|
75
|
-
[pop, push]
|
76
|
-
end
|
77
|
-
|
78
|
-
def get_pop_push_received pkt
|
79
|
-
pop, push = 6, []
|
80
|
-
offset = 0
|
81
|
-
case pkt.first.to_i(16)
|
82
|
-
when 0x00 then offset = 0 #1,2,3,4,5,6
|
83
|
-
when 0x10 then offset = 2 #1,2,3,4,7,8,5,6
|
84
|
-
else pop = @received
|
85
|
-
end
|
86
|
-
pop += offset
|
87
|
-
case pkt[4+offset..5+offset].join.to_i(16)
|
88
|
-
when 0x8000 then pop+=14
|
89
|
-
when 0x4220 # ae/802.1AX is special, no L2 received, but something extra
|
90
|
-
pop+=18
|
91
|
-
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4]
|
92
|
-
when 0x2000 # these were BFD packets from control-plane
|
93
|
-
pop+=5
|
94
|
-
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4]
|
95
|
-
# some BGP packets like this
|
96
|
-
# also SMB2 TCP Seq1 (maybe post ARP from control-plane?)
|
97
|
-
# they are misssing all of ipv4 headers before TTL
|
98
|
-
when 0x1f00
|
99
|
-
pop+=7
|
100
|
-
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4] + FAKE[:ipv4]
|
101
|
-
end
|
102
|
-
[pop, push]
|
103
|
-
end
|
104
|
-
|
105
44
|
def parse_packet pkt
|
106
45
|
pkt = pkt.gsub(/0x/, '')
|
107
46
|
pkt = pkt.gsub(/\s+/, '')
|
@@ -109,3 +48,5 @@ class PacketViaDMEM
|
|
109
48
|
pkt
|
110
49
|
end
|
111
50
|
end
|
51
|
+
|
52
|
+
require_relative 'packet_via_dmem/packets'
|
data/lib/packet_via_dmem/cli.rb
CHANGED
@@ -20,17 +20,26 @@ class PacketViaDMEM
|
|
20
20
|
rescue
|
21
21
|
raise InvalidFile, "unable to read #{file}"
|
22
22
|
end
|
23
|
-
packets
|
24
|
-
|
25
|
-
|
23
|
+
packets = PacketViaDMEM.new(:received=>@opts[:received], :sent=>@opts[:sent]).parse file
|
24
|
+
count = 0
|
25
|
+
packets.each do |pkt|
|
26
|
+
next if pkt.type == :received and (not @opts[:received] or @opts[:received] < 1)
|
27
|
+
next if pkt.type == :sent and (not @opts[:sent] or @opts[:sent] < 1)
|
28
|
+
packet = @opts.original? ? pkt.pretty_original : pkt.pretty_packet
|
29
|
+
puts '### Packet %d ###' % [count+=1]
|
30
|
+
puts packet
|
31
|
+
$stderr.puts pkt.header.join(' ') if @opts.headers?
|
32
|
+
puts
|
33
|
+
end
|
26
34
|
end
|
27
35
|
|
28
36
|
private
|
29
37
|
|
30
38
|
def opts_parse
|
31
39
|
Slop.parse do |o|
|
32
|
-
o.bool '-d', '--debug',
|
33
|
-
o.bool
|
40
|
+
o.bool '-d', '--debug', 'turn on debugging'
|
41
|
+
o.bool '--headers', 'print headers to stderr'
|
42
|
+
o.bool '-o', '--original', 'print original frames'
|
34
43
|
o.int '-r', '--received', "pop BYTES from received frames, default #{PacketViaDMEM::HEADER_SIZE[:received]}", :default=>PacketViaDMEM::HEADER_SIZE[:received]
|
35
44
|
o.int '-s', '--sent', "pop BYTES from senti frames, default is not to show sent frames"
|
36
45
|
o.on '-h', '--help' do puts o; exit; end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class PacketViaDMEM
|
2
|
+
|
3
|
+
class Packet
|
4
|
+
class NoPayload < Error; end
|
5
|
+
attr_reader :type, :packet, :header, :original
|
6
|
+
|
7
|
+
def pop bytes
|
8
|
+
@original[bytes..-1]
|
9
|
+
end
|
10
|
+
|
11
|
+
def header_and_packet packet, pop_bytes, push_bytes
|
12
|
+
header = packet[0..pop_bytes-1]
|
13
|
+
payload = packet[pop_bytes..-1]
|
14
|
+
raise NoPayload, "no payload for #{packet}" unless payload
|
15
|
+
payload = push_bytes + payload
|
16
|
+
[header, payload]
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
pretty_packet
|
21
|
+
end
|
22
|
+
|
23
|
+
def pretty_packet
|
24
|
+
pretty @packet
|
25
|
+
end
|
26
|
+
|
27
|
+
def pretty_original
|
28
|
+
pretty @original
|
29
|
+
end
|
30
|
+
|
31
|
+
def pretty packet
|
32
|
+
offset = -16
|
33
|
+
out = ''
|
34
|
+
packet.each_slice(16) do |slice|
|
35
|
+
hex, str = [], []
|
36
|
+
slice.each_slice(8) do |subslice|
|
37
|
+
hex << subslice
|
38
|
+
str << subslice.inject(' ') do |r, s|
|
39
|
+
int = s.to_i(16)
|
40
|
+
r + ((int > 31 and int < 127) ? int.chr : '.')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
hex << [] if not hex[1]
|
44
|
+
hex.each do |h|
|
45
|
+
(8-h.size).times { h << ' ' }
|
46
|
+
end
|
47
|
+
out << "%04x %s %s %s \n" % [offset+=16, hex[0].join(' '), hex[1].to_a.join(' '), str.join(' ')]
|
48
|
+
end
|
49
|
+
out
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'packet'
|
2
|
+
require_relative 'received'
|
3
|
+
require_relative 'sent'
|
4
|
+
|
5
|
+
class PacketViaDMEM
|
6
|
+
class Packets
|
7
|
+
include Enumerable
|
8
|
+
class InvalidType < Error; end
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@packets = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def add packet, type
|
15
|
+
packet = case type
|
16
|
+
when :received then Received.new packet
|
17
|
+
when :sent then Sent.new packet
|
18
|
+
else raise InvalidType, "#{type} not valid packet type"
|
19
|
+
end
|
20
|
+
@packets << packet
|
21
|
+
rescue Packet::NoPayload
|
22
|
+
end
|
23
|
+
|
24
|
+
def each &block
|
25
|
+
@packets.each { |packet| block.call packet }
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@packets.size
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class PacketViaDMEM
|
2
|
+
class Received < Packet
|
3
|
+
|
4
|
+
def initialize packet
|
5
|
+
@type = :received
|
6
|
+
@original = packet
|
7
|
+
@header, @packet = parse_packet packet
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def parse_packet pkt
|
13
|
+
pop, push = 6, []
|
14
|
+
offset = 0
|
15
|
+
case pkt.first.to_i(16)
|
16
|
+
when 0x00 then offset = 0 #1,2,3,4,5,6
|
17
|
+
when 0x10 then offset = 2 #1,2,3,4,7,8,5,6
|
18
|
+
end
|
19
|
+
pop += offset
|
20
|
+
case pkt[4+offset..5+offset].join.to_i(16)
|
21
|
+
when 0x8000 then pop+=14
|
22
|
+
when 0x4220 # ae/802.1AX is special, no L2 received, but something extra
|
23
|
+
pop+=18
|
24
|
+
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4]
|
25
|
+
when 0x2000 # these were BFD packets from control-plane
|
26
|
+
pop+=5
|
27
|
+
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4]
|
28
|
+
# some BGP packets like this
|
29
|
+
# also SMB2 TCP Seq1 (maybe post ARP from control-plane?)
|
30
|
+
# they are misssing all of ipv4 headers before TTL
|
31
|
+
when 0x1f00
|
32
|
+
pop+=7
|
33
|
+
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_ipv4] + FAKE[:ipv4]
|
34
|
+
end
|
35
|
+
header_and_packet pkt, pop, push
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class PacketViaDMEM
|
2
|
+
class Sent < Packet
|
3
|
+
|
4
|
+
def initialize packet
|
5
|
+
@type = :sent
|
6
|
+
@original = packet
|
7
|
+
@header, @packet = parse_packet packet
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def parse_packet pkt
|
13
|
+
pop, push = nil, []
|
14
|
+
case pkt.first.to_i(16)
|
15
|
+
when 0x00 # we're sending to fabric
|
16
|
+
# we may send MAC to fabric,byte 6, 7, 9, 11, 21?
|
17
|
+
if pkt[5].to_i(16) == 0xf0 # we don't send MAC to fabric
|
18
|
+
push = FAKE[:dmac] + FAKE[:smac] + FAKE[:etype_mpls]
|
19
|
+
pop = 24
|
20
|
+
else # we send MAC to fabric
|
21
|
+
pop = 33
|
22
|
+
end
|
23
|
+
when 0x08 then pop = 13
|
24
|
+
else pop = @sent
|
25
|
+
end
|
26
|
+
header_and_packet pkt, pop, push
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/packet_via_dmem.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packet_via_dmem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Saku Ytti
|
@@ -40,6 +40,10 @@ files:
|
|
40
40
|
- bin/packet-via-dmem
|
41
41
|
- lib/packet_via_dmem.rb
|
42
42
|
- lib/packet_via_dmem/cli.rb
|
43
|
+
- lib/packet_via_dmem/packet.rb
|
44
|
+
- lib/packet_via_dmem/packets.rb
|
45
|
+
- lib/packet_via_dmem/received.rb
|
46
|
+
- lib/packet_via_dmem/sent.rb
|
43
47
|
- packet_via_dmem.gemspec
|
44
48
|
homepage: http://github.com/ytti/packet_via_dmem
|
45
49
|
licenses:
|