Проблема с адресом IPv6 в структуре ifreq - PullRequest
2 голосов
/ 01 апреля 2011

Я работаю со следующим кодом:

struct sockaddr_in6 *sin;
struct ifreq ifr;
sin = (struct sockaddr_in6 *)&ifr.ifr_addr;

ifr_addr относится к типу struct sockaddr, который для удобства описан здесь:

struct sockaddr {
        sa_family_t     sa_family;      /* address family, AF_xxx       */
        char            sa_data[14];    /* 14 bytes of protocol address */
};

Как ядолжен ввести IPv6-адрес (через sin->sin6_addr.s6_addr) в поле ifr_addr, если доступно только 14 байтов?

Где я ошибаюсь?

TIA, Chris

Ответы [ 2 ]

3 голосов
/ 01 апреля 2011

К счастью, struct ifreq объявляется содержащим адреса в объединении в конце структуры:

struct ifreq
  {


    union
      {
 char ifrn_name[16];
      } ifr_ifrn;

    union
      {
 struct sockaddr ifru_addr;
 struct sockaddr ifru_dstaddr;
 struct sockaddr ifru_broadaddr;
 struct sockaddr ifru_netmask;
 struct sockaddr ifru_hwaddr;
 short int ifru_flags;
 int ifru_ivalue;
 int ifru_mtu;
 struct ifmap ifru_map;
 char ifru_slave[16];
 char ifru_newname[16];
 __caddr_t ifru_data;
      } ifr_ifru;
  };

Обратите внимание, что вышеприведенный результат был результатом gcc -E, поэтому весь материал препроцессора был расширен. Также обратите внимание, что ifr_addr это #define d, чтобы быть ifr_ifru.ifru_addr.

Это означает, что технически вы можете выделить байты за пределами структуры для хранения адреса.

На мой взгляд, это очень небрежно. Должно быть объявлено, что объединение содержит значение типа sockaddr_storage вместе со всем остальным. Тогда размер структуры будет достаточно большим, чтобы вместить любой адрес.

Если вы хотите объявить свою собственную структуру правильного размера, которую вы можете использовать довольно легко, просто сделайте это:

union my_ifreq {
    struct ifreq sys_ifreq;
    struct {
        char name_pad[IFNAMSIZ];
        struct sockaddr_storage addr;
    } padding;
};

Тогда у вас будет структура, в которой всегда будет достаточно памяти, чтобы вы могли вставить любой действительный адрес в sys_ifreq.ifr_addr и заставить его работать.

0 голосов
/ 02 апреля 2011

Платформы, которые используют struct sockaddr внутри struct ifreq, также имеют дружественную для IPv6 версию struct lifreq, в которой вместо * используется, например, Solaris, другие платформы, такие как Linux и AIX, уже используют более длинную структуру.

...