午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

linux下ioctl操作網(wǎng)絡(luò)接口

 身子莫 2013-05-13
在linux下使用ioctl操作網(wǎng)絡(luò)接口時(shí),首先需要兩個(gè)結(jié)構(gòu)體結(jié)構(gòu)ifconf和ifreq
ifconf用來(lái)保存所有網(wǎng)絡(luò)接口的信息,其結(jié)構(gòu)體為:
  1. struct ifconf   
  2. {   
  3.     int ifc_len;      /* size of buffer */  //存放接口信息所需的長(zhǎng)度
  4.     union {              
  5.        char *ifc_buf; /* buffer address */   //存放接口信息的地址
  6.        struct ifreq *ifc_req; /* array of structures */  
  7.     };    
  8. };       
  9. #define ifc_buf ifc_ifcu.ifcu_buf   
  10. #define ifc_req ifc_ifcu.ifcu_req


ifreq用來(lái)保存某個(gè)接口的信息,用來(lái)獲取Ip地址,MAC,子網(wǎng)掩碼等網(wǎng)絡(luò)接口信息,其結(jié)構(gòu)體為:
  1. struct ifreq{  
  2. #define IFHWADDRLEN 6  
  3. #define IFNAMSIZ IF_NAMESIZE  
  4.     union{  
  5.         char ifrn_name[IFNAMSIZ];  //接口的名字  
  6. } ifr_ifrn;  
  7.   
  8.   
  9.     union{  
  10.         struct sockaddr ifru_addr;  //接口的IP地址
  11.         struct sockaddr ifru_dstaddr;  
  12.         struct sockaddr ifru_broadaddr;  //接口的廣播地址
  13.         struct sockaddr ifru_netmask;    //接口的子網(wǎng)掩碼
  14.         struct sockaddr ifru_hwaddr;     //接口的MAC地址
  15.         short int ifru_flags;  
  16.         int ifru_ivalue;  
  17.         int ifru_mtu;                   //接口傳輸單元的大小
  18.         struct ifmap ifru_map;  
  19.         char ifru_slave[IFNAMSIZ];   
  20.         char ifru_newname[IFNAMSIZ];  
  21.         __caddr_t ifru_data;  
  22. } ifr_ifru;  
  23. };  
  24. #define ifr_name ifr_ifrn.ifrn_name   
  25. #define ifr_hwaddr ifr_ifru.ifru_hwaddr   
  26. #define ifr_addr ifr_ifru.ifru_addr   
  27. #define ifr_dstaddr ifr_ifru.ifru_dstaddr   
  28. #define ifr_broadaddr ifr_ifru.ifru_broadaddr   
  29. #define ifr_netmask ifr_ifru.ifru_netmask   
  30. #define ifr_flags ifr_ifru.ifru_flags   
  31. #define ifr_metric ifr_ifru.ifru_ivalue   
  32. #define ifr_mtu ifr_ifru.ifru_mtu   
  33. #define ifr_map ifr_ifru.ifru_map   
  34. #define ifr_slave ifr_ifru.ifru_slave   
  35. #define ifr_data ifr_ifru.ifru_data   
  36. #define ifr_ifindex ifr_ifru.ifru_ivalue   
  37. #define ifr_bandwidth ifr_ifru.ifru_ivalue   
  38. #define ifr_qlen ifr_ifru.ifru_ivalue   
  39. #define ifr_newname ifr_ifru.ifru_newname   
  40. #define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)  
  41. #define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)  
  42. #define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
  43.   
具體操作方法是:
1.通過(guò)ioctl獲得本地所有接口的信息并保存在ifconf結(jié)構(gòu)體中;
2.在從ifconf中獲得具體某個(gè)ifreq的接口信息
其中:
ifc_len:表示用來(lái)存放所有接口信息的緩沖區(qū)長(zhǎng)度

ifc_buf:表示存放接口信息的緩沖區(qū)

因此我們需要在程序開(kāi)始時(shí)對(duì)ifconf的ifc_led和ifc_buf進(jìn)行初始化
接下來(lái)使用ioctl獲取所有接口信息,完成后ifc_len內(nèi)存放實(shí)際獲得的借口信息總長(zhǎng)度
并且信息被存放在ifc_buf中。


實(shí)例:

#include <string.h>

 #include <net/if.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>  
 int main()
 {
 	int i=0;
 	int sockfd;
 	struct ifconf ifconf;
 	unsigned char buf[512];
 	struct ifreq *ifreq;
 
 	//初始化ifconf 
 	ifconf.ifc_len = 512;
 	ifconf.ifc_buf = buf;
 
 	if((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
 	{
 		perror("socket");
 		exit(1);
 	}
 	ioctl(sockfd, SIOCGIFCONF, &ifconf); //獲取所有接口信息 
 
 	//接下來(lái)一個(gè)一個(gè)的獲取IP地址 
 	ifreq = (struct ifreq*)buf;
 	for(i=(ifconf.ifc_len/sizeof(struct ifreq)); i>0; i--)
 	{
 		printf("name = [%s]n", ifreq->ifr_name);
 		printf("local addr = [%s]n",
 		inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));
 		ifreq++; 
 	}
 return 0;
 }

此參考程序是通過(guò)ioctl獲得本地接口的信息,我們也可以通過(guò)操作socket的函數(shù)寫(xiě)一些小的應(yīng)用程序,下面的例子是實(shí)現(xiàn)ifconfig的源代碼(自測(cè)試,可通過(guò))
#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); //啟動(dòng)接口
int set_if_down(char *interface_name); //關(guān)閉接口
int set_if_ip(char *interface_name, char *ip_str); //設(shè)置接口的ip地址
void usage(); //打印該程序的使用手冊(cè)
int main(int argc, char **argv)
{
int sockfd;
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地址轉(zhuǎn)換為主機(jī)字節(jié)序的字符串并輸出
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; //獲得子網(wǎng)掩碼。注意!我們?nèi)苑旁趕truct aockaddr_in結(jié)構(gòu)中返回
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!因?yàn)閏har要對(duì)[1xxx xxxx]這樣的數(shù)進(jìn)行補(bǔ)碼運(yùn)算的。
//但我們等下要打印的mac地址是不需要符號(hào)的數(shù)值
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地址,用字符串指針?lè)祷?/div>
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++);
//這么寫(xiě)會(huì)導(dǎo)致輸出為倒序。這并不是p指針有什么問(wèn)題,不信你可以用
// for(;;)
// printf(p++);
//來(lái)試驗(yàn)就是正確的,我猜倒序的原因是編譯器的優(yōu)化問(wèn)題吧
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; //獲得子網(wǎng)掩碼。注意!我們?nèi)苑旁趕truct aockaddr_in結(jié)構(gòu)中返回
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;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
/* strcpy(ifr.ifr_name, if_name);
if(ioctl(fd, SIOCGIFMTU, &ifr) < 0)
{
perror("ioctl SIOCGIFMTU error");
return -1;
}
mtu = ifr.ifr_ifru.ifru_mtu; //獲得子網(wǎng)掩碼。注意!我們?nèi)苑旁趕truct aockaddr_in結(jié)構(gòu)中返回
printf(" ipv6: %d/n", mtu);
*/
//未寫(xiě)完,不知道怎么獲得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;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
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(" Interface [%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;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
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) //啟動(dòng)接口
{
struct ifreq ifr;
int sockfd;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Socket error");
return -1;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
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) //關(guān)閉接口
{
struct ifreq ifr;
int sockfd;
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Socket error");
return -1;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
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取反后與原來(lái)的標(biāo)志進(jìn)行 與運(yùn)算。
if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) < 0)
{
perror("ioctl SIOCSIFFLAGS error");
return -1;
}
return 0;
}
int set_if_ip(char *if_name, char *ip_str) //設(shè)置接口的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;
} // 創(chuàng)建用來(lái)檢查網(wǎng)絡(luò)接口的套接字
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;
}

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多