Chinaunix首页 | 论坛 | 博客
  • 博客访问: 749582
  • 博文数量: 3
  • 博客积分: 8011
  • 博客等级: 中将
  • 技术积分: 885
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-03 09:38
文章分类

全部博文(3)

文章存档

2008年(3)

我的朋友

分类: C/C++

2008-05-13 11:17:32

代码基本上是摘自"Unix 网络编程"

头文件:

#ifndef __NET_INF_H
#define __NET_INF_H

#include <net/if.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define IFI_NAME 16
#define IFI_HADDR 8

typedef struct ifi_info
{
  char ifi_name[IFI_NAME];
  u_char ifi_haddr[IFI_HADDR];
  u_short ifi_hlen;
  short ifi_flags;
  short ifi_myflags;
  struct sockaddr *ifi_addr;
  struct sockaddr *ifi_brdaddr;
  struct sockaddr *ifi_dstaddr;
  struct ifi_info *ifi_next;
}ifi_info;

#define IFI_ALIAS 1

struct ifi_info *get_ifi_info(int, int);

void free_ifi_info(struct ifi_info *);

#endif


主程序:

#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);
}

阅读(7792) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~