Как я произвожу IP-адреса своего хоста из программы C?

Я должен отобразить все IP-адреса от своего локального компьютера, с помощью языка C. Как это может быть сделано?

15
задан Peter Mortensen 25 March 2016 в 13:17
поделиться

8 ответов

#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;
}
13
ответ дан 1 December 2019 в 01:30
поделиться

Пока еще не готовое решение, но посмотрите в /proc/net !

  • dev перечисляет доступные интерфейсные устройства по имени,
  • route перечисляет некоторые маршруты, так же как и ipv6_route,
  • arp перечисляет устройства в реальной таблице маршрутизации (не включает localhost).

Не так высокотехнологично, как другое решение, но это может быть сделано с помощью простого чтения файлов. Однако, для Linux

.
3
ответ дан 1 December 2019 в 01:30
поделиться
$ sudo ifconfig | grep 'inet addr' | cut -d':' -f2 | cut -d' ' -f1
213.xx.xxx.xx
192.168.xx.x
127.0.0.1

И вы можете поместить это в 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);
-2
ответ дан 1 December 2019 в 01:30
поделиться
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

/*
 * Who sez?
 * http://blog.stackoverflow.com/2010/01/stack-overflow-where-we-hate-fun/
 */
int main(int argc, char *argv[])
{
  int status;
  const char * const cmd =  /* die from END is too chatty */
    "/sbin/ifconfig -a | \
     perl -lne \
       'print $1 if /inet6? addr:\\s*(\\S+)/; \
        END { $. > 0 or \
                warn(\"no output from ifconfig\\n\"), \
                exit 1; }'";

  status = system(cmd);
  if (status < 0) {
    perror("system");
    return 1;
  }
  else if (status != 0) {
    const char *extra;
    status = WEXITSTATUS(status);
    extra = status == 127 ? " (is /bin/sh ok?)" : "";
    fprintf(stderr, "%s: command failed with status %d%s\n",
            argv[0], status, extra);
  }

  return 0;
}
.
-3
ответ дан 1 December 2019 в 01:30
поделиться

Другой способ сделать это в C. Я должен сказать, что ... существует так много способов сделать это из оболочки, в чем смысл?

#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;
}
8
ответ дан 1 December 2019 в 01:30
поделиться

Ваш вопрос может быть неточным, но я не уверен, почему все ломают вам отбивные.

Я думаю, что вы спрашиваете основы, и в этом случае вы, вероятно, хотите гетифаддры . В man-странице есть небольшая примерная программа.

Вы также можете получить подобную информацию, используя опцию SIOCGIFCONF с помощью ioctl(). Здесь и в интернете есть примеры кода на here.

Если вы будете искать вокруг этих и подобных терминов, вы обнаружите, что этот вопрос уже задавался в различных формах. Вы должны немного покопаться.

Также обратите внимание, что это не даст вам публичный IP-адрес вашей сети, если вы находитесь за NAT.

10
ответ дан 1 December 2019 в 01:30
поделиться

Как насчет того, чтобы просто обмануть и посмотреть на источник /sbin/ifconfig/ ? Нет ничего плохого в том, чтобы стоять на плечах других гигантов...

4
ответ дан 1 December 2019 в 01:30
поделиться

Вам нужна POSIX-функция getaddrinfo() - она возвращает связанный список всех IP-адресов.

Смотрите man getaddrinfo для получения подробностей и примеров.

2
ответ дан 1 December 2019 в 01:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: