packetgen 4.0.0 → 4.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 +4 -4
- data/README.md +1 -1
- data/lib/packetgen/deprecation.rb +7 -1
- data/lib/packetgen/header/arp.rb +6 -7
- data/lib/packetgen/header/asn1_base.rb +2 -1
- data/lib/packetgen/header/base.rb +27 -24
- data/lib/packetgen/header/bootp.rb +14 -14
- data/lib/packetgen/header/dhcp/option.rb +8 -8
- data/lib/packetgen/header/dhcp/options.rb +2 -2
- data/lib/packetgen/header/dhcp.rb +6 -7
- data/lib/packetgen/header/dhcpv6/duid.rb +1 -1
- data/lib/packetgen/header/dhcpv6/option.rb +37 -15
- data/lib/packetgen/header/dhcpv6/options.rb +3 -3
- data/lib/packetgen/header/dhcpv6/relay.rb +1 -0
- data/lib/packetgen/header/dhcpv6.rb +13 -14
- data/lib/packetgen/header/dns/name.rb +9 -8
- data/lib/packetgen/header/dns/opt.rb +3 -0
- data/lib/packetgen/header/dns/option.rb +7 -7
- data/lib/packetgen/header/dns/qdsection.rb +2 -2
- data/lib/packetgen/header/dns/question.rb +1 -0
- data/lib/packetgen/header/dns/rrsection.rb +2 -2
- data/lib/packetgen/header/dns.rb +76 -60
- data/lib/packetgen/header/dot11/control.rb +5 -5
- data/lib/packetgen/header/dot11/data.rb +11 -10
- data/lib/packetgen/header/dot11/element.rb +1 -1
- data/lib/packetgen/header/dot11/management.rb +18 -15
- data/lib/packetgen/header/dot11/sub_mngt.rb +22 -21
- data/lib/packetgen/header/dot11.rb +38 -38
- data/lib/packetgen/header/dot1q.rb +5 -4
- data/lib/packetgen/header/dot1x.rb +8 -8
- data/lib/packetgen/header/eap/fast.rb +3 -3
- data/lib/packetgen/header/eap/md5.rb +11 -3
- data/lib/packetgen/header/eap/tls.rb +9 -8
- data/lib/packetgen/header/eap/ttls.rb +13 -10
- data/lib/packetgen/header/eap.rb +58 -33
- data/lib/packetgen/header/eth.rb +26 -12
- data/lib/packetgen/header/gre.rb +26 -2
- data/lib/packetgen/header/http/headers.rb +6 -5
- data/lib/packetgen/header/http/request.rb +24 -16
- data/lib/packetgen/header/http/response.rb +22 -15
- data/lib/packetgen/header/icmp.rb +10 -10
- data/lib/packetgen/header/icmpv6.rb +10 -9
- data/lib/packetgen/header/igmp.rb +21 -10
- data/lib/packetgen/header/igmpv3/group_record.rb +7 -2
- data/lib/packetgen/header/igmpv3/mq.rb +1 -1
- data/lib/packetgen/header/igmpv3/mr.rb +1 -1
- data/lib/packetgen/header/igmpv3.rb +11 -10
- data/lib/packetgen/header/ip/addr.rb +6 -2
- data/lib/packetgen/header/ip/option.rb +18 -5
- data/lib/packetgen/header/ip.rb +52 -35
- data/lib/packetgen/header/ipv6/addr.rb +14 -13
- data/lib/packetgen/header/ipv6/extension.rb +9 -7
- data/lib/packetgen/header/ipv6/hop_by_hop.rb +26 -7
- data/lib/packetgen/header/ipv6.rb +31 -22
- data/lib/packetgen/header/llc.rb +20 -13
- data/lib/packetgen/header/mdns.rb +9 -2
- data/lib/packetgen/header/mld.rb +11 -9
- data/lib/packetgen/header/mldv2/mcast_address_record.rb +6 -1
- data/lib/packetgen/header/mldv2/mlq.rb +8 -8
- data/lib/packetgen/header/mldv2/mlr.rb +4 -4
- data/lib/packetgen/header/mldv2.rb +1 -1
- data/lib/packetgen/header/ospfv2/db_description.rb +10 -10
- data/lib/packetgen/header/ospfv2/hello.rb +11 -10
- data/lib/packetgen/header/ospfv2/ls_ack.rb +5 -6
- data/lib/packetgen/header/ospfv2/ls_request.rb +7 -6
- data/lib/packetgen/header/ospfv2/ls_update.rb +7 -7
- data/lib/packetgen/header/ospfv2/lsa.rb +33 -10
- data/lib/packetgen/header/ospfv2/lsa_header.rb +3 -2
- data/lib/packetgen/header/ospfv2.rb +31 -26
- data/lib/packetgen/header/ospfv3/db_description.rb +12 -13
- data/lib/packetgen/header/ospfv3/hello.rb +10 -9
- data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +6 -2
- data/lib/packetgen/header/ospfv3/ls_ack.rb +5 -6
- data/lib/packetgen/header/ospfv3/ls_request.rb +10 -10
- data/lib/packetgen/header/ospfv3/ls_update.rb +7 -7
- data/lib/packetgen/header/ospfv3/lsa.rb +23 -9
- data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -2
- data/lib/packetgen/header/ospfv3.rb +38 -34
- data/lib/packetgen/header/sctp/chunk.rb +38 -17
- data/lib/packetgen/header/sctp/error.rb +169 -197
- data/lib/packetgen/header/sctp/padded32.rb +3 -3
- data/lib/packetgen/header/sctp/parameter.rb +85 -132
- data/lib/packetgen/header/sctp.rb +14 -3
- data/lib/packetgen/header/snmp.rb +108 -7
- data/lib/packetgen/header/tcp/option.rb +7 -0
- data/lib/packetgen/header/tcp/options.rb +11 -3
- data/lib/packetgen/header/tcp.rb +33 -26
- data/lib/packetgen/header/tftp.rb +16 -10
- data/lib/packetgen/header/udp.rb +15 -13
- data/lib/packetgen/header.rb +19 -13
- data/lib/packetgen/headerable.rb +9 -3
- data/lib/packetgen/inspect.rb +2 -7
- data/lib/packetgen/packet.rb +94 -36
- data/lib/packetgen/pcapng/block.rb +2 -1
- data/lib/packetgen/pcapng/file.rb +41 -14
- data/lib/packetgen/pcapng/idb.rb +2 -1
- data/lib/packetgen/pcapng/shb.rb +2 -1
- data/lib/packetgen/pcapng/spb.rb +1 -1
- data/lib/packetgen/pcapng.rb +2 -0
- data/lib/packetgen/proto.rb +4 -0
- data/lib/packetgen/unknown_packet.rb +3 -3
- data/lib/packetgen/utils.rb +2 -1
- data/lib/packetgen/version.rb +1 -1
- data/lib/packetgen.rb +8 -2
- metadata +4 -4
@@ -9,14 +9,15 @@
|
|
9
9
|
module PacketGen
|
10
10
|
module Header
|
11
11
|
# @since 2.2.0
|
12
|
+
# @author Kent 'picat' Gruber
|
12
13
|
module HTTP
|
13
14
|
# @abstract Base class for HTTP headers.
|
14
15
|
# @author Kent 'picat' Gruber
|
15
16
|
class Headers
|
16
17
|
include BinStruct::Structable
|
17
18
|
|
18
|
-
# Underlying Headers data
|
19
|
-
# @return [Hash, nil]
|
19
|
+
# Underlying Headers data.
|
20
|
+
# @return [Hash{String => String}, nil]
|
20
21
|
attr_reader :data
|
21
22
|
alias to_h data
|
22
23
|
|
@@ -25,7 +26,7 @@ module PacketGen
|
|
25
26
|
end
|
26
27
|
|
27
28
|
# Populate object from a string or directly from a hash.
|
28
|
-
# @param [String, Hash] s_or_h
|
29
|
+
# @param [String, Hash{String=>String}] s_or_h
|
29
30
|
# @return [self]
|
30
31
|
def read(s_or_h)
|
31
32
|
case s_or_h
|
@@ -69,14 +70,14 @@ module PacketGen
|
|
69
70
|
d.join("\r\n") << "\r\n\r\n"
|
70
71
|
end
|
71
72
|
|
72
|
-
# Get a human readable
|
73
|
+
# Get a human readable hash.
|
73
74
|
# @return [Hash]
|
74
75
|
def to_human
|
75
76
|
@data
|
76
77
|
end
|
77
78
|
|
78
79
|
# Read human-readable data to populate header data.
|
79
|
-
# @param [Hash] data
|
80
|
+
# @param [Hash{String=>String}] data
|
80
81
|
# @return [self]
|
81
82
|
def from_human(data)
|
82
83
|
read(data)
|
@@ -10,28 +10,30 @@ module PacketGen
|
|
10
10
|
module Header
|
11
11
|
module HTTP
|
12
12
|
# An HTTP/1.1 Request packet consists of:
|
13
|
-
# * the http verb (
|
14
|
-
# * the path (
|
15
|
-
# * the version (
|
13
|
+
# * the http verb (+BinStruct::String+).
|
14
|
+
# * the path (+BinStruct::String+).
|
15
|
+
# * the version (+BinStruct::String+).
|
16
16
|
# * associated http headers ({HTTP::Headers}).
|
17
|
+
# * and a {#body} (+BinStruct::String+).
|
17
18
|
#
|
18
|
-
#
|
19
|
+
# Note: When creating a HTTP Request packet, {TCP#sport} and {TCP#dport}
|
20
|
+
# attributes are not set.
|
21
|
+
#
|
22
|
+
# @example Create a HTTP Request header
|
19
23
|
# # standalone
|
20
|
-
#
|
24
|
+
# http_request = PacketGen::Header::HTTP::Request.new
|
21
25
|
# # in a packet
|
22
26
|
# pkt = PacketGen.gen("IP").add("TCP").add("HTTP::Request")
|
23
27
|
# # access to HTTP Request header
|
24
|
-
# pkt.http_request # => PacketGen::Header::HTTP::Request
|
25
|
-
#
|
26
|
-
# Note: When creating a HTTP Request packet, +sport+ and +dport+
|
27
|
-
# attributes of TCP header are not set.
|
28
|
+
# pkt.http_request.class # => PacketGen::Header::HTTP::Request
|
28
29
|
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
30
|
+
# @example HTTP Request attributes
|
31
|
+
# http_request = PacketGen::Header::HTTP::Request.new
|
32
|
+
# http_request.version #=> "HTTP/1.1"
|
33
|
+
# http_request.verb = "GET"
|
34
|
+
# http_request.path = "/meow.html"
|
35
|
+
# http_request.headers = "Host: tcpdump.org" # string or
|
36
|
+
# http_request.headers = { "Host": "tcpdump.org" } # even a hash
|
35
37
|
#
|
36
38
|
# @author Kent 'picat' Gruber
|
37
39
|
# @author Sylvain Daubert
|
@@ -39,13 +41,16 @@ module PacketGen
|
|
39
41
|
# @since 3.1.0 Rename +#method+ into {#verb} to not mask +Object#method+.
|
40
42
|
class Request < Base
|
41
43
|
# @!attribute verb
|
44
|
+
# HTTP verb (method)
|
42
45
|
# @return [BinStruct::String]
|
43
46
|
# @since 3.1.0
|
44
47
|
define_attr :verb, BinStruct::String
|
45
48
|
# @!attribute path
|
49
|
+
# Requested path
|
46
50
|
# @return [BinStruct::String]
|
47
51
|
define_attr :path, BinStruct::String
|
48
52
|
# @!attribute version
|
53
|
+
# HTTP version
|
49
54
|
# @return [BinStruct::String]
|
50
55
|
define_attr :version, BinStruct::String, default: 'HTTP/1.1'
|
51
56
|
# @!attribute headers
|
@@ -53,6 +58,7 @@ module PacketGen
|
|
53
58
|
# @return [HTTP::Headers]
|
54
59
|
define_attr :headers, HTTP::Headers
|
55
60
|
# @!attribute body
|
61
|
+
# HTTP request body, if any
|
56
62
|
# @return [BinStruct::String]
|
57
63
|
define_attr :body, BinStruct::String
|
58
64
|
|
@@ -67,7 +73,7 @@ module PacketGen
|
|
67
73
|
end
|
68
74
|
|
69
75
|
# Read in the HTTP portion of the packet, and parse it.
|
70
|
-
# @return [
|
76
|
+
# @return [self]
|
71
77
|
def read(str)
|
72
78
|
lines = lines(str)
|
73
79
|
first_line_words = lines.shift.split
|
@@ -83,6 +89,8 @@ module PacketGen
|
|
83
89
|
self
|
84
90
|
end
|
85
91
|
|
92
|
+
# May be parsed as a HTTP request if verb is known, and if version is +HTTP/1.x+.
|
93
|
+
# @return [Boolean]
|
86
94
|
def parse?
|
87
95
|
VERBS.include?(self.verb) && self.version.start_with?('HTTP/1.')
|
88
96
|
end
|
@@ -10,25 +10,26 @@ module PacketGen
|
|
10
10
|
module Header
|
11
11
|
module HTTP
|
12
12
|
# An HTTP/1.1 Response packet consists of:
|
13
|
-
# * the version (
|
14
|
-
# * the status code (
|
15
|
-
# * the status message (
|
16
|
-
# * associated
|
17
|
-
# * the actual
|
13
|
+
# * the version (+BinStruct::String+).
|
14
|
+
# * the status code (+BinStruct::String+).
|
15
|
+
# * the status message (+BinStruct::String+).
|
16
|
+
# * associated HTTP headers ({HTTP::Headers}).
|
17
|
+
# * the actual HTTP payload body (+BinStruct::String+).
|
18
18
|
#
|
19
|
-
#
|
19
|
+
# Note: When creating a HTTP Response packet, +sport+ and +dport+
|
20
|
+
# attributes of TCP header are not set.
|
21
|
+
#
|
22
|
+
# @example Create a HTTP Response header
|
20
23
|
# # standalone
|
21
24
|
# http_resp = PacketGen::Header::HTTP::Response.new
|
22
25
|
# # in a packet
|
23
26
|
# pkt = PacketGen.gen("IP").add("TCP").add("HTTP::Response")
|
24
27
|
# # access to HTTP Response header
|
25
|
-
# pkt.http_response # => PacketGen::Header::HTTP::Response
|
28
|
+
# pkt.http_response.class # => PacketGen::Header::HTTP::Response
|
26
29
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# == HTTP Response attributes
|
31
|
-
# http_resp.version = "HTTP/1.1"
|
30
|
+
# @example HTTP Response attributes
|
31
|
+
# http_resp = PacketGen::Header::HTTP::Response.new
|
32
|
+
# http_resp.version #=> "HTTP/1.1"
|
32
33
|
# http_resp.status_code = "200"
|
33
34
|
# http_resp.status_mesg = "OK"
|
34
35
|
# http_resp.body = "this is a body"
|
@@ -39,20 +40,24 @@ module PacketGen
|
|
39
40
|
# @author LemonTree55
|
40
41
|
class Response < Base
|
41
42
|
# @!attribute version
|
43
|
+
# HTTP version
|
42
44
|
# @return [BinStruct::String]
|
43
45
|
define_attr :version, BinStruct::String, default: 'HTTP/1.1'
|
44
46
|
# @!attribute status_code
|
47
|
+
# Response status code
|
45
48
|
# @return [BinStruct::String]
|
46
49
|
define_attr :status_code, BinStruct::String
|
47
50
|
# @!attribute status_mesg
|
51
|
+
# Response status message
|
48
52
|
# @return [BinStruct::String]
|
49
53
|
define_attr :status_mesg, BinStruct::String
|
50
54
|
# @!attribute headers
|
51
55
|
# associated http/1.1 headers
|
52
|
-
# @return [
|
56
|
+
# @return [HTTP::Headers]
|
53
57
|
define_attr :headers, HTTP::Headers
|
54
58
|
# @!attribute body
|
55
|
-
#
|
59
|
+
# Response body
|
60
|
+
# @return [BinStruct::String]
|
56
61
|
define_attr :body, BinStruct::String
|
57
62
|
|
58
63
|
# @param [Hash] options
|
@@ -67,7 +72,7 @@ module PacketGen
|
|
67
72
|
end
|
68
73
|
|
69
74
|
# Read in the HTTP portion of the packet, and parse it.
|
70
|
-
# @return [
|
75
|
+
# @return [self]
|
71
76
|
def read(str)
|
72
77
|
headers, data = collect_headers_and_data(str)
|
73
78
|
|
@@ -80,6 +85,8 @@ module PacketGen
|
|
80
85
|
self
|
81
86
|
end
|
82
87
|
|
88
|
+
# May be parsed as a HTTP response if version is +HTTP/1.x+.
|
89
|
+
# @return [Boolean]
|
83
90
|
def parse?
|
84
91
|
version.start_with?('HTTP/1.')
|
85
92
|
end
|
@@ -15,24 +15,25 @@ module PacketGen
|
|
15
15
|
# | Type | Code | Checksum |
|
16
16
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
17
17
|
# A ICMP header consists of:
|
18
|
-
# * a {#type} field (
|
19
|
-
# * a {#code} field (
|
20
|
-
# * a {#checksum} field (
|
18
|
+
# * a {#type} field (+BinStruct::Int8+ type),
|
19
|
+
# * a {#code} field (+BinStruct::Int8+ type),
|
20
|
+
# * a {#checksum} field (+BinStruct::Int16+ type),
|
21
21
|
# * and a {#body}.
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# @example Create a ICMP header
|
24
24
|
# # standalone
|
25
25
|
# icmp = PacketGen::Header::ICMP.new
|
26
26
|
# # in a packet
|
27
27
|
# pkt = PacketGen.gen('IP').add('ICMP')
|
28
28
|
# # access to ICMP header
|
29
|
-
# pkt.icmp
|
29
|
+
# pkt.icmp.class # => PacketGen::Header::ICMP
|
30
30
|
#
|
31
|
-
#
|
31
|
+
# @example ICMP attributes
|
32
|
+
# icmp = PacketGen::Header::ICMP.new
|
32
33
|
# icmp.code = 0
|
33
34
|
# icmp.type = 200
|
34
35
|
# icmp.checksum = 0x248a
|
35
|
-
# icmp.body
|
36
|
+
# icmp.body = 'this is a body'
|
36
37
|
# @author Sylvain Daubert
|
37
38
|
class ICMP < Base
|
38
39
|
# ICMP internet protocol number
|
@@ -51,7 +52,8 @@ module PacketGen
|
|
51
52
|
# @return [Integer]
|
52
53
|
define_attr :checksum, BinStruct::Int16
|
53
54
|
# @!attribute body
|
54
|
-
#
|
55
|
+
# ICMP body
|
56
|
+
# @return [BinStruct::String,Headerable]
|
55
57
|
define_attr :body, BinStruct::String
|
56
58
|
|
57
59
|
# Compute checksum and set +checksum+ field
|
@@ -61,9 +63,7 @@ module PacketGen
|
|
61
63
|
self.checksum = IP.reduce_checksum(sum)
|
62
64
|
end
|
63
65
|
end
|
64
|
-
|
65
66
|
self.add_class ICMP
|
66
|
-
|
67
67
|
IP.bind ICMP, protocol: ICMP::IP_PROTOCOL
|
68
68
|
end
|
69
69
|
end
|
@@ -15,30 +15,31 @@ module PacketGen
|
|
15
15
|
# | Type | Code | Checksum |
|
16
16
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
17
17
|
# A ICMPv6 header consists of:
|
18
|
-
# * a
|
19
|
-
# * a
|
20
|
-
# * a
|
21
|
-
# * and a
|
18
|
+
# * a {#type #type} field (+BinStruct::Int8+ type),
|
19
|
+
# * a {#code #code} field (+BinStruct::Int8+ type),
|
20
|
+
# * a {#checksum #checksum} field (+BinStruct::Int16+ type),
|
21
|
+
# * and a {#body #body}.
|
22
22
|
#
|
23
|
-
#
|
23
|
+
# @example Create a ICMPv6 header
|
24
24
|
# # standalone
|
25
25
|
# icmpv6 = PacketGen::Header::ICMPv6.new
|
26
26
|
# # in a packet
|
27
27
|
# pkt = PacketGen.gen('IPv6').add('ICMPv6')
|
28
28
|
# # access to ICMPv6 header
|
29
|
-
# pkt.icmpv6
|
29
|
+
# pkt.icmpv6.class # => PacketGen::Header::ICMPv6
|
30
30
|
#
|
31
|
-
#
|
31
|
+
# @example ICMPv6 attributes
|
32
|
+
# icmpv6 = PacketGen::Header::ICMPv6.new
|
32
33
|
# icmpv6.code = 0
|
33
34
|
# icmpv6.type = 200
|
34
35
|
# icmpv6.checksum = 0x248a
|
35
|
-
# icmpv6.body
|
36
|
+
# icmpv6.body = 'this is a body'
|
36
37
|
# @author Sylvain Daubert
|
37
38
|
class ICMPv6 < ICMP
|
38
39
|
# ICMPv6 internet protocol number
|
39
40
|
IP_PROTOCOL = 58
|
40
41
|
|
41
|
-
# Compute checksum and set +checksum+ field
|
42
|
+
# Compute IPV6-style checksum and set +checksum+ field
|
42
43
|
# @return [Integer]
|
43
44
|
def calc_checksum
|
44
45
|
sum = ip_header(self).pseudo_header_checksum
|
@@ -20,25 +20,29 @@ module PacketGen
|
|
20
20
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
21
21
|
#
|
22
22
|
# A IGMP header consists of:
|
23
|
-
# * a {#type} field (
|
24
|
-
# * a {#max_resp_time} field (
|
25
|
-
# * a {#checksum} field (
|
23
|
+
# * a {#type} field (+BinStruct::Int8Enum+ type),
|
24
|
+
# * a {#max_resp_time} field (+BinStruct::Int8+ type),
|
25
|
+
# * a {#checksum} field (+BinStruct::Int16+ type),
|
26
26
|
# * a {#group_addr} field ({Header::IP::Addr} type),
|
27
27
|
# * and a {#body} (unused for IGMPv2).
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# After adding a IGMP header to a packet, you have to call {#igmpize} to ensure
|
30
|
+
# resulting packet conforms to RFC 2236.
|
31
|
+
#
|
32
|
+
# @example Create a IGMP header
|
30
33
|
# # standalone
|
31
34
|
# igmp = PacketGen::Header::IGMP.new
|
32
35
|
# # in a packet
|
33
36
|
# pkt = PacketGen.gen('IP').add('IGMP')
|
34
37
|
# # access to IGMP header
|
35
|
-
# pkt.igmp
|
38
|
+
# pkt.igmp.class # => PacketGen::Header::IGMP
|
36
39
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
40
|
+
# @example IGMP attributes
|
41
|
+
# igmp = PacketGen::Header::IGMP.new
|
42
|
+
# igmp.type = 'MembershipQuery' # or 0x11
|
43
|
+
# igmp.max_resp_time = 20
|
44
|
+
# igmp.checksum = 0x248a
|
45
|
+
# igmp.group_addr = '224.0.0.1'
|
42
46
|
# @author Sylvain Daubert
|
43
47
|
# @since 2.4.0
|
44
48
|
class IGMP < Base
|
@@ -70,12 +74,14 @@ module PacketGen
|
|
70
74
|
# @return [IP::Addr]
|
71
75
|
define_attr :group_addr, IP::Addr, default: '0.0.0.0'
|
72
76
|
# @!attribute body
|
77
|
+
# IGMP body (not used in IGMPv2)
|
73
78
|
# @return [String,Base]
|
74
79
|
define_attr :body, BinStruct::String
|
75
80
|
|
76
81
|
# @api private
|
77
82
|
# @note This method is used internally by PacketGen and should not be
|
78
83
|
# directly called
|
84
|
+
# Define +#igmpize+ method onto +packet+. This method calls {#igmpize}.
|
79
85
|
def added_to_packet(packet)
|
80
86
|
igmp_idx = packet.headers.size
|
81
87
|
packet.instance_eval "def igmpize() @headers[#{igmp_idx}].igmpize; end" # def igmpize() @headers[2].igmpize; end
|
@@ -103,6 +109,11 @@ module PacketGen
|
|
103
109
|
# pkt.igmp.igmpize
|
104
110
|
# # second method
|
105
111
|
# pkt.igmpize
|
112
|
+
# @example
|
113
|
+
# pkt = PacketGen.gen('IP').add('IGMP', type: 'MembershipQuery', max_resp_time: 20, group_addr: '1.2.3.4')
|
114
|
+
# pkt.igmpize
|
115
|
+
# pkt.ip.ttl #=> 1
|
116
|
+
# pkt.ip.options.map(&:class) #=> [PacketGen::Header::IP::RA]
|
106
117
|
# @return [void]
|
107
118
|
def igmpize
|
108
119
|
iph = ip_header(self)
|
@@ -11,7 +11,7 @@ module PacketGen
|
|
11
11
|
class IGMPv3
|
12
12
|
# Class to handle IGMPv3 Group Records.
|
13
13
|
#
|
14
|
-
# A Group Record is a block of attributes
|
14
|
+
# A Group Record is a block of attributes containing information
|
15
15
|
# pertaining to the sender's membership in a single multicast group on
|
16
16
|
# the interface from which the Report is sent.
|
17
17
|
#
|
@@ -76,14 +76,19 @@ module PacketGen
|
|
76
76
|
define_attr :source_addr, IP::ArrayOfAddr,
|
77
77
|
builder: ->(h, t) { t.new(counter: h[:number_of_sources]) }
|
78
78
|
# @!attribute aux_data
|
79
|
+
# Not used in IGMPv3
|
79
80
|
# @return [String]
|
80
81
|
define_attr :aux_data, BinStruct::String,
|
81
82
|
builder: ->(h, t) { t.new(length_from: -> { h[:aux_data_len].to_i * 4 }) }
|
82
83
|
|
84
|
+
# Human-readable type
|
85
|
+
# @return [String]
|
83
86
|
def human_type
|
84
87
|
self[:type].to_human
|
85
88
|
end
|
86
89
|
|
90
|
+
# Human-readable description of a group record
|
91
|
+
# @return [String]
|
87
92
|
def to_human
|
88
93
|
"#{human_type}(ma:#{multicast_addr}|src:#{source_addr.to_human})"
|
89
94
|
end
|
@@ -94,7 +99,7 @@ module PacketGen
|
|
94
99
|
class GroupRecords < BinStruct::Array
|
95
100
|
set_of GroupRecord
|
96
101
|
|
97
|
-
# Separator used in
|
102
|
+
# Separator used in +#to_human+.
|
98
103
|
HUMAN_SEPARATOR = ';'
|
99
104
|
end
|
100
105
|
end
|
@@ -49,7 +49,7 @@ module PacketGen
|
|
49
49
|
# First 8-bit field, composed of {#resv}, {#flag_s} and {#qrv}
|
50
50
|
# @return [Integer]
|
51
51
|
# @!attribute resv
|
52
|
-
# 4-bit reserved field
|
52
|
+
# 4-bit reserved field
|
53
53
|
# @return [Integer]
|
54
54
|
# @!attribute flag_s
|
55
55
|
# 1-bit S flag (Suppress Router-Side Processing)
|
@@ -48,7 +48,7 @@ module PacketGen
|
|
48
48
|
class MR < Base
|
49
49
|
# @!attribute reserved
|
50
50
|
# 16-bit reserved field
|
51
|
-
#
|
51
|
+
# @return [Integer]
|
52
52
|
define_attr :reserved, BinStruct::Int16, default: 0
|
53
53
|
# @!attribute number_of_gr
|
54
54
|
# 16-bit Number of group records in {#group_records}
|
@@ -18,23 +18,24 @@ module PacketGen
|
|
18
18
|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
19
|
#
|
20
20
|
# A IGMP header consists of:
|
21
|
-
# * a {#type} field (
|
22
|
-
# * a {#max_resp_time} field (
|
23
|
-
# * a {#checksum} field (
|
24
|
-
# * and a {#body}, containing more fields (see below).
|
21
|
+
# * a {#type #type} field (+BinStruct::Int8Enum+ type),
|
22
|
+
# * a {#max_resp_time #max_resp_time} field (+BinStruct::Int8+ type),
|
23
|
+
# * a {#checksum #checksum} field (+BinStruct::Int16+ type),
|
24
|
+
# * and a {#body #body}, containing more fields (see below).
|
25
25
|
#
|
26
|
-
# A IGMPv3 header may have additionnal fields. These attributes
|
26
|
+
# A IGMPv3 header may have additionnal fields. These attributes are handled by
|
27
27
|
# additional headers (see {IGMPv3::MQ}).
|
28
28
|
#
|
29
|
-
#
|
29
|
+
# @example Create a IGMPv3 header
|
30
30
|
# # standalone
|
31
31
|
# igmp = PacketGen::Header::IGMPv3.new
|
32
32
|
# # in a packet
|
33
33
|
# pkt = PacketGen.gen('IP').add('IGMPv3')
|
34
34
|
# # access to IGMPv3 header
|
35
|
-
# pkt.
|
35
|
+
# pkt.igmpv3.class # => PacketGen::Header::IGMPv3
|
36
36
|
#
|
37
|
-
#
|
37
|
+
# @example IGMPv3 attributes
|
38
|
+
# igmp = PacketGen::Header::IGMPv3.new
|
38
39
|
# igmp.type = 'MembershipQuery' # or 0x11
|
39
40
|
# igmp.max_resp_time = 20
|
40
41
|
# igmp.checksum = 0x248a
|
@@ -50,14 +51,14 @@ module PacketGen
|
|
50
51
|
# igmp.max_resp_code #=> 9728 error due to encoding as a floating point value
|
51
52
|
#
|
52
53
|
# === IGMPv3 Membership Query
|
53
|
-
# With IGMPv3, a Membership Query packet has more attributes
|
54
|
+
# With IGMPv3, a Membership Query packet has more attributes than with IGMPv2. To
|
54
55
|
# handle those fields, an additional header should be used:
|
55
56
|
# pkt = PacketGen.gen('IP').add('IGMPv3', type: 'MembershipQuery').add('IGMPv3::MQ')
|
56
57
|
# pkt.igmpv3 #=> PacketGen::Header::IGMPv3
|
57
58
|
# pkt.igmpv3_mq #=> PacketGen::Header::IGMPv3::MQ
|
58
59
|
#
|
59
60
|
# === IGMPv3 Membership Report
|
60
|
-
# With IGMPv3, a Membership Report packet has more attributes
|
61
|
+
# With IGMPv3, a Membership Report packet has more attributes than with IGMPv2. To
|
61
62
|
# handle those fields, an additional header should be used:
|
62
63
|
# pkt = PacketGen.gen('IP').add('IGMPv3', type: 'MembershipQuery').add('IGMPv3::MR')
|
63
64
|
# pkt.igmpv3 #=> PacketGen::Header::IGMPv3
|
@@ -18,7 +18,7 @@ module PacketGen
|
|
18
18
|
# @return [Integer] IP address first byte
|
19
19
|
define_attr :a1, BinStruct::Int8
|
20
20
|
# @!attribute a2
|
21
|
-
# @return [Integer] IP address
|
21
|
+
# @return [Integer] IP address second byte
|
22
22
|
define_attr :a2, BinStruct::Int8
|
23
23
|
# @!attribute a3
|
24
24
|
# @return [Integer] IP address third byte
|
@@ -27,6 +27,7 @@ module PacketGen
|
|
27
27
|
# @return [Integer] IP address fourth byte
|
28
28
|
define_attr :a4, BinStruct::Int8
|
29
29
|
|
30
|
+
## Regex to match IPv4 addresses
|
30
31
|
IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
|
31
32
|
|
32
33
|
# Read a dotted address
|
@@ -51,7 +52,7 @@ module PacketGen
|
|
51
52
|
attributes.map { |f| self[f].to_i.to_s }.join('.')
|
52
53
|
end
|
53
54
|
|
54
|
-
# Addr as
|
55
|
+
# Addr as a 32-bit integer
|
55
56
|
# @return [Integer]
|
56
57
|
def to_i
|
57
58
|
(self.a1 << 24) | (self.a2 << 16) | (self.a3 << 8) |
|
@@ -64,6 +65,9 @@ module PacketGen
|
|
64
65
|
self.a1 >= 224 && self.a1 <= 239
|
65
66
|
end
|
66
67
|
|
68
|
+
# Check equality.
|
69
|
+
# Equal is other has same class and all attributes are equal.
|
70
|
+
# @return [Boolean]
|
67
71
|
def ==(other)
|
68
72
|
other.is_a?(self.class) &&
|
69
73
|
attributes.all? { |attr| self[attr].value == other[attr].value }
|
@@ -17,7 +17,11 @@ module PacketGen
|
|
17
17
|
# Push a IP address to the array
|
18
18
|
# @param [String,Addr] addr
|
19
19
|
# @return [self]
|
20
|
+
# @example
|
21
|
+
# array = PacketGen::Header::IP::ArrayOfAddr.new
|
22
|
+
# # #<< uses #push internally
|
20
23
|
# array << '192.168.1.12'
|
24
|
+
# array.push(PacketGen::Header::IP::Addr.new.from_human('192.18.1.13'))
|
21
25
|
def push(addr)
|
22
26
|
addr = Addr.new.from_human(addr) unless addr.is_a?(Addr)
|
23
27
|
super
|
@@ -46,7 +50,7 @@ module PacketGen
|
|
46
50
|
|
47
51
|
# @!attribute type
|
48
52
|
# 8-bit option type
|
49
|
-
#
|
53
|
+
# @return [Integer]
|
50
54
|
# @!attribute copied
|
51
55
|
# 1-bit copied flag from {#type} field
|
52
56
|
# @return [Integer]
|
@@ -60,15 +64,17 @@ module PacketGen
|
|
60
64
|
define_bit_attr :type, copied: 1, option_class: 2, number: 5
|
61
65
|
# @!attribute length
|
62
66
|
# 8-bit option length. If 0, there is no +length+ field in option
|
63
|
-
#
|
67
|
+
# @return [Integer]
|
64
68
|
define_attr :length, BinStruct::Int8, default: 0, optional: ->(h) { h.type > 1 }
|
65
69
|
# @!attribute data
|
66
70
|
# option data
|
67
|
-
#
|
71
|
+
# @return [String]
|
68
72
|
define_attr :data, BinStruct::String, optional: ->(h) { h.length > 2 },
|
69
73
|
builder: ->(h, t) { t.new(length_from: -> { h.length - 2 }) }
|
70
74
|
|
71
|
-
# @
|
75
|
+
# @private
|
76
|
+
# Return a cached hash associating type name to its value.
|
77
|
+
# @return [Hash{String => Integer}]
|
72
78
|
def self.types
|
73
79
|
return @types if defined? @types
|
74
80
|
|
@@ -83,6 +89,7 @@ module PacketGen
|
|
83
89
|
end
|
84
90
|
|
85
91
|
# Factory to build an option from its type
|
92
|
+
# @param [Hash] options
|
86
93
|
# @return [Option]
|
87
94
|
def self.build(options={})
|
88
95
|
type = options[:type]
|
@@ -96,6 +103,8 @@ module PacketGen
|
|
96
103
|
klass.new(options)
|
97
104
|
end
|
98
105
|
|
106
|
+
# Force type value for subclasses, if not specified
|
107
|
+
# @return [Option]
|
99
108
|
def initialize(options={})
|
100
109
|
options[:type] = class2type unless options[:type]
|
101
110
|
|
@@ -153,7 +162,7 @@ module PacketGen
|
|
153
162
|
remove_attr :data
|
154
163
|
|
155
164
|
# @!attribute pointer
|
156
|
-
# 8-bit
|
165
|
+
# 8-bit po+++inter on next address
|
157
166
|
# @return [Integer]
|
158
167
|
define_attr :pointer, BinStruct::Int8, default: 4
|
159
168
|
# @!attribute data
|
@@ -190,6 +199,8 @@ module PacketGen
|
|
190
199
|
# @return [Integer]
|
191
200
|
define_attr :id, BinStruct::Int16
|
192
201
|
|
202
|
+
# Return a human-readable string
|
203
|
+
# @return [String]
|
193
204
|
def to_human
|
194
205
|
super << ":#{self.id}"
|
195
206
|
end
|
@@ -204,6 +215,8 @@ module PacketGen
|
|
204
215
|
# @return [Integer]
|
205
216
|
define_attr :value, BinStruct::Int16, default: 0
|
206
217
|
|
218
|
+
# Return a human-readable string
|
219
|
+
# @return [String]
|
207
220
|
def to_human
|
208
221
|
super << ":#{self.value}"
|
209
222
|
end
|