天天看點

擷取網絡接口資訊——ioctl()函數與結構體struct ifreq、 struct ifconf ioctlstruct ifreq struct ifconf Example:

轉載請注明出處:windeal專欄

Linux 下 可以使用ioctl()函數 以及 結構體 struct ifreq  結構體struct ifconf來擷取網絡接口的各種資訊。

ioctl

首先看ioctl()用法 ioctl()原型如下:

#include <sys/ioctl.h>              int ioctl(int fd, int request, ...);           

參數:      fd     : 檔案描述符 request:  表示要請求的資訊。如IP位址、網絡掩碼等        ...         :    後面的可變參數根據request而定

比如我們請求所有網絡接口的清單:

struct ifconf IoCtlReq;
...
ioctl( Sock, SIOCGIFCONF, &IoCtlReq )
           

其中 IoCtlReq 是一個

與接口相關的request如下表所示( 來源: < http://baike.baidu.com/view/1081282.htm?fr=aladdin > ):

接 口 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

關于ioctl的詳細解釋清查閱本博其它博文

struct ifreq

結構體 struct ifreq用來儲存某個接口的資訊。

// if.h
/*
 * Interface request structure used for socket
 * ioctl's.  All interface ioctl's must have parameter
 * definitions which begin with ifr_name.  The
 * remainder may be interface specific.
 */
struct ifreq {
#define IFHWADDRLEN	6
	union
	{
		char	ifrn_name[IFNAMSIZ];		/* if name, e.g. "en0" */
	} ifr_ifrn;
	
	union {
		struct	sockaddr ifru_addr;
		struct	sockaddr ifru_dstaddr;
		struct	sockaddr ifru_broadaddr;
		struct	sockaddr ifru_netmask;
		struct  sockaddr ifru_hwaddr;
		short	ifru_flags;
		int	ifru_ivalue;
		int	ifru_mtu;
		struct  ifmap ifru_map;
		char	ifru_slave[IFNAMSIZ];	/* Just fits the size */
		char	ifru_newname[IFNAMSIZ];
		void __user *	ifru_data;
		struct	if_settings ifru_settings;
	} ifr_ifru;
};
#define ifr_name	ifr_ifrn.ifrn_name	/* interface name 	*/
#define ifr_hwaddr	ifr_ifru.ifru_hwaddr	/* MAC address 		*/
#define	ifr_addr	ifr_ifru.ifru_addr	/* address		*/
#define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-p lnk	*/
#define	ifr_broadaddr	ifr_ifru.ifru_broadaddr	/* broadcast address	*/
#define	ifr_netmask	ifr_ifru.ifru_netmask	/* interface net mask	*/
#define	ifr_flags	ifr_ifru.ifru_flags	/* flags		*/
#define	ifr_metric	ifr_ifru.ifru_ivalue	/* metric		*/
#define	ifr_mtu		ifr_ifru.ifru_mtu	/* mtu			*/
#define ifr_map		ifr_ifru.ifru_map	/* device map		*/
#define ifr_slave	ifr_ifru.ifru_slave	/* slave device		*/
#define	ifr_data	ifr_ifru.ifru_data	/* for use by interface	*/
#define ifr_ifindex	ifr_ifru.ifru_ivalue	/* interface index	*/
#define ifr_bandwidth	ifr_ifru.ifru_ivalue    /* link bandwidth	*/
#define ifr_qlen	ifr_ifru.ifru_ivalue	/* Queue length 	*/
#define ifr_newname	ifr_ifru.ifru_newname	/* New name		*/
#define ifr_settings	ifr_ifru.ifru_settings	/* Device/proto settings*/
           

ifr_name 辨別了某一接口。

可以通過ioctl擷取該接口的資訊。如:

ioctl(Sock, SIOCGIFNETMASK, &IfReq);//擷取網絡接口位址掩碼           

該代碼需要先對IfReq->ifr_name指派,然後擷取與 IfReq->ifr_name向比對的網絡接口 的位址掩碼

struct ifconf

結構體struct ifconf通常用來儲存所有接口資訊

// if.h
/*
 * Structure used in SIOCGIFCONF request.
 * Used to retrieve interface configuration
 * for machine (useful for programs which
 * must know all networks accessible).
 */
struct ifconf  {
	int	ifc_len;			/* size of buffer	*/
	union {
		char __user *ifcu_buf;
		struct ifreq __user *ifcu_req;
	} ifc_ifcu;
};
#define	ifc_buf	ifc_ifcu.ifcu_buf		/* buffer address	*/
#define	ifc_req	ifc_ifcu.ifcu_req		/* array of structures	*/
           

該結構體可以用來擷取所喲網絡接口的名字和資訊(不是全部資訊,是ip位址) (圖檔來自: http://tech.sunplusedu.com/space/post-4064.aspx )

擷取網絡接口資訊——ioctl()函數與結構體struct ifreq、 struct ifconf ioctlstruct ifreq struct ifconf Example:
擷取網絡接口資訊——ioctl()函數與結構體struct ifreq、 struct ifconf ioctlstruct ifreq struct ifconf Example:

Example:

#include <sys/types.h>  
#include <sys/ioctl.h>  
#include <sys/socket.h>  
#include <net/if.h>  
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <netdb.h>  
#include <string.h>  
#include <fcntl.h>  
#include <string.h>  
#include <errno.h>
typedef uint32_t uint32; 
#define MAX_IF 10
int 
main()
{
	struct ifreq ifVec[MAX_IF];//用來儲存所有接口
	
	int sock = -1;
	if ( (sock = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
		fprintf(stderr, "Error:%d, cannot open RAM;\n");
	
	// get if vector
 	struct ifconf ioIfConf;
    	ioIfConf.ifc_buf = (void *)ifVec;
       	ioIfConf.ifc_len = sizeof(ifVec);
	 printf("Len:%d\n", ioIfConf.ifc_len);     
		
	if (ioctl(sock, SIOCGIFCONF, &ioIfConf) < 0 )//擷取所有網絡接口資訊
		fprintf(stderr, "Error:%d   ioctl IFCONF\n");
	
	 printf("Len:%d\n", ioIfConf.ifc_len);// 和前面到len對比,發現ioctl修改裡len到大小     
	//循環列印每個網絡接口到資訊
	{
		struct ifreq *ifPt;
		struct ifreq *ifEndPt;
		ifPt = ifVec;
		ifEndPt = (void *)((char *)ifVec + ioIfConf.ifc_len);
		for (ifPt = ifVec; ifPt < ifEndPt; ifPt++)
		{
			struct ifreq ifReq;
			if ( ifPt->ifr_addr.sa_family != AF_INET ) {
                		continue;
            		}
			
			// Temp keepers of interface params...
			uint32 u32_addr, u32_mask;
			
			/*	列印ip位址	*/
			char ipDotBuf[16], subnetDotBuf[16], maskDotBuf[16]; // 儲存點分十進制到ip位址
			u32_addr = ((struct sockaddr_in *)&ifPt->ifr_addr)->sin_addr.s_addr;
			inet_ntop(AF_INET, &u32_addr, ipDotBuf, (socklen_t )sizeof(ipDotBuf)); 
			printf("IP Address: %s\n", ipDotBuf);
			
			/*    列印位址掩碼    */
			bzero(&ifReq,sizeof(struct ifreq));  
			memcpy(ifReq.ifr_name, ifPt->ifr_name, sizeof(ifReq.ifr_name));  
			if (ioctl(sock, SIOCGIFNETMASK, &ifReq ) < 0){
				fprintf(stderr, "Error: %d, cannot get mask\n", errno);
			}
			else{
				u32_mask = ((struct sockaddr_in *)&ifReq.ifr_addr)->sin_addr.s_addr;
				inet_ntop(AF_INET, &u32_mask, maskDotBuf, (socklen_t )sizeof(maskDotBuf));
				printf("Mask: %s\n", maskDotBuf);
			}	
			/*    列印MTU    */
			bzero(&ifReq,sizeof(struct ifreq));  
			memcpy(ifReq.ifr_name, ifPt->ifr_name, sizeof(ifReq.ifr_name));  
			if (ioctl(sock, SIOCGIFMTU, &ifReq ) < 0){
				fprintf(stderr, "Error: %d, cannot get MTU\n", errno);
			}
			else{
				printf("SIOCGIFMTU:%d\n", ifReq.ifr_mtu); 
			}
	           /*    其他資訊的列印方式與掩碼和MTU相同    */
		}
	}
	
	
	
}
           

運作結果:

[email protected]:~/Windeal/apue$ ./exe 
Len:320
Len:64
IP Address: 127.0.0.1
Mask: 255.0.0.0
SIOCGIFMTU:16436
IP Address: 172.17.92.198
Mask: 255.255.254.0
SIOCGIFMTU:1500
[email protected]:~/Windeal/apue$