2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008 Herbert Haas
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.
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
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 // This section contains functions to send an arbitrary byte stream out of
24 // the network card. Currently it works perfect for Ethernet cards.
26 // TODO: Access to the 802.11 header
28 // ****************************************************************************
36 // 1. Check 'eth_src_txt' and 'eth_dst_txt' which contain either a MAC address or a keyword
37 // 'eth_dst' can be set without having 'eth_src_txt' specified (the next 6 bytes of the
38 // 'arg_string' will be used). But if 'eth_src_txt' is given then also 'eth_dst_txt'
39 // should have been specified, otherwise a default (ff-ff-ff-ff-ff-ff) will be used.
40 // 2. Check whether 'arg_string' contains a hex-string. If YES then convert it into an
41 // 'eth_payload' and extract eth_type.
42 // 3. Apply 'padding' if specified
43 // 4. Check if frame has at least minimum length (14 Bytes).
44 // 5. Send frame 'count' times and
45 // 6. Apply 'delay' (make precautions for better delay functions)
48 src
, // flag telling whether user has specified a source address
49 dst
, // flag telling whether user has specified a destination address
60 err_buf
[LIBNET_ERRBUF_SIZE
],
61 message
[MAX_PAYLOAD_SIZE
*3],
62 argval
[MAX_PAYLOAD_SIZE
*2];
64 u_int8_t bytestring
[MAX_PAYLOAD_SIZE
];
72 fprintf(stderr
," Note: raw layer 2 mode does not support 802.1Q builder.\n"
73 " If you want to create VLAN tags then you must do it by hand.\n");
79 fprintf(stderr
," Note: raw layer 2 mode does not support MPLS builder.\n"
80 " If you want to create MPLS labels then you must do it by hand.\n");
87 // So other functions can use this function for sending Ethernet frames
88 // These other functions must set dst, src, type and payload!
89 if (tx
.eth_params_already_set
) goto ALL_SPECIFIED
;
92 if ((tx
.padding
) && (tx
.padding
<15)) // Note: ignored if padding==0
96 cli_print(gcli
, "Note: Set padding to 15 bytes (total length)\n");
98 fprintf(stderr
, " mz/send_eth: [Note] adjusted minimum frame size to 15 bytes.\n");
101 // Create a temporal, local bytestring:
103 for (i
=0; i
<MAX_PAYLOAD_SIZE
; i
++) bytestring
[i
]=0x00;
104 if ( (getarg(tx
.arg_string
,"payload", argval
)==1) || (getarg(tx
.arg_string
,"p", argval
)==1))
106 bytestring_s
= str2hex (argval
, bytestring
, MAX_PAYLOAD_SIZE
);
109 // Set the flags to shorten subsequent decisions:
110 src
= strlen(tx
.eth_src_txt
);
111 dst
= strlen(tx
.eth_dst_txt
);
114 // IN ANY CASE if src has been specified:
118 // Evaluate Ethernet CLI options (-a and -b)
119 if (check_eth_mac_txt(ETH_SRC
)) // if true then problem!
121 // use own (already set in init.c)
123 src_random
= tx
.eth_src_rand
; // local vars are faster
126 // IN ANY CASE if dst has been specified:
130 // Evaluate Ethernet CLI options (-a and -b)
131 if (check_eth_mac_txt(ETH_DST
)) // if true then problem!
133 str2hex("ff:ff:ff:ff:ff:ff",tx
.eth_dst
, 6); // the default
135 dst_random
= tx
.eth_dst_rand
; // local vars are faster
139 // Catch errors with too short bytestrings:
143 // bytestring only needs to contain eth_type
148 // bytstring must contain src and type
151 if (bytestring_s
< min_size
)
153 j
= min_size
- bytestring_s
; // this is what's missing
154 bytestring_s
+= j
; // note that bytestring has been filled up with 0x00, so we can do that
158 // ADDENDUM: If src specified, dst missing:
160 if ( (!dst
) && (src
) )
162 str2hex_mac ("ff:ff:ff:ff:ff:ff", tx
.eth_dst
);
167 // ADDENDUM: If dst specified, src missing:
171 // Get eth_src from bytestring:
172 if (bytestring_s
>=6) {
173 (void) getbytes (bytestring
, tx
.eth_src
, byte_ptr
, byte_ptr
+5);
174 byte_ptr
=7; // now points to eth_type within bytestring
178 // FINALLY: If both dst and src have NOT been specified:
180 if ((!dst
) && (!src
))
182 if (bytestring_s
>=6) {
183 (void) getbytes (bytestring
, tx
.eth_dst
, byte_ptr
, byte_ptr
+5);
187 if (bytestring_s
>=12) {
188 (void) getbytes (bytestring
, tx
.eth_src
, byte_ptr
, byte_ptr
+5);
189 byte_ptr
=13; // points to eth_type
195 if (bytestring_s
>=2) {
196 tx
.eth_type
= 256 * bytestring
[byte_ptr
-1] + bytestring
[byte_ptr
]; // don't forget: byte_ptr counts from 1 not 0
197 byte_ptr
+=2; // points to first payload byte (if available)
201 // Get remaining payload:
203 if ( (tx
.eth_payload_s
= bytestring_s
- byte_ptr
+1) > 0 ) // if there are any remaining bytes
205 (void) getbytes (bytestring
, tx
.eth_payload
, byte_ptr
, bytestring_s
);
210 // Add padding if desired.
211 // Note: padding means 'extend to given length' (not 'add these number of bytes')
214 pad
= tx
.padding
- (14 + tx
.eth_payload_s
); // number of additonal pad bytes required
215 for (i
=0; i
<pad
; i
++)
217 // tx.eth_payload[i+tx.eth_payload_s] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
218 tx
.eth_payload
[i
+tx
.eth_payload_s
] = 0x00;
220 tx
.eth_payload_s
+= pad
;
226 // *** All Ethernet parameters have been determined !
227 // *** Now let's send the frame!
229 l
= libnet_init (LIBNET_LINK_ADV
, tx
.device
, err_buf
);
233 fprintf(stderr
, " mz/send_eth: libnet_init() failed (%s)", err_buf
);
243 fprintf(stderr
, " mz: !!! Infinite mode! Will send frames until you stop Mausezahn!!!\n");
248 if ( (!quiet
) && (!tx
.delay
) && (tx
.count
==0) )
249 fprintf(stderr
, " mz: !!! Will send at maximum frame rate without feedback!!!\n");
254 // this is for the statistics:
260 if (tx
.count
!=0) repeat
=0; // count=0 means repeat ad inifinitum
262 for (i
=0; i
<loop
; i
++)
266 tx
.eth_src
[0] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256) & 0xFE;
267 tx
.eth_src
[1] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
268 tx
.eth_src
[2] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
269 tx
.eth_src
[3] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
270 tx
.eth_src
[4] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
271 tx
.eth_src
[5] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
277 tx
.eth_dst
[0] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
278 tx
.eth_dst
[1] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
279 tx
.eth_dst
[2] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
280 tx
.eth_dst
[3] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
281 tx
.eth_dst
[4] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
282 tx
.eth_dst
[5] = (u_int8_t
) ( ((float) rand()/RAND_MAX
)*256);
286 if (update
) // new frame parameters
288 t
= libnet_build_ethernet (tx
.eth_dst
,
298 fprintf(stderr
, " mz/send_eth: %s", libnet_geterror(l
));
304 bs2str (tx
.eth_dst
, message
, 6); // DA
305 fprintf(stderr
, " mz: send %s",message
);
307 bs2str (tx
.eth_src
, message
, 6); // SA
308 fprintf(stderr
, " %s",message
);
310 type2str(tx
.eth_type
, message
);
311 fprintf(stderr
, " %s",message
); // Type
313 bs2str (tx
.eth_payload
, message
, tx
.eth_payload_s
); // Payload
314 fprintf(stderr
, " %s\n",message
);
319 fprintf(stderr
, "\n");
320 fprintf(stderr
, "*** NOTE: Simulation only! Nothing has been sent! ***\n");
333 if ( (verbose
) && (!src_random
) && (!dst_random
) )
335 fprintf(stderr
, ".");
345 if ((tx
.delay
) || (tx
.count
==0))
347 fprintf(stderr
,"\n");
350 fprintf(stderr
, " mz: sent %u frames.\n",loop
);
363 // ==========================================================================================
368 fprintf(stderr," mz/send_bytes: \n");
370 fprintf(stderr," DA = %s", dast);
372 fprintf(stderr," SA = %s", sast);
373 fprintf(stderr," type = %x",et);
374 bs2str(payload,pl,payload_s);
375 fprintf(stderr," data = %s\n",pl);