c - Measuring size of struct by counting size of members -


the code mentioned here gets list of network interfaces , corresponding addresses.

---------------------------------------------------------------- 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: generic version written 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 memory allocate 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 1 */     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; } 

i not understand reason line ifsize = sizeof(ifr->ifr_name) + size(ifr->ifr_addr); why directly using sizeof(struct ifreq) fails here?

edit 1: understand logic behind size macro.

**edit 2: struct ifreq as:

struct  ifreq { #ifndef ifnamsiz        /* 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      /* use 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 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 */ }; 

size(p) macro return maximum of ifr->ifr_addr.sa_len , sizeof(struct sockaddr).

size(ifr->ifr_addr) expanded max(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)).

max macro defined return greatest of these 2 , expanded like.

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


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

How to get multiresult with multicondition in Sql Server -