如何使用SharpPcap和Packet.Net发送LLDP数据包并接收设备信息?

时间:2016-07-01 12:29:20

标签: c#

这是我的代码:

public class Program
{
    // LLDP MAC address
     readonly static PhysicalAddress destinationHW = new PhysicalAddress(new byte[] { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e });

    //readonly static PhysicalAddress destinationHW = new PhysicalAddress(new byte[] { 0x98, 0x90, 0x96, 0x00, 0x00, 0x0e });

    public static void Main(string[] args)
    {
        Program mainprog = new Program();
        mainprog.Run();
    }

    public bool Run()
    {

        List<NetworkInterface> adapters = new List<NetworkInterface>();

        // Get list of connected adapters
        Console.WriteLine("Getting connected adapter list", EventLogEntryType.Information);
        adapters = NetworkInterface.GetAllNetworkInterfaces()
            .Where(
            x =>
            x.NetworkInterfaceType != NetworkInterfaceType.Loopback
            &&
            x.OperationalStatus == OperationalStatus.Up
            )
            .ToList();

        if (0 == adapters.Count)
        {
            Console.WriteLine("No adapters found.", EventLogEntryType.Information);
            // No available adapters
            return true;
        }

        // Open network devices for sending raw packets
        OpenDevices();

        // Wait to open devices
        System.Threading.Thread.Sleep(Convert.ToInt32(TimeSpan.FromSeconds(1).TotalMilliseconds));

        foreach (NetworkInterface adapter in adapters)
        {
            Console.WriteLine(String.Format("Adapter {0}:", adapter.Name), EventLogEntryType.Information);

            try
            {
                Console.WriteLine("Generating packet", EventLogEntryType.Information);
                Packet packet = CreateLLDPPacket(adapter);

                Console.WriteLine("Sending packet", EventLogEntryType.Information);

                while(true)
                {
                    sendRawPacket(adapter, packet);

                System.Threading.Thread.Sleep(5000);

                }

            }
            catch (Exception e)
            {
                Debug.WriteLine(String.Format("Error sending packet:{0}{1}", Environment.NewLine, e.ToString()), EventLogEntryType.Error);
            }

            Console.WriteLine("", EventLogEntryType.Information);
            Console.WriteLine(new String('-', 40), EventLogEntryType.Information);
        }

        return true;

    }

    public void Stop()
    {
        CloseDevices();
    }
    /// <summary>
    /// Convert network mask to CIDR notation
    /// </summary>
    /// <param name="ip"></param>
    /// <returns></returns>
    private int getCIDRFromIPMaskAddress(IPAddress ip)
    {
        return Convert.ToString(BitConverter.ToInt32(ip.GetAddressBytes(), 0), 2).ToCharArray().Count(x => x == '1');
    }
    /// <summary>
    /// TLV value's lenght can be only 0-511 octets
    /// Organizational spesific TLV value's lenght can be only 0-507 octets
    /// </summary>
    /// <param name="dict"></param>
    /// <returns></returns>
    private string CreateTlvString(Dictionary<string, string> dict)
    {
        int maxlen = 507;

        string o = String.Empty;

        foreach (var s in dict)
        {
            string tmp = String.Format("{0}:'{1}', ", s.Key, s.Value);

            if ((tmp.Length + o.Length) <= maxlen)
            {
                o += tmp;
            }
        }

        return o.Trim().TrimEnd(',');
    }

    /// <summary>
    /// Generate LLDP packet for adapter
    /// </summary>
    /// <param name="adapter"></param>
    public Packet CreateLLDPPacket(NetworkInterface adapter)
    {
        Debug.IndentLevel = 2;

        PhysicalAddress MACAddress = adapter.GetPhysicalAddress();

        IPInterfaceProperties ipProperties = adapter.GetIPProperties();
        IPv4InterfaceProperties ipv4Properties = null; // Ipv4
        IPv6InterfaceProperties ipv6Properties = null;// Ipv6

        // IPv6
        if (adapter.Supports(NetworkInterfaceComponent.IPv6))
        {
            try
            {
                ipv6Properties = ipProperties.GetIPv6Properties();
            }
            catch (NetworkInformationException e)
            {
                // Adapter doesn't probably have IPv6 enabled
                Debug.WriteLine(e.Message, EventLogEntryType.Warning);
            }
        }

        // IPv4
        if (adapter.Supports(NetworkInterfaceComponent.IPv4))
        {
            try
            {
                ipv4Properties = ipProperties.GetIPv4Properties();
            }
            catch (NetworkInformationException e)
            {
                // Adapter doesn't probably have IPv4 enabled
                Debug.WriteLine(e.Message, EventLogEntryType.Warning);
            }
        }

        // Port description
        Dictionary<string, string> portDescription = new Dictionary<string, string>();

        portDescription.Add("Vendor", adapter.Description);

        portDescription.Add("ID", adapter.Id);

        // Gateway
        if (ipProperties.GatewayAddresses.Count > 0)
        {
            portDescription.Add("GW", String.Join(", ", ipProperties.GatewayAddresses.Select(i => i.Address.ToString()).ToArray()));
        }
        else
        {
            portDescription.Add("GW", "-");
        }

        // CIDR
        if (ipProperties.UnicastAddresses.Count > 0)
        {
            int[] mask = ipProperties.UnicastAddresses
                .Where(
                  w => w.IPv4Mask.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork
                )
                .Select(x => getCIDRFromIPMaskAddress(x.IPv4Mask))
                .ToArray()
                ;


            portDescription.Add("CIDR", String.Join(", ", mask));
        }
        else
        {
            portDescription.Add("CIDR", "-");
        }


        // DNS server(s)
        if (ipProperties.DnsAddresses.Count > 0)
        {
            portDescription.Add("DNS", String.Join(", ", ipProperties.DnsAddresses.Select(i => i.ToString()).ToArray()));
        }
        else
        {
            portDescription.Add("DNS", "-");
        }

        // DHCP server
        if (ipProperties.DhcpServerAddresses.Count > 0)
        {
            portDescription.Add("DHCP", String.Join(", ", ipProperties.DhcpServerAddresses.Select(i => i.ToString()).ToArray()));
        }
        else
        {
            portDescription.Add("DHCP", "-");
        }

        // WINS server(s)
        if (ipProperties.WinsServersAddresses.Count > 0)
        {
            portDescription.Add("WINS", String.Join(", ", ipProperties.WinsServersAddresses.Select(i => i.ToString()).ToArray()));
        }


        // Link speed
       // portDescription.Add("Speed", ReadableSize(adapter.Speed) + "ps");

        // Capabilities enabled
        List<CapabilityOptions> capabilitiesEnabled = new List<CapabilityOptions>();
        capabilitiesEnabled.Add(CapabilityOptions.StationOnly);

        if (ipv4Properties.IsForwardingEnabled)
        {
            capabilitiesEnabled.Add(CapabilityOptions.Router);
        }

        ushort expectedSystemCapabilitiesCapability = GetCapabilityOptionsBits(GetCapabilityOptions());
        ushort expectedSystemCapabilitiesEnabled = GetCapabilityOptionsBits(capabilitiesEnabled);

        // Constuct LLDP packet 
        LLDPPacket lldpPacket = new LLDPPacket();
        lldpPacket.TlvCollection.Add(new ChassisID(ChassisSubTypes.MACAddress, MACAddress));
        lldpPacket.TlvCollection.Add(new PortID(PortSubTypes.LocallyAssigned, System.Text.Encoding.UTF8.GetBytes(adapter.Name)));
        lldpPacket.TlvCollection.Add(new TimeToLive(120));
        lldpPacket.TlvCollection.Add(new PortDescription(CreateTlvString(portDescription)));
        lldpPacket.TlvCollection.Add(new SystemName(Environment.MachineName));
       // lldpPacket.TlvCollection.Add(new SystemDescription(CreateTlvString(systemDescription)));
        lldpPacket.TlvCollection.Add(new SystemCapabilities(expectedSystemCapabilitiesCapability, expectedSystemCapabilitiesEnabled));

        // Management
        var managementAddressObjectIdentifier = "Management";

        // Add management IPv4 address(es)
        if (null != ipv4Properties)
        {
            foreach (UnicastIPAddressInformation ip in ipProperties.UnicastAddresses)
            {
                if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    lldpPacket.TlvCollection.Add(new ManagementAddress(new NetworkAddress(ip.Address), InterfaceNumbering.SystemPortNumber, Convert.ToUInt32(ipv4Properties.Index), managementAddressObjectIdentifier));
                }
            }
        }

        // Add management IPv6 address(es)
        if (null != ipv6Properties)
        {
            foreach (UnicastIPAddressInformation ip in ipProperties.UnicastAddresses)
            {
                if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
                {
                    lldpPacket.TlvCollection.Add(new ManagementAddress(new NetworkAddress(ip.Address), InterfaceNumbering.SystemPortNumber, Convert.ToUInt32(ipv6Properties.Index), managementAddressObjectIdentifier));
                }
            }
        }

        // == Organization specific TLVs

        // Ethernet
        lldpPacket.TlvCollection.Add(new OrganizationSpecific(new byte[] { 0x0, 0x12, 0x0f }, 5, new byte[] { 0x5 }));

        var expectedOrganizationUniqueIdentifier = new byte[3] { 0, 0, 0 };
        var expectedOrganizationSpecificBytes = new byte[] { 0, 0, 0, 0 };

        //int orgSubType = 0;

        // IPv4 Information:
        //if (null != ipv4Properties)
        //{
        //    lldpPacket.TlvCollection.Add((new StringTLV(TLVTypes.OrganizationSpecific, String.Format("IPv4 DHCP: {0}", ipv4Properties.IsDhcpEnabled.ToString()))));
        //lldpPacket.TlvCollection.Add(new OrganizationSpecific(expectedOrganizationSpecificBytes, new StringTLV(), System.Text.Encoding.UTF8.GetBytes(String.Format("IPv4 DHCP: {0}", ipv4Properties.IsDhcpEnabled.ToString()))));
        //}

        // End of LLDP packet
        lldpPacket.TlvCollection.Add(new EndOfLLDPDU());

        if (0 == lldpPacket.TlvCollection.Count)
        {
            throw new Exception("Couldn't construct LLDP TLVs.");
        }

        if (lldpPacket.TlvCollection.Last().GetType() != typeof(EndOfLLDPDU))
        {
            throw new Exception("Last TLV must be type of 'EndOfLLDPDU'!");
        }

        foreach (TLV tlv in lldpPacket.TlvCollection)
        {
            Console.WriteLine(tlv.ToString(), EventLogEntryType.Information);
        }

        // Generate packet
        Packet packet = new EthernetPacket(MACAddress, destinationHW, EthernetPacketType.LLDP);
        packet.PayloadData = lldpPacket.Bytes;

        return packet;

    }

    public bool sendRawPacket(NetworkInterface adapter, Packet payload)
    {
        Debug.WriteLine("Sending RAW packet", EventLogEntryType.Information);

        foreach (PcapDevice device in CaptureDeviceList.Instance)
        {
            if (adapter.GetPhysicalAddress().Equals(device.MacAddress))
            {
                Debug.WriteLine("Device found!", EventLogEntryType.Information);


                if (!device.Opened)
                {
                    Debug.WriteLine("Device is not open.", EventLogEntryType.Error);
                    return false;
                }

                device.SendPacket(payload);

                return true;
            }

        }

        return false;
    }

    /// <summary>
    /// Open devices for sending
    /// </summary>
    /// <param name="adapters"></param>
    public void OpenDevices()
    {
        Debug.WriteLine("Opening devices..", EventLogEntryType.Information);

        foreach (PcapDevice device in CaptureDeviceList.Instance)
        {
            if (!device.Opened)
            {
                device.Open(DeviceMode.Promiscuous);
            }
        }
    }

    private void Device_OnPacketArrival(object sender, CaptureEventArgs e)
    {
    }

    /// <summary>
    /// Close devices for sending
    /// </summary>
    /// <param name="adapters"></param>
    public void CloseDevices()
    {
        Console.WriteLine("Closing devices..", EventLogEntryType.Information);

        foreach (ICaptureDevice device in CaptureDeviceList.Instance)
        {              
                device.Close();            
        }

    }
    /// <summary>
    /// List possible LLDP capabilities such as:
    /// - Bridge 
    /// - Router 
    /// - WLAN Access Point 
    /// - Station 
    /// </summary>
    /// <returns>List<CapabilityOptions></returns>
    private List<CapabilityOptions> GetCapabilityOptions()
    {
        List<CapabilityOptions> capabilities = new List<CapabilityOptions>();
        capabilities.Add(CapabilityOptions.Bridge);
        capabilities.Add(CapabilityOptions.Router);
        capabilities.Add(CapabilityOptions.WLanAP);
        capabilities.Add(CapabilityOptions.StationOnly);

        //Console.WriteLine("Closing devices..", capabilities);

        return capabilities;

    }

    /// <summary>
    /// Get LLDP capabilities as bits
    /// </summary>
    /// <returns>ushort</returns>
    public ushort GetCapabilityOptionsBits(List<CapabilityOptions> capabilities)
    {
        ushort caps = 0;

        foreach (var cap in capabilities)
        {
            ushort tmp = ushort.Parse(cap.GetHashCode().ToString());
            caps |= tmp;
        }

        return caps;
    }

}

在此,我能够通过我的系统在wireshark中获取LLDP数据包,但我想从我的系统传输相同的(发送),并且应该通过wireshark在其他系统中获取LLDP数据包。

0 个答案:

没有答案