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!因为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: %02x:%02x:%02x:%02x:%02x:%02x\n", *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5));
//printf(" MAC:%02x:%02x:%02x:%02x:%02x:%02x\n", *p++, *p++, *p++, *p++, *p++, *p++);
//这么写会导致输出为倒序。这并不是p指针有什么问题,不信你可以用
// for(;;) 
// printf(p++);
//来试验就是正确的,我猜倒序的原因是编译器的优化问题吧
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;
}

你可能感兴趣的:(网络,struct,socket,UP,include,interface)