点击
#include#include #include //memcpy #include #include #include #include #include //MAC #include //IP #include //UDP #if 1 //---------------发送UDP-------------// typedef struct{ //伪UDP的首部数据类型 u_int32_t saddr; u_int32_t daddr; u_int8_t flag; u_int8_t type; u_int16_t len; }FALSE_HEAD; //数据包校验计算 //接收传递的数据地址、长度 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)); //-----------------------------【-明确发送对象--】-----------------------// //网卡结构体 struct ifreq ethreq; strncpy(ethreq.ifr_name,"eth0",IFNAMSIZ);//指定网卡名字eth0 if(ioctl(sockfd, SIOCGIFINDEX, ðreq)==-1){ //获得eth0的接口类型 return 0; } //发送接口的结构体 struct sockaddr_ll sll; bzero(&sll,sizeof(sll)); sll.sll_ifindex = ethreq.ifr_ifindex;//将网卡的接口类型赋值给发送接口 unsigned char udp_buf[1500]="";//一个完整的MTU数据包最大1500 unsigned char buf[1024] = ""; fgets(buf,sizeof(buf),stdin);//获得键盘输入 buf[strlen(buf) - 1]=' '; int date_len = strlen(buf) + strlen(buf) % 2;//整数补齐偶数位,strlen(buf)%2:偶数+0,奇数+1 printf("%d---%sn",date_len, buf); //-----开始组包------// //----------------------组udp数据包的MAC----------------------------// struct ether_header *mac_head=(struct ether_header *)udp_buf; //先给定MAC地址 unsigned char dst_mac[8]={0x2C,0x4D,0x54,0x57,0x04,0x7F};//主机MAC--目的:串口工具所在地的MAC unsigned char src_mac[8]={0x00,0x0c,0x29,0xfa,0x7c,0x9e};//虚拟机MAC--源MAC memcpy(mac_head->ether_dhost,dst_mac,6); memcpy(mac_head->ether_shost,src_mac,6); //数据类型IP包 mac_head->ether_type=htons(0x0800); //MAC的数据是IP包 //组udp数据包的IP struct iphdr *ip_head=(struct iphdr *)(udp_buf+14);//跳过MAC包的首部 ip_head->version = 4; ip_head->ihl =5; ip_head->tos =0; ip_head->tot_len =htons(20+8+date_len);//当前数据包长度,IP首部长度+IP数据,IP数据包含【UDP首部长度+键盘输入(UDP数据)】 ip_head->id =htons(0); ip_head->frag_off=htons(0); ip_head->ttl=128; ip_head->protocol=17;//UDP协议类型 ip_head->check=htons(0);//暂时未知,赋值0 ip_head->saddr=inet_addr("10.36.145.56");//IP包中需要给定源IP ip_head->daddr=inet_addr("10.36.145.91"); //当填充完ip所有数据重新计算校验和 //校验IP包首部长度以内的成员,不带IP的数据 //IP的数据是UDP ip_head->check=checksum((unsigned short *)(udp_buf+14), 20); //------------------------------组udp数据包的UDP-----------------------------// //先对官方给定的UDP首部,赋值 struct udphdr *udp_head=(struct udphdr *)(udp_buf+14+20);//跳过MAC+IP的首部 udp_head->source=htons(8000);//源(虚拟机)端口 udp_head->dest=htons(8000);//目的(串口工具)端口 udp_head->len=htons(8+date_len);//UDP包长度 udp_head->check=htons(0);//暂时未知,赋值0 //对伪UDP首部,人为设定一个结构体 //内涵5个成员 //udp检验和校验的是udp伪头部+其余内容,其余内容包含:(UDP首部+数据) //当填充完UDP所有数据重新计算检验和 unsigned char false_buf[1056] = ""; FALSE_HEAD *false_head = ( FALSE_HEAD *)false_buf; false_head->saddr = inet_addr("10.36.145.56"); false_head->daddr = inet_addr("10.36.145.91"); false_head->flag = 0; false_head->type = 17; false_head->len = htons(8 + date_len);//UDP首部长度+键盘输入(UDP数据) //指针+,和数组名+不一样 //将上面赋值过的UDP首部,拷贝给一个新整体中的UDP首部(新的整体包含【伪首部+UDP首部+数据】) //新的UDP首部是没有数据的,拷贝一下 memcpy(false_buf+12,udp_head,8);//false_buf+ memcpy(false_buf+12+8,buf,date_len); //UDP校验,校验全部,发送伪首部+UDP首部+数据 udp_head->check=checksum((unsigned short *)false_buf,12+8+date_len); //组udp数据包的UDP数据部分 memcpy(udp_buf+14+20+8,buf,date_len); //-----------------------发送数据------------------------------// //---发送MAC首部长度+IP首部长度+UDP首部长度+UDP数据----// int send_len=sendto(sockfd, udp_buf, 14+20+8+date_len, 0, (struct sockaddr *)&sll,sizeof(sll)); printf("send_len=%dn",send_len); return 0; } #endif



