1.设置数据链路层的原始套接字
2.设置为混杂模式
3.针对个层协议都有不同的数据结构,可以去/usr/include/netinet/目录下去查找相应的文件,察看struct的定义
4.如果自己定义结构体,必须注意大小端的问题。详情请看 /usr/include/netinet/ip.h中steuct iphdr 中ihl和version的定义。
5.本程序是从数据链路层开始抓区数据,如果想从IP层抓取TCP或者UDP数据的话,只需要修改socket函数中的第三个参数改为IPPROTO_TCP或者IPPROTO_UDP即可。
6.我只是把网卡名称设置为了 “eth0“, 在别的机器上,可能要改成别的名称。
7.通过这次编程知道了,127.0.0.1是自循环的,如果从数据链路层开始抓包的话,mac地址显示的是0(实际上可能都不经过数据链路层).
8.本程序,不支持无线网卡。
- #include <stdio.h>
- #include <net/ethernet.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
- #include <netinet/udp.h>
- #include <arpa/inet.h>
- #include <sys/ioctl.h>
- #include <string.h>
- #include <net/if.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- int analyData(char *data);
- int rawSocket();
- int setPromisc(char *,int *);
- int native(char *data);
- int count=0;
- int main(int argc,char **argv)
- {
- /* if(argc!=2)
- {
- perror("please enter the ecterface");
- exit(1);
- }
- */
- int sock;
- int msgsock;
- struct sockaddr_in rcvaddr;
- char buf[9216];
- struct ifreq ifr;
- int len;
- int rval;
- sock=rawSocket();
- setPromisc("eth0",&sock);
- len=sizeof(struct sockaddr);
- memset(buf,0,sizeof(buf));
- while(1)
- {
- rval=recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&rcvaddr,&len);
- if(rval>0)
- {
- printf("本次获取 %d bytes,以下是分析数据\n",rval);
- analyData(buf);
- }
- }
- return 0;
- }
- int analyData(char *data)
- {
- struct iphdr *ip;
- struct tcphdr *tcp;
- struct udphdr *udp;
- struct ether_header *ether;
- ether=(struct ether_header*)data;//若数据是从数据链路曾抓取的,那么就有这个以太网帧头
- count++;
- printf("Frame %d \n",count);
- printf("帧中协议: %04x\n",htons(ether->ether_type));
-
- /*mac部分*/
- int Ndata;
- u_int8_t *tmp = (u_int8_t *)data;
- printf("dst mac:\n");
- for(Ndata=0; Ndata<ETHER_ADDR_LEN; Ndata++){
- printf("%02x ", tmp[Ndata]);
- }
-
- tmp = (u_int8_t *)data + ETHER_ADDR_LEN;
- printf("\nsrc mac:\n");
- for(Ndata=6; Ndata<ETHER_ADDR_LEN + 6; Ndata++){
- printf("%02x ", tmp[Ndata]);
- }
- printf("\n");
-
- /*ip 部分*/
- ip=(struct iphdr*)(data+sizeof(struct ether_header));
- data = data + sizeof(struct ether_header);
- char ip_buf[100];
- printf("version: %d ", ip->version);
- printf("ttl: %d\n", ip->ttl);
- printf("Source IP::%s",inet_ntop(AF_INET, &ip->saddr, ip_buf, 100));
- printf("Dest IP::%s",inet_ntop(AF_INET, &ip->daddr, ip_buf, 100));
- printf("\n");
- /*tc部分*/
- data = data + (ip->ihl<<2);
- if(ip->protocol == 6){
- printf("tcp header:\n");
- tcp=(struct tcphdr *)data;
- printf("Source Port::%d\n",ntohs(tcp->source));
- printf("Dest Port::%d\n",ntohs(tcp->dest));
- printf("\n");
- }
- /*udp 部分*/
- if(ip->protocol == 17){
- udp = (struct udphdr *)data;
- printf("udp header:\n");
- printf("udp source port: %d\n", ntohs(udp->source));
- printf("udp dst port: %d\n", ntohs(udp->dest));
- printf("udp len \n: %d\n", ntohs(udp->len));
- }
- return 1;
- }
- int rawSocket()//创建原始套接字
- {
- int sock;
- // sock=socket(PF_INET,SOCK_RAW,IPPROTO_TCP);//IP层抓取
- sock=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));//数据链路层抓取
- if(sock<0)
- {
- printf("create raw socket failed::%s\n",strerror(errno));
- exit(1);
- }
-
- printf("raw socket ::%d created successful\n",sock);
- return sock;
- }
- int setPromisc(char *enterface,int *sock)//设置eth0的混乱模式
- {
- struct ifreq ifr;
- strcpy(ifr.ifr_name, "eth0");
- ifr.ifr_flags=IFF_UP|IFF_PROMISC|IFF_BROADCAST|IFF_RUNNING;
- if(ioctl(*sock,SIOCSIFFLAGS,&ifr)==-1)//设置混乱模式
- {
- perror("set 'eth0' to promisc model failed\n");
- exit(1);
- }
- printf("set '%s' to promisc successed\n",enterface);
- return 1;
- }
阅读(1922) | 评论(0) | 转发(0) |