ifpps: use uint32_t instead of u32
[netsniff-ng.git] / staging / layer4.c
blob8ccf80c1be26b66884bfd751bcf81ff616331e24
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
21 ////////////////////////////////////////////////////////////////////
23 // Layer 4 packet types
24 //
25 // 1. UDP
26 // 2. ICMP
27 // 3. TCP
28 //
29 ////////////////////////////////////////////////////////////////////
31 #include "mz.h"
32 #include "cli.h"
35 #define MZ_UDP_HELP \
36 "| UDP type: Send raw UDP packets.\n" \
37 "|\n" \
38 "| Parameters: \n" \
39 "|\n" \
40 "| sp 0-65535\n" \
41 "| dp 0-65535\n" \
42 "| len 0-65535\n" \
43 "| udp_sum 0-65535\n" \
44 "| payload|p <hex payload>\n" \
45 "|\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" \
48 "|\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" \
51 "|\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" \
55 "|\n" \
56 "\n"
59 #define MZ_ICMP_HELP \
60 "| ICMP type: Send raw ICMP packets.\n" \
61 "|\n" \
62 "| ARGUMENT SYNTAX: [type] <optional parameters> \n" \
63 "| \n" \
64 "| Per default an echo reply is sent (type=0, code=0)\n" \
65 "|\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" \
71 "|\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" \
74 "| IP address.\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" \
82 "| yourself.\n" \
83 "|\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" \
92 "|\n" \
93 "|\n" \
94 "| (other ICMP types will follow)\n" \
95 "|\n" \
96 "\n"
98 #define MZ_ICMP6_HELP \
99 "| ICMPv6 type: Send raw ICMPv6 packets.\n" \
100 "|\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" \
108 "\n"
110 #define MZ_TCP_HELP \
111 "| TCP type: Send raw TCP packets.\n" \
112 "|\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" \
123 "|\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" \
126 "|\n" \
127 "| Also the sequence number can be specified as a range, for example:\n" \
128 "|\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" \
133 "|\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"\
137 "|\n"
139 #define MZ_IGMP_HELP \
140 "| IGMP type: Send raw IGMP packets.\n" \
141 "|\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" \
152 "\n"
154 int print_packet_help(char *help)
156 if (mz_port) {
157 cli_print(gcli, "%s", help);
158 } else {
159 fprintf(stderr,"\n" MAUSEZAHN_VERSION "\n%s", help);
160 exit(0);
163 return -1;
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)
170 libnet_ptag_t t;
171 char argval[MAX_PAYLOAD_SIZE];
172 int T; // only an abbreviation for tx.packet_mode
173 int i;
174 int udp_sum_set = 0;
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) )
185 if (mz_port)
187 cli_print(gcli, "%s", MZ_UDP_HELP);
188 return -1;
190 else
193 fprintf(stderr,"\n"
194 MAUSEZAHN_VERSION
195 "\n%s", MZ_UDP_HELP);
197 exit(0);
203 // Evaluate CLI parameters:
205 if (getarg(tx.arg_string,"dp", argval)==1)
207 if (get_port_range (DST_PORT, argval)) // problem
209 tx.dp = 0;
213 if (getarg(tx.arg_string,"sp", argval)==1)
215 if (get_port_range (SRC_PORT, argval)) // problem
217 tx.sp = 0;
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);
245 udp_sum_set = 1;
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);
257 /////////
258 // Want some padding? The specified number of padding bytes are ADDED to the
259 // payload.
260 // (Note the difference in send_eth() where you specified the total number
261 // of bytes in the frame)
263 if (tx.padding)
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;
274 ////////
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,
298 tx.dp,
299 tx.udp_len,
300 tx.udp_sum,
301 (tx.udp_payload_s) ? tx.udp_payload : NULL,
302 tx.udp_payload_s,
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);
309 if (t == -1)
311 fprintf(stderr, " mz/create_udp_packet: Can't build UDP header: %s\n", libnet_geterror(l));
312 exit (0);
317 return t;
328 ///////////////////////////////////////////////////
329 ///////////////////////////////////////////////////
330 ///////////////////////////////////////////////////
331 ///////////////////////////////////////////////////
332 ///////////////////////////////////////////////////
336 libnet_ptag_t create_icmp_packet (libnet_t *l)
339 libnet_ptag_t t;
340 char argval[MAX_PAYLOAD_SIZE];
341 unsigned char *x;
343 int i;
345 enum
347 NONE,
348 ECHO_REQUEST,
349 REDIRECT,
350 UNREACHABLE
352 icmp; // which ICMP Type?
355 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==ICMP) )
357 if (mz_port)
359 cli_print(gcli, "%s", MZ_ICMP_HELP);
360 return -1;
362 else
365 fprintf(stderr,"\n"
366 MAUSEZAHN_VERSION
367 "\n%s", MZ_ICMP_HELP);
368 exit(0);
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) )
382 icmp = REDIRECT;
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) )
390 icmp = ECHO_REQUEST;
391 tx.icmp_type = ICMP_ECHO;
392 tx.icmp_code = 0;
396 if (getarg(tx.arg_string,"unreach", NULL)==1)
398 icmp = UNREACHABLE;
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);
418 else
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);
433 else
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);
462 else
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);
475 /////////
476 // Want some padding? The specified number of padding bytes are ADDED to the
477 // payload.
478 // (Note the difference in send_eth() where you specified the total number
479 // of bytes in the frame)
481 if (tx.padding)
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 ////////////////////////////////////////////////////////////////////////////////////////////
503 switch (icmp)
505 case REDIRECT: // +++++++++++++++
506 t = libnet_build_icmpv4_redirect (tx.icmp_type,
507 tx.icmp_code,
508 tx.icmp_chksum,
509 tx.icmp_gateway,
510 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
511 tx.icmp_payload_s,
514 tx.ip_payload_s = LIBNET_ICMPV4_REDIRECT_H + tx.icmp_payload_s; // for send_ip
515 if (verbose)
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; // ++++++++++++++++++++++
522 case NONE:
523 case ECHO_REQUEST:
524 t = libnet_build_icmpv4_echo(tx.icmp_type,
525 tx.icmp_code,
526 tx.icmp_chksum,
527 tx.icmp_ident,
528 tx.icmp_sqnr,
529 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
530 tx.icmp_payload_s,
533 tx.ip_payload_s = LIBNET_ICMPV4_REDIRECT_H + tx.icmp_payload_s; // for send_ip
534 if (verbose)
536 if (icmp == NONE)
537 sprintf(tx.icmp_verbose_txt,"ICMP Type %u Code %u\n",tx.icmp_type,tx.icmp_code);
538 else
539 sprintf(tx.icmp_verbose_txt,"ICMP Echo Request (id=%u seq=%u)\n",tx.icmp_ident,tx.icmp_sqnr);
541 break; // ++++++++++++++++++++++
542 case UNREACHABLE:
543 t = libnet_build_icmpv4_unreach(tx.icmp_type,
544 tx.icmp_code,
545 tx.icmp_chksum,
546 (tx.icmp_payload_s) ? tx.icmp_payload : NULL,
547 tx.icmp_payload_s,
550 if (verbose)
552 sprintf(tx.icmp_verbose_txt,"ICMP unreachable (code=%u)\n",tx.icmp_code);
554 break; // ++++++++++++++++++++++
555 default:
556 (void) fprintf(stderr," mz/icmp: unknown mode! Stop.\n");
557 return (1);
560 libnet_toggle_checksum(l, t, tx.icmp_chksum ? LIBNET_OFF : LIBNET_ON);
562 if (t == -1)
564 fprintf(stderr, " mz/create_icmp_packet: Can't build ICMP header: %s\n", libnet_geterror(l));
565 exit (0);
569 return t;
572 libnet_ptag_t create_icmp6_packet (libnet_t *l)
574 libnet_ptag_t t;
575 char argval[MAX_PAYLOAD_SIZE];
577 int i;
578 tx.icmp_ident = 0;
579 tx.icmp_sqnr = 0;
581 if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==ICMP) )
583 if (mz_port)
585 cli_print(gcli, "%s", MZ_ICMP6_HELP);
586 return -1;
588 else
590 fprintf(stderr,"\n"
591 MAUSEZAHN_VERSION
592 "\n%s", MZ_ICMP6_HELP);
593 exit(0);
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);
639 else
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);
650 /////////
651 // Want some padding? The specified number of padding bytes are ADDED to the
652 // payload.
653 // (Note the difference in send_eth() where you specified the total number
654 // of bytes in the frame)
656 if (tx.padding)
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,
668 tx.icmp_code,
669 tx.icmp_chksum,
670 tx.icmp_ident,
671 tx.icmp_sqnr,
672 tx.icmp_payload_s ? tx.icmp_payload : NULL,
673 tx.icmp_payload_s,
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);
681 if (t == -1)
683 fprintf(stderr, " mz/create_icmp_packet: Can't build ICMPv6 header: %s\n", libnet_geterror(l));
684 exit (0);
687 return t;
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)
703 libnet_ptag_t t, t2;
704 char argval[MAX_PAYLOAD_SIZE], *dummy1, *dummy2;
705 int T; // only an abbreviation for tx.packet_mode
706 int i;
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
713 0x01, // NOP
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) )
728 if (mz_port)
730 cli_print(gcli, "%s", MZ_TCP_HELP);
731 return -1;
733 else
735 fprintf(stderr,"\n"
736 MAUSEZAHN_VERSION
737 "\n%s", MZ_TCP_HELP);
738 exit(0);
743 // Evaluate CLI parameters:
745 if (getarg(tx.arg_string,"dp", argval)==1)
747 if (get_port_range (DST_PORT, argval)) // problem
749 tx.dp = 0;
754 if (getarg(tx.arg_string,"sp", argval)==1)
756 if (get_port_range (SRC_PORT, argval)) // problem
758 tx.sp = 0;
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;
772 else // range
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
839 /////////
840 // Want some padding? The specified number of padding bytes are ADDED to the
841 // payload.
842 // (Note the difference in send_eth() where you specified the total number
843 // of bytes in the frame)
845 if (tx.padding)
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,
863 20,
867 if (t2 == -1)
869 fprintf(stderr, " mz/create_tcp_packet: Can't build TCP options: %s\n", libnet_geterror(l));
870 exit (0);
873 tx.tcp_len += 20;
874 tx.tcp_offset = 10;
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);
878 else
880 tx.tcp_offset = 5;
881 tx.tcp_sum_part = 0;
884 t = libnet_build_tcp (tx.sp,
885 tx.dp,
886 tx.tcp_seq,
887 tx.tcp_ack,
888 tx.tcp_control,
889 tx.tcp_win,
890 tx.tcp_sum,
891 tx.tcp_urg,
892 tx.tcp_len,
893 (tx.tcp_payload_s) ? tx.tcp_payload : NULL,
894 tx.tcp_payload_s,
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);
903 if (t == -1)
905 fprintf(stderr, " mz/create_tcp_packet: Can't build TCP header: %s\n", libnet_geterror(l));
906 exit (0);
910 return t;
913 libnet_ptag_t create_igmp_packet(libnet_t *l)
915 libnet_ptag_t t;
916 char argval[MAX_PAYLOAD_SIZE];
917 int ver = 2;
918 uint8_t type = IGMP_MEMBERSHIP_QUERY;
919 uint8_t resp_time = 10;
920 uint16_t sum = 0;
921 uint32_t group = 0;
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);
930 if (ver == 1)
931 resp_time = 0;
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) {
939 if (ver == 1)
940 type = IGMP_V1_MEMBERSHIP_REPORT;
941 else if (ver == 2)
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)
969 tx.ip_dst = group;
970 } else if (type == IGMP_V1_MEMBERSHIP_REPORT ||
971 type == IGMP_V2_MEMBERSHIP_REPORT) {
973 tx.ip_dst = group;
976 if (getarg(tx.arg_string, "ttl", argval) == 0)
977 tx.ip_ttl = 1;
979 t = libnet_build_igmp(type, resp_time, sum, group, NULL, 0, l, 0);
980 if (t == -1) {
981 fprintf(stderr, " mz/create_igmp_packet: Can't build IGMP header: %s\n",
982 libnet_geterror(l));
983 exit (0);
986 return t;