2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
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.
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
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
29 ////////////////////////////////////////////////////////////////////
36 "| UDP type: Send raw UDP packets.\n" \
43 "| udp_sum 0-65535\n" \
44 "| payload|p <hex payload>\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" \
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" \
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" \
59 #define MZ_ICMP_HELP \
60 "| ICMP type: Send raw ICMP packets.\n" \
62 "| ARGUMENT SYNTAX: [type] <optional parameters> \n" \
64 "| Per default an echo reply is sent (type=0, code=0)\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" \
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" \
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" \
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" \
94 "| (other ICMP types will follow)\n" \
98 #define MZ_ICMP6_HELP \
99 "| ICMPv6 type: Send raw ICMPv6 packets.\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" \
110 #define MZ_TCP_HELP \
111 "| TCP type: Send raw TCP packets.\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" \
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" \
127 "| Also the sequence number can be specified as a range, for example:\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" \
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"\
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
)
146 char argval
[MAX_PAYLOAD_SIZE
];
147 int T
; // only an abbreviation for tx.packet_mode
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
) )
161 cli_print(gcli
, "%s", MZ_UDP_HELP
);
169 "\n%s", MZ_UDP_HELP
);
177 // Evaluate CLI parameters:
179 if (getarg(tx
.arg_string
,"dp", argval
)==1)
181 if (get_port_range (DST_PORT
, argval
)) // problem
187 if (getarg(tx
.arg_string
,"sp", argval
)==1)
189 if (get_port_range (SRC_PORT
, argval
)) // problem
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
);
231 // Want some padding? The specified number of padding bytes are ADDED to the
233 // (Note the difference in send_eth() where you specified the total number
234 // of bytes in the frame)
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
;
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
,
274 (tx
.udp_payload_s
) ? tx
.udp_payload
: NULL
,
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
);
284 fprintf(stderr
, " mz/create_udp_packet: Can't build UDP header: %s\n", libnet_geterror(l
));
301 ///////////////////////////////////////////////////
302 ///////////////////////////////////////////////////
303 ///////////////////////////////////////////////////
304 ///////////////////////////////////////////////////
305 ///////////////////////////////////////////////////
309 libnet_ptag_t
create_icmp_packet (libnet_t
*l
)
313 char argval
[MAX_PAYLOAD_SIZE
];
325 icmp
; // which ICMP Type?
328 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==ICMP
) )
332 cli_print(gcli
, "%s", MZ_ICMP_HELP
);
340 "\n%s", MZ_ICMP_HELP
);
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) )
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) )
364 tx
.icmp_type
= ICMP_ECHO
;
369 if (getarg(tx
.arg_string
,"unreach", NULL
)==1)
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
);
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
);
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
);
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
);
449 // Want some padding? The specified number of padding bytes are ADDED to the
451 // (Note the difference in send_eth() where you specified the total number
452 // of bytes in the frame)
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 ////////////////////////////////////////////////////////////////////////////////////////////
478 case REDIRECT
: // +++++++++++++++
479 t
= libnet_build_icmpv4_redirect (tx
.icmp_type
,
483 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
487 tx
.ip_payload_s
= LIBNET_ICMPV4_REDIRECT_H
+ tx
.icmp_payload_s
; // for send_ip
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; // ++++++++++++++++++++++
497 t
= libnet_build_icmpv4_echo(tx
.icmp_type
,
502 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
506 tx
.ip_payload_s
= LIBNET_ICMPV4_REDIRECT_H
+ tx
.icmp_payload_s
; // for send_ip
510 sprintf(tx
.icmp_verbose_txt
,"ICMP Type %u Code %u\n",tx
.icmp_type
,tx
.icmp_code
);
512 sprintf(tx
.icmp_verbose_txt
,"ICMP Echo Request (id=%u seq=%u)\n",tx
.icmp_ident
,tx
.icmp_sqnr
);
514 break; // ++++++++++++++++++++++
516 t
= libnet_build_icmpv4_unreach(tx
.icmp_type
,
519 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
525 sprintf(tx
.icmp_verbose_txt
,"ICMP unreachable (code=%u)\n",tx
.icmp_code
);
527 break; // ++++++++++++++++++++++
529 (void) fprintf(stderr
," mz/icmp: unknown mode! Stop.\n");
533 libnet_toggle_checksum(l
, t
, tx
.icmp_chksum
? LIBNET_OFF
: LIBNET_ON
);
537 fprintf(stderr
, " mz/create_icmp_packet: Can't build ICMP header: %s\n", libnet_geterror(l
));
545 libnet_ptag_t
create_icmp6_packet (libnet_t
*l
)
548 char argval
[MAX_PAYLOAD_SIZE
];
554 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==ICMP
) )
558 cli_print(gcli
, "%s", MZ_ICMP6_HELP
);
565 "\n%s", MZ_ICMP6_HELP
);
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
);
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
);
624 // Want some padding? The specified number of padding bytes are ADDED to the
626 // (Note the difference in send_eth() where you specified the total number
627 // of bytes in the frame)
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
,
645 tx
.icmp_payload_s
? tx
.icmp_payload
: NULL
,
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
);
656 fprintf(stderr
, " mz/create_icmp_packet: Can't build ICMPv6 header: %s\n", libnet_geterror(l
));
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
)
677 char argval
[MAX_PAYLOAD_SIZE
], *dummy1
, *dummy2
;
678 int T
; // only an abbreviation for tx.packet_mode
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
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
) )
703 cli_print(gcli
, "%s", MZ_TCP_HELP
);
710 "\n%s", MZ_TCP_HELP
);
716 // Evaluate CLI parameters:
718 if (getarg(tx
.arg_string
,"dp", argval
)==1)
720 if (get_port_range (DST_PORT
, argval
)) // problem
727 if (getarg(tx
.arg_string
,"sp", argval
)==1)
729 if (get_port_range (SRC_PORT
, argval
)) // problem
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
;
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
813 // Want some padding? The specified number of padding bytes are ADDED to the
815 // (Note the difference in send_eth() where you specified the total number
816 // of bytes in the frame)
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
,
842 fprintf(stderr
, " mz/create_tcp_packet: Can't build TCP options: %s\n", libnet_geterror(l
));
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);
857 t
= libnet_build_tcp (tx
.sp
,
866 (tx
.tcp_payload_s
) ? tx
.tcp_payload
: NULL
,
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
);
878 fprintf(stderr
, " mz/create_tcp_packet: Can't build TCP header: %s\n", libnet_geterror(l
));