From d0009856814c13d13770db5aadd7b2fabf947776 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 13 May 2013 13:53:27 +0200 Subject: staging: add mausezahn staging directory After some back and forth, we decided that it is easier to maintain mausezahn in a staging directory until it is fully reworked and cleaned up to be ready to be fully integrated. This way, it is better than having it in a separate branch, and we can also accept patches from outside more easily. Also, while at it, fix up some function mismatches with libcli. Signed-off-by: Daniel Borkmann Signed-off-by: Tobias Klauser --- staging/layer4.c | 884 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 884 insertions(+) create mode 100644 staging/layer4.c (limited to 'staging/layer4.c') diff --git a/staging/layer4.c b/staging/layer4.c new file mode 100644 index 0000000..ca4d229 --- /dev/null +++ b/staging/layer4.c @@ -0,0 +1,884 @@ +/* + * Mausezahn - A fast versatile traffic generator + * Copyright (C) 2008-2010 Herbert Haas + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see http://www.gnu.org/licenses/gpl-2.0.html + * +*/ + + + +//////////////////////////////////////////////////////////////////// +// +// Layer 4 packet types +// +// 1. UDP +// 2. ICMP +// 3. TCP +// +//////////////////////////////////////////////////////////////////// + +#include "mz.h" +#include "cli.h" + + +#define MZ_UDP_HELP \ + "| UDP type: Send raw UDP packets.\n" \ + "|\n" \ + "| Parameters: \n" \ + "|\n" \ + "| sp 0-65535\n" \ + "| dp 0-65535\n" \ + "| len 0-65535\n" \ + "| udp_sum 0-65535\n" \ + "| payload|p \n" \ + "|\n" \ + "| Optionally the port numbers can be specified as ranges, e. g. \"dp=1023-33700\",\n" \ + "| in which case one packet per port number is sent.\n" \ + "|\n" \ + "| Note that the UDP length must include the header length. If you do NOT specify the len\n" \ + "| parameter (or specify len=0) then Mausezahn will compute the correct length.\n" \ + "|\n" \ + "| Note that all IP parameters can be modified (see IP help, i. e. '-t ip \"help\")\n" \ + "| except that (to avoid confusion) the IP length is 'iplen' and the IP checksum is 'ipsum'.\n" \ + "| Of course all Ethernet fields can also be accessed.\n" \ + "|\n" \ + "\n" + + +#define MZ_ICMP_HELP \ + "| ICMP type: Send raw ICMP packets.\n" \ + "|\n" \ + "| ARGUMENT SYNTAX: [type] \n" \ + "| \n" \ + "| Per default an echo reply is sent (type=0, code=0)\n" \ + "|\n" \ + "| TYPE OPTIONAL PARAMETERS\n" \ + "| =========== ====================================================================\n" \ + "| Ping: \"ping\" or \"echoreq\" \n" \ + "| 'id' (0-65535) is the optional identification number\n" \ + "| 'seq' (0-65535) is the optional packet sequence number\n" \ + "|\n" \ + "| Redirect: \"redir, code=0, gw=192.168.1.10, p=aa:bb:cc\"\n" \ + "| 'gw' (or 'gateway') is the announced gateway, by default your own\n" \ + "| IP address.\n" \ + "| 'code' can be:\n" \ + "| 0 ... redirect datagram for the network\n" \ + "| 1 ... redirect datagram for the host\n" \ + "| 2 ... redirect datagram for ToS and network\n" \ + "| 3 ... redirect datagram for ToS and host\n" \ + "| 'p' (or 'payload') is the payload of the ICMP packet, tpyically an IP\n" \ + "| header. Note that - at the moment - you must prepare this payload by\n" \ + "| yourself.\n" \ + "|\n" \ + "| Unreachable \"unreach, code=2\"\n" \ + "| 'code' can be:\n" \ + "| 0 ... network unreachable\n" \ + "| 1 ... host unreachable\n" \ + "| 2 ... protocol unreachable\n" \ + "| 3 ... port unreachable\n" \ + "| 4 ... fragmentation needed but DF-bit is set\n" \ + "| 5 ... source route failed\n" \ + "|\n" \ + "|\n" \ + "| (other ICMP types will follow)\n" \ + "|\n" \ + "\n" + +#define MZ_ICMP6_HELP \ + "| ICMPv6 type: Send raw ICMPv6 packets.\n" \ + "|\n" \ + "| Parameters Values Explanation \n" \ + "| ---------- ------------------------------------ -------------------\n" \ + "| type 0-255 ICMPv6 Type\n" \ + "| code 0-255 ICMPv6 Code\n" \ + "| id 0-65535 optional identification number\n" \ + "| seq 0-65535 optional packet sequence number\n" \ + "| icmpv6_sum 0-65535 optional checksum\n" \ + "\n" + +#define MZ_TCP_HELP \ + "| TCP type: Send raw TCP packets.\n" \ + "|\n" \ + "| Parameters Values Explanation \n" \ + "| ---------- ------------------------------------ -------------------\n" \ + "| sp 0-65535 Source Port\n" \ + "| dp 0-65535 Destination Port\n" \ + "| flags fin|syn|rst|psh|ack|urg|ecn|cwr\n" \ + "| s 0-4294967295 Sequence Nr.\n" \ + "| a 0-4294967295 Acknowledgement Nr.\n" \ + "| win 0-65535 Window Size\n" \ + "| urg 0-65535 Urgent Pointer\n" \ + "| tcp_sum 0-65535 Checksum\n" \ + "|\n" \ + "| The port numbers can be specified as ranges, e. g. \"dp=1023-33700\".\n" \ + "| Multiple flags can be specified such as \"flags=syn|ack|urg\".\n" \ + "|\n" \ + "| Also the sequence number can be specified as a range, for example:\n" \ + "|\n" \ + "| s=10000-50000 ... send 40000 packets with SQNRs in that range. If the second\n" \ + "| value is lower than the first then it is assumed that the\n" \ + "| SQNRs should 'wrap around'.\n" \ + "| ds=30000 ........ use this increment within a SQNR-range.\n" \ + "|\n" \ + "| Note that all IP parameters can be modified (see IP help, i. e. '-t ip \"help\")\n" \ + "| except that (to avoid confusion) the IP length is 'iplen' and the IP checksum is 'ipsum'.\n" \ + "| Of course all Ethernet fields can also be accessed.\n"\ + "|\n" + + + +// Note: If another function specified tx.udp_payload then it must also +// set tx.udp_payload_s AND tx.udp_len = tx.udp_payload_s + 8 +libnet_ptag_t create_udp_packet (libnet_t *l) +{ + libnet_ptag_t t; + char argval[MAX_PAYLOAD_SIZE]; + int T; // only an abbreviation for tx.packet_mode + int i; + + ///////////////////////////// + // Default UDP header fields + // Already reset in init.c + ///////////////////////////// + + T = tx.packet_mode; // >0 means automatic L2 creation + + if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==UDP) ) + { + if (mz_port) + { + cli_print(gcli, "%s", MZ_UDP_HELP); + return -1; + } + else + { + + fprintf(stderr,"\n" + MAUSEZAHN_VERSION + "\n%s", MZ_UDP_HELP); + + exit(0); + } + + } + + + // Evaluate CLI parameters: + + if (getarg(tx.arg_string,"dp", argval)==1) + { + if (get_port_range (DST_PORT, argval)) // problem + { + tx.dp = 0; + } + } + + if (getarg(tx.arg_string,"sp", argval)==1) + { + if (get_port_range (SRC_PORT, argval)) // problem + { + tx.sp = 0; + } + } + + + // Check if hex_payload already specified (externally) + if (tx.hex_payload_s) + { + memcpy( (void*) tx.udp_payload, (void*) tx.hex_payload, tx.hex_payload_s); + tx.udp_payload_s = tx.hex_payload_s; + } + + if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1)) + { + tx.udp_payload_s = str2hex (argval, tx.udp_payload, MAX_PAYLOAD_SIZE); + } + + + + if (getarg(tx.arg_string,"sum", argval)==1) + { + if (T) fprintf(stderr, " IP_Warning: 'sum' cannot be set in this mode.\n"); + tx.ip_sum = (u_int16_t) str2int(argval); + } + + if (getarg(tx.arg_string,"udp_sum", argval)==1) + { + tx.udp_sum = (u_int16_t) str2int(argval); + } + + + if (tx.ascii) // ASCII PAYLOAD overrides hex payload + { + strncpy((char *)tx.udp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE); + tx.udp_payload_s = strlen((char *)tx.ascii_payload); + printf("[%s]\n", tx.ascii_payload); + } + + + ///////// + // Want some padding? The specified number of padding bytes are ADDED to the + // payload. + // (Note the difference in send_eth() where you specified the total number + // of bytes in the frame) + // + if (tx.padding) + { + for (i=0; i0 means automatic L2 creation + + if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==TCP) ) + { + if (mz_port) + { + cli_print(gcli, "%s", MZ_TCP_HELP); + return -1; + } + else + { + fprintf(stderr,"\n" + MAUSEZAHN_VERSION + "\n%s", MZ_TCP_HELP); + exit(0); + } + } + + + // Evaluate CLI parameters: + + if (getarg(tx.arg_string,"dp", argval)==1) + { + if (get_port_range (DST_PORT, argval)) // problem + { + tx.dp = 0; + } + } + + + if (getarg(tx.arg_string,"sp", argval)==1) + { + if (get_port_range (SRC_PORT, argval)) // problem + { + tx.sp = 0; + } + } + + + if (getarg(tx.arg_string,"s", argval)==1) + { + //check whether a range has been specified: + dummy1 = strtok(argval, "-"); + tx.tcp_seq = (u_int32_t) str2int (dummy1); + if ( (dummy2 = strtok(NULL, "-")) == NULL ) // no additional value + { + tx.tcp_seq_stop = tx.tcp_seq; + } + else // range + { + tx.tcp_seq_stop = (u_int32_t) str2int (dummy2); + tx.tcp_seq_start = tx.tcp_seq; // initially tcp_seq = tcp_seq_start + tx.tcp_seq_delta = 1; // an initialization only in case 'ds' not specified + } + } + + if (getarg(tx.arg_string,"ds", argval)==1) + { + tx.tcp_seq_delta = (u_int32_t) str2int (argval); + } + + if (getarg(tx.arg_string,"a", argval)==1) + { + tx.tcp_ack = (u_int32_t) str2int (argval); + } + + if (getarg(tx.arg_string,"win", argval)==1) + { + tx.tcp_win = (u_int16_t) str2int (argval); + } + + if (getarg(tx.arg_string,"urg", argval)==1) + { + tx.tcp_urg = (u_int16_t) str2int (argval); + } + + + if ( (getarg(tx.arg_string,"flags", argval)==1) || + (getarg(tx.arg_string,"flag", argval)==1) ) // because everybody confuses this + { + if (get_tcp_flags(argval)) // problem + { + tx.tcp_control=2; // Assume SYN as default + } + } + + if (getarg(tx.arg_string,"tcp_sum", argval)==1) + { + tx.tcp_sum = (u_int16_t) str2int(argval); + } + + // Check if hex_payload already specified (externally) + if (tx.hex_payload_s) + { + memcpy( (void*) tx.tcp_payload, (void*) tx.hex_payload, tx.hex_payload_s); + tx.tcp_payload_s = tx.hex_payload_s; + } + + + if ( (getarg(tx.arg_string,"payload", argval)==1) || (getarg(tx.arg_string,"p", argval)==1)) + { + tx.tcp_payload_s = str2hex (argval, tx.tcp_payload, MAX_PAYLOAD_SIZE); + } + + + if (tx.ascii) // ASCII PAYLOAD overrides hex payload + { + strncpy((char *)tx.tcp_payload, (char *)tx.ascii_payload, MAX_PAYLOAD_SIZE); + tx.tcp_payload_s = strlen((char *)tx.ascii_payload); + tx.tcp_len = 20 + tx.tcp_payload_s; // only needed by libnet to calculate checksum + tx.ip_payload_s = tx.tcp_len; // for create_ip_packet + } + + + + ///////// + // Want some padding? The specified number of padding bytes are ADDED to the + // payload. + // (Note the difference in send_eth() where you specified the total number + // of bytes in the frame) + // + if (tx.padding) + { + for (i=0; i