/// ************************************************************************ /// Copyright (C) 2001, Patrick Charles and Jonas Lehmann * /// Distributed under the Mozilla Public License * /// http://www.mozilla.org/NPL/MPL-1.1.txt * /// ************************************************************************* /// using System; using System.Net.NetworkInformation; using SharpPcap.Packets.Util; using ArrayHelper = SharpPcap.Packets.Util.ArrayHelper; using Timeval = SharpPcap.Packets.Util.Timeval; namespace SharpPcap.Packets { /// An ethernet packet. ///

/// Contains link-level header and data payload encapsulated by an ethernet /// packet. ///

/// There are currently two subclasses. IP and ARP protocols are supported. /// IPPacket extends with ip header and data information. /// ARPPacket extends with hardware and protocol addresses. /// ///

[Serializable] public class EthernetPacket : Packet, EthernetFields { /// Code constants for well-defined ethernet protocols. ///

/// Taken from linux/if_ether.h and tcpdump/ethertype.h /// ///

public struct EtherType { /// IP protocol. public const int IP = 0x0800; /// Address resolution protocol. public const int ARP = 0x0806; /// Reverse address resolution protocol. public const int RARP = 0x8035; /// Ethernet Loopback packet public const int LOOP = 0x0060; /// Ethernet Echo packet public const int ECHO = 0x0200; /// Xerox PUP packet public const int PUP = 0x0400; /// CCITT X.25 public const int X25 = 0x0805; /// G8BPQ AX.25 Ethernet Packet [ NOT AN OFFICIALLY REGISTERED ID ] public const int BPQ = 0x08FF; /// DEC Assigned proto public const int DEC = 0x6000; /// DEC DNA Dump/Load public const int DNA_DL = 0x6001; /// DEC DNA Remote Console public const int DNA_RC = 0x6002; /// DEC DNA Routing public const int DNA_RT = 0x6003; /// DEC LAT public const int LAT = 0x6004; /// DEC Diagnostics public const int DIAG = 0x6005; /// DEC Customer use public const int CUST = 0x6006; /// DEC Systems Comms Arch public const int SCA = 0x6007; /// Appletalk DDP public const int ATALK = 0x809B; /// Appletalk AARP public const int AARP = 0x80F3; /// IPX over DIX public const int IPX = 0x8137; /// IPv6 over bluebook public const int IPV6 = 0x86DD; /// Dummy type for 802.3 frames public const int N802_3 = 0x0001; /// Dummy protocol id for AX.25 public const int AX25 = 0x0002; /// Every packet. public const int ALL = 0x0003; /// 802.2 frames public const int N802_2 = 0x0004; /// Internal only public const int SNAP = 0x0005; /// DEC DDCMP: Internal only public const int DDCMP = 0x0006; /// Dummy type for WAN PPP frames public const int WAN_PPP = 0x0007; /// Dummy type for PPP MP frames public const int PPP_MP = 0x0008; /// Localtalk pseudo type public const int LOCALTALK = 0x0009; /// Dummy type for Atalk over PPP public const int PPPTALK = 0x0010; /// 802.2 frames public const int TR_802_2 = 0x0011; /// Mobitex (kaz@cafe.net) public const int MOBITEX = 0x0015; /// Card specific control frames public const int CONTROL = 0x0016; /// Linux/IR public const int IRDA = 0x0017; // others not yet documented.. public const int NS = 0x0600; public const int SPRITE = 0x0500; public const int TRAIL = 0x1000; public const int LANBRIDGE = 0x8038; public const int DECDNS = 0x803c; public const int DECDTS = 0x803e; public const int VEXP = 0x805b; public const int VPROD = 0x805c; public const int N8021Q = 0x8100; public const int PPP = 0x880b; public const int PPPOED = 0x8863; public const int PPPOES = 0x8864; public const int LOOPBACK = 0x9000; // spanning tree bridge protocol public const int STBPDU = 0x0026; // intel adapter fault tolerance heartbeats public const int INFTH = 0x886d; /// Ethernet protocol mask. public const int MASK = 0xffff; } /// Extract the protocol type field from packet data. ///

/// The type field indicates what type of data is contained in the /// packet's data block. ///

/// packet bytes. /// /// the ethernet type code. i.e. 0x800 signifies IP datagram. /// public static int extractProtocol(byte[] packetBytes) { // convert the bytes that contain the type code into a value.. return packetBytes[EthernetFields_Fields.ETH_CODE_POS] << 8 | packetBytes[EthernetFields_Fields.ETH_CODE_POS + 1]; } /// Fetch the ethernet header length in bytes. virtual public int EthernetHeaderLength { get { return _ethernetHeaderLength; } } /// Fetch the packet ethernet header length. virtual public int HeaderLength { get { return EthernetHeaderLength; } } /// Fetch the ethernet header as a byte array. virtual public byte[] EthernetHeader { get { return PacketEncoding.extractHeader(0, EthernetHeaderLength, _bytes); } } /// Fetch the ethernet header as a byte array. override public byte[] Header { get { return EthernetHeader; } } /// Fetch the ethernet data as a byte array. virtual public byte[] EthernetData { get { return PacketEncoding.extractData(0, EthernetHeaderLength, _bytes); } } /// Fetch the ethernet protocol. /// Sets the ethernet protocol. virtual public int EthernetProtocol { get { return ArrayHelper.extractInteger(_bytes, EthernetFields_Fields.ETH_CODE_POS, EthernetFields_Fields.ETH_CODE_LEN); } set { ArrayHelper.insertLong(_bytes, value, EthernetFields_Fields.ETH_CODE_POS, EthernetFields_Fields.ETH_CODE_LEN); } } /// /// should be overriden by upper classes /// public virtual void OnOffsetChanged() { if(PcapHeader!=null) { PcapHeader = new PcapHeader(PcapHeader.Seconds, PcapHeader.MicroSeconds, (uint)_bytes.Length, (uint)_bytes.Length); } } /// Fetch the timeval containing the time the packet arrived on the /// device where it was captured. /// override public Timeval Timeval { get { return _timeval; } } /// Fetch ascii escape sequence of the color associated with this packet type. override public System.String Color { get { return AnsiEscapeSequences_Fields.DARK_GRAY; } } override public byte[] Bytes { get { return _bytes; } protected set { _bytes = value; } } // store the data here, all subclasses can offset into this private byte[] _bytes; // offset from beginning of byte array where the data payload // (i.e. IP packet) starts. The size of the ethernet frame header. protected internal int _ethOffset; // time that the packet was captured off the wire protected internal Timeval _timeval; /// Construct a new ethernet packet. ///

/// For the purpose of jpcap, when the type of ethernet packet is /// recognized as a protocol for which a class exists network library, /// then a more specific class like IPPacket or ARPPacket is instantiated. /// The subclass can always be cast into a more generic form. ///

public EthernetPacket(int lLen, byte[] bytes) { _bytes = bytes; _ethernetHeaderLength = lLen; _ethOffset = lLen; } /// Construct a new ethernet packet, including the capture time. public EthernetPacket(int lLen, byte[] bytes, Timeval tv) : this(lLen, bytes) { this._timeval = tv; } // set in constructor private int _ethernetHeaderLength; /// Fetch the ethernet data as a byte array. public override byte[] Data { get { return EthernetData; } } private static int macAddressLength = 6; /// Fetch the MAC address of the host where the packet originated from. public virtual PhysicalAddress SourceHwAddress { get { byte[] hwAddress = new byte[macAddressLength]; Array.Copy(_bytes, EthernetFields_Fields.ETH_SRC_POS, hwAddress, 0, hwAddress.Length); return new PhysicalAddress(hwAddress); } set { byte[] hwAddress = value.GetAddressBytes(); if(hwAddress.Length != macAddressLength) { throw new System.InvalidOperationException("address length " + hwAddress.Length + " not equal to the expected length of " + macAddressLength); } Array.Copy(hwAddress, 0, _bytes, EthernetFields_Fields.ETH_SRC_POS, hwAddress.Length); } } /// Fetch the MAC address of the host where the packet originated from. public virtual PhysicalAddress DestinationHwAddress { get { byte[] hwAddress = new byte[macAddressLength]; Array.Copy(_bytes, EthernetFields_Fields.ETH_DST_POS, hwAddress, 0, hwAddress.Length); return new PhysicalAddress(hwAddress); } set { byte[] hwAddress = value.GetAddressBytes(); if(hwAddress.Length != macAddressLength) { throw new System.InvalidOperationException("address length " + hwAddress.Length + " not equal to the expected length of " + macAddressLength); } Array.Copy(hwAddress, 0, _bytes, EthernetFields_Fields.ETH_DST_POS, hwAddress.Length); } } /// Convert this ethernet packet to a readable string. public override System.String ToString() { return ToColoredString(false); } /// Generate string with contents describing this ethernet packet. /// whether or not the string should contain ansi /// color escape sequences. /// public override System.String ToColoredString(bool colored) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); buffer.Append('['); if (colored) buffer.Append(Color); buffer.Append("EthernetPacket"); if (colored) buffer.Append(AnsiEscapeSequences_Fields.RESET); buffer.Append(": "); buffer.Append(SourceHwAddress + " -> " + DestinationHwAddress); buffer.Append(" proto=0x" + System.Convert.ToString(EthernetProtocol, 16)); buffer.Append(" l=" + EthernetHeaderLength); // + "," + data.length); buffer.Append(']'); // append the base output buffer.Append(base.ToColoredString(colored)); return buffer.ToString(); } /// Convert this IP packet to a more verbose string. public override System.String ToColoredVerboseString(bool colored) { //TODO: just output the colored output for now return ToColoredString(colored); } } }