mausezahn: use getopt_long instead of getopt
[netsniff-ng.git] / staging / layer1.c
blobecba7fc74c80206e975953a10b40c975cb5f5183
1 /*
2 * Mausezahn - A fast versatile traffic generator
3 * Copyright (C) 2008 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 // ****************************************************************************
22 //
23 // This section contains functions to send an arbitrary byte stream out of
24 // the network card. Currently it works perfect for Ethernet cards.
25 //
26 // TODO: Access to the 802.11 header
27 //
28 // ****************************************************************************
30 #include "mz.h"
31 #include "cli.h"
33 int send_eth(void)
35 // Tasks:
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)
47 int
48 src, // flag telling whether user has specified a source address
49 dst, // flag telling whether user has specified a destination address
50 src_random=0,
51 dst_random=0,
52 byte_ptr=1,
53 bytestring_s=0,
54 min_size=15,
55 pad=0,
56 repeat, loop, update,
57 i=0,
58 j=0;
59 char
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];
65 libnet_ptag_t t;
66 libnet_t *l;
70 if (tx.dot1Q)
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");
74 exit(1);
77 if (tx.mpls)
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");
81 exit(1);
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
94 tx.padding=15;
95 if (mz_port) {
96 cli_print(gcli, "Note: Set padding to 15 bytes (total length)\n");
97 } else
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);
108 else
110 bytestring_s = str2hex (tx.arg_string, bytestring, MAX_PAYLOAD_SIZE);
113 // Set the flags to shorten subsequent decisions:
114 src = strlen(tx.eth_src_txt);
115 dst = strlen(tx.eth_dst_txt);
118 // IN ANY CASE if src has been specified:
120 if (src)
122 // Evaluate Ethernet CLI options (-a and -b)
123 if (check_eth_mac_txt(ETH_SRC)) // if true then problem!
125 // use own (already set in init.c)
127 src_random = tx.eth_src_rand; // local vars are faster
130 // IN ANY CASE if dst has been specified:
132 if (dst)
134 // Evaluate Ethernet CLI options (-a and -b)
135 if (check_eth_mac_txt(ETH_DST)) // if true then problem!
137 str2hex("ff:ff:ff:ff:ff:ff",tx.eth_dst, 6); // the default
139 dst_random = tx.eth_dst_rand; // local vars are faster
143 // Catch errors with too short bytestrings:
145 if (src)
147 // bytestring only needs to contain eth_type
148 min_size-=12;
150 else if (dst)
152 // bytstring must contain src and type
153 min_size-=6;
155 if (bytestring_s < min_size)
157 j = min_size - bytestring_s; // this is what's missing
158 bytestring_s += j; // note that bytestring has been filled up with 0x00, so we can do that
162 // ADDENDUM: If src specified, dst missing:
164 if ( (!dst) && (src) )
166 str2hex_mac ("ff:ff:ff:ff:ff:ff", tx.eth_dst);
171 // ADDENDUM: If dst specified, src missing:
173 if ((dst) && (!src))
175 // Get eth_src from bytestring:
176 if (bytestring_s>=6) {
177 (void) getbytes (bytestring, tx.eth_src, byte_ptr, byte_ptr+5);
178 byte_ptr=7; // now points to eth_type within bytestring
182 // FINALLY: If both dst and src have NOT been specified:
184 if ((!dst) && (!src))
186 if (bytestring_s>=6) {
187 (void) getbytes (bytestring, tx.eth_dst, byte_ptr, byte_ptr+5);
188 byte_ptr=7;
191 if (bytestring_s>=12) {
192 (void) getbytes (bytestring, tx.eth_src, byte_ptr, byte_ptr+5);
193 byte_ptr=13; // points to eth_type
197 // Set eth_type:
199 if (bytestring_s>=2) {
200 tx.eth_type = 256 * bytestring[byte_ptr-1] + bytestring[byte_ptr]; // don't forget: byte_ptr counts from 1 not 0
201 byte_ptr+=2; // points to first payload byte (if available)
205 // Get remaining payload:
207 if ( (tx.eth_payload_s = bytestring_s - byte_ptr +1) > 0 ) // if there are any remaining bytes
209 (void) getbytes (bytestring, tx.eth_payload, byte_ptr, bytestring_s);
214 // Add padding if desired.
215 // Note: padding means 'extend to given length' (not 'add these number of bytes')
216 if (tx.padding)
218 pad = tx.padding - (14 + tx.eth_payload_s); // number of additonal pad bytes required
219 for (i=0; i<pad; i++)
221 // tx.eth_payload[i+tx.eth_payload_s] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
222 tx.eth_payload[i+tx.eth_payload_s] = 0x00;
224 tx.eth_payload_s += pad;
229 ALL_SPECIFIED:
230 // *** All Ethernet parameters have been determined !
231 // *** Now let's send the frame!
233 l = libnet_init (LIBNET_LINK_ADV, tx.device, err_buf );
235 if (l == NULL)
237 fprintf(stderr, " mz/send_eth: libnet_init() failed (%s)", err_buf);
238 return -1;
241 repeat=1;
243 if (tx.count == 0)
245 loop = 1000000;
246 if (!quiet)
247 fprintf(stderr, " mz: !!! Infinite mode! Will send frames until you stop Mausezahn!!!\n");
249 else
250 loop = tx.count;
252 if ( (!quiet) && (!tx.delay) && (tx.count==0) )
253 fprintf(stderr, " mz: !!! Will send at maximum frame rate without feedback!!!\n");
255 t=0;
256 update=1;
258 // this is for the statistics:
259 mz_start = clock();
260 total_d = tx.count;
262 while (repeat)
264 if (tx.count!=0) repeat=0; // count=0 means repeat ad inifinitum
266 for (i=0; i<loop; i++)
268 if (src_random)
270 tx.eth_src[0] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256) & 0xFE;
271 tx.eth_src[1] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
272 tx.eth_src[2] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
273 tx.eth_src[3] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
274 tx.eth_src[4] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
275 tx.eth_src[5] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
276 update=1;
279 if (dst_random)
281 tx.eth_dst[0] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
282 tx.eth_dst[1] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
283 tx.eth_dst[2] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
284 tx.eth_dst[3] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
285 tx.eth_dst[4] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
286 tx.eth_dst[5] = (u_int8_t) ( ((float) rand()/RAND_MAX)*256);
287 update=1;
290 if (update) // new frame parameters
292 t = libnet_build_ethernet (tx.eth_dst,
293 tx.eth_src,
294 tx.eth_type,
295 tx.eth_payload,
296 tx.eth_payload_s,
298 t);
300 if (t == -1)
302 fprintf(stderr, " mz/send_eth: %s", libnet_geterror(l));
303 return -1;
306 if (verbose)
308 bs2str (tx.eth_dst, message, 6); // DA
309 fprintf(stderr, " mz: send %s",message);
311 bs2str (tx.eth_src, message, 6); // SA
312 fprintf(stderr, " %s",message);
314 type2str(tx.eth_type, message);
315 fprintf(stderr, " %s",message); // Type
317 bs2str (tx.eth_payload, message, tx.eth_payload_s); // Payload
318 fprintf(stderr, " %s\n",message);
320 update=0;
321 if (verbose==2)
323 fprintf(stderr, "\n");
324 fprintf(stderr, "*** NOTE: Simulation only! Nothing has been sent! ***\n");
325 libnet_destroy(l);
326 return 0;
332 libnet_write(l);
334 if (tx.delay)
336 SLEEP (tx.delay);
337 if ( (verbose) && (!src_random) && (!dst_random) )
339 fprintf(stderr, ".");
343 } // end for
345 } // end while
347 if (verbose)
349 if ((tx.delay) || (tx.count==0))
351 fprintf(stderr,"\n");
354 fprintf(stderr, " mz: sent %u frames.\n",loop);
359 libnet_destroy(l);
362 return 0;
367 // ==========================================================================================
370 if (verbose)
372 fprintf(stderr," mz/send_bytes: \n");
373 bs2str(da,dast,6);
374 fprintf(stderr," DA = %s", dast);
375 bs2str(sa,sast,6);
376 fprintf(stderr," SA = %s", sast);
377 fprintf(stderr," type = %x",et);
378 bs2str(payload,pl,payload_s);
379 fprintf(stderr," data = %s\n",pl);