-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathraw_socket.c
More file actions
197 lines (174 loc) · 6.27 KB
/
raw_socket.c
File metadata and controls
197 lines (174 loc) · 6.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/tcp.h> /* TCP Header */
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <netint/ip.h>
#define DEBUG 0
struct sockaddr_in *clientaddr = NULL;
int raw_socket;
int SERVPORT = 50000;
int DESTPORT = 50001;
/* structure to calculate TCP checksum
* which do not change from the TCP layer and hence
* are used as a part of the TCP checksum */
struct pseudo_iphdr
{
unsigned int source_ip_addr;
unsigned int dest_ip_addr;
unsigned char fixed;
unsigned char protocol;
unsigned short tcp_len;
};
/* checksum code to calculate TCP checksum
* Code taken from Unix network programming – Richard stevens*/
unsigned short in_cksum(uint16_t *addr, int len)
{
int nleft = len;
unsigned int sum = 0;
unsigned short *w = addr;
unsigned short answer = 0;
/* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
{
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = (unsigned short)~sum; /* truncate to 16 bits */
return (answer);
}
/* Interrupt_handler – so that CTRL + C can be used to
* exit the program */
void interrupt_handler(int signum)
{
close(raw_socket);
free(clientaddr);
exit(0);
}
#if DEBUG
/* print the IP and TCP headers */
void dumpmsg(unsigned char *recvbuffer, int length)
{
int count_per_length = 40, i = 0;
for (i = 0; i < count_per_length; i++)
{
printf("%02x ", recvbuffer[i]);
}
printf(“\n”);
}
#endif
void main()
{
socklen_t length, num_of_bytes;
char buffer[1024] = {0};
unsigned char recvbuffer[1024] = {0};
char *string = "Hello client\n";
struct tcphdr *tcp_hdr = NULL;
char *string_data = NULL;
char *recv_string_data = NULL;
char *csum_buffer = NULL;
struct pseudo_iphdr csum_hdr;
signal(SIGINT, interrupt_handler);
signal(SIGTERM, interrupt_handler);
if (0 > (raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)))
{
printf("Unable to create a socket\n");
exit(0);
}
/* Part 2 – create the server connection – fill the structure*/
clientaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
if (clientaddr == NULL)
{
printf("Unable to allocate memory\n");
goto end;
}
clientaddr->sin_family = AF_INET;
clientaddr->sin_port = htons(DESTPORT);
clientaddr->sin_addr.s_addr = inet_addr("127.0.0.1");
memset(buffer, 0, sizeof(buffer));
/* copy the data after the TCP header */
string_data = (char *)(buffer + sizeof(struct tcphdr));
strncpy(string_data, string, strlen(string));
/* Modify some parameters to send to client in TCP hdr
* code will perform a syn re-transmit to the receive side */
tcp_hdr = (struct tcphdr *)buffer;
tcp_hdr->source = htons(SERVPORT);
tcp_hdr->dest = htons(DESTPORT);
tcp_hdr->ack_seq = 0x0; /* seq number */
tcp_hdr->doff = 5; /* data_offset * 4 is TCP header size */
tcp_hdr->syn = 1; /* SYN flag */
tcp_hdr->window = htons(200); /* Window size scaling*/
/* calculate the TCP checksum – based on pseudo IP header + TCP HDR +
* TCP data. create a buffer and calculate CSUM*/
csum_buffer = (char *)calloc((sizeof(struct pseudo_iphdr) + sizeof(struct tcphdr) + strlen(string_data)), sizeof(char));
if (csum_buffer == NULL)
{
printf("Unable to allocate csum buffer\n");
goto end1;
}
csum_hdr.source_ip_addr = inet_addr("127.0.0.1");
csum_hdr.dest_ip_addr = inet_addr("127.0.0.1");
csum_hdr.fixed = 0;
csum_hdr.protocol = IPPROTO_TCP; /* TCP protocol */
csum_hdr.tcp_len = htons(sizeof(struct tcphdr) + strlen(string_data) + 1);
memcpy(csum_buffer, (char *)&csum_hdr, sizeof(struct pseudo_iphdr));
memcpy(csum_buffer + sizeof(struct pseudo_iphdr), buffer, (sizeof(struct tcphdr) + strlen(string_data) + 1));
tcp_hdr->check = (in_cksum((unsigned short *)csum_buffer,
(sizeof(struct pseudo_iphdr) + sizeof(struct tcphdr) + strlen(string_data) + 1)));
printf("checksum is %x", tcp_hdr->check);
/* since we are re-sending the same packet over and over again
* free the csum buffer here */
free(csum_buffer);
while (1)
{
num_of_bytes = sendto(raw_socket, buffer, (sizeof(struct tcphdr) + strlen(string_data) + 1), 0,
(struct sockaddr *)clientaddr, sizeof(struct sockaddr_in));
if (num_of_bytes == -1)
{
printf("unable to send Message\n");
goto end1;
}
/* sleep is placed so that the recvfrom API does not exit with no data available
* generally do not use sleep in code if possible */
sleep(1);
memset(recvbuffer, 0, sizeof(recvbuffer));
num_of_bytes = recvfrom(raw_socket, recvbuffer, (sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(string_data) + 1), 0,
(struct sockaddr *)clientaddr, &length);
if (num_of_bytes == -1)
{
printf("unable to recv Message\n");
goto end1;
}
tcp_hdr = (struct tcphdr *)(recvbuffer + sizeof(struct iphdr));
recv_string_data = (char *)(recvbuffer + sizeof(struct iphdr) + sizeof(struct tcphdr));
#if DEBUG
dumpmsg((unsigned char *)&recvbuffer, (sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(string_data) + 1));
#endif
if (SERVPORT == ntohs(tcp_hdr->source))
{
printf("tcp source is %d, tcp destination is %d, tcp window is %d\n", ntohs(tcp_hdr->source),
ntohs(tcp_hdr->dest), ntohs(tcp_hdr->window));
printf("data is %s\n", recv_string_data);
}
}
end1:
free(clientaddr);
end:
close(raw_socket);
return;
}