#include "net_if.h"
ifi_info *get_ifi_info(int family, int doaliases)
{
ifi_info *ifi, *ifihead, **ifipnext;
int sockfd, len, lastlen, flags, myflags;
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
if ((sockfd=socket(AF_INET, SOCK_DGRAM, 0))<0)
{
printf("socket error.\n");
exit(1);
}
lastlen = 0;
len = 10*sizeof(struct ifreq);
while (1)
{
buf = (char*)malloc(len);
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (ioctl(sockfd, SIOCGIFCONF, &ifc)<0)
{
if (errno!=EINVAL||lastlen!=0)
{
printf("ioctl error.\n");
}
}
else
{
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10*sizeof(struct ifreq);
free(buf);
}
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
for (ptr = buf; ptr<buf+ifc.ifc_len;)
{
ifr = (struct ifreq*)ptr;
#ifdef HAVE_SOCKADDR_SA_LEN
len = sizeof(struct sockaddr)>ifr->ifr_addr.sa_len?sizeof(struct sockaddr):ifr->ifr_addr.sa_len;
#else
switch (ifr->ifr_addr.sa_family)
{
#ifdef IPV6
case: AF_INET6:
LEN = sizeof(struct sockaddr_in6);
break;
#endif
case AF_INET:
default:
len = sizeof(struct sockaddr);
break;
}
#endif
ptr += sizeof(ifr->ifr_name) + len;
if (ifr->ifr_addr.sa_family != family)
continue;
myflags = 0;
if ((cptr=strchr(ifr->ifr_name, ':'))!=NULL)
*cptr = 0;
if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ)==0)
{
if (doaliases == 0)
continue;
myflags = IFI_ALIAS;
}
memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
ifrcopy = *ifr;
ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);
flags = ifrcopy.ifr_flags;
if ((flags&IFF_UP)==0)
continue;
/*
if ((flags&IFF_BROADCAST)==0)
continue;
*/
ifi = calloc(1, sizeof(struct ifi_info));
*ifipnext = ifi;
ifipnext = &ifi->ifi_next;
ifi->ifi_flags = flags;
ifi->ifi_myflags = myflags;
memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
ifi->ifi_name[IFI_NAME-1] = '\0';
switch (ifr->ifr_addr.sa_family)
{
case AF_INET:
sinptr = (struct sockaddr_in *)&ifr->ifr_addr;
if (ifi->ifi_addr == NULL)
{
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
#ifdef SIOCGIFBRDADDR
if (flags & IFF_BROADCAST)
{
ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);
sinptr = (struct sockaddr_in *)&ifrcopy.ifr_broadaddr;
ifi->ifi_brdaddr = calloc(1, sizeof(struct sockaddr_in));
memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
}
#endif
#ifdef SIOCGIFDSTADDR
if (flags & IFF_POINTOPOINT)
{
ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
sinptr = (struct sockaddr_in*)&ifrcopy.ifr_dstaddr;
ifi->ifi_dstaddr = calloc(1, sizeof(struct sockaddr_in));
memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
}
#endif
}
break;
default:
break;
}
}
free(buf);
return(ifihead);
}
void free_ifi_info(ifi_info *ifihead)
{
ifi_info *ifi, *ifinext;
for (ifi=ifihead; ifi!=NULL; ifi=ifinext)
{
if (ifi->ifi_addr!=NULL)
free(ifi->ifi_addr);
if (ifi->ifi_brdaddr!=NULL)
free(ifi->ifi_brdaddr);
if (ifi->ifi_dstaddr!=NULL)
free(ifi->ifi_dstaddr);
ifinext = ifi->ifi_next;
free(ifi);
}
}
char *sock_ntop(const struct sockaddr *sa, socklen_t salen)
{
char portstr[7];
static char str[128];
switch (sa->sa_family)
{
case AF_INET:
{
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))==NULL)
return NULL;
if (ntohs(sin->sin_port)!=0)
{
snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port));
strcat(str, portstr);
}
return str;
}
break;
case AF_INET6:
{
struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa;
if (inet_ntop(AF_INET6, &sin->sin6_addr, str, sizeof(str))==NULL)
return NULL;
if (ntohs(sin->sin6_port)!=0)
{
snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin6_port));
strcat(str, portstr);
}
return str;
}
break;
default:
return NULL;
break;
}
}
int main(int argc, char *argv[])
{
ifi_info *ifi, *ifihead;
struct sockaddr *sa;
u_char *ptr;
int i, family, doaliases;
if (argc!=3)
{
printf("usage: prifinfo ");
exit(1);
}
if (strcmp(argv[1], "inet4") == 0)
family = AF_INET;
#ifdef IPV6
else if (strcmp(argv[1], "inet6") == 0)
family =AF_INET6;
#endif
else
{
printf("invalid ");
exit(1);
}
doaliases = atoi(argv[2]);
for(ifihead = ifi = get_ifi_info(family, doaliases);
ifi!=NULL;ifi=ifi->ifi_next)
{
printf("%s:<", ifi->ifi_name);
if (ifi->ifi_flags&IFF_UP) printf("UP");
if (ifi->ifi_flags&IFF_BROADCAST) printf("BCAST");
if (ifi->ifi_flags&IFF_MULTICAST) printf("MCAST");
if (ifi->ifi_flags&IFF_LOOPBACK) printf("LOOP");
if (ifi->ifi_flags&IFF_POINTOPOINT) printf("P2P");
printf(">\n");
if ((i=ifi->ifi_hlen)>0)
{
ptr = ifi->ifi_haddr;
do
{
printf("%s%x", (i==ifi->ifi_hlen)?" ":":", *ptr++);
}while(--i>0);
printf("\n");
}
if ((sa=ifi->ifi_addr)!=NULL)
printf(" IP addr: %s\n",
sock_ntop(sa, sizeof(*sa)));
if ((sa=ifi->ifi_brdaddr)!=NULL)
printf(" broadcast addr: %s\n",
sock_ntop(sa, sizeof(*sa)));
if ((sa=ifi->ifi_dstaddr)!=NULL)
printf(" destnation addr: %s\n",
sock_ntop(sa, sizeof(*sa)));
}
free_ifi_info(ifihead);
exit(0);
}
|