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