+}
+
+static int
+ike_session_is_id_ipany (vchar_t *ext_id)
+{
+ struct id {
+ u_int8_t type; /* ID Type */
+ u_int8_t proto_id; /* Protocol ID */
+ u_int16_t port; /* Port */
+ u_int32_t addr; /* IPv4 address */
+ u_int32_t mask;
+ } *id_ptr;
+
+ /* ignore protocol and port */
+ id_ptr = (struct id *)ext_id->v;
+ if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
+ id_ptr->addr == 0) {
+ return 1;
+ } else if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR_SUBNET &&
+ id_ptr->mask == 0 &&
+ id_ptr->addr == 0) {
+ return 1;
+ }
+ plog(LLV_DEBUG2, LOCATION, NULL, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
+ __FUNCTION__, id_ptr->type, id_ptr->addr, id_ptr->mask);
+ return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
+ vchar_t *ext_id_p)
+{
+ if (ike_session_is_id_ipany(ext_id) &&
+ ike_session_is_id_ipany(ext_id_p)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids (struct ph2handle *iph2,
+ struct ph2handle *older_ph2)
+{
+ if (iph2->id && older_ph2->id &&
+ iph2->id->l == older_ph2->id->l &&
+ memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
+ iph2->id_p && older_ph2->id_p &&
+ iph2->id_p->l == older_ph2->id_p->l &&
+ memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
+ return 0;
+ }
+ if (iph2->ext_nat_id && older_ph2->ext_nat_id &&
+ iph2->ext_nat_id->l == older_ph2->ext_nat_id->l &&
+ memcmp(iph2->ext_nat_id->v, older_ph2->ext_nat_id->v, iph2->ext_nat_id->l) == 0 &&
+ iph2->ext_nat_id_p && older_ph2->ext_nat_id_p &&
+ iph2->ext_nat_id_p->l == older_ph2->ext_nat_id_p->l &&
+ memcmp(iph2->ext_nat_id_p->v, older_ph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l) == 0) {
+ return 0;
+ }
+ if (iph2->id && older_ph2->ext_nat_id &&
+ iph2->id->l == older_ph2->ext_nat_id->l &&
+ memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 &&
+ iph2->id_p && older_ph2->ext_nat_id_p &&
+ iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
+ memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
+ return 0;
+ }
+ return -1;
+}
+
+int
+ike_session_get_sainfo_r (struct ph2handle *iph2)
+{
+ if (iph2->parent_session &&
+ iph2->parent_session->is_client &&
+ iph2->id && iph2->id_p) {
+ struct ph2handle *p;
+ int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p);
+ plog(LLV_DEBUG2, LOCATION, NULL, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__);
+
+ for (p = LIST_FIRST(&iph2->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
+ if (iph2 != p && !p->is_dying && p->status >= PHASE2ST_ESTABLISHED &&
+ p->sainfo && !p->sainfo->to_delete && !p->sainfo->to_remove) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 found in %s.\n", __FUNCTION__);
+ if (ipany_ids ||
+ ike_session_cmp_ph2_ids(iph2, p) == 0) {
+ plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
+ iph2->sainfo = p->sainfo;
+ return 0;
+ }
+ }
+ }
+ }
+ return -1;