linux下使用ioctl() 获取本机mac地址、ip地址等等

来源:互联网 发布:存在主义 知乎 编辑:程序博客网 时间:2024/03/29 05:57

       在linux下,我们知道可以通过ifconfig获取mac地址和ip地址等相关信息,但是如果要使用gcc程序实现的话,我们就需要使用到系统所提供的一个函数ioctl(),iotec函数是对设备的i/o通道进行管理的函数。由于这个函数用途比较多,如果要学习可以参照官方的说明。

       第一步,我们需要定义几个变量:

    struct ifreq *ifrp,ifr;    struct ifconf ifc;    char buffer[720],name[16];    int socketfd,error,flags,len,space=0;

       其中,struct ifreq 就是用来存储返回的接口相关信息的结构体,由于电脑可能有多个硬件借口,因此我们使用指针来存储返回的结构体数组。struct ifconf变量是用来存储ioctl()函数返回结果的。因为我们是要获取mac地址的相关信
////  main.cpp//  arp////  Created by Allen on 14-4-7.//  Copyright (c) 2014年 Allen. All rights reserved.//#include <iostream>#include <sys/param.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/sysctl.h>#include <net/ethernet.h>#include <net/if.h>#include <net/if_var.h>#include <net/if_dl.h>#include <net/if_types.h>#include <netinet/in.h>#include <netinet/in_var.h>#include <arpa/inet.h>#include <err.h>#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>//读取本机mac地址的方法int main(){    struct ifreq *ifrp,ifr;    struct ifconf ifc;    char buffer[720],name[16];    int socketfd,error,flags,len,space=0;    ifc.ifc_len=sizeof(buffer);    len=ifc.ifc_len;        ifc.ifc_buf=buffer;        socketfd=socket(AF_INET,SOCK_DGRAM,0);//创建一个socket        if((error=ioctl(socketfd,SIOCGIFCONF,&ifc))<0)//使用SIOCGIFCONF获得所有接口的清单    {        perror("ioctl faild");        exit(1);    }        if(ifc.ifc_len<=len)//buffer 的大小如果没有问题    {        ifrp=ifc.ifc_req;//将获取的所有借口的所有清单传到ifrp指针上。        do        {            struct sockaddr *sa=&ifrp->ifr_addr;//定义sockaddr对象            strcpy(ifr.ifr_name,ifrp->ifr_name);            if(strcmp(ifrp->ifr_name,name)!=0){                strcpy(name,ifrp->ifr_name);                printf("%s:",ifrp->ifr_name);// 打印接口名                if(!ioctl(socketfd,SIOCGIFFLAGS,&ifr))//get ifnet flags                {                    flags=ifr.ifr_flags;                    printf("flags=%x<",flags<<16);                    if(ifr.ifr_flags&IFF_UP){                        printf("UP,");                    }                    else{                        printf("DOWN");                    }                    if(ifr.ifr_flags&IFF_BROADCAST){                        printf("BOROADCAST,");                    }                    if(ifr.ifr_flags&IFF_POINTOPOINT){                        printf("POINTOPOINT,");                    }                    if(ifr.ifr_flags&IFF_LOOPBACK){                        printf("LOOPBACK,");                    }                    if(ifr.ifr_flags&IFF_RUNNING){                        printf("RUNNING,");                    }                    if(ifr.ifr_flags&IFF_SIMPLEX){                        printf("SIMPLEX,");                    }                    if(ifr.ifr_flags&IFF_MULTICAST){                        printf("MULTICAST");                    }                    printf(">;\n");                }                if(!ioctl(socketfd,SIOCGIFADDR,&ifr)){                    printf("     inet %s",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));                }                if(!ioctl(socketfd,SIOCGIFNETMASK,&ifr)){                    printf(" netmask %s",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));                }                if(!ioctl(socketfd,SIOCGIFBRDADDR,&ifr)){                    printf(" broadcast %s\n",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));                }                if(((struct sockaddr_dl *)sa)->sdl_type==IFT_ETHER)                    printf("     ether %s\n",ether_ntoa((struct ether_addr *)LLADDR((struct sockaddr_dl *)sa)));                //printf("types %x\n",((struct sockaddr_dl *)sa)->;sdl_type);                            }            ifrp=(struct ifreq*)(sa->sa_len+(caddr_t)&ifrp->ifr_addr);            space+=(int)sa->sa_len+sizeof(ifrp->ifr_name);        }        while(space<ifc.ifc_len);            }    exit(0);}

息,那么按照ioctl函数穿惨的要求,第一个是socketfd,第二个是宏SIOCGIFCONF,返回值是所有接口的清单存储在ifc中。之后使用ifreq指针指向ifc中的ifc_req数组。之后使用一个循环来分别获取每个接口的参数。


0 0