打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
ifconfig 源码分析(转载)
    int main(int argc, char **argv)
 
   ……
    argc--;
    argv++;
   
    while (argc&& *argv[0] == '-') {
    ……
   }

  打开内核支持的所有协议的套接字,主要是一个循环调用socket的过程
    if ((skfd = sockets_open(0))< 0) {
       perror("socket");
       exit(1);
    }


    if (argc == 0) {
       int err = if_print((char *) NULL);
       (void) close(skfd);
       exit(err < 0);
    }
   
    spp = argv;
    safe_strncpy(ifr.ifr_name,*spp++, IFNAMSIZ);
    if (*spp == (char *) NULL){
       int err = if_print(ifr.ifr_name);
       (void) close(skfd);
       exit(err < 0);
    }


    if ((ap = get_aftype(*spp))!= NULL)
       spp++;
    else
       ap = get_aftype(DFLT_AF);
      
    if (ap) {
       addr_family = ap->af;
       skfd = ap->fd;
    }

  
   while (*spp != (char *) NULL){
   
   }


    switch(ap->af) {
    ……
    r = ioctl(fd, SIOCSIFADDR,&ifr);
    ……
}
在主函数中判断argc,如果仅仅是输入了ifconfig而没有任何参数,则输出全部网卡信息
   
    if (argc == 0) {
       int err = if_print((char *) NULL);
       (void) close(skfd);
       exit(err < 0);
    }
   
   
函数if_print 定义在ifconfig.c中,用来输出网卡地址等信息:
static int if_print(char *ifname)
{
    int res;

    if(ife_short)              //如果是以省略模式输出
       printf(_("Iface  MTU Met   RX-OK RX-ERR RX-DRP RX-OVR   TX-OK TX-ERR TX-DRP TX-OVR Flg\n"));

    if (!ifname){             //如果ifname==NULL,则表示输出全部网卡的信息
       res = for_all_interfaces(do_if_print,&opt_a);
    } else {                    //否则仅仅输出ifname的。
       struct interface *ife;

       ife = lookup_interface(ifname);
       res = do_if_fetch(ife);
       if (res >= 0)
          ife_print(ife);
    }
    return res;
}

这里,又涉及到两个函数的调用:for_all_interfaces和lookup_interface。先来看for_all_interfaces
函数在interface.c中实现:
参数int (*doit) (struct interface *, void*)是一个指向函数的指针,为实际的功能函数,在上层函数中传递过来的是do_if_print
int for_all_interfaces(int (*doit) (struct interface *, void *),void *cookie)
{
    struct interface *ife;

    if (!int_list&& (if_readlist() <0))
       return -1;
    for (ife = int_list; ife; ife= ife->next) {
       int err = doit(ife, cookie);             //调用函数do_if_print实现
       if (err)
          returnerr;
    }
    return 0;
}


int do_if_print(struct interface *ife, void *cookie)
{
    int *opt_a = (int *)cookie;
    int res;

    res = do_if_fetch(ife);                    //提取出网卡的信息,置于结构ife中,顺便检查一下设备的合法性,如是否存在等等……
    if (res >= 0){   
       if ((ife->flags &IFF_UP) || *opt_a)
          ife_print(ife);                    //输出
    }
    return res;
}

int do_if_fetch(struct interface *ife)
{
    if (if_fetch(ife)< 0) {
       char *errmsg;
       if (errno == ENODEV) {
          
          errmsg =_("Device not found");
       } else {
          errmsg =strerror(errno);
       }
        fprintf(stderr, _("%s: error fetching interface information:%s\n"),
              ife->name,errmsg);
       return -1;
    }
    return 0;
}


int if_fetch(struct interface *ife)
{
    struct ifreq ifr;
    int fd;
    char *ifname =ife->name;

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd, SIOCGIFFLAGS,&ifr) < 0)                   
       return (-1);
    ife->flags =ifr.ifr_flags;

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd,SIOCGIFHWADDR, &ifr) < 0)
       memset(ife->hwaddr, 0, 32);
    else
       memcpy(ife->hwaddr,ifr.ifr_hwaddr.sa_data, 8);

    ife->type =ifr.ifr_hwaddr.sa_family;

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd,SIOCGIFMETRIC, &ifr) < 0)
       ife->metric = 0;
    else
       ife->metric =ifr.ifr_metric;

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd, SIOCGIFMTU,&ifr) < 0)
       ife->mtu = 0;
    else
       ife->mtu = ifr.ifr_mtu;

#ifdef HAVE_HWSLIP
    if (ife->type== ARPHRD_SLIP || ife->type == ARPHRD_CSLIP ||
       ife->type == ARPHRD_SLIP6 ||ife->type == ARPHRD_CSLIP6 ||
       ife->type == ARPHRD_ADAPT){
#ifdef SIOCGOUTFILL
       strcpy(ifr.ifr_name, ifname);
       if (ioctl(skfd, SIOCGOUTFILL,&ifr) < 0)
          ife->outfill= 0;
       else
          ife->outfill= (unsigned int) ifr.ifr_data;
#endif
#ifdef SIOCGKEEPALIVE
       strcpy(ifr.ifr_name, ifname);
       if (ioctl(skfd, SIOCGKEEPALIVE,&ifr) < 0)
          ife->keepalive= 0;
       else
          ife->keepalive= (unsigned int) ifr.ifr_data;
#endif
    }
#endif

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd, SIOCGIFMAP,&ifr) < 0)
       memset(&ife->map,0, sizeof(struct ifmap));
    else
       memcpy(&ife->map,&ifr.ifr_map, sizeof(struct ifmap));

    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd, SIOCGIFMAP,&ifr) < 0)
       memset(&ife->map,0, sizeof(struct ifmap));
    else
       ife->map = ifr.ifr_map;

#ifdef HAVE_TXQUEUELEN
    strcpy(ifr.ifr_name,ifname);
    if (ioctl(skfd,SIOCGIFTXQLEN, &ifr) < 0)
       ife->tx_queue_len =-1;      
    else
       ife->tx_queue_len =ifr.ifr_qlen;
#else
   ife->tx_queue_len = -1;      
#endif

#if HAVE_AFINET
   
    fd =get_socket_for_af(AF_INET);
    if (fd >= 0){
       strcpy(ifr.ifr_name, ifname);
       ifr.ifr_addr.sa_family = AF_INET;
       if (ioctl(fd, SIOCGIFADDR, &ifr)== 0) {
          ife->has_ip= 1;
          ife->addr= ifr.ifr_addr;
          strcpy(ifr.ifr_name,ifname);
          if (ioctl(fd,SIOCGIFDSTADDR, &ifr) < 0)
            memset(&ife->dstaddr,0, sizeof(struct sockaddr));
          else
            ife->dstaddr =ifr.ifr_dstaddr;

          strcpy(ifr.ifr_name,ifname);
          if (ioctl(fd,SIOCGIFBRDADDR, &ifr) < 0)
            memset(&ife->broadaddr,0, sizeof(struct sockaddr));
          else
              ife->broadaddr= ifr.ifr_broadaddr;

          strcpy(ifr.ifr_name,ifname);
          if (ioctl(fd,SIOCGIFNETMASK, &ifr) < 0)
             memset(&ife->netmask, 0,sizeof(struct sockaddr));
          else
              ife->netmask =ifr.ifr_netmask;
       } else
          memset(&ife->addr,0, sizeof(struct sockaddr));
    }
#endif

#if HAVE_AFATALK
   
    fd =get_socket_for_af(AF_APPLETALK);
    if (fd >= 0){
       strcpy(ifr.ifr_name, ifname);
       if (ioctl(fd, SIOCGIFADDR, &ifr)== 0) {
          ife->ddpaddr= ifr.ifr_addr;
          ife->has_ddp= 1;
       }
    }
#endif

#if HAVE_AFIPX
   
    fd =get_socket_for_af(AF_IPX);
    if (fd >= 0){
       strcpy(ifr.ifr_name, ifname);
       if (!ipx_getaddr(fd, IPX_FRAME_ETHERII,&ifr)) {
          ife->has_ipx_bb= 1;
          ife->ipxaddr_bb= ifr.ifr_addr;
       }
       strcpy(ifr.ifr_name, ifname);
       if (!ipx_getaddr(fd, IPX_FRAME_SNAP,&ifr)) {
          ife->has_ipx_sn= 1;
          ife->ipxaddr_sn= ifr.ifr_addr;
       }
       strcpy(ifr.ifr_name, ifname);
       if (!ipx_getaddr(fd, IPX_FRAME_8023,&ifr)) {
          ife->has_ipx_e3= 1;
          ife->ipxaddr_e3= ifr.ifr_addr;
       }
       strcpy(ifr.ifr_name, ifname);
       if (!ipx_getaddr(fd, IPX_FRAME_8022,&ifr)) {
          ife->has_ipx_e2= 1;
          ife->ipxaddr_e2= ifr.ifr_addr;
       }
    }
#endif

#if HAVE_AFECONET
   
    fd =get_socket_for_af(AF_ECONET);
    if (fd >= 0){
       strcpy(ifr.ifr_name, ifname);
       if (ioctl(fd, SIOCGIFADDR, &ifr)== 0) {
          ife->ecaddr= ifr.ifr_addr;
          ife->has_econet= 1;
       }
    }
#endif

    return 0;
}

ife_print 仅仅是根据标志来判断是省略模式输出还是详细模式输出:
void ife_print(struct interface *i)
{
    if (ife_short)
       ife_print_short(i);
    else
       ife_print_long(i);
}

以详细模式为例,其实就是一个printf 的过程,读取后的参数都放在结构struct interface 中……大家可以对照Linux中输出命令look一下就明白了!
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Linux内核的ioctl函数学习
linux下获得MAC地址
Linux下检测网卡与网线连接状态
ioctl函数详解
linux下ioctl操作网络接口
Android WIFI 移植
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服