Simple compressed conversation generator.
[tcp-comp-utils.git] / pack-gen.c
blobd84ff35a48503f87970110706e0c2a348853e8e3
1 /*
2 * Pack-gen Simple one-pack TCP conversation generator.
4 * Author: Alex Suhan <alex.suhan@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #define __USE_BSD
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netinet/ip.h>
16 #define __FAVOR_BSD
17 #include <netinet/tcp.h>
18 #include <arpa/inet.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <time.h>
24 #include <assert.h>
26 // libipq stuff
27 #include <linux/netfilter.h>
28 #include <libipq.h>
30 // zlib stuff
31 #include <zlib.h>
33 #define MAGIC_TS 3031184
34 #define MAGIC_PORT 39171
35 #define MAGIC_WINDOW 5840
37 #define DATAGRAM_SIZE 4096
39 #define CHUNK 16384
41 unsigned char uncomp_data_buff[] = "1111111111111111111111111111111\n";
42 unsigned char comp_data_buff[DATAGRAM_SIZE];
44 /* Compress from 'source' repeated 'times' times to 'dest' until EOF on source.
45 def_repeat() returns Z_OK on success, Z_MEM_ERROR if memory could not be
46 allocated for processing, Z_STREAM_ERROR if an invalid compression
47 level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
48 version of the library linked do not match, or Z_ERRNO if there is
49 an error reading or writing the files. */
50 int def_repeat(unsigned char *source, size_t src_count, unsigned char *dest, unsigned *dest_off, unsigned times, int level)
52 int ret, flush;
53 unsigned have;
54 z_stream strm;
55 *dest_off = 0;
56 unsigned crt_avail_in = 0;
57 unsigned char *orig_source = source;
58 unsigned orig_source_count = src_count;
60 /* allocate deflate state */
61 strm.zalloc = Z_NULL;
62 strm.zfree = Z_NULL;
63 strm.opaque = Z_NULL;
64 ret = deflateInit(&strm, level);
65 if (ret != Z_OK)
66 return ret;
68 /* compress until end of file */
69 do {
70 crt_avail_in = CHUNK < src_count ? CHUNK : src_count;
72 strm.avail_in = crt_avail_in;
74 src_count -= crt_avail_in;
76 if (src_count == 0)
77 times--;
79 flush = (times == 1 && src_count == 0) ? Z_FINISH : Z_NO_FLUSH;
81 strm.next_in = source;
83 /* run deflate() on input until output buffer not full, finish
84 compression if all of source has been read in */
85 do {
86 strm.avail_out = CHUNK;
87 strm.next_out = dest + *dest_off;
88 ret = deflate(&strm, flush); /* no bad return value */
89 assert(ret != Z_STREAM_ERROR); /* state not clobbered */
90 have = CHUNK - strm.avail_out;
91 *dest_off += have;
92 } while (strm.avail_out == 0);
93 assert(strm.avail_in == 0); /* all input will be used */
95 if (src_count > 0)
96 source += crt_avail_in;
97 else if (times > 1)
99 src_count = orig_source_count;
100 source = orig_source;
103 /* done when last data in file processed */
104 } while (flush != Z_FINISH);
105 assert(ret == Z_STREAM_END); /* stream will be complete */
107 /* clean up and return */
108 (void)deflateEnd(&strm);
109 return Z_OK;
112 /* checksum over buf1 concatenated with buf2 */
113 unsigned short csum(unsigned short *buf1, unsigned short *buf2, int nwords1, int nwords2)
115 unsigned long sum;
116 for (sum = 0; nwords1 > 0; nwords1--)
117 sum += *buf1++;
118 for (; nwords2 > 0; nwords2--)
119 sum += *buf2++;
120 sum = (sum >> 16) + (sum & 0xffff);
121 sum += (sum >> 16);
122 return ~sum;
125 unsigned char pseudo_header[] =
127 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x06, 0x00, 0x00
132 static void die(struct ipq_handle *h)
134 ipq_perror("passer");
135 ipq_destroy_handle(h);
136 exit(1);
139 int main(int argc, char **argv)
141 unsigned off;
142 unsigned option_off;
143 unsigned seq;
144 unsigned peer_seq = 0;
145 unsigned short magic_port;
146 unsigned comp_size;
147 unsigned times = 1 << atoi(argv[4]);
148 unsigned uncomp_size = (sizeof(uncomp_data_buff) - 1) * times;
150 def_repeat(uncomp_data_buff, sizeof(uncomp_data_buff) - 1, comp_data_buff, &comp_size, 2, Z_DEFAULT_COMPRESSION);
152 // ipq library handle
153 struct ipq_handle *h;
154 int status;
156 // message
157 unsigned char datagram[DATAGRAM_SIZE];
159 // socket
160 int raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
162 // headers
163 struct ip *iph = (struct ip *) datagram;
164 struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof(struct ip));
166 // socket endpoint address
167 struct sockaddr_in sin;
168 sin.sin_family = AF_INET;
170 if(argc < 5) {
171 printf("Usage : %s <sourceIP> <destIP> <destPORT> <times>\n", argv[0]);
172 return -1;
175 sin.sin_port = htons(atoi(argv[3]));
176 sin.sin_addr.s_addr = inet_addr(argv[2]);
178 h = ipq_create_handle(0, NFPROTO_IPV4);
179 if (!h)
180 die(h);
182 status = ipq_set_mode(h, IPQ_COPY_PACKET, DATAGRAM_SIZE);
183 if (status < 0)
184 die(h);
186 memset(datagram, 0, DATAGRAM_SIZE);
188 int options_size = 16;
190 iph->ip_hl = 5;
191 iph->ip_v = 4;
192 iph->ip_tos = 0x10;
193 iph->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + options_size);
194 iph->ip_id = htons(random());
195 iph->ip_off = htons(0 | IP_DF);
196 iph->ip_ttl = 64;
197 iph->ip_p = 6;
198 iph->ip_sum = 0;
199 iph->ip_src.s_addr = inet_addr(argv[1]);
200 iph->ip_dst.s_addr = sin.sin_addr.s_addr;
201 iph->ip_sum = csum((unsigned short *) datagram, NULL, (sizeof(struct ip) + sizeof(struct ip) % 2) / 2, 0);
203 unsigned char *src_bytes = (unsigned char *) (&iph->ip_src.s_addr);
204 unsigned char *dst_bytes = (unsigned char *) (&iph->ip_dst.s_addr);
206 memcpy(pseudo_header, src_bytes, 4);
207 memcpy(pseudo_header + 4, dst_bytes, 4);
209 srand(time(NULL));
210 seq = random();
211 magic_port = 40000 + random() % 5000;
213 unsigned tcp_header_size = sizeof(struct tcphdr) + options_size; // ok, ok, ar trebui rotunjit la multiplu de 4
215 tcph->th_sport = htons(magic_port);
216 tcph->th_dport = htons(atoi(argv[3]));
217 tcph->th_seq = htonl(seq);
218 tcph->th_ack = 0;
219 tcph->th_x2 = 0;
220 tcph->th_flags = TH_SYN;
221 tcph->th_win = htons(MAGIC_WINDOW);
222 tcph->th_sum = 0;
223 tcph->th_urp = 0;
224 tcph->th_off = tcp_header_size / 4;
226 option_off = sizeof(struct tcphdr) + sizeof(struct ip);
228 // MSS
229 datagram[option_off] = 0x02;
230 datagram[option_off + 1] = 0x04;
231 *((unsigned short *) (datagram + option_off + 2)) = htons(1460);
233 option_off += 4;
235 // SACK permitted
236 datagram[option_off] = 0x04;
237 datagram[option_off + 1] = 0x02;
239 option_off += 2;
241 // Window scale
242 datagram[option_off] = 0x03;
243 datagram[option_off + 1] = 0x03;
244 datagram[option_off + 2] = 0x06;
246 option_off += 3;
248 // NOP's
249 datagram[option_off] = 0x01;
250 datagram[option_off + 1] = 0x01;
251 datagram[option_off + 2] = 0x01;
253 option_off += 3;
255 // tcp-comp related
256 datagram[option_off] = 253;
257 datagram[option_off + 1] = 0x04;
258 datagram[option_off + 2] = 0;
259 datagram[option_off + 3] = 0x01;
261 option_off += 4;
263 pseudo_header[sizeof(pseudo_header) - 1] = tcp_header_size;
265 unsigned short check =
266 csum((unsigned short *) pseudo_header, (unsigned short *) (datagram + sizeof(struct ip)),
267 sizeof(pseudo_header) / 2, (tcp_header_size + tcp_header_size % 2) / 2);
269 tcph->th_sum = check;
271 printf("CHECKSUM: %04x\n", check);
273 printf("Sending SYN packet\n");
274 printf("------------------\n");
275 for (off = 0; off < sizeof(struct ip); off += 4)
276 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
277 (unsigned char) datagram[off],
278 (unsigned char) datagram[off + 1],
279 (unsigned char) datagram[off + 2],
280 (unsigned char) datagram[off + 3]
282 for (off = 0; off < tcp_header_size; off += 4)
283 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
284 (unsigned char) datagram[off + sizeof(struct ip)],
285 (unsigned char) datagram[off + 1 + sizeof(struct ip)],
286 (unsigned char) datagram[off + 2 + sizeof(struct ip)],
287 (unsigned char) datagram[off + 3 + sizeof(struct ip)]
289 printf("\n");
291 int one = 1;
292 const int *val = &one;
293 if (setsockopt(raw_sock, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
295 fprintf(stderr, "Can't set socket option\n");
296 return -1;
299 int err =
300 sendto(raw_sock, datagram, sizeof(struct ip) + tcp_header_size, 0, (struct sockaddr *) &sin, sizeof(sin));
302 memset(datagram, 0, sizeof(datagram));
304 status = ipq_read(h, datagram, DATAGRAM_SIZE, 0);
305 if (status < 0)
306 die(h);
308 switch (ipq_message_type(datagram))
310 case NLMSG_ERROR:
311 fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(datagram));
312 break;
313 case IPQM_PACKET:
315 ipq_packet_msg_t *m = ipq_get_packet(datagram);
317 iph = (struct ip *) m->payload;
318 printf("IP header length: %d\n", iph->ip_hl);
319 tcph = (struct tcphdr *) (m->payload + (iph->ip_hl << 2));
320 printf("TCP header length: %d\n", tcph->th_off << 2);
322 peer_seq = ntohl(tcph->th_seq);
323 printf("%u %u\n\n", seq, peer_seq);
325 status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
326 if (status < 0)
327 die(h);
328 break;
330 default:
331 fprintf(stderr, "Unknown message type!\n");
332 break;
335 iph = (struct ip *) datagram;
336 tcph = (struct tcphdr *) (datagram + sizeof(struct ip));
338 option_off = sizeof(struct tcphdr) + sizeof(struct ip);
340 // ACK segment
341 memset(datagram, 0, DATAGRAM_SIZE);
343 options_size = 0;
345 iph->ip_hl = 5;
346 iph->ip_v = 4;
347 iph->ip_tos = 0x10;
348 iph->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + options_size);
349 iph->ip_id = htons(random());
350 iph->ip_off = htons(0 | IP_DF);
351 iph->ip_ttl = 64;
352 iph->ip_p = 6;
353 iph->ip_sum = 0;
354 iph->ip_src.s_addr = inet_addr(argv[1]);
355 iph->ip_dst.s_addr = sin.sin_addr.s_addr;
356 iph->ip_sum = csum((unsigned short *) datagram, NULL, (sizeof(struct ip) + sizeof(struct ip) % 2) / 2, 0);
358 src_bytes = (unsigned char *) (&iph->ip_src.s_addr);
359 dst_bytes = (unsigned char *) (&iph->ip_dst.s_addr);
361 memcpy(pseudo_header, src_bytes, 4);
362 memcpy(pseudo_header + 4, dst_bytes, 4);
364 tcp_header_size = sizeof(struct tcphdr) + options_size;
366 tcph->th_sport = htons(magic_port);
367 tcph->th_dport = htons(atoi(argv[3]));
368 tcph->th_seq = htonl(seq + 1);
369 tcph->th_ack = htonl(peer_seq + 1);
370 tcph->th_x2 = 0;
371 tcph->th_flags = TH_ACK;
372 tcph->th_win = htons(MAGIC_WINDOW / 64);
373 tcph->th_sum = 0;
374 tcph->th_urp = 0;
375 tcph->th_off = tcp_header_size / 4;
377 pseudo_header[sizeof(pseudo_header) - 1] = tcp_header_size;
379 check =
380 csum((unsigned short *) pseudo_header, (unsigned short *) (datagram + sizeof(struct ip)),
381 sizeof(pseudo_header) / 2, (tcp_header_size + tcp_header_size % 2) / 2);
383 tcph->th_sum = check;
385 printf("Sending ACK packet\n");
386 printf("------------------\n");
387 for (off = 0; off < sizeof(struct ip); off += 4)
388 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
389 (unsigned char) datagram[off],
390 (unsigned char) datagram[off + 1],
391 (unsigned char) datagram[off + 2],
392 (unsigned char) datagram[off + 3]
394 for (off = 0; off < tcp_header_size; off += 4)
395 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
396 (unsigned char) datagram[off + sizeof(struct ip)],
397 (unsigned char) datagram[off + 1 + sizeof(struct ip)],
398 (unsigned char) datagram[off + 2 + sizeof(struct ip)],
399 (unsigned char) datagram[off + 3 + sizeof(struct ip)]
401 printf("\n");
403 err =
404 sendto(raw_sock, datagram, sizeof(struct ip) + tcp_header_size, 0, (struct sockaddr *) &sin, sizeof(sin));
406 // data segment
407 memset(datagram, 0, DATAGRAM_SIZE);
409 int data_size = comp_size;
411 options_size = 12;
413 int data_off = sizeof(struct tcphdr) + sizeof(struct ip) + options_size;
415 iph->ip_hl = 5;
416 iph->ip_v = 4;
417 iph->ip_tos = 0x10;
418 iph->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + options_size + data_size);
419 iph->ip_id = htons(random());
420 iph->ip_off = htons(0 | IP_DF);
421 iph->ip_ttl = 64;
422 iph->ip_p = 6;
423 iph->ip_sum = 0;
424 iph->ip_src.s_addr = inet_addr(argv[1]);
425 iph->ip_dst.s_addr = sin.sin_addr.s_addr;
426 iph->ip_sum = csum((unsigned short *) datagram, NULL, (sizeof(struct ip) + sizeof(struct ip) % 2) / 2, 0);
428 src_bytes = (unsigned char *) (&iph->ip_src.s_addr);
429 dst_bytes = (unsigned char *) (&iph->ip_dst.s_addr);
431 memcpy(pseudo_header, src_bytes, 4);
432 memcpy(pseudo_header + 4, dst_bytes, 4);
434 tcp_header_size = sizeof(struct tcphdr) + options_size;
436 tcph->th_sport = htons(magic_port);
437 tcph->th_dport = htons(atoi(argv[3]));
438 tcph->th_seq = htonl(seq + 1);
439 tcph->th_ack = htonl(peer_seq + 1);
440 tcph->th_x2 = 0;
441 tcph->th_flags = TH_ACK | TH_PUSH;
442 tcph->th_win = htons(MAGIC_WINDOW / 64);
443 tcph->th_sum = 0;
444 tcph->th_urp = 0;
445 tcph->th_off = tcp_header_size / 4;
447 option_off = sizeof(struct tcphdr) + sizeof(struct ip);
449 datagram[option_off + 0] = 0x01;
450 datagram[option_off + 1] = 0x01;
451 datagram[option_off + 2] = 0xfd;
452 datagram[option_off + 3] = 0x0a;
453 *((unsigned int *) (datagram + option_off + 4)) = htonl(comp_size);
454 *((unsigned int *) (datagram + option_off + 8)) = htonl(uncomp_size);
456 option_off += 12;
458 pseudo_header[sizeof(pseudo_header) - 1] = tcp_header_size + data_size;
460 memcpy(datagram + data_off, comp_data_buff, data_size);
462 check =
463 csum((unsigned short *) pseudo_header, (unsigned short *) (datagram + sizeof(struct ip)),
464 sizeof(pseudo_header) / 2, ((tcp_header_size + data_size) +(tcp_header_size + data_size) % 2) / 2);
466 tcph->th_sum = check;
468 printf("Sending DATA packet\n");
469 printf("------------------\n");
470 for (off = 0; off < sizeof(struct ip); off += 4)
471 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
472 (unsigned char) datagram[off],
473 (unsigned char) datagram[off + 1],
474 (unsigned char) datagram[off + 2],
475 (unsigned char) datagram[off + 3]
477 for (off = 0; off < tcp_header_size + data_size; off += 4)
478 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
479 (unsigned char) datagram[off + sizeof(struct ip)],
480 (unsigned char) datagram[off + 1 + sizeof(struct ip)],
481 (unsigned char) datagram[off + 2 + sizeof(struct ip)],
482 (unsigned char) datagram[off + 3 + sizeof(struct ip)]
484 printf("\n");
486 err =
487 sendto(raw_sock, datagram, sizeof(struct ip) + tcp_header_size + data_size, 0, (struct sockaddr *) &sin, sizeof(sin));
489 // reading the response
491 memset(datagram, 0, sizeof(datagram));
493 while (1)
495 status = ipq_read(h, datagram, DATAGRAM_SIZE, 0);
496 if (status < 0)
497 die(h);
499 switch (ipq_message_type(datagram))
501 case NLMSG_ERROR:
502 fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(datagram));
503 return -1;
504 case IPQM_PACKET:
506 ipq_packet_msg_t *m = ipq_get_packet(datagram);
508 iph = (struct ip *) m->payload;
509 printf("IP header length: %d\n", iph->ip_hl);
510 tcph = (struct tcphdr *) (m->payload + (iph->ip_hl << 2));
511 printf("TCP header length: %d\n", tcph->th_off << 2);
513 peer_seq = ntohl(tcph->th_seq);
514 printf("%u %u\n\n", seq, peer_seq);
516 status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
517 if (status < 0)
518 die(h);
519 break;
521 default:
522 fprintf(stderr, "Unknown message type!\n");
523 return -1;
526 if (tcph->th_flags & TH_ACK)
527 break;
530 iph = (struct ip *) datagram;
531 tcph = (struct tcphdr *) (datagram + sizeof(struct ip));
533 option_off = sizeof(struct tcphdr) + sizeof(struct ip);
535 // FIN segment
536 memset(datagram, 0, DATAGRAM_SIZE);
538 options_size = 0;
540 iph->ip_hl = 5;
541 iph->ip_v = 4;
542 iph->ip_tos = 0x10;
543 iph->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + options_size);
544 iph->ip_id = htons(random());
545 iph->ip_off = htons(0 | IP_DF);
546 iph->ip_ttl = 64;
547 iph->ip_p = 6;
548 iph->ip_sum = 0;
549 iph->ip_src.s_addr = inet_addr(argv[1]);
550 iph->ip_dst.s_addr = sin.sin_addr.s_addr;
551 iph->ip_sum = csum((unsigned short *) datagram, NULL, (sizeof(struct ip) + sizeof(struct ip) % 2) / 2, 0);
553 src_bytes = (unsigned char *) (&iph->ip_src.s_addr);
554 dst_bytes = (unsigned char *) (&iph->ip_dst.s_addr);
556 memcpy(pseudo_header, src_bytes, 4);
557 memcpy(pseudo_header + 4, dst_bytes, 4);
559 tcp_header_size = sizeof(struct tcphdr) + options_size;
561 tcph->th_sport = htons(magic_port);
562 tcph->th_dport = htons(atoi(argv[3]));
563 tcph->th_seq = htonl(seq + 1 + uncomp_size);
564 tcph->th_ack = htonl(peer_seq + 1);
565 tcph->th_x2 = 0;
566 tcph->th_flags = TH_FIN | TH_ACK;
567 tcph->th_win = htons(MAGIC_WINDOW / 64);
568 tcph->th_sum = 0;
569 tcph->th_urp = 0;
570 tcph->th_off = tcp_header_size / 4;
572 pseudo_header[sizeof(pseudo_header) - 1] = tcp_header_size;
574 check =
575 csum((unsigned short *) pseudo_header, (unsigned short *) (datagram + sizeof(struct ip)),
576 sizeof(pseudo_header) / 2, (tcp_header_size + tcp_header_size % 2) / 2);
578 tcph->th_sum = check;
580 printf("Sending FIN packet\n");
581 printf("------------------\n");
582 for (off = 0; off < sizeof(struct ip); off += 4)
583 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
584 (unsigned char) datagram[off],
585 (unsigned char) datagram[off + 1],
586 (unsigned char) datagram[off + 2],
587 (unsigned char) datagram[off + 3]
589 for (off = 0; off < tcp_header_size; off += 4)
590 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
591 (unsigned char) datagram[off + sizeof(struct ip)],
592 (unsigned char) datagram[off + 1 + sizeof(struct ip)],
593 (unsigned char) datagram[off + 2 + sizeof(struct ip)],
594 (unsigned char) datagram[off + 3 + sizeof(struct ip)]
596 printf("\n");
598 err =
599 sendto(raw_sock, datagram, sizeof(struct ip) + tcp_header_size, 0, (struct sockaddr *) &sin, sizeof(sin));
601 // reading the response
603 memset(datagram, 0, sizeof(datagram));
605 while (1)
607 status = ipq_read(h, datagram, DATAGRAM_SIZE, 0);
608 if (status < 0)
609 die(h);
611 switch (ipq_message_type(datagram))
613 case NLMSG_ERROR:
614 fprintf(stderr, "Received error message %d\n", ipq_get_msgerr(datagram));
615 return -1;
616 case IPQM_PACKET:
618 ipq_packet_msg_t *m = ipq_get_packet(datagram);
620 iph = (struct ip *) m->payload;
621 printf("IP header length: %d\n", iph->ip_hl);
622 tcph = (struct tcphdr *) (m->payload + (iph->ip_hl << 2));
623 printf("TCP header length: %d\n", tcph->th_off << 2);
625 peer_seq = ntohl(tcph->th_seq);
626 printf("%u %u\n\n", seq, peer_seq);
628 status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
629 if (status < 0)
630 die(h);
631 break;
633 default:
634 fprintf(stderr, "Unknown message type!\n");
635 return -1;
638 if (tcph->th_flags & TH_FIN)
639 break;
642 iph = (struct ip *) datagram;
643 tcph = (struct tcphdr *) (datagram + sizeof(struct ip));
645 option_off = sizeof(struct tcphdr) + sizeof(struct ip);
647 // ACK segment
648 memset(datagram, 0, DATAGRAM_SIZE);
650 options_size = 0;
652 iph->ip_hl = 5;
653 iph->ip_v = 4;
654 iph->ip_tos = 0x10;
655 iph->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + options_size);
656 iph->ip_id = htons(random());
657 iph->ip_off = htons(0 | IP_DF);
658 iph->ip_ttl = 64;
659 iph->ip_p = 6;
660 iph->ip_sum = 0;
661 iph->ip_src.s_addr = inet_addr(argv[1]);
662 iph->ip_dst.s_addr = sin.sin_addr.s_addr;
663 iph->ip_sum = csum((unsigned short *) datagram, NULL, (sizeof(struct ip) + sizeof(struct ip) % 2) / 2, 0);
665 src_bytes = (unsigned char *) (&iph->ip_src.s_addr);
666 dst_bytes = (unsigned char *) (&iph->ip_dst.s_addr);
668 memcpy(pseudo_header, src_bytes, 4);
669 memcpy(pseudo_header + 4, dst_bytes, 4);
671 tcp_header_size = sizeof(struct tcphdr) + options_size;
673 tcph->th_sport = htons(magic_port);
674 tcph->th_dport = htons(atoi(argv[3]));
675 tcph->th_seq = htonl(seq + 1 + uncomp_size);
676 tcph->th_ack = htonl(peer_seq + 1);
677 tcph->th_x2 = 0;
678 tcph->th_flags = TH_ACK;
679 tcph->th_win = htons(MAGIC_WINDOW / 64);
680 tcph->th_sum = 0;
681 tcph->th_urp = 0;
682 tcph->th_off = tcp_header_size / 4;
684 pseudo_header[sizeof(pseudo_header) - 1] = tcp_header_size;
686 check =
687 csum((unsigned short *) pseudo_header, (unsigned short *) (datagram + sizeof(struct ip)),
688 sizeof(pseudo_header) / 2, (tcp_header_size + tcp_header_size % 2) / 2);
690 tcph->th_sum = check;
692 printf("Sending ACK packet\n");
693 printf("------------------\n");
694 for (off = 0; off < sizeof(struct ip); off += 4)
695 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
696 (unsigned char) datagram[off],
697 (unsigned char) datagram[off + 1],
698 (unsigned char) datagram[off + 2],
699 (unsigned char) datagram[off + 3]
701 for (off = 0; off < tcp_header_size; off += 4)
702 printf("0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
703 (unsigned char) datagram[off + sizeof(struct ip)],
704 (unsigned char) datagram[off + 1 + sizeof(struct ip)],
705 (unsigned char) datagram[off + 2 + sizeof(struct ip)],
706 (unsigned char) datagram[off + 3 + sizeof(struct ip)]
708 printf("\n");
710 err =
711 sendto(raw_sock, datagram, sizeof(struct ip) + tcp_header_size, 0, (struct sockaddr *) &sin, sizeof(sin));
713 ipq_destroy_handle(h);
715 return err;