分类: LINUX
2013-08-23 15:58:46
原文地址:linux下常用二层抓包源码实例 作者:newcch
#include #include #include #include #include /* 其中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 char MacLocal[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 pkg RecLen=%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); } |