linux 系统调用---ioctl

xiaoxiao2021-02-28  104

/***************************************************/   /**** 一个用ioctl实现的类似ifconfig命令的小程序 ****/   /***************************************************/   #include <stdio.h> //printf()    #include <unistd.h> //ioctl()    #include <sys/ioctl.h> //ioctl    #include <sys/socket.h> //socket()    #include <net/if.h> //struct ifconf{} & struct ifreq{}    #include <string.h> //strcpy()    #include <arpa/inet.h> //inet_ntoa()    #include <stdlib.h> //malloc() & free()       int print_if_addr(int fd, char *interface_name); //打印接口的ip地址    int print_if_mac(int fd, char *interface_name); //打印接口的mac地址    int print_if_broadaddr(int fd, char *interface_name); //打印接口的广播地址    int print_if_mask(int fd, char *interface_name); //打印接口的掩码    int print_if_mtu(int fd, char *interface_name); //打印接口的mtu    int print_all_interface(); //打印所有接口的基本信息    int print_if_addr6(char *interface_name); //打印接口的ipv6地址    int print_interface_info(char *interface_name); //打印接口的以上所有信息    int set_if_up(char *interface_name); //启动接口    int set_if_down(char *interface_name); //关闭接口    int set_if_ip(char *interface_name, char *ip_str); //设置接口的ip地址    void usage(); //打印该程序的使用手册       int main(int argc, char **argv)    {        int sockfd;        printf("/n **********funway:用ioctl函数来实现ifconfig命令的效果**********/n");        switch(argc)        {            case 1:                print_all_interface();                break;            case 2:                print_interface_info(argv[1]);                break;            case 3:                if(strcmp(argv[2], "up") == 0)                    set_if_up(argv[1]);                else if(strcmp(argv[2], "down") == 0)                    set_if_down(argv[1]);                else                set_if_ip(argv[1], argv[2]);                    break;            default:                usage();                break;        }           return 0;    }       void usage()    {        printf("usage: ./myifconfig [interface [down|up|ip]]/n");    }       int print_if_addr(int fd, char *if_name)    {        struct sockaddr_in *ip;        struct ifreq ifr;           strcpy(ifr.ifr_name, if_name);           if(ioctl(fd, SIOCGIFADDR, &ifr) < 0)        {            perror("ioctl SIOCGIFADDR error");            return -1;        }           ip = (struct sockaddr_in *)&ifr.ifr_addr; //获得ipv4地址        printf(" IP: %s/n", inet_ntoa(ip->sin_addr)); //将ipv4地址转换为主机字节序的字符串并输出        return 0;    }       int print_if_broadaddr(int fd, char *if_name)    {        struct sockaddr_in *ip;        struct ifreq ifr;           strcpy(ifr.ifr_name, if_name);           if(ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)        {            perror("ioctl SIOCGIFBRDADDR error");            return -1;        }           ip = (struct sockaddr_in *)&ifr.ifr_broadaddr; //获得广播地址        printf(" Broadcast: %s/n", inet_ntoa(ip->sin_addr));        return 0;    }       int print_if_mask(int fd, char *if_name)    {        struct sockaddr_in *ip;        struct ifreq ifr;           strcpy(ifr.ifr_name, if_name);           if(ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)        {            perror("ioctl SIOCGIFNETMASK error");            return -1;        }           ip = (struct sockaddr_in *)&ifr.ifr_ifru.ifru_netmask; //获得子网掩码。注意!我们仍放在struct aockaddr_in结构中返回        printf(" Mask: %s/n", inet_ntoa(ip->sin_addr));        return 0;    }       int print_if_mac(int fd, char *if_name)    {        unsigned char *p; //这里要用unsigned char,因为char要对[1xxx xxxx]这样的数进行补码运算的,但mac地址是不需要符号的数值        struct ifreq ifr;           strcpy(ifr.ifr_name, if_name);           if(ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)        {            perror("ioctl SIOCGIFHWADDR error");            return -1;        }           p = (char *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0]; //获得接口的MAC地址,用字符串指针返回        printf(" MAC: x:x:x:x:x:x/n", *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5));        return 0;    }       int print_if_mtu(int fd, char *if_name)    {        unsigned int mtu;        struct ifreq ifr;           strcpy(ifr.ifr_name, if_name);           if(ioctl(fd, SIOCGIFMTU, &ifr) < 0)        {            perror("ioctl SIOCGIFMTU error");            return -1;        }           mtu = ifr.ifr_ifru.ifru_mtu; //获得子网掩码。注意!我们仍放在struct aockaddr_in结构中返回        printf(" MTU: %d/n", mtu);        return 0;    }       int print_if_addr6(char *if_name)    {        unsigned int mtu;        struct ifreq ifr;        int sockfd;           if((sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           /* strcpy(ifr.ifr_name, if_name);         if(ioctl(fd, SIOCGIFMTU, &ifr) < 0)       {           perror("ioctl SIOCGIFMTU error");           return -1;       }         mtu = ifr.ifr_ifru.ifru_mtu; //获得子网掩码。注意!我们仍放在struct aockaddr_in结构中返回       printf(" ipv6: %d/n", mtu);       */        //未写完,不知道怎么获得ipv6地址。。。        return 0;    }       int print_all_interface()    {        struct ifconf ifc;        struct ifreq *ifr_p;        int sockfd, len, old_len = 0, i;        char *buf;           if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           len = 10 * sizeof(struct ifreq);        for( ; ; )        {            if((buf = malloc(len)) == NULL)            {                perror("malloc error");                return -1;            }            ifc.ifc_len = len;            ifc.ifc_buf = buf;            if(ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)            {                perror("ioctl SIOCGIFCONF error");                return -1;            }            if(ifc.ifc_len == old_len)            break;            old_len = ifc.ifc_len;            len += 10 * sizeof(struct ifreq);            free(buf);        }        printf("we have %d interfaces/n", ifc.ifc_len / sizeof(struct ifreq));           for(i = 0; i < ifc.ifc_len / sizeof(struct ifreq); i++)        {            ifr_p = &ifc.ifc_req[i];            printf("/ninterface [%s]:/n", ifr_p->ifr_name);               print_if_addr(sockfd, ifr_p->ifr_name);            print_if_broadaddr(sockfd, ifr_p->ifr_name);            print_if_mask(sockfd, ifr_p->ifr_name);            print_if_mac(sockfd, ifr_p->ifr_name);            print_if_mtu(sockfd, ifr_p->ifr_name);        }        close(sockfd);        return 0;    }       int print_interface_info(char *if_name)    {        int sockfd;        if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           printf("%s:/n", if_name);        print_if_addr(sockfd, if_name);        print_if_broadaddr(sockfd, if_name);        print_if_mask(sockfd, if_name);        print_if_mac(sockfd, if_name);        print_if_mtu(sockfd, if_name);        close(sockfd);        return 0;    }       int set_if_up(char *if_name) //启动接口    {        struct ifreq ifr;        int sockfd;           if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           strcpy(ifr.ifr_name, if_name);        if(ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)        {            perror("ioctl SIOCGIFFLAGS error");            return -1;        }        ifr.ifr_flags |= IFF_UP;        if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)        {            perror("ioctl SIOCSIFFLAGS error");            return -1;        }        return 0;    }       int set_if_down(char *if_name) //关闭接口    {        struct ifreq ifr;        int sockfd;           if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           strcpy(ifr.ifr_name, if_name);        if(ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0)        {            perror("ioctl SIOCGIFFLAGS error");            return -1;        }        ifr.ifr_flags &= ~IFF_UP; //将IIF_UP取反后与原来的标志进行 与运算。        if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)        {            perror("ioctl SIOCSIFFLAGS error");            return -1;        }        return 0;    }       int set_if_ip(char *if_name, char *ip_str) //设置接口的ip地址    {        struct ifreq ifr;        struct sockaddr_in ip_addr;        int sockfd;           if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)        {            perror("Socket error");            return -1;        } // 创建用来检查网络接口的套接字           ip_addr.sin_family = AF_INET;        if(inet_pton(AF_INET, ip_str, &ip_addr.sin_addr) < 1)        {            perror("error ipv4 addr:");            return -1;        }           strcpy(ifr.ifr_name, if_name);        memcpy(&ifr.ifr_addr, &ip_addr, sizeof(struct sockaddr_in));        if(ioctl(sockfd, SIOCSIFADDR, &ifr) < 0)        {            perror("ioctl SIOCSIFADDR error");            return -1;        }        return 0;    }    注:有线连接mac接口名:eth0    无线连接MAC接口名:wlan0
转载请注明原文地址: https://www.6miu.com/read-36940.html

最新回复(0)