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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/packetgen/deprecation.rb +7 -1
  4. data/lib/packetgen/header/arp.rb +6 -7
  5. data/lib/packetgen/header/asn1_base.rb +2 -1
  6. data/lib/packetgen/header/base.rb +27 -24
  7. data/lib/packetgen/header/bootp.rb +14 -14
  8. data/lib/packetgen/header/dhcp/option.rb +8 -8
  9. data/lib/packetgen/header/dhcp/options.rb +2 -2
  10. data/lib/packetgen/header/dhcp.rb +6 -7
  11. data/lib/packetgen/header/dhcpv6/duid.rb +1 -1
  12. data/lib/packetgen/header/dhcpv6/option.rb +37 -15
  13. data/lib/packetgen/header/dhcpv6/options.rb +3 -3
  14. data/lib/packetgen/header/dhcpv6/relay.rb +1 -0
  15. data/lib/packetgen/header/dhcpv6.rb +13 -14
  16. data/lib/packetgen/header/dns/name.rb +9 -8
  17. data/lib/packetgen/header/dns/opt.rb +3 -0
  18. data/lib/packetgen/header/dns/option.rb +7 -7
  19. data/lib/packetgen/header/dns/qdsection.rb +2 -2
  20. data/lib/packetgen/header/dns/question.rb +1 -0
  21. data/lib/packetgen/header/dns/rrsection.rb +2 -2
  22. data/lib/packetgen/header/dns.rb +76 -60
  23. data/lib/packetgen/header/dot11/control.rb +5 -5
  24. data/lib/packetgen/header/dot11/data.rb +11 -10
  25. data/lib/packetgen/header/dot11/element.rb +1 -1
  26. data/lib/packetgen/header/dot11/management.rb +18 -15
  27. data/lib/packetgen/header/dot11/sub_mngt.rb +22 -21
  28. data/lib/packetgen/header/dot11.rb +38 -38
  29. data/lib/packetgen/header/dot1q.rb +5 -4
  30. data/lib/packetgen/header/dot1x.rb +8 -8
  31. data/lib/packetgen/header/eap/fast.rb +3 -3
  32. data/lib/packetgen/header/eap/md5.rb +11 -3
  33. data/lib/packetgen/header/eap/tls.rb +9 -8
  34. data/lib/packetgen/header/eap/ttls.rb +13 -10
  35. data/lib/packetgen/header/eap.rb +58 -33
  36. data/lib/packetgen/header/eth.rb +26 -12
  37. data/lib/packetgen/header/gre.rb +26 -2
  38. data/lib/packetgen/header/http/headers.rb +6 -5
  39. data/lib/packetgen/header/http/request.rb +24 -16
  40. data/lib/packetgen/header/http/response.rb +22 -15
  41. data/lib/packetgen/header/icmp.rb +10 -10
  42. data/lib/packetgen/header/icmpv6.rb +10 -9
  43. data/lib/packetgen/header/igmp.rb +21 -10
  44. data/lib/packetgen/header/igmpv3/group_record.rb +7 -2
  45. data/lib/packetgen/header/igmpv3/mq.rb +1 -1
  46. data/lib/packetgen/header/igmpv3/mr.rb +1 -1
  47. data/lib/packetgen/header/igmpv3.rb +11 -10
  48. data/lib/packetgen/header/ip/addr.rb +6 -2
  49. data/lib/packetgen/header/ip/option.rb +18 -5
  50. data/lib/packetgen/header/ip.rb +52 -35
  51. data/lib/packetgen/header/ipv6/addr.rb +14 -13
  52. data/lib/packetgen/header/ipv6/extension.rb +9 -7
  53. data/lib/packetgen/header/ipv6/hop_by_hop.rb +26 -7
  54. data/lib/packetgen/header/ipv6.rb +31 -22
  55. data/lib/packetgen/header/llc.rb +20 -13
  56. data/lib/packetgen/header/mdns.rb +9 -2
  57. data/lib/packetgen/header/mld.rb +11 -9
  58. data/lib/packetgen/header/mldv2/mcast_address_record.rb +6 -1
  59. data/lib/packetgen/header/mldv2/mlq.rb +8 -8
  60. data/lib/packetgen/header/mldv2/mlr.rb +4 -4
  61. data/lib/packetgen/header/mldv2.rb +1 -1
  62. data/lib/packetgen/header/ospfv2/db_description.rb +10 -10
  63. data/lib/packetgen/header/ospfv2/hello.rb +11 -10
  64. data/lib/packetgen/header/ospfv2/ls_ack.rb +5 -6
  65. data/lib/packetgen/header/ospfv2/ls_request.rb +7 -6
  66. data/lib/packetgen/header/ospfv2/ls_update.rb +7 -7
  67. data/lib/packetgen/header/ospfv2/lsa.rb +33 -10
  68. data/lib/packetgen/header/ospfv2/lsa_header.rb +3 -2
  69. data/lib/packetgen/header/ospfv2.rb +31 -26
  70. data/lib/packetgen/header/ospfv3/db_description.rb +12 -13
  71. data/lib/packetgen/header/ospfv3/hello.rb +10 -9
  72. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +6 -2
  73. data/lib/packetgen/header/ospfv3/ls_ack.rb +5 -6
  74. data/lib/packetgen/header/ospfv3/ls_request.rb +10 -10
  75. data/lib/packetgen/header/ospfv3/ls_update.rb +7 -7
  76. data/lib/packetgen/header/ospfv3/lsa.rb +23 -9
  77. data/lib/packetgen/header/ospfv3/lsa_header.rb +3 -2
  78. data/lib/packetgen/header/ospfv3.rb +38 -34
  79. data/lib/packetgen/header/sctp/chunk.rb +38 -17
  80. data/lib/packetgen/header/sctp/error.rb +169 -197
  81. data/lib/packetgen/header/sctp/padded32.rb +3 -3
  82. data/lib/packetgen/header/sctp/parameter.rb +85 -132
  83. data/lib/packetgen/header/sctp.rb +14 -3
  84. data/lib/packetgen/header/snmp.rb +108 -7
  85. data/lib/packetgen/header/tcp/option.rb +7 -0
  86. data/lib/packetgen/header/tcp/options.rb +11 -3
  87. data/lib/packetgen/header/tcp.rb +33 -26
  88. data/lib/packetgen/header/tftp.rb +16 -10
  89. data/lib/packetgen/header/udp.rb +15 -13
  90. data/lib/packetgen/header.rb +19 -13
  91. data/lib/packetgen/headerable.rb +9 -3
  92. data/lib/packetgen/inspect.rb +2 -7
  93. data/lib/packetgen/packet.rb +94 -36
  94. data/lib/packetgen/pcapng/block.rb +2 -1
  95. data/lib/packetgen/pcapng/file.rb +41 -14
  96. data/lib/packetgen/pcapng/idb.rb +2 -1
  97. data/lib/packetgen/pcapng/shb.rb +2 -1
  98. data/lib/packetgen/pcapng/spb.rb +1 -1
  99. data/lib/packetgen/pcapng.rb +2 -0
  100. data/lib/packetgen/proto.rb +4 -0
  101. data/lib/packetgen/unknown_packet.rb +3 -3
  102. data/lib/packetgen/utils.rb +2 -1
  103. data/lib/packetgen/version.rb +1 -1
  104. data/lib/packetgen.rb +8 -2
  105. 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 (or nil).
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 string.
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 ({BinStruct::String}).
14
- # * the path ({BinStruct::String}).
15
- # * the version ({BinStruct::String}).
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
- # == Create a HTTP Request header
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
- # http_rqst = PacketGen::Header::HTTP::Request.new
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
- # == HTTP Request attributes
30
- # http_rqst.version = "HTTP/1.1"
31
- # http_rqst.verb = "GET"
32
- # http_rqst.path = "/meow.html"
33
- # http_rqst.headers = "Host: tcpdump.org" # string or
34
- # http_rqst.headers = { "Host": "tcpdump.org" } # even a hash
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 [PacketGen::HTTP::Request]
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 ({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}).
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
- # == Create a HTTP Response header
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
- # Note: When creating a HTTP Response packet, +sport+ and +dport+
28
- # attributes of TCP header are not set.
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 [BinStruct::String]
56
+ # @return [HTTP::Headers]
53
57
  define_attr :headers, HTTP::Headers
54
58
  # @!attribute body
55
- # @return [HTTP::PHeaders]
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 [PacketGen::HTTP::Response]
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 ({BinStruct::Int8} type),
19
- # * a {#code} field ({BinStruct::Int8} type),
20
- # * a {#checksum} field ({BinStruct::Int16} type),
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
- # == Create a ICMP header
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 # => PacketGen::Header::ICMP
29
+ # pkt.icmp.class # => PacketGen::Header::ICMP
30
30
  #
31
- # == ICMP attributes
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.read 'this is a 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
- # @return [BinStruct::String,Header::Base]
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 +type+ field ({BinStruct::Int8} type),
19
- # * a +code+ field ({BinStruct::Int8} type),
20
- # * a +checksum+ field ({BinStruct::Int16} type),
21
- # * and a +body+.
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
- # == Create a ICMPv6 header
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 # => PacketGen::Header::ICMPv6
29
+ # pkt.icmpv6.class # => PacketGen::Header::ICMPv6
30
30
  #
31
- # == ICMPv6 attributes
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.read 'this is a 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 ({BinStruct::Int8Enum} type),
24
- # * a {#max_resp_time} field ({BinStruct::Int8} type),
25
- # * a {#checksum} field ({BinStruct::Int16} type),
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
- # == Create a IGMP header
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 # => PacketGen::Header::IGMP
38
+ # pkt.igmp.class # => PacketGen::Header::IGMP
36
39
  #
37
- # == IGMP attributes
38
- # icmp.type = 'MembershipQuery' # or 0x11
39
- # icmp.max_resp_time = 20
40
- # icmp.checksum = 0x248a
41
- # icmp.group_addr = '224.0.0.1'
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.containing information
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 {#to_human}.
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 in
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
- # @return [Integer]
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 ({BinStruct::Int8Enum} type),
22
- # * a {#max_resp_time} field ({BinStruct::Int8} type),
23
- # * a {#checksum} field ({BinStruct::Int16} type),
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.are handled by
26
+ # A IGMPv3 header may have additionnal fields. These attributes are handled by
27
27
  # additional headers (see {IGMPv3::MQ}).
28
28
  #
29
- # == Create a IGMPv3 header
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.igmp # => PacketGen::Header::IGMPv3
35
+ # pkt.igmpv3.class # => PacketGen::Header::IGMPv3
36
36
  #
37
- # == IGMPv3 attributes
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.than with IGMPv2. To
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.than with IGMPv2. To
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 seconf byte
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 an integer
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
- # @return [Integer]
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
- # @return [Integer]
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
- # @return [String]
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
- # @return [Hash]
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 pointer on next address
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