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 }