Linux下利用ioctl函數獲取網卡信息


linux下的ioctl函數原型如下:

#include <sys/ioctl.h>

int ioctl(int handle, int cmd, [int *argc, int argv])

函數成功返回0,失敗返回-1.

其相關命令接口如下:

 

類別
Request
說明
數據類型
SIOCATMARK
SIOCSPGRP
SIOCGPGRP
是否位於帶外標記
設置套接口的進程ID 或進程組ID
獲取套接口的進程ID 或進程組ID
int
int
int
FIONBIO
FIOASYNC
FIONREAD
FIOSETOWN
FIOGETOWN
設置/ 清除非阻塞I/O 標志
設置/ 清除信號驅動異步I/O 標志
獲取接收緩存區中的字節數
設置文件的進程ID 或進程組ID
獲取文件的進程ID 或進程組ID
int
int
int
int
int
SIOCGIFCONF
SIOCSIFADDR
SIOCGIFADDR
SIOCSIFFLAGS
SIOCGIFFLAGS
SIOCSIFDSTADDR
SIOCGIFDSTADDR
SIOCGIFBRDADDR
SIOCSIFBRDADDR
SIOCGIFNETMASK
SIOCSIFNETMASK
SIOCGIFMETRIC
SIOCSIFMETRIC
SIOCGIFMTU
SIOCxxx
獲取所有接口的清單
設置接口地址
獲取接口地址
設置接口標志
獲取接口標志
設置點到點地址
獲取點到點地址
獲取廣播地址
設置廣播地址
獲取子網掩碼
設置子網掩碼
獲取接口的測度
設置接口的測度
獲取接口MTU
(還有很多取決於系統的實現)
struct ifconf
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
struct ifreq
ARP
SIOCSARP
SIOCGARP
SIOCDARP
創建/ 修改ARP 表項
獲取ARP 表項
刪除ARP 表項
struct arpreq
struct arpreq
struct arpreq
SIOCADDRT
SIOCDELRT
增加路徑
刪除路徑
struct rtentry
struct rtentry
       

 

 

在這里我們需要用到的結構體

#include<netinet/in.h>

struct sockaddr_in {
short sin_family; /* Address family */
unsigned short sin_port; /* Port number */
struct  in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
};

#include <net/if.h>

struct ifreq
{
#define IFHWADDRLEN 6
union
{
charifrn_name[IFNAMSIZ]; 
} ifr_ifrn;

union {
structsockaddr ifru_addr;
structsockaddr ifru_dstaddr;
structsockaddr ifru_broadaddr;
structsockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
shortifru_flags;
intifru_ivalue;
intifru_mtu;
struct ifmap ifru_map;
charifru_slave[IFNAMSIZ]; 
charifru_newname[IFNAMSIZ];
void __user * ifru_data;
structif_settings ifru_settings;
} ifr_ifru;
};

#define ifr_name ifr_ifrn.ifrn_name 
#define ifr_hwaddr ifr_ifru.ifru_hwaddr 
#defineifr_addr ifr_ifru.ifru_addr 
#defineifr_dstaddr ifr_ifru.ifru_dstaddr 
#defineifr_broadaddr ifr_ifru.ifru_broadaddr 
#defineifr_netmask ifr_ifru.ifru_netmask
#defineifr_flags ifr_ifru.ifru_flags 
#defineifr_metric ifr_ifru.ifru_ivalue
#defineifr_mtu ifr_ifru.ifru_mtu
#define ifr_map ifr_ifru.ifru_map
#define ifr_slave ifr_ifru.ifru_slave
#defineifr_data ifr_ifru.ifru_data 
#define ifr_ifindex ifr_ifru.ifru_ivalue
#define ifr_bandwidth ifr_ifru.ifru_ivalue 
#define ifr_qlen ifr_ifru.ifru_ivalue
#define ifr_newname ifr_ifru.ifru_newname
#define ifr_settings ifr_ifru.ifru_setting

ioctl函數能獲取到IP地址、子網掩碼、廣播地址、硬件MAC地址等信息,至於網關及路由表比較復雜,在此不討論。

具體代碼如下:(測試通過)

#include <stdio.h>

#include <stdlib.h>

#include <net/if.h>

#include <unistd.h>

#include <sys/ioctl.h>

#include <arpa/inet.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <errno.h>

#include <fcntl.h>

#include <netinet/in.h>

#include <net/route.h>

#include <string.h>

#include <net/if_arp.h>

 

int main()

{

   struct sockaddr_in *sin;

   struct ifreq ifr;

   FILE *dns;

   FILE *gw;

   char *ip = new char(16);

   char *netmask = new char(16);

   char *broadcast = new char(16);

   //char *ip = (char *)malloc(16);

   char *mac = new  char(32);

   //char *mac = (char *)malloc(32);

   int socket_fd;

 

       if((socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){

               perror("socket");

               exit(1);

       }

 

       memset(&ifr, 0, sizeof(ifr));

       strcpy(ifr.ifr_name, "eth0");

       memset(&sin, 0, sizeof(sin));

//獲取IP地址

       if(ioctl(socket_fd, SIOCGIFADDR, &ifr) != -1){

               sin = (struct sockaddr_in *)&ifr.ifr_addr;

               strcpy(ip, inet_ntoa(sin->sin_addr));

               printf("IP address is %s\n", ip);

       }

//獲取廣播地址

 

       if(ioctl(socket_fd, SIOCGIFBRDADDR, &ifr) != -1){

               sin = (struct sockaddr_in *)&ifr.ifr_broadaddr;

               strcpy(broadcast, inet_ntoa(sin->sin_addr));

               printf("Broadcast is %s\n", broadcast);

       }

//獲取子網掩碼

 

       if(ioctl(socket_fd, SIOCGIFNETMASK, &ifr) != -1){

               sin = (struct sockaddr_in *)&ifr.ifr_broadaddr;

               strcpy(netmask, inet_ntoa(sin->sin_addr));

               printf("Net-mask is %s\n", netmask);

       }

//獲取硬件MAC地址

 

       if(ioctl(socket_fd, SIOCGIFHWADDR, &ifr) != -1){

               sin = (struct sockaddr_in *)&ifr.ifr_netmask;

               sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",

               (unsigned char)ifr.ifr_netmask.sa_data[0],

               (unsigned char)ifr.ifr_netmask.sa_data[1],

               (unsigned char)ifr.ifr_netmask.sa_data[2],

               (unsigned char)ifr.ifr_netmask.sa_data[3],

               (unsigned char)ifr.ifr_netmask.sa_data[4],

               (unsigned char)ifr.ifr_netmask.sa_data[5]);

               printf("Mac address is %s\n", mac);

       }

   return 0;

}

 

至於獲取網關以及DNS,我是通過相關命令獲得的。

主要代碼如下:

//獲取網關,利用route -n 命令可以看到相關的網關。連接標志是‘UG’

if(gw_fd = popen("route -n | grep 'UG'", "r")){

   fread(temp,1,128, gw_fd);

   sscanf(temp, "%*s%s", szNetGate);

   printf("Gateway is %s\n", szNetGate);

}

//獲取DNS;一般DNS保存在/etc/reslov.conf文件中。具體獲得方法要根據實際情況而定。

我的配置文件中是這樣的

root@nill:/home/arm-none-linux# cat /etc/resolv.conf

 

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)

#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

nameserver 202.96.134.133  

上面的202.96.134.133就是我需要獲取的主DNS,沒有備用DNS

if(dns_fd = popen("cat /etc/reslov.conf | grep 'nameserver'", "r")){

   fread(temp,1,128, gw_fd);

   sscanf(temp, "%*s%s%*s%s", szDNS1,szDNS2);

   printf("DNS1 is %s",szDNS1);

   printf("DNS2is %s", szDNS2);

}

 

轉載地址:http://5375342.blog.51cto.com/5365342/1209335

相關地址:http://blog.csdn.net/bailyzheng/article/details/7489656


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM