1 #include "isic.h"
2
3 /* This is tuned for ethernet sized frames (1500 bytes)
4 * For user over a modem or frame (or other) you will have to change the
5 * 'rand() & 0x4ff' line below. The 0x4ff needs to be less than the size of
6 * the frame size minus the length of the ip header (20 bytes IIRC) minus the
7 * length of the TCP header.
8 */
9
10
11 /* Variables shared between main and the signal handler so we can display
12 * output if ctrl-c'd
13 */
14 u_int seed = 0;
15 u_long acx = 0;
16 struct timeval starttime;
17 u_long datapushed = 0; /* How many bytes we pushed */
18
19
20 int
main(int argc,char ** argv)21 main(int argc, char **argv)
22 {
23 int c, frag_flag = 0, dstopt_flag = 0;
24 u_char *buf = NULL;
25 u_short *payload = NULL;
26 u_int payload_s = 0;
27 int packet_len = 0, dstopt_tlen = 0;
28 char addrbuf[INET6_ADDRSTRLEN];
29
30 /* libnet variables */
31 char errbuf[LIBNET_ERRBUF_SIZE];
32 libnet_t *l;
33 char *device = NULL;
34
35 /* Packet Variables */
36 u_int src_addr_flag = 0, dst_addr_flag = 0;
37 u_char ver, hlim, nxt;
38 u_int16_t plen;
39 u_int32_t flow;
40 struct ip6_hdr *ip6 = NULL;
41 struct libnet_in6_addr src_addr;
42 struct libnet_in6_addr dst_addr;
43
44 struct tcphdr *tcp = NULL;
45 u_short src_prt = 0, dst_prt = 0;
46
47 struct ip6_frag *ip6_fraghdr = NULL; /* IPv6 fragment header */
48 u_char f6_nxt = 0, f6_rsv = 0;
49 u_int32_t f6_id = 0;
50 u_int16_t f6_offlg = 0;
51
52 struct ip6_dest *ip6_dopthdr = NULL; /* IPv6 destination option header */
53 u_char dstopt_nxt = 0, dstopt_len = 0;
54
55 /* Functionality Variables */
56 int src_ip_rand = 0, dst_ip_rand = 0;
57 struct timeval tv, tv2;
58 float sec;
59 unsigned int cx = 0;
60 u_long max_pushed = 10240; /* 10MB/sec */
61 u_long num_to_send = 0xffffffff; /* Send 4billion packets */
62 u_long skip = 0; /* Skip how many packets */
63 int printout = 0; /* Debugging */
64 int dst_port_rand = 0;
65 int src_port_rand = 0;
66 char *tmp_port = NULL;
67 u_int repeat = 1;
68
69 /* Defaults */
70 float FragPct = 10;
71 float DstOpts = 10;
72 float UrgPct = 10;
73 float TCPOptsPct= 10;
74 float TCPCksm = 10;
75
76 /* Not crypto strong randomness but we don't really care. And this *
77 * gives us a way to determine the seed while the program is running *
78 * if we need to repeat the results */
79 seed = getpid();
80
81 /* Initialize libnet context, Root priviledges are required.*/
82 l = libnet_init(
83 LIBNET_RAW6_ADV, /* injection type */
84 device, /* network interface */
85 errbuf); /* error buffer */
86
87 if (l == NULL) {
88 fprintf(stderr, "libnet_init() failed: %s", errbuf);
89 exit( -1 );
90 }
91
92 while((c = getopt(argc, argv, "hd:s:r:m:k:Dp:F:I:u:T:t:vx:")) != EOF){
93 switch (c) {
94 case 'h':
95 usage(argv[0]);
96 exit(0);
97 break;
98 case 'd':
99 dst_port_rand = 1;
100 if ( (tmp_port = index(optarg, ',')) != NULL ) {
101 *tmp_port++ = '\0';
102 dst_port_rand = 0;
103 dst_prt = htons((u_int) atol(tmp_port));
104 }
105 if ( strcmp(optarg, "rand") == 0 ) {
106 printf("Using random destination IP's\n");
107 dst_addr_flag = 1; /* Just to pass sanity checks */
108 dst_ip_rand = 1;
109 break;
110 }
111 dst_addr = libnet_name2addr6(l, optarg, LIBNET_RESOLVE);
112 if (strncmp((char *)&dst_addr, (char *)&in6addr_error, sizeof(in6addr_error)) == 0) {
113 fprintf(stderr, "Bad destination IPv6 address!\n");
114 exit( -1 );
115 }
116 dst_addr_flag = 1;
117 break;
118 case 's':
119 src_port_rand = 1;
120 if ( (tmp_port = index(optarg, ',')) != NULL ) {
121 *tmp_port++ = '\0';
122 src_port_rand = 0;
123 src_prt = htons((u_int) atol(tmp_port));
124 }
125 if ( strcmp(optarg, "rand") == 0 ) {
126 printf("Using random source IP's\n");
127 src_addr_flag = 1; /* Just to pass sanity checks */
128 src_ip_rand = 1;
129 break;
130 }
131 src_addr = libnet_name2addr6(l, optarg, LIBNET_RESOLVE);
132 if (strncmp((char *)&src_addr, (char *)&in6addr_error, sizeof(in6addr_error)) == 0) {
133 fprintf(stderr, "Bad source IPv6 address!\n");
134 exit( -1 );
135 }
136 src_addr_flag = 1;
137 break;
138 case 'r':
139 seed = atoi(optarg);
140 break;
141 case 'm':
142 max_pushed = atol(optarg);
143 break;
144 case 'k':
145 skip = atol(optarg);
146 printf("Will not transmit first %li packets.\n", skip);
147 break;
148 case 'D':
149 printout++;
150 break;
151 case 'p':
152 num_to_send = atoi(optarg);
153 break;
154 case 'F':
155 FragPct = atof(optarg);
156 break;
157 case 'I':
158 DstOpts = atof(optarg);
159 break;
160 case 'T':
161 TCPOptsPct = atof(optarg);
162 break;
163 case 'u':
164 UrgPct = atof(optarg);
165 break;
166 case 't':
167 TCPCksm = atof(optarg);
168 break;
169 case 'x':
170 repeat = atoi(optarg);
171 break;
172 case 'v':
173 printf("Version %s\n", VERSION);
174 exit(0);
175 }
176 }
177
178 if ( !src_addr_flag || !dst_addr_flag ) {
179 usage(argv[0]);
180 exit(EXIT_FAILURE);
181 }
182
183 printf("Compiled against Libnet %s\n", LIBNET_VERSION);
184 printf("Installing Signal Handlers.\n");
185 if ( signal(SIGTERM, &sighandler) == SIG_ERR )
186 printf("Failed to install signal handler for SIGTERM\n");
187 if ( signal(SIGINT, &sighandler) == SIG_ERR )
188 printf("Failed to install signal handler for SIGINT\n");
189 if ( signal(SIGQUIT, &sighandler) == SIG_ERR )
190 printf("Failed to install signal handler for SIGQUIT\n");
191
192 printf("Seeding with %i\n", seed);
193 srand(seed);
194 max_pushed *= 1024;
195
196 if ( (buf = malloc(IP_MAXPACKET)) == NULL ) {
197 perror("malloc: ");
198 exit( -1 );
199 }
200
201
202 if ( max_pushed >= 10000000 )
203 printf("No Maximum traffic limiter\n");
204 else printf("Maximum traffic rate = %.2f k/s\n", max_pushed/1024.0 );
205
206 if ( src_port_rand )
207 printf("Using random source ports.\n");
208 if ( dst_port_rand )
209 printf("Using random destination ports.\n");
210
211
212 printf("Frag'd Pcnt\t= %.0f%%\t", FragPct);
213 printf("IPv6 Dst Opts\t= %.0f%%\n", DstOpts);
214 printf("Urg Pcnt\t= %.0f%%\t", UrgPct);
215 printf("Bad TCP Cksm\t= %.0f%%\t", TCPCksm);
216 printf("TCP Opts Pcnt\t= %.0f%%\n", TCPOptsPct);
217 printf("\n");
218
219
220 /* Drop them down to floats so we can multiply and not overflow */
221 FragPct /= 100;
222 DstOpts /= 100;
223 UrgPct /= 100;
224 TCPOptsPct /= 100;
225 TCPCksm /= 100;
226
227
228
229 /*************
230 * Main Loop *
231 *************/
232 gettimeofday(&tv, NULL);
233 gettimeofday(&starttime, NULL);
234 ver = 6;
235
236 for(acx = 0; acx < num_to_send; acx++) {
237 packet_len = IP6_H;
238
239 hlim = RAND8;
240 flow = RAND32;
241 nxt = IPPROTO_TCP;
242 tcp = (struct tcphdr *) (buf + IP6_H); /* for no extension header case */
243
244 if ( src_ip_rand == 1 ) {
245 (src_addr.__u6_addr.__u6_addr32)[0] = RAND32;
246 (src_addr.__u6_addr.__u6_addr32)[1] = RAND32;
247 (src_addr.__u6_addr.__u6_addr32)[2] = RAND32;
248 (src_addr.__u6_addr.__u6_addr32)[3] = RAND32;
249 }
250 if ( dst_ip_rand == 1 ) {
251 (dst_addr.__u6_addr.__u6_addr32)[0] = RAND32;
252 (dst_addr.__u6_addr.__u6_addr32)[1] = RAND32;
253 (dst_addr.__u6_addr.__u6_addr32)[2] = RAND32;
254 (dst_addr.__u6_addr.__u6_addr32)[3] = RAND32;
255 }
256
257 if ( rand() <= (RAND_MAX * FragPct) ) {
258 /* should add fragment header after IPv6 header */
259 f6_offlg = RAND16;
260 f6_id = RAND32;
261 f6_nxt = IPPROTO_TCP;
262 f6_rsv = RAND8;
263 nxt = IPPROTO_FRAGMENT;
264 tcp = (struct tcphdr *) (buf + IP6_H + IP6_FRAGH); /* adjust the pointer */
265 ip6_fraghdr = (struct ip6_frag *)(buf + IP6_H);
266 frag_flag = 1;
267 packet_len += IP6_FRAGH;
268 }
269
270 if ( rand() <= (RAND_MAX * DstOpts) ) {
271 /* should add Destination Options header */
272 dstopt_len = (int)(9.0*rand()/(RAND_MAX+1.0)); /* maximun 10 x 8 = 80 bytes */
273 dstopt_nxt = IPPROTO_TCP;
274 dstopt_flag = 1;
275 dstopt_tlen = (dstopt_len << 3) + 8;
276 packet_len += dstopt_tlen;
277 if (frag_flag) {
278 f6_nxt = IPPROTO_DSTOPTS;
279 tcp = (struct tcphdr *) (buf + IP6_H + IP6_FRAGH + dstopt_tlen);
280 ip6_dopthdr = (struct ip6_dest *)(buf + IP6_H + IP6_FRAGH);
281 }
282 else {
283 nxt = IPPROTO_DSTOPTS;
284 tcp = (struct tcphdr *) (buf + IP6_H + dstopt_tlen);
285 ip6_dopthdr = (struct ip6_dest *)(buf + IP6_H);
286 }
287 }
288
289 payload_s = rand() & 0x4ff; /* length of 1279 */
290 packet_len += payload_s;
291
292 if ( rand() <= (RAND_MAX * TCPOptsPct) )
293 tcp->th_off = rand() & 0xf;
294 else tcp->th_off = 5;
295 packet_len += (tcp->th_off) << 2;
296 plen = packet_len - IP6_H;
297 /*
298 * Build the IPv6 header
299 */
300 ip6 = (struct ip6_hdr *) buf;
301 ip6->ip6_flow = htonl(flow);
302 ip6->ip6_vfc = ver<<4; /* version 6 */
303 ip6->ip6_plen = htons(plen); /* payload length */
304 ip6->ip6_nxt = nxt; /* next header value */
305 ip6->ip6_hlim = hlim; /* hop limit */
306 memcpy(&(ip6->ip6_src), &src_addr, sizeof(struct in6_addr));
307 memcpy(&(ip6->ip6_dst), &dst_addr, sizeof(struct in6_addr));
308
309 if (frag_flag) {
310 /* Build fragment header */
311 ip6_fraghdr->ip6f_nxt = f6_nxt; /* next header value */
312 ip6_fraghdr->ip6f_reserved = f6_rsv; /* reserved field */
313 ip6_fraghdr->ip6f_offlg = htons(f6_offlg); /* offset, reserved and flag */
314 ip6_fraghdr->ip6f_ident = htonl(f6_id); /* fragment id */
315 }
316
317 if (dstopt_flag) {
318 /* Build destination options header */
319 ip6_dopthdr->ip6d_nxt = dstopt_nxt;
320 ip6_dopthdr->ip6d_len = dstopt_len; /* remember: it is 8 bytes by unit */
321 payload = (ushort *)(ip6_dopthdr);
322 payload[1] = RAND16; /* set the 3rd and 4th bytes */
323 payload[2] = RAND16; /* set the 5-6th bytes */
324 payload[3] = RAND16; /* set the 7-8th bytes */
325 /* set the remaining in the header */
326 for (cx = 0; cx < (u_int)(dstopt_len << 2); cx+=1) {
327 payload[cx+4] = RAND16;
328 }
329 }
330
331 /* Build TCP header */
332 if ( src_port_rand == 1 )
333 tcp->th_sport = RAND16;
334 else tcp->th_sport = src_prt;
335 if ( dst_port_rand == 1 )
336 tcp->th_dport = RAND16;
337 else tcp->th_dport = dst_prt;
338
339 tcp->th_seq = RAND32;
340 tcp->th_ack = RAND32;
341 tcp->th_x2 = rand() & 0xf; /* 4bit */
342 tcp->th_flags = RAND8;
343 tcp->th_win = RAND16;
344 tcp->th_sum = 0;
345 if ( rand() <= (RAND_MAX * UrgPct) ) {
346 tcp->th_urp = RAND16;
347 tcp->th_flags |= 0x20; /* set URG bit */
348 }
349 else tcp->th_urp = 0;
350
351 payload = (u_short *)((u_char *) tcp + 20);
352 for(cx = 0; cx <= (payload_s >> 1); cx+=1)
353 payload[cx] = RAND16;
354
355 if ( rand() <= (RAND_MAX * TCPCksm) )
356 tcp->th_sum = RAND16;
357 else libnet_do_checksum(l, (u_int8_t *)buf, IPPROTO_TCP, packet_len - IP6_H);
358
359 if ( printout ) {
360 printf("%s ->",
361 inet_ntop(AF_INET6, &src_addr, addrbuf, INET6_ADDRSTRLEN));
362 printf(" %s ver[%i] plen[%i] nxt[%i] hlim[%i]\n",
363 inet_ntop(AF_INET6, &dst_addr, addrbuf, INET6_ADDRSTRLEN),
364 ver & 0xf, plen, nxt, hlim);
365 }
366
367 if ( skip <= acx ) {
368 for ( cx = 0; cx < repeat; cx++ ) {
369 c = libnet_write_raw_ipv6(l, buf, packet_len);
370 if (c != -1)
371 datapushed+=c;
372 }
373 if ( c < (packet_len) )
374 perror("Failed to send packet");
375 }
376
377 if ( !(acx % 1000) ) {
378 if ( acx == 0 )
379 continue;
380 gettimeofday(&tv2, NULL);
381 sec = (tv2.tv_sec - tv.tv_sec)
382 - (tv.tv_usec - tv2.tv_usec) / 1000000.0;
383 printf(" %li @ %.1f pkts/sec and %.1f k/s\n", acx,
384 1000/sec, (datapushed / 1024.0) / sec);
385 datapushed=0;
386 gettimeofday(&tv, NULL);
387 }
388
389
390 /* Flood protection for low traffic limit only. */
391 if ( max_pushed < 10000000 ) {
392 gettimeofday(&tv2, NULL);
393 sec = (tv2.tv_sec - tv.tv_sec)
394 - (tv.tv_usec - tv2.tv_usec) / 1000000.0;
395 if ( (datapushed / sec) >= max_pushed )
396 usleep(10); /* 10 should give up our timeslice */
397 }
398 }
399
400
401 gettimeofday(&tv, NULL);
402 printf("\nWrote %li packets in %.2fs @ %.2f pkts/s\n", acx,
403 (tv.tv_sec-starttime.tv_sec)
404 + (tv.tv_usec-starttime.tv_usec) / 1000000.0,
405 acx / ((tv.tv_sec-starttime.tv_sec)
406 + (tv.tv_usec-starttime.tv_usec)/1000000.0) );
407
408 libnet_destroy(l);
409 free(buf);
410 return ( 0 );
411 }
412
413
usage(char * name)414 void usage(char *name)
415 {
416 fprintf(stderr,
417 "usage: %s [-v] [-D] -s <sourceip>[,port] -d <destination ip>[,port]\n"
418 " [-r seed] [-m <max kB/s to generate>]\n"
419 " [-p <pkts to generate>] [-k <skip packets>] [-x <repeat times>]\n\n"
420 " Percentage Opts: [-F frags] [-I <IPv6 Destination Options>]\n"
421 " [-T <TCP Options>] [-u <urgent data>] [-t <Bad TCP Cksm>]\n\n"
422 " [-D] causes packet info to be printed out -- DEBUGGING\n\n"
423 " ex: -s 2001:1:2:3:4::1,23 -d 2001:1:2:3:4::2 -I 100\n"
424 " will give a 100%% chance of IPv6 Destination ^^^ Options \n"
425 " ex: -s 2001:a:b:c:d::1,23 -d 2001:a:b:c:d::2 -p 100 -r 103334\n"
426 " ex: -s rand -d rand,1234 -r 23342\n"
427 " ^^^^ causes random source addr\n"
428 " ex: -s rand -d rand -k 10000 -p 10001 -r 666\n"
429 " Will only send the 10001 packet with random seed 666\n"
430 " this is especially useful if you suspect that packet is\n"
431 " causing a problem with the target stack.\n\n",
432 ((char *) rindex(name, '/')) == ((char *) NULL)
433 ? (char *) name
434 : (char *) rindex(name, '/') + 1);
435 }
436
sighandler(int sig)437 void sighandler(int sig)
438 {
439 struct timeval tv;
440 gettimeofday(&tv, NULL);
441
442 printf("\n");
443 printf("Caught signal %i\n", sig);
444
445 printf("Used random seed %i\n", seed);
446 printf("Wrote %li packets in %.2fs @ %.2f pkts/s\n", acx,
447 (tv.tv_sec - starttime.tv_sec)
448 + (tv.tv_usec - starttime.tv_usec)/1000000.0,
449 acx / (( tv.tv_sec - starttime.tv_sec)
450 + (tv.tv_usec - starttime.tv_usec)/1000000.0)
451 );
452
453 fflush(stdout);
454 exit(0);
455 }
456