if leftsourceip is defined, it is requested.
server may define rightsourceip=%config to accept any,
or it may overwrite it using rightsourceip.
if server does not return an IP, client enforces its configured leftsourceip.
}
/**
- * Implementation of peer_cfg_t.get_virtual_ip.
+ * Implementation of peer_cfg_t.get_my_virtual_ip.
*/
-static host_t* get_virtual_ip(private_peer_cfg_t *this, host_t *suggestion)
+static host_t* get_my_virtual_ip(private_peer_cfg_t *this)
{
- if (suggestion == NULL)
+ if (this->my_virtual_ip == NULL)
{
- if (this->my_virtual_ip)
- {
- return this->my_virtual_ip->clone(this->my_virtual_ip);
- }
return NULL;
}
- if (this->other_virtual_ip)
- {
+ return this->my_virtual_ip->clone(this->my_virtual_ip);
+}
+
+/**
+ * Implementation of peer_cfg_t.get_other_virtual_ip.
+ */
+static host_t* get_other_virtual_ip(private_peer_cfg_t *this, host_t *suggestion)
+{
+ if (this->other_virtual_ip == NULL)
+ { /* disallow */
+ return NULL;
+ }
+ if (!this->other_virtual_ip->is_anyaddr(this->other_virtual_ip))
+ { /* force own configuration */
return this->other_virtual_ip->clone(this->other_virtual_ip);
}
- if (suggestion->is_anyaddr(suggestion))
+ if (suggestion == NULL || suggestion->is_anyaddr(suggestion))
{
return NULL;
}
this->public.use_reauth = (bool (*) (peer_cfg_t *))use_reauth;
this->public.get_dpd_delay = (u_int32_t (*) (peer_cfg_t *))get_dpd_delay;
this->public.get_dpd_action = (dpd_action_t (*) (peer_cfg_t *))get_dpd_action;
- this->public.get_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_virtual_ip;
+ this->public.get_my_virtual_ip = (host_t* (*) (peer_cfg_t *))get_my_virtual_ip;
+ this->public.get_other_virtual_ip = (host_t* (*) (peer_cfg_t *, host_t *))get_other_virtual_ip;
this->public.get_ref = (void(*)(peer_cfg_t *))get_ref;
this->public.destroy = (void(*)(peer_cfg_t *))destroy;
dpd_action_t (*get_dpd_action) (peer_cfg_t *this);
/**
- * @brief Get a virtual IP for the local or the remote host.
+ * @brief Get a virtual IP for the local peer.
+ *
+ * If no virtual IP should be used, NULL is returned. %any means to request
+ * a virtual IP using configuration payloads. A specific address is also
+ * used for a request and may be changed by the server.
+ *
+ * @param this peer_cfg
+ * @param suggestion NULL, %any or specific
+ * @return clone of an IP, %any or NULL
+ */
+ host_t* (*get_my_virtual_ip) (peer_cfg_t *this);
+
+ /**
+ * @brief Get a virtual IP for the remote peer.
+ *
+ * An IP may be supplied, if one was requested by the initiator. However,
+ * the suggestion is not more as it says, any address may be returned, even
+ * NULL to not use virtual IPs.
*
- * By supplying NULL as IP, an IP for the local host is requested. It
- * may be %any or specific.
- * By supplying %any as host, an IP from the pool is selected to be
- * served to the peer.
- * If a specified host is supplied, it is checked if this address
- * is acceptable to serve to the peer. If so, it is returned. Otherwise,
- * an alternative IP is returned.
- * In any mode, this call may return NULL indicating virtual IP should
- * not be used.
- *
* @param this peer_cfg
- * @param suggestion NULL, %any or specific, see description
- * @return clone of an IP to use, or NULL
+ * @param suggestion NULL, %any or specific
+ * @return clone of an IP to use
*/
- host_t* (*get_virtual_ip) (peer_cfg_t *this, host_t *suggestion);
+ host_t* (*get_other_virtual_ip) (peer_cfg_t *this, host_t *suggestion);
/**
* @brief Get a new reference.
{
my_vip = host_create_from_string(msg->add_conn.me.sourceip, 0);
}
- other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
+ if (msg->add_conn.other.virtual_ip)
+ {
+ other_vip = host_create_from_string(msg->add_conn.other.sourceip, 0);
+ }
if (msg->add_conn.me.tohost)
{
if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
{
+ my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+ other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
SIG(CHILD_UP_FAILED, "no acceptable traffic selectors found");
return NOT_FOUND;
}
me = this->ike_sa->get_my_host(this->ike_sa);
other = this->ike_sa->get_other_host(this->ike_sa);
peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
- vip = peer_cfg->get_virtual_ip(peer_cfg, NULL);
+ vip = peer_cfg->get_my_virtual_ip(peer_cfg);
if (vip)
{ /* propose a 0.0.0.0/0 subnet when we use virtual ip */
else
{
config = this->ike_sa->get_peer_cfg(this->ike_sa);
- this->virtual_ip = config->get_virtual_ip(config, NULL);
+ this->virtual_ip = config->get_my_virtual_ip(config);
}
build_payloads(this, message, CFG_REQUEST);
host_t *ip;
DBG1(DBG_IKE, "peer requested virtual IP %H", this->virtual_ip);
- ip = config->get_virtual_ip(config, this->virtual_ip);
+ ip = config->get_other_virtual_ip(config, this->virtual_ip);
if (ip == NULL || ip->is_anyaddr(ip))
{
DBG1(DBG_IKE, "not assigning a virtual IP to peer");
!message->get_payload(message, EXTENSIBLE_AUTHENTICATION))
{
host_t *ip;
+ peer_cfg_t *config;
DESTROY_IF(this->virtual_ip);
this->virtual_ip = NULL;
process_payloads(this, message);
+
+ if (this->virtual_ip == NULL)
+ { /* force a configured virtual IP, even server didn't return one */
+ config = this->ike_sa->get_peer_cfg(this->ike_sa);
+ this->virtual_ip = config->get_my_virtual_ip(config);
+ }
- if (this->virtual_ip)
+ if (this->virtual_ip && !this->virtual_ip->is_anyaddr(this->virtual_ip))
{
this->ike_sa->set_virtual_ip(this->ike_sa, TRUE, this->virtual_ip);
msg_end->tohost = !conn_end->has_client;
msg_end->protocol = conn_end->protocol;
msg_end->port = conn_end->port;
- msg_end->virtual_ip = conn_end->modecfg;
+ msg_end->virtual_ip = conn_end->modecfg || conn_end->has_srcip;
ip_address2string(&conn_end->srcip, buffer, sizeof(buffer));
msg_end->sourceip = push_string(msg, buffer);
}