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 OSPFv2
11
+
12
+ # This class handles {OSPFv2 OSPFv2} 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
+ # | Network Mask |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | HelloInterval | Options | Rtr Pri |
20
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21
+ # | RouterDeadInterval |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # | Designated Router |
24
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ # | Backup Designated Router |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # | Neighbor |
28
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29
+ # | ... |
30
+ # A HELLO payload consists of:
31
+ # * a {#network_mask} field ({IP::Addr}),
32
+ # * a {#hello_interval} field ({Types::Int16}),
33
+ # * an {#options} field ({Types::Int8}),
34
+ # * a {#priority} field ({Types::Int8}),
35
+ # * a {#dead_interval} field ({Types::Int32}),
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::OSPFv2::Hello.new
43
+ # # in a packet
44
+ # pkt = PacketGen.gen('IP', src: source_ip).add('OSPFv2').add('OSPFv2::Hello')
45
+ # # make IP header correct for OSPF
46
+ # pkt.ospfize
47
+ # # access to Hello payload
48
+ # pkt.ospfv2_hello # => PacketGen::Header::OSPFv2::Hello
49
+ #
50
+ # == HELLO attributes
51
+ # hello.network_mask = '255.255.255.0'
52
+ # hello.hello_interval = 10
53
+ # hello.options = 0
54
+ # hello.priority = 1
55
+ # hello.dead_interval = 300
56
+ # hello.designated_router = '10.0.0.1'
57
+ # hello.backup_designated_router = '0.0.0.0'
58
+ # # set neighbors identifiers
59
+ # hello.neighbors << '10.0.1.1'
60
+ # hello.neighbors << '10.0.2.1'
61
+ # @author Sylvain Daubert
62
+ class Hello < Base
63
+ # @!attribute network_mask
64
+ # The network mask associated with this interface.
65
+ # @return [String]
66
+ define_field :network_mask, IP::Addr
67
+ # @!attribute hello_interval
68
+ # The number of seconds between this router's Hello packets.
69
+ # @return [Integer]
70
+ define_field :hello_interval, Types::Int16
71
+
72
+ # @!macro define_options
73
+ OSPFv2.define_options(self)
74
+
75
+ # @!attribute priority
76
+ # This router's Router Priority. Used in (Backup) Designated
77
+ # Router election.
78
+ # @return [Integer]
79
+ define_field :priority, Types::Int8
80
+ # @!attribute dead_interval
81
+ # The number of seconds before declaring a silent router down.
82
+ # @return [Integer]
83
+ define_field :dead_interval, Types::Int32
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 OSPFv2::Hello
102
+ OSPFv2.bind_header OSPFv2::Hello, type: OSPFv2::TYPES['HELLO']
103
+ end
104
+ end
@@ -0,0 +1,55 @@
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 OSPFv2
11
+
12
+ # This class handles {OSPFv2 OSPFv2} LS Acknowledgment packets payload.
13
+ # The LS Acknowledgment 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
+ # | |
20
+ # +- An LSA Header -+
21
+ # | |
22
+ # +- -+
23
+ # | |
24
+ # +- -+
25
+ # | |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # | ... |
28
+ # This paylod is implemented as a unique field: {#lsas}, which is an
29
+ # {ArrayOfLSAHeader} object.
30
+ #
31
+ # == Create a LSAck payload
32
+ # # standalone
33
+ # lsack = PacketGen::Header::OSPFv2::LSAck.new
34
+ # # in a packet
35
+ # pkt = PacketGen.gen('IP', src: source_ip).add('OSPFv2').add('OSPFv2::LSAck')
36
+ # # access to LSAck payload
37
+ # lasck = pkt.ospfv2_lsack # => PacketGen::Header::OSPFv2::LSAck
38
+ #
39
+ # == Adding LSA headers to a LSAck payload
40
+ # 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 }
41
+ # # a header may also be set from an existing lsa
42
+ # lasck.lsas << existing_lsa.to_lsa_header
43
+ # @author Sylvain Daubert
44
+ class LSAck < Base
45
+ # @!attribute lsas
46
+ # Array of LSA headers
47
+ # @return [ArrayOfLSAHeader]
48
+ define_field :lsas, ArrayOfLSA, builder: ->(h, t) { t.new(only_headers: true) }
49
+ end
50
+ end
51
+
52
+ self.add_class OSPFv2::LSAck
53
+ OSPFv2.bind_header OSPFv2::LSAck, type: OSPFv2::TYPES['LS_ACK']
54
+ end
55
+ end
@@ -0,0 +1,90 @@
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 OSPFv2
11
+
12
+ # This class handle a LS request, which is composed 3 {Types::Int32} fields:
13
+ # * {#type},
14
+ # * {#link_state_id},
15
+ # * and {#advertising_router}.
16
+ # @author Sylvain Daubert
17
+ class LSR < Types::Fields
18
+ # @!attribute type
19
+ # The type of the LSA to request.
20
+ # @return [Integer]
21
+ define_field :type, Types::Int32Enum, enum: LSAHeader::TYPES
22
+ # @!attribute link_state_id
23
+ # This field identifies the portion of the internet environment
24
+ # that is being described by the LSA to request.
25
+ # @return [String]
26
+ define_field :link_state_id, IP::Addr
27
+ # @!attribute advertising_router
28
+ # The Router ID of the requested LSA.
29
+ # @return [String]
30
+ define_field :advertising_router, IP::Addr
31
+
32
+ # Get human-readable type
33
+ # @return [String]
34
+ def human_type
35
+ self[:type].to_human
36
+ end
37
+
38
+ # @return [String]
39
+ def to_human
40
+ "LSR<#{human_type},#{link_state_id},#{advertising_router}>"
41
+ end
42
+ end
43
+
44
+ # This class defines a specialized {Types::Array array} to handle series
45
+ # of {LSR LSRs}.
46
+ # @author Sylvain Daubert
47
+ class ArrayOfLSR < Types::Array
48
+ set_of LSR
49
+ end
50
+
51
+ # This class handles {OSPFv2 OSPFv2} Link State Request packets
52
+ # payload. The LSR payload has the following format:
53
+ # 0 1 2 3
54
+ # 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
55
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
+ # | LS type |
57
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
+ # | Link State ID |
59
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
+ # | Advertising Router |
61
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
+ # | ... |
63
+ # This paylod is implemented as a unique field: {#lsrs}, which is an
64
+ # {ArrayOfLSR} object.
65
+ #
66
+ # == Create a LSRequest payload
67
+ # # standalone
68
+ # lsr = PacketGen::Header::OSPFv2::LSRequest.new
69
+ # # in a packet
70
+ # pkt = PacketGen.gen('IP', src: source_ip).add('OSPFv2').add('OSPFv2::LSRequest')
71
+ # # make IP header correct for OSPF
72
+ # pkt.ospfize
73
+ # # access to LSRequest payload
74
+ # pkt.ospfv2_lsrequest # => PacketGen::Header::OSPFv2::LSRequest
75
+ #
76
+ # == Add LSA requests to a LSRequest
77
+ # lsr.lsrs << { type: 'Router', link_state_id: '0.0.0.1', advertising_router: '1.1.1.1'}
78
+ # @author Sylvain Daubert
79
+ class LSRequest < Base
80
+ # @!attribute lsrs
81
+ # Array of {LSR}
82
+ # @return [ArrayOfLSR]
83
+ define_field :lsrs, ArrayOfLSR
84
+ end
85
+ end
86
+
87
+ self.add_class OSPFv2::LSRequest
88
+ OSPFv2.bind_header OSPFv2::LSRequest, type: OSPFv2::TYPES['LS_REQUEST']
89
+ end
90
+ end
@@ -0,0 +1,72 @@
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 OSPFv2
11
+
12
+ # This class handles {OSPFv2 OSPFv2} 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
+ # This paylod is implemented with two fields:
25
+ # * {#lsas_count}, a {Types::Int32} field,
26
+ # * and {#lsas}, an {ArrayOfLSA} object.
27
+ #
28
+ # == Create a LSUpdate payload
29
+ # # standalone
30
+ # lsu = PacketGen::Header::OSPFv2::LSUpdate.new
31
+ # # in a packet
32
+ # pkt = PacketGen.gen('IP', src: source_ip).add('OSPFv2').add('OSPFv2::LSUpdate')
33
+ # # make IP header correct for OSPF
34
+ # pkt.ospfize
35
+ # # access to LSUpdate payload
36
+ # lsu = pkt.ospfv2_lsupdate # => PacketGen::Header::OSPFv2::LSUpdate
37
+ #
38
+ # == Add LSAs to a LSUpdate payload
39
+ # Adding LSAs with {ArrayOfLSA#<< ArrayOfLSA#<<} automagically update
40
+ # {#lsas_count}. To not update it, use {ArrayOfLSA#push ArrayOfLSA#push}.
41
+ # lsu.lsas << { type: 'Router', age: 40, link_state_id: '0.0.0.1', advertising_router: '1.1.1.1', sequence_number: 42 }
42
+ # lsu.lsas_count #=> 1
43
+ # # add a link to Router LSA
44
+ # lsu.lsas.first.links << { type: 1, metric: 10, id: '1.1.1.1' }
45
+ # @author Sylvain Daubert
46
+ class LSUpdate < Base
47
+ # @!attribute lsas_count
48
+ # Count of LSAs included in this update
49
+ # @return [Integer]
50
+ define_field :lsas_count, Types::Int32
51
+ # @!attribute lsas
52
+ # Array of {LSA LSAs}
53
+ # @return [ArrayOfLSA]
54
+ define_field :lsas, ArrayOfLSA, builder: ->(h, t) { t.new(counter: h[:lsas_count]) }
55
+
56
+ # Calculate checksums of all LSAs
57
+ # @return [void]
58
+ def calc_checksum
59
+ lsas.each { |lsa| lsa.calc_checksum }
60
+ end
61
+
62
+ # Calculate length of all LSAs
63
+ def calc_length
64
+ lsas.each { |lsa| lsa.calc_length }
65
+ end
66
+ end
67
+ end
68
+
69
+ self.add_class OSPFv2::LSUpdate
70
+ OSPFv2.bind_header OSPFv2::LSUpdate, type: OSPFv2::TYPES['LS_UPDATE']
71
+ end
72
+ 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 OSPFv2
11
+
12
+ # This class handles unsupported {OSPFv2 OSPFv2} LSA payloads.
13
+ # A LSA payload is a {LSAHeader} with a {#body} field.
14
+ # @author Sylvain Daubert
15
+ class LSA < LSAHeader
16
+ # @!attribute body
17
+ # LSA body
18
+ # @return [String]
19
+ define_field :body, Types::String,
20
+ builder: ->(h,t) { t.new(length_from: ->() { h.length - 20 }) }
21
+ end
22
+
23
+ # This class handles TOS metrics for {Link links} in a {LSARouter
24
+ # LSA router payload}.
25
+ # @author Sylvain Daubert
26
+ class TosMetric < Types::Fields
27
+ # @!attribute tos
28
+ # 8-bit IP Type of Service that this metric refers to.
29
+ # @return [Integer]
30
+ define_field :tos, Types::Int8
31
+ # @!attribute reserved
32
+ # 8-bit reserved field.
33
+ # @return [Integer]
34
+ define_field :reserved, Types::Int8, default: 0
35
+ # @!attribute tos_metric
36
+ # 16-bit TOS-specific metric information..
37
+ # @return [Integer]
38
+ define_field :tos_metric, Types::Int16
39
+
40
+ # @return [String]
41
+ def to_human
42
+ "TOS<type:#{type},metric:#{tos_metric}>"
43
+ end
44
+ end
45
+
46
+ # This class defines a specialized {Types::Array array} to handle series
47
+ # of {TosMetric TOS metrics}.
48
+ # @author Sylvain Daubert
49
+ class ArrayOfTosMetric < Types::Array
50
+ set_of TosMetric
51
+ end
52
+
53
+ # This class handles links in a {LSARouter LSA router payload}.
54
+ # @author Sylvain Daubert
55
+ class Link < Types::Fields
56
+ # @!attribute id
57
+ # @return [IP::Addr]
58
+ define_field :id, IP::Addr
59
+ # @!attribute data
60
+ # @return [IP::Addr]
61
+ define_field :data, IP::Addr
62
+ # @!attribute type
63
+ # @return [Integer]
64
+ define_field :type, Types::Int8
65
+ # @!attribute tos_count
66
+ # @return [Integer]
67
+ define_field :tos_count, Types::Int8
68
+ # @!attribute metric
69
+ # @return [Integer]
70
+ define_field :metric, Types::Int16
71
+ # @!attribute tos
72
+ # Additionnal TOS metrics
73
+ # @return [ArrayOfTosMetric]
74
+ define_field :tos, ArrayOfTosMetric, builder: ->(h,t) { t.new(counter: h[:tos_count]) }
75
+
76
+ # @return [String]
77
+ def to_human
78
+ "Link<type:#{type},metric:#{metric},id:#{id},data:#{data}>"
79
+ end
80
+ end
81
+
82
+ # This class defines a specialized {Types::Array array} to handle series
83
+ # of {Link Links}.
84
+ # @author Sylvain Daubert
85
+ class ArrayOfLink < Types::Array
86
+ set_of Link
87
+ end
88
+
89
+ # This class handles LSA Router payloads.
90
+ #
91
+ # A LSA router payload is composed of:
92
+ # * a header (see methods inherited from {LSAHeader}),
93
+ # * a 16-bit flag word {#u16} ({Types::Int16}),
94
+ # * a 16-bit {#link_count} field ({Types::Int16}),
95
+ # * an array of {#links} ({ArrayOfLink}).
96
+ # @author Sylvain Daubert
97
+ class LSARouter < LSAHeader
98
+ # @attribute u16
99
+ # 16-bit flag word
100
+ # @return [Integer]
101
+ define_field :u16, Types::Int16
102
+ # @attribute link_count
103
+ # Number of links
104
+ # @return [Integer]
105
+ define_field :link_count, Types::Int16
106
+ # @attribute links
107
+ # @return [ArrayOfLink]
108
+ define_field :links, ArrayOfLink, builder: ->(h, t) { t.new(counter: h[:link_count]) }
109
+
110
+ # @attribute v_flag
111
+ # @return [Boolean]
112
+ # @attribute e_flag
113
+ # @return [Boolean]
114
+ # @attribute b_flag
115
+ # @return [Boolean]
116
+ define_bit_fields_on :u16, :z, 5, :v_flag, :e_flag, :b_flag, :zz, 8
117
+ end
118
+
119
+ # This class handles LSA Network payloads.
120
+ #
121
+ # A LSA network payload is composed of:
122
+ # * a header (see methods inherited from {LSAHeader}),
123
+ # * a 32-bit {#netmask} field ({IP::Addr}),
124
+ # * an array of router addresses ({#routers}, {IP::ArrayOfAddr}).
125
+ # @author Sylvain Daubert
126
+ class LSANetwork < LSAHeader
127
+ # @!attribute netmask
128
+ # @return [IP::Addr]
129
+ define_field :netmask, IP::Addr
130
+ # @!attribute routers
131
+ # List of routers in network
132
+ # @return [IP::ArrayOfAddr]
133
+ define_field :routers, IP::ArrayOfAddr
134
+ end
135
+
136
+ # This class handles external links in {LSAASExternal LSA AS-External payloads}.
137
+ # @author Sylvain Daubert
138
+ class External < Types::Fields
139
+ # @!attribute u8
140
+ # @return [Integer]
141
+ define_field :u8, Types::Int8
142
+ # @!attribute metric
143
+ # @return [Integer]
144
+ define_field :metric, Types::Int24
145
+ # @!attribute forwarding_addr
146
+ # @return [IP::Addr]
147
+ define_field :forwarding_addr, IP::Addr
148
+ # @!attribute ext_route_tag
149
+ # @return [Integer]
150
+ define_field :ext_route_tag, Types::Int32
151
+
152
+ # @!attribute e_flag
153
+ # @return [Boolean]
154
+ # @!attribute tos
155
+ # @return [Integer]
156
+ define_bit_fields_on :u8, :e_flag, :tos, 7
157
+ end
158
+
159
+ # This class defines a specialized {Types::Array array} to handle series
160
+ # of {External Externals}.
161
+ # @author Sylvain Daubert
162
+ class ArrayOfExternal < Types::Array
163
+ set_of External
164
+ end
165
+
166
+ # This class handles LSA AS-External payloads.
167
+ #
168
+ # A LSA network payload is composed of:
169
+ # * a header (see methods inherited from {LSAHeader}),
170
+ # * a 32-bit {#netmask} field ({IP::Addr}),
171
+ # * an array of external destinations ({#externals}, {ArrayOfExternal}).
172
+ # @author Sylvain Daubert
173
+ class LSAASExternal < LSAHeader
174
+ # @!attribute netmask
175
+ # @return [IP::Addr]
176
+ define_field :netmask, IP::Addr
177
+ # @!attribute externals
178
+ # List of external destinations
179
+ # @return [ArrayOfExternal]
180
+ define_field :externals, ArrayOfExternal
181
+ end
182
+
183
+ # This class defines a specialized {Types::Array array} to handle series
184
+ # of {LSA LSAs}. It recognizes known LSA types 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 OSPFv2.const_defined? klassname
244
+ OSPFv2.const_get klassname
245
+ else
246
+ LSA
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
252
+ end