Как перечислить все IP-адреса, подключенные к машине в POSIX C?

Если Вы используете exec в функции, переменные правила поиска изменяются решительно. Закрытия больше не возможны, но Python позволяет произвольные идентификаторы в функции. Это дает Вам "модифицируемых местных жителей ()" и может привыкнуть к идентификаторам звездообразного импорта. На оборотной стороне это делает каждый поиск медленнее, потому что переменные заканчиваются в dict, а не слотах в кадре:

>>> def f():
...  exec "a = 42"
...  return a
... 
>>> def g():
...  a = 42
...  return a
... 
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_CONST               1 ('a = 42')
              3 LOAD_CONST               0 (None)
              6 DUP_TOP             
              7 EXEC_STMT           

  3           8 LOAD_NAME                0 (a)
             11 RETURN_VALUE        
>>> dis.dis(g)
  2           0 LOAD_CONST               1 (42)
              3 STORE_FAST               0 (a)

  3           6 LOAD_FAST                0 (a)
              9 RETURN_VALUE        
5
задан Community 23 May 2017 в 12:34
поделиться

6 ответов

Это можно сделать только в зависимости от операционной системы. Вы можете попробовать разобрать вывод iptables, но правильный ответ для Linux - использовать ioctl.

 SIOCGIFCONF принимает struct ifconf *. Поле ifc_buf указывает на
 буфер длиной ifc_len bytes, в который ядро ​​записывает список
 введите struct ifreq [].

Структура struct ifreq задокументирована в linux / if.h:

struct ifreq 
{
#define IFHWADDRLEN     6
        union
        {
                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
        } ifr_ifrn;

        union {
                struct  sockaddr ifru_addr;
                struct  sockaddr ifru_dstaddr;
                struct  sockaddr ifru_broadaddr;
                struct  sockaddr ifru_netmask;
                struct  sockaddr ifru_hwaddr;
                short   ifru_flags;
                int     ifru_ivalue;
                int     ifru_mtu;
                struct  ifmap ifru_map;
                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
                char    ifru_newname[IFNAMSIZ];
                void *  ifru_data;
                struct  if_settings ifru_settings;
        } ifr_ifru;
};

Как видите, она содержит необходимую вам адресную информацию.

6
ответ дан 18 December 2019 в 12:00
поделиться

Вот мое доказательство концептуального кода с использованием принятого ответа Каски для потомков:

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>


static const char * flags(int sd, const char * name)
{
    static char buf[1024];

    static struct ifreq ifreq;
    strcpy(ifreq.ifr_name, name);

    int r = ioctl(sd, SIOCGIFFLAGS, (char *)&ifreq);
    assert(r == 0);

    int l = 0;
#define FLAG(b) if(ifreq.ifr_flags & b) l += snprintf(buf + l, sizeof(buf) - l, #b " ")
    FLAG(IFF_UP);
    FLAG(IFF_BROADCAST);
    FLAG(IFF_DEBUG);
    FLAG(IFF_LOOPBACK);
    FLAG(IFF_POINTOPOINT);
    FLAG(IFF_RUNNING);
    FLAG(IFF_NOARP);
    FLAG(IFF_PROMISC);
    FLAG(IFF_NOTRAILERS);
    FLAG(IFF_ALLMULTI);
    FLAG(IFF_MASTER);
    FLAG(IFF_SLAVE);
    FLAG(IFF_MULTICAST);
    FLAG(IFF_PORTSEL);
    FLAG(IFF_AUTOMEDIA);
    FLAG(IFF_DYNAMIC);
#undef FLAG

    return buf;
}

int main(void)
{
    static struct ifreq ifreqs[32];
    struct ifconf ifconf;
    memset(&ifconf, 0, sizeof(ifconf));
    ifconf.ifc_req = ifreqs;
    ifconf.ifc_len = sizeof(ifreqs);

    int sd = socket(PF_INET, SOCK_STREAM, 0);
    assert(sd >= 0);

    int r = ioctl(sd, SIOCGIFCONF, (char *)&ifconf);
    assert(r == 0);

    for(int i = 0; i < ifconf.ifc_len/sizeof(struct ifreq); ++i)
    {
        printf("%s: %s\n", ifreqs[i].ifr_name, inet_ntoa(((struct sockaddr_in *)&ifreqs[i].ifr_addr)->sin_addr));
        printf(" flags: %s\n", flags(sd, ifreqs[i].ifr_name));
    }

    close(sd);

    return 0;
}

Работает как шарм!

7
ответ дан 18 December 2019 в 12:00
поделиться

вы уверены, что правильно используете gethostname () / gethostbyname ()? проверьте здесь , единственная проблема, которую я вижу при этом, заключается в том, что возможно, что имя домена имеет несколько сопоставленных IP-адресов. В таком случае невозможно узнать, какой IP-адрес принадлежит локальной машине

.
0
ответ дан 18 December 2019 в 12:00
поделиться

Некоторые ответы на дополнительные вопросы:

  • Добавление нескольких IP-адресов к устройству может выполняться с использованием псевдонимов. Когда вы это делаете, Linux создает устройства с именами типа eth0: 0.

    ifconfig eth0: 0 10.0.0.1

  • Наличие одного и того же IP-адреса на нескольких устройствах может быть выполнено с помощью связывания каналов / агрегации каналов.

1
ответ дан 18 December 2019 в 12:00
поделиться

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

Учитывая список из все IP-адреса, как мне отфильтровать адреса обратной связи?

См. структуру ifreq в ответе caskey. Вы можете определить петлю (правильно) с помощью:

if (ifru_flags & IFF_LOOPBACK) 

Константы находятся в if.h

1
ответ дан 18 December 2019 в 12:00
поделиться

Как мне получить список всех IP-адресов, по которым машина может устанавливать исходящие (т. Е. К любому другому компьютеру) соединения? Имея список всех IP-адресов, как мне отфильтровать адреса обратной связи?

Посмотрите исходный код lsof и netstat . Вы увидите, что это включает в себя обход структур памяти ядра, а не только выполнение системных вызовов.

0
ответ дан 18 December 2019 в 12:00
поделиться
Другие вопросы по тегам:

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