#include
#include
#include
#include
#include /* the L2 protocols */
/*
其中socket_type可以是SOCK_DGRAM,SOCK_RAW。设置为SOCK_RAW则接收到的报文中包含二层协议头,否则只有二层数据帧内容。
例如:
*/
int main(void)
{
int skfd;
int retval;
int RecLen;
unsigned char *resultframe;
int resultsize;
int i;
unsigned charMacLocal[6];
skfd = socket(PF_PACKET, SOCK_RAW, htons(SOCK_RAW));
/*2、绑定到网络接口这一步是可选的。如果不绑定,则所有接口上的二层数据帧都会收到。*/
struct sockaddr_ll ll;
struct ifreq ifr;
struct ifreq ifr1;
resultframe=malloc(10*1024);
if(resultframe==NULL)
{
printf("malloc resultframe failed.\r\n");
return -1;
}
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
//获取这个接口的索引
retval = ioctl(skfd, SIOCGIFINDEX, &ifr);
//获取这个接口的MAC地址,需要使用另一个零时变量ifr1,否则绑定和收包都会失败
strncpy(ifr1.ifr_name, "eth0", sizeof(ifr.ifr_name));
retval = ioctl(skfd, SIOCGIFHWADDR, &ifr1);
memcpy((char *)MacLocal, (char *)&ifr1.ifr_hwaddr.sa_data[0], 6);
printf("mac=%02x:%02x:%02x:%02x:%02x:%02x\r\n",MacLocal[0],MacLocal[1],MacLocal[2],
MacLocal[3],MacLocal[4],MacLocal[5]);
memset(&ll, 0, sizeof(ll));
ll.sll_family = PF_PACKET;
ll.sll_ifindex = ifr.ifr_ifindex;
ll.sll_protocol = htons(ETH_P_ALL);
if (bind(skfd, (struct sockaddr *) &ll, sizeof(ll)) < 0)
{
perror("bind[PF_PACKET]");
close(skfd);
free(resultframe);
return NULL;
}
/*protocol是需要监听的协议类型,如果为ETH_P_ALL,则接收所有数据帧。
注意:
桥中接收不到转发的非自己的报文*/
//设置最大可接收的单个报文长度,多余字节丢弃
resultsize=1800;
while(1)
{
printf("now to receive pkg\r\n");
RecLen=recvfrom(skfd, resultframe, resultsize, 0, 0, 0);
if(RecLen==-1)
break;
//把本接口发送的报文过滤掉
if(memcmp(resultframe+6,MacLocal,6)==0)
{
printf("Recv Own Pkg Out....\r\n");
continue;
}
printf("end to receive pkgRecLen=%d.\r\n",RecLen);
#if 0
if(RecLen>1600)
{
for(i=0;i
{
printf("%02x ",resultframe[i]);
if((i+1)%16==0)
printf("\r\n");
}
printf("\r\n");
break;
}
else
#endif
{
for(i=0;i<16;i++)
printf("%02x ",resultframe[i]);
printf("\r\n");
}
/*
for(i=0;i<16;i++)
printf("%02x ",resultframe[i]);
printf("\r\n");*/
}
close(skfd);
free(resultframe);
sleep(1000);
}