linux下使用ioctl() 獲取本機mac地址、ip地址等等
阿新 • • 發佈:2019-01-31
在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陣列。之後使用一個迴圈來分別獲取每個介面的引數。