原始套接字-自定义IP首部和TCP首部
1 /* ===================================================================================== 2 * 3 * Filename: raw.c 4 * Description: 使用原始套接字发送TCP协议,并外带自己的数据。 5 * 6 * ====================================================================================*/ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <sys/socket.h> 11 #include <netinet/in.h> 12 #include <netinet/ip.h> 13 #include <netinet/tcp.h> 14 #include <arpa/inet.h> 15 #define DATA "hello" 16 #define PACKET_SIZE sizeof(struct iphdr) + sizeof(struct tcphdr) + sizeof(DATA) 17 18 /*--------------------------------------------------------- 19 Function Name : check_sum() 20 Descrypthon : 校验和计算,摘自UNP源码 21 ------------------------------------------------------------*/ 22 unsigned short check_sum(unsigned short *addr, int len) 23 { 24 int nleft = len; 25 int sum = 0; 26 unsigned short *w = addr; 27 short answer = 0; 28 while (nleft > 1) 29 { 30 sum += *w++; 31 nleft -=2; 32 } 33 if (nleft == 1) 34 { 35 *(unsigned char *)(&answer) = *(unsigned char *)w; 36 sum += answer; 37 } 38 sum = (sum >> 16) + (sum & 0xffff); 39 sum += (sum >> 16); 40 answer = ~sum; 41 return answer; 42 } 43 44 /*--------------------------------------------------------- 45 Function Name : init_socket() 46 Descrypthon : 初始化socket,使用原始套接字 47 parameter : P1 一个待初始化的原始套接字,P2 待初始化的目标地址结构,P3 目标地址,P4 目标端口 48 return : 返回一个原始套接字,在函数体内将目标地址结构进行初始 49 ------------------------------------------------------------*/ 50 int init_socket(int sockfd, struct sockaddr_in *target,const char *dst_addr, const char *dst_port) 51 { 52 const int flag = 1; 53 //目标协议簇 54 target->sin_family = AF_INET; 55 //目标端口 56 target->sin_port = htons(atoi(dst_port)); 57 58 //将dst_addr中的ASCII-IP地址更新到target->sin_addr结构中 59 if (inet_aton(dst_addr, &target->sin_addr) == 0) 60 { 61 perror("inet_aton fail\n"); 62 exit(-1); 63 } 64 //初始化原始套接字 65 if((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) 66 { 67 perror("error"); 68 exit(-1); 69 } 70 //设置套接字××× 71 if (setsockopt(sockfd,IPPROTO_IP, IP_HDRINCL, &flag, sizeof(flag)) < 0) 72 { 73 perror("setsockopt fail \n"); 74 exit(-1); 75 } 76 return sockfd; 77 } 78 79 /*--------------------------------------------------------------- 80 Function Name : buile_iphdr() 81 Descrypthon : 构建IP头部数据, 源地址使用伪随机地址 82 -----------------------------------------------------------------*/ 83 void buile_iphdr(struct sockaddr_in *target, char *buffer) 84 { 85 struct iphdr *ip = (struct iphdr *)(buffer); 86 ip->version = 4;//版本 87 ip->ihl = 5;//首部长度 5*4 = 20 88 ip->tos = 0;//8位服务类型 89 ip->tot_len = htons(PACKET_SIZE);//16位总长度 90 ip->id = 0;//16位标识符 91 ip->frag_off = 0;//3位标志 92 ip->ttl = 255;//生存时间 93 ip->protocol = IPPROTO_TCP;//协议 94 ip->check = check_sum((unsigned short *)ip, sizeof(struct iphdr) + sizeof(DATA));//16位首部校验和 95 ip->saddr = random();//源ip地址 96 ip->daddr = target->sin_addr.s_addr;//目标ip地址 97 } 98 99 /*--------------------------------------------------------------- 100 Function Name : buile_tcphdr() 101 Descrypthon : 构建TCP头部信息,并加入一些自己的数据,然后进行 102 校验计算。 103 -----------------------------------------------------------------*/ 104 void buile_tcphdr(struct sockaddr_in *target, const char *src_port, char *buffer) 105 { 106 struct tcphdr *tcp = (struct tcphdr *)(buffer); 107 tcp->source = htons(atoi(src_port));//16位源端口号 108 tcp->dest = target->sin_port;//16位目的端口号 109 tcp->seq = random();//32位序号 110 tcp->doff = 5;// 111 tcp->syn = 1;//同步序号 112 buffer += sizeof(struct tcphdr); 113 tcp->check = check_sum((unsigned short *)tcp, sizeof(struct tcphdr) + sizeof(DATA));//16位检验和 114 memcpy(buffer, DATA, sizeof(DATA));//将DATA中的数据拷贝sizeof(DATA)字节到buffer所指的地址中 115 } 116 int main(int argc, const char *argv[]) 117 { 118 char *buffer; 119 char *buffer_head = NULL; 120 int sockfd = 0; 121 struct sockaddr_in *target; 122 if (argc != 4) 123 { 124 printf("usage: destination addresss, destination port, source port \n"); 125 exit(-1); 126 } 127 const char *dst_addr = argv[1]; 128 const char *dst_port = argv[2]; 129 const char *src_port = argv[3]; 130 131 target = calloc(sizeof(struct sockaddr_in),1); 132 //calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。 133 buffer = calloc(PACKET_SIZE, 1); 134 buffer_head = buffer; 135 136 //初始化套接字 137 sockfd = init_socket(sockfd, target, dst_addr, dst_port); 138 //创建IP首部 139 buile_iphdr(target, buffer); 140 buffer += sizeof(struct iphdr);//指针下移 141 //创建TCP首部 142 buile_tcphdr(target, src_port, buffer); 143 //发送 144 sendto(sockfd, buffer_head, PACKET_SIZE, 0,(struct sockaddr *)target, sizeof(struct sockaddr_in)); 145 146 //下两行是对calloc申请的释放 147 free(buffer_head); 148 free(target); 149 return 0; 150 }