/* * 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; int udp_sum_set = 0; ///////////////////////////// // 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); udp_sum_set = 1; } 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