tags:

views:

492

answers:

8

I need to display all the ip addresses from my local computer, using C language. How this can be done?

Thanks.

+3  A: 

Not a complete solution yet, but take a look in /proc/net!

  • dev lists the available interface devices by name,
  • route lists some routes, as does ipv6_route,
  • arp lists devices in the actual routing table (does not include localhost).

Not as high-tech as the other solution, but it can be done with simple file reading. Linux specific, though.

Carl Smotricz
+1  A: 
#include <stdio.h>
#include <stdlib.h>

/*
 * Who sez?
 * http://blog.stackoverflow.com/2010/01/stack-overflow-where-we-hate-fun/
 */
int main(int argc, char *argv[])
{
  const char *cmd = "ifconfig -a | \
                     perl -ne 'print $1, \"\\n\" \
                       if /inet6? addr:\\s*(\\S+)/'";
  int status;

  status = system(cmd);
  if (status != 0)
    fprintf(stderr, "%s: system returned %d\n", argv[0], status);

  return 0;
}
Greg Bacon
Using C to write Perl... That's um... cheating :P. And totally nonportable.
Macha
-1 for being a wrapper around a higher language and other utility
PP
@Macha Which Linux distribution does not ship with perl? I also gave an all-C answer. http://blog.stackoverflow.com/2010/01/stack-overflow-where-we-hate-fun/
Greg Bacon
+2 for more conciseness and maintainability than the accepted answer.
molecules
+2  A: 

How about you simply cheat and look at the source of /sbin/ifconfig/ ? Nothing wrong with standing on the shoulders of other giants...

Dirk Eddelbuettel
A: 
$ sudo ifconfig | grep 'inet addr' | cut -d':' -f2 | cut -d' ' -f1
213.xx.xxx.xx
192.168.xx.x
127.0.0.1

And you can put that into popen():

/* not tested */
ph = popen("sudo ifconfig | grep 'inet addr' | cut -d':' -f2 | cut -d' ' -f1", "r");
while (fgets(buf, sizeof buf, ph)) {
    /* ip address, in nul-terminated string format, is in `buf` */
}
pclose(ph);
pmg
-1 for using shell commands in C code. IMO this shouldn't be advised. A solution using the actual language and system/library calls is much better. Especially for a beginner question like this.
Steve Lazaridis
+2  A: 

You need POSIX function getaddrinfo() - it returns linked list of all IP addresses.

See man getaddrinfo for details and examples.

qrdl
+6  A: 
#include <stdio.h>
#include <stropts.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netdevice.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

int print_addresses(const int domain)
{
  int s;
  struct ifconf ifconf;
  struct ifreq ifr[50];
  int ifs;
  int i;

  s = socket(domain, SOCK_STREAM, 0);
  if (s < 0) {
    perror("socket");
    return 0;
  }

  ifconf.ifc_buf = (char *) ifr;
  ifconf.ifc_len = sizeof ifr;

  if (ioctl(s, SIOCGIFCONF, &ifconf) == -1) {
    perror("ioctl");
    return 0;
  }

  ifs = ifconf.ifc_len / sizeof(ifr[0]);
  printf("interfaces = %d:\n", ifs);
  for (i = 0; i < ifs; i++) {
    char ip[INET_ADDRSTRLEN];
    struct sockaddr_in *s_in = (struct sockaddr_in *) &ifr[i].ifr_addr;

    if (!inet_ntop(domain, &s_in->sin_addr, ip, sizeof(ip))) {
      perror("inet_ntop");
      return 0;
    }

    printf("%s - %s\n", ifr[i].ifr_name, ip);
  }

  close(s);

  return 1;
}

int main(int argc, char *argv[])
{
  int domains[] = { AF_INET, AF_INET6 };
  int i;

  for (i = 0; i < sizeof(domains) / sizeof(domains[0]); i++)
    if (!print_addresses(domains[i]))
      return 1;

  return 0;
}
Greg Bacon
+4  A: 

Your question might be imprecise but I am not sure why everyone is breaking your chops.

I think you are asking the basics in which case you probably want is getifaddrs. The man page has a little example program.

You can also get similar info using the SIOCGIFCONF option with ioctl(). There is some sample code on here and the web.

If you search around for these and similar terms you will find this question has been asked in various forms before. You have to dig around a bit.

Also note, these will not give you the public facing IP of your network if you are behind NAT.

Duck
+2  A: 

Another way to do it in C. I do have to say though.... there are so many ways to do it from the shell, what's the point?

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/if.h>

#include <errno.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>


void show_address_info( struct ifaddrs *ifa ){
  struct sockaddr_in *s4;
  struct sockaddr_in6 *s6;
  /* ipv6 addresses have to fit in this buffer */
  char buf[64];

  if (AF_INET == ifa->ifa_addr->sa_family){
    s4 = (struct sockaddr_in *)(ifa->ifa_addr);
    if (NULL == inet_ntop(ifa->ifa_addr->sa_family, (void *)&(s4->sin_addr), buf, sizeof(buf))){
      printf("%s: inet_ntop failed!\n", ifa->ifa_name);
    } else {
      printf("IPv4 addr %s: %s\n", ifa->ifa_name, buf);
    }
  }
  else if (AF_INET6 == ifa->ifa_addr->sa_family) {
    s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
    if (NULL == inet_ntop(ifa->ifa_addr->sa_family, (void *)&(s6->sin6_addr), buf, sizeof(buf))) {
      printf("%s: inet_ntop failed!\n", ifa->ifa_name);
    } else {
      printf("IPv6 addr %s: %s\n", ifa->ifa_name, buf);
      }
  }

}


int main(int argc, char **argv){
  struct ifaddrs *myaddrs, *ifa;
  int status;

  status = getifaddrs(&myaddrs);
  if (status != 0){
    perror("getifaddrs failed!");
    exit(1);
  }

  for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next){
    if (NULL == ifa->ifa_addr){
      continue;
    }
    if ((ifa->ifa_flags & IFF_UP) == 0) {
      continue;
    }
    show_address_info(ifa);
  }
  freeifaddrs(myaddrs);
  return 0;
}
Jason Stelzer