Skip to content

Instantly share code, notes, and snippets.

@carun
Created April 22, 2019 22:40
Show Gist options
  • Save carun/1ae91dfb1af825e2df1eacd5bb6becb1 to your computer and use it in GitHub Desktop.
Save carun/1ae91dfb1af825e2df1eacd5bb6becb1 to your computer and use it in GitHub Desktop.
Print macaddress
/* net/if.h -- declarations for inquiring about network interfaces
Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
import core.stdc.config;
import core.sys.posix.sys.socket;
extern (C):
enum _NET_IF_H = 1;
/* Length of interface name. */
enum IF_NAMESIZE = 16;
alias __caddr_t = char*;
struct if_nameindex_
{
uint if_index; /* 1, 2, ... */
char* if_name; /* null terminated name: "eth0", ... */
}
/* Standard interface flags. */
enum
{
IFF_UP = 0x1, /* Interface is up. */
IFF_BROADCAST = 0x2, /* Broadcast address valid. */
IFF_DEBUG = 0x4, /* Turn on debugging. */
IFF_LOOPBACK = 0x8, /* Is a loopback net. */
IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link. */
IFF_NOTRAILERS = 0x20, /* Avoid use of trailers. */
IFF_RUNNING = 0x40, /* Resources allocated. */
IFF_NOARP = 0x80, /* No address resolution protocol. */
IFF_PROMISC = 0x100, /* Receive all packets. */
/* Not supported */
IFF_ALLMULTI = 0x200, /* Receive all multicast packets. */
IFF_MASTER = 0x400, /* Master of a load balancer. */
IFF_SLAVE = 0x800, /* Slave of a load balancer. */
IFF_MULTICAST = 0x1000, /* Supports multicast. */
IFF_PORTSEL = 0x2000, /* Can set media type. */
IFF_AUTOMEDIA = 0x4000, /* Auto media select active. */
IFF_DYNAMIC = 0x8000 /* Dialup device with changing addresses. */
}
/* The ifaddr structure contains information about one address of an
interface. They are maintained by the different address families,
are allocated and attached when an address is set, and are linked
together so all addresses for an interface can be located. */
struct ifaddr
{
sockaddr ifa_addr; /* Address of interface. */
union ifa_ifu_t
{
sockaddr ifu_broadaddr;
sockaddr ifu_dstaddr;
}
alias ifa_broadaddr = ifa_ifu.ifu_broadaddr; /* broadcast address */
alias ifa_dstaddr = ifa_ifu.ifu_dstaddr; /* other end of link */
ifa_ifu_t ifa_ifu;
struct iface;
iface* ifa_ifp; /* Back-pointer to interface. */
ifaddr* ifa_next; /* Next address for interface. */
}
/* Device mapping structure. I'd just gone off and designed a
beautiful scheme using only loadable modules with arguments for
driver options and along come the PCMCIA people 8)
Ah well. The get() side of this is good for WDSETUP, and it'll be
handy for debugging things. The set side is fine for now and being
very small might be worth keeping for clean configuration. */
struct ifmap
{
c_ulong mem_start;
c_ulong mem_end;
ushort base_addr;
ubyte irq;
ubyte dma;
ubyte port;
/* 3 bytes spare */
}
/* Interface request structure used for socket ioctl's. All interface
ioctl's must have parameter definitions which begin with ifr_name.
The remainder may be interface specific. */
struct ifreq
{
/* Interface name, e.g. "en0". */
union ifr_ifrn_t
{
char[IFNAMSIZ] ifrn_name;
}
/* Just fits the size */
union ifr_ifru_t
{
sockaddr ifru_addr;
sockaddr ifru_dstaddr;
sockaddr ifru_broadaddr;
sockaddr ifru_netmask;
sockaddr ifru_hwaddr;
short ifru_flags;
int ifru_ivalue;
int ifru_mtu;
ifmap ifru_map;
char[IFNAMSIZ] ifru_slave;
char[IFNAMSIZ] ifru_newname;
__caddr_t ifru_data;
}
ifr_ifrn_t ifr_ifrn;
ifr_ifru_t ifr_ifru;
@property ref ifr_name(ref ifreq this_) { return this_.ifr_ifrn.ifrn_name; }
@property ref ifr_addr() { return this.ifr_ifru.ifru_addr; } /* address */
@property ref ifr_hwaddr(ref ifreq this_) { return this_.ifr_ifru.ifru_hwaddr; } /* MAC address */
@property ref ifr_dstaddr(ref ifreq this_) { return this_.ifr_ifru.ifru_dstaddr; } /* other end of p-p lnk */
@property ref ifr_broadaddr(ref ifreq this_) { return this_.ifr_ifru.ifru_broadaddr; } /* broadcast address */
@property ref ifr_netmask(ref ifreq this_) { return this_.ifr_ifru.ifru_netmask; } /* interface net mask */
@property ref ifr_flags(ref ifreq this_) { return this_.ifr_ifru.ifru_flags; } /* flags */
@property ref ifr_metric(ref ifreq this_) { return this_.ifr_ifru.ifru_ivalue; } /* metric */
@property ref ifr_mtu(ref ifreq this_) { return this_.ifr_ifru.ifru_mtu; } /* mtu */
@property ref ifr_map(ref ifreq this_) { return this_.ifr_ifru.ifru_map; } /* device map */
@property ref ifr_slave(ref ifreq this_) { return this_.ifr_ifru.ifru_slave; } /* slave device */
@property ref ifr_data(ref ifreq this_) { return this_.ifr_ifru.ifru_data; } /* for use by interface */
@property ref ifr_ifindex(ref ifreq this_) { return this_.ifr_ifru.ifru_ivalue; } /* interface index */
@property ref ifr_bandwidth(ref ifreq this_) { return this_.ifr_ifru.ifru_ivalue; } /* link bandwidth */
@property ref ifr_qlen(ref ifreq this_) { return this_.ifr_ifru.ifru_ivalue; } /* queue length */
@property ref ifr_newname(ref ifreq this_) { return this_.ifr_ifru.ifru_newname; } /* New name */
}
enum IFHWADDRLEN = 6;
enum IFNAMSIZ = IF_NAMESIZE;
/* Structure used in SIOCGIFCONF request. Used to retrieve interface
configuration for machine (useful for programs which must know all
networks accessible). */
struct ifconf
{
int ifc_len; /* Size of buffer. */
union ifc_ifcu_t
{
__caddr_t ifcu_buf;
ifreq* ifcu_req;
}
ifc_ifcu_t ifc_ifcu;
@property ref ifc_buf() { return this.ifc_ifcu.ifcu_buf; } /* Buffer address. */
@property ref ifc_req() { return this.ifc_ifcu.ifcu_req; } /* Array of structures. */
@property void ifc_buf(char* buf) { this.ifc_ifcu.ifcu_buf = buf; }
@property void ifc_req(ifreq* r) { this.ifc_ifcu.ifcu_req = r; }
}
/* Misc. */
/* Convert an interface name to an index, and vice versa. */
uint if_nametoindex (const(char)* __ifname);
char* if_indextoname (uint __ifindex, char* __ifname);
/* Return a list of all interfaces and their indices. */
if_nameindex_* if_nameindex ();
/* Free the data returned from if_nameindex. */
void if_freenameindex (if_nameindex_* __ptr);
/* net/if.h */
void main()
{
import core.sys.posix.sys.ioctl;
import std.experimental.all;
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0)
return;
// enumerate all IP addresses of the system
auto conf = ifconf();
char[128 * ifreq.sizeof] ifconfbuf;
conf.ifc_buf = ifconfbuf.ptr;
conf.ifc_len = ifconfbuf.sizeof;
if (ioctl(sock, SIOCGIFCONF, &conf))
{
assert(false);
return;
}
// get MAC address
bool foundMac1;
ifreq* ifr;
for (ifr = conf.ifc_req; cast(char*) ifr < cast(char*) conf.ifc_req + conf.ifc_len; ifr++)
{
if (ifr.ifr_addr.sa_data == (ifr + 1).ifr_addr.sa_data)
continue; // duplicate, skip it
if (ioctl(sock, SIOCGIFFLAGS, ifr))
continue; // failed to get flags, skip it
if (ioctl(sock, SIOCGIFHWADDR, ifr) == 0)
writeln(ifr.ifr_addr.sa_data);
}
// close(sock);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment