packet_via_dmem 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: