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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b47f13f61222ca447bf34212f1de3d08670bceaa
4
- data.tar.gz: d6d328de5f66ab0375feded9d1c98b591e93a76c
3
+ metadata.gz: ef2cad0361ca93db4bedc5a4ba817c091bb7caae
4
+ data.tar.gz: 3a15a48484054db79bba1014ec008d5147e9427c
5
5
  SHA512:
6
- metadata.gz: adcfe3a75112cdecbd2ae523708f3f69dfab4a40d3835364d31d68bafb44d5a9df3fe9ca30041d45d5f8c8ba914159031837b404705db8824a872374383cb9d4
7
- data.tar.gz: 9da8b106d908c403fbabb707a2f9217e3f6d45725998f8017aaec6710a037f1dc9ebbe6ae3d4efc083159fb0f8f9008b10cb2795d2dbdf80cc6a5f6bd01cb105
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
- puts dmem.parse File.read(ARGF[0])
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
 
@@ -16,92 +16,31 @@ class PacketViaDMEM
16
16
  class Error < StandardError; end
17
17
 
18
18
  def initialize opts={}
19
- @received = opts.delete :received
20
- @sent = opts.delete :sent
19
+ @received = opts.delete :received
20
+ @sent = opts.delete :sent
21
21
  @received ||= HEADER_SIZE[:received]
22
- @sc = StringScanner.new ''
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
- pop, push = get_pop_push(type, pkt)
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
- [packets, headers]
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'
@@ -20,17 +20,26 @@ class PacketViaDMEM
20
20
  rescue
21
21
  raise InvalidFile, "unable to read #{file}"
22
22
  end
23
- packets, headers = PacketViaDMEM.new(:received=>@opts[:received], :sent=>@opts[:sent]).parse file
24
- $stderr.puts headers if @opts.headers?
25
- puts packets
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', 'turn on debugging'
33
- o.bool '--headers', 'print headers to stderr'
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'packet_via_dmem'
3
- s.version = '0.0.3'
3
+ s.version = '0.0.4'
4
4
  s.licenses = %w( Apache-2.0 )
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = [ 'Saku Ytti' ]
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.3
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: