一、struct ifconf结构体
  • 功能:用来保存所有网络接口的名字和信息(不是全部信息,是ip地址)
// 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	*/

UNP编程:37---struct ifreq、 struct ifconf结构体_#include

二、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*/
三、与ioctl的配合使用

 

类别 Request 说明 数据类型

SIOCGIFCONF 获取所有接口的清单 struct ifconf
SIOCSIFADDR 设置接口地址 struct ifreq
SIOCGIFADDR 获取接口地址 struct ifreq
SIOCSIFFLAGS 设置接口标志 struct ifreq
SIOCGIFFLAGS 获取接口标志 struct ifreq
SIOCSIFDSTADDR 设置点到点地址 struct ifreq
SIOCGIFDSTADDR 获取点到点地址 struct ifreq
SIOCGIFBRDADDR 获取广播地址 struct ifreq
SIOCSIFBRDADDR 设置广播地址 struct ifreq
SIOCGIFNETMASK 获取子网掩码 struct ifreq
SIOCSIFNETMASK 设置子网掩码 struct ifreq
SIOCGIFMETRIC 获取接口的测度 struct ifreq
SIOCSIFMETRIC 设置接口的测度 struct ifreq
SIOCGIFMTU 获取接口MTU struct ifreq
SIOCxxx (还有很多取决于系统的实现)  

比如我们请求所有网络接口的清单:

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

演示案例:

  • 获取"eth0"网卡接口的地址掩码
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <netinet/in.h> 
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>  
#include <net/if.h>  
#include <unistd.h>  
#include <string.h>

int main()
{
	//此处我们的实验对象为eth0这块网卡
	struct ifreq ifr;
	strcpy (ifr.ifr_name, "eth0");
	
	//打开一个通信socket
	int sock = -1;
	if ((sock=socket( AF_INET, SOCK_DGRAM, 0 )) < 0 )
		return -1;
		
	uint32_t u32_mask;
	char maskDotBuf[16]; 
	
	//获取eth0这个借口的掩码
	ioctl(sock, SIOCGIFNETMASK, &ifr);
	
	//获取掩码地址(这是网络字节序的地址格式)
	u32_mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
	//将网络字节序的掩码地址转换为本地点分二进制字符串格式的
	inet_ntop(AF_INET, &u32_mask, maskDotBuf, (socklen_t )sizeof(maskDotBuf));
	
	//打印掩码
	printf("Mask: %s\n", maskDotBuf);

	return 0;
}

UNP编程:37---struct ifreq、 struct ifconf结构体_#include_02 UNP编程:37---struct ifreq、 struct ifconf结构体_#include_03

演示案例:

  • 打印主机中所有的网络接口地址及信息
#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相同    */
		}
	}
	
	
	
}

UNP编程:37---struct ifreq、 struct ifconf结构体_网络接口_04

演示案例

  • 下面演示在TCP/UDP通信中,通过struct ifreq结构体获取一个指定的接口地址作为本次通信的IP地址
int listen_fd;
if (-1 == (listen_fd = socket (AF_INET, SOCK_STREAM, 0))){
    return -1;
}

//获取eth0接口的信息
struct ifreq ifr;
strcpy (ifr.ifr_name, "eth0");
if (ioctl (listen_fd, SIOCGIFADDR, &ifr) < 0){
    return -1;
}
    
struct sockaddr_in myaddr;
myaddr.sin_family = AF_INET;  
myaddr.sin_port = htons (8888);
//将eth0接口的IP地址作为本次通信的IP地址
myaddr.sin_addr.s_addr =((struct sockaddr_in *) &(ifr.ifr_addr))->sin_addr.s_addr;