/// <summary>
        ///		Create a new ARP packet. 
        /// </summary>
        /// <param name="data">
        ///		The data representing the ARP packet.
        ///	</param>
        public ArpPacket(byte[] data)
        {
            int position = 0;

            m_hardware = (MediaType)IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (data, position));
            position += 2;

            m_protocol = (NetworkLayerProtocol)BitConverter.ToInt16 (data, position);
            position += 2;

            int macLength = data[position];
            position ++;

            int ipLength = data[position];
            position++;

            m_type = (ArpOpcode)IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (data, position));
            position += 2;

            // copy out source MAC
            byte[] sourceMac	= new byte[macLength];
            Array.Copy (data, position, sourceMac, 0, macLength);
            m_sourceMac = new MACAddress (sourceMac);
            position += macLength;

            // copy out source IP
            byte[] sourceIP	= new byte[ipLength];
            Array.Copy (data, position, sourceIP, 0, ipLength);

            string sIP = string.Empty;

            for (int i = 0; i < ipLength; i++)
            {
                sIP = string.Concat(sIP, sourceIP[i], ".");
            }

            m_sourceIP = IPAddress.Parse(sIP.Substring (0, sIP.Length - 1));
            position += ipLength;

            // copy out destination MAC
            byte[] destMac		= new byte[macLength];
            Array.Copy (data, position, destMac, 0, macLength);
            m_destMac = new MACAddress (destMac);
            position += macLength;

            // copy out destination IP
            byte[] destIP	= new byte[ipLength];
            Array.Copy (data, position, destIP, 0, ipLength);

            sIP = string.Empty;

            for (int i = 0; i < ipLength; i++)
            {
                sIP = string.Concat(sIP, destIP[i], ".");
            }

            m_destIP = IPAddress.Parse(sIP.Substring (0, sIP.Length - 1));
            position += ipLength;
        }
        /// <summary>
        ///		Resolve a physical address to an IP address.
        /// </summary>
        /// <param name="address">
        ///		The physical address to resolve.
        ///	</param>
        /// <returns>
        ///		Returns the IP address belonging to the physical address.
        ///	</returns>
        /// <exception cref="ObjectDisposedException">
        ///		If the object has already been disposed then an ObjectDisposedException
        ///		will be thrown
        ///	</exception>
        /// <exception cref="Exception">
        ///		If the driver failed to start or was not bound, an exception will be thrown.
        ///	</exception>
        public IPAddress ResolveMACAddress(MACAddress address)
        {
            if (m_disposed)
            {
                throw new ObjectDisposedException (this.ToString());
            }

            if (!m_driver.DriverStarted)
            {
                throw new Exception ("The driver has not been started.");
            }

            if (!m_driver.DriverBound)
            {
                throw new Exception ("The driver has not yet been bound to a device.");
            }

            Ethernet802_3 ethernet = new Ethernet802_3 ();

            // construct the ethernet header
            ethernet.SourceMACAddress		= m_driver.BoundAdapter.MediaAccessControlAddress;
            ethernet.DestinationMACAddress	= MACAddress.BroadcastAddress;
            ethernet.NetworkProtocol		= NetworkLayerProtocol.ARP;

            ArpPacket arp = new ArpPacket ();

            // construct the ARP header
            arp.Type					= ArpOpcode.ReverseRequest;
            arp.Protocol				= NetworkLayerProtocol.IP;
            arp.MediaType				= MediaType.Ethernet;
            arp.SourceMACAddress		= ethernet.SourceMACAddress;
            arp.SourceIPAddress			= m_driver.BoundAdapter.Interfaces[0].Address;
            arp.DestinationMACAddress	= address;

            // serialize and send the packet
            ethernet.Data = arp.Serialize ();
            m_driver.SendPacket (ethernet.Serialize ());

            m_querying = true;

            // wait for the reply
            while (m_querying)
            {
                byte[] packet = m_driver.RecievePacket ();

                Ethernet802_3 ethReply = new Ethernet802_3 (packet);

                // if this is an ARP packet
                if (ethReply.NetworkProtocol == NetworkLayerProtocol.ARP)
                {
                    ArpPacket arpReply = new ArpPacket (ethReply.Data);

                    // if this is an ARP reply
                    if (arpReply.Type == ArpOpcode.Reply)
                    {
                        // if the address matches the one we requested
                        if (arpReply.DestinationIPAddress.Equals (address))
                        {
                            // return the IP address
                            return arpReply.DestinationIPAddress;
                        }
                    }
                }
            }

            return IPAddress.Any;
        }
        /// <summary>
        ///		Returns the vendor given a MAC address.
        /// </summary>
        /// <param name="reader">
        ///		The XML text reader to use to read the file.
        ///		Use the oui.xml file included in the Data folder of the library or a
        ///		file with the same format. If the format is not correct then the
        ///		behaviour of this method is undefined. In other words, don't blame me
        ///		if it freezes or raises an exception, if you pass an incorrectly
        ///		formatted file.
        ///	</param>
        /// <param name="address">
        ///		The MAC address whose vendor to find.
        ///	</param>
        /// <returns>
        ///		The vendor name.
        ///	</returns>
        public static string GetVender(XmlTextReader reader, MACAddress address)
        {
            // find the prefix
            string macPrefix = address.ToString().Substring (0, 8).Replace (":", "-").ToLower();

            // return value
            string retVal = string.Empty;

            // keep reading nodes
            while (reader.Read ())
            {
                // if this is a MAC
                if (reader.NodeType == XmlNodeType.Element && reader.Name == "MAC")
                {
                    // read the next part
                    reader.Read ();

                    // if this is the MAC prefix
                    if (reader.NodeType == XmlNodeType.Text && reader.Value.ToLower() == macPrefix)
                    {
                        // keep reading until we find the vendor
                        while (reader.NodeType != XmlNodeType.Element || reader.Name != "Vendor")
                        {
                            reader.Read ();
                        }

                        reader.Read ();
                        retVal = reader.Value;
                        break;
                    }
                    else
                    {
                        reader.Skip ();
                    }
                }
            }

            reader.Close ();
            return retVal;
        }