这是一种更为直接地、无须安装其它库的从MAC层收发数据帧的方式,即通过定义链路层的套接字来完成。
下面的代码也是我做的项目中的代码(夸网段访问网络中的嵌入式设备),去掉了敏感部分,和大家共享!
但是得尊重别人的劳动成果,转载注明出处,谢谢!
- #include <string.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <linux/if_packet.h>
- #include <arpa/inet.h>
- /*链路层socket接收端口*/
- #define RAW_PROTOCOL 0x0909
- #define ETH_NAME "eth0"
- #define __DEBUG
- #ifdef __DEBUG
- #define DBG(fmt,args...) fprintf(stdout, fmt, ##args)
- #else
- #define DBG(fmt,args...)
- #endif
- #define ERR(fmt,args...) fprintf(stderr, fmt, ##args)
- static int raw_fd;
- static int if_index;
- static int isSearchQuit = 0;
- unsigned char my_mac[6]; /*用于本机保存网卡地址*/
- /*接收链路层数据包*/
- int GetPacket(unsigned char *buf, int *len)
- {
- int length = 0;
- length = recvfrom( raw_fd, buf, 2000, 0, NULL, NULL );
- if ( length < 0 ) {
- ERR("failed to receive buf!");
- return -1;
- }else {
- *len = length;
- return 0;
- }
- }
- /*发送链路层数据包*/
- int SendPacket(unsigned char *buf, int len)
- {
- struct sockaddr_ll link;
- link.sll_ifindex = if_index;
- memcpy( link.sll_addr, buf, link.sll_halen );
- if ( sendto( raw_fd, buf, len, 0, (struct sockaddr *)&link, sizeof(link) ) < 0 ) {
- ERR( "failed to send to RAW socket!\r\n" );
- return -1;
- }
- return 0;
- }
- void ShowData(unsigned char *d1,int len)
- {
- int i;
- for(i=0;i<len;i++)
- printf("%02x ",d1[i]);
- printf("\n\r");
- }
- void *RawSocketThread(void *arg)
- {
- unsigned char rcvPackage[70];
- unsigned char sndPackage[70];
- int len;
- int curStatus = 0;
- while(1){
- int ret = 0;
- int done = 0;
- ret = GetPacket(rcvPackage,&len); //block here
- if(ret == -1)
- break;
- ShowData(rcvPackage,len);
- sleep(1);
- ret = SendPacket(rcvPackage,len);
- if(ret ==-1)
- break;
- }
- pthread_exit(NULL);
- close(raw_fd);
- }
- int RawSocketInit()
- {
- pthread_t tRawSocketThr;
- struct ifreq req;
- /*创建链路层socket,注意PF_PACKET,SOCK_RAW,以及RAW_PROTOCOL(自定义的)*/
- if ( (raw_fd = socket(PF_PACKET, SOCK_RAW, htons( RAW_PROTOCOL ) ) ) < 0 ) {
- ERR( "failed to create raw socket!\n" );
- return -1;
- }
- /*绑定网卡*/
- strcpy( req.ifr_name, ETH_NAME );
- if ( ioctl( raw_fd, SIOCGIFFLAGS, &req ) < 0 ) {
- ERR( "failed to do ioctl!" );
- return -1;
- }
- /*设置工作模式*/
- req.ifr_flags |= IFF_PROMISC;
- if ( ioctl( raw_fd, SIOCSIFFLAGS, &req ) < 0 ) {
- ERR( "failed to set eth0 into promisc mode!" );
- return -1;
- }
- if ( ioctl( raw_fd, SIOCGIFHWADDR, &req ) < 0 ) {
- ERR( "failed to get interface hw address!" );
- return -1;
- }
- memcpy( my_mac, req.ifr_hwaddr.sa_data, sizeof(my_mac) );
- if ( ioctl( raw_fd, SIOCGIFINDEX, &req ) < 0 ) {
- ERR( "failed to get interface index!" );
- return -1;
- }
- if_index = req.ifr_ifindex;
- if(pthread_create(&tRawSocketThr,NULL,RawSocketThread,NULL) == -1){
- ERR("ERROR in RawSocketThread\n");
- return -1;
- }
- pthread_detach(tIPNCSearchThr);
- return 0;
- }
- #if 1
- int main()
- {
- int count =0;
- RawSocketInit();
- while(1){
- sleep(1);
- }
- }
- #endif
运行结果,接收自网络中的完整数据包:
- [root@localhost src]# ./RawSocket
- 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