packetgen 0.1.0 → 0.2.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 +4 -4
- data/.travis.yml +1 -1
- data/README.md +7 -2
- data/Rakefile +5 -2
- data/lib/packetgen/header/header_methods.rb +1 -1
- data/lib/packetgen/header/ip.rb +21 -0
- data/lib/packetgen/header/ipv6.rb +40 -0
- data/lib/packetgen/header/udp.rb +2 -4
- data/lib/packetgen/packet.rb +1 -1
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +2 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d79b3046c42fa081a32cbb80633d26115aa8d8a
|
4
|
+
data.tar.gz: 554c95accb7cba2eb8fd1199962b76c914d479dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4543ec99fea03226b5a0acaf712f49e2683910953d852dcdff5ec1d71e3ec7e908efb32ee7a5e9707ed0bfe8ec33fba757922a7c0ae4a99e84401e8454e934f0
|
7
|
+
data.tar.gz: e4c77821a111d8d0b921c87067d3a890c2efd23d2127b0655863ca7b062ac1546746a9d2e0690b3622cc73e355b7592fbe34bbb2b75c3e7770d6ee82e2065a6a
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
|
2
|
+
[](https://badge.fury.io/rb/packetgen)
|
2
3
|
[](https://travis-ci.org/sdaubert/packetgen)
|
3
4
|
|
4
5
|
# PacketGen
|
5
6
|
|
6
|
-
PacketGen
|
7
|
+
PacketGen provides simple ways to generate, send and capture network packets easily.
|
7
8
|
|
8
9
|
## Why PacketGen
|
9
10
|
Why create PacketGen ? There is already PacketFu!
|
@@ -17,7 +18,11 @@ Yes. But PacketFu is limited:
|
|
17
18
|
|
18
19
|
## use cases
|
19
20
|
|
20
|
-
|
21
|
+
These use cases are the roadmap for PacketGen.
|
22
|
+
|
23
|
+
Not yet implemented:
|
24
|
+
- encapsulation/decapsulation
|
25
|
+
- some protocols...
|
21
26
|
|
22
27
|
### Easily create packets
|
23
28
|
```
|
data/Rakefile
CHANGED
@@ -8,11 +8,14 @@ RSpec::Core::RakeTask.new do |t|
|
|
8
8
|
t.rspec_opts = '-t ~sudo'
|
9
9
|
end
|
10
10
|
RSpec::Core::RakeTask.new('spec:sudo') do |t|
|
11
|
-
|
11
|
+
if ENV['TRAVIS']
|
12
|
+
t.rspec_opts = '-t sudo -t ~notravis'
|
13
|
+
else
|
14
|
+
t.rspec_opts = '-t sudo'
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
YARD::Rake::YardocTask.new do |t|
|
15
19
|
t.options = ['--no-private']
|
16
20
|
t.files = ['lib/**/*.rb', '-', 'LICENSE']
|
17
21
|
end
|
18
|
-
|
@@ -42,7 +42,7 @@ module PacketGen
|
|
42
42
|
# @raise FormatError +header+ not in a packet
|
43
43
|
def ip_header(header)
|
44
44
|
hid = header_id(header)
|
45
|
-
iph = packet.headers[0...hid].reverse.find { |h| h.is_a? IP }
|
45
|
+
iph = packet.headers[0...hid].reverse.find { |h| h.is_a? IP or h.is_a? IPv6 }
|
46
46
|
raise FormatError, 'no IP or IPv6 header in packet' if iph.nil?
|
47
47
|
iph
|
48
48
|
end
|
data/lib/packetgen/header/ip.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
1
3
|
module PacketGen
|
2
4
|
module Header
|
3
5
|
|
@@ -275,6 +277,25 @@ module PacketGen
|
|
275
277
|
first_byte = [(version << 4) | ihl].pack('C')
|
276
278
|
first_byte << to_a[2..-1].map { |field| field.to_s }.join
|
277
279
|
end
|
280
|
+
|
281
|
+
# Get IP part of pseudo header sum.
|
282
|
+
# @return [Integer]
|
283
|
+
def pseudo_header_sum
|
284
|
+
sum = self[:src].to_i + self[:dst].to_i
|
285
|
+
(sum >> 16) + (sum & 0xffff)
|
286
|
+
end
|
287
|
+
|
288
|
+
# Send IP packet on wire.
|
289
|
+
#
|
290
|
+
# When sending packet at IP level, +sum+ and +length+ fields are set by
|
291
|
+
# kernel, so bad IP packets cannot be sent this way. To do so, use {Eth#to_w}.
|
292
|
+
# @param [String,nil] iface interface name. Not used
|
293
|
+
# @return [void]
|
294
|
+
def to_w(iface=nil)
|
295
|
+
sock = Socket.new(Socket::AF_INET, Socket::SOCK_RAW, Socket::IPPROTO_RAW)
|
296
|
+
sockaddrin = Socket.sockaddr_in(0, dst)
|
297
|
+
sock.send to_s, 0, sockaddrin
|
298
|
+
end
|
278
299
|
end
|
279
300
|
|
280
301
|
Eth.bind_header IP, proto: 0x800
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require 'ipaddr'
|
2
3
|
|
3
4
|
module PacketGen
|
@@ -207,6 +208,45 @@ module PacketGen
|
|
207
208
|
first32 = (version << 28) | (traffic_class << 20) | flow_label
|
208
209
|
[first32].pack('N') << to_a[3..-1].map { |field| field.to_s }.join
|
209
210
|
end
|
211
|
+
|
212
|
+
# Get IPv6 part of pseudo header sum.
|
213
|
+
# @return [Integer]
|
214
|
+
def pseudo_header_sum
|
215
|
+
sum = 0
|
216
|
+
self[:src].each { |word| sum += word.to_i }
|
217
|
+
self[:dst].each { |word| sum += word.to_i }
|
218
|
+
sum
|
219
|
+
end
|
220
|
+
|
221
|
+
# Send IPv6 packet on wire.
|
222
|
+
#
|
223
|
+
# When sending packet at IPv6 level, +version+, +flow_label+ and +length+
|
224
|
+
# fields are set by kernel. Source address should be a unicast address
|
225
|
+
# assigned to the host. To set any of this fields, use {Eth#to_w}.
|
226
|
+
# @param [String] iface interface name
|
227
|
+
# @return [void]
|
228
|
+
def to_w(iface=nil)
|
229
|
+
sock = Socket.new(Socket::AF_INET6, Socket::SOCK_RAW, self.next)
|
230
|
+
sockaddrin = Socket.sockaddr_in(0, dst)
|
231
|
+
|
232
|
+
# IPv6 RAW sockets don't have IPHDRINCL option to send IPv6 header.
|
233
|
+
# So, header must be built using ancillary data.
|
234
|
+
# Only src address, traffic_class and hop_limit can be set this way.
|
235
|
+
hop_limit = Socket::AncillaryData.int(Socket::AF_INET6,
|
236
|
+
Socket::IPPROTO_IPV6,
|
237
|
+
Socket::IPV6_HOPLIMIT, hop)
|
238
|
+
tc = Socket::AncillaryData.int(Socket::AF_INET6,
|
239
|
+
Socket::IPPROTO_IPV6,
|
240
|
+
Socket::IPV6_TCLASS,
|
241
|
+
traffic_class)
|
242
|
+
|
243
|
+
# src address is set through PKT_INFO, which needs interface index.
|
244
|
+
ifaddr = Socket.getifaddrs.find { |ia| ia.name == iface }
|
245
|
+
raise WireError, "unknown #{iface} interface" if ifaddr.nil?
|
246
|
+
pkt_info = Socket::AncillaryData.ipv6_pktinfo(Addrinfo.ip(src), ifaddr.ifindex)
|
247
|
+
|
248
|
+
sock.sendmsg body.to_s, 0, sockaddrin, hop_limit, tc, pkt_info
|
249
|
+
end
|
210
250
|
end
|
211
251
|
|
212
252
|
Eth.bind_header IPv6, proto: 0x86DD
|
data/lib/packetgen/header/udp.rb
CHANGED
@@ -45,10 +45,7 @@ module PacketGen
|
|
45
45
|
# @return [Integer]
|
46
46
|
def calc_sum
|
47
47
|
ip = ip_header(self)
|
48
|
-
sum = ip
|
49
|
-
sum += ip[:src].to_i & 0xffff
|
50
|
-
sum += ip[:dst].to_i >> 16
|
51
|
-
sum += ip[:dst].to_i & 0xffff
|
48
|
+
sum = ip.pseudo_header_sum
|
52
49
|
sum += IP_PROTOCOL
|
53
50
|
sum += length
|
54
51
|
sum += sport
|
@@ -129,5 +126,6 @@ module PacketGen
|
|
129
126
|
end
|
130
127
|
|
131
128
|
IP.bind_header UDP, proto: UDP::IP_PROTOCOL
|
129
|
+
IPv6.bind_header UDP, next: UDP::IP_PROTOCOL
|
132
130
|
end
|
133
131
|
end
|
data/lib/packetgen/packet.rb
CHANGED
data/lib/packetgen/version.rb
CHANGED
data/packetgen.gemspec
CHANGED
@@ -20,6 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
21
|
spec.require_paths = ['lib']
|
22
22
|
|
23
|
+
spec.required_ruby_version = '>= 2.1.0'
|
24
|
+
|
23
25
|
spec.add_dependency 'pcaprub', '~>0.12.4'
|
24
26
|
|
25
27
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: packetgen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Daubert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pcaprub
|
@@ -140,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
140
140
|
requirements:
|
141
141
|
- - ">="
|
142
142
|
- !ruby/object:Gem::Version
|
143
|
-
version:
|
143
|
+
version: 2.1.0
|
144
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
145
|
requirements:
|
146
146
|
- - ">="
|