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 }