packetgen 2.4.0 → 2.5.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 (127) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +13 -4
  3. data/lib/packetgen.rb +3 -1
  4. data/lib/packetgen/capture.rb +2 -0
  5. data/lib/packetgen/config.rb +1 -0
  6. data/lib/packetgen/header.rb +5 -0
  7. data/lib/packetgen/header/arp.rb +2 -0
  8. data/lib/packetgen/header/asn1_base.rb +2 -0
  9. data/lib/packetgen/header/base.rb +16 -0
  10. data/lib/packetgen/header/bootp.rb +2 -0
  11. data/lib/packetgen/header/crypto.rb +2 -0
  12. data/lib/packetgen/header/dhcp.rb +2 -0
  13. data/lib/packetgen/header/dhcp/option.rb +3 -0
  14. data/lib/packetgen/header/dhcp/options.rb +2 -0
  15. data/lib/packetgen/header/dhcpv6.rb +109 -0
  16. data/lib/packetgen/header/dhcpv6/duid.rb +147 -0
  17. data/lib/packetgen/header/dhcpv6/option.rb +391 -0
  18. data/lib/packetgen/header/dhcpv6/options.rb +29 -0
  19. data/lib/packetgen/header/dhcpv6/relay.rb +48 -0
  20. data/lib/packetgen/header/dns.rb +10 -2
  21. data/lib/packetgen/header/dns/name.rb +7 -0
  22. data/lib/packetgen/header/dns/opt.rb +6 -0
  23. data/lib/packetgen/header/dns/option.rb +7 -0
  24. data/lib/packetgen/header/dns/qdsection.rb +7 -1
  25. data/lib/packetgen/header/dns/question.rb +7 -0
  26. data/lib/packetgen/header/dns/rr.rb +7 -0
  27. data/lib/packetgen/header/dns/rrsection.rb +7 -0
  28. data/lib/packetgen/header/dot11.rb +4 -2
  29. data/lib/packetgen/header/dot11/control.rb +2 -0
  30. data/lib/packetgen/header/dot11/data.rb +2 -0
  31. data/lib/packetgen/header/dot11/element.rb +2 -0
  32. data/lib/packetgen/header/dot11/management.rb +2 -0
  33. data/lib/packetgen/header/dot11/sub_mngt.rb +2 -0
  34. data/lib/packetgen/header/dot1q.rb +2 -0
  35. data/lib/packetgen/header/dot1x.rb +3 -1
  36. data/lib/packetgen/header/eap.rb +3 -1
  37. data/lib/packetgen/header/eap/fast.rb +2 -0
  38. data/lib/packetgen/header/eap/md5.rb +2 -0
  39. data/lib/packetgen/header/eap/tls.rb +2 -0
  40. data/lib/packetgen/header/eap/ttls.rb +2 -0
  41. data/lib/packetgen/header/esp.rb +7 -0
  42. data/lib/packetgen/header/eth.rb +2 -0
  43. data/lib/packetgen/header/gre.rb +4 -9
  44. data/lib/packetgen/header/http/headers.rb +2 -0
  45. data/lib/packetgen/header/http/request.rb +3 -1
  46. data/lib/packetgen/header/http/response.rb +3 -1
  47. data/lib/packetgen/header/icmp.rb +4 -11
  48. data/lib/packetgen/header/icmpv6.rb +4 -11
  49. data/lib/packetgen/header/igmp.rb +4 -11
  50. data/lib/packetgen/header/igmpv3.rb +4 -11
  51. data/lib/packetgen/header/igmpv3/group_record.rb +2 -0
  52. data/lib/packetgen/header/igmpv3/mq.rb +2 -0
  53. data/lib/packetgen/header/igmpv3/mr.rb +2 -0
  54. data/lib/packetgen/header/ike.rb +13 -6
  55. data/lib/packetgen/header/ike/auth.rb +2 -0
  56. data/lib/packetgen/header/ike/cert.rb +2 -0
  57. data/lib/packetgen/header/ike/certreq.rb +2 -0
  58. data/lib/packetgen/header/ike/id.rb +2 -0
  59. data/lib/packetgen/header/ike/ke.rb +2 -0
  60. data/lib/packetgen/header/ike/nonce.rb +2 -0
  61. data/lib/packetgen/header/ike/notify.rb +7 -0
  62. data/lib/packetgen/header/ike/payload.rb +9 -0
  63. data/lib/packetgen/header/ike/sa.rb +11 -4
  64. data/lib/packetgen/header/ike/sk.rb +7 -0
  65. data/lib/packetgen/header/ike/ts.rb +2 -0
  66. data/lib/packetgen/header/ike/vendor_id.rb +2 -0
  67. data/lib/packetgen/header/ip.rb +48 -11
  68. data/lib/packetgen/header/ip/addr.rb +8 -0
  69. data/lib/packetgen/header/ip/option.rb +2 -0
  70. data/lib/packetgen/header/ip/options.rb +2 -0
  71. data/lib/packetgen/header/ipv6.rb +5 -3
  72. data/lib/packetgen/header/ipv6/addr.rb +8 -0
  73. data/lib/packetgen/header/ipv6/extension.rb +2 -0
  74. data/lib/packetgen/header/ipv6/hop_by_hop.rb +2 -0
  75. data/lib/packetgen/header/llc.rb +2 -0
  76. data/lib/packetgen/header/mld.rb +2 -0
  77. data/lib/packetgen/header/mldv2.rb +4 -2
  78. data/lib/packetgen/header/mldv2/mcast_address_record.rb +3 -1
  79. data/lib/packetgen/header/mldv2/mlq.rb +2 -0
  80. data/lib/packetgen/header/mldv2/mlr.rb +4 -2
  81. data/lib/packetgen/header/ospfv2.rb +249 -0
  82. data/lib/packetgen/header/ospfv2/db_description.rb +105 -0
  83. data/lib/packetgen/header/ospfv2/hello.rb +104 -0
  84. data/lib/packetgen/header/ospfv2/ls_ack.rb +55 -0
  85. data/lib/packetgen/header/ospfv2/ls_request.rb +90 -0
  86. data/lib/packetgen/header/ospfv2/ls_update.rb +72 -0
  87. data/lib/packetgen/header/ospfv2/lsa.rb +252 -0
  88. data/lib/packetgen/header/ospfv2/lsa_header.rb +122 -0
  89. data/lib/packetgen/header/ospfv3.rb +216 -0
  90. data/lib/packetgen/header/ospfv3/db_description.rb +114 -0
  91. data/lib/packetgen/header/ospfv3/hello.rb +104 -0
  92. data/lib/packetgen/header/ospfv3/ipv6_prefix.rb +103 -0
  93. data/lib/packetgen/header/ospfv3/ls_ack.rb +51 -0
  94. data/lib/packetgen/header/ospfv3/ls_request.rb +108 -0
  95. data/lib/packetgen/header/ospfv3/ls_update.rb +74 -0
  96. data/lib/packetgen/header/ospfv3/lsa.rb +252 -0
  97. data/lib/packetgen/header/ospfv3/lsa_header.rb +123 -0
  98. data/lib/packetgen/header/snmp.rb +2 -0
  99. data/lib/packetgen/header/tcp.rb +14 -14
  100. data/lib/packetgen/header/tcp/option.rb +7 -1
  101. data/lib/packetgen/header/tcp/options.rb +7 -0
  102. data/lib/packetgen/header/tftp.rb +2 -0
  103. data/lib/packetgen/header/udp.rb +6 -14
  104. data/lib/packetgen/inspect.rb +5 -1
  105. data/lib/packetgen/packet.rb +3 -1
  106. data/lib/packetgen/pcapng.rb +2 -0
  107. data/lib/packetgen/pcapng/block.rb +2 -0
  108. data/lib/packetgen/pcapng/epb.rb +2 -0
  109. data/lib/packetgen/pcapng/file.rb +2 -0
  110. data/lib/packetgen/pcapng/idb.rb +2 -0
  111. data/lib/packetgen/pcapng/shb.rb +2 -0
  112. data/lib/packetgen/pcapng/spb.rb +2 -0
  113. data/lib/packetgen/pcapng/unknown_block.rb +2 -0
  114. data/lib/packetgen/proto.rb +2 -0
  115. data/lib/packetgen/types/array.rb +3 -0
  116. data/lib/packetgen/types/cstring.rb +3 -1
  117. data/lib/packetgen/types/enum.rb +2 -0
  118. data/lib/packetgen/types/fields.rb +8 -4
  119. data/lib/packetgen/types/int.rb +3 -1
  120. data/lib/packetgen/types/int_string.rb +2 -0
  121. data/lib/packetgen/types/oui.rb +2 -0
  122. data/lib/packetgen/types/string.rb +3 -0
  123. data/lib/packetgen/types/tlv.rb +8 -0
  124. data/lib/packetgen/utils.rb +6 -4
  125. data/lib/packetgen/utils/arp_spoofer.rb +2 -0
  126. data/lib/packetgen/version.rb +3 -1
  127. metadata +25 -3
@@ -0,0 +1,104 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # This class handles {OSPFv3 OSPFv3} HELLO packets payload. The HELLO
13
+ # payload has the following format:
14
+ # 0 1 2 3
15
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | Interface ID |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | Rtr Priority | Options |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # | HelloInterval | RouterDeadInterval |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # | Designated Router ID |
24
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ # | Backup Designated Router ID |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # | Neighbor ID |
28
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
+ # | ... |
30
+ # A HELLO payload consists of:
31
+ # * a {#interface_id} field ({Types::Int32}),
32
+ # * a {#priority} field ({Types::Int8}),
33
+ # * an {#options} field ({Types::Int24}),
34
+ # * a {#hello_interval} field ({Types::Int16}),
35
+ # * a {#dead_interval} field ({Types::Int16}),
36
+ # * a {#designated_router} field ({IP::Addr}),
37
+ # * a {#backup_designated_router} field ({IP::Addr}),
38
+ # * a {#neighbors} array containing neighbors as {IP::Addr}.
39
+ #
40
+ # == Create a HELLO payload
41
+ # # standalone
42
+ # hello = PacketGen::Header::OSPFv3::Hello.new
43
+ # # in a packet
44
+ # pkt = PacketGen.gen('IPv6', src: source_ip).add('OSPFv3').add('OSPFv3::Hello')
45
+ # # make IPv6 header correct for OSPF
46
+ # pkt.ospfize
47
+ # # access to Hello payload
48
+ # pkt.ospfv3_hello # => PacketGen::Header::OSPFv3::Hello
49
+ #
50
+ # == HELLO attributes
51
+ # hello.interface_id = 1
52
+ # hello.priority = 1
53
+ # # set options. Options may also be set one by one with #v6_opt, #e_opt,
54
+ # # #n_opt, #r_opt and #dc_opt
55
+ # hello.options = 0x33
56
+ # hello.hello_interval = 10
57
+ # hello.dead_interval = 300
58
+ # hello.designated_router = '0.0.0.1'
59
+ # hello.backup_designated_router = '0.0.0.2'
60
+ # # set neighbors identifiers
61
+ # hello.neighbors << '1.1.1.1'
62
+ # hello.neighbors << '2.2.2.2'
63
+ # @author Sylvain Daubert
64
+ class Hello < Base
65
+ # @!attribute interface_id
66
+ # The network mask associated with this interface.
67
+ # @return [String]
68
+ define_field :interface_id, Types::Int32
69
+ # @!attribute priority
70
+ # This router's Router Priority. Used in (Backup) Designated
71
+ # Router election.
72
+ # @return [Integer]
73
+ define_field :priority, Types::Int8
74
+ # @!macro define_ospfv3_options
75
+ OSPFv3.define_options(self)
76
+ # @!attribute hello_interval
77
+ # The number of seconds between this router's Hello packets.
78
+ # @return [Integer]
79
+ define_field :hello_interval, Types::Int16
80
+ # @!attribute dead_interval
81
+ # The number of seconds before declaring a silent router down.
82
+ # @return [Integer]
83
+ define_field :dead_interval, Types::Int16
84
+ # @!attribute designated_router
85
+ # The identity of the Designated Router for this network, in the
86
+ # view of the sending router.
87
+ # @return [String]
88
+ define_field :designated_router, IP::Addr
89
+ # @!attribute backup_designated_router
90
+ # The identity of the Backup Designated Router for this network,
91
+ # in the view of the sending router.
92
+ # @return [String]
93
+ define_field :backup_designated_router, IP::Addr
94
+ # @!attribute neighbors
95
+ # Array of neighbors
96
+ # @return [IP::ArrayOfAddr]
97
+ define_field :neighbors, IP::ArrayOfAddr
98
+ end
99
+ end
100
+
101
+ self.add_class OSPFv3::Hello
102
+ OSPFv3.bind_header OSPFv3::Hello, type: OSPFv3::TYPES['HELLO']
103
+ end
104
+ end
@@ -0,0 +1,103 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # Array of 32-bit words.
13
+ # @author Sylvain Daubert
14
+ class ArrayOfInt32 < Types::Array
15
+ set_of Types::Int32
16
+ end
17
+
18
+ # This class handles IPv6 prefixes, as defined in RFC 5340 §A.4.1.
19
+ # A IPv6 prefix consists of:
20
+ # * a 8-bit {#length} field (length of the prefix, in bits),
21
+ # * a 8-bit {#options} field, giving prefix capabilities,
22
+ # * a 16-bit {#reserved} field (but it may be used in some LSA),
23
+ # * and an array of 32-bit words to encode prefix itself ({#prefix}). This
24
+ # array consumes ((PrefixLength + 31) / 32) 32-bit words.
25
+ # @author Sylvain Daubert
26
+ class IPv6Prefix < Types::Fields
27
+ # @!attribute length
28
+ # Prefix length, in bits
29
+ # @return [Integer]
30
+ define_field :length, Types::Int8
31
+ # @!attribute options
32
+ # Prefix capabilities. See also capability bits: {#dn_opt}, {#p_opt},
33
+ # {#la_opt} and {#nu_opt}.
34
+ # @return [Options]
35
+ define_field :options, Types::Int8
36
+ # @!attribute reserved
37
+ # Reserved field in most of LSA types.
38
+ # @return [Integer]
39
+ define_field :reserved, Types::Int16
40
+ # @!attribute prefix
41
+ # IPv6 Prefix as an array of 32-bit words
42
+ # @return [Prefix]
43
+ define_field :prefix, ArrayOfInt32
44
+
45
+ # @!attribute dn_opt
46
+ # This bit controls an inter-area-prefix-LSAs or AS-external-LSAs
47
+ # re-advertisement in a VPN environment.
48
+ # @return [Boolean]
49
+ # @!attribute p_opt
50
+ # The "propagate" bit. Set on NSSA area prefixes that should be
51
+ # readvertised by the translating NSSA area border.
52
+ # @return [Boolean]
53
+ # @!attribute la_opt
54
+ # The "local address" capability bit. If set, the prefix is
55
+ # actually an IPv6 interface address of the Advertising Router.
56
+ # @return [Boolean]
57
+ # @!attribute nu_opt
58
+ # The "no unicast" capability bit. If set, the prefix should be
59
+ # excluded from IPv6 unicast calculations.
60
+ # @return [Boolean]
61
+ define_bit_fields_on :options, :zz, 3, :dn_opt, :p_opt, :z, :la_opt, :nu_opt
62
+
63
+ # Get human-readable prefix
64
+ # @return [String]
65
+ def to_human
66
+ ary = prefix.map(&:to_i).map do |v|
67
+ "#{((v>>16) & 0xffff).to_s(16)}:#{(v & 0xffff).to_s(16)}"
68
+ end
69
+ pfx = ary.join(':')
70
+ pfx += '::' if prefix.size < (128/32)
71
+ "#{IPAddr.new(pfx).to_s}/#{length}"
72
+ end
73
+
74
+ # Set prefix from a human-readable string. This method cannot set
75
+ # {#options} field.
76
+ # @param [String] str
77
+ # @return [void]
78
+ def from_human(str)
79
+ pfx, len = str.split('/')
80
+ len = (len || 128).to_i
81
+ addr = IPv6::Addr.new.from_human(pfx)
82
+ ary_size = (len + 31) / 32
83
+ ary = addr.to_a[0...ary_size*2]
84
+ self.prefix.clear
85
+ ary.each_with_index do |v, i|
86
+ if i % 2 == 0
87
+ self.prefix << v
88
+ else
89
+ self.prefix.last.value = (self.prefix.last.to_i << 16) | v.to_i
90
+ end
91
+ end
92
+ self.length = len
93
+ end
94
+ end
95
+
96
+ # Array of {IPv6Prefix}
97
+ # @author Sylvain Daubert
98
+ class ArrayOfIPv6Prefix < Types::Array
99
+ set_of IPv6Prefix
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,51 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # This class handles {OSPFv3 OSPFv3} Link State Acknownledgment packets
13
+ # payload. The LSAck payload has the following format:
14
+ # 0 1 2 3
15
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | |
18
+ # +- +-+
19
+ # | LSAs |
20
+ # +- +-+
21
+ # | ... |
22
+ #
23
+ # This paylod is implemented with only one field:
24
+ # * {#lsas}, an {ArrayOfLSA} object.
25
+ #
26
+ # == Create a LSAck payload
27
+ # # standalone
28
+ # lsack = PacketGen::Header::OSPFv3::LSAck.new
29
+ # # in a packet
30
+ # pkt = PacketGen.gen('IPv6', src: source_ip).add('OSPFv3').add('OSPFv3::LSAck')
31
+ # # access to LSAck payload
32
+ # lasck = pkt.ospfv3_lsack # => PacketGen::Header::OSPFv3::LSAck
33
+ #
34
+ # == Adding LSA headers to a LSAck payload
35
+ # lsack.lsas << { type: 'Router', age: 40, link_state_id: '0.0.0.1', advertising_router: '1.1.1.1', sequence_number: 42, checksum: 0x1234, length: 56 }
36
+ # # a header may also be set from an existing lsa
37
+ # lasck.lsas << existing_lsa.to_lsa_header
38
+ # @author Sylvain Daubert
39
+ class LSAck < Base
40
+ # @!attribute lsas
41
+ # Array of {LSA LSAs}
42
+ # @return [ArrayOfLSA]
43
+ define_field :lsas, ArrayOfLSA,
44
+ builder: ->(h, t) { t.new(only_headers: true) }
45
+ end
46
+ end
47
+
48
+ self.add_class OSPFv3::LSAck
49
+ OSPFv3.bind_header OSPFv3::LSAck, type: OSPFv3::TYPES['LS_ACK']
50
+ end
51
+ end
@@ -0,0 +1,108 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # This class handle LSA requests, as used in {LSRequest} payloads.
13
+ # The LSA request payload has the following format:
14
+ # 0 1 2 3
15
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | 0 | LS Type |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | Link State ID |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # | Advertising Router |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ #
24
+ # It is composed of:
25
+ # * a 16-bit {#reserved} field,
26
+ # * a 16-bit {#type} field,
27
+ # * a 32-bit {#link_state_id} field,
28
+ # * and a 32-bit {#advertising_router} field.
29
+ # @author Sylvain Daubert
30
+ class LSR < Types::Fields
31
+ # @!attribute reserved
32
+ # reserved field.
33
+ # @return [Integer]
34
+ define_field :reserved, Types::Int16, default: 0
35
+ # @!attribute type
36
+ # The type of the LSA to request.
37
+ # @return [Integer]
38
+ define_field :type, Types::Int16Enum, enum: LSAHeader::TYPES
39
+ # @!attribute link_state_id
40
+ # This field identifies the portion of the internet environment
41
+ # that is being described by the LSA to request.
42
+ # @return [String]
43
+ define_field :link_state_id, IP::Addr
44
+ # @!attribute advertising_router
45
+ # The Router ID of the requested LSA.
46
+ # @return [String]
47
+ define_field :advertising_router, IP::Addr
48
+
49
+ # Get human-readable type
50
+ # @return [String]
51
+ def human_type
52
+ self[:type].to_human
53
+ end
54
+
55
+ # @return [String]
56
+ def to_human
57
+ "LSR<#{human_type},#{link_state_id},#{advertising_router}>"
58
+ end
59
+ end
60
+
61
+ # This class defines a specialized {Types::Array array} to handle series
62
+ # of {LSR LSRs}.
63
+ # @author Sylvain Daubert
64
+ class ArrayOfLSR < Types::Array
65
+ set_of LSR
66
+ end
67
+
68
+ # This class handles {OSPFv3 OSPFv3} Link State Request packets
69
+ # payload. The LSR payload has the following format:
70
+ # 0 1 2 3
71
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
72
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
73
+ # | 0 | LS Type |
74
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75
+ # | Link State ID |
76
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77
+ # | Advertising Router |
78
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79
+ # | ... |
80
+ #
81
+ # This paylod is implemented as a unique field: {#lsrs}, which is an
82
+ # {ArrayOfLSR} object.
83
+ #
84
+ # == Create a LSRequest payload
85
+ # # standalone
86
+ # lsr = PacketGen::Header::OSPFv3::LSRequest.new
87
+ # # in a packet
88
+ # pkt = PacketGen.gen('IPv6', src: source_ip).add('OSPFv3').add('OSPFv3::LSRequest')
89
+ # # make IPv6 header correct for OSPF
90
+ # pkt.ospfize
91
+ # # access to LSRequest payload
92
+ # pkt.ospfv3_lsrequest # => PacketGen::Header::OSPFv3::LSRequest
93
+ #
94
+ # == Add LSA requests to a LSRequest
95
+ # lsr.lsrs << { type: 'Router', link_state_id: '0.0.0.1', advertising_router: '1.1.1.1'}
96
+ # @author Sylvain Daubert
97
+ class LSRequest < Base
98
+ # @!attribute lsrs
99
+ # Array of {LSR}
100
+ # @return [ArrayOfLSR]
101
+ define_field :lsrs, ArrayOfLSR
102
+ end
103
+ end
104
+
105
+ self.add_class OSPFv3::LSRequest
106
+ OSPFv3.bind_header OSPFv3::LSRequest, type: OSPFv3::TYPES['LS_REQUEST']
107
+ end
108
+ end
@@ -0,0 +1,74 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # This class handles {OSPFv3 OSPFv3} Link State Update packets
13
+ # payload. The LSU payload has the following format:
14
+ # 0 1 2 3
15
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | # LSAs |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | |
20
+ # +- +-+
21
+ # | LSAs |
22
+ # +- +-+
23
+ # | ... |
24
+ #
25
+ # This paylod is implemented with two fields:
26
+ # * {#lsas_count}, a {Types::Int32} field,
27
+ # * and {#lsas}, an {ArrayOfLSA} object.
28
+ #
29
+ # == Create a LSUpdate payload
30
+ # # standalone
31
+ # lsu = PacketGen::Header::OSPFv3::LSUpdate.new
32
+ # # in a packet
33
+ # pkt = PacketGen.gen('IPv6', src: source_ip).add('OSPFv3').add('OSPFv3::LSUpdate')
34
+ # # make IPv6 header correct for OSPF
35
+ # pkt.ospfize
36
+ # # access to LSUpdate payload
37
+ # lsu = pkt.ospfv3_lsupdate # => PacketGen::Header::OSPFv3::LSUpdate
38
+ #
39
+ # == Add LSAs to a LSUpdate payload
40
+ # Adding LSAs with {ArrayOfLSA#<< ArrayOfLSA#<<} automagically update
41
+ # {#lsas_count}. To not update it, use {ArrayOfLSA#push ArrayOfLSA#push}.
42
+ # lsu.lsas << { type: 'Router', age: 40, link_state_id: '0.0.0.1', advertising_router: '1.1.1.1', sequence_number: 42 }
43
+ # lsu.lsas_count #=> 1
44
+ # # add a link to Router LSA
45
+ # lsu.lsas.first.links << { type: 1, metric: 10, interface_id: 1, neighbor_interface_id: 2, neighbor_router_id: '2.2.2.2'}
46
+ # @author Sylvain Daubert
47
+ class LSUpdate < Base
48
+ # @!attribute lsas_count
49
+ # Count of LSAs included in this update
50
+ # @return [Integer]
51
+ define_field :lsas_count, Types::Int32
52
+ # @!attribute lsas
53
+ # Array of {LSA LSAs}
54
+ # @return [ArrayOfLSA]
55
+ define_field :lsas, ArrayOfLSA,
56
+ builder: ->(h, t) { t.new(counter: h[:lsas_count]) }
57
+
58
+ # Calculate checksums of all LSAs
59
+ # @return [void]
60
+ def calc_checksum
61
+ lsas.each { |lsa| lsa.calc_checksum }
62
+ end
63
+
64
+ # Calculate length of all LSAs
65
+ def calc_length
66
+ lsas.each { |lsa| lsa.calc_length }
67
+ end
68
+ end
69
+ end
70
+
71
+ self.add_class OSPFv3::LSUpdate
72
+ OSPFv3.bind_header OSPFv3::LSUpdate, type: OSPFv3::TYPES['LS_UPDATE']
73
+ end
74
+ end
@@ -0,0 +1,252 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Header
10
+ class OSPFv3
11
+
12
+ # This class handles links in a {LSARouter OSPFv3 LSA router payload}.
13
+ # @author Sylvain Daubert
14
+ class Link < Types::Fields
15
+ # @!attribute type
16
+ # @return [Integer]
17
+ define_field :type, Types::Int8
18
+ # @!attribute reserved
19
+ # @return [Integer]
20
+ define_field :reserved, Types::Int8, default: 0
21
+ # @!attribute metric
22
+ # @return [Integer]
23
+ define_field :metric, Types::Int16
24
+ # @!attribute interface_id
25
+ # @return [Integer]
26
+ define_field :interface_id, Types::Int32
27
+ # @!attribute neighbor_interface_id
28
+ # @return [Integer]
29
+ define_field :neighbor_interface_id, Types::Int32
30
+ # @!attribute neighbor_router_id
31
+ # @return [String]
32
+ define_field :neighbor_router_id, IP::Addr
33
+
34
+ # @return [String]
35
+ def to_human
36
+ "Link<type:#{type},metric:#{metric},id:#{interface_id}," \
37
+ "neighbor_id:#{neighbor_interface_id},neighbor_router:#{neighbor_router_id}>"
38
+ end
39
+ end
40
+
41
+ # This class defines a specialized {Types::Array array} to handle series
42
+ # of {Link Links}.
43
+ # @author Sylvain Daubert
44
+ class ArrayOfLink < Types::Array
45
+ set_of Link
46
+ end
47
+
48
+ # This class handles unsupported {OSPFv3 OSPFv3} LSA payloads.
49
+ # A LSA payload is a {LSAHeader} with a {#body} field.
50
+ # @author Sylvain Daubert
51
+ class LSA < LSAHeader
52
+ # @!attribute body
53
+ # LSA body
54
+ # @return [String]
55
+ define_field :body, Types::String,
56
+ builder: ->(h,t) { t.new(length_from: ->() { h.length - 20 }) }
57
+ end
58
+
59
+ # This class handles OSPFv3 LSA Router payloads.
60
+ #
61
+ # A LSA router payload is composed of:
62
+ # * a header (see methods inherited from {LSAHeader}),
63
+ # * a 8-bit flag word {#flags} ({Types::Int8}),
64
+ # * a 24-bit {#options} field ({Types::Int24}),
65
+ # * and an array of {#links} ({ArrayOfLink}).
66
+ # @author Sylvain Daubert
67
+ class LSARouter < LSAHeader
68
+ # @attribute flags
69
+ # 8-bit flag word
70
+ # @return [Integer]
71
+ define_field :flags, Types::Int8
72
+ # @!macro define_ospfv3_options
73
+ OSPFv3.define_options(self)
74
+ # @attribute links
75
+ # @return [ArrayOfLink]
76
+ define_field :links, ArrayOfLink
77
+
78
+ # @!attribute nt_flag
79
+ # @return [Boolean]
80
+ # @!attribute v_flag
81
+ # @return [Boolean]
82
+ # @!attribute e_flag
83
+ # @return [Boolean]
84
+ # @!attribute b_flag
85
+ # @return [Boolean]
86
+ define_bit_fields_on :flags, :zz, 3, :nt_flag, :x_flag, :v_flag, :e_flag,
87
+ :b_flag
88
+ end
89
+
90
+ # This class handles OSPFv3 LSA Network payloads.
91
+ #
92
+ # A LSA network payload is composed of:
93
+ # * a header (see methods inherited from {LSAHeader}),
94
+ # * a 8-bit {#reserved} field,
95
+ # * a 24-bit {#options} field,
96
+ # * and an array of router IDs ({#routers}, {IP::ArrayOfAddr}).
97
+ # @author Sylvain Daubert
98
+ class LSANetwork < LSAHeader
99
+ # @!attribute reserved
100
+ # @return [Integer]
101
+ define_field :reserved, Types::Int8
102
+ # @!macro define_ospfv3_options
103
+ OSPFv3.define_options(self)
104
+ # @!attribute routers
105
+ # List of routers attached to the link.
106
+ # @return [IP::ArrayOfAddr]
107
+ define_field :routers, IP::ArrayOfAddr
108
+ end
109
+
110
+ # This class handles OSPFv3 LSA Intra-Area-Prefix payloads.
111
+ #
112
+ # An Intra-Area-Prefix payloads is composed of:
113
+ # * a 16-bit {#prefix_count} field ({Types::Int16}),
114
+ # * a 16-bit {#ref_ls_type} field ({Types::Int16Enum}),
115
+ # * a 32-bit {#ref_link_state_id} ({IP::Addr}),
116
+ # * a 32-bit {#ref_advertising_router} ({IP::Addr}),
117
+ # * and an array of {IPv6Prefix} ({#prefixes}, {ArrayOfIPv6Prefix}). In
118
+ # this array, {IPv6Prefix#reserved} is used as +metric+ value.
119
+ # @author Sylvain Daubert
120
+ class LSAIntraAreaPrefix < LSAHeader
121
+ # @!attribute prefix_count
122
+ # The number of IPv6 address prefixes contained in the LSA.
123
+ # @return [Integer]
124
+ define_field :prefix_count, Types::Int16
125
+ # @!attribute ref_ls_type
126
+ # Used to identify the router-LSA or network-LSA with which the IPv6
127
+ # address prefixes should be associated, in association with
128
+ # {#ref_link_state_id} and {#ref_advertising_router}.
129
+ # @return [Integer]
130
+ define_field :ref_ls_type, Types::Int16Enum, enum: TYPES
131
+ # @!attribute ref_link_state_id
132
+ # Used to identify the router-LSA or network-LSA with which the IPv6
133
+ # address prefixes should be associated, in association with
134
+ # {#ref_ls_type} and {#ref_advertising_router}.
135
+ # @return [String]
136
+ define_field :ref_link_state_id, IP::Addr
137
+ # @!attribute ref_advertising_router
138
+ # Used to identify the router-LSA or network-LSA with which the IPv6
139
+ # address prefixes should be associated, in association with
140
+ # {#ref_link_state_id} and {#ref_ls_type}.
141
+ # @return [String]
142
+ define_field :ref_advertising_router, IP::Addr
143
+ # @!attribute prefixes
144
+ # Array of {IPv6Prefix}. Note for this LSA, {IPv6Prefix#reserved} is
145
+ # used as +metric+ value.
146
+ # @return [ArrayOfIPv6Prefix]
147
+ define_field :prefixes, ArrayOfIPv6Prefix,
148
+ builder: ->(h, t) { t.new(counter: h[:prefix_count]) }
149
+ end
150
+
151
+ # This class handles OSPFv3 LSA Link payloads.
152
+ #
153
+ # A Link payloads is composed of:
154
+ # * a 8-bit {#router_priority} field ({Types::Int8}),
155
+ # * a 24-bit {#options} field ({Types::Int24}),
156
+ # * a 128-bit IPv6 {#interface_addr} ({IPv6::Addr}),
157
+ # * a 32-bit {#prefix_count} field ({Types::Int32}),
158
+ # * and an array of {IPv6Prefix} ({#prefixes}, {ArrayOfIPv6Prefix}).
159
+ # @author Sylvain Daubert
160
+ class LSALink < LSAHeader
161
+ # @!attribute router_priority
162
+ # The Router Priority of the interface attaching the originating
163
+ # router to the link.
164
+ # @return [Integer]
165
+ define_field :router_priority, Types::Int8
166
+ # @!macro define_ospfv3_options
167
+ OSPFv3.define_options(self)
168
+ # @!attribute interface_addr
169
+ # The originating router's link-local interface address on the link.
170
+ # @return [String]
171
+ define_field :interface_addr, IPv6::Addr
172
+ # @!attribute prefix_count
173
+ # The number of IPv6 address prefixes contained in the LSA.
174
+ # @return [Integer]
175
+ define_field :prefix_count, Types::Int32
176
+ # @!attribute prefixes
177
+ # List of IPv6 prefixes to be associated with the link.
178
+ # @return [ArrayOfIPv6Prefix]
179
+ define_field :prefixes, ArrayOfIPv6Prefix
180
+ end
181
+
182
+ # This class defines a specialized {Types::Array array} to handle series
183
+ # of {LSA LSAs} or {LSAHeader LSAHeaders}. It recognizes known LSA types
184
+ # and infers correct type.
185
+ # @author Sylvain Daubert
186
+ class ArrayOfLSA < Types::Array
187
+ set_of LSA
188
+
189
+ # @param [Hash] options
190
+ # @option options [Types::Int] counter Int object used as a counter for this set
191
+ # @option options [Boolean] only_headers if +true+, only {LSAHeader LSAHeaders}
192
+ # will be added to this array.
193
+ def initialize(options={})
194
+ super
195
+ @only_headers = options[:only_headers] || false
196
+ end
197
+
198
+ # Populate object from a string
199
+ # @param [String] str
200
+ # @return [self]
201
+ def read(str)
202
+ clear
203
+ return self if str.nil?
204
+ return self if @counter and @counter.to_i == 0
205
+ force_binary str
206
+ while str.length > 0
207
+ lsa = LSAHeader.new.read(str)
208
+ if !@only_headers
209
+ klass = get_lsa_class_by_human_type(lsa.human_type)
210
+ lsa = klass.new.read(str[0...lsa.length])
211
+ end
212
+ self.push lsa
213
+ str.slice!(0, lsa.sz)
214
+ break if @counter and self.size == @counter.to_i
215
+ end
216
+ self
217
+ end
218
+
219
+ private
220
+
221
+ def record_from_hash(hsh)
222
+ unless hsh.has_key? :type
223
+ raise ArgumentError, "hash should have :type key"
224
+ end
225
+
226
+ klass = if @only_headers
227
+ LSAHeader
228
+ else
229
+ case hsh[:type]
230
+ when String
231
+ get_lsa_class_by_human_type(hsh[:type])
232
+ when Integer
233
+ get_lsa_class_by_human_type(LSAHeader::TYPES.key(hsh[:type]))
234
+ else
235
+ LSA
236
+ end
237
+ end
238
+ klass.new(hsh)
239
+ end
240
+
241
+ def get_lsa_class_by_human_type(htype)
242
+ klassname = "LSA#{htype.to_s.gsub(/-/, '')}"
243
+ if OSPFv3.const_defined? klassname
244
+ OSPFv3.const_get klassname
245
+ else
246
+ LSA
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end