free(this);
}
+#ifdef VOWIFI_CFG
+METHOD(kernel_interface_t, create_interface, status_t,
+ private_kernel_interface_t *this, char *iface_template, char* iface_buffer)
+{
+ if (!this->net || !this->net->create_interface)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->create_interface(this->net, iface_template, iface_buffer);
+}
+
+METHOD(kernel_interface_t, remove_interface, status_t,
+ private_kernel_interface_t *this, char *iface)
+{
+ if (!this->net || !this->net->remove_interface)
+ {
+ return NOT_SUPPORTED;
+ }
+ return this->net->remove_interface(this->net, iface);
+}
+#endif
+
/*
* Described in header-file
*/
.del_route = _del_route,
.bypass_socket = _bypass_socket,
.enable_udp_decap = _enable_udp_decap,
+#ifdef VOWIFI_CFG
+ .create_interface = _create_interface,
+ .remove_interface = _remove_interface,
+#endif
.is_interface_usable = _is_interface_usable,
.all_interfaces_usable = _all_interfaces_usable,
transform_type_t type, uint16_t *kernel_id,
char **kernel_name);
+#ifdef VOWIFI_CFG
+ /**
+ *
+ * Create and delete XFRM interfaces
+ *
+ */
+ status_t (*create_interface)(kernel_interface_t *this, char *name_template, char* name_buf);
+ status_t (*remove_interface)(kernel_interface_t *this, char *if_name);
+#endif
+
/**
* Destroys a kernel_interface_t object.
*/
uint8_t prefixlen, host_t *gateway, host_t *src_ip,
char *if_name);
+#ifdef VOWIFI_CFG
+ /**
+ *
+ * Create and delete XFRM interfaces
+ *
+ */
+ status_t (*create_interface)(kernel_net_t *this, char *name_template, char* name_buffer);
+ status_t (*remove_interface)(kernel_net_t *this, char *if_name);
+#endif
+
/**
* Destroy the implementation.
*/
* MSS to set on installed routes
*/
uint32_t mss;
+
+#ifdef VOWIFI_CFG
+ /**
+ * Internal interface index
+ */
+ int interface_index;
+#endif
};
/**
return SUCCESS;
}
+#ifdef VOWIFI_CFG
+
+#define INTERFACE_INDEX_START 10
+#define INFO_KIND_MAX_LENGTH 8
+
+METHOD(kernel_net_t, create_interface, status_t,
+ private_kernel_netlink_net_t *this, char *iface_template, char* iface_buffer)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ chunk_t chunk;
+ char name[IFNAMSIZ];
+ void *attr_outer, *attr_inner;
+ uint32_t index; uint32_t link = 1;
+ status_t res;
+
+ memset(&request, 0, sizeof(request));
+
+ this->lock->write_lock(this->lock);
+ if (this->interface_index < INTERFACE_INDEX_START)
+ this->interface_index = INTERFACE_INDEX_START;
+
+ index = this->interface_index++;
+ snprintf(name, IFNAMSIZ, iface_template, index);
+ this->lock->unlock(this->lock);
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
+ hdr->nlmsg_type = RTM_NEWLINK;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+
+ chunk = chunk_alloc(IFNAMSIZ);
+ memcpy(chunk.ptr, name, IFNAMSIZ);
+ netlink_add_attribute(hdr, IFLA_IFNAME, chunk, sizeof(request));
+ chunk_free(&chunk);
+
+ attr_outer = netlink_nested_start(hdr, sizeof(request), IFLA_LINKINFO);
+ chunk = chunk_alloc(INFO_KIND_MAX_LENGTH);
+ strncpy(chunk.ptr, "xfrm", INFO_KIND_MAX_LENGTH);
+ netlink_add_attribute(hdr, IFLA_INFO_KIND, chunk, sizeof(request));
+ chunk_free(&chunk);
+ attr_inner = netlink_nested_start(hdr, sizeof(request), IFLA_INFO_DATA);
+ chunk = chunk_from_thing(link);
+ netlink_add_attribute(hdr, IFLA_XFRM_LINK, chunk, sizeof(request));
+ chunk = chunk_from_thing(index);
+ netlink_add_attribute(hdr, IFLA_XFRM_IF_ID, chunk, sizeof(request));
+ netlink_nested_end(hdr, attr_inner);
+ netlink_nested_end(hdr, attr_outer);
+
+ res = this->socket->send_ack(this->socket, hdr);
+ if ((res == SUCCESS) && iface_buffer)
+ {
+ strcpy(iface_buffer, name);
+ }
+ return res;
+}
+
+METHOD(kernel_net_t, remove_interface, status_t,
+ private_kernel_netlink_net_t *this, char *iface_name)
+{
+ netlink_buf_t request;
+ struct nlmsghdr *hdr;
+ chunk_t chunk;
+
+ memset(&request, 0, sizeof(request));
+
+ hdr = &request.hdr;
+ hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+ hdr->nlmsg_type = RTM_DELLINK;
+ hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+
+ chunk = chunk_alloc(strlen(iface_name) + 1);
+ strncpy(chunk.ptr, iface_name, chunk.len);
+ netlink_add_attribute(hdr, IFLA_IFNAME, chunk, sizeof(request));
+ chunk_free(&chunk);
+
+ this->lock->write_lock(this->lock);
+ if (--this->interface_index < INTERFACE_INDEX_START)
+ this->interface_index = INTERFACE_INDEX_START;
+ this->lock->unlock(this->lock);
+
+ return this->socket->send_ack(this->socket, hdr);
+}
+#endif
+
/**
* Manages source routes in the routing table.
* By setting the appropriate nlmsg_type, the route gets added or removed.
.del_ip = _del_ip,
.add_route = _add_route,
.del_route = _del_route,
+#ifdef VOWIFI_CFG
+ .create_interface = _create_interface,
+ .remove_interface = _remove_interface,
+#endif
.destroy = _destroy,
},
},
return inbound ? this->if_id_in : this->if_id_out;
}
+#ifdef VOWIFI_CFG
+METHOD(child_sa_t, set_if_id, void,
+ private_child_sa_t *this, int in, int out)
+{
+ this->if_id_in = in;
+ this->if_id_out = out;
+}
+#endif
+
METHOD(child_sa_t, get_lifetime, time_t,
private_child_sa_t *this, bool hard)
{
.install_policies = _install_policies,
.create_ts_enumerator = _create_ts_enumerator,
.create_policy_enumerator = _create_policy_enumerator,
+#ifdef VOWIFI_CFG
+ .set_if_id = _set_if_id,
+#endif
.destroy = _destroy,
},
.encap = data->encap,
*/
status_t (*update)(child_sa_t *this, host_t *me, host_t *other,
linked_list_t *vips, bool encap);
+
+#ifdef VOWIFI_CFG
+ void (*set_if_id)(child_sa_t *this, int in, int out);
+#endif
+
/**
* Destroys a child_sa.
*/
if (this->tun == NULL)
{
+ char name[32];
+
int mtu = 0;
#ifdef VOWIFI_PMTU_DISCOVERY
mtu = pmtu_discovery_stage2(this);
{
mtu = TUN_DEFAULT_MTU;
}
- this->tun = tun_device_create("epdg%d");
+ if (charon->kernel->create_interface(charon->kernel, "epdg%d", name) == SUCCESS)
+ {
+ sscanf(name, "epdg%d", &this->if_id_in);
+ this->if_id_out = this->if_id_in;
+
+ this->tun = xfrm_device_create(name);
+ }
+ else
+ {
+ this->tun = tun_device_create("epdg%d");
+ }
if (!this->tun)
{
DBG1(DBG_IKE, "failed to create TUN device");
if (!this->tun->set_mtu(this->tun, mtu))
{
DBG1(DBG_IKE, "failed to configure TUN device");
+ if (this->tun->is_xfrm_device(this->tun))
+ {
+ charon->kernel->remove_interface(charon->kernel,
+ this->tun->get_name(this->tun));
+ }
this->tun->destroy(this->tun);
this->tun = NULL;
return;
if (!this->tun->up(this->tun))
{
DBG1(DBG_IKE, "failed to up TUN device");
+ if (this->tun->is_xfrm_device(this->tun))
+ {
+ charon->kernel->remove_interface(charon->kernel,
+ this->tun->get_name(this->tun));
+ }
this->tun->destroy(this->tun);
this->tun = NULL;
return;
if (charon->kernel->add_ip(charon->kernel, ip, -1, this->tun->get_name(this->tun)) != SUCCESS)
{
DBG1(DBG_IKE, "failed to set ip to TUN device");
+ if (this->tun->is_xfrm_device(this->tun))
+ {
+ charon->kernel->remove_interface(charon->kernel,
+ this->tun->get_name(this->tun));
+ }
this->tun->destroy(this->tun);
this->tun = NULL;
return;
{
#ifdef VOWIFI_CFG
if (this->tun) {
+ if (this->tun->is_xfrm_device(this->tun))
+ {
+ charon->kernel->remove_interface(charon->kernel,
+ this->tun->get_name(this->tun));
+ }
this->tun->destroy(this->tun);
}
this->tun = NULL;
{
#ifdef VOWIFI_CFG
if (this->tun) {
+ if (this->tun->is_xfrm_device(this->tun))
+ {
+ charon->kernel->remove_interface(charon->kernel,
+ this->tun->get_name(this->tun));
+ }
this->tun->destroy(this->tun);
}
this->tun = NULL;
}
return total;
}
+
+METHOD(ike_sa_t, is_xfrm_interface_used, bool, private_ike_sa_t *this)
+{
+ if (this->tun)
+ {
+ return this->tun->is_xfrm_device(this->tun);
+ }
+ return FALSE;
+}
#endif
#ifdef VOWIFI_USE_TIMER
.process_vendor_notify = _process_vendor_notify,
.process_failed_notify = _process_failed_notify,
.get_vendor_notifies = _get_vendor_notifies,
+ .is_xfrm_interface_used = _is_xfrm_interface_used,
#endif
#ifdef ME
.act_as_mediation_server = _act_as_mediation_server,
void (*process_vendor_notify)(ike_sa_t *this, int type, message_t *message);
void* (*process_failed_notify)(ike_sa_t *this, int type, message_t *message);
int (*get_vendor_notifies)(ike_sa_t *this, linked_list_t *list);
+
+ /**
+ * TRUE if XFRM device was used
+ */
+ bool (*is_xfrm_interface_used)(ike_sa_t *this);
#endif
};
this->child_sa->set_mode(this->child_sa, this->mode);
this->child_sa->set_protocol(this->child_sa,
this->proposal->get_protocol(this->proposal));
+#ifdef VOWIFI_CFG
+ if (this->ike_sa->is_xfrm_interface_used(this->ike_sa))
+ {
+ /* update XFRM device ID to child */
+ this->child_sa->set_if_id(this->child_sa,
+ this->ike_sa->get_if_id(this->ike_sa, TRUE),
+ this->ike_sa->get_if_id(this->ike_sa, FALSE));
+ }
+#endif
if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
{
* Associated addresses
*/
linked_list_t* addresses;
+
+ bool is_xfrm_device;
#else
/**
* Associated address
#endif /* !__APPLE__ */
}
+#ifdef VOWIFI_CFG
+METHOD(tun_device_t, is_xfrm_device, bool,
+ private_tun_device_t *this)
+{
+ return this->is_xfrm_device;
+}
+#endif
+
/*
* Described in header
*/
.get_address = _get_address,
#else
.create_addresses_enumerator = _create_addresses_enumerator,
+ .is_xfrm_device = _is_xfrm_device,
#endif
.up = _up,
.destroy = _destroy,
return &this->public;
}
+#ifdef VOWIFI_CFG
+tun_device_t *xfrm_device_create(const char *name)
+{
+ private_tun_device_t *this;
+
+ INIT(this,
+ .public = {
+ .read_packet = _read_packet,
+ .write_packet = _write_packet,
+ .get_mtu = _get_mtu,
+ .set_mtu = _set_mtu,
+ .get_name = _get_name,
+ .get_fd = _get_fd,
+ .set_address = _set_address,
+ .create_addresses_enumerator = _create_addresses_enumerator,
+ .is_xfrm_device = _is_xfrm_device,
+ .up = _up,
+ .destroy = _destroy,
+ },
+ .tunfd = -1,
+ .sock = -1,
+ );
+ strncpy(this->if_name, name, IFNAMSIZ);
+ this->addresses = linked_list_create();
+ this->is_xfrm_device = TRUE;
+
+ DBG1(DBG_LIB, "created XFRM device: %s", this->if_name);
+ this->sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (this->sock < 0)
+ {
+ DBG1(DBG_LIB, "failed to open socket to configure TUN device");
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
+#endif
+
#endif /* TUN devices supported */
*/
int (*get_fd)(tun_device_t *this);
+#ifdef VOWIFI_CFG
+ bool (*is_xfrm_device)(tun_device_t *this);
+#endif
+
/**
* Destroy a tun_device_t
*/
*/
tun_device_t *tun_device_create(const char *name_tmpl);
+#ifdef VOWIFI_CFG
+tun_device_t *xfrm_device_create(const char *name);
+#endif
+
#endif /** TUN_DEVICE_H_ @}*/