+/*
+ * https://tools.ietf.org/html/rfc6052#section-2
+ * https://tools.ietf.org/html/rfc6147#section-5.2
+ */
+static boolean_t
+mptcp_desynthesize_ipv6_addr(const struct in6_addr *addr,
+ const struct ipv6_prefix *prefix,
+ struct in_addr *addrv4)
+{
+ char buf[MAX_IPv4_STR_LEN];
+ char *ptrv4 = (char *)addrv4;
+ const char *ptr = (const char *)addr;
+
+ if (memcmp(addr, &prefix->ipv6_prefix, prefix->prefix_len) != 0)
+ return false;
+
+ switch (prefix->prefix_len) {
+ case NAT64_PREFIX_LEN_96:
+ memcpy(ptrv4, ptr + 12, 4);
+ break;
+ case NAT64_PREFIX_LEN_64:
+ memcpy(ptrv4, ptr + 9, 4);
+ break;
+ case NAT64_PREFIX_LEN_56:
+ memcpy(ptrv4, ptr + 7, 1);
+ memcpy(ptrv4 + 1, ptr + 9, 3);
+ break;
+ case NAT64_PREFIX_LEN_48:
+ memcpy(ptrv4, ptr + 6, 2);
+ memcpy(ptrv4 + 2, ptr + 9, 2);
+ break;
+ case NAT64_PREFIX_LEN_40:
+ memcpy(ptrv4, ptr + 5, 3);
+ memcpy(ptrv4 + 3, ptr + 9, 1);
+ break;
+ case NAT64_PREFIX_LEN_32:
+ memcpy(ptrv4, ptr + 4, 4);
+ break;
+ default:
+ panic("NAT64-prefix len is wrong: %u\n",
+ prefix->prefix_len);
+ }
+
+ os_log_info(mptcp_log_handle, "%s desynthesized to %s\n", __func__,
+ inet_ntop(AF_INET, (void *)addrv4, buf, sizeof(buf)));
+
+ return true;
+}
+
+static void
+mptcp_handle_ipv6_connection(struct mptses *mpte, const struct mptsub *mpts)
+{
+ struct ipv6_prefix nat64prefixes[NAT64_MAX_NUM_PREFIXES];
+ struct socket *so = mpts->mpts_socket;
+ struct ifnet *ifp;
+ int j;
+
+ ifp = sotoinpcb(so)->inp_last_outifp;
+
+ if (ifnet_get_nat64prefix(ifp, nat64prefixes) == ENOENT) {
+ mptcp_ask_for_nat64(ifp);
+ return;
+ }
+
+
+ for (j = 0; j < NAT64_MAX_NUM_PREFIXES; j++) {
+ int success;
+
+ if (nat64prefixes[j].prefix_len == 0)
+ continue;
+
+ success = mptcp_desynthesize_ipv6_addr(&mpte->__mpte_dst_v6.sin6_addr,
+ &nat64prefixes[j],
+ &mpte->mpte_dst_v4_nat64.sin_addr);
+ if (success) {
+ mpte->mpte_dst_v4_nat64.sin_len = sizeof(mpte->mpte_dst_v4_nat64);
+ mpte->mpte_dst_v4_nat64.sin_family = AF_INET;
+ mpte->mpte_dst_v4_nat64.sin_port = mpte->__mpte_dst_v6.sin6_port;
+ break;
+ }
+ }
+}
+