• 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;
    ");
    
        // get if verctor
        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相同 */
            }
        }
    }
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    JWT安装配置
    封装axios请求&添加拦截器
    RESTful风格
    APIView使用增删改查user
    虚拟环境
    VUE异步检查用户名和手机号(6)
    Django-celery验证用户名和手机号(5)
    vue异步发送短息短信(4)
    Django-celery异步发送信息(3)
    Django-celery异步基本配置与使用(2)
  • 原文地址:https://www.cnblogs.com/ch122633/p/9229551.html
Copyright © 2020-2023  润新知