simple_capture 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d8ab97c1d77026f80dc16f0e798a730078d52f9323b9038769c5d60c2385a1a3
4
+ data.tar.gz: 6fc14246c88e07be902c1dae27ec8ac268f6db4d6d144b414f5902f0ff0d1170
5
+ SHA512:
6
+ metadata.gz: c600259cbe23284c1ba1e27eac9430da64c841c4c0879b850ca8f7c092df0e711aec3335dc3fd827ed206c5df1b16b94c8bb9994a571ee9f32b0c669bec69ebf
7
+ data.tar.gz: 94b33abf943b6a48c13e23e1cc4423171427f15e001e384c8d279903429c3bb70ae03cb48b5ba2ecac63ac84fd0ffdf0058a4f55dedd3af06faf1d4e6a259bbf
data/.gitignore ADDED
@@ -0,0 +1,57 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ # Used by dotenv library to load environment variables.
14
+ # .env
15
+
16
+ # Ignore Byebug command history file.
17
+ .byebug_history
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
+ # .rubocop-https?--*
57
+ simple_capture.code-workspace
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Akira kure
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # SimpleCapture
2
+
3
+ Packet capture tool made only with Ruby
4
+
5
+ ## Installation
6
+
7
+ ## Usage
8
+
9
+
10
+ ## Development
11
+
12
+
13
+ ## Contributing
14
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "simple_capture"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ require_relative "simple_capture/version"
2
+ require_relative "simple_capture/capture"
3
+ require_relative "simple_capture/packet"
4
+ require_relative "simple_capture/string"
5
+ require_relative "simple_capture/recv_message"
6
+ require_relative "simple_capture/header/ehter_header"
7
+ require_relative "simple_capture/header/ipv4_header"
8
+ require_relative "simple_capture/header/icmp_header"
9
+
10
+ module SimpleCapture
11
+ end
@@ -0,0 +1,92 @@
1
+ require "socket"
2
+
3
+ module SimpleCapture
4
+ class Capture
5
+ SOL_PACKET = 0x0107 # bits/socket.h
6
+ IFINDEX_SIZE = 0x0004 # sizeof(ifreq.ifr_ifindex) on 64bit
7
+ IFREQ_SIZE = 0x0028 # sizeof(ifreq) on 64bit
8
+ SIOCGIFINDEX = 0x8933 # bits/ioctls.h
9
+ PACKET_MR_PROMISC = 0x0001 # netpacket/packet.h
10
+ PACKET_MREQ_SIZE = 0x0010 # sizeof(packet_mreq) on 64bit
11
+ PACKET_ADD_MEMBERSHIP = 0x0001 # netpacket/packet.h
12
+ ETH_P_ALL = 768 # htons(ETH_P_ALL), linux/if_ether.h
13
+
14
+ # @param [String] interface_name
15
+ def initialize(interface_name)
16
+ @interface_name = interface_name
17
+ end
18
+
19
+ # Run Capture
20
+ def run
21
+ socket = generate_socket(@interface_name)
22
+ cap_loop(socket)
23
+ end
24
+
25
+ private
26
+
27
+ def cap_loop(socket)
28
+ while true
29
+ mesg, _ = socket.recvfrom(1500)
30
+ packet = RecvMessageHandler.new(mesg).to_packet
31
+ packet.dump
32
+ end
33
+ end
34
+
35
+ def bind_if(socket, interface_name)
36
+ index_str = mr_ifindex(interface_name)
37
+
38
+ eth_p_all_hbo = [ ETH_P_ALL ].pack('S').unpack('S>').first
39
+ sll = [ Socket::AF_PACKET, eth_p_all_hbo, index_str ].pack('SS>a16')
40
+ socket.bind(sll)
41
+ end
42
+
43
+ # @return [Integer]
44
+ def if_name_to_index(if_name)
45
+ Socket.getifaddrs.find do |ifaddr|
46
+ ifaddr.name == if_name
47
+ end&.ifindex
48
+ end
49
+
50
+ def generate_socket(interface_name)
51
+ socket = Socket.new(Socket::AF_PACKET, Socket::SOCK_RAW, ETH_P_ALL)
52
+ bind_if(socket, interface_name)
53
+ socket_promiscuous(socket, interface_name)
54
+ socket
55
+ end
56
+
57
+ def mr_ifindex(if_name)
58
+ [[if_name_to_index(if_name)].pack("c")].pack("a4")
59
+ end
60
+
61
+ def mr_type
62
+ [PACKET_MR_PROMISC].pack("S")
63
+ end
64
+
65
+ def mr_alen
66
+ [0].pack("S")
67
+ end
68
+
69
+ def mr_address
70
+ [0].pack("C")*8
71
+ end
72
+
73
+ #
74
+ # https://linuxjm.osdn.jp/html/LDP_man-pages/man7/packet.7.html
75
+ # struct packet_mreq {
76
+ # int mr_ifindex; 4Byte
77
+ # unsigned short mr_type; 2Byte
78
+ # unsigned short mr_alen; 2Byte
79
+ # unsigned char mr_address[8]; 1Byte * 8
80
+ #};
81
+ #
82
+ # @param [String]
83
+ # @return [String]
84
+ def mreq(interface)
85
+ mr_ifindex(interface) + mr_type + mr_alen + mr_address
86
+ end
87
+
88
+ def socket_promiscuous(socket, interface_name)
89
+ socket.setsockopt(SOL_PACKET, PACKET_ADD_MEMBERSHIP, mreq(interface_name))
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,70 @@
1
+ module SimpleCapture
2
+ class EtherHeader
3
+ IPv4 = 0x0800
4
+
5
+ attr_reader :dst_mac_address, :src_mac_address, :type
6
+
7
+ # @param [Array<Integer>] [10, 46, ...]
8
+ def initialize(bytes: nil)
9
+ # support 14Byte EhterHeader only now.
10
+ raise ArgumentError, "bytes's size must be 10Byte" unless bytes.size == 14
11
+
12
+ convert_bytes_to_headers(bytes) unless bytes.nil?
13
+ end
14
+
15
+ # @return [Boolean]
16
+ def upper_layer_protocol_ipv4?
17
+ type_hex = type.map { |byte| byte.to_s(16).rjust(2, "0") }
18
+ type_hex.join.to_i(16) == IPv4
19
+ end
20
+
21
+ # Print Header Info
22
+ def dump
23
+ puts "■ether header------------------------------".red
24
+ print_dst_mac_address
25
+ print_src_mac_address
26
+ print_type
27
+ end
28
+
29
+ private
30
+
31
+ def convert_bytes_to_headers(bytes)
32
+ @dst_mac_address = bytes[0..5]
33
+ @src_mac_address = bytes[6..11]
34
+ @type = bytes[12..13]
35
+ end
36
+
37
+ def print_dst_mac_address
38
+ hex_dst_mac_address = dst_mac_address.map { |byte| byte.to_s(16) }
39
+
40
+ puts "dst_mac_address = #{hex_dst_mac_address[0]}:\
41
+ #{hex_dst_mac_address[1]}:\
42
+ #{hex_dst_mac_address[2]}:\
43
+ #{hex_dst_mac_address[3]}:\
44
+ #{hex_dst_mac_address[4]}:\
45
+ #{hex_dst_mac_address[5]}"
46
+ end
47
+
48
+ def print_src_mac_address
49
+ hex_src_mac_address = src_mac_address.map { |byte| byte.to_s(16) }
50
+
51
+ puts "src_mac_address = #{hex_src_mac_address[0]}:\
52
+ #{hex_src_mac_address[1]}:\
53
+ #{hex_src_mac_address[2]}:\
54
+ #{hex_src_mac_address[3]}:\
55
+ #{hex_src_mac_address[4]}:\
56
+ #{hex_src_mac_address[5]}"
57
+ end
58
+
59
+ def print_type
60
+ type_hex = type.map { |byte| byte.to_s(16).rjust(2, "0") }
61
+ type_hex_int = type_hex.join.to_i(16) # ["08", "00"]
62
+ protocol_display = if type_hex_int == IPv4
63
+ "IPv4"
64
+ else
65
+ "[UnKnown Protocol]"
66
+ end
67
+ puts "protocol = #{protocol_display}"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,76 @@
1
+ module SimpleCapture
2
+ class ICMPHeader
3
+ attr_reader :type, :code, :checksum, :id, :seq_number, :data
4
+
5
+ # @param [Array<Integer>] [10, 46, ...]
6
+ def initialize(bytes: nil)
7
+ convert_bytes_to_header(bytes) unless bytes.nil?
8
+ end
9
+
10
+ def dump
11
+ puts "■icmp--------------------------------------".blue
12
+ print_checksum
13
+ print_code
14
+ print_type
15
+ print_id
16
+ print_seqnumber
17
+ print_data
18
+ end
19
+
20
+ private
21
+
22
+ def print_checksum
23
+ puts "checksum = 0x#{combine_2bits_in_hex(checksum).to_s(16)}"
24
+ end
25
+
26
+ def print_code
27
+ puts "code = #{code}"
28
+ end
29
+
30
+ def print_data
31
+ puts "data = "
32
+ data.each_slice(10) do |data10|
33
+ data10.each { |data_| print "0x#{data_.to_s(16)} " }
34
+ puts "\n"
35
+ end
36
+ end
37
+
38
+ def print_id
39
+ if id
40
+ puts "id = 0x#{combine_2bits_in_hex(id).to_s(16)}"
41
+ end
42
+ end
43
+
44
+ def print_seqnumber
45
+ if seq_number
46
+ puts "seq_number = 0x#{combine_2bits_in_hex(seq_number).to_s(16)}"
47
+ end
48
+ end
49
+
50
+ def print_type
51
+ puts "type = #{type}"
52
+ end
53
+
54
+ # Combine 2 bits of numbers in hexadecimal
55
+ #
56
+ # @param [Array<Integer>] [0d80, 0d30]
57
+ # @return [Integer] 0x501e... 0d80 -> 0x50, 0d30 -> 0x1e
58
+ def combine_2bits_in_hex(bytes)
59
+ (bytes[0].to_s(16) + bytes[1].to_s(16)).to_i(16)
60
+ end
61
+
62
+ def convert_bytes_to_header(bytes)
63
+ @type = bytes[0]
64
+ @code = bytes[1]
65
+ @checksum = bytes[2..3]
66
+
67
+ if @type == 0 || 8
68
+ @id = bytes[4..5]
69
+ @seq_number = bytes[6..7]
70
+ @data = bytes[8..(bytes.size-1)]
71
+ else
72
+ @data = bytes[4..(bytes.size-1)]
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,117 @@
1
+ module SimpleCapture
2
+ class IPv4Header
3
+ ICMP = 1
4
+
5
+ attr_reader :version, :ihl, :type_of_service, :length, :id, :flags, :offset, :ttl,
6
+ :checksum, :src_addr, :dst_addr, :protocol
7
+
8
+ # @param [Array<Integer>] 各バイトの数値の配列、[10, 46, ...]
9
+ def initialize(bytes: nil)
10
+ # support 20Byte IPHeader only now.
11
+ raise ArgumentError, "bytes's size must be 20Byte" unless bytes.size == 20
12
+
13
+ convert_bytes_to_header(bytes) unless bytes.nil?
14
+ end
15
+
16
+ def dump
17
+ puts "■ipv4--------------------------------------".yellow
18
+ print_version
19
+ print_ihl
20
+ print_type_of_service
21
+ print_length
22
+ print_id
23
+ print_flags
24
+ print_offset
25
+ print_ttl
26
+ print_protocol
27
+ print_checksum
28
+ print_src_addr
29
+ print_dst_addr
30
+ end
31
+
32
+ def upper_layer_protocol_icmp?
33
+ protocol == ICMP
34
+ end
35
+
36
+ private
37
+
38
+ # Combine 2 bits of numbers in hexadecimal
39
+ #
40
+ # @param [Array<Integer>] [0d80, 0d30]
41
+ # @return [Integer] 0x501e... 0d80 -> 0x50, 0d30 -> 0x1e
42
+ def combine_2bits_in_hex(bytes)
43
+ bytes_hex = bytes.map { |byte| byte.to_s(16).rjust(2, "0") }
44
+ bytes_hex.join.to_i(16)
45
+
46
+ # (bytes[0].to_s(16) + bytes[1].to_s(16)).to_i(16)
47
+ end
48
+
49
+ def convert_bytes_to_header(bytes)
50
+ @version = bytes[0][4, 4]
51
+ @ihl = bytes[0][0, 4]
52
+ @type_of_service = bytes[1]
53
+ @length = bytes[2..3]
54
+ @id = bytes[4..5]
55
+ bytes67 = combine_2bits_in_hex(bytes[6..7])
56
+ @flags = bytes67[0, 3]
57
+ @offset = bytes67[3, 13]
58
+ @ttl = bytes[8]
59
+ @protocol = bytes[9]
60
+ @checksum = bytes[10..11]
61
+ @src_addr = bytes[12..15]
62
+ @dst_addr = bytes[16..19]
63
+ end
64
+
65
+ def print_checksum
66
+ puts "checksum = 0x#{combine_2bits_in_hex(checksum).to_s(16)}"
67
+ end
68
+
69
+ def print_dst_addr
70
+ puts "dst_addr = #{dst_addr}"
71
+ end
72
+
73
+ def print_flags
74
+ puts "flags = #{flags}"
75
+ end
76
+
77
+ def print_id
78
+ puts "id = 0x#{combine_2bits_in_hex(id).to_s(16)}\n"
79
+ end
80
+
81
+ def print_ihl
82
+ puts "ihl = #{ihl}"
83
+ end
84
+
85
+ def print_length
86
+ puts "length = 0x#{combine_2bits_in_hex(length).to_s(16)}"
87
+ end
88
+
89
+ def print_offset
90
+ puts "offset = #{offset}"
91
+ end
92
+
93
+ def print_protocol
94
+ if protocol == ICMP
95
+ puts "protocol = ICMP"
96
+ else
97
+ puts "protocol = [UnKnown Protocol]"
98
+ end
99
+ end
100
+
101
+ def print_src_addr
102
+ puts "src_addr = #{src_addr}"
103
+ end
104
+
105
+ def print_type_of_service
106
+ puts "type_of_service = #{type_of_service}"
107
+ end
108
+
109
+ def print_ttl
110
+ puts "ttl = #{ttl}"
111
+ end
112
+
113
+ def print_version
114
+ puts "version = #{version}"
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,18 @@
1
+ module SimpleCapture
2
+ class Packet
3
+
4
+ # @param [Array] headers
5
+ def initialize(headers)
6
+ @headers = headers
7
+ end
8
+
9
+ def dump
10
+ puts "\n■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■".green
11
+ puts "Display Packet".green
12
+ puts "■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■".green
13
+ @headers.each do |header|
14
+ header.dump
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,25 @@
1
+ module SimpleCapture
2
+ class RecvMessageHandler
3
+ def initialize(mesg)
4
+ @mesg = mesg
5
+ end
6
+
7
+ # @return [Packet]
8
+ def to_packet
9
+ headers = []
10
+ ether = SimpleCapture::EtherHeader.new(bytes: @mesg.bytes[0..13])
11
+ headers.push(ether)
12
+
13
+ if ether.upper_layer_protocol_ipv4?
14
+ ip = SimpleCapture::IPv4Header.new(bytes: @mesg.bytes[14..33])
15
+ headers.push(ip)
16
+ if ip.upper_layer_protocol_icmp?
17
+ icmp = SimpleCapture::ICMPHeader.new(bytes: @mesg.bytes[34..(@mesg.bytes.size-1)])
18
+ headers.push(icmp)
19
+ end
20
+ end
21
+ SimpleCapture::Packet.new(headers)
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,25 @@
1
+ class String
2
+ def colorize(color_code)
3
+ "\e[#{color_code}m#{self}\e[0m"
4
+ end
5
+
6
+ def red
7
+ colorize(31)
8
+ end
9
+
10
+ def green
11
+ colorize(32)
12
+ end
13
+
14
+ def yellow
15
+ colorize(33)
16
+ end
17
+
18
+ def blue
19
+ colorize(34)
20
+ end
21
+
22
+ def pink
23
+ colorize(35)
24
+ end
25
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleCapture
2
+ VERSION = "0.1.0"
3
+ end
data/sample_run.rb ADDED
@@ -0,0 +1,4 @@
1
+ require_relative "lib/simple_capture"
2
+
3
+ cap = SimpleCapture::Capture.new("eth1")
4
+ cap.run
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/simple_capture/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "simple_capture"
7
+ spec.version = SimpleCapture::VERSION
8
+ spec.authors = ["Akira Kure"]
9
+ spec.email = ["kuredev@gmail.com"]
10
+
11
+ spec.summary = "Packet capture tool made only with Ruby."
12
+ spec.description = "Packet capture tool made only with Ruby."
13
+ spec.homepage = "https://github.com/kuredev/simple_capture"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = "https://github.com/kuredev/simple_capture"
20
+ spec.metadata["changelog_uri"] = "https://github.com/kuredev/simple_capture"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ # Uncomment to register a new dependency of your gem
32
+ # spec.add_dependency "example-gem", "~> 1.0"
33
+
34
+ # For more information and examples about making a new gem, checkout our
35
+ # guide at: https://bundler.io/guides/creating_gem.html
36
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_capture
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Akira Kure
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-02-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Packet capture tool made only with Ruby.
14
+ email:
15
+ - kuredev@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".ruby-version"
22
+ - LICENSE
23
+ - README.md
24
+ - Rakefile
25
+ - bin/console
26
+ - bin/setup
27
+ - lib/simple_capture.rb
28
+ - lib/simple_capture/capture.rb
29
+ - lib/simple_capture/header/ehter_header.rb
30
+ - lib/simple_capture/header/icmp_header.rb
31
+ - lib/simple_capture/header/ipv4_header.rb
32
+ - lib/simple_capture/packet.rb
33
+ - lib/simple_capture/recv_message.rb
34
+ - lib/simple_capture/string.rb
35
+ - lib/simple_capture/version.rb
36
+ - sample_run.rb
37
+ - simple_capture.gemspec
38
+ homepage: https://github.com/kuredev/simple_capture
39
+ licenses: []
40
+ metadata:
41
+ allowed_push_host: https://rubygems.org
42
+ homepage_uri: https://github.com/kuredev/simple_capture
43
+ source_code_uri: https://github.com/kuredev/simple_capture
44
+ changelog_uri: https://github.com/kuredev/simple_capture
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.3.0
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubygems_version: 3.2.3
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Packet capture tool made only with Ruby.
64
+ test_files: []