linux网络接口,struct ifreq struct ifconf结构

网络相关的ioctl请求的request参数及arg地址必须指向的数据类型如下表所示:

 

接口

SIOCGIFCONF

SIOCSIFADDR

SIOCGIFADDR

SIOCSIFBRDADDR

SIOCGIFBRDADDR

SIOCSIFNETMASK

SIOCGIFNETMASK


获取所有接口列表

设置接口地址

获取接口地址

设置广播地址

获取广播地址

设置子网掩码

获取子网掩码


Struct  ifconf

Struct  ifreq

Struct  ifreq

Struct  ifreq

Struct  ifreq

Struct  ifreq

Struct  ifreq


Ifreq结构用来配置ip地址,激活接口,配置MTU。在Linux系统中获取IP地址通常都是通过ifconfig命令来实现的,然而ifconfig命令实际是通过ioctl接口与内核通信,ifconfig命令首先打开一个socket,然后调用ioctlrequest传递到内核,从而获取request请求数据。处理网络接口的许多程序沿用的初始步骤之一就是从内核获取配置在系统中的所有接口。

 

struct     ifreq     data;
fd = socket(AF_NET,SOCK_DGRAM,0);
ioctl(fd,SIOCGIFADDR,&data);

 

 struct ifconf结构体

 

struct ifconf{
    lint ifc_len;
    union{
        caddr_t  ifcu_buf
        struct   ifreq *ifcu_req;
    }ifc_ifcu
} 
#define    ifc_buf    ifc_ifcu.ifcu_buf
#define    ifc_req    ifc_ifcu.ifcu_req

 

struct ifreq接口

struct ifreq{
    char ifr_name[IFNAMSIZ];
    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_metric;
        caddr_t ifru_data;
    }ifr_ifru;
};

#define ifr_addr        ifr_ifru.ifru_addr
#define ifr_broadaddr   ifr_ifru.ifru_broadadd
#define ifr_hwaddr      ifr_ifru_hwaddr

对于ifconfifc_buf,其实就是Nifc_req,从上面的结构体中可以看出来,通过下面两幅图可以更加明显。

#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 verctor
    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相同 */
        }
    }
}

 

posted @ 2018-06-26 15:58  习惯就好233  阅读(2097)  评论(0编辑  收藏  举报