return status;
}
+METHOD(ike_sa_t, handle_redirect, bool,
+ private_ike_sa_t *this, identification_t *gateway)
+{
+ char gw[BUF_LEN];
+ host_t *other;
+
+ DBG1(DBG_IKE, "redirected to %Y", gateway);
+
+ snprintf(gw, sizeof(gw), "%Y", gateway);
+ gw[sizeof(gw)-1] = '\0';
+ other = host_create_from_dns(gw, AF_UNSPEC, IKEV2_UDP_PORT);
+ if (!other)
+ {
+ DBG1(DBG_IKE, "unable to resolve gateway ID '%Y', redirect failed",
+ gateway);
+ return FALSE;
+ }
+ switch (this->state)
+ {
+ case IKE_CONNECTING:
+ reset(this);
+ set_other_host(this, other);
+ return TRUE;
+ default:
+ DBG1(DBG_IKE, "unable to handle redirect for IKE_SA in state %N",
+ ike_sa_state_names, this->state);
+ other->destroy(other);
+ return FALSE;
+ }
+}
+
METHOD(ike_sa_t, retransmit, status_t,
private_ike_sa_t *this, u_int32_t message_id)
{
.destroy = _destroy,
.send_dpd = _send_dpd,
.send_keepalive = _send_keepalive,
+ .handle_redirect = _handle_redirect,
.get_keymat = _get_keymat,
.add_child_sa = _add_child_sa,
.get_child_sa = _get_child_sa,
*/
void (*send_keepalive) (ike_sa_t *this, bool scheduled);
+ /**
+ * Handle a redirect request.
+ *
+ * The behavior is different depending on the state of the IKE_SA.
+ *
+ * @param gateway gateway ID (IP or FQDN) of the target
+ * @return FALSE if redirect not possible, TRUE otherwise
+ */
+ bool (*handle_redirect)(ike_sa_t *this, identification_t *gateway);
+
/**
* Get the keying material of this IKE_SA.
*
this->retry++;
return NEED_MORE;
}
+ case REDIRECT:
+ {
+ identification_t *gateway;
+ chunk_t data, nonce = chunk_empty;
+ status_t status = FAILED;
+
+ data = notify->get_notification_data(notify);
+ gateway = redirect_data_parse(data, &nonce);
+ enumerator->destroy(enumerator);
+ if (!gateway || !chunk_equals(nonce, this->my_nonce))
+ {
+ DBG1(DBG_IKE, "received invalid REDIRECT notify");
+ }
+ else if (this->ike_sa->handle_redirect(this->ike_sa,
+ gateway))
+ {
+ status = NEED_MORE;
+ }
+ DESTROY_IF(gateway);
+ chunk_free(&nonce);
+ return status;
+ }
default:
{
if (type <= 16383)