packetgen 3.3.3 → 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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -22
  3. data/lib/packetgen/capture.rb +2 -2
  4. data/lib/packetgen/config.rb +0 -1
  5. data/lib/packetgen/deprecation.rb +14 -8
  6. data/lib/packetgen/header/arp.rb +17 -18
  7. data/lib/packetgen/header/asn1_base.rb +2 -1
  8. data/lib/packetgen/header/base.rb +42 -40
  9. data/lib/packetgen/header/bootp.rb +35 -37
  10. data/lib/packetgen/header/dhcp/option.rb +21 -21
  11. data/lib/packetgen/header/dhcp/options.rb +3 -3
  12. data/lib/packetgen/header/dhcp.rb +8 -9
  13. data/lib/packetgen/header/dhcpv6/duid.rb +16 -16
  14. data/lib/packetgen/header/dhcpv6/option.rb +83 -61
  15. data/lib/packetgen/header/dhcpv6/options.rb +4 -4
  16. data/lib/packetgen/header/dhcpv6/relay.rb +6 -5
  17. data/lib/packetgen/header/dhcpv6.rb +17 -18
  18. data/lib/packetgen/header/dns/name.rb +21 -16
  19. data/lib/packetgen/header/dns/opt.rb +5 -2
  20. data/lib/packetgen/header/dns/option.rb +14 -14
  21. data/lib/packetgen/header/dns/qdsection.rb +3 -3
  22. data/lib/packetgen/header/dns/question.rb +7 -8
  23. data/lib/packetgen/header/dns/rr.rb +56 -43
  24. data/lib/packetgen/header/dns/rrsection.rb +6 -6
  25. data/lib/packetgen/header/dns.rb +103 -90
  26. data/lib/packetgen/header/dot11/control.rb +12 -12
  27. data/lib/packetgen/header/dot11/data.rb +25 -24
  28. data/lib/packetgen/header/dot11/element.rb +4 -4
  29. data/lib/packetgen/header/dot11/management.rb +21 -18
  30. data/lib/packetgen/header/dot11/sub_mngt.rb +40 -53
  31. data/lib/packetgen/header/dot11.rb +117 -122
  32. data/lib/packetgen/header/dot1q.rb +12 -13
  33. data/lib/packetgen/header/dot1x.rb +13 -13
  34. data/lib/packetgen/header/eap/fast.rb +4 -4
  35. data/lib/packetgen/header/eap/md5.rb +16 -8
  36. data/lib/packetgen/header/eap/tls.rb +18 -19
  37. data/lib/packetgen/header/eap/ttls.rb +22 -21
  38. data/lib/packetgen/header/eap.rb +73 -48
  39. data/lib/packetgen/header/eth.rb +41 -27
  40. data/lib/packetgen/header/gre.rb +33 -11
  41. data/lib/packetgen/header/http/headers.rb +7 -6
  42. data/lib/packetgen/header/http/request.rb +38 -29
  43. data/lib/packetgen/header/http/response.rb +35 -27
  44. data/lib/packetgen/header/http/verbs.rb +1 -3
  45. data/lib/packetgen/header/icmp.rb +14 -14
  46. data/lib/packetgen/header/icmpv6.rb +10 -9
  47. data/lib/packetgen/header/igmp.rb +26 -15
  48. data/lib/packetgen/header/igmpv3/group_record.rb +18 -13
  49. data/lib/packetgen/header/igmpv3/mq.rb +16 -18
  50. data/lib/packetgen/header/igmpv3/mr.rb +5 -5
  51. data/lib/packetgen/header/igmpv3.rb +12 -11
  52. data/lib/packetgen/header/ip/addr.rb +19 -15
  53. data/lib/packetgen/header/ip/option.rb +47 -36
  54. data/lib/packetgen/header/ip/options.rb +1 -1
  55. data/lib/packetgen/header/ip.rb +77 -95
  56. data/lib/packetgen/header/ipv6/addr.rb +28 -27
  57. data/lib/packetgen/header/ipv6/extension.rb +13 -11
  58. data/lib/packetgen/header/ipv6/hop_by_hop.rb +32 -13
  59. data/lib/packetgen/header/ipv6.rb +42 -35
  60. data/lib/packetgen/header/llc.rb +28 -21
  61. data/lib/packetgen/header/mdns.rb +10 -3
  62. data/lib/packetgen/header/mld.rb +15 -13
  63. data/lib/packetgen/header/mldv2/mcast_address_record.rb +17 -12
  64. data/lib/packetgen/header/mldv2/mlq.rb +22 -24
  65. data/lib/packetgen/header/mldv2/mlr.rb +8 -8
  66. data/lib/packetgen/header/mldv2.rb +1 -1
  67. data/lib/packetgen/header/ospfv2/db_description.rb +17 -18
  68. data/lib/packetgen/header/ospfv2/hello.rb +18 -17
  69. data/lib/packetgen/header/ospfv2/ls_ack.rb +6 -7
  70. data/lib/packetgen/header/ospfv2/ls_request.rb +14 -13
  71. data/lib/packetgen/header/ospfv2/ls_update.rb +9 -9
  72. data/lib/packetgen/header/ospfv2/lsa.rb +79 -60
  73. data/lib/packetgen/header/ospfv2/lsa_header.rb +12 -11
  74. data/lib/packetgen/header/ospfv2.rb +49 -46
  75. data/lib/packetgen/header/ospfv3/db_description.rb +20 -22
  76. data/lib/packetgen/header/ospfv3/hello.rb +17 -16
  77. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +22 -20
  78. data/lib/packetgen/header/ospfv3/ls_ack.rb +7 -8
  79. data/lib/packetgen/header/ospfv3/ls_request.rb +18 -18
  80. data/lib/packetgen/header/ospfv3/ls_update.rb +10 -10
  81. data/lib/packetgen/header/ospfv3/lsa.rb +62 -51
  82. data/lib/packetgen/header/ospfv3/lsa_header.rb +12 -11
  83. data/lib/packetgen/header/ospfv3.rb +54 -52
  84. data/lib/packetgen/header/sctp/chunk.rb +80 -56
  85. data/lib/packetgen/header/sctp/error.rb +174 -202
  86. data/lib/packetgen/header/sctp/padded32.rb +3 -3
  87. data/lib/packetgen/header/sctp/parameter.rb +89 -136
  88. data/lib/packetgen/header/sctp.rb +19 -8
  89. data/lib/packetgen/header/snmp.rb +108 -7
  90. data/lib/packetgen/header/tcp/option.rb +52 -39
  91. data/lib/packetgen/header/tcp/options.rb +13 -5
  92. data/lib/packetgen/header/tcp.rb +83 -65
  93. data/lib/packetgen/header/tftp.rb +31 -25
  94. data/lib/packetgen/header/udp.rb +21 -19
  95. data/lib/packetgen/header.rb +23 -18
  96. data/lib/packetgen/headerable.rb +21 -5
  97. data/lib/packetgen/inspect.rb +3 -8
  98. data/lib/packetgen/packet.rb +146 -71
  99. data/lib/packetgen/pcap.rb +15 -4
  100. data/lib/packetgen/pcapng/block.rb +20 -18
  101. data/lib/packetgen/pcapng/epb.rb +13 -15
  102. data/lib/packetgen/pcapng/file.rb +44 -111
  103. data/lib/packetgen/pcapng/idb.rb +11 -12
  104. data/lib/packetgen/pcapng/shb.rb +15 -16
  105. data/lib/packetgen/pcapng/spb.rb +9 -11
  106. data/lib/packetgen/pcapng/unknown_block.rb +6 -17
  107. data/lib/packetgen/pcapng.rb +6 -4
  108. data/lib/packetgen/pcaprub_wrapper.rb +17 -1
  109. data/lib/packetgen/proto.rb +5 -1
  110. data/lib/packetgen/unknown_packet.rb +5 -5
  111. data/lib/packetgen/utils/arp_spoofer.rb +18 -19
  112. data/lib/packetgen/utils.rb +4 -3
  113. data/lib/packetgen/version.rb +1 -1
  114. data/lib/packetgen.rb +12 -5
  115. metadata +29 -38
  116. data/lib/packetgen/types/abstract_tlv.rb +0 -278
  117. data/lib/packetgen/types/array.rb +0 -287
  118. data/lib/packetgen/types/cstring.rb +0 -109
  119. data/lib/packetgen/types/enum.rb +0 -171
  120. data/lib/packetgen/types/fieldable.rb +0 -66
  121. data/lib/packetgen/types/fields.rb +0 -622
  122. data/lib/packetgen/types/int.rb +0 -473
  123. data/lib/packetgen/types/int_string.rb +0 -102
  124. data/lib/packetgen/types/length_from.rb +0 -54
  125. data/lib/packetgen/types/oui.rb +0 -52
  126. data/lib/packetgen/types/string.rb +0 -97
  127. data/lib/packetgen/types/tlv.rb +0 -161
  128. data/lib/packetgen/types.rb +0 -26
@@ -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 ({Types::String}).
14
- # * the status code ({Types::String}).
15
- # * the status message ({Types::String}).
16
- # * associated http headers ({HTTP::Headers}).
17
- # * the actual http payload body ({Types::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"
@@ -36,23 +37,28 @@ module PacketGen
36
37
  # http_resp.headers = { "Host": "tcpdump.org" } # even a hash
37
38
  #
38
39
  # @author Kent 'picat' Gruber
40
+ # @author LemonTree55
39
41
  class Response < Base
40
42
  # @!attribute version
41
- # @return [Types::String]
42
- define_field :version, Types::String, default: 'HTTP/1.1'
43
+ # HTTP version
44
+ # @return [BinStruct::String]
45
+ define_attr :version, BinStruct::String, default: 'HTTP/1.1'
43
46
  # @!attribute status_code
44
- # @return [Types::String]
45
- define_field :status_code, Types::String
47
+ # Response status code
48
+ # @return [BinStruct::String]
49
+ define_attr :status_code, BinStruct::String
46
50
  # @!attribute status_mesg
47
- # @return [Types::String]
48
- define_field :status_mesg, Types::String
51
+ # Response status message
52
+ # @return [BinStruct::String]
53
+ define_attr :status_mesg, BinStruct::String
49
54
  # @!attribute headers
50
55
  # associated http/1.1 headers
51
- # @return [Types::String]
52
- define_field :headers, HTTP::Headers
56
+ # @return [HTTP::Headers]
57
+ define_attr :headers, HTTP::Headers
53
58
  # @!attribute body
54
- # @return [HTTP::PHeaders]
55
- define_field :body, Types::String
59
+ # Response body
60
+ # @return [BinStruct::String]
61
+ define_attr :body, BinStruct::String
56
62
 
57
63
  # @param [Hash] options
58
64
  # @option options [String] :version
@@ -61,12 +67,12 @@ module PacketGen
61
67
  # @option options [String] :body
62
68
  # @option options [Hash] :headers
63
69
  def initialize(options={})
64
- super(options)
70
+ super
65
71
  self.headers ||= options[:headers]
66
72
  end
67
73
 
68
74
  # Read in the HTTP portion of the packet, and parse it.
69
- # @return [PacketGen::HTTP::Response]
75
+ # @return [self]
70
76
  def read(str)
71
77
  headers, data = collect_headers_and_data(str)
72
78
 
@@ -79,6 +85,8 @@ module PacketGen
79
85
  self
80
86
  end
81
87
 
88
+ # May be parsed as a HTTP response if version is +HTTP/1.x+.
89
+ # @return [Boolean]
82
90
  def parse?
83
91
  version.start_with?('HTTP/1.')
84
92
  end
@@ -125,9 +133,9 @@ module PacketGen
125
133
  first_line = headers.shift.split
126
134
  return if first_line.size < 3
127
135
 
128
- self[:version].read first_line[0]
129
- self[:status_code].read first_line[1]
130
- self[:status_mesg].read first_line[2..].join(' ')
136
+ self[:version].read(first_line[0])
137
+ self[:status_code].read(first_line[1])
138
+ self[:status_mesg].read(first_line[2..].join(' '))
131
139
  end
132
140
 
133
141
  def raise_on_bad_version_status
@@ -9,10 +9,8 @@
9
9
  module PacketGen
10
10
  module Header
11
11
  # @since 2.2.0
12
+ # @author Kent 'picat' Gruber
12
13
  module HTTP
13
- # @abstract Collection of useful HTTP verbs.
14
- # @author Kent 'picat' Gruber
15
-
16
14
  # Valid HTTP Verbs
17
15
  VERBS = %w[GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATCH].freeze
18
16
 
@@ -15,24 +15,25 @@ module PacketGen
15
15
  # | Type | Code | Checksum |
16
16
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
17
  # A ICMP header consists of:
18
- # * a {#type} field ({Types::Int8} type),
19
- # * a {#code} field ({Types::Int8} type),
20
- # * a {#checksum} field ({Types::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
@@ -41,18 +42,19 @@ module PacketGen
41
42
  # @!attribute type
42
43
  # 8-bit ICMP type
43
44
  # @return [Integer]
44
- define_field :type, Types::Int8
45
+ define_attr :type, BinStruct::Int8
45
46
  # @!attribute code
46
47
  # 8-bit ICMP code
47
48
  # @return [Integer]
48
- define_field :code, Types::Int8
49
+ define_attr :code, BinStruct::Int8
49
50
  # @!attribute checksum
50
51
  # 16-bit ICMP checksum
51
52
  # @return [Integer]
52
- define_field :checksum, Types::Int16
53
+ define_attr :checksum, BinStruct::Int16
53
54
  # @!attribute body
54
- # @return [Types::String,Header::Base]
55
- define_field :body, Types::String
55
+ # ICMP body
56
+ # @return [BinStruct::String,Headerable]
57
+ define_attr :body, BinStruct::String
56
58
 
57
59
  # Compute checksum and set +checksum+ field
58
60
  # @return [Integer]
@@ -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 ({Types::Int8} type),
19
- # * a +code+ field ({Types::Int8} type),
20
- # * a +checksum+ field ({Types::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 ({Types::Int8Enum} type),
24
- # * a {#max_resp_time} field ({Types::Int8} type),
25
- # * a {#checksum} field ({Types::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
@@ -56,26 +60,28 @@ module PacketGen
56
60
  # @!attribute type
57
61
  # 8-bit IGMP Type
58
62
  # @return [Integer]
59
- define_field :type, Types::Int8Enum, enum: TYPES
63
+ define_attr :type, BinStruct::Int8Enum, enum: TYPES
60
64
  # @!attribute max_resp_time
61
65
  # 8-bit IGMP Max Response Time
62
66
  # @return [Integer]
63
- define_field :max_resp_time, Types::Int8
67
+ define_attr :max_resp_time, BinStruct::Int8
64
68
  # @!attribute checksum
65
69
  # 16-bit IGMP Checksum
66
70
  # @return [Integer]
67
- define_field :checksum, Types::Int16
71
+ define_attr :checksum, BinStruct::Int16
68
72
  # @!attribute group_addr
69
73
  # IP Group address
70
74
  # @return [IP::Addr]
71
- define_field :group_addr, IP::Addr, default: '0.0.0.0'
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
- define_field :body, Types::String
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 fields 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
  #
@@ -40,8 +40,8 @@ module PacketGen
40
40
  # | |
41
41
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
42
  # @author Sylvain Daubert
43
- class GroupRecord < Types::Fields
44
- include Types::Fieldable
43
+ class GroupRecord < BinStruct::Struct
44
+ include BinStruct::Structable
45
45
 
46
46
  # Known record types
47
47
  RECORD_TYPES = {
@@ -56,34 +56,39 @@ module PacketGen
56
56
  # @!attribute type
57
57
  # 8-bit record type
58
58
  # @return [Integer]
59
- define_field :type, Types::Int8Enum, enum: RECORD_TYPES
59
+ define_attr :type, BinStruct::Int8Enum, enum: RECORD_TYPES
60
60
  # @!attribute aux_data_len
61
61
  # 8-bit length of of the Auxiliary Data field ({#aux_data}), in unit of
62
62
  # 32-bit words
63
63
  # @return [Integer]
64
- define_field :aux_data_len, Types::Int8, default: 0
64
+ define_attr :aux_data_len, BinStruct::Int8, default: 0
65
65
  # @!attribute number_of_sources
66
66
  # 16-bit Number of source addresses in {#source_addr}
67
67
  # @return [Integer]
68
- define_field :number_of_sources, Types::Int16, default: 0
68
+ define_attr :number_of_sources, BinStruct::Int16, default: 0
69
69
  # @!attribute multicast_addr
70
70
  # IP multicast address to which this Group Record pertains
71
71
  # @return [IP::Addr]
72
- define_field :multicast_addr, IP::Addr, default: '0.0.0.0'
72
+ define_attr :multicast_addr, IP::Addr, default: '0.0.0.0'
73
73
  # @!attribute source_addr
74
74
  # Array of source addresses
75
75
  # @return [IP::ArrayOfAddr]
76
- define_field :source_addr, IP::ArrayOfAddr,
77
- builder: ->(h, t) { t.new(counter: h[:number_of_sources]) }
76
+ define_attr :source_addr, IP::ArrayOfAddr,
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
- define_field :aux_data, Types::String,
81
- builder: ->(h, t) { t.new(length_from: -> { h[:aux_data_len].to_i * 4 }) }
81
+ define_attr :aux_data, BinStruct::String,
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
@@ -91,10 +96,10 @@ module PacketGen
91
96
 
92
97
  # Class to handle series of {GroupRecord}.
93
98
  # @author Sylvain Daubert
94
- class GroupRecords < Types::Array
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
@@ -31,7 +31,7 @@ module PacketGen
31
31
  # | Source Address [N] |
32
32
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33
33
  #
34
- # Fields are:
34
+ # Struct are:
35
35
  # * 32-bit {#group_addr} field ({Header::IP::Addr} type),
36
36
  # * 4-bit {#resv}, a reserved field,
37
37
  # * 1-bit {#flag_s} (Suppress Router-Side Processing),
@@ -44,36 +44,34 @@ module PacketGen
44
44
  # @!attribute group_addr
45
45
  # IP Group address
46
46
  # @return [IP::Addr]
47
- define_field :group_addr, IP::Addr, default: '0.0.0.0'
47
+ define_attr :group_addr, IP::Addr, default: '0.0.0.0'
48
48
  # @!attribute u8
49
49
  # First 8-bit field, composed of {#resv}, {#flag_s} and {#qrv}
50
50
  # @return [Integer]
51
- define_field :u8, Types::Int8
51
+ # @!attribute resv
52
+ # 4-bit reserved field
53
+ # @return [Integer]
54
+ # @!attribute flag_s
55
+ # 1-bit S flag (Suppress Router-Side Processing)
56
+ # @return [Integer]
57
+ # @!attribute qrv
58
+ # 3-bit Querier's Robustness Variable
59
+ # @return [Integer]
60
+ define_bit_attr :u8, resv: 4, flag_s: 1, qrv: 3
52
61
  # @!attribute qqic
53
62
  # 8-bit QQIC
54
63
  # @return [Integer,Float]
55
- define_field :qqic, Types::Int8
64
+ define_attr :qqic, BinStruct::Int8
56
65
  # @!attribute number_of_sources
57
66
  # 16-bit Number of Sources in {#source_addr}
58
67
  # @return [Integer]
59
- define_field :number_of_sources, Types::Int16
68
+ define_attr :number_of_sources, BinStruct::Int16
60
69
 
61
70
  # @!attribute source_addr
62
71
  # Array of IP source addresses
63
72
  # @return [IP::ArrayOfAddr]
64
- define_field :source_addr, IP::ArrayOfAddr,
65
- builder: ->(h, t) { t.new(counter: h[:number_of_sources]) }
66
-
67
- # @!attribute resv
68
- # 4-bit reserved field in
69
- # @return [Integer]
70
- # @!attribute flag_s
71
- # 1-bit S flag (Suppress Router-Side Processing)
72
- # @return [Boolean]
73
- # @!attribute qrv
74
- # 3-bit Querier's Robustness Variable
75
- # @return [Integer]
76
- define_bit_fields_on :u8, :resv, 4, :flag_s, :qrv, 3
73
+ define_attr :source_addr, IP::ArrayOfAddr,
74
+ builder: ->(h, t) { t.new(counter: h[:number_of_sources]) }
77
75
 
78
76
  undef qqic, qqic=
79
77
 
@@ -48,18 +48,18 @@ module PacketGen
48
48
  class MR < Base
49
49
  # @!attribute reserved
50
50
  # 16-bit reserved field
51
- # @return [Integer]
52
- define_field :reserved, Types::Int16, default: 0
51
+ # @return [Integer]
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}
55
55
  # @return [Integer]
56
- define_field :number_of_gr, Types::Int16, default: 0
56
+ define_attr :number_of_gr, BinStruct::Int16, default: 0
57
57
 
58
58
  # @!attribute group_records
59
59
  # Array of group records
60
60
  # @return [GroupRecords]
61
- define_field :group_records, GroupRecords,
62
- builder: ->(h, t) { t.new(counter: h[:number_of_gr]) }
61
+ define_attr :group_records, GroupRecords,
62
+ builder: ->(h, t) { t.new(counter: h[:number_of_gr]) }
63
63
  end
64
64
  end
65
65
 
@@ -18,23 +18,24 @@ module PacketGen
18
18
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
19
  #
20
20
  # A IGMP header consists of:
21
- # * a {#type} field ({Types::Int8Enum} type),
22
- # * a {#max_resp_time} field ({Types::Int8} type),
23
- # * a {#checksum} field ({Types::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 fields 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 fields 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 fields 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
@@ -71,7 +72,7 @@ module PacketGen
71
72
  'MembershipReport' => 0x22,
72
73
  }.freeze
73
74
 
74
- remove_field :group_addr
75
+ remove_attr :group_addr
75
76
 
76
77
  # Encode value for IGMPv3 Max Resp Code and QQIC.
77
78
  # Value may be encoded as a float, so some error may occur.
@@ -11,23 +11,24 @@ module PacketGen
11
11
  class IP
12
12
  # IP address, as a group of 4 bytes
13
13
  # @author Sylvain Daubert
14
- class Addr < Types::Fields
15
- include Types::Fieldable
14
+ class Addr < BinStruct::Struct
15
+ include BinStruct::Structable
16
16
 
17
17
  # @!attribute a1
18
18
  # @return [Integer] IP address first byte
19
- define_field :a1, Types::Int8
19
+ define_attr :a1, BinStruct::Int8
20
20
  # @!attribute a2
21
- # @return [Integer] IP address seconf byte
22
- define_field :a2, Types::Int8
21
+ # @return [Integer] IP address second byte
22
+ define_attr :a2, BinStruct::Int8
23
23
  # @!attribute a3
24
24
  # @return [Integer] IP address third byte
25
- define_field :a3, Types::Int8
25
+ define_attr :a3, BinStruct::Int8
26
26
  # @!attribute a4
27
27
  # @return [Integer] IP address fourth byte
28
- define_field :a4, Types::Int8
28
+ define_attr :a4, BinStruct::Int8
29
29
 
30
- IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.freeze
30
+ ## Regex to match IPv4 addresses
31
+ IPV4_ADDR_REGEX = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
31
32
 
32
33
  # Read a dotted address
33
34
  # @param [String] str
@@ -37,10 +38,10 @@ module PacketGen
37
38
 
38
39
  m = str.match(IPV4_ADDR_REGEX)
39
40
  if m
40
- self[:a1].read m[1].to_i
41
- self[:a2].read m[2].to_i
42
- self[:a3].read m[3].to_i
43
- self[:a4].read m[4].to_i
41
+ self[:a1].from_human(m[1].to_i)
42
+ self[:a2].from_human(m[2].to_i)
43
+ self[:a3].from_human(m[3].to_i)
44
+ self[:a4].from_human(m[4].to_i)
44
45
  end
45
46
  self
46
47
  end
@@ -48,10 +49,10 @@ module PacketGen
48
49
  # Addr in human readable form (dotted format)
49
50
  # @return [String]
50
51
  def to_human
51
- fields.map { |f| self[f].to_i.to_s }.join('.')
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,9 +65,12 @@ 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
- fields.all? { |attr| self[attr].value == other[attr].value }
73
+ attributes.all? { |attr| self[attr].value == other[attr].value }
70
74
  end
71
75
  end
72
76
  end