您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 冶金工业 > 用C++实现网卡侦听
物联网工程学院实验报告课程名称《计算机网络》实验名称网卡侦听实验日期2012-5-1班级计科姓名学号0304实验报告要求1.实验名称2.实验要求3.实验环境4.实验步骤(写明实验结果)5.实验体会实验2编程实现网卡侦听程序代码:#includestdio.h#includestring.h#includeWinsock2.h#includemstcpip.h#pragmacomment(lib,ws2_32.lib)#defineSTATUS_FAILED0xFFFF//定义异常出错代码#defineMAX_PACK_LEN65535//接收的最大IP报文#defineMAX_ADDR_LEN16//点分十进制地址的最大长度#defineMAX_PROTO_TEXT_LEN16//子协议名称(如TCP)最大长度#defineMAX_PROTO_NUM12//子协议数量#defineMAX_HOSTNAME_LAN255//最大主机名长度#defineCMD_PARAM_HELPtruetypedefstruct_iphdr//定义IP头部{unsignedcharh_lenver;//4位首部长度+4位IP版本号unsignedchartos;//8位服务类型TOSunsignedshorttotal_len;//16位总长度(字节)unsignedshortident;//16位标识unsignedshortfrag_and_flags;//3位标志位unsignedcharttl;//8位生存时间TTLunsignedcharproto;//8位协议(TCP,UDP或其他)unsignedshortchecksum;//16位IP首部校验和unsignedintsourceIP;//32位源IP地址unsignedintdestIP;//32位目的IP地址}IP_HEADER;typedefstruct_tcphdr//定义TCP首部{USHORTth_sport;//16位源端口USHORTth_dport;//16位目的端口unsignedintth_seq;//32位序列号unsignedintth_ack;//32位确认号unsignedcharth_lenres;//4位首部长度/6位保留字unsignedcharth_flag;//6位标志位USHORTth_win;//16位窗口大小USHORTth_sum;//16位校验和USHORTth_urp;//16位紧急数据偏移量}TCP_HEADER;typedefstruct_udphdr//定义UDP首部{unsignedshortuh_sport;//16位源端口unsignedshortuh_dport;//16位目的端口unsignedshortuh_len;//16位长度unsignedshortun_sum;//16位校验和}UDP_HEADER;typedefstruct_icmphdr//定义ICMP首部{BYTEi_type;//8位类型BYTEi_code;//8位代码USHORTi_cksum;//16位校验和USHORTi_id;//识别号(一般用进程号作为识别号)USHORTi_seq;//报文序列号ULONGtimestamp;//时间戳}ICMP_HEADER;typedefstruct_protomap//定义子协议映射表{intProtoNum;charProtoText[MAX_PROTO_TEXT_LEN];}PROTOMAP;PROTOMAPProtoMap[MAX_PROTO_NUM]={//为子协议映射表赋值{IPPROTO_IP,IP},{IPPROTO_ICMP,ICMP},{IPPROTO_IGMP,IGMP},{IPPROTO_GGP,GGP},{IPPROTO_TCP,TCP},{IPPROTO_PUP,PUP},{IPPROTO_UDP,UDP},{IPPROTO_IDP,IDP},{IPPROTO_ND,NP},{IPPROTO_RAW,RAW},{IPPROTO_MAX,MAX},{NULL,}};SOCKETSockRaw;charTcpFlag[6]={'F','S','R','P','A','U'};//定义TCP标志位boolParamTcp=false;//关注TCP报文boolParamUdp=false;//关注UDP报文boolParamIcmp=false;//关注ICMP报文boolParamDecode=true;//对协议进行解码char*strFromIpFilter=NULL;//源IP地址过滤char*strDestIpFilter=NULL;//目的地址过滤intDecodeIpPack(char*,int);//IP解码函数intDecodeTcpPack(char*);//TCP解码函数intDecodeUdpPack(char*);//UDP解码函数intDecodeIcmpPack(char*);//ICMP解码函数voidGetFtp(char*);voidCheckSockError(int,char*);//错误检测函数char*CheckProtocol(int);//协议检测函数voidusage(void);//帮助函数boolGetCmdLine(int,char**);//获取命令行函数voidmain(intargc,char**argv){intiErrorCode;charRecvBuf[MAX_PACK_LEN]={0};//接收缓冲区usage();//调用使用说明if(GetCmdLine(argc,argv)==CMD_PARAM_HELP)exit(0);//初始化SOCKET,判断命令行接收函数WSADATAwsaData;iErrorCode=WSAStartup(MAKEWORD(2,1),&wsaData);CheckSockError(iErrorCode,WSAStartup);//建立Socket。属性必须是AF_INET(Ipv4协议)、//SOCK_RAW(原始套接字,即底层IP)、IPPROTO_IP(自己构造IP头),//否则不能设子SIP_RCVALL(混杂模式)属性SockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_IP);CheckSockError(SockRaw,socket);//获取本机IP地址,并判断socket版本,建立原始套接字charFARname[MAX_HOSTNAME_LAN];iErrorCode=gethostname(name,MAX_HOSTNAME_LAN);//得到本地主机名CheckSockError(iErrorCode,gethostname);structhostentFAR*pHostent;pHostent=(structhostent*)malloc(sizeof(structhostent));pHostent=gethostbyname(name);//获得给定主机名信息SOCKADDR_INsa;sa.sin_family=AF_INET;//设置协议族sa.sin_port=htons(6000);//设置端口memcpy(&sa.sin_addr.S_un.S_addr,pHostent-h_addr_list[0],pHostent-h_length);//绑定本机IP地址。首先获得本机主机名,在根据本地名获得本地IP地址。//注意不能使用参数INADDR_ANY,而是PSOCKADDR。iErrorCode=bind(SockRaw,(PSOCKADDR)&sa,sizeof(sa));//绑定CheckSockError(iErrorCode,bind);//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包DWORDdwBufferLen[10];DWORDdwBufferInLen=1;DWORDdwBytesReturned=0;//设置混杂模式。下面使用WSAIcotl函数给一个SOCK_RAW类型的socket设置//SIO_RCVALL混杂模式,这样该socket就可以收到所以经过本机的数据iErrorCode=WSAIoctl(SockRaw,SIO_RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);CheckSockError(iErrorCode,Ioctl);//侦听IP报文while(1)//1永远为真,不断循环抓包{memset(RecvBuf,0,sizeof(RecvBuf));//强制RecvBuf缓冲区数据为0//获取数据包,开始接收缓冲区数据iErrorCode=recv(SockRaw,RecvBuf,sizeof(RecvBuf),0);CheckSockError(iErrorCode,recv);iErrorCode=DecodeIpPack(RecvBuf,iErrorCode);//开始从缓冲区解码CheckSockError(iErrorCode,Decode);}}//IP解包程序intDecodeIpPack(char*buf,intiBufSize){IP_HEADER*pIpheader;intiProtocol,iTTL;//定义协议,生存时间charszProtocol[MAX_PROTO_TEXT_LEN];charszSourceIP[MAX_ADDR_LEN],szDestIP[MAX_ADDR_LEN];SOCKADDR_INsaSource,saDest;//定义原目标和目的结构pIpheader=(IP_HEADER*)buf;//检测协议是哪种协议//如果命令行指定了IP协议,则校验协议,否则跳出iProtocol=pIpheader-proto;strncpy(szProtocol,CheckProtocol(iProtocol),MAX_PROTO_TEXT_LEN);if((iProtocol==IPPROTO_TCP)&&(!ParamTcp))returntrue;if((iProtocol==IPPROTO_UDP)&&(!ParamUdp))returntrue;if((iProtocol==IPPROTO_ICMP)&&(!ParamIcmp))returntrue;//判断协议类型,返回true//检测源IP,不是命令行所给的IP,则跳出saSource.sin_addr.s_addr=pIpheader-sourceIP;strncpy(szSourceIP,inet_ntoa(saSource.sin_addr),MAX_ADDR_LEN);if(strFromIpFilter)if(strcmp(strFromIpFilter,szSourceIP))returntrue;//检测目标IP,不是命令行所给的IP,则跳出saDest.sin_addr.s_addr=pIpheader-destIP;strncpy(szDestIP,inet_ntoa(saDest.sin_addr),MAX_ADDR_LEN);if(strDestIpFilter)if(strcmp(strDestIpFilter,szDestIP))returntrue;iTTL=pIpheader-ttl;//输出包信息printf(%s,szProtocol);printf(%s-%s,szSourceIP,szDestIP);printf(bytes=%dTTL=%d,iBufSize,iTTL);//计算IP头长度intiIph
本文标题:用C++实现网卡侦听
链接地址:https://www.777doc.com/doc-4375454 .html