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"\
139 #define MZ_IGMP_HELP \
140 "| IGMP type: Send raw IGMP packets.\n" \
142 "| Parameters Values Explanation \n" \
143 "| ---------- ------------------------------------ -------------------\n" \
144 "| v,ver 1-2 version\n" \
145 "| t,type packet type:\n" \
146 "| q,qry,query - memberhsip query\n" \
147 "| j,join - join group\n" \
148 "| l,lv,leave - leave group\n" \
149 "| resp_time max response time (v2 only)\n" \
150 "| igmp_sum checksum (optional)\n" \
151 "| g,group group ipv4 address\n" \
154 int print_packet_help(char *help
)
157 cli_print(gcli
, "%s", help
);
159 fprintf(stderr
,"\n" MAUSEZAHN_VERSION
"\n%s", help
);
166 // Note: If another function specified tx.udp_payload then it must also
167 // set tx.udp_payload_s AND tx.udp_len = tx.udp_payload_s + 8
168 libnet_ptag_t
create_udp_packet (libnet_t
*l
)
171 char argval
[MAX_PAYLOAD_SIZE
];
172 int T
; // only an abbreviation for tx.packet_mode
176 /////////////////////////////
177 // Default UDP header fields
178 // Already reset in init.c
179 /////////////////////////////
181 T
= tx
.packet_mode
; // >0 means automatic L2 creation
183 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==UDP
) )
187 cli_print(gcli
, "%s", MZ_UDP_HELP
);
195 "\n%s", MZ_UDP_HELP
);
203 // Evaluate CLI parameters:
205 if (getarg(tx
.arg_string
,"dp", argval
)==1)
207 if (get_port_range (DST_PORT
, argval
)) // problem
213 if (getarg(tx
.arg_string
,"sp", argval
)==1)
215 if (get_port_range (SRC_PORT
, argval
)) // problem
222 // Check if hex_payload already specified (externally)
223 if (tx
.hex_payload_s
)
225 memcpy( (void*) tx
.udp_payload
, (void*) tx
.hex_payload
, tx
.hex_payload_s
);
226 tx
.udp_payload_s
= tx
.hex_payload_s
;
229 if ( (getarg(tx
.arg_string
,"payload", argval
)==1) || (getarg(tx
.arg_string
,"p", argval
)==1))
231 tx
.udp_payload_s
= str2hex (argval
, tx
.udp_payload
, MAX_PAYLOAD_SIZE
);
236 if (getarg(tx
.arg_string
,"sum", argval
)==1)
238 if (T
) fprintf(stderr
, " IP_Warning: 'sum' cannot be set in this mode.\n");
239 tx
.ip_sum
= (u_int16_t
) str2int(argval
);
242 if (getarg(tx
.arg_string
,"udp_sum", argval
)==1)
244 tx
.udp_sum
= (u_int16_t
) str2int(argval
);
249 if (tx
.ascii
) // ASCII PAYLOAD overrides hex payload
251 strncpy((char *)tx
.udp_payload
, (char *)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
);
252 tx
.udp_payload_s
= strlen((char *)tx
.ascii_payload
);
253 printf("[%s]\n", tx
.ascii_payload
);
258 // Want some padding? The specified number of padding bytes are ADDED to the
260 // (Note the difference in send_eth() where you specified the total number
261 // of bytes in the frame)
265 for (i
=0; i
<tx
.padding
; i
++)
267 tx
.udp_payload
[tx
.udp_payload_s
+i
] = 0x42; // pad with THE ANSWER (why random?)
269 tx
.udp_payload_s
+= tx
.padding
;
275 // The following is VERY IMPORTANT because the ip_payload_s is also set!
276 if (getarg(tx
.arg_string
,"len", argval
)==1)
278 tx
.udp_len
= (u_int16_t
) str2int(argval
);
279 tx
.ip_payload_s
= tx
.udp_len
;
281 else // len NOT specified by user
283 if (tx
.udp_len
== 0) // len also not specified by another function (e. g. create_dns_packet...)
285 tx
.udp_len
= 8 + tx
.udp_payload_s
;
286 tx
.ip_payload_s
= tx
.udp_len
;
288 else // len (and payload and payload_s) has been specified by another function
290 tx
.ip_payload_s
= tx
.udp_len
;
297 t
= libnet_build_udp(tx
.sp
,
301 (tx
.udp_payload_s
) ? tx
.udp_payload
: NULL
,
306 // Checksum overwrite? Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
307 libnet_toggle_checksum(l
, t
, (udp_sum_set
|| ipv6_mode
) ? LIBNET_OFF
: LIBNET_ON
);
311 fprintf(stderr
, " mz/create_udp_packet: Can't build UDP header: %s\n", libnet_geterror(l
));
328 ///////////////////////////////////////////////////
329 ///////////////////////////////////////////////////
330 ///////////////////////////////////////////////////
331 ///////////////////////////////////////////////////
332 ///////////////////////////////////////////////////
336 libnet_ptag_t
create_icmp_packet (libnet_t
*l
)
340 char argval
[MAX_PAYLOAD_SIZE
];
352 icmp
; // which ICMP Type?
355 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==ICMP
) )
359 cli_print(gcli
, "%s", MZ_ICMP_HELP
);
367 "\n%s", MZ_ICMP_HELP
);
373 /////////////////////////////////////////
375 // Which ICMP Type has been specified?
377 // Note: to allow invalid type values we need the enum 'icmp' tp specify the sending function
378 // and the 'type' variable seperately.
380 if ( (getarg(tx
.arg_string
,"redirect", NULL
)==1) || (getarg(tx
.arg_string
,"redir", NULL
)==1) )
383 tx
.icmp_type
= ICMP_REDIRECT
;
384 tx
.icmp_code
=ICMP_REDIRECT_HOST
;
388 if ( (getarg(tx
.arg_string
,"ping", NULL
)==1) || (getarg(tx
.arg_string
,"echoreq", NULL
)==1) )
391 tx
.icmp_type
= ICMP_ECHO
;
396 if (getarg(tx
.arg_string
,"unreach", NULL
)==1)
399 tx
.icmp_type
= ICMP_UNREACH
;
400 tx
.icmp_code
= 0; // network unreachable
404 /////////////////////////////////////////
406 // Which parameters have been specified?
409 if (getarg(tx
.arg_string
,"type", argval
)==1)
411 tx
.icmp_type
= (u_int8_t
) str2int(argval
);
414 if (getarg(tx
.arg_string
,"code", argval
)==1)
416 tx
.icmp_code
= (u_int8_t
) str2int(argval
);
420 // Use appropriate defaults depending on ICMP type
424 if (getarg(tx
.arg_string
,"icmp_sum", argval
)==1)
426 tx
.icmp_chksum
= (u_int16_t
) str2int(argval
);
429 if ( (getarg(tx
.arg_string
,"gateway", argval
)==1) || (getarg(tx
.arg_string
,"gw", argval
)==1) )
431 tx
.icmp_gateway
= str2ip32 (argval
);
435 tx
.icmp_gateway
= tx
.ip_src
; // prefer own address
439 if (getarg(tx
.arg_string
,"id", argval
)==1)
441 tx
.icmp_ident
= (u_int16_t
) str2int(argval
);
444 if (getarg(tx
.arg_string
,"seq", argval
)==1)
446 tx
.icmp_sqnr
= (u_int16_t
) str2int(argval
);
450 // Check if hex_payload already specified (externally)
451 if (tx
.hex_payload_s
)
453 memcpy( (void*) tx
.icmp_payload
, (void*) tx
.hex_payload
, tx
.hex_payload_s
);
454 tx
.icmp_payload_s
= tx
.hex_payload_s
;
458 if ( (getarg(tx
.arg_string
,"payload", argval
)==1) || (getarg(tx
.arg_string
,"p", argval
)==1))
460 tx
.icmp_payload_s
= str2hex (argval
, tx
.icmp_payload
, MAX_PAYLOAD_SIZE
);
464 tx
.icmp_payload_s
= 0;
468 if (tx
.ascii
) // ASCII PAYLOAD overrides hex payload
470 strncpy((char *)tx
.icmp_payload
, (char *)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
);
471 tx
.icmp_payload_s
= strlen((char *)tx
.ascii_payload
);
476 // Want some padding? The specified number of padding bytes are ADDED to the
478 // (Note the difference in send_eth() where you specified the total number
479 // of bytes in the frame)
483 for (i
=0; i
<tx
.padding
; i
++)
485 tx
.icmp_payload
[tx
.icmp_payload_s
+i
] = 0x42; // pad with THE ANSWER (why random?)
487 tx
.icmp_payload_s
+= tx
.padding
;
491 ////////////////////////////////////////////////////////////////////////////////////////////
493 // Now determine which type of ICMP packet to send.
495 // NOTE: Every section (icmp-type) must provide
497 // 1. a build function
498 // 2. tx.ip_payload_s which indicates the whole ICMP packet size
499 // 3. tx.icmp_verbose_string containing details about the ICMP packet (verbose mode)
501 ////////////////////////////////////////////////////////////////////////////////////////////
505 case REDIRECT
: // +++++++++++++++
506 t
= libnet_build_icmpv4_redirect (tx
.icmp_type
,
510 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
514 tx
.ip_payload_s
= LIBNET_ICMPV4_REDIRECT_H
+ tx
.icmp_payload_s
; // for send_ip
517 x
= (unsigned char*) &tx
.icmp_gateway
;
518 sprintf(tx
.icmp_verbose_txt
,"ICMP Redirect, GW=%u.%u.%u.%u",
519 *(x
),*(x
+1),*(x
+2),*(x
+3));
521 break; // ++++++++++++++++++++++
524 t
= libnet_build_icmpv4_echo(tx
.icmp_type
,
529 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
533 tx
.ip_payload_s
= LIBNET_ICMPV4_REDIRECT_H
+ tx
.icmp_payload_s
; // for send_ip
537 sprintf(tx
.icmp_verbose_txt
,"ICMP Type %u Code %u\n",tx
.icmp_type
,tx
.icmp_code
);
539 sprintf(tx
.icmp_verbose_txt
,"ICMP Echo Request (id=%u seq=%u)\n",tx
.icmp_ident
,tx
.icmp_sqnr
);
541 break; // ++++++++++++++++++++++
543 t
= libnet_build_icmpv4_unreach(tx
.icmp_type
,
546 (tx
.icmp_payload_s
) ? tx
.icmp_payload
: NULL
,
552 sprintf(tx
.icmp_verbose_txt
,"ICMP unreachable (code=%u)\n",tx
.icmp_code
);
554 break; // ++++++++++++++++++++++
556 (void) fprintf(stderr
," mz/icmp: unknown mode! Stop.\n");
560 libnet_toggle_checksum(l
, t
, tx
.icmp_chksum
? LIBNET_OFF
: LIBNET_ON
);
564 fprintf(stderr
, " mz/create_icmp_packet: Can't build ICMP header: %s\n", libnet_geterror(l
));
572 libnet_ptag_t
create_icmp6_packet (libnet_t
*l
)
575 char argval
[MAX_PAYLOAD_SIZE
];
581 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==ICMP
) )
585 cli_print(gcli
, "%s", MZ_ICMP6_HELP
);
592 "\n%s", MZ_ICMP6_HELP
);
598 /////////////////////////////////////////
600 // Which parameters have been specified?
603 if (getarg(tx
.arg_string
,"type", argval
)==1)
605 tx
.icmp_type
= (u_int8_t
) str2int(argval
);
608 if (getarg(tx
.arg_string
,"code", argval
)==1)
610 tx
.icmp_code
= (u_int8_t
) str2int(argval
);
613 if (getarg(tx
.arg_string
,"id", argval
)==1)
615 tx
.icmp_ident
= (u_int16_t
) str2int(argval
);
618 if (getarg(tx
.arg_string
,"seq", argval
)==1)
620 tx
.icmp_sqnr
= (u_int16_t
) str2int(argval
);
623 if (getarg(tx
.arg_string
,"icmpv6_sum", argval
)==1)
625 tx
.icmp_chksum
= (u_int16_t
) str2int(argval
);
628 // Check if hex_payload already specified (externally)
629 if (tx
.hex_payload_s
)
631 memcpy( (void*) tx
.icmp_payload
, (void*) tx
.hex_payload
, tx
.hex_payload_s
);
632 tx
.icmp_payload_s
= tx
.hex_payload_s
;
635 if ( (getarg(tx
.arg_string
,"payload", argval
)==1) || (getarg(tx
.arg_string
,"p", argval
)==1))
637 tx
.icmp_payload_s
= str2hex (argval
, tx
.icmp_payload
, MAX_PAYLOAD_SIZE
);
641 tx
.icmp_payload_s
= 0;
644 if (tx
.ascii
) // ASCII PAYLOAD overrides hex payload
646 strncpy((char *)tx
.icmp_payload
, (char *)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
);
647 tx
.icmp_payload_s
= strlen((char *)tx
.ascii_payload
);
651 // Want some padding? The specified number of padding bytes are ADDED to the
653 // (Note the difference in send_eth() where you specified the total number
654 // of bytes in the frame)
658 for (i
=0; i
<tx
.padding
; i
++)
660 tx
.icmp_payload
[tx
.icmp_payload_s
+i
] = 0x42; // pad with THE ANSWER (why random?)
662 tx
.icmp_payload_s
+= tx
.padding
;
665 sprintf(tx
.icmp_verbose_txt
,"ICMPv6 Type %u Code %u\n",tx
.icmp_type
,tx
.icmp_code
);
667 t
= libnet_build_icmpv4_echo (tx
.icmp_type
,
672 tx
.icmp_payload_s
? tx
.icmp_payload
: NULL
,
676 tx
.ip_payload_s
= LIBNET_ICMPV6_H
+ tx
.icmp_payload_s
; // for send_ip
678 // Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
679 libnet_toggle_checksum(l
, t
, (tx
.icmp_chksum
|| ipv6_mode
) ? LIBNET_OFF
: LIBNET_ON
);
683 fprintf(stderr
, " mz/create_icmp_packet: Can't build ICMPv6 header: %s\n", libnet_geterror(l
));
692 ///////////////////////////////////////////////////
693 ///////////////////////////////////////////////////
694 ///////////////////////////////////////////////////
695 ///////////////////////////////////////////////////
696 ///////////////////////////////////////////////////
699 // Note: If another function specified tx.tcp_payload then it must also
700 // set tx.tcp_payload_s AND tx.tcp_len = tx.tcp_payload_s + 20
701 libnet_ptag_t
create_tcp_packet (libnet_t
*l
)
704 char argval
[MAX_PAYLOAD_SIZE
], *dummy1
, *dummy2
;
705 int T
; // only an abbreviation for tx.packet_mode
708 u_int8_t tcp_default_options
[] =
710 0x02, 0x04, 0x05, 0xac, // MSS
711 0x04, 0x02, // SACK permitted
712 0x08, 0x0a, 0x19, 0x35, 0x90, 0xc3, 0x00, 0x00, 0x00, 0x00, // Timestamps
714 0x03, 0x03, 0x05 // Window Scale 5
719 /////////////////////////////
720 // Default TCP header fields
721 // Already reset in init.c
722 /////////////////////////////
724 T
= tx
.packet_mode
; // >0 means automatic L2 creation
726 if ( (getarg(tx
.arg_string
,"help", NULL
)==1) && (mode
==TCP
) )
730 cli_print(gcli
, "%s", MZ_TCP_HELP
);
737 "\n%s", MZ_TCP_HELP
);
743 // Evaluate CLI parameters:
745 if (getarg(tx
.arg_string
,"dp", argval
)==1)
747 if (get_port_range (DST_PORT
, argval
)) // problem
754 if (getarg(tx
.arg_string
,"sp", argval
)==1)
756 if (get_port_range (SRC_PORT
, argval
)) // problem
763 if (getarg(tx
.arg_string
,"s", argval
)==1)
765 //check whether a range has been specified:
766 dummy1
= strtok(argval
, "-");
767 tx
.tcp_seq
= (u_int32_t
) str2int (dummy1
);
768 if ( (dummy2
= strtok(NULL
, "-")) == NULL
) // no additional value
770 tx
.tcp_seq_stop
= tx
.tcp_seq
;
774 tx
.tcp_seq_stop
= (u_int32_t
) str2int (dummy2
);
775 tx
.tcp_seq_start
= tx
.tcp_seq
; // initially tcp_seq = tcp_seq_start
776 tx
.tcp_seq_delta
= 1; // an initialization only in case 'ds' not specified
780 if (getarg(tx
.arg_string
,"ds", argval
)==1)
782 tx
.tcp_seq_delta
= (u_int32_t
) str2int (argval
);
785 if (getarg(tx
.arg_string
,"a", argval
)==1)
787 tx
.tcp_ack
= (u_int32_t
) str2int (argval
);
790 if (getarg(tx
.arg_string
,"win", argval
)==1)
792 tx
.tcp_win
= (u_int16_t
) str2int (argval
);
795 if (getarg(tx
.arg_string
,"urg", argval
)==1)
797 tx
.tcp_urg
= (u_int16_t
) str2int (argval
);
801 if ( (getarg(tx
.arg_string
,"flags", argval
)==1) ||
802 (getarg(tx
.arg_string
,"flag", argval
)==1) ) // because everybody confuses this
804 if (get_tcp_flags(argval
)) // problem
806 tx
.tcp_control
=2; // Assume SYN as default
810 if (getarg(tx
.arg_string
,"tcp_sum", argval
)==1)
812 tx
.tcp_sum
= (u_int16_t
) str2int(argval
);
815 // Check if hex_payload already specified (externally)
816 if (tx
.hex_payload_s
)
818 memcpy( (void*) tx
.tcp_payload
, (void*) tx
.hex_payload
, tx
.hex_payload_s
);
819 tx
.tcp_payload_s
= tx
.hex_payload_s
;
823 if ( (getarg(tx
.arg_string
,"payload", argval
)==1) || (getarg(tx
.arg_string
,"p", argval
)==1))
825 tx
.tcp_payload_s
= str2hex (argval
, tx
.tcp_payload
, MAX_PAYLOAD_SIZE
);
829 if (tx
.ascii
) // ASCII PAYLOAD overrides hex payload
831 strncpy((char *)tx
.tcp_payload
, (char *)tx
.ascii_payload
, MAX_PAYLOAD_SIZE
);
832 tx
.tcp_payload_s
= strlen((char *)tx
.ascii_payload
);
833 tx
.tcp_len
= 20 + tx
.tcp_payload_s
; // only needed by libnet to calculate checksum
834 tx
.ip_payload_s
= tx
.tcp_len
; // for create_ip_packet
840 // Want some padding? The specified number of padding bytes are ADDED to the
842 // (Note the difference in send_eth() where you specified the total number
843 // of bytes in the frame)
847 for (i
=0; i
<tx
.padding
; i
++)
849 tx
.tcp_payload
[tx
.tcp_payload_s
+i
] = 0x42; // pad with THE ANSWER (why random?)
851 tx
.tcp_payload_s
+= tx
.padding
;
857 tx
.tcp_len
= 20 + tx
.tcp_payload_s
; // only needed by libnet to calculate checksum
858 tx
.ip_payload_s
= tx
.tcp_len
; // for create_ip_packet
860 if (tx
.tcp_control
& 0x02) // packets with syn require an MSS option
862 t2
= libnet_build_tcp_options(tcp_default_options
,
869 fprintf(stderr
, " mz/create_tcp_packet: Can't build TCP options: %s\n", libnet_geterror(l
));
875 tx
.ip_payload_s
= tx
.tcp_len
; // for create_ip_packet
876 tx
.tcp_sum_part
= libnet_in_cksum((u_int16_t
*) tcp_default_options
, 20);
884 t
= libnet_build_tcp (tx
.sp
,
893 (tx
.tcp_payload_s
) ? tx
.tcp_payload
: NULL
,
900 // Libnet IPv6 checksum calculation can't deal with extension headers, we have to do it ourself...
901 libnet_toggle_checksum(l
, t
, (tx
.tcp_sum
|| ipv6_mode
) ? LIBNET_OFF
: LIBNET_ON
);
905 fprintf(stderr
, " mz/create_tcp_packet: Can't build TCP header: %s\n", libnet_geterror(l
));
913 libnet_ptag_t
create_igmp_packet(libnet_t
*l
)
916 char argval
[MAX_PAYLOAD_SIZE
];
918 uint8_t type
= IGMP_MEMBERSHIP_QUERY
;
919 uint8_t resp_time
= 10;
923 if ((getarg(tx
.arg_string
, "help", NULL
) == 1) && (mode
== IGMP
))
924 return print_packet_help(MZ_IGMP_HELP
);
926 if (getarg(tx
.arg_string
, "ver", argval
) == 1 ||
927 getarg(tx
.arg_string
, "v", argval
) == 1) {
929 ver
= str2int(argval
);
934 if (getarg(tx
.arg_string
, "type", argval
) == 1 ||
935 getarg(tx
.arg_string
, "t", argval
) == 1) {
937 if (strcmp("j", argval
) == 0 || strcmp("join", argval
) == 0) {
940 type
= IGMP_V1_MEMBERSHIP_REPORT
;
942 type
= IGMP_V2_MEMBERSHIP_REPORT
;
944 } else if (strcmp("l", argval
) == 0 || strcmp("lv", argval
) == 0 ||
945 strcmp("leave", argval
) == 0) {
947 type
= IGMP_LEAVE_GROUP
;
951 if (getarg(tx
.arg_string
, "resp_time", argval
) == 1)
952 resp_time
= (uint8_t)str2int(argval
);
954 if (getarg(tx
.arg_string
, "igmp_sum", argval
) == 1)
955 sum
= (uint16_t)str2int(argval
);
957 if (getarg(tx
.arg_string
, "group", argval
) == 1 ||
958 getarg(tx
.arg_string
, "g", argval
) == 1) {
960 group
= str2ip32_rev(argval
);
963 if (type
== IGMP_LEAVE_GROUP
) {
964 tx
.ip_dst
= str2ip32_rev("224.0.0.2");
965 } else if (type
== IGMP_MEMBERSHIP_QUERY
) {
966 if (ver
== 1 || group
== 0)
967 tx
.ip_dst
= str2ip32_rev("224.0.0.1");
968 else if (ver
== 2 && group
!= 0)
970 } else if (type
== IGMP_V1_MEMBERSHIP_REPORT
||
971 type
== IGMP_V2_MEMBERSHIP_REPORT
) {
976 if (getarg(tx
.arg_string
, "ttl", argval
) == 0)
979 t
= libnet_build_igmp(type
, resp_time
, sum
, group
, NULL
, 0, l
, 0);
981 fprintf(stderr
, " mz/create_igmp_packet: Can't build IGMP header: %s\n",