5

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?

Community
  • 1
  • 1
Fabian
  • 53
  • 1
  • 3
  • what's the point of OSX tag here? the question and and the accepted answer look completely irrelevant to OSX... – ivan Jun 05 '12 at 14:18

4 Answers4

3

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.

Martin v. Löwis
  • 124,830
  • 17
  • 198
  • 235
  • Thank you. I think this should solve my problem. I tried it, but it isn't simple to get it work in 5 minutes ;). If I have a result, I contact over again – Fabian Nov 03 '10 at 12:27
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!
Jeremy Visser
  • 6,237
  • 1
  • 25
  • 30
  • Many thanks for your response. Though she does not fit completely, because I work in C# and .Net. But she has helped me, nevertheless. – Fabian Nov 03 '10 at 12:36
0

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
}
Jesse Chisholm
  • 3,857
  • 1
  • 35
  • 29
-1

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;

        }
The iOSDev
  • 5,237
  • 7
  • 41
  • 78
Alex
  • 1
  • I suspect the down vote was because this is very fragile parsing code. If the IPv6 argument is in a different case from the netsh output, it will fail. If the IPv6 argument is perfectly legal and correct but makes a different choice on leading zero or collapsing zero fields, then it will fail. If the IPv6 argument is a subset of what happens to appear on a line it will give a false positive match. – Jesse Chisholm Nov 06 '12 at 17:12