2013-08-01 2 views
0

В приведенном коде here представлен список сетевых интерфейсов и соответствующих адресов.Измерение размера структуры путем подсчета размера элементов

---------------------------------------------------------------- 
header file - ifaddrs.h 
---------------------------------------------------------------- 

#ifndef GENERIC_AIX_IFADDRS_H 
#define GENERIC_AIX_IFADDRS_H 

#include <sys/socket.h> 
#include <net/if.h> 

#undef ifa_dstaddr 
#undef ifa_broadaddr 
#define ifa_broadaddr ifa_dstaddr 

struct ifaddrs { 
    struct ifaddrs *ifa_next; 
    char   *ifa_name; 
    unsigned int  ifa_flags; 
    struct sockaddr *ifa_addr; 
    struct sockaddr *ifa_netmask; 
    struct sockaddr *ifa_dstaddr; 
}; 

extern int getifaddrs(struct ifaddrs **); 
extern void freeifaddrs(struct ifaddrs *); 

#endif 

---------------------------------------------------------------- 
source file - getifaddrs.c 
---------------------------------------------------------------- 

#include <string.h> 
#include <sys/ioctl.h> 

#include "ifaddrs.h" 

/******************************************************************** 
*** NOTE: this generic version written specifically for AIX 5.3 *** 
********************************************************************/ 

#define MAX(x,y) ((x)>(y)?(x):(y)) 
#define SIZE(p) MAX((p).sa_len,sizeof(p)) 


static struct sockaddr * 
sa_dup (struct sockaddr *sa1) 
{ 
    struct sockaddr *sa2; 
    size_t sz = sa1->sa_len; 
    sa2 = (struct sockaddr *) calloc(1,sz); 
    memcpy(sa2,sa1,sz); 
    return(sa2); 
} 


void freeifaddrs (struct ifaddrs *ifp) 
{ 
    if (NULL == ifp) return; 
    free(ifp->ifa_name); 
    free(ifp->ifa_addr); 
    free(ifp->ifa_netmask); 
    free(ifp->ifa_dstaddr); 
    freeifaddrs(ifp->ifa_next); 
    free(ifp); 
} 


int getifaddrs (struct ifaddrs **ifap) 
{ 
    int sd, ifsize; 
    char *ccp, *ecp; 
    struct ifconf ifc; 
    struct ifreq *ifr; 
    struct ifaddrs *cifa = NULL; /* current */ 
    struct ifaddrs *pifa = NULL; /* previous */ 
    const size_t IFREQSZ = sizeof(struct ifreq); 

    sd = socket(AF_INET, SOCK_DGRAM, 0); 

    *ifap = NULL; 

    /* find how much memory to allocate for the SIOCGIFCONF call */ 
    if (ioctl(sd, SIOCGSIZIFCONF, (caddr_t)&ifsize) < 0) return(-1); 

    ifc.ifc_req = (struct ifreq *) calloc(1,ifsize); 
    ifc.ifc_len = ifsize; 

    if (ioctl(sd, SIOCGIFCONF, &ifc) < 0) return(-1); 

    ccp = (char *)ifc.ifc_req; 
    ecp = ccp + ifsize; 

    while (ccp < ecp) { 

    ifr = (struct ifreq *) ccp; 
    ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr); 
    cifa = (struct ifaddrs *) calloc(1, sizeof(struct ifaddrs)); 
    cifa->ifa_next = NULL; 
    cifa->ifa_name = strdup(ifr->ifr_name); 

    if (pifa == NULL) *ifap = cifa; /* first one */ 
    else  pifa->ifa_next = cifa; 

    if (ioctl(sd, SIOCGIFADDR, ifr, IFREQSZ) < 0) return(-1); 
    cifa->ifa_addr = sa_dup(&ifr->ifr_addr); 

    if (ioctl(sd, SIOCGIFNETMASK, ifr, IFREQSZ) < 0) return(-1); 
    cifa->ifa_netmask = sa_dup(&ifr->ifr_addr); 

    cifa->ifa_flags = 0; 
    cifa->ifa_dstaddr = NULL; 

    if (0 == ioctl(sd, SIOCGIFFLAGS, ifr)) /* optional */ 
     cifa->ifa_flags = ifr->ifr_flags; 

    if (ioctl(sd, SIOCGIFDSTADDR, ifr, IFREQSZ) < 0) { 
     if (0 == ioctl(sd, SIOCGIFBRDADDR, ifr, IFREQSZ)) 
     cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); 
    } 
    else cifa->ifa_dstaddr = sa_dup(&ifr->ifr_addr); 

    pifa = cifa; 
    ccp += ifsize; 
    } 
    return 0; 
} 

Я не понимаю причину линии ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr); Почему непосредственно с помощью sizeof(struct ifreq) терпит неудачу здесь?

Редактировать 1: Также я хотел бы понять логику макроса SIZE.

** Edit 2: структура ifreq как:

struct ifreq { 
#ifndef IFNAMSIZ  /* Also in net_if.h */ 
#define IFNAMSIZ  16 
#endif 
     char ifr_name[IFNAMSIZ];    /* if name, e.g. "en0" */ 
     union { 
       struct sockaddr ifru_addr; 
       struct sockaddr ifru_dstaddr; 
       struct sockaddr ifru_broadaddr; 
       __ulong32_t  ifru_flags; 
       int  ifru_metric; 
       caddr_t ifru_data; 
       u_short ifru_site6; 
       __ulong32_t ifru_mtu; 
       int  ifru_baudrate; 
       int  ifru_checksum_offload[2]; 
     } ifr_ifru; 
#define ifr_addr  ifr_ifru.ifru_addr  /* address */ 
#define ifr_dstaddr  ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ 
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ 
#define ifr_flags  ifr_ifru.ifru_flags  /* flags */ 
#define ifr_metric  ifr_ifru.ifru_metric /* metric */ 
#define ifr_data  ifr_ifru.ifru_data  /* for use by interface */ 
#define ifr_site6  ifr_ifru.ifru_site6  /* IPv6 site index */ 
#define ifr_mtu   ifr_ifru.ifru_mtu  /* mtu of interface */ 
#define ifr_isno  ifr_ifru.ifru_data  /* pointer to if_netopts */ 
#define ifr_baudrate ifr_ifru.ifru_baudrate /* baudrate of interface */ 
#define ifr_checksum_offload ifr_ifru.ifru_checksum_offload[1] /* checksum offload active or not */ 
}; 
+3

Возможно, вопрос [Почему размер sizeof для структуры не равен сумме sizeof каждого члена?] (Http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct- равный сумме размера каждого члена). –

+0

И почему SIZE был определен следующим образом? – Xolve

+0

Предоставьте :: struct ifreq {???} – JackCColeman

ответ

0

SIZE(p) макрос возвращает максимум ifr->ifr_addr.sa_len и sizeof(struct sockaddr).

SIZE(ifr->ifr_addr) будет расширен до MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)).

MAX macro предназначен для возврата наибольшего из этих двух и будет расширен как.

((ifr->ifr_addr.sa_len)>(sizeof(ifr->ifr_addr))?(ifr->ifr_addr.sa_len):(sizeof(ifr->ifr_addr)))

Смежные вопросы