freeaddrinfo(res);
}
- struct sockaddr_in6 saddr = {.sin6_family = AF_INET6, .sin6_addr = {{{0x20, 0x01, 0x0d, 0xb8}}}};
- socklen_t saddrlen = sizeof(saddr);
- int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
- struct icmp6_filter filt;
- ICMP6_FILTER_SETBLOCKALL(&filt);
- setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));
- setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, argv[2], strlen(argv[2]));
- if (connect(sock, (struct sockaddr*)&saddr, sizeof(saddr)) ||
- getsockname(sock, (struct sockaddr*)&saddr, &saddrlen))
- return 3;
+ int i = 0;
+ int sock;
+ struct sockaddr_in6 saddr;
+
+ do {
+ socklen_t saddrlen = sizeof(saddr);
+ struct icmp6_filter filt;
+
+ sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ ICMP6_FILTER_SETBLOCKALL(&filt);
+ setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));
+ setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, argv[2], strlen(argv[2]));
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sin6_family = AF_INET6;
+ saddr.sin6_addr.s6_addr32[0] = htonl(0x2001);
+ saddr.sin6_addr.s6_addr32[1] = htonl(0xdb8);
+ if (connect(sock, (struct sockaddr*)&saddr, sizeof(saddr)) ||
+ getsockname(sock, (struct sockaddr*)&saddr, &saddrlen))
+ return 3;
+
+ if (!IN6_IS_ADDR_LINKLOCAL(&saddr.sin6_addr) || argv[5])
+ break;
+
+ close(sock);
+ sleep(3);
+ i++;
+ } while (i < 3);
struct ipv6_mreq mreq = {saddr.sin6_addr, if_nametoindex(argv[2])};
if (!argv[5]) {
+ if (IN6_IS_ADDR_LINKLOCAL(&mreq.ipv6mr_multiaddr))
+ return 5;
+
srandom(mreq.ipv6mr_multiaddr.s6_addr32[0] ^ mreq.ipv6mr_multiaddr.s6_addr32[1] ^
mreq.ipv6mr_multiaddr.s6_addr32[2] ^ mreq.ipv6mr_multiaddr.s6_addr32[3]);
mreq.ipv6mr_multiaddr.s6_addr32[2] = random();