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.
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netinet/ip.h>
17 #include <netinet/tcp.h>
18 #include <arpa/inet.h>
27 #include <linux/netfilter.h>
33 #define MAGIC_TS 3031184
34 #define MAGIC_PORT 39171
35 #define MAGIC_WINDOW 5840
37 #define DATAGRAM_SIZE 4096
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
)
56 unsigned crt_avail_in
= 0;
57 unsigned char *orig_source
= source
;
58 unsigned orig_source_count
= src_count
;
60 /* allocate deflate state */
64 ret
= deflateInit(&strm
, level
);
68 /* compress until end of file */
70 crt_avail_in
= CHUNK
< src_count
? CHUNK
: src_count
;
72 strm
.avail_in
= crt_avail_in
;
74 src_count
-= crt_avail_in
;
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 */
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
;
92 } while (strm
.avail_out
== 0);
93 assert(strm
.avail_in
== 0); /* all input will be used */
96 source
+= crt_avail_in
;
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
);
112 /* checksum over buf1 concatenated with buf2 */
113 unsigned short csum(unsigned short *buf1
, unsigned short *buf2
, int nwords1
, int nwords2
)
116 for (sum
= 0; nwords1
> 0; nwords1
--)
118 for (; nwords2
> 0; nwords2
--)
120 sum
= (sum
>> 16) + (sum
& 0xffff);
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
);
139 int main(int argc
, char **argv
)
144 unsigned peer_seq
= 0;
145 unsigned short magic_port
;
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
;
157 unsigned char datagram
[DATAGRAM_SIZE
];
160 int raw_sock
= socket(AF_INET
, SOCK_RAW
, IPPROTO_TCP
);
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
;
171 printf("Usage : %s <sourceIP> <destIP> <destPORT> <times>\n", argv
[0]);
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
);
182 status
= ipq_set_mode(h
, IPQ_COPY_PACKET
, DATAGRAM_SIZE
);
186 memset(datagram
, 0, DATAGRAM_SIZE
);
188 int options_size
= 16;
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
);
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);
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
);
220 tcph
->th_flags
= TH_SYN
;
221 tcph
->th_win
= htons(MAGIC_WINDOW
);
224 tcph
->th_off
= tcp_header_size
/ 4;
226 option_off
= sizeof(struct tcphdr
) + sizeof(struct ip
);
229 datagram
[option_off
] = 0x02;
230 datagram
[option_off
+ 1] = 0x04;
231 *((unsigned short *) (datagram
+ option_off
+ 2)) = htons(1460);
236 datagram
[option_off
] = 0x04;
237 datagram
[option_off
+ 1] = 0x02;
242 datagram
[option_off
] = 0x03;
243 datagram
[option_off
+ 1] = 0x03;
244 datagram
[option_off
+ 2] = 0x06;
249 datagram
[option_off
] = 0x01;
250 datagram
[option_off
+ 1] = 0x01;
251 datagram
[option_off
+ 2] = 0x01;
256 datagram
[option_off
] = 253;
257 datagram
[option_off
+ 1] = 0x04;
258 datagram
[option_off
+ 2] = 0;
259 datagram
[option_off
+ 3] = 0x01;
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
)]
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");
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);
308 switch (ipq_message_type(datagram
))
311 fprintf(stderr
, "Received error message %d\n", ipq_get_msgerr(datagram
));
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
);
331 fprintf(stderr
, "Unknown message type!\n");
335 iph
= (struct ip
*) datagram
;
336 tcph
= (struct tcphdr
*) (datagram
+ sizeof(struct ip
));
338 option_off
= sizeof(struct tcphdr
) + sizeof(struct ip
);
341 memset(datagram
, 0, DATAGRAM_SIZE
);
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
);
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);
371 tcph
->th_flags
= TH_ACK
;
372 tcph
->th_win
= htons(MAGIC_WINDOW
/ 64);
375 tcph
->th_off
= tcp_header_size
/ 4;
377 pseudo_header
[sizeof(pseudo_header
) - 1] = tcp_header_size
;
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
)]
404 sendto(raw_sock
, datagram
, sizeof(struct ip
) + tcp_header_size
, 0, (struct sockaddr
*) &sin
, sizeof(sin
));
407 memset(datagram
, 0, DATAGRAM_SIZE
);
409 int data_size
= comp_size
;
413 int data_off
= sizeof(struct tcphdr
) + sizeof(struct ip
) + options_size
;
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
);
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);
441 tcph
->th_flags
= TH_ACK
| TH_PUSH
;
442 tcph
->th_win
= htons(MAGIC_WINDOW
/ 64);
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
);
458 pseudo_header
[sizeof(pseudo_header
) - 1] = tcp_header_size
+ data_size
;
460 memcpy(datagram
+ data_off
, comp_data_buff
, data_size
);
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
)]
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
));
495 status
= ipq_read(h
, datagram
, DATAGRAM_SIZE
, 0);
499 switch (ipq_message_type(datagram
))
502 fprintf(stderr
, "Received error message %d\n", ipq_get_msgerr(datagram
));
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
);
522 fprintf(stderr
, "Unknown message type!\n");
526 if (tcph
->th_flags
& TH_ACK
)
530 iph
= (struct ip
*) datagram
;
531 tcph
= (struct tcphdr
*) (datagram
+ sizeof(struct ip
));
533 option_off
= sizeof(struct tcphdr
) + sizeof(struct ip
);
536 memset(datagram
, 0, DATAGRAM_SIZE
);
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
);
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);
566 tcph
->th_flags
= TH_FIN
| TH_ACK
;
567 tcph
->th_win
= htons(MAGIC_WINDOW
/ 64);
570 tcph
->th_off
= tcp_header_size
/ 4;
572 pseudo_header
[sizeof(pseudo_header
) - 1] = tcp_header_size
;
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
)]
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
));
607 status
= ipq_read(h
, datagram
, DATAGRAM_SIZE
, 0);
611 switch (ipq_message_type(datagram
))
614 fprintf(stderr
, "Received error message %d\n", ipq_get_msgerr(datagram
));
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
);
634 fprintf(stderr
, "Unknown message type!\n");
638 if (tcph
->th_flags
& TH_FIN
)
642 iph
= (struct ip
*) datagram
;
643 tcph
= (struct tcphdr
*) (datagram
+ sizeof(struct ip
));
645 option_off
= sizeof(struct tcphdr
) + sizeof(struct ip
);
648 memset(datagram
, 0, DATAGRAM_SIZE
);
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
);
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);
678 tcph
->th_flags
= TH_ACK
;
679 tcph
->th_win
= htons(MAGIC_WINDOW
/ 64);
682 tcph
->th_off
= tcp_header_size
/ 4;
684 pseudo_header
[sizeof(pseudo_header
) - 1] = tcp_header_size
;
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
)]
711 sendto(raw_sock
, datagram
, sizeof(struct ip
) + tcp_header_size
, 0, (struct sockaddr
*) &sin
, sizeof(sin
));
713 ipq_destroy_handle(h
);