linux 设置网络API --- 开/关网卡、设置/获取Mac地址

来源:互联网 发布:预科生的贩毒网络免费 编辑:程序博客网 时间:2024/06/11 19:05

最近在做项目过程中,由于在多线程中使用system函数,有时候出现莫名程序异常终止,最后决定替换所有的system函数,但是对于设置mac地址这个函数试了很多次都没有成功;今天在此总结下原因:

1. 编写的关闭/打开网卡函数没有延时;(一般情况设置开关网卡可能需要初始化,所以如果开关连续可能没有初始化成功,你可以试试在嵌入式Linux命令行下快速的开关网卡,也是没有反应的)

2. 类型转换问题;(由于为了便捷,使用sscanf提取mac字符串,如果使用8bit提取%x,转换出错,最后只能使用32bit,再一个个赋值即可)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/ioctl.h>  
  4. #include <string.h>  
  5. #include <sys/types.h>  
  6. #include <sys/socket.h>  
  7. #include <net/if.h>  
  8. #include <netinet/in.h>  
  9.   
  10. typedef signed   char   INT8S;  
  11. typedef unsigned char   INT8U;  
  12. typedef signed   short  INT16S;  
  13. typedef unsigned short  INT16U;  
  14. typedef signed   int    INT32S;  
  15. typedef unsigned int    INT32U;  
  16.   
  17.   
  18.   
  19. //add by lightd, 2014-06-04  
  20. //============================================================================  
  21. //Function:    ifconfig_ethx_down_API   
  22. //Description: 关闭本地指定网卡 - eg: ifconfig eth0 down  
  23. //Input:               
  24. //Output:          
  25. //Return:                     
  26. //Others:      None  
  27. //============================================================================  
  28. INT8S ifconfig_ethx_down_API(const INT8U *interface_name)  
  29. {  
  30.     INT32S       sock_fd;  
  31.     struct ifreq ifr;  
  32.     int          selector;   
  33.        
  34.     //传入参数合法性检测  
  35.     if(interface_name == NULL)  
  36.     {  
  37.         fprintf(stdout, "%s:%d: args invalid!", __FUNCTION__, __LINE__);  
  38.         return -1;  
  39.     }  
  40.       
  41.     //禁止关闭回环  
  42.     if(strncmp((char *)interface_name, (char *)"lo", 2) == 0)  
  43.     {  
  44.        fprintf(stdout, "%s:%d: You can't pull down interface lo!",  __FUNCTION__, __LINE__);  
  45.        return 0;      
  46.     }  
  47.      
  48.     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);  
  49.     if(sock_fd < 0)  
  50.     {  
  51.         fprintf(stdout, "%s:%d: socket failed!",  __FUNCTION__, __LINE__);  
  52.         return -2;  
  53.     }  
  54.   
  55.     sprintf(ifr.ifr_name, "%s", interface_name);  
  56.      
  57.     if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0)  
  58.     {  
  59.         fprintf(stdout, "%s:%d: ioctl failed 1!",  __FUNCTION__, __LINE__);  
  60.         return -3;  
  61.     }  
  62.       
  63.     selector = IFF_UP;  
  64.     ifr.ifr_flags &= ~selector;   
  65.     if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0)  
  66.     {  
  67.         fprintf(stdout, "%s:%d: ioctl failed 2!",  __FUNCTION__, __LINE__);  
  68.         return -4;  
  69.     }  
  70.   
  71.     close( sock_fd );  
  72.       
  73.     return 0;  
  74. }  
  75.   
  76. //add by lightd, 2014-06-04  
  77. //============================================================================  
  78. //Function:    ifconfig_ethx_up_API   
  79. //Description: 打开本地指定网卡 - eg: ifconfig eth0 up  
  80. //Input:               
  81. //Output:          
  82. //Return:                     
  83. //Others:            None  
  84. //============================================================================  
  85. INT8S ifconfig_ethx_up_API(const INT8U *interface_name)  
  86. {  
  87.     INT32S          sock_fd;  
  88.     struct ifreq    ifr;  
  89.     int             selector;   
  90.       
  91.     //传入参数合法性检测  
  92.     if(interface_name == NULL)  
  93.     {  
  94.         fprintf(stdout, "%s:%d: args invalid!",  __FUNCTION__, __LINE__);  
  95.         return -1;  
  96.     }  
  97.   
  98.     sock_fd = socket(AF_INET, SOCK_DGRAM, 0);  
  99.     if(sock_fd < 0)  
  100.     {  
  101.         fprintf(stdout, "%s:%d: create socket failed!",  __FUNCTION__, __LINE__);  
  102.         return -2;  
  103.     }  
  104.       
  105.     sprintf(ifr.ifr_name, "%s", interface_name);  
  106.     if(ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0)  
  107.     {  
  108.         fprintf(stdout, "%s:%d: ioctl error 1",  __FUNCTION__, __LINE__);  
  109.         return -3;  
  110.     }  
  111.       
  112.     selector = (IFF_UP | IFF_RUNNING);  
  113.     ifr.ifr_flags |= selector;    
  114.     if(ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0)  
  115.     {  
  116.         fprintf(stdout, "%s:%d: ioctl error 2",  __FUNCTION__, __LINE__);  
  117.         return -4;  
  118.     }  
  119.   
  120.     close( sock_fd );  
  121.       
  122.     return 0;     
  123. }  
  124.   
  125.   
  126.   
  127. //add by lightd, 2014-06-04  
  128. //============================================================================  
  129. //Function:    SetLocalMACAddr_API   
  130. //Description: 设置本地指定网卡的MAC  
  131. //Input:               
  132. //Output:          
  133. //Return:                     
  134. //Others:      None  
  135. //Test result: 测试结果 - 连续调用20次不出错  
  136. //============================================================================  
  137. INT8S SetLocalMACAddr_API(const INT8U *interface_name, const INT8U *str_macaddr)    
  138. {  
  139.     int             ret;    
  140.     int             sock_fd;    
  141.     struct ifreq    ifr;        
  142.     INT32U          mac2bit[6];  
  143.       
  144.     //传入参数合法性检测  
  145.     if(interface_name == NULL || str_macaddr == NULL)  
  146.     {  
  147.         fprintf(stdout, "%s:%d: args invalid!",  __FUNCTION__, __LINE__);  
  148.         return -1;  
  149.     }  
  150.       
  151.     //提取mac格式   
  152.     sscanf((char *)str_macaddr, "%02X:%02X:%02X:%02X:%02X:%02X", (INT8U *)&mac2bit[0], (INT8U *)&mac2bit[1], (INT8U *)&mac2bit[2], (INT8U *)&mac2bit[3], (INT8U *)&mac2bit[4], (INT8U *)&mac2bit[5]);  
  153.       
  154.     sock_fd = socket(PF_INET, SOCK_DGRAM, 0);    
  155.     if (sock_fd < 0)    
  156.     {    
  157.         perror("socket error");         
  158.         return -2;    
  159.     }    
  160.       
  161.     //设置mac前,必须关闭对应的网卡 - 否则出错  
  162.     ret = ifconfig_ethx_down_API( interface_name );  
  163.     if(ret < 0)  
  164.     {  
  165.         fprintf(stdout, "%s:%d: close eth0 error",  __FUNCTION__, __LINE__);  
  166.         return -3;  
  167.     }  
  168.     sleep(1); //等待网卡关闭OK  
  169.       
  170.     sprintf(ifr.ifr_ifrn.ifrn_name, "%s", interface_name);    
  171.     ifr.ifr_ifru.ifru_hwaddr.sa_family = 1;    
  172.     ifr.ifr_ifru.ifru_hwaddr.sa_data[0] = mac2bit[0];  
  173.     ifr.ifr_ifru.ifru_hwaddr.sa_data[1] = mac2bit[1];  
  174.     ifr.ifr_ifru.ifru_hwaddr.sa_data[2] = mac2bit[2];  
  175.     ifr.ifr_ifru.ifru_hwaddr.sa_data[3] = mac2bit[3];  
  176.     ifr.ifr_ifru.ifru_hwaddr.sa_data[4] = mac2bit[4];  
  177.     ifr.ifr_ifru.ifru_hwaddr.sa_data[5] = mac2bit[5];  
  178.       
  179.     ret = ioctl(sock_fd, SIOCSIFHWADDR, &ifr);    
  180.     if (ret != 0)    
  181.     {    
  182.         perror("set mac address erorr");  
  183.         return -4;    
  184.     }    
  185.       
  186.     close( sock_fd );  
  187.       
  188.     ret = ifconfig_ethx_up_API( interface_name );  
  189.     if(ret < 0)  
  190.     {  
  191.         fprintf(stdout, "%s:%d: open eth0 error!",  __FUNCTION__, __LINE__);  
  192.         return -5;  
  193.     }  
  194.       
  195.     sleep(2); //等待网卡打开OK  
  196.   
  197.       
  198.     return 0;    
  199. }  
  200.   
  201. //add by lightd, 2014-06-04  
  202. //============================================================================  
  203. //Function:    GetLocalMACAddr_API   
  204. //Description: 获取本地指定网卡的MAC  
  205. //Input:               
  206. //Output:          
  207. //Return:                     
  208. //Others:      None  
  209. //============================================================================  
  210. INT8S GetLocalMACAddr_API(const INT8U *interface_name, INT8U *str_macaddr)    
  211. {    
  212.     INT32S       sock_fd;    
  213.     struct ifreq ifr_mac;    
  214.       
  215.     //传入参数合法性检测  
  216.     if(interface_name == NULL || str_macaddr == NULL)  
  217.     {  
  218.         fprintf(stdout, "%s:%d: args invalid!",  __FUNCTION__, __LINE__);  
  219.         return -1;  
  220.     }  
  221.       
  222.     sock_fd = socket( AF_INET, SOCK_STREAM, 0 );    
  223.     if( sock_fd == -1)    
  224.     {    
  225.         perror("create socket failed");    
  226.         sprintf((char *)str_macaddr, "00:00:00:00:00:00");  
  227.         return -2;    
  228.     }    
  229.         
  230.     //指定网卡  
  231.     memset(&ifr_mac, 0, sizeof(ifr_mac));       
  232.     sprintf(ifr_mac.ifr_name, "%s", interface_name);       
  233.     
  234.     //获取指定网卡的mac地址  
  235.     if( (ioctl( sock_fd, SIOCGIFHWADDR, &ifr_mac)) < 0 )   
  236.     {    
  237.         perror("mac ioctl error");    
  238.         sprintf((char *)str_macaddr, "00:00:00:00:00:00");  
  239.         return -3;    
  240.     }    
  241.         
  242.     close( sock_fd );    
  243.       
  244.     sprintf((char *)str_macaddr,"%02x:%02x:%02x:%02x:%02x:%02x",    
  245.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[0],    
  246.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[1],    
  247.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[2],    
  248.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[3],    
  249.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[4],    
  250.             (unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]);    
  251.     
  252.     printf("local mac:<%s> \n", str_macaddr);        
  253.       
  254.     return 0;  
  255. }  
  256.   
  257.   
  258.   
  259. int main(void)  
  260. {  
  261.     INT8U str_macaddr[20];  
  262.       
  263.     memset(str_macaddr, 0, sizeof(str_macaddr));  
  264.     GetLocalMACAddr_API("eth0", str_macaddr);  
  265.     fprintf(stdout, "1 mac: %s\n", str_macaddr);  
  266.       
  267.     //ifconfig_ethx_down_API("eth0");  
  268.           
  269.     //system("ifconfig eth0 down");  
  270.     //usleep(500000);  
  271.     //system("ifconfig eth0 up");  
  272.     //usleep(500000);  
  273.     //sleep(1); //10ms  
  274.     //ifconfig_ethx_down_API("eth0");  
  275.     //sleep(1);  
  276.       
  277.     SetLocalMACAddr_API("eth0""08:00:11:22:33:44");  
  278.     //ifconfig_ethx_up_API("eth0");  
  279.     //ifconfig_ethx_up_API("eth0");  
  280.     //sleep(2);   
  281.       
  282.     memset(str_macaddr, 0, sizeof(str_macaddr));  
  283.     GetLocalMACAddr_API("eth0", str_macaddr);  
  284.     fprintf(stdout, "2 mac: %s\n", str_macaddr);  
  285.       
  286.     system("ping 200.200.200.100");  
  287.     //usleep(50000);   
  288.     //ifconfig_ethx_down_API("eth0");  
  289.     //ifconfig_ethx_up_API("eth0");  
  290.   
  291.     //memset(str_macaddr, 0, sizeof(str_macaddr));  
  292.     //GetLocalMACAddr_API("eth0", str_macaddr);  
  293.     fprintf(stdout, "2 mac: %s\n", str_macaddr);  
  294.           
  295.     return 0;  
  296. }  
0 0
原创粉丝点击