此处提到的代码获取网络接口和相应地址的列表。
----------------------------------------------------------------
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;
}
我不明白 line 的原因ifsize = sizeof(ifr->ifr_name) + SIZE(ifr->ifr_addr);
为什么在这里直接使用sizeof(struct ifreq)
失败?
编辑 1:我也想了解 SIZE 宏背后的逻辑。
**编辑 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 */
};