Print this page
Current snapshot of OpenSolaris port.
Checkpoint
Checkpoint
Merge from parent.
Merge with WIDE update.
Pull from WIDE.
Pull from WIDE.
Checkpoint
Re-update.
blah
WIDE update
Update from WIDE.
@@ -61,14 +61,20 @@
# include <netinet6/ipsec.h>
#else
# ifdef HAVE_NETIPSEC_IPSEC_H
# include <netipsec/ipsec.h>
# else
+# ifndef sun /* XXX KEBE SAYS OpenSolaris */
# include <linux/ipsec.h>
# endif
+# endif
#endif
+#ifdef sun /* XXX KEBE SAYS OpenSolaris */
+#define IPSEC_ULPROTO_ANY 0
+#endif
+
#include "racoon.h"
#include "var.h"
/* #include "vmbuf.h" */
/* #include "schedule.h" */
@@ -95,10 +101,15 @@
#include "proposal.h"
/* #include "sainfo.h" */
/* #include "admin.h" */
#include "strnames.h"
+#ifdef sun
+#include "ikev1_natt.h"
+#define IPSECDOI_PREFIX_HOST 32 /* Hack for port of NAT-OA from ipsec-tools. */
+#endif
+
#include "ike_conf.h"
/* quick mode */
static rc_vchar_t *quick_ir1mx (struct ph2handle *, rc_vchar_t *, rc_vchar_t *);
static int get_sainfo_r (struct ph2handle *);
@@ -185,11 +196,11 @@
return error;
}
/*
* send to responder
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_i1send(struct ph2handle *iph2, rc_vchar_t *msg /* must be null pointer */)
{
rc_vchar_t *body = NULL;
@@ -199,10 +210,15 @@
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
int pfsgroup, idci, idcr;
int np;
struct ipsecdoi_id_b *id, *id_p;
+#ifdef sun
+ int natoa = ISAKMP_NPTYPE_NONE;
+ rc_vchar_t *nat_oai = NULL;
+ rc_vchar_t *nat_oar = NULL;
+#endif
/* validity check */
if (msg != NULL) {
plog(PLOG_INTERR, PLOGLOC, NULL,
"msg has to be NULL in this function.\n");
@@ -273,19 +289,61 @@
&& ipsecdoi_transportmode(iph2->proposal)) {
idci = idcr = 0;
} else
idci = idcr = 1;
+#ifdef sun
+ /*
+ * RFC3947 5.2. if we propose UDP-Encapsulated-Transport
+ * we should send NAT-OA
+ *
+ * XXX KEBE ASKS if we should send it for tunnel mode anyway, like
+ * we do with in.iked?
+ */
+ if (ipsecdoi_transportmode(iph2->proposal)
+ && (iph2->ph1->natt_flags & NAT_DETECTED)) {
+ natoa = iph2->ph1->natt_options->payload_nat_oa;
+
+ nat_oai = ipsecdoi_sockaddr2id(iph2->src,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+ nat_oar = ipsecdoi_sockaddr2id(iph2->dst,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+
+ if (nat_oai == NULL || nat_oar == NULL) {
+ plog(PLOG_INTERR, PLOGLOC, NULL,
+ "failed to generate NAT-OA payload.\n");
+ goto end;
+ }
+
+ plog(PLOG_INFO, PLOGLOC, NULL, "Using NAT-OA.\n");
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAi:\n");
+ plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oai->v, nat_oai->l);
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAr:\n");
+ plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oar->v, nat_oar->l);
+ } else {
+ plog(PLOG_INFO, PLOGLOC, NULL, "Not using NAT-OA.\n");
+ plog(PLOG_INFO, PLOGLOC, NULL, "transportmode == %d, "
+ "natt_flags == 0x%x\n",
+ ipsecdoi_transportmode(iph2->proposal),
+ iph2->ph1->natt_flags & NAT_DETECTED);
+ natoa = ISAKMP_NPTYPE_NONE;
+ }
+#endif
+
/* create SA;NONCE payload, and KE if need, and IDii, IDir. */
tlen = + sizeof(*gen) + iph2->sa->l
+ sizeof(*gen) + iph2->nonce->l;
if (pfsgroup)
tlen += (sizeof(*gen) + iph2->dhpub->l);
if (idci)
tlen += sizeof(*gen) + iph2->id->l;
if (idcr)
tlen += sizeof(*gen) + iph2->id_p->l;
+#ifdef sun
+ if (natoa != ISAKMP_NPTYPE_NONE)
+ tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
+#endif
body = rc_vmalloc(tlen);
if (body == NULL) {
plog(PLOG_INTERR, PLOGLOC, NULL,
"failed to get buffer to send.\n");
@@ -301,27 +359,35 @@
if (pfsgroup)
np = ISAKMP_NPTYPE_KE;
else if (idci || idcr)
np = ISAKMP_NPTYPE_ID;
else
- np = ISAKMP_NPTYPE_NONE;
+ np = natoa;
p = set_isakmp_payload(p, iph2->nonce, np);
/* add KE payload if need. */
- np = (idci || idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+ np = (idci || idcr) ? ISAKMP_NPTYPE_ID : natoa;
if (pfsgroup)
p = set_isakmp_payload(p, iph2->dhpub, np);
/* IDci */
- np = (idcr) ? ISAKMP_NPTYPE_ID : ISAKMP_NPTYPE_NONE;
+ np = (idcr) ? ISAKMP_NPTYPE_ID : natoa;
if (idci)
p = set_isakmp_payload(p, iph2->id, np);
/* IDcr */
if (idcr)
- p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_NONE);
+ p = set_isakmp_payload(p, iph2->id_p, natoa);
+#ifdef sun
+ /* NAT-OA */
+ if (natoa != ISAKMP_NPTYPE_NONE) {
+ p = set_isakmp_payload(p, nat_oai, natoa);
+ p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
+ }
+#endif
+
/* generate HASH(1) */
hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, body);
if (hash == NULL)
goto end;
@@ -343,28 +409,33 @@
end:
if (body != NULL)
rc_vfree(body);
if (hash != NULL)
rc_vfree(hash);
+ if (nat_oai != NULL)
+ rc_vfree(nat_oai);
+ if (nat_oar != NULL)
+ rc_vfree(nat_oar);
return error;
}
/*
* receive from responder
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_i2recv(struct ph2handle *iph2, rc_vchar_t *msg0)
{
rc_vchar_t *msg = NULL;
rc_vchar_t *hbuf = NULL; /* for hash computing. */
rc_vchar_t *pbuf = NULL; /* for payload parsing */
+ rc_vchar_t *idci = NULL;
+ rc_vchar_t *idcr = NULL;
struct isakmp_parse_t *pa;
struct isakmp *isakmp = (struct isakmp *)msg0->v;
struct isakmp_pl_hash *hash = NULL;
- int f_id;
char *p;
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
/* validity check */
@@ -437,11 +508,10 @@
/*
* parse the payloads.
* copy non-HASH payloads into hbuf, so that we can validate HASH.
*/
iph2->sa_ret = NULL;
- f_id = 0; /* flag to use checking ID */
tlen = 0; /* count payload length except of HASH payload. */
for (; pa->type; pa++) {
/* copy to buffer for HASH */
/* Don't modify the payload */
@@ -468,41 +538,64 @@
if (isakmp_p2ph(&iph2->dhpub_p, pa->ptr) < 0)
goto end;
break;
case ISAKMP_NPTYPE_ID:
- {
- rc_vchar_t *vp;
-
- /* check ID value */
- if (f_id == 0) {
- /* for IDci */
- f_id = 1;
- vp = iph2->id;
+ if (idci == NULL) {
+ if (isakmp_p2ph(&idci, pa->ptr) < 0)
+ goto end;
+ } else if (idcr == NULL) {
+ if (isakmp_p2ph(&idcr, pa->ptr) < 0)
+ goto end;
} else {
- /* for IDcr */
- vp = iph2->id_p;
}
-
- if (memcmp(vp->v, (caddr_t)pa->ptr + sizeof(struct isakmp_gen), vp->l)) {
-
- plog(PLOG_PROTOERR, PLOGLOC, NULL,
- "mismatched ID was returned.\n");
- error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
- goto end;
- }
- }
break;
case ISAKMP_NPTYPE_N:
isakmp_check_notify(pa->ptr, iph2->ph1);
break;
#ifdef ENABLE_NATT
case ISAKMP_NPTYPE_NATOA_DRAFT:
case ISAKMP_NPTYPE_NATOA_RFC:
+#ifdef sun
+ /* DON'T ignore original source/destination. */
+ {
+ struct sockaddr_storage addr;
+ struct sockaddr *daddr;
+ uint8_t prefix;
+ uint16_t ul_proto;
+ rc_vchar_t *vp = NULL;
+
+ if (isakmp_p2ph(&vp, pa->ptr) < 0)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(vp,
+ (struct sockaddr *) &addr,
+ &prefix, &ul_proto);
+
+ rc_vfree(vp);
+
+ if (error)
+ goto end;
+
+ daddr = rcs_sadup((struct sockaddr *) &addr);
+ if (daddr == NULL)
+ goto end;
+
+ if (iph2->natoa_src == NULL)
+ iph2->natoa_src = daddr;
+ else if (iph2->natoa_dst == NULL)
+ iph2->natoa_dst = daddr;
+ else {
+ racoon_free(daddr);
+ goto end;
+ }
+ }
+#else
/* Ignore original source/destination messages */
+#endif
break;
#endif
default:
/* don't send information, see ident_r1recv() */
@@ -526,10 +619,102 @@
PLOG_PROTOERR, PLOGLOC,
"few isakmp message received.\n");
goto end;
}
+ /* identity check */
+ if (idci != NULL) {
+ struct sockaddr_storage proposed_addr, got_addr;
+ uint8_t proposed_prefix, got_prefix;
+ uint16_t proposed_ulproto, got_ulproto;
+
+ error = ipsecdoi_id2sockaddr(iph2->id,
+ (struct sockaddr *) &proposed_addr,
+ &proposed_prefix, &proposed_ulproto);
+ if (error)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(idci,
+ (struct sockaddr *) &got_addr,
+ &got_prefix, &got_ulproto);
+ if (error)
+ goto end;
+
+ if (proposed_prefix != got_prefix
+ || proposed_ulproto != got_ulproto) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDci prefix/ulproto does not match proposal.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+
+ if (rcs_cmpsa((struct sockaddr *) &proposed_addr,
+ (struct sockaddr *) &got_addr) == 0) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDci matches proposal.\n");
+#ifdef ENABLE_NATT
+ } else if (iph2->natoa_src != NULL
+ && rcs_cmpsa_wop(iph2->natoa_src,
+ (struct sockaddr *) &got_addr) == 0
+ && extract_port((struct sockaddr *) &proposed_addr) ==
+ extract_port((struct sockaddr *) &got_addr)) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDci matches NAT-OAi.\n");
+#endif
+ } else {
+ plog(PLOG_INTERR, PLOGLOC, NULL,
+ "mismatched IDci was returned.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+ }
+ if (idcr != NULL) {
+ struct sockaddr_storage proposed_addr, got_addr;
+ uint8_t proposed_prefix, got_prefix;
+ uint16_t proposed_ulproto, got_ulproto;
+
+ error = ipsecdoi_id2sockaddr(iph2->id_p,
+ (struct sockaddr *) &proposed_addr,
+ &proposed_prefix, &proposed_ulproto);
+ if (error)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(idcr,
+ (struct sockaddr *) &got_addr,
+ &got_prefix, &got_ulproto);
+ if (error)
+ goto end;
+
+ if (proposed_prefix != got_prefix
+ || proposed_ulproto != got_ulproto) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDcr prefix/ulproto does not match proposal.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+
+ if (rcs_cmpsa((struct sockaddr *) &proposed_addr,
+ (struct sockaddr *) &got_addr) == 0) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDcr matches proposal.\n");
+#ifdef ENABLE_NATT
+ } else if (iph2->natoa_dst != NULL
+ && rcs_cmpsa_wop(iph2->natoa_dst,
+ (struct sockaddr *) &got_addr) == 0
+ && extract_port((struct sockaddr *) &proposed_addr) ==
+ extract_port((struct sockaddr *) &got_addr)) {
+ plog(PLOG_DEBUG, PLOGLOC, NULL,
+ "IDcr matches NAT-OAr.\n");
+#endif
+ } else {
+ plog(PLOG_INTERR, PLOGLOC, NULL,
+ "mismatched IDcr was returned.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }
+ }
+
/* Fixed buffer for calculating HASH */
memcpy(hbuf->v, iph2->nonce->v, iph2->nonce->l);
plog(PLOG_DEBUG, PLOGLOC, NULL,
"HASH allocated:hbuf->l=%d actual:tlen=%d\n",
hbuf->l, tlen + iph2->nonce->l);
@@ -579,22 +764,67 @@
rc_vfree(hbuf);
if (pbuf)
rc_vfree(pbuf);
if (msg)
rc_vfree(msg);
+ if (idci)
+ rc_vfree(idci);
+ if (idcr)
+ rc_vfree(idcr);
if (error) {
VPTRINIT(iph2->sa_ret);
VPTRINIT(iph2->nonce_p);
VPTRINIT(iph2->dhpub_p);
VPTRINIT(iph2->id);
VPTRINIT(iph2->id_p);
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
}
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
+ }
+#endif
+ }
return error;
}
+static int
+fill_in_ipsec_sas(struct ph2handle *iph2)
+{
+ /*
+ * NOTE: The OpenSolaris kernel can queue up packets on a larval SA
+ * such that when the SA is filled-in via SADB_UPDATE, these packets
+ * can be immediately processed. If the reply packet is generated
+ * in-kernel (e.g. ICMP_ECHO processing), an additonal ACQUIRE can
+ * be sent if there is not a corresponding outbound SA waiting in
+ * the wings. We therefore perform SADB_ADD first so that if an
+ * outbound SA is needed immediately during SADB_UPDATE processing,
+ * it is ready.
+ */
+
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendadd\n");
+ if (pk_sendadd(iph2) < 0) {
+ plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey add failed.\n");
+ return (-1);
+ }
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey add sent.\n");
+
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendupdate\n");
+ if (pk_sendupdate(iph2) < 0) {
+ plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey update failed.\n");
+ return (-1);
+ }
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey update sent.\n");
+
+ return (0);
+}
+
/*
* send to responder
* HDR*, HASH(3)
*/
int
@@ -702,27 +932,13 @@
iph2->status = PHASE2ST_COMMIT;
error = 0;
goto end;
}
- /* Do UPDATE for initiator */
- plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendupdate\n");
- if (pk_sendupdate(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey update failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey update sent.\n");
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
+ error = fill_in_ipsec_sas(iph2);
- /* Do ADD for responder */
- if (pk_sendadd(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey add failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey add sent.\n");
-
- error = 0;
-
end:
if (buf != NULL)
rc_vfree(buf);
if (msg != NULL)
rc_vfree(msg);
@@ -849,27 +1065,13 @@
error = 0;
goto end;
}
#endif
- /* Do UPDATE for initiator */
- plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendupdate\n");
- if (pk_sendupdate(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey update failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey update sent.\n");
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
+ error = fill_in_ipsec_sas(iph2);
- /* Do ADD for responder */
- if (pk_sendadd(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey add failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey add sent.\n");
-
- error = 0;
-
end:
if (msg != NULL)
rc_vfree(msg);
if (pbuf != NULL)
rc_vfree(pbuf);
@@ -879,11 +1081,11 @@
return error;
}
/*
* receive from initiator
- * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(1), SA, Ni [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_r1recv(struct ph2handle *iph2, rc_vchar_t *msg0)
{
rc_vchar_t *msg = NULL;
@@ -1049,11 +1251,46 @@
break;
#ifdef ENABLE_NATT
case ISAKMP_NPTYPE_NATOA_DRAFT:
case ISAKMP_NPTYPE_NATOA_RFC:
+#ifdef sun
+ {
+ struct sockaddr_storage addr;
+ struct sockaddr *daddr;
+ uint8_t prefix;
+ uint16_t ul_proto;
+ rc_vchar_t *vp = NULL;
+
+ if (isakmp_p2ph(&vp, pa->ptr) < 0)
+ goto end;
+
+ error = ipsecdoi_id2sockaddr(vp,
+ (struct sockaddr *) &addr,
+ &prefix, &ul_proto);
+
+ rc_vfree(vp);
+
+ if (error)
+ goto end;
+
+ daddr = rcs_sadup((struct sockaddr *) &addr);
+ if (daddr == NULL)
+ goto end;
+
+ if (iph2->natoa_dst == NULL)
+ iph2->natoa_dst = daddr;
+ else if (iph2->natoa_src == NULL)
+ iph2->natoa_src = daddr;
+ else {
+ racoon_free(daddr);
+ goto end;
+ }
+ }
+#else
/* Ignore original source/destination messages */
+#endif
break;
#endif
default:
isakmp_log(0, 0, iph2->ph1->remote, 0,
@@ -1117,10 +1354,11 @@
error = ISAKMP_NTYPE_INVALID_HASH_INFORMATION;
goto end;
}
}
+#ifndef sun
/* get sainfo */
error = get_sainfo_r(iph2);
if (error) {
plog(PLOG_PROTOERR, PLOGLOC, NULL,
"failed to get sainfo.\n");
@@ -1165,20 +1403,21 @@
plog(PLOG_PROTOERR, PLOGLOC, NULL,
"PFS is specified, but peer doesn't sends KE.\n");
error = ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN;
goto end;
}
+ /* change status of isakmp status entry */
+ iph2->status = PHASE2ST_STATUS2;
+#endif /* sun/OpenSolaris */
+
/*
* save the packet from the initiator in order to resend the
* responder's first packet against this packet.
*/
iph2->msg1 = rc_vdup(msg0);
- /* change status of isakmp status entry */
- iph2->status = PHASE2ST_STATUS2;
-
error = 0;
end:
if (hbuf)
rc_vfree(hbuf);
@@ -1191,11 +1430,21 @@
VPTRINIT(iph2->sa);
VPTRINIT(iph2->nonce_p);
VPTRINIT(iph2->dhpub_p);
VPTRINIT(iph2->id);
VPTRINIT(iph2->id_p);
+#ifdef ENABLE_NATT
+ if (iph2->natoa_src) {
+ racoon_free(iph2->natoa_src);
+ iph2->natoa_src = NULL;
}
+ if (iph2->natoa_dst) {
+ racoon_free(iph2->natoa_dst);
+ iph2->natoa_dst = NULL;
+ }
+#endif
+ }
return error;
}
/*
@@ -1230,11 +1479,11 @@
return error;
}
/*
* send to initiator
- * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ]
+ * HDR*, HASH(2), SA, Nr [, KE ] [, IDi2, IDr2 ] [, NAT-OAi, NAT-OAr ]
*/
int
quick_r2send(struct ph2handle *iph2, rc_vchar_t *msg)
{
rc_vchar_t *body = NULL;
@@ -1241,12 +1490,17 @@
rc_vchar_t *hash = NULL;
struct isakmp_gen *gen;
char *p;
int tlen;
int error = ISAKMP_INTERNAL_ERROR;
+ int natoa = ISAKMP_NPTYPE_NONE;
int pfsgroup;
uint8_t *np_p = NULL;
+#ifdef ENABLE_NATT
+ rc_vchar_t *nat_oai = NULL;
+ rc_vchar_t *nat_oar = NULL;
+#endif
/* validity check */
if (msg != NULL) {
plog(PLOG_INTERR, PLOGLOC, NULL,
"msg has to be NULL in this function.\n");
@@ -1283,19 +1537,51 @@
&iph2->dhpub, &iph2->dhpriv) < 0) {
goto end;
}
}
+#ifdef ENABLE_NATT
+ /*
+ * RFC3947 5.2. if we chose UDP-Encapsulated-Transport
+ * we should send NAT-OA
+ */
+ if (ipsecdoi_transportmode(iph2->proposal)
+ && (iph2->ph1->natt_flags & NAT_DETECTED)) {
+ natoa = iph2->ph1->natt_options->payload_nat_oa;
+
+ nat_oai = ipsecdoi_sockaddr2id(iph2->dst,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+ nat_oar = ipsecdoi_sockaddr2id(iph2->src,
+ IPSECDOI_PREFIX_HOST, IPSEC_ULPROTO_ANY);
+
+ if (nat_oai == NULL || nat_oar == NULL) {
+ plog(PLOG_INTERR, PLOGLOC, NULL,
+ "failed to generate NAT-OA payload.\n");
+ goto end;
+ }
+
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "NAT-OAi:\n");
+ plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oai->v, nat_oai->l);
+ plog(PLOG_DEBUG, PLOGLOC, 0, NULL, "NAT-OAr:\n");
+ plogdump(PLOG_DEBUG, PLOGLOC, 0, nat_oar->v, nat_oar->l);
+ }
+#endif
+
/* create SA;NONCE payload, and KE and ID if need */
tlen = sizeof(*gen) + iph2->sa_ret->l
+ sizeof(*gen) + iph2->nonce->l;
if (iph2->dhpub_p != NULL && pfsgroup != 0)
tlen += (sizeof(*gen) + iph2->dhpub->l);
if (iph2->id_p != NULL)
tlen += (sizeof(*gen) + iph2->id_p->l
+ sizeof(*gen) + iph2->id->l);
+#ifdef ENABLE_NATT
+ if (natoa != ISAKMP_NPTYPE_NONE)
+ tlen += 2 * sizeof(*gen) + nat_oai->l + nat_oar->l;
+#endif
+
body = rc_vmalloc(tlen);
if (body == NULL) {
plog(PLOG_INTERR, PLOGLOC, NULL,
"failed to get buffer to send.\n");
goto end;
@@ -1310,29 +1596,36 @@
p = set_isakmp_payload(p, iph2->nonce,
(iph2->dhpub_p != NULL && pfsgroup != 0)
? ISAKMP_NPTYPE_KE
: (iph2->id_p != NULL
? ISAKMP_NPTYPE_ID
- : ISAKMP_NPTYPE_NONE));
+ : natoa));
/* add KE payload if need. */
if (iph2->dhpub_p != NULL && pfsgroup != 0) {
np_p = &((struct isakmp_gen *)p)->np; /* XXX */
p = set_isakmp_payload(p, iph2->dhpub,
(iph2->id_p == NULL)
- ? ISAKMP_NPTYPE_NONE
+ ? natoa
: ISAKMP_NPTYPE_ID);
}
/* add ID payloads received. */
if (iph2->id_p != NULL) {
/* IDci */
p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
/* IDcr */
np_p = &((struct isakmp_gen *)p)->np; /* XXX */
- p = set_isakmp_payload(p, iph2->id, ISAKMP_NPTYPE_NONE);
+ p = set_isakmp_payload(p, iph2->id, natoa);
}
+#ifdef ENABLE_NATT
+ /* NAT-OA */
+ if (natoa != ISAKMP_NPTYPE_NONE) {
+ p = set_isakmp_payload(p, nat_oai, natoa);
+ p = set_isakmp_payload(p, nat_oar, ISAKMP_NPTYPE_NONE);
+ }
+#endif
/* add a RESPONDER-LIFETIME notify payload if needed */
{
rc_vchar_t *data = NULL;
struct saprop *pp = iph2->approval;
@@ -1423,10 +1716,16 @@
end:
if (body != NULL)
rc_vfree(body);
if (hash != NULL)
rc_vfree(hash);
+#ifdef ENABLE_NATT
+ if (nat_oai != NULL)
+ rc_vfree(nat_oai);
+ if (nat_oar != NULL)
+ rc_vfree(nat_oar);
+#endif
return error;
}
/*
@@ -1692,27 +1991,13 @@
"generate policy failed.\n");
goto end;
}
}
- /* Do UPDATE as responder */
- plog(PLOG_DEBUG, PLOGLOC, NULL, "call pk_sendupdate\n");
- if (pk_sendupdate(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey update failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey update sent.\n");
+ plog(PLOG_DEBUG, PLOGLOC, NULL, "call fill_in_ipsec_sas");
+ error = fill_in_ipsec_sas(iph2);
- /* Do ADD for responder */
- if (pk_sendadd(iph2) < 0) {
- plog(PLOG_INTERR, PLOGLOC, NULL, "pfkey add failed.\n");
- goto end;
- }
- plog(PLOG_DEBUG, PLOGLOC, NULL, "pfkey add sent.\n");
-
- error = 0;
-
end:
if (msg != NULL)
rc_vfree(msg);
return error;
@@ -2124,11 +2409,11 @@
plog(LLV_INFO, LOCATION, NULL,
"Update the generated policy : %s\n",
spidx2str(&spidx));
iph2->spidx_gen = racoon_malloc(sizeof(spidx));
if (!iph2->spidx_gen) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(PLOG_INTERR, PLOGLOC, NULL,
"buffer allocation failed.\n");
return ISAKMP_INTERNAL_ERROR;
}
memcpy(iph2->spidx_gen, &spidx, sizeof(spidx));
}
@@ -2174,11 +2459,11 @@
"failed to create saprop.\n");
return ISAKMP_INTERNAL_ERROR;
}
return 0;
-#endif
+#endif /* 0 */
}
#ifdef INET6
static uint32_t
setscopeid(struct sockaddr *sp_addr0, struct sockaddr *sa_addr0)