zoukankan      html  css  js  c++  java
  • ioctl函数

    一、函数原型

    #include    <unistd.h>
    
    int ioctl(int fd, int request, .../* void *arg */);
    
    返回:成功返回0,否则为-1

    二、和网络相关的请求(request)

     (1)套接字操作

     (2)文件操作

     (3)接口操作

     (4)ARP告诉缓存操作

     (5)路由表操作

     (6)流系统

    三、request参数及arg地址必须指向的数据类型

    四、案列:获取所有网络设备接口名称

    #include    <stdio.h>
    #include    <stdlib.h>
    #include    <errno.h>
    #include    <sys/ioctl.h>
    #include    <sys/socket.h>
    #include    <net/if.h>
    
    struct ifreq *get_ifreq();
    
    int main(int argc, char **argv)
    {
        struct ifreq *ifr, *tobefree;
    
        ifr = tobefree = get_ifreq();
        
        do {
            printf("%s
    ", ifr->ifr_name);
            ifr++;
        } while (ifr->ifr_name[0] != 0);
    
        free(tobefree);
    
        exit(0);
    }
    
    struct ifreq *get_ifreq()
    {
        int  sockfd, len, lastlen;
        char *buf;
        struct ifconf ifc;
    
        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
        lastlen = 0;
        len = 40 * sizeof(struct ifreq);        /* initial buffer size guess */
        for ( ; ; ) {
            buf = malloc(len);
            ifc.ifc_len = len;
            ifc.ifc_buf = buf;
            if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
                if (errno != EINVAL || lastlen != 0) {
                    perror("ioctl");
                    exit(-1);
                }
            } else {
                if (ifc.ifc_len == lastlen) {
                    break;                      /* success, len has not changed */
                }
                lastlen = ifc.ifc_len;
            }
            len += 10 * sizeof(struct ifreq);   /* increment */
            free(buf);
        }
        
        return ((struct ifreq *)ifc.ifc_buf);
    }

     五、关于ioctl函数应该注意

    六、get_ifi_info函数

    #include    "unpifi.h"
    
    struct ifi_info *get_ifi_info(int family, int doaliases)
    {
        int       sockfd, len, lastlen, flags, myflags, idx = 0, hlen = 0;
        char   *ptr, *buf, lastname[IFNAMSIZ], *cptr, *haddr, *sdlname;
        struct ifconf        ifc;
        struct ifreq        *ifr, ifrcopy;
        struct sockaddr_in    *sinptr;
        struct sockaddr_in6    *sin6ptr;
        struct ifi_info        *ifi, *ifihead, **ifipnext;
    
    
        sockfd = socket(family, SOCK_DGRAM, 0);
    
        lastlen = 0;
        len = 100 * sizeof(struct ifreq);     /* initial buffer size guess */
        for ( ; ; ) {
            buf = malloc(len);
            ifc.ifc_len = len;
            ifc.ifc_buf = buf;
            if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
                if (errno != EINVAL || lastlen != 0) {
                    perror("ioctl");
                    exit(-1);
                }
            } else {
                if (ifc.ifc_len == lastlen) {
                    break;                    /* success, len has not changed */
                }
                lastlen = ifc.ifc_len;
            }
            len += 10 * sizeof(struct ifreq); /* increment */
            free(buf);
        }
        ifihead = NULL;
        ifipnext = &ifihead;
        lastname[0] = 0;
        sdlname = NULL;
    
        for (ptr = buf; ptr < buf + ifc.ifc_len; ) {
            ifr = (struct ifreq *) ptr;
    
    #ifdef    HAVE_SOCKADDR_SA_LEN
            len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
    #else
            switch (ifr->ifr_addr.sa_family) {
    #ifdef    IPV6
            case AF_INET6:    
                len = sizeof(struct sockaddr_in6);
                break;
    #endif
            case AF_INET:    
            default:    
                len = sizeof(struct sockaddr);
                break;
            }
    #endif    /* HAVE_SOCKADDR_SA_LEN */
    
            ptr += sizeof(ifr->ifr_name) + len + 8;    /* for next one in buffer */
    
    #ifdef    HAVE_SOCKADDR_DL_STRUCT
            /* assumes that AF_LINK precedes AF_INET or AF_INET6 */
            if (ifr->ifr_addr.sa_family == AF_LINK) {
                struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
                sdlname = ifr->ifr_name;
                idx = sdl->sdl_index;
                haddr = sdl->sdl_data + sdl->sdl_nlen;
                hlen = sdl->sdl_alen;
            }
    #endif
    
            if (ifr->ifr_addr.sa_family != family) {
                continue;      /* ignore if not desired address family */
            }
    
            myflags = 0;
            if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL) {
                *cptr = 0;     /* replace colon with null */
            }
            if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
                if (doaliases == 0)
                    continue;  /* already processed this interface */
                myflags = IFI_ALIAS;
            }
            memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
    
            ifrcopy = *ifr;
            ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);
            flags = ifrcopy.ifr_flags;
            if ((flags & IFF_UP) == 0) {
                continue;      /* ignore if interface not up */
            }
    
            ifi = calloc(1, sizeof(struct ifi_info));
            *ifipnext = ifi;              /* prev points to this new one */
            ifipnext = &ifi->ifi_next;    /* pointer to next one goes here */
    
            ifi->ifi_flags = flags;       /* IFF_xxx values */
            ifi->ifi_myflags = myflags;   /* IFI_xxx values */
    #if defined(SIOCGIFMTU) && defined(HAVE_STRUCT_IFREQ_IFR_MTU)
            ioctl(sockfd, SIOCGIFMTU, &ifrcopy);
            ifi->ifi_mtu = ifrcopy.ifr_mtu;
    #else
            ifi->ifi_mtu = 0;
    #endif
            memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
            ifi->ifi_name[IFI_NAME-1] = '';
            /* If the sockaddr_dl is from a different interface, ignore it */
            if (sdlname == NULL || strcmp(sdlname, ifr->ifr_name) != 0) {
                idx = hlen = 0;
            }
            ifi->ifi_index = idx;
            ifi->ifi_hlen = hlen;
            if (ifi->ifi_hlen > IFI_HADDR) {
                ifi->ifi_hlen = IFI_HADDR;
            }
            if (hlen) {
                memcpy(ifi->ifi_haddr, haddr, ifi->ifi_hlen);
            }
    
            switch (ifr->ifr_addr.sa_family) {
            case AF_INET:
                sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
                ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
                memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
    
    #ifdef    SIOCGIFBRDADDR
                if (flags & IFF_BROADCAST) {
                    ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy);
                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr;
                    ifi->ifi_brdaddr = calloc(1, sizeof(struct sockaddr_in));
                    memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
                }
    #endif
    
    #ifdef    SIOCGIFDSTADDR
                if (flags & IFF_POINTOPOINT) {
                    ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
                    sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr;
                    ifi->ifi_dstaddr = calloc(1, sizeof(struct sockaddr_in));
                    memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
                }
    #endif
                break;
    
            case AF_INET6:
                sin6ptr = (struct sockaddr_in6 *) &ifr->ifr_addr;
                ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
                memcpy(ifi->ifi_addr, sin6ptr, sizeof(struct sockaddr_in6));
    
    #ifdef    SIOCGIFDSTADDR
                if (flags & IFF_POINTOPOINT) {
                    ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy);
                    sin6ptr = (struct sockaddr_in6 *) &ifrcopy.ifr_dstaddr;
                    ifi->ifi_dstaddr = calloc(1, sizeof(struct sockaddr_in6));
                    memcpy(ifi->ifi_dstaddr, sin6ptr, sizeof(struct sockaddr_in6));
                }
    #endif
                break;
    
            default:
                break;
            }
        }
        free(buf);
        return (ifihead);    /* pointer to first structure in linked list */
    }
    
    void free_ifi_info(struct ifi_info *ifihead)
    {
        struct ifi_info    *ifi, *ifinext;
    
        for (ifi = ifihead; ifi != NULL; ifi = ifinext) {
            if (ifi->ifi_addr != NULL) {
                free(ifi->ifi_addr);
            }
            if (ifi->ifi_brdaddr != NULL) {
                free(ifi->ifi_brdaddr);
            }
            if (ifi->ifi_dstaddr != NULL) {
                free(ifi->ifi_dstaddr);
            }
            ifinext = ifi->ifi_next;    /* can't fetch ifi_next after free() */
            free(ifi);                  /* the ifi_info{} itself */
        }
    }
    
    struct ifi_info *Get_ifi_info(int family, int doaliases)
    {
        struct ifi_info    *ifi;
    
        if ( (ifi = get_ifi_info(family, doaliases)) == NULL) {
            printf("get_ifi_info error
    ");
            exit(-1);
        }
        return(ifi);
    }

    七、unpifi.h头文件

    #ifndef    __unp_ifi_h
    #define    __unp_ifi_h
    
    #include    <stdio.h>
    #include    <errno.h>
    #include    <stdlib.h>
    #include    <string.h>
    #include    <net/if.h>
    #include    <netinet/in.h>
    #include    <sys/ioctl.h>
    
    #define    IFI_NAME    16          /* same as IFNAMSIZ in <net/if.h> */
    #define    IFI_HADDR   8           /* allow for 64-bit EUI-64 in future */
    
    struct ifi_info {
      char    ifi_name[IFI_NAME];      /* interface name, null-terminated */
      short   ifi_index;               /* interface index */
      short   ifi_mtu;                 /* interface MTU */
      u_char  ifi_haddr[IFI_HADDR];    /* hardware address */
      u_short ifi_hlen;                /* # bytes in hardware address: 0, 6, 8 */
      short   ifi_flags;               /* IFF_xxx constants from <net/if.h> */
      short   ifi_myflags;             /* our own IFI_xxx flags */
      struct sockaddr  *ifi_addr;      /* primary address */
      struct sockaddr  *ifi_brdaddr;   /* broadcast address */
      struct sockaddr  *ifi_dstaddr;   /* destination address */
      struct ifi_info  *ifi_next;      /* next of these structures */
    };
    
    #define    IFI_ALIAS    1          /* ifi_addr is an alias */
    
    /* function prototypes */
    char   *sock_ntop_host(const struct sockaddr *, socklen_t);
    void   free_ifi_info(struct ifi_info *);
    struct ifi_info    *get_ifi_info(int, int);
    struct ifi_info    *Get_ifi_info(int, int);
    
    #endif    /* __unp_ifi_h */

    八、sock_ntop_host函数

    #include    <stdio.h>
    #include    <string.h>
    #include    <arpa/inet.h>
    #include    <sys/un.h>
    
    #ifdef    HAVE_SOCKADDR_DL_STRUCT
    #include    <net/if_dl.h>
    #endif
    
    char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
    {
        static char str[128];        /* Unix domain is largest */
    
        switch (sa->sa_family) {
        case AF_INET: {
            struct sockaddr_in    *sin = (struct sockaddr_in *) sa;
    
            if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)
                return(NULL);
            return(str);
        }
    
    #ifdef    IPV6
        case AF_INET6: {
            struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;
    
            if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL)
                return(NULL);
            return(str);
        }
    #endif
    
    #ifdef    AF_UNIX
        case AF_UNIX: {
            struct sockaddr_un    *unp = (struct sockaddr_un *) sa;
    
                /* OK to have no pathname bound to the socket: happens on
                   every connect() unless client calls bind() first. */
            if (unp->sun_path[0] == 0)
                strcpy(str, "(no pathname bound)");
            else
                snprintf(str, sizeof(str), "%s", unp->sun_path);
            return(str);
        }
    #endif
    
    #ifdef    HAVE_SOCKADDR_DL_STRUCT
        case AF_LINK: {
            struct sockaddr_dl    *sdl = (struct sockaddr_dl *) sa;
    
            if (sdl->sdl_nlen > 0)
                snprintf(str, sizeof(str), "%*s",
                         sdl->sdl_nlen, &sdl->sdl_data[0]);
            else
                snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);
            return(str);
        }
    #endif
        default:
            snprintf(str, sizeof(str), "sock_ntop_host: unknown AF_xxx: %d, len %d",
                     sa->sa_family, salen);
            return(str);
        }
        return (NULL);
    }
  • 相关阅读:
    VSCode中按ESLint规则格式化Javascript代码
    VSCode设置资源管理器字体大小
    Windows下利用安装压缩包安装MySQL
    Windows部署Apache 2.4.46及PHP 8.0.3
    npm设置国内镜像
    IDEA运行Tomcat输出信息乱码
    深入理解jvm虚拟机读书笔记-Java内存区域与内存溢出异常
    Navicat Premium
    mysql安装
    ElasticSearch 基础
  • 原文地址:https://www.cnblogs.com/soldierback/p/10784462.html
Copyright © 2011-2022 走看看