Get interface list and MAC addresses on Solaris

For CA Nimsoft Monitor, I had to implement the ability to get a list of ethernet interfaces and corresponding MAC addresses on Solaris. The basic process is:

  • Create a socket to be used for ioctl() calls
  • Use SIOCGIFCONF ioctl() call to get list of interfaces
  • For each interface, get name and IP address from the SIOCGIFCONF result
  • For each interface, use SIOCGARP ioctl() call to get the MAC address

Here’s the result:

void get_interfaces() {
char buf[8192] = {0};
struct ifconf ifc = {0};
struct ifreq *ifr = NULL;
int sck = 0;
int nInterfaces = 0;
int i, j;
char ip[INET6_ADDRSTRLEN] = {0};
char macp[19];
struct ifreq *item;
struct sockaddr *addr;
struct arpreq arpreq;

/* Get a socket handle. */
if ( sck = socket(AF_INET, SOCK_DGRAM, 0) ) {
/* Query available interfaces. */
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;

if( ioctl(sck, SIOCGIFCONF, &ifc) == 0 ) {
/* Iterate through the list of interfaces. */
ifr = ifc.ifc_req;
nInterfaces = ifc.ifc_len / sizeof(struct ifreq);

for(i = 0; i < nInterfaces; i++) { item = &ifr[i]; addr = &(item->ifr_addr);

/* The interface name: .... = strdup(item->ifr_name); */

/* Get the IP address */
if( ioctl(sck, SIOCGIFADDR, item) >= 0 ) {
if (inet_ntop(AF_INET, &(((struct sockaddr_in *)addr)->sin_addr), ip, sizeof ip) == NULL)
continue;

/* The IP address: .... = strdup(ip); */

/* Get the MAC address */
memcpy(&arpreq.arp_pa,addr,sizeof(struct sockaddr));
if (ioctl(sck,SIOCGARP,(char*)&arpreq) == 0) {
sprintf(macp, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)arpreq.arp_ha.sa_data[0],
(unsigned char)arpreq.arp_ha.sa_data[1],
(unsigned char)arpreq.arp_ha.sa_data[2],
(unsigned char)arpreq.arp_ha.sa_data[3],
(unsigned char)arpreq.arp_ha.sa_data[4],
(unsigned char)arpreq.arp_ha.sa_data[5]);

/* The formatted MAC address: .... = strdup(macp); */
}
}
}
}

close(sck);
}
}