weskoerber / mac_address

A cross-platform library to retrieve the MAC address from your network interfaces without libc.
https://weskoerber.github.io/mac_address/
MIT License
2 stars 1 forks source link

Failing test due to layer 3 device having all-zero MAC address #9

Open weskoerber opened 2 months ago

weskoerber commented 2 months ago

The get_first_no_loopback test looks like this:

test "get_first_no_loopback" {
    const addr = try getFirstNoLoopback(testing.allocator);

    try testing.expectEqual(false, addr.is_loopback);
    try testing.expect(!std.mem.eql(u8, &addr.data, &.{ 0, 0, 0, 0, 0, 0 }));
}

It calls the getFirstNoLoopback function to -- you guessed it -- get the first interface that is not a loopback device. What identifies a loopback device is the is_loopback field in the MacAddress struct (related: #8). However, I assumed that only a loopback interface would have a MAC address with all zeroes, but that's not the case.

I use tailscale, which runs at layer 3^1. At this level, the tailscale0 device cannot be assigned a MAC address. Therefore, the data field in the MacAddress struct was all zeroes, which caused the test to fail.

This has 2 implications:

  1. The test for non-loopback devices should not assume only loopback devices have a MAC address of all zeroes.
  2. I may not want to remove the is_loopback field from the MacAddress struct (again, see #8); otherwise, there will be no way to differentiate true loopback devices from devices on layer 3.

An alternative to item 2 in the preceding list is to include the IP address in the MacAddress struct- that way 127.0.0.1 can be the identifier for loopback devices.

I'm not sure what I want to do here. I still want to have loopback device identification but I do not want to encode more information than necessary in the MacAddress struct -- I think even the is_loopback field is too much. I want to keep the scope of this library relatively narrow.

weskoerber commented 2 months ago

I added e9ca243 that addresses this, in one way or another.

It removes is_loopback from MacAddress.

If we encounter a loopback device in getFirstNoLoopback as reported by the SIOCGIFFLAGS request, we recursively call next() on the iterator which will either return null if there are no more devices or the next device.

thafer30 commented 2 months ago

I'm curious if other "virtual" network interfaces such as docker networks show up with a Mac address of all zeros as well

weskoerber commented 1 month ago

I'm curious if other "virtual" network interfaces such as docker networks show up with a Mac address of all zeros as well

Interestingly, I got a MAC address from a Docker virtual network that was not all zeroes... I'm not sure why though; I don't know how docker manages it's virtual networks.

weskoerber commented 4 days ago

I don't know how docker manages it's virtual networks.

https://stackoverflow.com/questions/42946453/how-does-the-docker-assign-mac-addresses-to-containers

Additionally, Docker's network interface is a bridge, whereas Tailscale's is a user-space TUN adapter:

❯ ethtool -i tailscale0
driver: tun
version: 1.6
firmware-version: 
expansion-rom-version: 
bus-info: tun
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

❯ ethtool -i docker0
driver: bridge
version: 2.3
firmware-version: N/A
expansion-rom-version: 
bus-info: N/A
supports-statistics: no
supports-test: no
supports-eeprom-access: no
supports-register-dump: no
supports-priv-flags: no

Some additional info on the topic from the interwebs:

So it seems the answer to this is that network bridges (Docker) operate on Layer 2 - which is why they have MAC addresses - and Tailscale's TUN adapters operate on Layer 3.