+#if ENABLE_TRACEROUTE6
+# if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
+#define packet_ok(read_len, from_lsa, to, seq) \
+ packet_ok(read_len, from_lsa, seq)
+# endif
+static int
+packet_ok(int read_len, len_and_sockaddr *from_lsa,
+ struct sockaddr *to,
+ int seq)
+{
+ const struct icmp6_hdr *icp;
+ unsigned char type, code;
+
+ if (from_lsa->u.sa.sa_family == AF_INET)
+ return packet4_ok(read_len, &from_lsa->u.sin, seq);
+
+ icp = (struct icmp6_hdr *) recv_pkt;
+
+ type = icp->icmp6_type;
+ code = icp->icmp6_code;
+
+ if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
+ || type == ICMP6_DST_UNREACH
+ ) {
+ struct ip6_hdr *hip;
+ struct udphdr *up;
+ int nexthdr;
+
+ hip = (struct ip6_hdr *)(icp + 1);
+ up = (struct udphdr *) (hip + 1);
+ nexthdr = hip->ip6_nxt;
+
+ if (nexthdr == IPPROTO_FRAGMENT) {
+ nexthdr = *(unsigned char*)up;
+ up++;
+ }
+ if (nexthdr == IPPROTO_UDP) {
+ struct outdata6_t *pkt;
+
+ pkt = (struct outdata6_t *) (up + 1);
+
+ if (ntohl(pkt->ident6) == ident
+ && ntohl(pkt->seq6) == seq
+ ) {
+ return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1);
+ }
+ }
+ }
+
+# if ENABLE_FEATURE_TRACEROUTE_VERBOSE
+ if (verbose) {
+ unsigned char *p;
+ char pa1[MAXHOSTNAMELEN];
+ char pa2[MAXHOSTNAMELEN];
+ int i;
+
+ p = (unsigned char *) (icp + 1);
+
+ printf("\n%d bytes from %s to "
+ "%s: icmp type %d (%s) code %d\n",
+ read_len,
+ inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)),
+ inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)),
+ type, pr_type(type), icp->icmp6_code);
+
+ read_len -= sizeof(struct icmp6_hdr);
+ for (i = 0; i < read_len; i++) {
+ if (i % 16 == 0)
+ printf("%04x:", i);
+ if (i % 4 == 0)
+ bb_putchar(' ');
+ printf("%02x", p[i]);
+ if ((i % 16 == 15) && (i + 1 < read_len))
+ bb_putchar('\n');
+ }
+ bb_putchar('\n');
+ }
+# endif
+
+ return 0;
+}
+#else /* !ENABLE_TRACEROUTE6 */
+static ALWAYS_INLINE int
+packet_ok(int read_len,
+ len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM),
+ struct sockaddr *to UNUSED_PARAM,
+ int seq)
+{
+ return packet4_ok(read_len, &from_lsa->u.sin, seq);
+}
+#endif
+