Skip to content

Instantly share code, notes, and snippets.

@OrangeTide
Created April 8, 2011 02:59
Show Gist options
  • Save OrangeTide/909204 to your computer and use it in GitHub Desktop.
Save OrangeTide/909204 to your computer and use it in GitHub Desktop.
example to list network interfaces on linux/bsd/osx/etc
/* showif.c : PUBLIC DOMAIN - Jon Mayo - August 22, 2006
* - You may remove any comments you wish, modify this code any way you wish,
* and distribute any way you wish.*/
/* finds all network interfaces and shows a little information about them.
* some operating systems list interfaces multiple times because of different
* flags, modes, etc. if you want to use this code you should be aware that
* duplicate interfaces is a possibility */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <netdb.h>
static void show_interface(int fd, const char *name) {
int family;
struct ifreq ifreq;
char host[128];
memset(&ifreq, 0, sizeof ifreq);
strncpy(ifreq.ifr_name, name, IFNAMSIZ);
if(ioctl(fd, SIOCGIFADDR, &ifreq)!=0) {
/* perror(name); */
return; /* ignore */
}
switch(family=ifreq.ifr_addr.sa_family) {
case AF_UNSPEC:
return; /* ignore */
case AF_INET:
case AF_INET6:
getnameinfo(&ifreq.ifr_addr, sizeof ifreq.ifr_addr, host, sizeof host, 0, 0, NI_NUMERICHOST);
break;
default:
sprintf(host, "unknown (family: %d)", family);
}
printf("%-24s%s\n", name, host);
}
static void list_interfaces(int fd, void (*show)(int fd, const char *name)) {
struct ifreq *ifreq;
struct ifconf ifconf;
char buf[16384];
unsigned i;
size_t len;
ifconf.ifc_len=sizeof buf;
ifconf.ifc_buf=buf;
if(ioctl(fd, SIOCGIFCONF, &ifconf)!=0) {
perror("ioctl(SIOCGIFCONF)");
exit(EXIT_FAILURE);
}
ifreq=ifconf.ifc_req;
for(i=0;i<ifconf.ifc_len;) {
/* some systems have ifr_addr.sa_len and adjust the length that
* way, but not mine. weird */
#ifndef linux
len=IFNAMSIZ + ifreq->ifr_addr.sa_len;
#else
len=sizeof *ifreq;
#endif
if(show) {
show(fd, ifreq->ifr_name);
} else {
printf("%s\n", ifreq->ifr_name);
}
ifreq=(struct ifreq*)((char*)ifreq+len);
i+=len;
}
}
void show_all_interfaces(int family) {
int fd;
fd=socket(family, SOCK_DGRAM, 0);
if(fd<0) {
perror("socket()");
exit(EXIT_FAILURE);
}
list_interfaces(fd, show_interface);
close(fd);
}
int main() {
show_all_interfaces(PF_INET); /* IPv4 */
show_all_interfaces(PF_INET6); /* IPv6 */
return EXIT_SUCCESS;
}
@ebarcikowski
Copy link

Thanks for the trick on line 60 for OSX. Saved me some time hunting that down.

@sherlock1982
Copy link

Will not work for IPV6 because of SIOCGIFADDR

@lwerdna
Copy link

lwerdna commented Oct 6, 2017

@sherlock1982: works ok here (confirmed vs. ifconfig) on Sierra 10.12.4

@Feng-Zihao
Copy link

Thanks. !!

#ifndef linux
len=IFNAMSIZ + ifreq->ifr_addr.sa_len;
#else
len=sizeof *ifreq;
#endif

This is exactly wired. But works.

@OrangeTide
Copy link
Author

Some old code but still seems useful to some of you. I'm happy to accept improvements if anyone has suggestions. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment