*/
static chunk_t get_from_address(private_traffic_selector_t *this)
{
- chunk_t from = chunk_empty;
-
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
- {
- from.len = sizeof(this->from4);
- from.ptr = malloc(from.len);
- memcpy(from.ptr, this->from4, from.len);
- break;
- }
+ return chunk_create(this->from, sizeof(this->from4));
case TS_IPV6_ADDR_RANGE:
- {
- from.len = sizeof(this->from6);
- from.ptr = malloc(from.len);
- memcpy(from.ptr, this->from6, from.len);
- break;
- }
+ return chunk_create(this->from, sizeof(this->from6));
+ default:
+ return chunk_empty;
}
- return from;
}
/**
*/
static chunk_t get_to_address(private_traffic_selector_t *this)
{
- chunk_t to = chunk_empty;
-
switch (this->type)
{
case TS_IPV4_ADDR_RANGE:
- {
- to.len = sizeof(this->to4);
- to.ptr = malloc(to.len);
- memcpy(to.ptr, this->to4, to.len);
- break;
- }
+ return chunk_create(this->to, sizeof(this->to4));
case TS_IPV6_ADDR_RANGE:
- {
- to.len = sizeof(this->to6);
- to.ptr = malloc(to.len);
- memcpy(to.ptr, this->to6, to.len);
- break;
- }
+ return chunk_create(this->to, sizeof(this->to6));
+ default:
+ return chunk_empty;
}
- return to;
}
/**
}
/**
+ * Implementation of traffic_selector_t.is_dynamic
+ */
+static bool is_dynamic(private_traffic_selector_t *this)
+{
+ return this->dynamic;
+}
+
+/**
* Implements traffic_selector_t.set_address.
*/
static void set_address(private_traffic_selector_t *this, host_t *host)
this->public.get_type = (ts_type_t(*)(traffic_selector_t*))get_type;
this->public.get_protocol = (u_int8_t(*)(traffic_selector_t*))get_protocol;
this->public.is_host = (bool(*)(traffic_selector_t*,host_t*))is_host;
+ this->public.is_dynamic = (bool(*)(traffic_selector_t*))is_dynamic;
this->public.is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in;
this->public.includes = (bool(*)(traffic_selector_t*,host_t*))includes;
this->public.set_address = (void(*)(traffic_selector_t*,host_t*))set_address;
/**
* Get starting address of this ts as a chunk.
*
- * Chunk is in network order gets allocated.
+ * Chunk is in network and points to internal data.
*
* @return chunk containing the address
*/
/**
* Get ending address of this ts as a chunk.
*
- * Chunk is in network order gets allocated.
+ * Chunk is in network and points to internal data.
*
* @return chunk containing the address
*/
bool (*is_host) (traffic_selector_t *this, host_t* host);
/**
+ * Check if a traffic selector has been created by create_dynamic().
+ *
+ * @return TRUE if TS is dynamic
+ */
+ bool (*is_dynamic)(traffic_selector_t *this);
+
+ /**
* Update the address of a traffic selector.
*
* Update the address range of a traffic selector, if it is
this->ip_protocol_id = traffic_selector->get_protocol(traffic_selector);
this->start_port = traffic_selector->get_from_port(traffic_selector);
this->end_port = traffic_selector->get_to_port(traffic_selector);
- this->starting_address = traffic_selector->get_from_address(traffic_selector);
- this->ending_address = traffic_selector->get_to_address(traffic_selector);
+ this->starting_address = chunk_clone(traffic_selector->get_from_address(traffic_selector));
+ this->ending_address = chunk_clone(traffic_selector->get_to_address(traffic_selector));
compute_length(this);
host_t *start = NULL, *end = NULL;
/**
- * create a host from a blob
- */
-static host_t *host_create_from_blob(chunk_t blob)
-{
- return host_create_from_chunk(blob.len == 4 ? AF_INET : AF_INET6, blob, 0);
-}
-
-/**
* calculate the size of a pool using start and end address chunk
*/
static u_int get_pool_size(chunk_t start, chunk_t end)
found = TRUE;
}
- start = host_create_from_blob(start_chunk);
- end = host_create_from_blob(end_chunk);
+ start = host_create_from_chunk(AF_UNSPEC, start_chunk, 0);
+ end = host_create_from_chunk(AF_UNSPEC, end_chunk, 0);
size = get_pool_size(start_chunk, end_chunk);
printf("%8s %15H %15H ", name, start, end);
if (timeout)
printf("%-8s %-15s %-7s %-*s %-*s %s\n",
"name", "address", "status", len, "start", len, "end", "identity");
}
- address = host_create_from_blob(address_chunk);
+ address = host_create_from_chunk(AF_UNSPEC, address_chunk, 0);
identity = identification_create_from_encoding(identity_type, identity_chunk);
printf("%-8s %-15H ", name, address);
};
/**
- * read a host_t address from the addresses table
- */
-static host_t *host_from_chunk(chunk_t chunk)
-{
- switch (chunk.len)
- {
- case 4:
- return host_create_from_chunk(AF_INET, chunk, 0);
- case 16:
- return host_create_from_chunk(AF_INET6, chunk, 0);
- default:
- return NULL;
- }
-}
-
-/**
* lookup/insert an identity
*/
static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
"WHERE id = ? AND identity = ? AND released != 0",
DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
{
- host = host_from_chunk(address);
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
DBG1(DBG_CFG, "acquired existing lease "
DB_UINT, now, DB_UINT, identity,
DB_UINT, id, DB_UINT, now - timeout) > 0)
{
- host = host_from_chunk(address);
+ host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
DBG1(DBG_CFG, "acquired new lease "
soft = this->config->get_lifetime(this->config, TRUE);
hard = this->config->get_lifetime(this->config, FALSE);
+
status = charon->kernel_interface->add_sa(charon->kernel_interface,
src, dst, spi, this->protocol, this->reqid,
in ? soft : 0, hard, enc_alg, encr, int_alg, integ,
this->other_addr, this->my_addr, other_ts, my_ts, POLICY_IN,
this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
this->my_cpi, routed);
-
if (mode == MODE_TUNNEL)
{
status |= charon->kernel_interface->add_policy(charon->kernel_interface,
this->my_spi, this->protocol, this->reqid, mode, this->ipcomp,
this->my_cpi, routed);
}
-
+
if (status != SUCCESS)
{
break;
}
enumerator->destroy(enumerator);
}
-
+
if (status == SUCCESS)
{
/* switch to routed state if no SAD entry set up */
{
return NOT_SUPPORTED;
}
-
/* update his (responder) SA */
if (charon->kernel_interface->update_sa(charon->kernel_interface, this->other_spi,
this->protocol, this->ipcomp != IPCOMP_NONE ? this->other_cpi : 0,
{
enumerator_t *enumerator;
traffic_selector_t *my_ts, *other_ts;
-
+
/* always use high priorities, as hosts getting updated are INSTALLED */
enumerator = create_policy_enumerator(this);
while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
charon->kernel_interface->del_policy(charon->kernel_interface,
other_ts, my_ts, POLICY_FWD, FALSE);
}
-
+
/* check whether we have to update a "dynamic" traffic selector */
if (!me->ip_equals(me, this->my_addr) &&
my_ts->is_host(my_ts, this->my_addr))
{
other_ts->set_address(other_ts, other);
}
-
+
/* we reinstall the virtual IP to handle interface roaming
* correctly */
if (vip)
charon->kernel_interface->del_ip(charon->kernel_interface, vip);
charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
}
-
+
/* reinstall updated policies */
charon->kernel_interface->add_policy(charon->kernel_interface,
me, other, my_ts, other_ts, POLICY_OUT, this->other_spi,
enumerator->destroy(enumerator);
}
}
-
+
/* apply hosts */
if (!this->config->use_proxy_mode(this->config) || this->mode != MODE_TRANSPORT)
{
}
enumerator->destroy(enumerator);
}
-
+
this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
this->my_addr->destroy(this->my_addr);
return &this->public;
}
-
* Optimum length of exponent in bits.
*/
long opt_exponent_len;
-
+
/*
* Generator value.
*/
* Other public value
*/
BIGNUM *pub_key;
-
+
/**
* Shared secret
*/
*/
host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
{
- private_host_t *this = host_create_empty();
+ private_host_t *this;
- this->address.sa_family = family;
switch (family)
{
case AF_INET:
- {
- if (address.len != IPV4_LEN)
+ if (address.len < IPV4_LEN)
{
- break;
+ return NULL;
}
- memcpy(&(this->address4.sin_addr.s_addr), address.ptr, IPV4_LEN);
- this->address4.sin_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in);
- return &(this->public);
- }
+ address.len = IPV4_LEN;
+ break;
case AF_INET6:
- {
- if (address.len != IPV6_LEN)
+ if (address.len < IPV6_LEN)
{
- break;
+ return NULL;
}
- memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, IPV6_LEN);
+ address.len = IPV6_LEN;
+ break;
+ case AF_UNSPEC:
+ switch (address.len)
+ {
+ case IPV4_LEN:
+ family = AF_INET;
+ break;
+ case IPV6_LEN:
+ family = AF_INET6;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ default:
+ return NULL;
+ }
+ this = host_create_empty();
+ this->address.sa_family = family;
+ switch (family)
+ {
+ case AF_INET:
+ memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
+ this->address4.sin_port = htons(port);
+ this->socklen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
this->address6.sin6_port = htons(port);
this->socklen = sizeof(struct sockaddr_in6);
- return &this->public;
- }
- default:
break;
}
- free(this);
- return NULL;
+ return &this->public;
}
/*
host_t *host_create_from_dns(char *string, int family, u_int16_t port);
/**
- * Constructor to create a host_t object from an address chunk
+ * Constructor to create a host_t object from an address chunk.
+ *
+ * If family is AF_UNSPEC, it is guessed using address.len.
*
* @param family Address family, such as AF_INET or AF_INET6
* @param address address as chunk_t in network order