Class: Mu::Pcap::Ethernet
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.
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
- #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 |
# File 'lib/mu/pcap/ethernet.rb', line 20 def initialize src=nil, dst=nil, type=0 super() @src = src @dst = dst @type = type end |
Instance Attribute Details
#dst ⇒ Object
Returns the value of attribute dst.
9 10 11 |
# File 'lib/mu/pcap/ethernet.rb', line 9 def dst @dst end |
#src ⇒ Object
Returns the value of attribute src.
9 10 11 |
# File 'lib/mu/pcap/ethernet.rb', line 9 def src @src end |
#type ⇒ Object
Returns the value of attribute type.
9 10 11 |
# File 'lib/mu/pcap/ethernet.rb', line 9 def type @type end |
Class Method Details
.from_bytes(bytes) ⇒ Object
38 39 40 41 42 43 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 |
# File 'lib/mu/pcap/ethernet.rb', line 38 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] 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.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
139 140 141 142 143 144 |
# File 'lib/mu/pcap/ethernet.rb', line 139 def == other return super && self.src == other.src && self.dst == other.dst && self.type == other.type end |
#flow_id ⇒ Object
27 28 29 30 31 32 33 |
# File 'lib/mu/pcap/ethernet.rb', line 27 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
75 76 77 |
# File 'lib/mu/pcap/ethernet.rb', line 75 def ip? return payload.is_a?(IP) end |
#remove_pppoe! ⇒ Object
Remove the PPPoE and PPP headers. PPPoE is documented in RFC 2516.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/mu/pcap/ethernet.rb', line 94 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
130 131 132 133 134 135 136 137 |
# File 'lib/mu/pcap/ethernet.rb', line 130 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 |
#write(io) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/mu/pcap/ethernet.rb', line 81 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 |