ffi-packets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +20 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/ffi-packets.gemspec +67 -0
- data/lib/ffi/packets.rb +14 -0
- data/lib/ffi/packets/arp.rb +60 -0
- data/lib/ffi/packets/constants.rb +478 -0
- data/lib/ffi/packets/eth.rb +74 -0
- data/lib/ffi/packets/icmp.rb +294 -0
- data/lib/ffi/packets/ip.rb +227 -0
- data/lib/ffi/packets/tcp.rb +104 -0
- data/lib/ffi/packets/udp.rb +30 -0
- data/lib/ffi/packets/util.rb +54 -0
- data/spec/ffi-packets_spec.rb +7 -0
- data/spec/spec_helper.rb +9 -0
- metadata +103 -0
@@ -0,0 +1,104 @@
|
|
1
|
+
module FFI::Packets
|
2
|
+
module Tcp
|
3
|
+
|
4
|
+
# TCP header, without options
|
5
|
+
#
|
6
|
+
# field :sport, :uint16, :desc => 'source port'
|
7
|
+
# field :dport, :uint16, :desc => 'destination port'
|
8
|
+
# field :seq, :uint32, :desc => 'sequence number'
|
9
|
+
# field :ack, :uint32, :desc => 'acknowledgment number'
|
10
|
+
# field :off_x2, :uint8, :desc => 'data offset(& 0xf0) unused (& 0x0f)'
|
11
|
+
# field :flags, :uint8, :desc => 'control flags'
|
12
|
+
# field :win, :uint16, :desc => 'window'
|
13
|
+
# field :sum, :uint16, :desc => 'checksum'
|
14
|
+
# field :urgp, :uint16, :desc => 'urgent pointer'
|
15
|
+
#
|
16
|
+
class Hdr < ::FFI::Struct
|
17
|
+
include ::FFI::DRY::NetStructHelper
|
18
|
+
|
19
|
+
dsl_layout do
|
20
|
+
field :sport, :uint16, :desc => 'source port'
|
21
|
+
field :dport, :uint16, :desc => 'destination port'
|
22
|
+
field :seq, :uint32, :desc => 'sequence number'
|
23
|
+
field :ack, :uint32, :desc => 'acknowledgment number'
|
24
|
+
field :off_x2, :uint8, :desc => 'data offset(& 0xf0) unused (& 0x0f)'
|
25
|
+
field :flags, :uint8, :desc => 'control flags'
|
26
|
+
field :win, :uint16, :desc => 'window'
|
27
|
+
field :sum, :uint16, :desc => 'checksum'
|
28
|
+
field :urgp, :uint16, :desc => 'urgent pointer'
|
29
|
+
end
|
30
|
+
|
31
|
+
# TCP control flags (flags)
|
32
|
+
module Flags
|
33
|
+
include ::FFI::DRY::ConstFlagsMap
|
34
|
+
slurp_constants(Constants, "TH_")
|
35
|
+
def self.list; @@list ||= super() ; end
|
36
|
+
end
|
37
|
+
|
38
|
+
# #define \
|
39
|
+
# tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do { \
|
40
|
+
# struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr); \
|
41
|
+
# tcp_pack_p->th_sport = htons(sport); \
|
42
|
+
# tcp_pack_p->th_dport = htons(dport); \
|
43
|
+
# tcp_pack_p->th_seq = htonl(seq); \
|
44
|
+
# tcp_pack_p->th_ack = htonl(ack); \
|
45
|
+
# tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5; \
|
46
|
+
# tcp_pack_p->th_flags = flags; \
|
47
|
+
# tcp_pack_p->th_win = htons(win); \
|
48
|
+
# tcp_pack_p->th_urp = htons(urp); \
|
49
|
+
# } while (0)
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# TCP option (following TCP header)
|
55
|
+
#
|
56
|
+
# struct tcp_opt {
|
57
|
+
# uint8_t opt_type; /* option type */
|
58
|
+
# uint8_t opt_len; /* option length >= TCP_OPT_LEN */
|
59
|
+
# union tcp_opt_data {
|
60
|
+
# uint16_t mss; /* TCP_OPT_MSS */
|
61
|
+
# uint8_t wscale; /* TCP_OPT_WSCALE */
|
62
|
+
# uint16_t sack[19]; /* TCP_OPT_SACK */
|
63
|
+
# uint32_t echo; /* TCP_OPT_ECHO{REPLY} */
|
64
|
+
# uint32_t timestamp[2]; /* TCP_OPT_TIMESTAMP */
|
65
|
+
# uint32_t cc; /* TCP_OPT_CC{NEW,ECHO} */
|
66
|
+
# uint8_t cksum; /* TCP_OPT_ALTSUM */
|
67
|
+
# uint8_t md5[16]; /* TCP_OPT_MD5 */
|
68
|
+
# uint8_t data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN];
|
69
|
+
# } opt_data;
|
70
|
+
# } __attribute__((__packed__));
|
71
|
+
#
|
72
|
+
class Opt < ::FFI::Struct
|
73
|
+
include ::FFI::DRY::NetStructHelper
|
74
|
+
|
75
|
+
TCP_OPT_LEN = Constants::TCP_OPT_LEN
|
76
|
+
TCP_OPT_LEN_MAX = Constants::TCP_OPT_LEN_MAX
|
77
|
+
|
78
|
+
DATA_LEN = TCP_OPT_LEN_MAX - TCP_OPT_LEN
|
79
|
+
|
80
|
+
dsl_layout do
|
81
|
+
field :otype, :uint8
|
82
|
+
field :len, :uint8
|
83
|
+
array :data8, [:uint8, DATA_LEN]
|
84
|
+
end
|
85
|
+
|
86
|
+
# Options (otype) - http://www.iana.org/assignments/tcp-parameters
|
87
|
+
module Otype
|
88
|
+
include ::FFI::DRY::ConstMap
|
89
|
+
slurp_constants(Constants, "TCP_OTYPE_")
|
90
|
+
def self.list; @@list ||= super() ; end
|
91
|
+
end
|
92
|
+
|
93
|
+
end # class Opt
|
94
|
+
|
95
|
+
# TCP FSM states
|
96
|
+
module State
|
97
|
+
include ::FFI::DRY::ConstMap
|
98
|
+
slurp_constants(Constants, "TCP_STATE_")
|
99
|
+
def self.list; @@list ||= super() ; end
|
100
|
+
end
|
101
|
+
|
102
|
+
end # module Tcp
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module FFI::Packets
|
2
|
+
|
3
|
+
class Udp
|
4
|
+
class Hdr < ::FFI::Struct
|
5
|
+
include ::FFI::DRY::NetStructHelper
|
6
|
+
|
7
|
+
# struct udp_hdr {
|
8
|
+
# uint16_t uh_sport; /* source port */
|
9
|
+
# uint16_t uh_dport; /* destination port */
|
10
|
+
# uint16_t uh_ulen; /* udp length (including header) */
|
11
|
+
# uint16_t uh_sum; /* udp checksum */
|
12
|
+
# };
|
13
|
+
dsl_layout do
|
14
|
+
field :sport, :uint16
|
15
|
+
field :dport, :uint16
|
16
|
+
field :len, :uint16
|
17
|
+
field :sum, :uint16
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# #define udp_pack_hdr(hdr, sport, dport, ulen) do { \
|
24
|
+
# struct udp_hdr *udp_pack_p = (struct udp_hdr *)(hdr); \
|
25
|
+
# udp_pack_p->uh_sport = htons(sport); \
|
26
|
+
# udp_pack_p->uh_dport = htons(dport); \
|
27
|
+
# udp_pack_p->uh_ulen = htons(ulen); \
|
28
|
+
# } while (0)
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
module FFI::Packets
|
3
|
+
module Util
|
4
|
+
|
5
|
+
RX_IP4_ADDR = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/
|
6
|
+
RX_MAC_ADDR = /(?:(?:[a-f0-9]{1,2}[:-])?{5}[a-f0-9]{1,2})/i
|
7
|
+
|
8
|
+
# takes a IPv4 number and returns it as a 32-bit number
|
9
|
+
def Util.ipv4_atol(str)
|
10
|
+
unless str =~ /^#{RX_IP4_ADDR}$/
|
11
|
+
raise(::ArgumentError, "invalid IP address #{str.inspect}")
|
12
|
+
else
|
13
|
+
u32=0
|
14
|
+
str.split('.',4).each {|o| u32 = ((u32 << 8) | o.to_i) }
|
15
|
+
return u32
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# takes a 32-bit number and returns it as an IPv4 address string.
|
20
|
+
def Util.ipv4_ltoa(int)
|
21
|
+
unless(int.is_a? Numeric and int <= 0xffffffff)
|
22
|
+
raise(::ArgumentError, "not a long integer: #{int.inspect}")
|
23
|
+
end
|
24
|
+
ret = []
|
25
|
+
4.times do
|
26
|
+
ret.unshift(int & 0xff)
|
27
|
+
int >>= 8
|
28
|
+
end
|
29
|
+
ret.join('.')
|
30
|
+
end
|
31
|
+
|
32
|
+
def Util.unhexify(str, d=/\s*/)
|
33
|
+
str.to_s.strip.gsub(/([A-Fa-f0-9]{1,2})#{d}?/) { $1.hex.chr }
|
34
|
+
end
|
35
|
+
|
36
|
+
def Util.htonl(*args)
|
37
|
+
FFI::DRY::NetEndian.htonl(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def Util.htons(*args)
|
41
|
+
FFI::DRY::NetEndian.htons(*args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def Util.ntohl(*args)
|
45
|
+
FFI::DRY::NetEndian.ntohl(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
def Util.ntohs(*args)
|
49
|
+
FFI::DRY::NetEndian.ntohs(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
end # module Util
|
53
|
+
|
54
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ffi-packets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eric Monti
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-02 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ffi
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: ffi_dry
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: A collection of common network packets structures in FFI::Struct form for use with bindings to raw network libraries such as libdnet, libnet, or libpcap.
|
46
|
+
email: emonti@matasano.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
- README.rdoc
|
54
|
+
files:
|
55
|
+
- .document
|
56
|
+
- .gitignore
|
57
|
+
- LICENSE
|
58
|
+
- README.rdoc
|
59
|
+
- Rakefile
|
60
|
+
- VERSION
|
61
|
+
- ffi-packets.gemspec
|
62
|
+
- lib/ffi/packets.rb
|
63
|
+
- lib/ffi/packets/arp.rb
|
64
|
+
- lib/ffi/packets/constants.rb
|
65
|
+
- lib/ffi/packets/eth.rb
|
66
|
+
- lib/ffi/packets/icmp.rb
|
67
|
+
- lib/ffi/packets/ip.rb
|
68
|
+
- lib/ffi/packets/tcp.rb
|
69
|
+
- lib/ffi/packets/udp.rb
|
70
|
+
- lib/ffi/packets/util.rb
|
71
|
+
- spec/ffi-packets_spec.rb
|
72
|
+
- spec/spec_helper.rb
|
73
|
+
has_rdoc: true
|
74
|
+
homepage: http://github.com/emonti/ffi-packets
|
75
|
+
licenses: []
|
76
|
+
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options:
|
79
|
+
- --charset=UTF-8
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
version:
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: "0"
|
93
|
+
version:
|
94
|
+
requirements: []
|
95
|
+
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 1.3.5
|
98
|
+
signing_key:
|
99
|
+
specification_version: 3
|
100
|
+
summary: A collection of common network packets structures
|
101
|
+
test_files:
|
102
|
+
- spec/ffi-packets_spec.rb
|
103
|
+
- spec/spec_helper.rb
|