1 /*
2 * flow6: A security assessment tool that determines the Flow Label
3 * generation policy of a target node
4 *
5 * Copyright (C) 2011-2015 Fernando Gont <fgont@si6networks.com>
6 *
7 * Programmed by Fernando Gont for SI6 Networks (www.si6networks.com)
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warrsi6networks.allanty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 *
23 * Build with: make flow6
24 *
25 * It requires that the libpcap library be installed on your system.
26 *
27 * Please send any bug reports to Fernando Gont <fgont@si6networks.com>
28 */
29
30 #include <sys/types.h>
31 #include <sys/param.h>
32 #include <sys/select.h>
33 #include <sys/socket.h>
34
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netinet/ip6.h>
38 #include <netinet/icmp6.h>
39 #include <netinet/tcp.h>
40 #include <netinet/udp.h>
41 #include <net/if.h>
42 #include <netdb.h>
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <errno.h>
47 #include <time.h>
48 #include <getopt.h>
49 #include <unistd.h>
50 #include <signal.h>
51 #include <string.h>
52 #include <pcap.h>
53
54 #include "flow6.h"
55 #include "ipv6toolkit.h"
56 #include "libipv6.h"
57
58
59 /* Function prototypes */
60 void print_attack_info(void);
61 void usage(void);
62 void print_help(void);
63 int send_fid_probe(void);
64 int predict_flow_id(uint32_t *, unsigned int, uint32_t *, unsigned int);
65
66
67 /* Used for router discovery */
68 struct iface_data idata;
69 struct in6_addr randprefix;
70 unsigned char randpreflen;
71
72 /* Data structures for packets read from the wire */
73 struct pcap_pkthdr *pkthdr;
74 const u_char *pktdata;
75 unsigned char *pkt_end, *pkt_ptr;
76 struct ether_header *pkt_ether;
77 struct ip6_hdr *pkt_ipv6;
78 struct tcp_hdr *pkt_tcp;
79 struct udp_hdr *pkt_udp;
80 struct icmp6_hdr *pkt_icmp6;
81 struct nd_neighbor_solicit *pkt_ns;
82 struct in6_addr *pkt_ipv6addr;
83 unsigned int pktbytes;
84
85
86 bpf_u_int32 my_netmask;
87 bpf_u_int32 my_ip;
88 struct bpf_program pcap_filter;
89 char dev[64];
90 unsigned char buffer[65556], buffrh[MIN_IPV6_HLEN + MIN_TCP_HLEN];
91 unsigned char *v6buffer, *ptr, *startofprefixes;
92 char *pref;
93 char iface[IFACE_LENGTH];
94
95 struct ip6_hdr *ipv6;
96 struct icmp6_hdr *icmp6;
97
98 struct ether_header *ethernet;
99 struct nd_opt_tlla *tllaopt;
100 struct ether_addr linkaddr[MAX_TLLA_OPTION];
101 unsigned int nlinkaddr=0, linkaddrs;
102
103 char *lasts, *rpref;
104 char *charptr;
105
106 size_t nw;
107 unsigned long ul_res, ul_val;
108 unsigned int i, j, startrand;
109 unsigned int skip;
110 unsigned int frags, nfrags, nsleep;
111 unsigned char srcpreflen;
112
113 uint16_t mask, ip6length;
114 uint8_t hoplimit;
115
116 char plinkaddr[ETHER_ADDR_PLEN];
117 char psrcaddr[INET6_ADDRSTRLEN], pdstaddr[INET6_ADDRSTRLEN], pv6addr[INET6_ADDRSTRLEN];
118 unsigned char localaddr_f=0;
119 unsigned char srcprefix_f=0, hoplimit_f=0, flowidp_f=0, dstport_f=0, protocol_f=0;
120
121 /* Support for Extension Headers */
122 unsigned int dstopthdrs, dstoptuhdrs, hbhopthdrs;
123 char hbhopthdr_f=0, dstoptuhdr_f=0, dstopthdr_f=0;
124 unsigned char *dstopthdr[MAX_DST_OPT_HDR], *dstoptuhdr[MAX_DST_OPT_U_HDR];
125 unsigned char *hbhopthdr[MAX_HBH_OPT_HDR];
126 unsigned int dstopthdrlen[MAX_DST_OPT_HDR], dstoptuhdrlen[MAX_DST_OPT_U_HDR];
127 unsigned int hbhopthdrlen[MAX_HBH_OPT_HDR], m, pad;
128
129 struct ip6_frag *fh;
130 struct ip6_hdr *fipv6;
131 unsigned char fragh_f=0;
132
133 unsigned char *fragpart, *ptrend, *ptrhdr, *ptrhdrend;
134 unsigned int hdrlen, ndstopthdr=0, nhbhopthdr=0, ndstoptuhdr=0;
135 unsigned int nfrags, fragsize;
136 unsigned char *prev_nh, *startoffragment;
137
138
139 /* For the sampling of Flow Label values */
140 uint16_t baseport, lastport, dstport, tcpwin, addr_sig, addr_key;
141 uint32_t tcpseq;
142 uint8_t protocol;
143
144
main(int argc,char ** argv)145 int main(int argc, char **argv){
146 extern char *optarg;
147 fd_set sset, rset;
148 struct timeval timeout;
149 int r, sel;
150 time_t curtime, start, lastfrag1=0;
151 struct target_ipv6 targetipv6;
152
153 /* Arrays for storing the Flow ID samples */
154 uint32_t test1[NSAMPLES], test2[NSAMPLES];
155 unsigned int ntest1=0, ntest2=0;
156 unsigned char testtype;
157
158 static struct option longopts[] = {
159 {"interface", required_argument, 0, 'i'},
160 {"src-address", required_argument, 0, 's'},
161 {"dst-address", required_argument, 0, 'd'},
162 {"hop-limit", required_argument, 0, 'A'},
163 {"link-src-addr", required_argument, 0, 'S'},
164 {"link-dst-addr", required_argument, 0, 'D'},
165 {"protocol", required_argument, 0, 'P'},
166 {"dst-port", no_argument, 0, 'p'},
167 {"flow-label-policy", no_argument, 0, 'W'},
168 {"verbose", no_argument, 0, 'v'},
169 {"help", no_argument, 0, 'h'},
170 {0, 0, 0, 0 }
171 };
172
173 char shortopts[]= "i:s:d:A:S:D:P:p:Wvh";
174
175 char option;
176
177 if(argc<=1){
178 usage();
179 exit(EXIT_FAILURE);
180 }
181
182
183 srandom(time(NULL));
184 hoplimit=64+random()%180;
185
186 if(init_iface_data(&idata) == FAILURE){
187 puts("Error initializing internal data structure");
188 exit(EXIT_FAILURE);
189 }
190
191 while((r=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
192 option= r;
193
194 switch(option) {
195
196 case 'i': /* Interface */
197 strncpy(idata.iface, optarg, IFACE_LENGTH-1);
198 idata.iface[IFACE_LENGTH-1]=0;
199 idata.ifindex= if_nametoindex(idata.iface);
200 idata.iface_f=TRUE;
201 break;
202
203 case 's': /* IPv6 Source Address */
204 if((charptr = strtok_r(optarg, "/", &lasts)) == NULL){
205 puts("Error in Source Address");
206 exit(EXIT_FAILURE);
207 }
208
209 if ( inet_pton(AF_INET6, charptr, &(idata.srcaddr)) <= 0){
210 puts("inet_pton(): Source Address not valid");
211 exit(EXIT_FAILURE);
212 }
213
214 idata.srcaddr_f = 1;
215
216 if((charptr = strtok_r(NULL, " ", &lasts)) != NULL){
217 srcpreflen = atoi(charptr);
218
219 if(srcpreflen>128){
220 puts("Prefix length error in IPv6 Source Address");
221 exit(EXIT_FAILURE);
222 }
223
224 sanitize_ipv6_prefix(&(idata.srcaddr), srcpreflen);
225 srcprefix_f=1;
226 }
227
228 break;
229
230 case 'd': /* IPv6 Destination Address */
231 strncpy( targetipv6.name, optarg, NI_MAXHOST);
232 targetipv6.name[NI_MAXHOST-1]= 0;
233 targetipv6.flags= AI_CANONNAME;
234
235 if( (r=get_ipv6_target(&targetipv6)) != 0){
236
237 if(r < 0){
238 printf("Unknown Destination: %s\n", gai_strerror(targetipv6.res));
239 }
240 else{
241 puts("Unknown Destination: No IPv6 address found for specified destination");
242 }
243
244 exit(1);
245 }
246
247 idata.dstaddr= targetipv6.ip6;
248 idata.dstaddr_f = 1;
249 break;
250
251 case 'A': /* Hop Limit */
252 hoplimit= atoi(optarg);
253 hoplimit_f=1;
254 break;
255
256 case 'S': /* Source Ethernet address */
257 if(ether_pton(optarg, &(idata.hsrcaddr), sizeof(idata.hsrcaddr)) == 0){
258 puts("Error in Source link-layer address.");
259 exit(EXIT_FAILURE);
260 }
261
262 idata.hsrcaddr_f = 1;
263 break;
264
265 case 'D': /* Destination Ethernet Address */
266 if(ether_pton(optarg, &(idata.hdstaddr), sizeof(idata.hdstaddr)) == 0){
267 puts("Error in Source link-layer address.");
268 exit(EXIT_FAILURE);
269 }
270
271 idata.hdstaddr_f = 1;
272 break;
273
274 case 'P': /* Protocol */
275 if(strncmp(optarg, "tcp", MAX_STRING_SIZE) == 0 || \
276 strncmp(optarg, "TCP", MAX_STRING_SIZE) == 0){
277 protocol= IPPROTO_TCP;
278 }
279 else if(strncmp(optarg, "udp", MAX_STRING_SIZE) == 0 || \
280 strncmp(optarg, "UDP", MAX_STRING_SIZE) == 0){
281 protocol= IPPROTO_UDP;
282 }
283 else{
284 puts("Unknown protocol type (valid types: 'tcp', 'udp')");
285 exit(EXIT_FAILURE);
286 }
287
288 protocol_f= 1;
289 break;
290
291 case 'p': /* Destination port */
292 dstport= atoi(optarg);
293 dstport_f=1;
294 break;
295
296 case 'W': /* Assess the Flow Label generation policy of the target */
297 flowidp_f= 1;
298 break;
299
300 case 'v': /* Be verbose */
301 idata.verbose_f++;
302 break;
303
304 case 'h': /* Help */
305 print_help();
306
307 exit(EXIT_FAILURE);
308 break;
309
310 default:
311 usage();
312 exit(EXIT_FAILURE);
313 break;
314
315 } /* switch */
316 } /* while(getopt) */
317
318 if(geteuid()) {
319 puts("flow6 needs root privileges to run.");
320 exit(EXIT_FAILURE);
321 }
322
323 if(!idata.iface_f){
324 if(idata.dstaddr_f && IN6_IS_ADDR_LINKLOCAL(&(idata.dstaddr))){
325 puts("Must specify a network interface for link-local destinations");
326 exit(EXIT_FAILURE);
327 }
328 }
329
330 if(load_dst_and_pcap(&idata, LOAD_SRC_NXT_HOP) == FAILURE){
331 puts("Error while learning Souce Address and Next Hop");
332 exit(EXIT_FAILURE);
333 }
334
335 release_privileges();
336
337 if( !fragh_f && dstoptuhdr_f){
338 puts("Dst. Options Header (Unfragmentable Part) set, but Fragmentation not specified");
339 exit(EXIT_FAILURE);
340 }
341
342 if(idata.verbose_f){
343 print_attack_info();
344 }
345
346 if(!idata.dstaddr_f){
347 puts("Error: Nothing to send! (Destination Address left unspecified)");
348 exit(EXIT_FAILURE);
349 }
350
351 /* Assess the Flow ID generation policy */
352 if(flowidp_f){
353 if(dstport_f && !protocol_f){
354 puts("Error: Must specify a protocol if the port number is specified");
355 exit(EXIT_FAILURE);
356 }
357
358 if(!protocol_f){
359 protocol= IPPROTO_TCP;
360 dstport= 80;
361 }
362 else if(!dstport_f){
363 if(protocol == IPPROTO_TCP)
364 dstport= 80;
365 else
366 dstport= 53;
367 }
368
369 puts("Identifying the 'Flow ID' generation policy of the target node....");
370
371 if(protocol == IPPROTO_TCP){
372 tcpwin= ((uint16_t) random() + 1500) & (uint16_t)0x7f00;
373 tcpseq= random();
374 baseport= 50000+ random()%10000;
375 lastport= baseport;
376 }
377
378 /*
379 Set filter for receiving Neighbor Solicitations, and TCP segments
380 */
381 if(pcap_compile(idata.pfd, &pcap_filter, PCAP_NSTCP_FILTER, PCAP_OPT, PCAP_NETMASK_UNKNOWN) == -1){
382 printf("pcap_compile(): %s", pcap_geterr(idata.pfd));
383 exit(EXIT_FAILURE);
384 }
385
386 if(pcap_setfilter(idata.pfd, &pcap_filter) == -1){
387 printf("pcap_setfilter(): %s", pcap_geterr(idata.pfd));
388 exit(EXIT_FAILURE);
389 }
390
391 pcap_freecode(&pcap_filter);
392
393 FD_ZERO(&sset);
394 FD_SET(idata.fd, &sset);
395 start= time(NULL);
396 lastfrag1=0;
397 ntest1=0;
398 ntest2=0;
399 testtype= FIXED_ORIGIN;
400
401 if(srcprefix_f){
402 randprefix= idata.srcaddr;
403 randpreflen=srcpreflen;
404 }
405 else{
406 randprefix= idata.srcaddr;
407 randpreflen=64;
408 sanitize_ipv6_prefix(&randprefix, randpreflen);
409 }
410
411 while(1){
412 curtime=time(NULL);
413
414 if( testtype==FIXED_ORIGIN && ((curtime - start) >= ID_ASSESS_TIMEOUT || ntest1 >= NSAMPLES)){
415 testtype= MULTI_ORIGIN;
416 addr_sig= random();
417 addr_key= random();
418 start= curtime;
419 continue;
420 }
421 else if( testtype==MULTI_ORIGIN && ((curtime - start) >= ID_ASSESS_TIMEOUT || ntest2 >= NSAMPLES)){
422 break;
423 }
424
425 if((curtime - lastfrag1) >= 1){
426 if(testtype == FIXED_ORIGIN){
427 for(i=0; i<NSAMPLES; i++){
428 if(send_fid_probe() == -1){
429 puts("Error while sending packet");
430 exit(EXIT_FAILURE);
431 }
432
433 lastport++;
434 }
435 }
436 else{
437 for(i=0; i<NSAMPLES; i++){
438 randomize_ipv6_addr(&(idata.srcaddr), &randprefix, randpreflen);
439
440 /*
441 * Two words of the Source IPv6 Address are specially encoded such that we only respond
442 * to Neighbor Solicitations that target those addresses, and accept ICMPv6 Echo Replies
443 * only if they are destined to those addresses
444 */
445 idata.srcaddr.s6_addr32[2]= htonl((ntohl(idata.srcaddr.s6_addr32[2]) & 0xffff0000) | addr_sig);
446 idata.srcaddr.s6_addr32[3]= htonl((ntohl(idata.srcaddr.s6_addr32[3]) & 0xffff0000) | \
447 ((uint16_t)(ntohl(idata.srcaddr.s6_addr32[3])>>16) ^ addr_key));
448
449 if(send_neighbor_solicit(&idata, &(idata.dstaddr)) == -1){
450 puts("Error while sending Neighbor Solicitation");
451 exit(EXIT_FAILURE);
452 }
453
454 if(send_fid_probe() == -1){
455 puts("Error while sending packet");
456 exit(EXIT_FAILURE);
457 }
458
459 lastport++;
460 }
461 }
462
463 lastfrag1=curtime;
464 continue;
465 }
466
467 rset= sset;
468
469 #if !defined(sun) && !defined(__sun)
470 timeout.tv_usec=0;
471 timeout.tv_sec= 1;
472 #else
473 timeout.tv_usec=10000;
474 timeout.tv_sec= 0;
475 #endif
476
477 if((sel=select(idata.fd+1, &rset, NULL, NULL, &timeout)) == -1){
478 if(errno == EINTR){
479 continue;
480 }
481 else{
482 puts("Error in select()");
483 exit(EXIT_FAILURE);
484 }
485 }
486
487 #if defined(sun) || defined(__sun)
488 if(TRUE){
489 #else
490 if(sel && FD_ISSET(idata.fd, &rset)){
491 #endif
492 /* Read a packet (Echo Reply, or Neighbor Solicitation) */
493 if((r=pcap_next_ex(idata.pfd, &pkthdr, &pktdata)) == -1){
494 printf("pcap_next_ex(): %s", pcap_geterr(idata.pfd));
495 exit(EXIT_FAILURE);
496 }
497 else if(r == 1 && pktdata != NULL){
498 pkt_ether = (struct ether_header *) pktdata;
499 pkt_ipv6 = (struct ip6_hdr *)((char *) pkt_ether + idata.linkhsize);
500 pkt_icmp6 = (struct icmp6_hdr *) ((char *) pkt_ipv6 + sizeof(struct ip6_hdr));
501 pkt_end = (unsigned char *) pktdata + pkthdr->caplen;
502
503 if( (pkt_end - pktdata) < (idata.linkhsize + MIN_IPV6_HLEN))
504 continue;
505
506 if(pkt_ipv6->ip6_nxt == IPPROTO_ICMPV6 && pkt_icmp6->icmp6_type == ND_NEIGHBOR_SOLICIT){
507 pkt_ns= (struct nd_neighbor_solicit *) pkt_icmp6;
508
509 if( (pkt_end - (unsigned char *) pkt_ns) < sizeof(struct nd_neighbor_solicit))
510 continue;
511 /*
512 If the addresses that we're using are not actually configured on the local system
513 (i.e., they are "spoofed", we must check whether it is a Neighbor Solicitation for
514 one of our addresses, and respond with a Neighbor Advertisement. Otherwise, the kernel
515 will take care of that.
516 */
517 if(testtype==FIXED_ORIGIN){
518 if(!localaddr_f && is_eq_in6_addr(&(pkt_ns->nd_ns_target), &(idata.srcaddr))){
519 if(send_neighbor_advert(&idata, idata.pfd, pktdata) == -1){
520 puts("Error sending Neighbor Advertisement");
521 exit(EXIT_FAILURE);
522 }
523 }
524 }
525 else if(idata.type == DLT_EN10MB && !(idata.flags & IFACE_LOOPBACK)){
526 if( (ntohl(pkt_ns->nd_ns_target.s6_addr32[2]) & 0x0000ffff) != addr_sig || \
527 (ntohl(pkt_ns->nd_ns_target.s6_addr32[3]) & 0x0000ffff) != ( (ntohl(pkt_ns->nd_ns_target.s6_addr32[3])>>16) ^ addr_key)){
528 continue;
529 }
530
531 if(send_neighbor_advert(&idata, idata.pfd, pktdata) == -1){
532 puts("Error sending Neighbor Advertisement");
533 exit(EXIT_FAILURE);
534 }
535 }
536 }
537 else if(pkt_ipv6->ip6_nxt == protocol){
538
539 /* Perform TCP-specific validation checks */
540 if(protocol == IPPROTO_TCP){
541 if( (pkt_end - (unsigned char *) pkt_ipv6) < \
542 (sizeof(struct ip6_hdr) + sizeof(struct tcp_hdr)))
543 continue;
544
545 pkt_tcp= (struct tcp_hdr *) ((unsigned char *)pkt_ipv6 + sizeof(struct ip6_hdr));
546
547 /*
548 * The TCP Destination Port must correspond to one of the ports that we have used as
549 * TCP Source Port
550 */
551 if(ntohs(pkt_tcp->th_dport) < baseport || ntohs(pkt_tcp->th_dport) > lastport)
552 continue;
553
554 /* The Source Port must be that to which we're sending our TCP segments */
555 if(ntohs(pkt_tcp->th_sport) != dstport)
556 continue;
557
558 /* The TCP Acknowledgement Number must ack our SYN */
559 if(ntohl(pkt_tcp->th_ack) != tcpseq+1)
560 continue;
561
562 /* We sample Flow ID's only on SYN/ACKs */
563 if( (pkt_tcp->th_flags & ~TH_SYN) == 0 || (pkt_tcp->th_flags & TH_ACK) == 0)
564 continue;
565
566 /* The TCP checksum must be valid */
567 if(in_chksum(pkt_ipv6, pkt_tcp, pkt_end-((unsigned char *)pkt_tcp), IPPROTO_TCP) != 0)
568 continue;
569 }
570 /* Perform UDP-specific validation checks */
571 else if(protocol == IPPROTO_UDP){
572 if( (pkt_end - (unsigned char *) pkt_ipv6) < \
573 (sizeof(struct ip6_hdr) + sizeof(struct udp_hdr)))
574 continue;
575
576 pkt_udp= (struct udp_hdr *) ((unsigned char *)pkt_ipv6 + sizeof(struct ip6_hdr));
577
578 /*
579 * The UDP Destination Port must correspond to one of the ports that we have used as
580 * the UDP Source Port
581 */
582 if(ntohs(pkt_udp->uh_dport) < baseport || ntohs(pkt_udp->uh_dport) > lastport)
583 continue;
584
585 /* The Source Port must be that to which we're sending our UDP datagrams */
586 if(ntohs(pkt_udp->uh_sport) != dstport)
587 continue;
588
589 /* The UDP checksum must be valid */
590 if(in_chksum(pkt_ipv6, pkt_udp, pkt_end-((unsigned char *)pkt_udp), IPPROTO_UDP) != 0)
591 continue;
592 }
593
594 if(testtype==FIXED_ORIGIN){
595 if(!is_eq_in6_addr(&(pkt_ipv6->ip6_dst), &(idata.srcaddr))){
596 continue;
597 }
598
599 if(ntest1 >= NSAMPLES)
600 continue;
601
602 test1[ntest1]= ntohl(pkt_ipv6->ip6_flow) & 0x000fffff;
603 ntest1++;
604 }
605 else{
606 if( (ntohl(pkt_ipv6->ip6_dst.s6_addr32[2]) & 0x0000ffff) != addr_sig || \
607 (ntohl(pkt_ipv6->ip6_dst.s6_addr32[3]) & 0x0000ffff) != ( (ntohl(pkt_ipv6->ip6_dst.s6_addr32[3])>>16) ^ addr_key)){
608 continue;
609 }
610
611 if(ntest2 >= NSAMPLES)
612 continue;
613
614 test2[ntest2]= ntohl(pkt_ipv6->ip6_flow) & 0x000fffff;
615 ntest2++;
616 }
617 }
618 }
619 }
620 }
621
622 if(idata.verbose_f > 1){
623 printf("Sampled %u Flow Labels from single-origin probes\n", ntest1);
624
625 for(i=0; i<ntest1; i++)
626 printf("#%02u: %05x\n", (i+1), test1[i]);
627
628 printf("\nSampled %u Flow Labels from multi-origin probes\n", ntest2);
629
630 for(i=0; i<ntest2; i++)
631 printf("#%02u: %05x\n", (i+1), test2[i]);
632
633 puts("");
634 }
635
636 if(ntest1 < 10 || ntest2 < 10){
637 puts("Error: Didn't receive enough response packets");
638 exit(EXIT_FAILURE);
639 }
640
641 if(predict_flow_id(test1, ntest1, test2, ntest2) == -1){
642 puts("Error in predict_flow_id()");
643 exit(EXIT_FAILURE);
644 }
645
646 exit(EXIT_SUCCESS);
647 }
648
649 exit(EXIT_SUCCESS);
650 }
651
652
653 /*
654 * Function: send_fid_probe()
655 *
656 * Send a TCP segment or UDP datagram used for sampling the Flow Label
657 * values sent by the target
658 */
659 int send_fid_probe(void){
660 struct ether_header *ethernet;
661 struct dlt_null *dlt_null;
662 struct ip6_hdr *ipv6;
663 struct tcp_hdr *tcp;
664 struct udp_hdr *udp;
665 unsigned char *ptr;
666
667 ethernet= (struct ether_header *) buffer;
668 dlt_null= (struct dlt_null *) buffer;
669 v6buffer = buffer + idata.linkhsize;
670 ipv6 = (struct ip6_hdr *) v6buffer;
671
672 if(idata.type == DLT_EN10MB){
673 ethernet->ether_type = htons(ETHERTYPE_IPV6);
674
675 if( !(idata.flags & IFACE_LOOPBACK)){
676 ethernet->src = idata.hsrcaddr;
677 ethernet->dst = idata.hdstaddr;
678 }
679 }
680 else if(idata.type == DLT_NULL){
681 dlt_null->family= PF_INET6;
682 }
683 #if defined (__OpenBSD__)
684 else if(idata->type == DLT_LOOP){
685 dlt_null->family= htonl(PF_INET6);
686 }
687 #endif
688
689 ipv6->ip6_flow=0;
690 ipv6->ip6_vfc= 0x60;
691 ipv6->ip6_hlim= hoplimit;
692 ipv6->ip6_src= idata.srcaddr;
693 ipv6->ip6_dst= idata.dstaddr;
694 ipv6->ip6_nxt= protocol;
695
696 if(protocol == IPPROTO_TCP){
697 tcp= (struct tcp_hdr *) ( (unsigned char *) ipv6 + sizeof(struct ip6_hdr));
698 ptr= (unsigned char *) tcp + sizeof(struct tcp_hdr);
699 memset(tcp, 0, sizeof(struct tcp_hdr));
700 tcp->th_sport= htons(lastport);
701 tcp->th_dport= htons(dstport);
702 tcp->th_seq = htonl(tcpseq);
703 tcp->th_ack= htonl(0);
704 tcp->th_flags= TH_SYN;;
705 tcp->th_urp= htons(0);
706 tcp->th_win= htons(tcpwin);
707 tcp->th_off= sizeof(struct tcp_hdr) >> 2;
708 ipv6->ip6_plen= htons(ptr - (unsigned char *) tcp);
709 tcp->th_sum = in_chksum(ipv6, tcp, (ptr - (unsigned char *) tcp), IPPROTO_TCP);
710 }
711 else{
712 udp= (struct udp_hdr *) ( (unsigned char *) ipv6 + sizeof(struct ip6_hdr));
713 ptr= (unsigned char *) udp + sizeof(struct udp_hdr);
714 memset(udp, 0, sizeof(struct udp_hdr));
715 udp->uh_sport= htons(lastport);
716 udp->uh_dport= htons(dstport);
717 ipv6->ip6_plen= htons(ptr - (unsigned char *) udp);
718 udp->uh_sum = in_chksum(ipv6, udp, (ptr - (unsigned char *) udp), IPPROTO_TCP);
719 }
720
721 if((nw=pcap_inject(idata.pfd, buffer, ptr - buffer)) == -1){
722 if(idata.verbose_f)
723 printf("pcap_inject(): %s\n", pcap_geterr(idata.pfd));
724
725 return(-1);
726 }
727
728 if(nw != (ptr- buffer)){
729 if(idata.verbose_f)
730 printf("pcap_inject(): only wrote %lu bytes (rather than %lu bytes)\n", (LUI) nw, (LUI) (ptr-buffer));
731
732 return(-1);
733 }
734
735 return(0);
736 }
737
738
739 /*
740 * Function: usage()
741 *
742 * Prints the syntax of the flow6 tool
743 */
744 void usage(void){
745 puts("usage: flow6 -d DST_ADDR [-i INTERFACE] [-S LINK_SRC_ADDR] [-D LINK-DST-ADDR]\n"
746 " [-s SRC_ADDR[/LEN]] [-A HOP_LIMIT] [-P PROTOCOL] [-p PORT]\n"
747 " [-W] [-v] [-h]");
748 }
749
750
751 /*
752 * Function: print_help()
753 *
754 * Prints help information for the flow6 tool
755 */
756 void print_help(void){
757 puts(SI6_TOOLKIT);
758 puts("flow6: Security assessment tool for the IPv6 Flow Label field\n");
759 usage();
760
761 puts("\nOPTIONS:\n"
762 " --interface, -i Network interface\n"
763 " --link-src-address, -S Link-layer Destination Address\n"
764 " --link-dst-address, -D Link-layer Source Address\n"
765 " --src-address, -s IPv6 Source Address\n"
766 " --dst-address, -d IPv6 Destination Address\n"
767 " --hop-limit, -A IPv6 Hop Limit\n"
768 " --protocol, -P IPv6 Payload protocol (valid: TCP, UDP)\n"
769 " --dst-port, -p Transport Protocol Destination Port\n"
770 " --flow-label-policy, -W Assess the Flow Label generation policy\n"
771 " --help, -h Print help for the flow6 tool\n"
772 " --verbose, -v Be verbose\n"
773 "\n"
774 "Programmed by Fernando Gont on behalf of SI6 Networks <http://www.si6networks.com>\n"
775 "Please send any bug reports to <fgont@si6networks.com>\n"
776 );
777 }
778
779
780
781
782 /*
783 * Function: print_attack_info()
784 *
785 * Prints attack details (when the verbose ("-v") option is specified).
786 */
787
788 void print_attack_info(void){
789 if(ether_ntop(&(idata.hsrcaddr), plinkaddr, sizeof(plinkaddr)) == 0){
790 puts("ether_ntop(): Error converting address");
791 exit(EXIT_FAILURE);
792 }
793
794 printf("Ethernet Source Address: %s%s\n", plinkaddr, (!idata.hsrcaddr_f)?" (automatically selected)":"");
795
796 /*
797 Ethernet Destination Address only used if a IPv6 Destination Address or an
798 Ethernet Destination Address were specified.
799 */
800 if(ether_ntop(&(idata.hdstaddr), plinkaddr, sizeof(plinkaddr)) == 0){
801 puts("ether_ntop(): Error converting address");
802 exit(EXIT_FAILURE);
803 }
804
805 printf("Ethernet Destination Address: %s%s\n", plinkaddr, (!idata.hdstaddr_f)?" (automatically selected)":"");
806
807 if(inet_ntop(AF_INET6, &(idata.srcaddr), psrcaddr, sizeof(psrcaddr)) == NULL){
808 puts("inet_ntop(): Error converting IPv6 Source Address to presentation format");
809 exit(EXIT_FAILURE);
810 }
811
812 if(idata.dstaddr_f){
813 printf("IPv6 Source Address: %s%s\n", psrcaddr, ((!idata.srcaddr_f)?" (automatically selected)":""));
814 }
815
816 if(inet_ntop(AF_INET6, &(idata.dstaddr), pdstaddr, sizeof(pdstaddr)) == NULL){
817 puts("inet_ntop(): Error converting IPv6 Destination Address to presentation format");
818 exit(EXIT_FAILURE);
819 }
820
821 printf("IPv6 Destination Address: %s\n", pdstaddr);
822
823 printf("IPv6 Hop Limit: %u%s\n", hoplimit, (hoplimit_f)?"":" (randomized)");
824
825 printf("Protocol: %s\tDestination Port: %u\n", (protocol==IPPROTO_TCP)?"TCP":"UDP", dstport);
826 }
827
828
829
830 /*
831 * Function: predict_flow_id()
832 *
833 * Identifies and prints the Flow Label generation policy
834 */
835 int predict_flow_id(uint32_t *s1, unsigned int n1, uint32_t *s2, unsigned int n2){
836 uint32_t diff1_avg, diff2_avg;
837 double diff1_sdev, diff2_sdev;
838
839 if(inc_sdev(s1, n1, &diff1_avg, &diff1_sdev) == -1){
840 if(idata.verbose_f)
841 puts("Error while allocating memory in inc_sdev()");
842
843 return(-1);
844 }
845
846 if(inc_sdev(s2, n2, &diff2_avg, &diff2_sdev) == -1){
847 if(idata.verbose_f)
848 puts("Error while allocating memory in inc_sdev()");
849
850 return(-1);
851 }
852
853 if(diff1_sdev == 0 && diff1_avg == 0){
854 if(diff2_sdev == 0 && diff2_avg == 0){
855 printf("Flow Label policy: Global (predictable) constant labels, set to %05lu\n", (LUI) s1[0]);
856 }
857 else{
858 printf("Flow Label policy: Per-destination constant labels with increments of %lu (sdev: %f)\n", \
859 (LUI) diff2_avg, diff2_sdev);
860 }
861 }
862
863 else if(diff1_sdev <= 100){
864 if(diff2_sdev <= 100){
865 printf("Flow Label policy: Global (predictable) labels with increments of %lu (sdev: %f)\n", \
866 (LUI) diff1_avg, diff1_sdev);
867 }
868 else{
869 printf("Flow Label policy: Per-destination labels with increments of %lu (sdev: %f)\n", \
870 (LUI) diff1_avg, diff1_sdev);
871 printf(" Global policy: Avg. inc.: %lu, sdev: %f\n", (LUI) diff2_avg, diff2_sdev);
872 }
873 }
874 else{
875 puts("Flow Label policy: Randomized labels");
876 printf(" Per-destination: Avg. inc.: %lu, sdev: %f\n"
877 " Global: Avg. inc.: %lu, sdev: %f\n", \
878 (LUI) diff1_avg, diff1_sdev, (LUI) diff2_avg, diff2_sdev);
879 }
880
881 return(0);
882 }
883
884
885