linux基础编程 链路层socket 摆脱winPcap 夸网段socket通信 可夸平台移植

Linux链路层收发数据
本文介绍了一种在Linux环境下直接从链路层(MAC)收发数据帧的方法,无需依赖额外库,通过创建链路层套接字实现。提供了具体代码示例,展示如何创建、绑定和配置套接字,以及如何收发数据包。
在linux环境中要从链路层(MAC)直接收发数据帧,可以通过libpcap与libnet两个动态库来分别完成收与发的工作。虽然它已被广泛使用,但在要求进行跨平台移植的软件中使用就很难办到了。。

这是一种更为直接地、无须安装其它库的从MAC层收发数据帧的方式,即通过定义链路层的套接字来完成。

下面的代码也是我做的项目中的代码(夸网段访问网络中的嵌入式设备),去掉了敏感部分,和大家共享!

但是得尊重别人的劳动成果,转载注明出处,谢谢!

[cpp]  view plain copy
  1. #include <string.h>           
  2. #include <stdio.h>            
  3. #include <unistd.h>  
  4. #include <stdlib.h>  
  5. #include <errno.h>   
  6. #include <pthread.h>        
  7. #include <sys/types.h>        
  8. #include <sys/socket.h>        
  9. #include <sys/ioctl.h>         
  10. #include <net/if.h>           
  11. #include <linux/if_packet.h>  
  12. #include <arpa/inet.h>  
  13.   
  14.   
  15. /*链路层socket接收端口*/  
  16. #define RAW_PROTOCOL 0x0909  
  17. #define ETH_NAME "eth0"  
  18.   
  19. #define __DEBUG  
  20. #ifdef __DEBUG  
  21. #define DBG(fmt,args...) fprintf(stdout,  fmt,  ##args)  
  22. #else  
  23. #define DBG(fmt,args...)  
  24. #endif  
  25. #define ERR(fmt,args...) fprintf(stderr,  fmt,  ##args)  
  26.   
  27. static int raw_fd;  
  28. static int if_index;  
  29. static int isSearchQuit = 0;  
  30. unsigned char my_mac[6];    /*用于本机保存网卡地址*/  
  31.   
  32. /*接收链路层数据包*/  
  33. int GetPacket(unsigned char *buf, int *len)  
  34. {  
  35.     int length = 0;  
  36.   
  37.     length = recvfrom( raw_fd, buf, 2000, 0, NULL, NULL );  
  38.     if ( length < 0 )    {  
  39.         ERR("failed to receive buf!");  
  40.         return -1;  
  41.     }else   {  
  42.         *len = length;  
  43.         return 0;  
  44.     }  
  45. }  
  46.   
  47. /*发送链路层数据包*/  
  48. int SendPacket(unsigned char *buf, int len)  
  49. {  
  50.     struct sockaddr_ll link;  
  51.     link.sll_ifindex = if_index;  
  52.   
  53.     memcpy( link.sll_addr, buf, link.sll_halen );  
  54.   
  55.     if ( sendto( raw_fd, buf, len, 0, (struct sockaddr *)&link, sizeof(link) ) < 0 ) {  
  56.         ERR( "failed to send to RAW socket!\r\n" );  
  57.         return -1;  
  58.     }  
  59.     return 0;  
  60. }  
  61.   
  62. void ShowData(unsigned char *d1,int len)  
  63. {  
  64.     int i;  
  65.     for(i=0;i<len;i++)  
  66.         printf("%02x ",d1[i]);  
  67.     printf("\n\r");  
  68. }  
  69.   
  70. void *RawSocketThread(void *arg)  
  71. {  
  72.     unsigned char rcvPackage[70];  
  73.     unsigned char sndPackage[70];  
  74.       
  75.     int len;  
  76.     int curStatus = 0;  
  77.     while(1){  
  78.         int ret = 0;  
  79.         int done = 0;  
  80.         ret = GetPacket(rcvPackage,&len);       //block here  
  81.         if(ret == -1)  
  82.             break;  
  83.         ShowData(rcvPackage,len);  
  84.         sleep(1);  
  85.         ret = SendPacket(rcvPackage,len);  
  86.         if(ret ==-1)  
  87.             break;  
  88.   
  89.     }  
  90.     pthread_exit(NULL);  
  91.     close(raw_fd);  
  92. }  
  93.   
  94. int RawSocketInit()  
  95. {  
  96.     pthread_t tRawSocketThr;  
  97.     struct ifreq req;  
  98.     /*创建链路层socket,注意PF_PACKET,SOCK_RAW,以及RAW_PROTOCOL(自定义的)*/  
  99.     if ( (raw_fd = socket(PF_PACKET, SOCK_RAW, htons( RAW_PROTOCOL ) ) ) < 0 )   {  
  100.         ERR( "failed to create raw socket!\n" );  
  101.         return -1;  
  102.     }  
  103.     /*绑定网卡*/  
  104.     strcpy( req.ifr_name, ETH_NAME );  
  105.     if ( ioctl( raw_fd, SIOCGIFFLAGS, &req ) < 0 )   {  
  106.         ERR( "failed to do ioctl!" );  
  107.         return -1;  
  108.     }  
  109.     /*设置工作模式*/  
  110.     req.ifr_flags |= IFF_PROMISC;  
  111.   
  112.     if ( ioctl( raw_fd, SIOCSIFFLAGS, &req ) < 0 )   {  
  113.         ERR( "failed to set eth0 into promisc mode!" );  
  114.         return -1;  
  115.     }  
  116.   
  117.     if ( ioctl( raw_fd, SIOCGIFHWADDR, &req ) < 0 )  {  
  118.         ERR( "failed to get interface hw address!" );  
  119.         return -1;  
  120.     }  
  121.   
  122.     memcpy( my_mac, req.ifr_hwaddr.sa_data, sizeof(my_mac) );  
  123.   
  124.     if ( ioctl( raw_fd, SIOCGIFINDEX, &req ) < 0 )   {  
  125.         ERR( "failed to get interface index!" );  
  126.         return -1;  
  127.     }  
  128.     if_index = req.ifr_ifindex;  
  129.   
  130.     if(pthread_create(&tRawSocketThr,NULL,RawSocketThread,NULL) == -1){  
  131.         ERR("ERROR in RawSocketThread\n");  
  132.         return -1;  
  133.     }  
  134.     pthread_detach(tIPNCSearchThr);  
  135.     return 0;  
  136. }  
  137.   
  138. #if 1  
  139. int main()  
  140. {     
  141.     int count =0;  
  142.     RawSocketInit();  
  143.     while(1){  
  144.         sleep(1);  
  145.     }  
  146.   
  147. }  
  148. #endif   

运行结果,接收自网络中的完整数据包:

[cpp]  view plain copy
  1. [root@localhost src]# ./RawSocket  
  2. ff ff ff ff ff ff 1c 6f 65 dc fa fb 09 09 00 00 00 00 06 04 01 00 00 00 00 00 00 00 c0 a8 01 dc ff ff ff ff ff ff c0 a8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值