UDP校验方式:
- 在对UDP校验的时候需要在UDP报文之间加上伪头部。
- IP校验的时候不需要伪头部
注意:伪头部中的源ip、目的IP必须和 IP报文中源ip、目的IP 一致。
#include#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef struct{ u_int32_t saddr;//源IP u_int32_t daddr;//目的IP u_int8_t flag;//标记(0) u_int8_t protocol;//udp协议 17 u_int16_t len;//长度 }FAKEHDR; //校验函数,通信两边的校验方法需要保持一致 unsigned short checksum(unsigned short *buf, int len) { int nword = len/2; unsigned long sum; if(len%2 == 1) nword++; for(sum = 0; nword > 0; nword--) { sum += *buf; buf++; } sum = (sum>>16) + (sum&0xffff); sum += (sum>>16); return ~sum; } int main(int argc, char *argv[]) { int sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); if(sockfd < 0) { perror("socket error"); return -1; } struct ifreq ethreq; strncpy(ethreq.ifr_ifrn.ifrn_name,"ens33",IFNAMSIZ); if(ioctl(sockfd,SIOCGIFINDEX,ðreq) == -1) { perror("socket error"); close(sockfd); return -2; } cout<< "请输入要发送的内容:" << endl; char data[128] = ""; fgets(data,sizeof(data),stdin); data[strlen(data) - 1 ] = 0;//去掉回车 int dataLen = strlen(data); //udp需要数据长度为偶数个字节,不是偶数补0 if(dataLen %2 != 0) dataLen++; struct sockaddr_ll sll; bzero(&sll,sizeof(sll)); sll.sll_ifindex = ethreq.ifr_ifindex; unsigned char dstMac[6] = {0x00,0xFF,0xB4,0x31,0xD1,0xE2}; unsigned char srcMac[6] = {0x00,0x0c,29,0xee,0x18,0x53}; unsigned char dstIp[4] = {192,168,123,249}; unsigned char srcIp[4] = {192,168,243,128}; unsigned char msg[1024] = ""; //1.ether struct ether_header *macHeader = (struct ether_header*)msg; memcpy(macHeader->ether_dhost,dstMac,6); memcpy(macHeader->ether_shost,srcMac,6); macHeader->ether_type = htons(0x0800); //2.IP struct iphdr *ipHeader = (struct iphdr*)(msg+14); ipHeader->version = 4;//ipv4版本 ipHeader->ihl = 5;//IP头部长度 单位4B 所以赋值5其实就是5*4=20B ipHeader->tos = 0;//服务类型 ipHeader->tot_len = htons(20+8+dataLen);//总长度=IP首部长度+UDP首部长度+IP数据长度 ipHeader->id = htons(0);//标识 ipHeader->frag_off = htons(0);//标志 + 片偏移 ipHeader->ttl = 128;//64或128都可以 生命周期 ipHeader->protocol = 17;//协议类型:UDP-17;TCP-6 memcpy(&ipHeader->daddr,dstIp,4); memcpy(&ipHeader->saddr,srcIp,4); //ip报文头部校验 ipHeader->check = checksum((unsigned short *)ipHeader,20); //3.UDP struct udphdr *udpHeader = (struct udphdr*)(msg+14+20); udpHeader->source = htons(8000);//源端口 udpHeader->dest = htons(9000);//目的端口 udpHeader->len = htons(8+dataLen);//udp总长度=udp报文头+数据长度 //UDP校验 unsigned char fakeHdr[256] = ""; FAKEHDR* fakeHeader = (FAKEHDR*)fakeHdr; memcpy(&fakeHeader->saddr,srcIp,4); memcpy(&fakeHeader->daddr,dstIp,4); fakeHeader->protocol = 17; fakeHeader->flag = 0; fakeHeader->len = htons(8+dataLen);//udp的总长度 //将msg中的udp头部信息以及data数据 拷贝到伪头部后方 memcpy(fakeHdr+12,udpHeader,8+dataLen); //校验udp: 伪头部+udp头部+data部分 udpHeader->check = checksum((unsigned short *)fakeHdr,12+8+dataLen); //4.要发送的数据 memcpy(msg+14+20+8,data,dataLen); sendto(sockfd,msg,14+20+8+dataLen,0,(struct sockaddr*)&sll,sizeof(sll)); close(sockfd); return 0; }



