- static char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
- static u_char prefix_v4[5];
- if (prefix[0] >= 96 && max_length >= 13 && EXTRACT_64BITS(prefix+1) == 0x0 && EXTRACT_32BITS(prefix+9) == 0xffff) {
- prefix_v4[0] = prefix[0]-96;
- prefix_v4[1] = prefix[13];
- prefix_v4[2] = prefix[14];
- prefix_v4[3] = prefix[15];
- prefix_v4[4] = prefix[16];
- plenbytes = 12 + decode_prefix4(ndo, (const u_char *)prefix_v4, max_length-12, buf, 45);
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
+ /* First 12 bytes of an IPv4-mapped IPv6 address */
+ static const u_char ipv4_mapped_heading[12] =
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
+
+ if (prefix[0] >= 96 && max_length >= 13 && memcmp(prefix+1, ipv4_mapped_heading, 12) == 0) {
+ struct in_addr addr;
+ u_int plen;
+
+ plen = prefix[0]-96;
+ if (32 < plen)
+ return -1;
+ max_length -= 1;
+
+ memset(&addr, 0, sizeof(addr));
+ plenbytes = (plen + 7) / 8;
+ if (max_length < (u_int)plenbytes)
+ return -3;
+ memcpy(&addr, &prefix[13], plenbytes);
+ if (plen % 8) {
+ ((u_char *)&addr)[plenbytes - 1] &=
+ ((0xff00 >> (plen % 8)) & 0xff);
+ }
+ snprintf(buf, sizeof(buf), "%s/%d", ipaddr_string(ndo, &addr), plen);
+ plenbytes += 13;