ikev2: Handle REDIRECT notifies during IKE_SA_INIT
This commit is contained in:
@@ -1951,6 +1951,37 @@ METHOD(ike_sa_t, reestablish, status_t,
|
|||||||
return status;
|
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,
|
METHOD(ike_sa_t, retransmit, status_t,
|
||||||
private_ike_sa_t *this, u_int32_t message_id)
|
private_ike_sa_t *this, u_int32_t message_id)
|
||||||
{
|
{
|
||||||
@@ -2543,6 +2574,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
|
|||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
.send_dpd = _send_dpd,
|
.send_dpd = _send_dpd,
|
||||||
.send_keepalive = _send_keepalive,
|
.send_keepalive = _send_keepalive,
|
||||||
|
.handle_redirect = _handle_redirect,
|
||||||
.get_keymat = _get_keymat,
|
.get_keymat = _get_keymat,
|
||||||
.add_child_sa = _add_child_sa,
|
.add_child_sa = _add_child_sa,
|
||||||
.get_child_sa = _get_child_sa,
|
.get_child_sa = _get_child_sa,
|
||||||
|
|||||||
@@ -847,6 +847,16 @@ struct ike_sa_t {
|
|||||||
*/
|
*/
|
||||||
void (*send_keepalive) (ike_sa_t *this, bool scheduled);
|
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.
|
* Get the keying material of this IKE_SA.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -704,6 +704,28 @@ METHOD(task_t, process_i, status_t,
|
|||||||
this->retry++;
|
this->retry++;
|
||||||
return NEED_MORE;
|
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:
|
default:
|
||||||
{
|
{
|
||||||
if (type <= 16383)
|
if (type <= 16383)
|
||||||
|
|||||||
Reference in New Issue
Block a user