+
+ /* These ids may not match when natt is used with some devices.
+ * RFC 2407 says that the protocol and port fields should be ignored
+ * if they are zero, therefore they need to be checked individually.
+ */
+ struct ipsecdoi_id_b *id_ptr = (struct ipsecdoi_id_b *)vp->v;
+ struct ipsecdoi_pl_id *idp_ptr = (struct ipsecdoi_pl_id *)pa->ptr;
+
+ if (id_ptr->type != idp_ptr->b.type
+ || (idp_ptr->b.proto_id != 0 && idp_ptr->b.proto_id != id_ptr->proto_id)
+ || (idp_ptr->b.port != 0 && idp_ptr->b.port != id_ptr->port)
+ || memcmp(vp->v + sizeof(struct ipsecdoi_id_b), (caddr_t)pa->ptr + sizeof(struct ipsecdoi_pl_id),
+ vp->l - sizeof(struct ipsecdoi_id_b))) {
+ // to support servers that use our external nat address as our ID
+ if (iph2->ph1->natt_flags & NAT_DETECTED) {
+ plog(LLV_WARNING, LOCATION, NULL,
+ "mismatched ID was returned - ignored because nat traversal is being used.\n");
+ /* If I'm behind a nat and the ID is type address - save the address
+ * and port for when the peer rekeys.
+ */
+ if (f_id == 0 && (iph2->ph1->natt_flags & NAT_DETECTED_ME)) {
+ if (lcconf->ext_nat_id)
+ vfree(lcconf->ext_nat_id);
+ if (idp_ptr->h.len < sizeof(struct isakmp_gen)) {
+ plog(LLV_ERROR, LOCATION, NULL, "invalid length (%d) while allocating external nat id.\n", idp_ptr->h.len);
+ goto end;
+ }
+ lcconf->ext_nat_id = vmalloc(ntohs(idp_ptr->h.len) - sizeof(struct isakmp_gen));
+ if (lcconf->ext_nat_id == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating external nat id.\n");
+ goto end;
+ }
+ memcpy(lcconf->ext_nat_id->v, &(idp_ptr->b), lcconf->ext_nat_id->l);
+ if (iph2->ext_nat_id)
+ vfree(iph2->ext_nat_id);
+ iph2->ext_nat_id = vdup(lcconf->ext_nat_id);
+ if (iph2->ext_nat_id == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating ph2's external nat id.\n");
+ goto end;
+ }
+ plog(LLV_DEBUG, LOCATION, NULL, "external nat address saved.\n");
+ plogdump(LLV_DEBUG, iph2->ext_nat_id->v, iph2->ext_nat_id->l);
+ } else if (f_id && (iph2->ph1->natt_flags & NAT_DETECTED_PEER)) {
+ if (iph2->ext_nat_id_p)
+ vfree(iph2->ext_nat_id_p);
+ iph2->ext_nat_id_p = vmalloc(ntohs(idp_ptr->h.len) - sizeof(struct isakmp_gen));
+ if (iph2->ext_nat_id_p == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating peers ph2's external nat id.\n");
+ goto end;
+ }
+ memcpy(iph2->ext_nat_id_p->v, &(idp_ptr->b), iph2->ext_nat_id_p->l);
+ plog(LLV_DEBUG, LOCATION, NULL, "peer's external nat address saved.\n");
+ plogdump(LLV_DEBUG, iph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l);
+ }
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL, "mismatched ID was returned.\n");
+ error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+ goto end;
+ }