zoukankan      html  css  js  c++  java
  • 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    转载请注明出处: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地址)



    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;
    ");
    	
    	// get if vector
     	struct ifconf ioIfConf;
        	ioIfConf.ifc_buf = (void *)ifVec;
           	ioIfConf.ifc_len = sizeof(ifVec);
    	 printf("Len:%d
    ", ioIfConf.ifc_len);     
    		
    	if (ioctl(sock, SIOCGIFCONF, &ioIfConf) < 0 )//获取所有网络接口信息
    		fprintf(stderr, "Error:%d   ioctl IFCONF
    ");
    	
    	 printf("Len:%d
    ", 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
    ", 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
    ", 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
    ", 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
    ", errno);
    			}
    			else{
    				printf("SIOCGIFMTU:%d
    ", ifReq.ifr_mtu); 
    			}
    	           /*    其他信息的打印方式与掩码和MTU相同    */
    		}
    	}
    	
    	
    	
    }



    运行结果:
    windeal@ubuntu:~/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
    windeal@ubuntu:~/Windeal/apue$ 



















  • 相关阅读:
    PLC衔接新方式UcAsp.Opc
    dev barmanager 中的 add按钮出不来,无法创建菜单的问题解决
    一个或多个页边距被设置到也可打印的页面范围之外,处理方式
    bar设置全背景色
    PHP计算两个字符的相似程度similar_text
    PHP中双冒号::的用法
    百度站内搜索应该注意哪些方面?
    快给你的网站添加微信公众号吧!
    实例讲解网站前台界面开发流程
    百度富文本编辑器UEditor安装配置全过程
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284627.html
Copyright © 2011-2022 走看看