mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / staging / modifications.c
blobb105db0c59483ee24fea4784dabb1b951a582f14
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008-2010 Herbert Haas
4 *
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.
8 *
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
12 * details.
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
22 // ***************************************************************************
23 //
24 // This sections contains functions to manipulate headers of
25 // Eth, MPLS, 802.1Q, IP, UDP, and TCP:
26 //
27 // int rand_addr (u_int8_t *addr)
28 // int update_IP_SA (libnet_t *l, libnet_ptag_t t)
29 // int update_IP_DA (libnet_t *l, libnet_ptag_t t)
30 // int update_IP6_SA (libnet_t *l, libnet_ptag_t t)
31 // int update_IP6_DA (libnet_t *l, libnet_ptag_t t)
32 // int update_DPORT (libnet_t *l, libnet_ptag_t t)
33 // int update_SPORT (libnet_t *l, libnet_ptag_t t)
34 // int update_TCP_SQNR (libnet_t *l, libnet_ptag_t t)
35 //
36 // and finally:
37 //
38 // int print_frame_details()
40 // ***************************************************************************
42 #include "mz.h"
43 #include "mops.h"
45 // Applies another random address to a given buffer.
46 // (The calling function should check 'tx.eth_(dst|src)_rand' whether the address
47 // should be randomized.)
48 void rand_addr(u_int8_t *addr)
50 nrand48((unsigned short *)addr);
51 nrand48((unsigned short *)(addr + 3));
53 // Get rid of multicast addresses
54 addr[0] &= 0xfe;
56 // Set the locally administered bit
57 addr[0] |= 2;
61 // Update official timestamp, own timestamp and sequence number in the RTP header.
62 // The actual RTP message is stored in tx.udp_payload.
63 int update_RTP(libnet_t *l, libnet_ptag_t t)
65 u_int8_t *ptr;
66 struct mz_timestamp ts;
68 tx.rtp_sqnr++;
69 tx.rtp_stmp+=160; // TODO: different values for different codecs
71 // update SQNR
72 ptr = (u_int8_t*) &tx.rtp_sqnr;
73 tx.udp_payload[2] = *(ptr+1);
74 tx.udp_payload[3] = *ptr;
76 // update official timestamp
77 ptr = (u_int8_t*) &tx.rtp_stmp;
78 tx.udp_payload[4] = *(ptr+3);
79 tx.udp_payload[5] = *(ptr+2);
80 tx.udp_payload[6] = *(ptr+1);
81 tx.udp_payload[7] = *ptr;
84 // update own timestamp
85 getcurtime(&ts); // Now add TX timestamp:
86 mops_hton4 ((u_int32_t*) &ts.sec, &tx.udp_payload[16]);
87 mops_hton4 ((u_int32_t*) &ts.nsec, &tx.udp_payload[20]);
89 t = libnet_build_udp(tx.sp,
90 tx.dp,
91 tx.udp_len,
92 tx.udp_sum,
93 tx.udp_payload,
94 tx.udp_payload_s,
95 l,
96 t);
98 if (t == -1) {
99 fprintf(stderr," mz/send_frame: RTP header update failed!\n");
100 exit (1);
102 return 0;
106 ///////////////////////////////////////////////////////////////////////////
107 // Applies another SOURCE IP address,
108 // - either a random one (tx.ip_src_rand==1)
109 // - or from a specified range (tx.ip_src_isrange==1)
110 // to a given IP-PTAG.
112 // Note: tx.ip_src MUST be already initialized with tx.ip_src_start.
113 // This is done by 'get_ip_range_src()' in tools.c.
116 // RETURNS '1' if tx.ip_src restarts
118 int update_IP_SA (libnet_t *l, libnet_ptag_t t)
120 u_int8_t *x, *y;
121 int i=0;
123 if (ipv6_mode) {
124 return update_IP6_SA(l, t);
127 if (tx.ip_src_rand)
129 tx.ip_src_h = (u_int32_t) ( ((float) rand()/RAND_MAX)*0xE0000000); //this is 224.0.0.0
130 i=1;
132 else if (tx.ip_src_isrange)
134 tx.ip_src_h++;
135 if (tx.ip_src_h > tx.ip_src_stop) // reached the end of the range => restart!
137 tx.ip_src_h = tx.ip_src_start;
138 i=1;
142 // Now convert "tx.ip_src_h" into "tx.ip_src" which is in 'Network Byte Order':
143 x = (unsigned char*) &tx.ip_src_h;
144 y = (unsigned char*) &tx.ip_src;
146 *y = *(x+3);
147 y++;
148 *y = *(x+2);
149 y++;
150 *y = *(x+1);
151 y++;
152 *y = *x;
154 // TODO: Omit certain IP addresses:
155 // E.g. if (rand_ip == tx.ip_src) goto rand_again; // never use true interface IP
156 // TODO: Check other address exceptions ...
158 t = libnet_build_ipv4 (tx.ip_len,
159 tx.ip_tos,
160 tx.ip_id,
161 tx.ip_frag,
162 tx.ip_ttl,
163 tx.ip_proto,
164 tx.ip_sum,
165 tx.ip_src, // possibly now random
166 tx.ip_dst,
167 (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL, // if e.g. mode=UDP ignore payload argument
168 (mode==IP) ? tx.ip_payload_s : 0,
172 if (t == -1)
174 fprintf(stderr," mz/update_IP_SA: IP address manipulation failed!\n");
175 exit (1);
178 return i;
183 update_IP6_SA(libnet_t *l, libnet_ptag_t t)
185 int i = 0;
186 if (tx.ip_src_rand) {
187 fprintf(stderr, "Random source addresses are not supported in IPv6 mode.\n");
188 exit(1);
189 } else if (tx.ip_src_isrange) {
190 if (incr_in6_addr(tx.ip6_src, &tx.ip6_src)
191 || (in6_addr_cmp(tx.ip6_src, tx.ip6_src_stop) > 0))
193 tx.ip6_src = tx.ip6_src_start;
194 i = 1;
198 t = libnet_build_ipv6(tx.ip_tos,
199 tx.ip_flow,
200 tx.ip_len,
201 tx.ip_proto,
202 tx.ip_ttl,
203 tx.ip6_src,
204 tx.ip6_dst,
205 (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL,
206 (mode==IP) ? tx.ip_payload_s : 0,
210 if (t == -1) {
211 fprintf(stderr," mz/update_IP6_SA: IP address manipulation failed!\n");
212 exit (1);
215 return i;
219 /////////////////////////////////////////////////////////////////////////////////////////
220 // Applies another DESTINATION IP address from a specified range (tx.ip_dst_isrange==1)
221 // to a given IP-PTAG.
223 // Note: tx.ip_dst MUST be already initialized with tx.ip_dst_start.
224 // tx.ip_dst_h 'mirrors' tx.ip_dst
225 // (i. e. tx.ip_dst_h is NOT in network byte order => easy to count)
226 // This is done by 'get_ip_range_dst()' in tools.c.
228 // RETURN VALUE: '1' if tx.ip_dst restarts
230 int update_IP_DA(libnet_t *l, libnet_ptag_t t)
232 u_int8_t *x, *y;
233 int i=0;
235 if (ipv6_mode) {
236 return update_IP6_DA(l, t);
239 if (tx.ip_dst_isrange)
241 tx.ip_dst_h++;
242 if (tx.ip_dst_h > tx.ip_dst_stop) // we reached the end of the range => restart!
244 tx.ip_dst_h = tx.ip_dst_start;
245 i=1;
250 // Now convert "tx.ip_dst_h" into "tx.ip_dst" which is in 'Network Byte Order':
252 x = (unsigned char*) &tx.ip_dst_h;
253 y = (unsigned char*) &tx.ip_dst;
255 *y = *(x+3);
256 y++;
257 *y = *(x+2);
258 y++;
259 *y = *(x+1);
260 y++;
261 *y = *x;
264 // TODO: Omit certain IP addresses:
265 // E.g. if (rand_ip == tx.ip_src) goto rand_again; // never use true interface IP
266 // TODO: Check other address exceptions ...
268 t = libnet_build_ipv4 (tx.ip_len,
269 tx.ip_tos,
270 tx.ip_id,
271 tx.ip_frag,
272 tx.ip_ttl,
273 tx.ip_proto,
274 tx.ip_sum,
275 tx.ip_src,
276 tx.ip_dst,
277 (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL, // if e.g. mode=UDP ignore payload argument
278 (mode==IP) ? tx.ip_payload_s : 0,
282 if (t == -1)
284 fprintf(stderr," mz/update_IP_DA: IP address manipulation failed!\n");
285 exit (1);
288 return i;
293 update_IP6_DA(libnet_t *l, libnet_ptag_t t)
295 int i = 0;
296 if (tx.ip_dst_isrange) {
297 if (incr_in6_addr(tx.ip6_dst, &tx.ip6_dst)
298 || (in6_addr_cmp(tx.ip6_dst, tx.ip6_dst_stop) > 0))
300 tx.ip6_dst = tx.ip6_dst_start;
301 i = 1;
305 t = libnet_build_ipv6(tx.ip_tos,
306 tx.ip_flow,
307 tx.ip_len,
308 tx.ip_proto,
309 tx.ip_ttl,
310 tx.ip6_src,
311 tx.ip6_dst,
312 (mode==IP) ? (tx.ip_payload_s) ? tx.ip_payload : NULL : NULL,
313 (mode==IP) ? tx.ip_payload_s : 0,
317 if (t == -1) {
318 fprintf(stderr," mz/update_IP6_DA: IP address manipulation failed!\n");
319 exit (1);
322 return i;
327 ///////////////////////////////////////////////////////////////////////////////////////
329 // Applies another DESTINATION PORT from a specified range to a given UDP- or TCP-PTAG.
331 // Note: tx.dp MUST be already initialized with tx.dp_start
332 // This is done by 'get_port_range()' in tools.c.
334 // RETURN VALUE: '1' if tx.dp restarts
336 int update_DPORT(libnet_t *l, libnet_ptag_t t)
338 // u_int32_t DP;
339 int i=0;
341 // DP = (u_int32_t) tx.dp;
342 // DP++;
343 tx.dp++;
346 // Exceeded range => restart:
347 if ((tx.dp > tx.dp_stop) || // we exceeded the end of the range
348 (tx.dp == 65535) ) // or exceeded the 16-bit range
350 tx.dp = tx.dp_start;
351 i=1;
355 if (mode==UDP)
357 t = libnet_build_udp(tx.sp,
358 tx.dp,
359 tx.udp_len,
360 tx.udp_sum,
361 (tx.udp_payload_s) ? tx.udp_payload : NULL,
362 tx.udp_payload_s,
366 if (t == -1)
368 fprintf(stderr," mz/send_frame: UDP header manipulation failed!\n");
369 exit (1);
372 else // TCP
374 t = libnet_build_tcp (tx.sp,
375 tx.dp,
376 tx.tcp_seq,
377 tx.tcp_ack,
378 tx.tcp_control,
379 tx.tcp_win,
380 tx.tcp_sum,
381 tx.tcp_urg,
382 tx.tcp_len,
383 (tx.tcp_payload_s) ? tx.tcp_payload : NULL,
384 tx.tcp_payload_s,
388 if (t == -1)
390 fprintf(stderr, " mz/update_DPORT: Can't build TCP header: %s\n", libnet_geterror(l));
391 exit (0);
395 return i;
399 ///////////////////////////////////////////////////////////////////////////////////
401 // Applies another SOURCE PORT from a specified range to a given UDP- or TCP-PTAG.
403 // Note: tx.sp MUST be already initialized with tx.sp_start
404 // This is done by 'get_port_range()' in tools.c.
406 // RETURN VALUE: '1' if tx.sp restarts
408 int update_SPORT(libnet_t *l, libnet_ptag_t t)
411 // u_int32_t SP;
412 int i=0;
414 // SP = (u_int32_t) tx.sp;
415 // SP++;
416 tx.sp++;
419 // Exceeded range => restart:
420 if ((tx.sp > tx.sp_stop) || // we exceeded the end of the range
421 (tx.sp == 65535) ) // or exceeded the 16-bit range
423 tx.sp = tx.sp_start;
424 i=1;
427 if (mode==UDP)
429 t = libnet_build_udp(tx.sp,
430 tx.dp,
431 tx.udp_len,
432 tx.udp_sum,
433 (tx.udp_payload_s) ? tx.udp_payload : NULL,
434 tx.udp_payload_s,
438 if (t == -1)
440 fprintf(stderr," mz/send_frame: UDP header manipulation failed!\n");
441 exit (1);
444 else // TCP
446 t = libnet_build_tcp (tx.sp,
447 tx.dp,
448 tx.tcp_seq,
449 tx.tcp_ack,
450 tx.tcp_control,
451 tx.tcp_win,
452 tx.tcp_sum,
453 tx.tcp_urg,
454 tx.tcp_len,
455 (tx.tcp_payload_s) ? tx.tcp_payload : NULL,
456 tx.tcp_payload_s,
460 if (t == -1)
462 fprintf(stderr, " mz/update_SPORT: Can't build TCP header: %s\n", libnet_geterror(l));
463 exit (0);
467 return i;
470 #define LIBNET_CKSUM_CARRY(x) \
471 (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff))
473 int update_USUM(libnet_t *l, libnet_ptag_t t)
475 int sum = 0;
476 unsigned int tmp;
478 if (tx.udp_sum != 0)
479 return 0;
481 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16);
482 if (tx.ip_option_s && tx.ip6_segs)
483 sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address
484 else
485 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16);
487 tmp = htonl(tx.udp_len);
488 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
489 tmp = htonl(IPPROTO_UDP);
490 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
492 tmp = ((htons(tx.sp) << 16) + htons(tx.dp));
493 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
495 tmp = htons(tx.udp_len) << 16;
496 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
498 if (tx.udp_payload_s)
499 sum += libnet_in_cksum((u_int16_t *) tx.udp_payload, tx.udp_payload_s);
501 tx.udp_sum = ntohs(LIBNET_CKSUM_CARRY(sum));
503 t = libnet_build_udp(tx.sp,
504 tx.dp,
505 tx.udp_len,
506 tx.udp_sum,
507 tx.udp_payload_s ? tx.udp_payload : NULL,
508 tx.udp_payload_s,
511 tx.udp_sum = 0;
512 return t;
515 int update_TSUM(libnet_t *l, libnet_ptag_t t)
517 int sum = 0;
518 unsigned int tmp;
520 if (tx.tcp_sum != 0)
521 return 0;
523 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16);
524 if (tx.ip_option_s && tx.ip6_segs)
525 sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address
526 else
527 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16);
529 tmp = htonl(tx.tcp_len);
530 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
531 tmp = htonl(IPPROTO_TCP);
532 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
534 tmp = ((htons(tx.sp) << 16) + htons(tx.dp));
535 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
537 tmp = htonl(tx.tcp_seq);
538 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
539 tmp = htonl(tx.tcp_ack);
540 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
542 tmp = ((ntohs(((tx.tcp_offset) << 12) + tx.tcp_control) << 16) + htons(tx.tcp_win));
543 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
545 tmp = htonl(tx.tcp_urg);
546 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
548 sum += tx.tcp_sum_part;
550 if (tx.tcp_payload_s)
551 sum += libnet_in_cksum((u_int16_t *) tx.tcp_payload, tx.tcp_payload_s);
553 tx.tcp_sum = ntohs(LIBNET_CKSUM_CARRY(sum));
555 t = libnet_build_tcp (tx.sp,
556 tx.dp,
557 tx.tcp_seq,
558 tx.tcp_ack,
559 tx.tcp_control,
560 tx.tcp_win,
561 tx.tcp_sum,
562 tx.tcp_urg,
563 tx.tcp_len,
564 tx.tcp_payload_s ? tx.tcp_payload : NULL,
565 tx.tcp_payload_s,
568 tx.tcp_sum = 0;
570 return t;
573 int update_ISUM(libnet_t *l, libnet_ptag_t t)
575 int sum = 0;
576 unsigned int tmp;
578 if (tx.icmp_chksum != 0)
579 return 0;
581 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_src, 16);
582 if (tx.ip_option_s && tx.ip6_segs)
583 sum += libnet_in_cksum((u_int16_t *) &tx.ip_option[tx.ip_option_s - 16], 16); // Use last IP address
584 else
585 sum += libnet_in_cksum((u_int16_t *) &tx.ip6_dst, 16);
587 tmp = htonl(LIBNET_ICMPV6_H + tx.icmp_payload_s);
588 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
589 tmp = htonl(IPPROTO_ICMP6);
590 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
592 tmp = htonl(((tx.icmp_type << 8) + tx.icmp_code));
593 sum += libnet_in_cksum((u_int16_t *) &tmp, 4);
595 if (tx.icmp_payload_s)
596 sum += libnet_in_cksum((u_int16_t *) tx.icmp_payload, tx.icmp_payload_s);
598 tx.icmp_chksum = ntohs(LIBNET_CKSUM_CARRY(sum));
600 t = libnet_build_icmpv4_echo (tx.icmp_type,
601 tx.icmp_code,
602 tx.icmp_chksum,
603 tx.icmp_ident,
604 tx.icmp_sqnr,
605 tx.icmp_payload_s ? tx.icmp_payload : NULL,
606 tx.icmp_payload_s,
609 tx.icmp_chksum = 0;
611 return t;
614 ///////////////////////////////////////////////////////////////////////
616 // Applies another TCP SQNR from a specified range to a given TCP-PTAG
618 // RETURN VALUE: '1' if tx.txp_seq restarts
620 int update_TCP_SQNR(libnet_t *l, libnet_ptag_t t)
623 u_int32_t diff;
624 int i=0;
626 tx.tcp_seq += tx.tcp_seq_delta;
627 diff = tx.tcp_seq_stop - tx.tcp_seq_start;
629 if (diff < tx.tcp_seq_stop) // start < stop
631 if (tx.tcp_seq > tx.tcp_seq_stop)
633 tx.tcp_seq = tx.tcp_seq_start;
634 i=1;
637 else // stop < start
639 if ( (tx.tcp_seq<tx.tcp_seq_start) &&
640 (tx.tcp_seq>tx.tcp_seq_stop) )
642 tx.tcp_seq = tx.tcp_seq_start;
643 i=1;
648 t = libnet_build_tcp (tx.sp,
649 tx.dp,
650 tx.tcp_seq,
651 tx.tcp_ack,
652 tx.tcp_control,
653 tx.tcp_win,
654 tx.tcp_sum,
655 tx.tcp_urg,
656 tx.tcp_len,
657 (tx.tcp_payload_s) ? tx.tcp_payload : NULL,
658 tx.tcp_payload_s,
662 if (t == -1)
664 fprintf(stderr, " mz/update_TCP_SQNR: Can't build TCP header: %s\n", libnet_geterror(l));
665 exit (0);
668 return i;
672 ////////////////////////////////////////////////////////////////////////
676 int print_frame_details(void)
678 unsigned char *dum1, *dum2;
679 char pld[65535];
680 char sa[32], da[32];
682 if (!tx.packet_mode)
684 bs2str(tx.eth_dst, da, 6);
685 bs2str(tx.eth_src, sa, 6);
686 fprintf(stderr, " Eth: DA = %s, SA = %s\n",da,sa);
690 if (tx.dot1Q)
692 fprintf(stderr, " 802.1Q VLAN-TAG = %s\n", tx.dot1Q_txt);
695 if (tx.mpls)
697 fprintf(stderr," MPLS labels (label:exp:bos:ttl): %s\n",tx.mpls_verbose_string);
702 dum1 = (unsigned char*) &tx.ip_src_h;
703 dum2 = (unsigned char*) &tx.ip_dst_h;
704 if (mode==IP) {
705 (void) bs2str(tx.ip_payload, pld, tx.ip_payload_s);
706 } else {
707 strcpy(pld, "[see next layer]");
710 if (ipv6_mode) {
711 char src6[64]; char dst6[64];
712 libnet_addr2name6_r(tx.ip6_src, LIBNET_DONT_RESOLVE, src6, 64);
713 libnet_addr2name6_r(tx.ip6_dst, LIBNET_DONT_RESOLVE, dst6, 64);
715 fprintf(stderr," IP: ver=6, dscp=%u, flow=%u, len=%u, next=%u, hop=%u "
716 "SA=%s, DA=%s\n payload=%s\n", tx.ip_tos, tx.ip_flow,
717 tx.ip_len, tx.ip_proto, tx.ip_ttl, src6, dst6, pld);
719 else {
720 fprintf(stderr," IP: ver=4, len=%u, tos=%u, id=%u, frag=%u, ttl=%u, proto=%u, sum=%u, "
721 "SA=%u.%u.%u.%u, DA=%u.%u.%u.%u,\n"
722 " payload=%s\n", tx.ip_len, tx.ip_tos,
723 tx.ip_id, tx.ip_frag, tx.ip_ttl, tx.ip_proto, tx.ip_sum,
724 *(dum1+3),*(dum1+2),*(dum1+1),*(dum1), *(dum2+3),*(dum2+2),*(dum2+1),*(dum2+0), pld);
727 if ((mode==UDP)||(mode==DNS)||(mode==RTP))
729 bs2str(tx.udp_payload, pld, tx.udp_payload_s);
730 fprintf(stderr, " UDP: sp=%u, dp=%u, len=%u, sum=%u, \n"
731 " payload=%s\n", tx.sp, tx.dp, tx.udp_len, tx.udp_sum, pld);
733 if (mode==TCP) // TODO: Improve message details (flags, ...)
735 bs2str(tx.tcp_payload, pld, tx.tcp_payload_s);
736 fprintf(stderr, " TCP: sp=%u, dp=%u, S=%u, A=%u, flags=%x, win=%u, len=%u, sum=%u, \n"
737 " payload=%s\n",
738 tx.sp, tx.dp, tx.tcp_seq, tx.tcp_ack, tx.tcp_control, tx.tcp_win, tx.tcp_len, tx.tcp_sum, pld);
741 // send_icmp must prepare the verbose string because there are many
742 // different types of ICMP packets...
743 if (mode==ICMP)
745 fprintf(stderr, " %s\n", tx.icmp_verbose_txt);
748 if (mode==ICMP6)
750 fprintf(stderr, " %s\n", tx.icmp_verbose_txt);
753 // libnet_diag_dump_pblock(l);
754 fprintf(stderr,"\n");
756 if (simulate)
758 fprintf(stderr, "*** NOTE: Simulation only! Nothing has been sent! ***\n");
759 exit(0);
763 return 0;