diff options
Diffstat (limited to 'staging/modifications.c')
-rw-r--r-- | staging/modifications.c | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/staging/modifications.c b/staging/modifications.c new file mode 100644 index 0000000..3dc2abf --- /dev/null +++ b/staging/modifications.c @@ -0,0 +1,698 @@ +/* + * 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 + * +*/ + + + + +// *************************************************************************** +// +// This sections contains functions to manipulate headers of +// Eth, MPLS, 802.1Q, IP, UDP, and TCP: +// +// int update_Eth_SA (libnet_t *l, libnet_ptag_t t) +// int update_IP_SA (libnet_t *l, libnet_ptag_t t) +// int update_IP_DA (libnet_t *l, libnet_ptag_t t) +// int update_DPORT (libnet_t *l, libnet_ptag_t t) +// int update_SPORT (libnet_t *l, libnet_ptag_t t) +// int update_TCP_SQNR (libnet_t *l, libnet_ptag_t t) +// +// and finally: +// +// int print_frame_details() +// +// *************************************************************************** + +#include "mz.h" +#include "mops.h" + +/////////////////////////////////////////////////////////////////////////// +// Applies another random Ethernet source address to a given Ethernet-PTAG. +// (The calling function should check 'tx.eth_src_rand' whether the SA +// should be randomized.) +// +int update_Eth_SA(libnet_t *l, libnet_ptag_t t) +{ + tx.eth_src[0] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256) & 0xFE; // keeps bcast-bit zero + tx.eth_src[1] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256); + tx.eth_src[2] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256); + tx.eth_src[3] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256); + tx.eth_src[4] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256); + tx.eth_src[5] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256); + + t = libnet_build_ethernet (tx.eth_dst, + tx.eth_src, + tx.eth_type, + NULL, // the payload + 0, + l, + t); + + if (t == -1) + { + fprintf(stderr, " mz/update_Eth_SA: Can't build Ethernet header: %s\n", + libnet_geterror(l)); + exit(EXIT_FAILURE); + } + + return 0; +} + + +// Update official timestamp, own timestamp and sequence number in the RTP header. +// The actual RTP message is stored in tx.udp_payload. +int update_RTP(libnet_t *l, libnet_ptag_t t) +{ + u_int8_t *ptr; + struct mz_timestamp ts; + + tx.rtp_sqnr++; + tx.rtp_stmp+=160; // TODO: different values for different codecs + + // update SQNR + ptr = (u_int8_t*) &tx.rtp_sqnr; + tx.udp_payload[2] = *(ptr+1); + tx.udp_payload[3] = *ptr; + + // update official timestamp + ptr = (u_int8_t*) &tx.rtp_stmp; + tx.udp_payload[4] = *(ptr+3); + tx.udp_payload[5] = *(ptr+2); + tx.udp_payload[6] = *(ptr+1); + tx.udp_payload[7] = *ptr; + + + // update own timestamp + getcurtime(&ts); // Now add TX timestamp: + mops_hton4 ((u_int32_t*) &ts.sec, &tx.udp_payload[16]); + mops_hton4 ((u_int32_t*) &ts.nsec, &tx.udp_payload[20]); + + t = libnet_build_udp(tx.sp, + tx.dp, + tx.udp_len, + tx.udp_sum, + tx.udp_payload, + tx.udp_payload_s, + l, + t); + + if (t == -1) { + fprintf(stderr," mz/send_frame: RTP header update failed!\n"); + exit (1); + } + return 0; +} + + +/////////////////////////////////////////////////////////////////////////// +// Applies another SOURCE IP address, +// - either a random one (tx.ip_src_rand==1) +// - or from a specified range (tx.ip_src_isrange==1) +// to a given IP-PTAG. +// +// Note: tx.ip_src MUST be already initialized with tx.ip_src_start. +// This is done by 'get_ip_range_src()' in tools.c. +// +// +// RETURNS '1' if tx.ip_src restarts +// +int update_IP_SA (libnet_t *l, libnet_ptag_t t) +{ + u_int8_t *x, *y; + int i=0; + + if (tx.ip_src_rand) + { + tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0 + i=1; + } + else if (tx.ip_src_isrange) + { + tx.ip_src_h++; + if (tx.ip_src_h > tx.ip_src_stop) // reached the end of the range => restart! + { + tx.ip_src_h = tx.ip_src_start; + i=1; + } + } + + // Now convert "tx.ip_src_h" into "tx.ip_src" which is in 'Network Byte Order': + x = (unsigned char*) &tx.ip_src_h; + y = (unsigned char*) &tx.ip_src; + + *y = *(x+3); + y++; + *y = *(x+2); + y++; + *y = *(x+1); + y++; + *y = *x; + + // TODO: Omit certain IP addresses: + // E.g. if (rand_ip == tx.ip_src) goto rand_again; // never use true interface IP + // TODO: Check other address exceptions ... + + t = libnet_build_ipv4 (tx.ip_len, + tx.ip_tos, + tx.ip_id, + tx.ip_frag, + tx.ip_ttl, + tx.ip_proto, + tx.ip_sum, + tx.ip_src, // possibly now random + tx.ip_dst, + (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL, // if e.g. mode=UDP ignore payload argument + (mode==IP) ? tx.ip_payload_s : 0, + l, + t); + + if (t == -1) + { + fprintf(stderr," mz/update_IP_SA: IP address manipulation failed!\n"); + exit (1); + } + + return i; +} + + + + +///////////////////////////////////////////////////////////////////////////////////////// +// Applies another DESTINATION IP address from a specified range (tx.ip_dst_isrange==1) +// to a given IP-PTAG. +// +// Note: tx.ip_dst MUST be already initialized with tx.ip_dst_start. +// tx.ip_dst_h 'mirrors' tx.ip_dst +// (i. e. tx.ip_dst_h is NOT in network byte order => easy to count) +// This is done by 'get_ip_range_dst()' in tools.c. +// +// RETURN VALUE: '1' if tx.ip_dst restarts +// +int update_IP_DA(libnet_t *l, libnet_ptag_t t) +{ + u_int8_t *x, *y; + int i=0; + + + if (tx.ip_dst_isrange) + { + tx.ip_dst_h++; + if (tx.ip_dst_h > tx.ip_dst_stop) // we reached the end of the range => restart! + { + tx.ip_dst_h = tx.ip_dst_start; + i=1; + } + } + + + // Now convert "tx.ip_dst_h" into "tx.ip_dst" which is in 'Network Byte Order': + + x = (unsigned char*) &tx.ip_dst_h; + y = (unsigned char*) &tx.ip_dst; + + *y = *(x+3); + y++; + *y = *(x+2); + y++; + *y = *(x+1); + y++; + *y = *x; + + + // TODO: Omit certain IP addresses: + // E.g. if (rand_ip == tx.ip_src) goto rand_again; // never use true interface IP + // TODO: Check other address exceptions ... + + t = libnet_build_ipv4 (tx.ip_len, + tx.ip_tos, + tx.ip_id, + tx.ip_frag, + tx.ip_ttl, + tx.ip_proto, + tx.ip_sum, + tx.ip_src, + tx.ip_dst, + (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL, // if e.g. mode=UDP ignore payload argument + (mode==IP) ? tx.ip_payload_s : 0, + l, + t); + + if (t == -1) + { + fprintf(stderr," mz/update_IP_DA: IP address manipulation failed!\n"); + exit (1); + } + + return i; +} + + + + +/////////////////////////////////////////////////////////////////////////////////////// +// +// Applies another DESTINATION PORT from a specified range to a given UDP- or TCP-PTAG. +// +// Note: tx.dp MUST be already initialized with tx.dp_start +// This is done by 'get_port_range()' in tools.c. +// +// RETURN VALUE: '1' if tx.dp restarts +// +int update_DPORT(libnet_t *l, libnet_ptag_t t) +{ + // u_int32_t DP; + int i=0; + + // DP = (u_int32_t) tx.dp; + // DP++; + tx.dp++; + + + // Exceeded range => restart: + if ((tx.dp > tx.dp_stop) || // we exceeded the end of the range + (tx.dp == 65535) ) // or exceeded the 16-bit range + { + tx.dp = tx.dp_start; + i=1; + } + + + if (mode==UDP) + { + t = libnet_build_udp(tx.sp, + tx.dp, + tx.udp_len, + tx.udp_sum, + (tx.udp_payload_s) ? tx.udp_payload : NULL, + tx.udp_payload_s, + l, + t); + + if (t == -1) + { + fprintf(stderr," mz/send_frame: UDP header manipulation failed!\n"); + exit (1); + } + } + else // TCP + { + t = libnet_build_tcp (tx.sp, + tx.dp, + tx.tcp_seq, + tx.tcp_ack, + tx.tcp_control, + tx.tcp_win, + tx.tcp_sum, + tx.tcp_urg, + tx.tcp_len, + (tx.tcp_payload_s) ? tx.tcp_payload : NULL, + tx.tcp_payload_s, + l, + t); + + if (t == -1) + { + fprintf(stderr, " mz/update_DPORT: Can't build TCP header: %s\n", libnet_geterror(l)); + exit (0); + } + } + + return i; +} + + +/////////////////////////////////////////////////////////////////////////////////// +// +// Applies another SOURCE PORT from a specified range to a given UDP- or TCP-PTAG. +// +// Note: tx.sp MUST be already initialized with tx.sp_start +// This is done by 'get_port_range()' in tools.c. +// +// RETURN VALUE: '1' if tx.sp restarts +// +int update_SPORT(libnet_t *l, libnet_ptag_t t) +{ + +// u_int32_t SP; + int i=0; + +// SP = (u_int32_t) tx.sp; +// SP++; + tx.sp++; + + + // Exceeded range => restart: + if ((tx.sp > tx.sp_stop) || // we exceeded the end of the range + (tx.sp == 65535) ) // or exceeded the 16-bit range + { + tx.sp = tx.sp_start; + i=1; + } + + if (mode==UDP) + { + t = libnet_build_udp(tx.sp, + tx.dp, + tx.udp_len, + tx.udp_sum, + (tx.udp_payload_s) ? tx.udp_payload : NULL, + tx.udp_payload_s, + l, + t); + + if (t == -1) + { + fprintf(stderr," mz/send_frame: UDP header manipulation failed!\n"); + exit (1); + } + } + else // TCP + { + t = libnet_build_tcp (tx.sp, + tx.dp, + tx.tcp_seq, + tx.tcp_ack, + tx.tcp_control, + tx.tcp_win, + tx.tcp_sum, + tx.tcp_urg, + tx.tcp_len, + (tx.tcp_payload_s) ? tx.tcp_payload : NULL, + tx.tcp_payload_s, + l, + t); + + if (t == -1) + { + fprintf(stderr, " mz/update_DPORT: Can't build TCP header: %s\n", libnet_geterror(l)); + exit (0); + } + } + + return i; +} + +#define LIBNET_CKSUM_CARRY(x) \ + (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff)) + +int update_USUM(libnet_t *l, libnet_ptag_t t) +{ + int sum = 0; + unsigned int tmp; + + if (tx.udp_sum != 0) + return 0; + + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); + if (tx.ip_option_s && tx.ip6_segs) + sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address + else + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); + + tmp = htonl(tx.udp_len); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + tmp = htonl(IPPROTO_UDP); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = ((htons(tx.sp) << 16) + htons(tx.dp)); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = htons(tx.udp_len) << 16; + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + if (tx.udp_payload_s) + sum += libnet_in_cksum((u_int16_t *) tx.udp_payload, tx.udp_payload_s); + + tx.udp_sum = ntohs(LIBNET_CKSUM_CARRY(sum)); + + t = libnet_build_udp(tx.sp, + tx.dp, + tx.udp_len, + tx.udp_sum, + tx.udp_payload_s ? tx.udp_payload : NULL, + tx.udp_payload_s, + l, + t); + return t; +} + +int update_TSUM(libnet_t *l, libnet_ptag_t t) +{ + int sum = 0; + unsigned int tmp; + + if (tx.tcp_sum != 0) + return 0; + + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); + if (tx.ip_option_s && tx.ip6_segs) + sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address + else + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); + + tmp = htonl(tx.tcp_len); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + tmp = htonl(IPPROTO_TCP); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = ((htons(tx.sp) << 16) + htons(tx.dp)); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = htonl(tx.tcp_seq); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + tmp = htonl(tx.tcp_ack); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = ((ntohs(((tx.tcp_offset) << 12) + tx.tcp_control) << 16) + htons(tx.tcp_win)); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = htonl(tx.tcp_urg); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + sum += tx.tcp_sum_part; + + if (tx.tcp_payload_s) + sum += libnet_in_cksum((u_int16_t *) tx.tcp_payload, tx.tcp_payload_s); + + tx.tcp_sum = ntohs(LIBNET_CKSUM_CARRY(sum)); + + t = libnet_build_tcp (tx.sp, + tx.dp, + tx.tcp_seq, + tx.tcp_ack, + tx.tcp_control, + tx.tcp_win, + tx.tcp_sum, + tx.tcp_urg, + tx.tcp_len, + tx.tcp_payload_s ? tx.tcp_payload : NULL, + tx.tcp_payload_s, + l, + t); + + return t; +} + +int update_ISUM(libnet_t *l, libnet_ptag_t t) +{ + int sum = 0; + unsigned int tmp; + + if (tx.icmp_chksum != 0) + return 0; + + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16); + if (tx.ip_option_s && tx.ip6_segs) + sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address + else + sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16); + + tmp = htonl(LIBNET_ICMPV6_H + tx.icmp_payload_s); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + tmp = htonl(IPPROTO_ICMP6); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + tmp = htonl(((tx.icmp_type << 8) + tx.icmp_code)); + sum += libnet_in_cksum((u_int16_t *) &tmp, 4); + + if (tx.icmp_payload_s) + sum += libnet_in_cksum((u_int16_t *) tx.icmp_payload, tx.icmp_payload_s); + + tx.icmp_chksum = ntohs(LIBNET_CKSUM_CARRY(sum)); + + t = libnet_build_icmpv4_echo (tx.icmp_type, + tx.icmp_code, + tx.icmp_chksum, + tx.icmp_ident, + tx.icmp_sqnr, + tx.icmp_payload_s ? tx.icmp_payload : NULL, + tx.icmp_payload_s, + l, + t); + + return t; +} + +/////////////////////////////////////////////////////////////////////// +// +// Applies another TCP SQNR from a specified range to a given TCP-PTAG +// +// RETURN VALUE: '1' if tx.txp_seq restarts +// +int update_TCP_SQNR(libnet_t *l, libnet_ptag_t t) +{ + + u_int32_t diff; + int i=0; + + tx.tcp_seq += tx.tcp_seq_delta; + diff = tx.tcp_seq_stop - tx.tcp_seq_start; + + if (diff < tx.tcp_seq_stop) // start < stop + { + if (tx.tcp_seq > tx.tcp_seq_stop) + { + tx.tcp_seq = tx.tcp_seq_start; + i=1; + } + } + else // stop < start + { + if ( (tx.tcp_seq<tx.tcp_seq_start) && + (tx.tcp_seq>tx.tcp_seq_stop) ) + { + tx.tcp_seq = tx.tcp_seq_start; + i=1; + } + + } + + t = libnet_build_tcp (tx.sp, + tx.dp, + tx.tcp_seq, + tx.tcp_ack, + tx.tcp_control, + tx.tcp_win, + tx.tcp_sum, + tx.tcp_urg, + tx.tcp_len, + (tx.tcp_payload_s) ? tx.tcp_payload : NULL, + tx.tcp_payload_s, + l, + t); + + if (t == -1) + { + fprintf(stderr, " mz/update_TCP_SQNR: Can't build TCP header: %s\n", libnet_geterror(l)); + exit (0); + } + + return i; +} + + +//////////////////////////////////////////////////////////////////////// +// +// + +int print_frame_details() +{ + unsigned char *dum1, *dum2; + char pld[65535]; + char sa[32], da[32]; + + if (!tx.packet_mode) + { + bs2str(tx.eth_dst, da, 6); + bs2str(tx.eth_src, sa, 6); + fprintf(stderr, " Eth: DA = %s, SA = %s\n",da,sa); + } + + + if (tx.dot1Q) + { + fprintf(stderr, " 802.1Q VLAN-TAG = %s\n", tx.dot1Q_txt); + } + + if (tx.mpls) + { + fprintf(stderr," MPLS labels (label:exp:bos:ttl): %s\n",tx.mpls_verbose_string); + + } + + + dum1 = (unsigned char*) &tx.ip_src_h; + dum2 = (unsigned char*) &tx.ip_dst_h; + (mode==IP) ? (void) bs2str(tx.ip_payload, pld, tx.ip_payload_s) : strcpy(pld, "[see next layer]"); + + if (ipv6_mode) { + char src6[64]; char dst6[64]; + libnet_addr2name6_r(tx.ip6_src, LIBNET_DONT_RESOLVE, src6, 64); + libnet_addr2name6_r(tx.ip6_dst, LIBNET_DONT_RESOLVE, dst6, 64); + + fprintf(stderr," IP: ver=6, dscp=%u, flow=%u, len=%u, next=%u, hop=%u " + "SA=%s, DA=%s\n payload=%s\n", tx.ip_tos, tx.ip_flow, + tx.ip_len, tx.ip_proto, tx.ip_ttl, src6, dst6, pld); + } + else { + fprintf(stderr," IP: ver=4, len=%u, tos=%u, id=%u, frag=%u, ttl=%u, proto=%u, sum=%u, " + "SA=%u.%u.%u.%u, DA=%u.%u.%u.%u,\n" + " payload=%s\n", tx.ip_len, tx.ip_tos, + tx.ip_id, tx.ip_frag, tx.ip_ttl, tx.ip_proto, tx.ip_sum, + *(dum1+3),*(dum1+2),*(dum1+1),*(dum1), *(dum2+3),*(dum2+2),*(dum2+1),*(dum2+0), pld); + } + + if ((mode==UDP)||(mode==DNS)||(mode==RTP)) + { + bs2str(tx.udp_payload, pld, tx.udp_payload_s); + fprintf(stderr, " UDP: sp=%u, dp=%u, len=%u, sum=%u, \n" + " payload=%s\n", tx.sp, tx.dp, tx.udp_len, tx.udp_sum, pld); + } + if (mode==TCP) // TODO: Improve message details (flags, ...) + { + bs2str(tx.tcp_payload, pld, tx.tcp_payload_s); + fprintf(stderr, " TCP: sp=%u, dp=%u, S=%u, A=%u, flags=%x, win=%u, len=%u, sum=%u, \n" + " payload=%s\n", + tx.sp, tx.dp, tx.tcp_seq, tx.tcp_ack, tx.tcp_control, tx.tcp_win, tx.tcp_len, tx.tcp_sum, pld); + } + + // send_icmp must prepare the verbose string because there are many + // different types of ICMP packets... + if (mode==ICMP) + { + fprintf(stderr, " %s\n", tx.icmp_verbose_txt); + } + + if (mode==ICMP6) + { + fprintf(stderr, " %s\n", tx.icmp_verbose_txt); + } + + // libnet_diag_dump_pblock(l); + fprintf(stderr,"\n"); + + if (simulate) + { + fprintf(stderr, "*** NOTE: Simulation only! Nothing has been sent! ***\n"); + exit(0); + } + + + return 0; +} + |