Get a remote MAC address via IPv6

2019-05-02 05:59发布

问题:

Is it possible to get the MAC from an another PC in the same Network via IPv6 (without WMI)? With IPv4 it is easy (ARP).

IPv6 uses the "Neighbor Discovery Protocol" (NDP) to get the MAC address. Are there any methods in .Net for this?

回答1:

You can run the external command "netsh int ipv6 show neigh", and filter out the host you are interested in. You should have contacted it just before that, so you know it is in the NC.

If you want an API for that, use GetIpNetTable2 or, more directly, ResolveIpNetEntry2. I doubt there is a .NET API for this, so you'll have to use PInvoke.



回答2:

Martin's answer was for Windows, but this is for if you are on a GNU/Linux or other *nix box.

You want to use the neigh function of the ip command to show IPv6 neighbours, like so:

$ ip -6 neigh
fe80::200:ff:fe00:0 dev eth0 lladdr 00:0e:54:24:23:21 router REACHABLE
fe80::202:b0ff:fe01:2abe dev eth0 lladdr 00:02:b0:02:2a:be DELAY

(Pro tip: you can leave the -6 off and view IPv4 ARP as well as IPv6 ND in the same list.)

Also, if you want to find out the MAC addresses of all the IPv6 machines on the LAN, and not just those you already know about, you should ping them first, then look for neighbours:

$ ping6 ff02::1%eth0
64 bytes from fe80::221:84ff:fe42:86ef: icmp_seq=1 ttl=64 time=0.053 ms # <-- you
64 bytes from fe80::200:ff:fe00:0: icmp_seq=1 ttl=64 time=2.37 ms (DUP!)
64 bytes from fe80::202:b0ff:fe01:2abe: icmp_seq=1 ttl=64 time=2.38 ms (DUP!)
64 bytes from fe80::215:abff:fe63:f6fa: icmp_seq=1 ttl=64 time=2.66 ms (DUP!)

$ ip -6 neigh
fe80::200:ff:fe00:0 dev eth0 lladdr 00:0e:54:24:23:21 router REACHABLE
fe80::202:b0ff:fe01:2abe dev eth0 lladdr 00:02:b0:02:2a:be DELAY
fe80::215:abff:fe63:f6fa dev eth0 lladdr 00:02:15:ab:f6:fa DELAY # <-- a new one!


回答3:

The answer by @Alex would be better if the line parsing code were improved. Here is one way:

public static string netsh(String IPv6)
{
    IPAddress wanted;
    if (!IPAddress.TryParse(IPv6, out wanted))
        throw new ArgumentException("Can't parse as an IPAddress", "IPv6");

    Regex re = new Regex("^([0-9A-F]\S+)\s+(\S+)\s+(\S+)", RegexOptions.IgnoreCase);

    // ... the code that runs netsh and gathers the output.

        Match m = re.Match(output);
        if (m.Success)
        {
            // [0] is the entire line
            // [1] is the IP Address string
            // [2] is the MAC Address string
            // [3] is the status (Permanent, Stale, ...)
            //
            IPAddress found;
            if (IPAddress.TryParse(m.Groups[1].Value, out found))
            {
                 if(wanted.Equals(found))
                 {
                      return m.Groups[2].Value;
                 }
            }
        }

    // ... the code that finishes the loop on netsh output and returns failure
}


回答4:

Here is my code:

public static string netsh(String IPv6)
         {
           Process p = new Process();
           p.StartInfo.FileName = "netsh.exe";
           String command = "int ipv6 show neigh"; 
           Console.WriteLine(command);
           p.StartInfo.Arguments = command;
           p.StartInfo.UseShellExecute = false;
           p.StartInfo.RedirectStandardOutput = true;
           p.Start();

          String output = "go";
          while (output!=null){
            try
             {
               output = p.StandardOutput.ReadLine();
             }
             catch (Exception)
             {
               output = null;
             }
             if (output.Contains(IPv6))
             {
               // Nimmt die Zeile in der sich die IPv6 Addresse und die MAC Addresse des Clients befindet
               // Löscht den IPv6 Eintrag, entfernt alle Leerzeichen und kürzt den String auf 17 Zeichen, So erschein die MacAddresse im Format "33-33-ff-0d-57-00"

               output = output.Replace(IPv6, "").Replace(" ", "").TrimToMaxLength(17) ;
               return output;
             }
           }
           return null;

        }