+ /* enable broadcast pings */
+ setsockopt_broadcast(pingsock);
+
+ /* set recv buf for broadcast pings */
+ sockopt = 48 * 1024; /* explain why 48k? */
+ setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt));
+
+ sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
+ if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2)
+ BUG_bad_offsetof_icmp6_cksum();
+ setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt));
+
+ /* request ttl info to be returned in ancillary data */
+ setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1));
+
+ if (if_index)
+ pingaddr.sin6.sin6_scope_id = if_index;
+
+ signal(SIGINT, pingstats);
+
+ /* start the ping's going ... */
+ sendping6(0);
+
+ /* listen for replies */
+ msg.msg_name = &from;
+ msg.msg_namelen = sizeof(from);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = control_buf;
+ iov.iov_base = packet;
+ iov.iov_len = sizeof(packet);
+ while (1) {
+ int c;
+ struct cmsghdr *mp;
+ int hoplimit = -1;
+ msg.msg_controllen = sizeof(control_buf);
+
+ c = recvmsg(pingsock, &msg, 0);
+ if (c < 0) {
+ if (errno != EINTR)
+ bb_perror_msg("recvfrom");
+ continue;
+ }
+ for (mp = CMSG_FIRSTHDR(&msg); mp; mp = CMSG_NXTHDR(&msg, mp)) {
+ if (mp->cmsg_level == SOL_IPV6
+ && mp->cmsg_type == IPV6_HOPLIMIT
+ /* don't check len - we trust the kernel: */
+ /* && mp->cmsg_len >= CMSG_LEN(sizeof(int)) */
+ ) {
+ hoplimit = *(int*)CMSG_DATA(mp);
+ }
+ }
+ unpack6(packet, c, &from, hoplimit);
+ if (pingcount > 0 && nreceived >= pingcount)