trafgen: allow to schedule packets on specific CPUs
[netsniff-ng.git] / src / layer4.c
blobca4d229e3c5eaac3626ae6c77eb635a77de8d63d
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License version 2 as published by the
7 * Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12 * details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html
21 ////////////////////////////////////////////////////////////////////
23 // Layer 4 packet types
24 //
25 // 1. UDP
26 // 2. ICMP
27 // 3. TCP
28 //
29 ////////////////////////////////////////////////////////////////////
31 #include "mz.h"
32 #include "cli.h"
35 #define MZ_UDP_HELP \
36 "| UDP type: Send raw UDP packets.\n" \
37 "|\n" \
38 "| Parameters: \n" \
39 "|\n" \
40 "| sp 0-65535\n" \
41 "| dp 0-65535\n" \
42 "| len 0-65535\n" \
43 "| udp_sum 0-65535\n" \
44 "| payload|p <hex payload>\n" \
45 "|\n" \
46 "| Optionally the port numbers can be specified as ranges, e. g. \"dp=1023-33700\",\n" \
47 "| in which case one packet per port number is sent.\n" \
48 "|\n" \
49 "| Note that the UDP length must include the header length. If you do NOT specify the len\n" \
50 "| parameter (or specify len=0) then Mausezahn will compute the correct length.\n" \
51 "|\n" \
52 "| Note that all IP parameters can be modified (see IP help, i. e. '-t ip \"help\")\n" \
53 "| except that (to avoid confusion) the IP length is 'iplen' and the IP checksum is 'ipsum'.\n" \
54 "| Of course all Ethernet fields can also be accessed.\n" \
55 "|\n" \
56 "\n"
59 #define MZ_ICMP_HELP \
60 "| ICMP type: Send raw ICMP packets.\n" \
61 "|\n" \
62 "| ARGUMENT SYNTAX: [type] <optional parameters> \n" \
63 "| \n" \
64 "| Per default an echo reply is sent (type=0, code=0)\n" \
65 "|\n" \
66 "| TYPE OPTIONAL PARAMETERS\n" \
67 "| =========== ====================================================================\n" \
68 "| Ping: \"ping\" or \"echoreq\" \n" \
69 "| 'id' (0-65535) is the optional identification number\n" \
70 "| 'seq' (0-65535) is the optional packet sequence number\n" \
71 "|\n" \
72 "| Redirect: \"redir, code=0, gw=192.168.1.10, p=aa:bb:cc\"\n" \
73 "| 'gw' (or 'gateway') is the announced gateway, by default your own\n" \
74 "| IP address.\n" \
75 "| 'code' can be:\n" \
76 "| 0 ... redirect datagram for the network\n" \
77 "| 1 ... redirect datagram for the host\n" \
78 "| 2 ... redirect datagram for ToS and network\n" \
79 "| 3 ... redirect datagram for ToS and host\n" \
80 "| 'p' (or 'payload') is the payload of the ICMP packet, tpyically an IP\n" \
81 "| header. Note that - at the moment - you must prepare this payload by\n" \
82 "| yourself.\n" \
83 "|\n" \
84 "| Unreachable \"unreach, code=2\"\n" \
85 "| 'code' can be:\n" \
86 "| 0 ... network unreachable\n" \
87 "| 1 ... host unreachable\n" \
88 "| 2 ... protocol unreachable\n" \
89 "| 3 ... port unreachable\n" \
90 "| 4 ... fragmentation needed but DF-bit is set\n" \
91 "| 5 ... source route failed\n" \
92 "|\n" \
93 "|\n" \
94 "| (other ICMP types will follow)\n" \
95 "|\n" \
96 "\n"
98 #define MZ_ICMP6_HELP \
99 "| ICMPv6 type: Send raw ICMPv6 packets.\n" \
100 "|\n" \
101 "| Parameters Values Explanation \n" \
102 "| ---------- ------------------------------------ -------------------\n" \
103 "| type 0-255 ICMPv6 Type\n" \
104 "| code 0-255 ICMPv6 Code\n" \
105 "| id 0-65535 optional identification number\n" \
106 "| seq 0-65535 optional packet sequence number\n" \
107 "| icmpv6_sum 0-65535 optional checksum\n" \
108 "\n"
110 #define MZ_TCP_HELP \
111 "| TCP type: Send raw TCP packets.\n" \
112 "|\n" \
113 "| Parameters Values Explanation \n" \
114 "| ---------- ------------------------------------ -------------------\n" \
115 "| sp 0-65535 Source Port\n" \
116 "| dp 0-65535 Destination Port\n" \
117 "| flags fin|syn|rst|psh|ack|urg|ecn|cwr\n" \
118 "| s 0-4294967295 Sequence Nr.\n" \
119 "| a 0-4294967295 Acknowledgement Nr.\n" \
120 "| win 0-65535 Window Size\n" \
121 "| urg 0-65535 Urgent Pointer\n" \
122 "| tcp_sum 0-65535 Checksum\n" \
123 "|\n" \
124 "| The port numbers can be specified as ranges, e. g. \"dp=1023-33700\".\n" \
125 "| Multiple flags can be specified such as \"flags=syn|ack|urg\".\n" \
126 "|\n" \
127 "| Also the sequence number can be specified as a range, for example:\n" \
128 "|\n" \
129 "| s=10000-50000 ... send 40000 packets with SQNRs in that range. If the second\n" \
130 "| value is lower than the first then it is assumed that the\n" \
131 "| SQNRs should 'wrap around'.\n" \
132 "| ds=30000 ........ use this increment within a SQNR-range.\n" \
133 "|\n" \
134 "| Note that all IP parameters can be modified (see IP help, i. e. '-t ip \"help\")\n" \
135 "| except that (to avoid confusion) the IP length is 'iplen' and the IP checksum is 'ipsum'.\n" \
136 "| Of course all Ethernet fields can also be accessed.\n"\
137 "|\n"
141 // Note: If another function specified tx.udp_payload then it must also
142 // set tx.udp_payload_s AND tx.udp_len = tx.udp_payload_s + 8
143 libnet_ptag_t create_udp_packet (libnet_t *l)
145 libnet_ptag_t t;
146 char argval[MAX_PAYLOAD_SIZE];
147 int T; // only an abbreviation for tx.packet_mode
148 int i;
150 /////////////////////////////
151 // Default UDP header fields
152 // Already reset in init.c
153 /////////////////////////////
155 T = tx.packet_mode; // >0 means automatic L2 creation
157 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==UDP) )
159 if (mz_port)
161 cli_print(gcli, "%s", MZ_UDP_HELP);
162 return -1;
164 else
167 fprintf(stderr,"\n"
168 MAUSEZAHN_VERSION
169 "\n%s", MZ_UDP_HELP);
171 exit(0);
177 // Evaluate CLI parameters:
179 if (getarg(tx.arg_string,"dp", argval)==1)
181 if (get_port_range (DST_PORT, argval)) // problem
183 tx.dp = 0;
187 if (getarg(tx.arg_string,"sp", argval)==1)
189 if (get_port_range (SRC_PORT, argval)) // problem
191 tx.sp = 0;
196 // Check if hex_payload already specified (externally)
197 if (tx.hex_payload_s)
199 memcpy( (void*) tx.udp_payload, (void*) tx.hex_payload, tx.hex_payload_s);
200 tx.udp_payload_s = tx.hex_payload_s;
203 if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1))
205 tx.udp_payload_s = str2hex (argval, tx.udp_payload, MAX_PAYLOAD_SIZE);
210 if (getarg(tx.arg_string,"sum", argval)==1)
212 if (T) fprintf(stderr, " IP_Warning: 'sum' cannot be set in this mode.\n");
213 tx.ip_sum = (u_int16_t) str2int(argval);
216 if (getarg(tx.arg_string,"udp_sum", argval)==1)
218 tx.udp_sum = (u_int16_t) str2int(argval);
222 if (tx.ascii) // ASCII PAYLOAD overrides hex payload
224 strncpy((char *)tx.udp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE);
225 tx.udp_payload_s = strlen((char *)tx.ascii_payload);
226 printf("[%s]\n", tx.ascii_payload);
230 /////////
231 // Want some padding? The specified number of padding bytes are ADDED to the
232 // payload.
233 // (Note the difference in send_eth() where you specified the total number
234 // of bytes in the frame)
236 if (tx.padding)
238 for (i=0; i<tx.padding; i++)
240 tx.udp_payload[tx.udp_payload_s+i] = 0x42; // pad with THE ANSWER (why random?)
242 tx.udp_payload_s += tx.padding;
247 ////////
248 // The following is VERY IMPORTANT because the ip_payload_s is also set!
249 if (getarg(tx.arg_string,"len", argval)==1)
251 tx.udp_len = (u_int16_t) str2int(argval);
252 tx.ip_payload_s = tx.udp_len;
254 else // len NOT specified by user
256 if (tx.udp_len == 0) // len also not specified by another function (e. g. create_dns_packet...)
258 tx.udp_len = 8 + tx.udp_payload_s;
259 tx.ip_payload_s = tx.udp_len;
261 else // len (and payload and payload_s) has been specified by another function
263 tx.ip_payload_s = tx.udp_len;
270 t = libnet_build_udp(tx.sp,
271 tx.dp,
272 tx.udp_len,
273 tx.udp_sum,
274 (tx.udp_payload_s) ? tx.udp_payload : NULL,
275 tx.udp_payload_s,
279 // Checksum overwrite? Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
280 libnet_toggle_checksum(l, t, (tx.udp_sum || ipv6_mode) ? LIBNET_OFF : LIBNET_ON);
282 if (t == -1)
284 fprintf(stderr, " mz/create_udp_packet: Can't build UDP header: %s\n", libnet_geterror(l));
285 exit (0);
290 return t;
301 ///////////////////////////////////////////////////
302 ///////////////////////////////////////////////////
303 ///////////////////////////////////////////////////
304 ///////////////////////////////////////////////////
305 ///////////////////////////////////////////////////
309 libnet_ptag_t create_icmp_packet (libnet_t *l)
312 libnet_ptag_t t;
313 char argval[MAX_PAYLOAD_SIZE];
314 unsigned char *x;
316 int i;
318 enum
320 NONE,
321 ECHO_REQUEST,
322 REDIRECT,
323 UNREACHABLE
325 icmp; // which ICMP Type?
328 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==ICMP) )
330 if (mz_port)
332 cli_print(gcli, "%s", MZ_ICMP_HELP);
333 return -1;
335 else
338 fprintf(stderr,"\n"
339 MAUSEZAHN_VERSION
340 "\n%s", MZ_ICMP_HELP);
341 exit(0);
346 /////////////////////////////////////////
348 // Which ICMP Type has been specified?
350 // Note: to allow invalid type values we need the enum 'icmp' tp specify the sending function
351 // and the 'type' variable seperately.
353 if ( (getarg(tx.arg_string,"redirect", NULL)==1) || (getarg(tx.arg_string,"redir", NULL)==1) )
355 icmp = REDIRECT;
356 tx.icmp_type = ICMP_REDIRECT;
357 tx.icmp_code=ICMP_REDIRECT_HOST;
361 if ( (getarg(tx.arg_string,"ping", NULL)==1) || (getarg(tx.arg_string,"echoreq", NULL)==1) )
363 icmp = ECHO_REQUEST;
364 tx.icmp_type = ICMP_ECHO;
365 tx.icmp_code = 0;
369 if (getarg(tx.arg_string,"unreach", NULL)==1)
371 icmp = UNREACHABLE;
372 tx.icmp_type = ICMP_UNREACH;
373 tx.icmp_code = 0; // network unreachable
377 /////////////////////////////////////////
379 // Which parameters have been specified?
382 if (getarg(tx.arg_string,"type", argval)==1)
384 tx.icmp_type = (u_int8_t) str2int(argval);
387 if (getarg(tx.arg_string,"code", argval)==1)
389 tx.icmp_code = (u_int8_t) str2int(argval);
391 else
393 // Use appropriate defaults depending on ICMP type
397 if (getarg(tx.arg_string,"icmp_sum", argval)==1)
399 tx.icmp_chksum = (u_int16_t) str2int(argval);
402 if ( (getarg(tx.arg_string,"gateway", argval)==1) || (getarg(tx.arg_string,"gw", argval)==1) )
404 tx.icmp_gateway = str2ip32 (argval);
406 else
408 tx.icmp_gateway = tx.ip_src; // prefer own address
412 if (getarg(tx.arg_string,"id", argval)==1)
414 tx.icmp_ident = (u_int16_t) str2int(argval);
417 if (getarg(tx.arg_string,"seq", argval)==1)
419 tx.icmp_sqnr = (u_int16_t) str2int(argval);
423 // Check if hex_payload already specified (externally)
424 if (tx.hex_payload_s)
426 memcpy( (void*) tx.icmp_payload, (void*) tx.hex_payload, tx.hex_payload_s);
427 tx.icmp_payload_s = tx.hex_payload_s;
431 if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1))
433 tx.icmp_payload_s = str2hex (argval, tx.icmp_payload, MAX_PAYLOAD_SIZE);
435 else
437 tx.icmp_payload_s = 0;
441 if (tx.ascii) // ASCII PAYLOAD overrides hex payload
443 strncpy((char *)tx.icmp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE);
444 tx.icmp_payload_s = strlen((char *)tx.ascii_payload);
448 /////////
449 // Want some padding? The specified number of padding bytes are ADDED to the
450 // payload.
451 // (Note the difference in send_eth() where you specified the total number
452 // of bytes in the frame)
454 if (tx.padding)
456 for (i=0; i<tx.padding; i++)
458 tx.icmp_payload[tx.icmp_payload_s+i] = 0x42; // pad with THE ANSWER (why random?)
460 tx.icmp_payload_s += tx.padding;
464 ////////////////////////////////////////////////////////////////////////////////////////////
466 // Now determine which type of ICMP packet to send.
468 // NOTE: Every section (icmp-type) must provide
470 // 1. a build function
471 // 2. tx.ip_payload_s which indicates the whole ICMP packet size
472 // 3. tx.icmp_verbose_string containing details about the ICMP packet (verbose mode)
474 ////////////////////////////////////////////////////////////////////////////////////////////
476 switch (icmp)
478 case REDIRECT: // +++++++++++++++
479 t = libnet_build_icmpv4_redirect (tx.icmp_type,
480 tx.icmp_code,
481 tx.icmp_chksum,
482 tx.icmp_gateway,
483 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
484 tx.icmp_payload_s,
487 tx.ip_payload_s = LIBNET_ICMPV4_REDIRECT_H + tx.icmp_payload_s; // for send_ip
488 if (verbose)
490 x = (unsigned char*) &tx.icmp_gateway;
491 sprintf(tx.icmp_verbose_txt,"ICMP Redirect, GW=%u.%u.%u.%u",
492 *(x),*(x+1),*(x+2),*(x+3));
494 break; // ++++++++++++++++++++++
495 case NONE:
496 case ECHO_REQUEST:
497 t = libnet_build_icmpv4_echo(tx.icmp_type,
498 tx.icmp_code,
499 tx.icmp_chksum,
500 tx.icmp_ident,
501 tx.icmp_sqnr,
502 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
503 tx.icmp_payload_s,
506 tx.ip_payload_s = LIBNET_ICMPV4_REDIRECT_H + tx.icmp_payload_s; // for send_ip
507 if (verbose)
509 if (icmp == NONE)
510 sprintf(tx.icmp_verbose_txt,"ICMP Type %u Code %u\n",tx.icmp_type,tx.icmp_code);
511 else
512 sprintf(tx.icmp_verbose_txt,"ICMP Echo Request (id=%u seq=%u)\n",tx.icmp_ident,tx.icmp_sqnr);
514 break; // ++++++++++++++++++++++
515 case UNREACHABLE:
516 t = libnet_build_icmpv4_unreach(tx.icmp_type,
517 tx.icmp_code,
518 tx.icmp_chksum,
519 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
520 tx.icmp_payload_s,
523 if (verbose)
525 sprintf(tx.icmp_verbose_txt,"ICMP unreachable (code=%u)\n",tx.icmp_code);
527 break; // ++++++++++++++++++++++
528 default:
529 (void) fprintf(stderr," mz/icmp: unknown mode! Stop.\n");
530 return (1);
533 libnet_toggle_checksum(l, t, tx.icmp_chksum ? LIBNET_OFF : LIBNET_ON);
535 if (t == -1)
537 fprintf(stderr, " mz/create_icmp_packet: Can't build ICMP header: %s\n", libnet_geterror(l));
538 exit (0);
542 return t;
545 libnet_ptag_t create_icmp6_packet (libnet_t *l)
547 libnet_ptag_t t;
548 char argval[MAX_PAYLOAD_SIZE];
550 int i;
551 tx.icmp_ident = 0;
552 tx.icmp_sqnr = 0;
554 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==ICMP) )
556 if (mz_port)
558 cli_print(gcli, "%s", MZ_ICMP6_HELP);
559 return -1;
561 else
563 fprintf(stderr,"\n"
564 MAUSEZAHN_VERSION
565 "\n%s", MZ_ICMP6_HELP);
566 exit(0);
571 /////////////////////////////////////////
573 // Which parameters have been specified?
576 if (getarg(tx.arg_string,"type", argval)==1)
578 tx.icmp_type = (u_int8_t) str2int(argval);
581 if (getarg(tx.arg_string,"code", argval)==1)
583 tx.icmp_code = (u_int8_t) str2int(argval);
586 if (getarg(tx.arg_string,"id", argval)==1)
588 tx.icmp_ident = (u_int16_t) str2int(argval);
591 if (getarg(tx.arg_string,"seq", argval)==1)
593 tx.icmp_sqnr = (u_int16_t) str2int(argval);
596 if (getarg(tx.arg_string,"icmpv6_sum", argval)==1)
598 tx.icmp_chksum = (u_int16_t) str2int(argval);
601 // Check if hex_payload already specified (externally)
602 if (tx.hex_payload_s)
604 memcpy( (void*) tx.icmp_payload, (void*) tx.hex_payload, tx.hex_payload_s);
605 tx.icmp_payload_s = tx.hex_payload_s;
608 if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1))
610 tx.icmp_payload_s = str2hex (argval, tx.icmp_payload, MAX_PAYLOAD_SIZE);
612 else
614 tx.icmp_payload_s = 0;
617 if (tx.ascii) // ASCII PAYLOAD overrides hex payload
619 strncpy((char *)tx.icmp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE);
620 tx.icmp_payload_s = strlen((char *)tx.ascii_payload);
623 /////////
624 // Want some padding? The specified number of padding bytes are ADDED to the
625 // payload.
626 // (Note the difference in send_eth() where you specified the total number
627 // of bytes in the frame)
629 if (tx.padding)
631 for (i=0; i<tx.padding; i++)
633 tx.icmp_payload[tx.icmp_payload_s+i] = 0x42; // pad with THE ANSWER (why random?)
635 tx.icmp_payload_s += tx.padding;
638 sprintf(tx.icmp_verbose_txt,"ICMPv6 Type %u Code %u\n",tx.icmp_type,tx.icmp_code);
640 t = libnet_build_icmpv4_echo (tx.icmp_type,
641 tx.icmp_code,
642 tx.icmp_chksum,
643 tx.icmp_ident,
644 tx.icmp_sqnr,
645 tx.icmp_payload_s ? tx.icmp_payload : NULL,
646 tx.icmp_payload_s,
649 tx.ip_payload_s = LIBNET_ICMPV6_H + tx.icmp_payload_s; // for send_ip
651 // Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
652 libnet_toggle_checksum(l, t, (tx.icmp_chksum || ipv6_mode) ? LIBNET_OFF : LIBNET_ON);
654 if (t == -1)
656 fprintf(stderr, " mz/create_icmp_packet: Can't build ICMPv6 header: %s\n", libnet_geterror(l));
657 exit (0);
660 return t;
665 ///////////////////////////////////////////////////
666 ///////////////////////////////////////////////////
667 ///////////////////////////////////////////////////
668 ///////////////////////////////////////////////////
669 ///////////////////////////////////////////////////
672 // Note: If another function specified tx.tcp_payload then it must also
673 // set tx.tcp_payload_s AND tx.tcp_len = tx.tcp_payload_s + 20
674 libnet_ptag_t create_tcp_packet (libnet_t *l)
676 libnet_ptag_t t, t2;
677 char argval[MAX_PAYLOAD_SIZE], *dummy1, *dummy2;
678 int T; // only an abbreviation for tx.packet_mode
679 int i;
681 u_int8_t tcp_default_options[] =
683 0x02, 0x04, 0x05, 0xac, // MSS
684 0x04, 0x02, // SACK permitted
685 0x08, 0x0a, 0x19, 0x35, 0x90, 0xc3, 0x00, 0x00, 0x00, 0x00, // Timestamps
686 0x01, // NOP
687 0x03, 0x03, 0x05 // Window Scale 5
692 /////////////////////////////
693 // Default TCP header fields
694 // Already reset in init.c
695 /////////////////////////////
697 T = tx.packet_mode; // >0 means automatic L2 creation
699 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==TCP) )
701 if (mz_port)
703 cli_print(gcli, "%s", MZ_TCP_HELP);
704 return -1;
706 else
708 fprintf(stderr,"\n"
709 MAUSEZAHN_VERSION
710 "\n%s", MZ_TCP_HELP);
711 exit(0);
716 // Evaluate CLI parameters:
718 if (getarg(tx.arg_string,"dp", argval)==1)
720 if (get_port_range (DST_PORT, argval)) // problem
722 tx.dp = 0;
727 if (getarg(tx.arg_string,"sp", argval)==1)
729 if (get_port_range (SRC_PORT, argval)) // problem
731 tx.sp = 0;
736 if (getarg(tx.arg_string,"s", argval)==1)
738 //check whether a range has been specified:
739 dummy1 = strtok(argval, "-");
740 tx.tcp_seq = (u_int32_t) str2int (dummy1);
741 if ( (dummy2 = strtok(NULL, "-")) == NULL ) // no additional value
743 tx.tcp_seq_stop = tx.tcp_seq;
745 else // range
747 tx.tcp_seq_stop = (u_int32_t) str2int (dummy2);
748 tx.tcp_seq_start = tx.tcp_seq; // initially tcp_seq = tcp_seq_start
749 tx.tcp_seq_delta = 1; // an initialization only in case 'ds' not specified
753 if (getarg(tx.arg_string,"ds", argval)==1)
755 tx.tcp_seq_delta = (u_int32_t) str2int (argval);
758 if (getarg(tx.arg_string,"a", argval)==1)
760 tx.tcp_ack = (u_int32_t) str2int (argval);
763 if (getarg(tx.arg_string,"win", argval)==1)
765 tx.tcp_win = (u_int16_t) str2int (argval);
768 if (getarg(tx.arg_string,"urg", argval)==1)
770 tx.tcp_urg = (u_int16_t) str2int (argval);
774 if ( (getarg(tx.arg_string,"flags", argval)==1) ||
775 (getarg(tx.arg_string,"flag", argval)==1) ) // because everybody confuses this
777 if (get_tcp_flags(argval)) // problem
779 tx.tcp_control=2; // Assume SYN as default
783 if (getarg(tx.arg_string,"tcp_sum", argval)==1)
785 tx.tcp_sum = (u_int16_t) str2int(argval);
788 // Check if hex_payload already specified (externally)
789 if (tx.hex_payload_s)
791 memcpy( (void*) tx.tcp_payload, (void*) tx.hex_payload, tx.hex_payload_s);
792 tx.tcp_payload_s = tx.hex_payload_s;
796 if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1))
798 tx.tcp_payload_s = str2hex (argval, tx.tcp_payload, MAX_PAYLOAD_SIZE);
802 if (tx.ascii) // ASCII PAYLOAD overrides hex payload
804 strncpy((char *)tx.tcp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE);
805 tx.tcp_payload_s = strlen((char *)tx.ascii_payload);
806 tx.tcp_len = 20 + tx.tcp_payload_s; // only needed by libnet to calculate checksum
807 tx.ip_payload_s = tx.tcp_len; // for create_ip_packet
812 /////////
813 // Want some padding? The specified number of padding bytes are ADDED to the
814 // payload.
815 // (Note the difference in send_eth() where you specified the total number
816 // of bytes in the frame)
818 if (tx.padding)
820 for (i=0; i<tx.padding; i++)
822 tx.tcp_payload[tx.tcp_payload_s+i] = 0x42; // pad with THE ANSWER (why random?)
824 tx.tcp_payload_s += tx.padding;
830 tx.tcp_len = 20 + tx.tcp_payload_s; // only needed by libnet to calculate checksum
831 tx.ip_payload_s = tx.tcp_len; // for create_ip_packet
833 if (tx.tcp_control & 0x02) // packets with syn require an MSS option
835 t2 = libnet_build_tcp_options(tcp_default_options,
836 20,
840 if (t2 == -1)
842 fprintf(stderr, " mz/create_tcp_packet: Can't build TCP options: %s\n", libnet_geterror(l));
843 exit (0);
846 tx.tcp_len += 20;
847 tx.tcp_offset = 10;
848 tx.ip_payload_s = tx.tcp_len; // for create_ip_packet
849 tx.tcp_sum_part = libnet_in_cksum((u_int16_t *) tcp_default_options, 20);
851 else
853 tx.tcp_offset = 5;
854 tx.tcp_sum_part = 0;
857 t = libnet_build_tcp (tx.sp,
858 tx.dp,
859 tx.tcp_seq,
860 tx.tcp_ack,
861 tx.tcp_control,
862 tx.tcp_win,
863 tx.tcp_sum,
864 tx.tcp_urg,
865 tx.tcp_len,
866 (tx.tcp_payload_s) ? tx.tcp_payload : NULL,
867 tx.tcp_payload_s,
873 // Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
874 libnet_toggle_checksum(l, t, (tx.tcp_sum || ipv6_mode) ? LIBNET_OFF : LIBNET_ON);
876 if (t == -1)
878 fprintf(stderr, " mz/create_tcp_packet: Can't build TCP header: %s\n", libnet_geterror(l));
879 exit (0);
883 return t;