+static int
+create_natoa_payloads(struct ph2handle *iph2, vchar_t **natoa_i, vchar_t **natoa_r)
+{
+ int natoa_type = 0;
+ int natt_type;
+ vchar_t *i;
+ vchar_t *r;
+ u_int8_t *p;
+ size_t src_size;
+ size_t dst_size;
+
+ *natoa_i = *natoa_r = NULL;
+
+
+ /* create natoa payloads if natt being used */
+ /* don't send if type == apple */
+ if ((natt_type = natd_hasnat(iph2->ph1)) != 0)
+ if (natt_type == natt_type_rfc)
+ natoa_type = ISAKMP_NPTYPE_NATOA_RFC;
+ else if (natt_type == natt_type_02 || natt_type == natt_type_02N)
+ natoa_type = ISAKMP_NPTYPE_NATOA_DRAFT;
+
+ if (natoa_type == 0)
+ return 0;
+
+ switch (iph2->src->sa_family) {
+ case AF_INET:
+ src_size = sizeof(in_addr_t);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ src_size = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid address family: %d\n", iph2->src->sa_family);
+ return -1;
+ }
+
+ switch (iph2->dst->sa_family) {
+ case AF_INET:
+ dst_size = sizeof(in_addr_t);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ dst_size = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid address family: %d\n", iph2->dst->sa_family);
+ return -1;
+ }
+
+ i = vmalloc(sizeof(struct isakmp_pl_natoa) + src_size - sizeof(struct isakmp_gen));
+ r = vmalloc(sizeof(struct isakmp_pl_natoa) + dst_size - sizeof(struct isakmp_gen));
+ if (i == NULL || r == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get buffer for natoa payload.\n");
+ return -1;
+ }
+
+ /* copy src address */
+ p = i->v;
+
+ switch (iph2->src->sa_family) {
+ case AF_INET:
+ *p = IPSECDOI_ID_IPV4_ADDR;
+ bcopy(&(((struct sockaddr_in *)iph2->src)->sin_addr.s_addr), p + sizeof(u_int32_t), src_size);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ *p = IPSECDOI_ID_IPV6_ADDR;
+ bcopy(&(((struct sockaddr_in6 *)iph2->src)->sin6_addr), p + sizeof(u_int32_t), src_size);
+ break;
+#endif
+ }
+
+ /* copy dst address */
+ p = r->v;
+
+ switch (iph2->dst->sa_family) {
+ case AF_INET:
+ *p = IPSECDOI_ID_IPV4_ADDR;
+ bcopy(&(((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr), p + sizeof(u_int32_t), dst_size);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ *p = IPSECDOI_ID_IPV6_ADDR;
+ bcopy(&(((struct sockaddr_in6 *)iph2->dst)->sin6_addr), p + sizeof(u_int32_t), dst_size);
+ break;
+#endif
+ }
+
+ *natoa_i = i;
+ *natoa_r = r;
+ return natoa_type;
+}
+
+
+