Class: Mu::Pcap::Ethernet
- Defined in:
- lib/diy/parser/mu/pcap/ethernet.rb
Constant Summary collapse
- ETHERTYPE_IP =
0x0800
- ETHERTYPE_IP6 =
0x86dd
- ETHERTYPE_ARP =
0x0806
- ETHERTYPE_PPPOE_SESSION =
0x8864
- ETHERTYPE_802_1Q =
0X8100
- PPP_IP =
0x0021
- PPP_IPV6 =
0x0057
- FMT_MAC =
"C6"
- FMT_n =
'n'
- MAC_TEMPLATE =
'%02x:%02x:%02x:%02x:%02x:%02x'
- ADDR_TO_BYTES =
{}
- FMT_HEADER =
'a6a6n'
Constants inherited from Packet
Instance Attribute Summary collapse
-
#dst ⇒ Object
Returns the value of attribute dst.
-
#src ⇒ Object
Returns the value of attribute src.
-
#type ⇒ Object
Returns the value of attribute type.
-
#vlan ⇒ Object
Returns the value of attribute vlan.
Attributes inherited from Packet
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object
- #flow_id ⇒ Object
-
#initialize(src = nil, dst = nil, type = 0) ⇒ Ethernet
constructor
A new instance of Ethernet.
- #ip? ⇒ Boolean
-
#remove_pppoe! ⇒ Object
Remove the PPPoE and PPP headers.
- #to_s ⇒ Object
- #vlan? ⇒ Boolean
- #write(io) ⇒ Object
Methods inherited from Packet
#deepdup, isolate_l7, normalize, #payload_bytes, #to_bytes
Constructor Details
#initialize(src = nil, dst = nil, type = 0) ⇒ Ethernet
Returns a new instance of Ethernet.
20 21 22 23 24 25 26 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 20 def initialize src=nil, dst=nil, type=0 super() @src = src @dst = dst @type = type @vlan = false end |
Instance Attribute Details
#dst ⇒ Object
Returns the value of attribute dst.
9 10 11 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 9 def dst @dst end |
#src ⇒ Object
Returns the value of attribute src.
9 10 11 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 9 def src @src end |
#type ⇒ Object
Returns the value of attribute type.
9 10 11 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 9 def type @type end |
#vlan ⇒ Object
Returns the value of attribute vlan.
27 28 29 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 27 def vlan @vlan end |
Class Method Details
.from_bytes(bytes) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 44 def self.from_bytes bytes if bytes.length < 14 raise ParseError, "Truncated Ethernet header: expected 14 bytes, got #{bytes.length} bytes" end dst = bytes.slice!(0,6).unpack FMT_MAC dst = MAC_TEMPLATE % dst src = bytes.slice!(0,6).unpack FMT_MAC src = MAC_TEMPLATE % src type = bytes.slice!(0,2).unpack(FMT_n)[0] if type == ETHERTYPE_802_1Q @vlan = true else @vlan = false end while (type == ETHERTYPE_802_1Q) # Skip 4 bytes for 802.1q vlan tag field bytes.slice!(0,2) type = bytes.slice!(0,2).unpack(FMT_n)[0] end ethernet = Ethernet.new src, dst, type ethernet.vlan = @vlan ethernet.payload = bytes ethernet.payload_raw = bytes begin case type when ETHERTYPE_IP ethernet.payload = IPv4.from_bytes bytes when ETHERTYPE_IP6 ethernet.payload = IPv6.from_bytes bytes when ETHERTYPE_PPPOE_SESSION # Remove PPPoE/PPP session layer ethernet.payload = bytes ethernet.remove_pppoe! else ethernet.payload = bytes end rescue ParseError => e Pcap.warning e end return ethernet end |
Instance Method Details
#==(other) ⇒ Object
151 152 153 154 155 156 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 151 def == other return super && self.src == other.src && self.dst == other.dst && self.type == other.type end |
#flow_id ⇒ Object
33 34 35 36 37 38 39 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 33 def flow_id if not @payload or @payload.is_a? String return [:ethernet, @src, @dst, @type] else return @payload.flow_id end end |
#ip? ⇒ Boolean
87 88 89 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 87 def ip? return payload.is_a?(IP) end |
#remove_pppoe! ⇒ Object
Remove the PPPoE and PPP headers. PPPoE is documented in RFC 2516.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 106 def remove_pppoe! bytes = self.payload_raw # Remove PPPoE header Pcap.assert bytes.length >= 6, 'Truncated PPPoE header: ' + "expected at least 6 bytes, got #{bytes.length} bytes" version_type, code, session_id, length = bytes.unpack 'CCnn' version = version_type >> 4 & 0b1111 type = version_type & 0b1111 Pcap.assert version == 1, "Unknown PPPoE version: #{version}" Pcap.assert type == 1, "Unknown PPPoE type: #{type}" Pcap.assert code == 0, "Unknown PPPoE code: #{code}" bytes = bytes[6..-1] Pcap.assert bytes.length >= length, 'Truncated PPoE packet: ' + "expected #{length} bytes, got #{bytes.length} bytes" # Remove PPP header Pcap.assert bytes.length >= 2, 'Truncated PPP packet: ' + "expected at least bytes, got #{bytes.length} bytes" protocol_id, = bytes.unpack 'n' bytes = bytes[2..-1] case protocol_id when PPP_IP self.payload = IPv4.from_bytes bytes self.payload_raw = bytes self.type = ETHERTYPE_IP when PPP_IPV6 self.payload = IPv6.from_bytes bytes self.payload_raw = bytes self.type = ETHERTYPE_IP6 else # Failed. Don't update payload or type. raise ParseError, "Unknown PPP protocol: 0x#{'%04x' % protocol_id}" end end |
#to_s ⇒ Object
142 143 144 145 146 147 148 149 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 142 def to_s if @payload.is_a? String payload = @payload.inspect else payload = @payload.to_s end return "ethernet(%s, %s, %d, %s)" % [@src, @dst, @type, payload] end |
#vlan? ⇒ Boolean
29 30 31 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 29 def vlan? vlan end |
#write(io) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/diy/parser/mu/pcap/ethernet.rb', line 93 def write io dst_mac = ADDR_TO_BYTES[@dst] ||= @dst.split(':').inject('') {|m, b| m << b.to_i(16).chr} src_mac = ADDR_TO_BYTES[@src] ||= @src.split(':').inject('') {|m, b| m << b.to_i(16).chr} bytes = [dst_mac, src_mac, @type].pack(FMT_HEADER) io.write bytes if @payload.is_a? String io.write @payload else @payload.write io end end |