windows下不能获取数据链路层的数据

所以拿不到mac地址,RawSocket 编程

要用管理员权限打开

看到这张图,我又想起了期末考试的时候,考了tcp源地址和目的地址,记反了,丢了四分,我现在还记忆深刻。唉~

  1 #include <winsock2.h>
  2 #include <ws2tcpip.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #define MAX_HOSTNAME_LAN 255
  6 #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
  7 #define MAX_ADDR_LEN 16
  8 
  9 struct ipheader{
 10     unsigned char ip_h1:4;       //先存低位,再存高位。这样两个的顺序就反了
 11     unsigned char ip_v:4;
 12     unsigned char ip_tos;        //服务类型 8位
 13     unsigned short int ip_len;   //ip数据包总长度
 14     unsigned short int ip_id;    //16位标识
 15     unsigned short int ip_off;   //标志加偏移量(16)位
 16     unsigned char ip_ttl;        //8位 生成时间
 17     unsigned char ip_p;          //8位协议
 18     unsigned short int ip_sum;   //16位首部校验和
 19     unsigned int ip_src;         //32位长
 20     unsigned int ip_dst;
 21 };
 22 typedef struct tcpheader{
 23     unsigned short int sport;
 24     unsigned short int dport;
 25     unsigned int th_seq;
 26     unsigned int th_ack;
 27     unsigned char th_x:4;
 28     unsigned char th_off:4;
 29     unsigned char Flags;
 30     unsigned short int th_win;
 31     unsigned short int th_sum;
 32     unsigned short int th_urp;
 33 }TCP_HDR;
 34 
 35 typedef struct udphdr{
 36     unsigned short sport;
 37     unsigned short dport;
 38     unsigned short len;
 39     unsigned short cksum;
 40 }UDP_HDR;
 41 
 42 int main(){
 43     SOCKET sock;
 44     WSADATA wsd;
 45     DWORD dwBytesRet;
 46     unsigned int optval =1;
 47     unsigned char *dataudp,*datatcp;
 48     int i,pCount=0,lentcp,lenudp;
 49     SOCKADDR_IN sa,saSource,saDest;
 50     struct hostent FAR *pHostent;      //域名和网络地址结构体
 51     /*
 52     struct hostent
 53 {
 54     char *h_name;  //主机名,即官方域名
 55     char **h_aliases;  //主机所有别名构成的字符串数组,同一IP可绑定多个域名
 56     int h_addrtype; //主机IP地址的类型,例如IPV4(AF_INET)还是IPV6
 57     int h_length;  //主机IP地址长度,IPV4地址为4,IPV6地址则为16
 58     char **h_addr_list;  // 主机的ip地址,以网络字节序存储。若要打印出这个IP,需要调用inet_ntoa()。
 59 };*/
 60 
 61     char FAR name[MAX_HOSTNAME_LAN];
 62     char  szSourceIP[MAX_ADDR_LEN],szDestIP[MAX_ADDR_LEN],RecvBuf[65535]={0};
 63     struct udphdr *pUdpheader;
 64     struct ipheader *pIpheader;
 65     struct tcpheader *pTcpheader;
 66     WSAStartup(MAKEWORD(2,1),&wsd);
 67     if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP))==SOCKET_ERROR)
 68     {
 69         printf("创建Socket失败!");
 70          exit(1);
 71     }
 72     /*struct sockaddr_in
 73 {
 74    short                sin_family;
 75    unsigned short       sin_port;
 76    struct in_addr       sin_addr;
 77    char                 sin_zero[8];
 78 }
 79     struct in_addr{
 80         in_addr_t          s_addr;
 81     };*/
 82     //因为 sin_addr里面只有一个,所以指向sin_addr.s_addr和sin_addr是一样的。
 83 
 84     gethostname(name,MAX_HOSTNAME_LAN);  //获得本主机的姓名
 85     pHostent = gethostbyname(name);  //成功返回Hostent地址指针 失败返回NULL
 86     sa.sin_family=AF_INET;          //使用ipv4地址
 87     sa.sin_port =htons(6000);       //端口
 88     memcpy(&sa.sin_addr.s_addr,pHostent->h_addr_list[0],pHostent->h_length);  //ip地址(本主机ip地址)
 89 
 90     /*u_long ippppp = inet_addr("10.1.12.78");
 91     sa.sin_addr.s_addr = ippppp;
 92     char ccc[16];
 93     strncpy(ccc,inet_ntoa(sa.sin_addr),16);
 94     printf("%s",ccc);
 95     */
 96 
 97     bind(sock,(SOCKADDR*)&sa,sizeof(sa));     //将ip和端口信息和sock绑定在一起
 98     //connect(sock,(SOCKADDR*)&sa,sizeof(sa));
 99     if(WSAGetLastError()==10013)
100         exit(1);
101     //控制一个套接字的模式,我也不知道干什么的
102     WSAIoctl(sock,SIO_RCVALL,&optval,sizeof(optval),NULL,0,&dwBytesRet,NULL,NULL);
103     pIpheader = (struct ipheader*)RecvBuf;//把RecvBuf首地址给ip首部指针
104     pTcpheader = (struct tcpheader*)(RecvBuf+sizeof(struct ipheader));//往后挪了一个IP首部的大小
105     pUdpheader = (struct udphdr*)(RecvBuf+sizeof(struct ipheader));//udp也是和tcp共用一个地址
106 
107     while(1){
108         memset(RecvBuf,0,sizeof(RecvBuf));//初始化RecvBuf
109         //接受从所有的ip包
110         recv(sock,RecvBuf,sizeof(RecvBuf),0);
111         saSource.sin_addr.s_addr = pIpheader->ip_src;//原地址
112         //将ip地址转换成存储在数组里面
113         strncpy(szSourceIP,inet_ntoa(saSource.sin_addr),MAX_ADDR_LEN);
114         saDest.sin_addr.s_addr = pIpheader->ip_dst;//目的地址
115         strncpy(szDestIP,inet_ntoa(saDest.sin_addr),MAX_ADDR_LEN);
116         lentcp = (ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct tcpheader)));
117         lenudp = (ntohs(pIpheader->ip_len)-(sizeof(struct ipheader)+sizeof(struct udphdr)));
118 
119         if((pIpheader->ip_p)==IPPROTO_TCP&&lentcp!=0){
120             printf("**************************\n");
121             pCount++;
122             //datatcp指向数据部分,跳过了前面的ip首部和tcp首部
123             datatcp =(unsigned char *) RecvBuf+sizeof(struct ipheader)+sizeof(struct tcpheader);
124             printf("TCP\n");
125             printf("源IP地址:%s:%d\n",szSourceIP,ntohs(pTcpheader->sport));
126             printf("目的IP地址:%s:%d\n",szDestIP,ntohs(pTcpheader->dport));
127             printf("TCP数据包地址:%x\n",datatcp);
128             printf("IP首部长度:%d\n",4*(pIpheader->ip_h1));
129             printf("IP包总长度:%d\n",ntohs(pIpheader->ip_len));
130             printf("char packet %d [%d]=\n\"\n",pCount,lentcp);
131 
132             for(int i =0;i<lentcp;i++){
133                  if(i%10==0&&i!=0)
134                     printf("\"\n\"");
135                 printf("\\x%.2x",*(datatcp+i));
136             }
137             printf("\";\n\n");  //最后的引号 并且换行
138             //输出内容
139             printf("%s",datatcp);
140             printf("\n\n************************************\n");
141         }
142         if(pIpheader->ip_p==IPPROTO_UDP&&lentcp!=0){
143             pCount++;
144             dataudp=(unsigned char *)RecvBuf+sizeof(struct ipheader)+sizeof(struct udphdr);
145             printf("-UDP-\n");
146             printf("源IP地址:%s:%d\n",szSourceIP,ntohs(pUdpheader->sport));
147             printf("目的IP地址:%s:%d\n",szDestIP,ntohs(pUdpheader->dport));
148             printf("UDP数据报地址:%x\n",datatcp);
149             printf("IP首部长度:%d\n",4*(pIpheader->ip_h1));
150             printf("IP包总长度:%d\n",ntohs(pIpheader->ip_len));
151             printf("UDP长度:%d\n",ntohs(pUdpheader->len));
152             printf("这是第%d个包[%d]=\n\"",pCount,lenudp);
153             for(int i=0;i<lenudp;i++){
154                 if(i%10==0&&i!=0)
155                     printf("\"\n\"");
156                 printf("\\x%.2x",*(dataudp+i));
157             }
158             printf("\";\n\n");
159             //输出内容
160             printf("数据内容是:\n%s",dataudp);
161             printf("\n\n************************************\n");
162         }
163         getchar();
164     }
165 }

这个就是移动指针就可以得到你要的东西了。