Looks like the file content doesn't display correctly. Here it is again.
// clang++ -std=c++23 -o ifprobe ifprobe.cpp && ./ifprobe
#include <ifaddrs.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <sys/ioctl.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
static int open_bpf()
{
for ( int i = 0; i < 256; ++i )
{
std::string p = "/dev/bpf" + std::to_string( i );
int fd = open( p.c_str(), O_RDWR );
if ( fd != -1 ) return fd;
if ( errno != EBUSY ) break;
}
return -1;
}
static const char* functional_type_name( unsigned t )
{
switch ( t )
{
case IFRTYPE_FUNCTIONAL_LOOPBACK: return "LOOPBACK";
case IFRTYPE_FUNCTIONAL_WIRED: return "WIRED";
case IFRTYPE_FUNCTIONAL_WIFI_INFRA: return "WIFI_INFRA";
case IFRTYPE_FUNCTIONAL_WIFI_AWDL: return "WIFI_AWDL";
case IFRTYPE_FUNCTIONAL_CELLULAR: return "CELLULAR";
default: return "UNKNOWN";
}
}
static size_t sockaddr_aligned_size(const sockaddr* address)
{
if (address->sa_len == 0)
return sizeof(long);
return (address->sa_len + sizeof(long) - 1) &
~(sizeof(long) - 1);
}
static void print_sysctl_mac(const char* name)
{
const unsigned int index = if_nametoindex(name);
if (index == 0)
{
printf(" sysctl_mac=<unknown interface>");
return;
}
int mib[] = {
CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST,
static_cast<int>(index)
};
size_t length = 0;
if (sysctl(mib, 6, nullptr, &length, nullptr, 0) != 0)
{
printf(" sysctl_mac=<size query failed errno=%d>", errno);
return;
}
std::vector<unsigned char> buffer(length);
if (sysctl(mib, 6, buffer.data(), &length, nullptr, 0) != 0)
{
printf(" sysctl_mac=<read failed errno=%d>", errno);
return;
}
auto* message = reinterpret_cast<const if_msghdr*>(buffer.data());
const auto* address = reinterpret_cast<const sockaddr*>(
message + 1);
for (int address_index = 0;
address_index < RTAX_MAX;
++address_index)
{
if ((message->ifm_addrs & (1 << address_index)) == 0)
continue;
if (address_index == RTAX_IFP &&
address->sa_family == AF_LINK)
{
auto* link_address =
reinterpret_cast<const sockaddr_dl*>(address);
if (link_address->sdl_alen == 6)
{
const auto* mac =
reinterpret_cast<const unsigned char*>(
LLADDR(link_address));
printf(" sysctl_mac=%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
return;
}
}
address = reinterpret_cast<const sockaddr*>(
reinterpret_cast<const unsigned char*>(address) +
sockaddr_aligned_size(address));
}
printf(" sysctl_mac=<unavailable>");
}
int main()
{
ifaddrs* ifap = nullptr;
if ( getifaddrs( &ifap ) != 0 ) return 1;
int probe = socket( AF_INET, SOCK_DGRAM, 0 );
for ( ifaddrs* p = ifap; p; p = p->ifa_next )
{
if ( !p->ifa_addr || p->ifa_addr->sa_family != AF_LINK ) continue;
auto* dl = reinterpret_cast< sockaddr_dl* >( p->ifa_addr );
unsigned ftype = 0;
ifreq fr{};
strncpy( fr.ifr_name, p->ifa_name, IFNAMSIZ - 1 );
if ( ioctl( probe, SIOCGIFFUNCTIONALTYPE, &fr ) == 0 )
ftype = fr.ifr_ifru.ifru_functional_type;
// BIOCGDLT is the decisive check: DLT_EN10MB means our 14-byte Ethernet header is correct framing.
int dlt = -1;
int fd = open_bpf();
if ( fd >= 0 )
{
ifreq br{};
strncpy( br.ifr_name, p->ifa_name, IFNAMSIZ - 1 );
if ( ioctl( fd, BIOCSETIF, &br ) == 0 ) ioctl( fd, BIOCGDLT, &dlt );
close( fd );
}
printf( "%-10s maclen=%-2u ftype=%-11s dlt=%-3d up=%d running=%d ",
p->ifa_name, dl->sdl_alen, functional_type_name( ftype ), dlt,
( p->ifa_flags & IFF_UP ) != 0, ( p->ifa_flags & IFF_RUNNING ) != 0 );
print_sysctl_mac(p->ifa_name);
printf("\n");
}
close( probe );
freeifaddrs( ifap );
}
Topic:
App & System Services
SubTopic:
Networking