From 5a46065b335e2c2531c45f8055fc128896612953 Mon Sep 17 00:00:00 2001 From: Denis Vinogradov Date: Wed, 26 Aug 2020 15:01:57 +0900 Subject: [PATCH] add configurable vendor attributes and notifies lists Request and response Change-Id: Ibdab0e2bf9a22fc427c64c7cbf9b66bf85cc84a5 Signed-off-by: Denis Vinogradov --- Android.mk | 12 +- src/libcharon/Android.mk | 5 +- src/libcharon/attributes/attribute_handler.h | 5 - src/libcharon/attributes/attribute_manager.c | 12 +- src/libcharon/attributes/attributes.c | 35 -- src/libcharon/attributes/attributes.h | 20 +- src/libcharon/comm/comm_msg.c | 132 +++---- src/libcharon/comm/comm_msg.h | 4 +- src/libcharon/comm/vendor_request_data.c | 112 ++++++ src/libcharon/comm/vendor_request_data.h | 25 ++ src/libcharon/comm/vendor_request_list.c | 80 +++++ src/libcharon/comm/vendor_request_list.h | 21 ++ src/libcharon/comm/vendor_response_data.c | 85 +++++ src/libcharon/comm/vendor_response_data.h | 22 ++ src/libcharon/config/peer_cfg.c | 66 +++- src/libcharon/config/peer_cfg.h | 17 +- .../payloads/configuration_attribute.c | 18 +- src/libcharon/plugins/attr/attr_provider.c | 23 +- src/libcharon/plugins/p_cscf/p_cscf_handler.c | 10 - src/libcharon/plugins/stroke/stroke_config.c | 4 +- src/libcharon/plugins/stroke/stroke_handler.c | 331 +++++++++--------- src/libcharon/plugins/stroke/stroke_socket.c | 13 +- src/libcharon/sa/ike_sa.c | 68 ++-- src/libcharon/sa/ike_sa.h | 9 +- src/libcharon/sa/ikev2/tasks/ike_config.c | 57 --- src/libstrongswan/networking/tun_device.c | 1 + src/stroke/stroke_msg.h | 17 +- 27 files changed, 711 insertions(+), 493 deletions(-) create mode 100755 src/libcharon/comm/vendor_request_data.c create mode 100755 src/libcharon/comm/vendor_request_data.h create mode 100755 src/libcharon/comm/vendor_request_list.c create mode 100755 src/libcharon/comm/vendor_request_list.h create mode 100755 src/libcharon/comm/vendor_response_data.c create mode 100755 src/libcharon/comm/vendor_response_data.h diff --git a/Android.mk b/Android.mk index abddf6f..8d6b0e0 100755 --- a/Android.mk +++ b/Android.mk @@ -14,16 +14,20 @@ include $(CLEAR_VARS) # strongswan_BUILD_STARTER := true # strongswan_BUILD_SCEPCLIENT := true -strongswan_BUILD_VoWiFi:=true -strongswan_BUILD_USE_BORINGSSL:=true +strongswan_BUILD_VoWiFi := true +strongswan_BUILD_USE_BORINGSSL := true # this is the list of plugins that are built into libstrongswan and charon # also these plugins are loaded by default (if not changed in strongswan.conf) +ifneq ($(strongswan_BUILD_VoWiFi),) +strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ + pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default \ + counters stroke eap-identity eap-mschapv2 eap-md5 eap-gtc +strongswan_CHARON_PLUGINS += eap-aka eap-aka-3gpp-simril ctr des +else strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android-dns \ counters stroke eap-identity eap-mschapv2 eap-md5 eap-gtc -ifneq ($(strongswan_BUILD_VoWiFi),) -strongswan_CHARON_PLUGINS += eap-aka eap-aka-3gpp-simril p-cscf ctr des endif ifneq ($(strongswan_BUILD_SCEPCLIENT),) diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index a278d07..5ff8763 100755 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -144,7 +144,10 @@ libcharon_la_SOURCES += \ ifneq ($(strongswan_BUILD_VoWiFi),) libcharon_la_SOURCES += \ - comm/comm_msg.c comm/alerts.c + comm/comm_msg.c comm/alerts.c \ + comm/vendor_request_data.c \ + comm/vendor_response_data.c \ + comm/vendor_request_list.c endif LOCAL_SRC_FILES := $(filter %.c,$(libcharon_la_SOURCES)) diff --git a/src/libcharon/attributes/attribute_handler.h b/src/libcharon/attributes/attribute_handler.h index 2f1ac3a..cc09bef 100755 --- a/src/libcharon/attributes/attribute_handler.h +++ b/src/libcharon/attributes/attribute_handler.h @@ -69,13 +69,8 @@ struct attribute_handler_t { * @param vips list of virtual IPs (host_t*) we are requesting * @return enumerator (configuration_attribute_type_t, chunk_t) */ -#ifdef VOWIFI_CFG - enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this, - ike_sa_t *ike_sa, linked_list_t *vips, int attr_type); -#else enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips); -#endif }; #endif /** ATTRIBUTE_HANDLER_H_ @}*/ diff --git a/src/libcharon/attributes/attribute_manager.c b/src/libcharon/attributes/attribute_manager.c index 1d6111c..0a0220b 100755 --- a/src/libcharon/attributes/attribute_manager.c +++ b/src/libcharon/attributes/attribute_manager.c @@ -243,12 +243,9 @@ METHOD(enumerator_t, initiator_enumerate, bool, configuration_attribute_type_t *type; attribute_handler_t **handler; chunk_t *value; -#ifdef VOWIFI_CFG - int attr_type; - VA_ARGS_VGET(args, handler, type, value, attr_type); -#else + VA_ARGS_VGET(args, handler, type, value); -#endif + /* enumerate inner attributes using outer handler enumerator */ while (!this->inner || !this->inner->enumerate(this->inner, type, value)) { @@ -257,13 +254,8 @@ METHOD(enumerator_t, initiator_enumerate, bool, return FALSE; } DESTROY_IF(this->inner); -#ifdef VOWIFI_CFG - this->inner = this->handler->create_attribute_enumerator(this->handler, - this->ike_sa, this->vips, attr_type); -#else this->inner = this->handler->create_attribute_enumerator(this->handler, this->ike_sa, this->vips); -#endif } /* inject the handler as additional attribute */ *handler = this->handler; diff --git a/src/libcharon/attributes/attributes.c b/src/libcharon/attributes/attributes.c index 6381b7c..52c2ef1 100755 --- a/src/libcharon/attributes/attributes.c +++ b/src/libcharon/attributes/attributes.c @@ -44,23 +44,7 @@ ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, INTERNAL_DN "TIMEOUT_PERIOD_FOR_DPD", "INTERNAL_DNS_DOMAIN", "INTERNAL_DNSSEC_TA"); -#ifdef VOWIFI_CFG - /* As per different Requirements for different customer */ - -ENUM_NEXT(configuration_attribute_type_names, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, INTERNAL_DNSSEC_TA, - "P_CSCF_IP4_ADDRESS_OPR_TYPE_1"); - -ENUM_NEXT(configuration_attribute_type_names, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, - "P_CSCF_IP6_ADDRESS_OPR_TYPE_1"); - -ENUM_NEXT(configuration_attribute_type_names, P_CSCF_IP4_ADDRESS_OPR_TYPE_2, DEVICE_IMEI, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, - "P_CSCF_IP4_ADDRESS_OPR_TYPE_2", - "P_CSCF_IP6_ADDRESS_OPR_TYPE_2", - "DEVICE_IMEI"); -ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, DEVICE_IMEI, -#else ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, INTERNAL_DNSSEC_TA, -#endif "XAUTH_TYPE", "XAUTH_USER_NAME", "XAUTH_USER_PASSWORD", @@ -115,26 +99,7 @@ ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, INTER "DPD", "DOMAIN", "TA"); -#ifdef VOWIFI_CFG - /* As per different Requirements for different customer */ - - -ENUM_NEXT(configuration_attribute_type_short_names, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, INTERNAL_DNSSEC_TA, - "PCSCF_OPR_TYPE_1"); - -ENUM_NEXT(configuration_attribute_type_short_names, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, - "PCSCF6_OPR_TYPE_1"); - -ENUM_NEXT(configuration_attribute_type_short_names, P_CSCF_IP4_ADDRESS_OPR_TYPE_2, DEVICE_IMEI, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, - "PCSCF_OPR_TYPE_2", - "PCSCF6_OPR_TYPE_2", - "IMEI"); -ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, DEVICE_IMEI, - - -#else ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, INTERNAL_DNSSEC_TA, -#endif "X_TYPE", "X_USER", "X_PWD", diff --git a/src/libcharon/attributes/attributes.h b/src/libcharon/attributes/attributes.h index 1fdf8d7..f632787 100755 --- a/src/libcharon/attributes/attributes.h +++ b/src/libcharon/attributes/attributes.h @@ -48,27 +48,19 @@ enum configuration_attribute_type_t { MIP6_HOME_PREFIX = 16, INTERNAL_IP6_LINK = 17, INTERNAL_IP6_PREFIX = 18, - HOME_AGENT_ADDRESS = 19, + HOME_AGENT_ADDRESS = 19, /* RFC 7651 */ - P_CSCF_IP4_ADDRESS = 20, - P_CSCF_IP6_ADDRESS = 21, + P_CSCF_IP4_ADDRESS = 20, + P_CSCF_IP6_ADDRESS = 21, /* Firewall traversal keep-alive time (TS 24.302 12.6.0) */ - FTT_KAT = 22, + FTT_KAT = 22, /* External NAT endpoint (TS 29.139) */ EXT_SRC_IP4_NAT_INFO = 23, /* DPD interval (TS 24.302 13.4.0)*/ TIMEOUT_PERIOD_FOR_DPD = 24, /* RFC 8598 */ - INTERNAL_DNS_DOMAIN = 25, - INTERNAL_DNSSEC_TA = 26, -#ifdef VOWIFI_CFG - P_CSCF_IP4_ADDRESS_OPR_TYPE_1 = 16384, - P_CSCF_IP6_ADDRESS_OPR_TYPE_1 = 16386, - - P_CSCF_IP4_ADDRESS_OPR_TYPE_2 = 16389, - P_CSCF_IP6_ADDRESS_OPR_TYPE_2 = 16390, - DEVICE_IMEI = 16391, -#endif + INTERNAL_DNS_DOMAIN = 25, + INTERNAL_DNSSEC_TA = 26, /* XAUTH attributes */ XAUTH_TYPE = 16520, XAUTH_USER_NAME = 16521, diff --git a/src/libcharon/comm/comm_msg.c b/src/libcharon/comm/comm_msg.c index 09d1ab8..38e924f 100755 --- a/src/libcharon/comm/comm_msg.c +++ b/src/libcharon/comm/comm_msg.c @@ -10,6 +10,7 @@ #include "comm_msg.h" #include "alerts.h" #include "stroke_msg.h" +#include "vendor_response_data.h" static charon_response_t *create_response_msg(charon_response_type_t type) { @@ -50,6 +51,33 @@ static void push_string_impl(charon_response_t **msg, size_t offset, char *strin *(char**)((char*)*msg + offset) = (char*)cur_len; } +#define push_array(msg, field, data, length) \ + push_array_impl(msg, offsetof(charon_response_t, field), data, length) + +static void push_array_impl(charon_response_t **msg, size_t offset, char *data, int length) +{ + size_t cur_len = (*msg)->length; + + if (!data || !length) + { + return; + } + if (cur_len + length >= UINT16_MAX) + { + (*msg)->length = UINT16_MAX; + return; + } + while (cur_len + length > sizeof(charon_response_t) + (*msg)->buflen) + { + *msg = realloc(*msg, sizeof(charon_response_t) + (*msg)->buflen + + STROKE_BUF_LEN_INC); + (*msg)->buflen += STROKE_BUF_LEN_INC; + } + (*msg)->length += length; + memcpy((char*)*msg + cur_len, data, length); + *(char**)((char*)*msg + offset) = (char*)cur_len; +} + /* ADD_CONN and DEL_CONN responses always successful */ @@ -123,6 +151,34 @@ void charon_send_initate_failure(stroke_msg_t *msg, int index) free(res); } +static char* get_attributes(ike_sa_t *ike_sa, int *total) +{ + linked_list_t *vendor_attributes = linked_list_create(); + int length = ike_sa->get_configuration_attributes(ike_sa, vendor_attributes); + + if (length) + { + vendor_response_data_t *attr; + + char *mem = calloc(length + sizeof(int), 1); + char *tmp = mem + sizeof(int); + + *((unsigned int*)mem) = length; + + while (vendor_attributes->remove_first(vendor_attributes, &attr) == SUCCESS) + { + tmp = attr->pack(attr, tmp); + attr->destroy(attr); + } + vendor_attributes->destroy(vendor_attributes); + + *total = length + sizeof(int); + return mem; + } + vendor_attributes->destroy(vendor_attributes); + return NULL; +} + static char* get_addresses(ike_sa_t *ike_sa, int cnt) { enumerator_t *enumerator; @@ -195,76 +251,12 @@ void charon_send_initiate_success(stroke_msg_t *msg, int index) { if (streq(msg->initiate.name, ike_sa->get_name(ike_sa))) { - char *attr, *ipv4str = NULL, *ipv6str = NULL; + char *attr = NULL; + int length = 0; push_string(&res, initiate.device, ike_sa->get_tun_name(ike_sa)); res->initiate.mtu = ike_sa->get_mtu(ike_sa); - /* DNS */ - ipv4str = ike_sa->get_ip_configuration_attribute(ike_sa, INTERNAL_IP4_DNS, 8); - ipv6str = ike_sa->get_ip_configuration_attribute(ike_sa, INTERNAL_IP6_DNS, 8); - if (ipv4str || ipv6str) - { - char* dns = calloc((ipv4str ? strlen(ipv4str) : 0) + (ipv6str ? strlen(ipv6str) : 0) + 2, 1); - if (ipv4str) - { - strcat(dns, ipv4str); - free(ipv4str); - } - if (ipv6str) - { - if (ipv4str) - { - strcat(dns, ","); - } - strcat(dns, ipv6str); - free(ipv6str); - } - ipv4str = NULL; - ipv6str = NULL; - - push_string(&res, initiate.dns, dns); - free(dns); - } - /* P-CSCF */ - switch (ike_sa->get_operator(ike_sa)) - { - case OPERATOR_TYPE_TMO_ATT: - ipv4str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP4_ADDRESS_OPR_TYPE_1, 8); - ipv6str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, 8); - break; - case OPERATOR_TYPE_VZW: - ipv4str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP4_ADDRESS_OPR_TYPE_2, 8); - ipv6str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP6_ADDRESS_OPR_TYPE_2, 8); - break; - case OPERATOR_TYPE_DEFAULT: - default: - ipv4str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP4_ADDRESS, 8); - ipv6str = ike_sa->get_ip_configuration_attribute(ike_sa, P_CSCF_IP6_ADDRESS, 8); - } - if (ipv4str || ipv6str) - { - char* pcscf = calloc((ipv4str ? strlen(ipv4str) : 0) + (ipv6str ? strlen(ipv6str) : 0) + 2, 1); - if (ipv4str) - { - strcat(pcscf, ipv4str); - free(ipv4str); - } - if (ipv6str) - { - if (ipv4str) - { - strcat(pcscf, ","); - } - strcat(pcscf, ipv6str); - free(ipv6str); - } - ipv4str = NULL; - ipv6str = NULL; - - push_string(&res, initiate.pcscf, pcscf); - free(pcscf); - } /* Addresses */ attr = get_addresses(ike_sa, 4); if (attr) @@ -273,6 +265,14 @@ void charon_send_initiate_success(stroke_msg_t *msg, int index) free(attr); } + /* attributes */ + attr = get_attributes(ike_sa, &length); + if (attr) + { + push_array(&res, initiate.attributes, attr, length); + free(attr); + } + /* end */ ike_sa->set_handover(ike_sa, 0); DBG1(DBG_CFG,"Initiate completed, reset handover flag"); diff --git a/src/libcharon/comm/comm_msg.h b/src/libcharon/comm/comm_msg.h index ecf3bf7..1f75b4d 100755 --- a/src/libcharon/comm/comm_msg.h +++ b/src/libcharon/comm/comm_msg.h @@ -84,8 +84,8 @@ typedef struct int tmval; char *device; char *address; - char *pcscf; - char *dns; + char *attributes; + char *notifies; int mtu; } initiate; diff --git a/src/libcharon/comm/vendor_request_data.c b/src/libcharon/comm/vendor_request_data.c new file mode 100755 index 0000000..217a8b0 --- /dev/null +++ b/src/libcharon/comm/vendor_request_data.c @@ -0,0 +1,112 @@ +#include "vendor_request_data.h" + +typedef struct private_vendor_request_data_t private_vendor_request_data_t; + +/** + * Private data + */ +struct private_vendor_request_data_t { + /** + * Public interface + */ + vendor_request_data_t public; + + /** Type */ + int type; + + /** Data */ + chunk_t data; +}; + +/** + * Packed attribute structure from service +*/ +typedef struct { + unsigned short type; + unsigned short length; + char data[]; +} packed_vendor_request_data_t; + +METHOD(vendor_request_data_t, get_attribute_type, configuration_attribute_type_t, + private_vendor_request_data_t *this) +{ + return this->type; +} + +METHOD(vendor_request_data_t, get_data, chunk_t, + private_vendor_request_data_t *this) +{ + return this->data; +} + +METHOD(vendor_request_data_t, is_empty, bool, + private_vendor_request_data_t *this) +{ + return (this->type == 0); +} + +METHOD(vendor_request_data_t, destroy, void, + private_vendor_request_data_t *this) +{ + if (this->data.ptr) + { + chunk_free(&this->data); + } + free(this); +} + +vendor_request_data_t* build_vendor_request_data(char *buffer, int *offset) +{ + private_vendor_request_data_t *this; + + INIT(this, + .public = { + .get_attribute_type = _get_attribute_type, + .get_data = _get_data, + .is_empty = _is_empty, + .destroy = _destroy, + }, + .data = chunk_empty, + ); + + packed_vendor_request_data_t *packed = (packed_vendor_request_data_t*)(buffer + *offset); + this->type = packed->type; + if (packed->length) + { + chunk_t chunk = chunk_create(packed->data, packed->length); + this->data = chunk_clone(chunk); + } + *offset += (packed->length + sizeof(packed_vendor_request_data_t)); + + return &this->public; +} + +vendor_request_data_t* build_dns_request_data(host_t* host) +{ + private_vendor_request_data_t *this; + + INIT(this, + .public = { + .get_attribute_type = _get_attribute_type, + .get_data = _get_data, + .is_empty = _is_empty, + .destroy = _destroy, + }, + .data = chunk_empty, + ); + switch (host->get_family(host)) + { + case AF_INET: + this->type = INTERNAL_IP4_DNS; + break; + case AF_INET6: + this->type = INTERNAL_IP6_DNS; + break; + } + if (!host->is_anyaddr(host)) + { + this->data = host->get_address(host); + } + + return &this->public; +} \ No newline at end of file diff --git a/src/libcharon/comm/vendor_request_data.h b/src/libcharon/comm/vendor_request_data.h new file mode 100755 index 0000000..98fb39d --- /dev/null +++ b/src/libcharon/comm/vendor_request_data.h @@ -0,0 +1,25 @@ +#ifndef VENDOR_REQUEST_DATA_H +#define VENDOR_REQUEST_DATA_H + +#include + +typedef struct vendor_request_data_t vendor_request_data_t; + +struct vendor_request_data_t { + /* get configuration type */ + configuration_attribute_type_t (*get_attribute_type)(vendor_request_data_t *this); + + /* return vendor data */ + chunk_t (*get_data)(vendor_request_data_t *this); + + /* is it empty data */ + bool (*is_empty)(vendor_request_data_t *this); + + /* destroy */ + void (*destroy)(vendor_request_data_t *this); +}; + +vendor_request_data_t* build_vendor_request_data(char *buffer, int *offset); +vendor_request_data_t* build_dns_request_data(host_t* host); + +#endif /* VENDOR_REQUEST_DATA_H */ \ No newline at end of file diff --git a/src/libcharon/comm/vendor_request_list.c b/src/libcharon/comm/vendor_request_list.c new file mode 100755 index 0000000..4aef3f1 --- /dev/null +++ b/src/libcharon/comm/vendor_request_list.c @@ -0,0 +1,80 @@ +#include "vendor_request_list.h" + +typedef struct private_vendor_request_list_t private_vendor_request_list_t; + +/** + * Private data + */ +struct private_vendor_request_list_t { + /** + * Public interface + */ + vendor_request_list_t public; + + /** Size */ + int size; + + /** Index */ + int index; + + /** Values */ + unsigned int *values; +}; + +METHOD(vendor_request_list_t, get_next, int, + private_vendor_request_list_t *this) +{ + if (this->size && (this->index < this->size)) + { + return this->values[this->index++]; + } + return 0; +} + +METHOD(vendor_request_list_t, reset, void, + private_vendor_request_list_t *this) +{ + this->index = 0; +} + +METHOD(vendor_request_list_t, destroy, void, + private_vendor_request_list_t *this) +{ + if (this->values) + { + free(this->values); + } + free(this); +} + +vendor_request_list_t* build_vendor_request_list(char *buffer) +{ + private_vendor_request_list_t *this; + + INIT(this, + .public = { + .get_next = _get_next, + .reset = _reset, + .destroy = _destroy, + }, + .size = 0, + .index = 0, + .values = NULL, + ); + if (buffer != NULL) + { + unsigned int size = *((unsigned int*)buffer); + unsigned short *values = (unsigned short*)(buffer + sizeof(int)); + + if (size) + { + this->size = size / 2; + this->values = calloc(this->size, sizeof(unsigned int)); + for (int i = 0; i < this->size; i++) + { + this->values[i] = values[i] & 0xFFFF; + } + } + } + return &this->public; +} diff --git a/src/libcharon/comm/vendor_request_list.h b/src/libcharon/comm/vendor_request_list.h new file mode 100755 index 0000000..f4c5c27 --- /dev/null +++ b/src/libcharon/comm/vendor_request_list.h @@ -0,0 +1,21 @@ +#ifndef VENDOR_REQUEST_LIST_H +#define VENDOR_REQUEST_LIST_H + +#include + +typedef struct vendor_request_list_t vendor_request_list_t; + +struct vendor_request_list_t { + /* get next request value */ + int (*get_next)(vendor_request_list_t *this); + + /* reset to list start */ + void (*reset)(vendor_request_list_t *this); + + /* destroy */ + void (*destroy)(vendor_request_list_t *this); +}; + +vendor_request_list_t* build_vendor_request_list(char *buffer); + +#endif /* VENDOR_REQUEST_LIST_H */ \ No newline at end of file diff --git a/src/libcharon/comm/vendor_response_data.c b/src/libcharon/comm/vendor_response_data.c new file mode 100755 index 0000000..00b05aa --- /dev/null +++ b/src/libcharon/comm/vendor_response_data.c @@ -0,0 +1,85 @@ +#include "vendor_response_data.h" + +typedef struct private_vendor_response_data_t private_vendor_response_data_t; + +/** + * Private data + */ +struct private_vendor_response_data_t { + /** + * Public interface + */ + vendor_response_data_t public; + + /** Type */ + int type; + + /** Data */ + chunk_t data; +}; + +/** + * Packed attribute structure to service +*/ +typedef struct { + unsigned short type; + unsigned short length; + char data[]; +} packed_vendor_response_data_t; + +METHOD(vendor_response_data_t, get_length, int, + private_vendor_response_data_t *this) +{ + return (sizeof(packed_vendor_response_data_t) + this->data.len); +} + +METHOD(vendor_response_data_t, pack, char*, + private_vendor_response_data_t *this, char *buffer) +{ + packed_vendor_response_data_t* packed = (packed_vendor_response_data_t*)buffer; + packed->type = this->type; + packed->length = this->data.len; + if (packed->length) + { + memcpy(packed->data, this->data.ptr, packed->length); + } + return (buffer + get_length(this)); +} + +METHOD(vendor_response_data_t, destroy, void, + private_vendor_response_data_t *this) +{ + free(this); +} + +vendor_response_data_t* build_vendor_response_data(int type, chunk_t data) +{ + private_vendor_response_data_t *this; + + INIT(this, + .public = { + .pack = _pack, + .get_length = _get_length, + .destroy = _destroy, + }, + .type = type, + .data = data, + ); + return &this->public; +} + +vendor_response_data_t* build_empty_response_data() +{ + private_vendor_response_data_t *this; + + INIT(this, + .public = { + .pack = _pack, + .get_length = _get_length, + .destroy = _destroy, + }, + .type = 0, + .data = chunk_empty, + ); + return &this->public; +} diff --git a/src/libcharon/comm/vendor_response_data.h b/src/libcharon/comm/vendor_response_data.h new file mode 100755 index 0000000..c1ec9ca --- /dev/null +++ b/src/libcharon/comm/vendor_response_data.h @@ -0,0 +1,22 @@ +#ifndef VENDOR_RESPONSE_DATA_H +#define VENDOR_RESPONSE_DATA_H + +#include + +typedef struct vendor_response_data_t vendor_response_data_t; + +struct vendor_response_data_t { + /* pack data to service */ + char* (*pack)(vendor_response_data_t *this, char *buffer); + + /* get full length */ + int (*get_length)(vendor_response_data_t *this); + + /* destroy */ + void (*destroy)(vendor_response_data_t *this); +}; + +vendor_response_data_t* build_vendor_response_data(int type, chunk_t data); +vendor_response_data_t* build_empty_response_data(); + +#endif /* VENDOR_RESPONSE_DATA_H */ \ No newline at end of file diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index c0178bb..75edb73 100755 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -25,6 +25,10 @@ #include #include +#ifdef VOWIFI_CFG +#include "vendor_request_list.h" +#endif + ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND, "CERT_ALWAYS_SEND", "CERT_SEND_IF_ASKED", @@ -202,9 +206,6 @@ struct private_peer_cfg_t { */ int use_original_ts; - /** Operator type */ - int operator; - /** Handover flag */ int handover; @@ -223,6 +224,13 @@ struct private_peer_cfg_t { double retransmit_timeout_handover; double retransmit_base_handover; int retransmit_retries_handover; + + /** + * Vendor attributes request list + * + * configuration attributes requested by service + */ + vendor_request_list_t *attributes_list; #endif }; @@ -781,6 +789,7 @@ METHOD(peer_cfg_t, get_ref, peer_cfg_t*, ref_get(&this->refcount); return &this->public; } + #ifdef VOWIFI_CFG METHOD(peer_cfg_t, set_keepalive_interval, void, private_peer_cfg_t *this, int interval) @@ -807,18 +816,6 @@ METHOD(peer_cfg_t, use_original_ts, int, return this->use_original_ts; } -METHOD(peer_cfg_t, set_operator, void, - private_peer_cfg_t *this, int op) -{ - this->operator = op; -} - -METHOD(peer_cfg_t, get_operator, int, - private_peer_cfg_t *this) -{ - return this->operator; -} - METHOD(peer_cfg_t, set_handover, void, private_peer_cfg_t *this, int status) { @@ -927,6 +924,34 @@ METHOD(peer_cfg_t, get_retransmit_retries_handover, int, { return this->retransmit_retries_handover; } + +METHOD(peer_cfg_t, add_vendor_attributes_request_list, void, + private_peer_cfg_t *this, char *buffer) +{ + if (buffer) + { + this->attributes_list = build_vendor_request_list(buffer); + } +} + +METHOD(peer_cfg_t, get_next_vendor_attribute_request, int, + private_peer_cfg_t *this) +{ + if (this->attributes_list) + { + return this->attributes_list->get_next(this->attributes_list); + } + return 0; +} + +METHOD(peer_cfg_t, rewind_vendor_attributes_request_list, void, + private_peer_cfg_t *this) +{ + if (this->attributes_list) + { + this->attributes_list->reset(this->attributes_list); + } +} #endif METHOD(peer_cfg_t, destroy, void, @@ -947,6 +972,9 @@ METHOD(peer_cfg_t, destroy, void, DESTROY_IF(this->peer_id); free(this->mediated_by); #endif /* ME */ +#ifdef VOWIFI_CFG + DESTROY_IF(this->attributes_list); +#endif DESTROY_IF(this->ppk_id); this->lock->destroy(this->lock); free(this->name); @@ -1013,8 +1041,6 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg, .get_keepalive_interval = _get_keepalive_interval, .set_use_original_ts = _set_use_original_ts, .use_original_ts = _use_original_ts, - .set_operator = _set_operator, - .get_operator = _get_operator, .set_handover = _set_handover, .is_handover = _get_handover, .set_interface = _set_interface_name, @@ -1033,6 +1059,9 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg, .get_retransmit_base_handover = _get_retransmit_base_handover, .set_retransmit_retries_handover = _set_retransmit_retries_handover, .get_retransmit_retries_handover = _get_retransmit_retries_handover, + .add_vendor_attributes_request_list = _add_vendor_attributes_request_list, + .get_next_vendor_attribute_request = _get_next_vendor_attribute_request, + .rewind_vendor_attributes_request_list = _rewind_vendor_attributes_request_list, #endif #ifdef ME .is_mediation = _is_mediation, @@ -1070,6 +1099,9 @@ peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg, .mediated_by = strdupnull(data->mediated_by), .peer_id = data->peer_id, #endif /* ME */ +#ifdef VOWIFI_CFG + .attributes_list = NULL, +#endif ); return &this->public; } diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index b060981..c6d7596 100755 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -407,16 +407,6 @@ struct peer_cfg_t { int (*use_original_ts)(peer_cfg_t *this); - /** - * Set operator type - */ - void (*set_operator)(peer_cfg_t *this, int op); - - /** - * Get operator type - */ - int (*get_operator)(peer_cfg_t *this); - /** * Set handover flag */ @@ -466,6 +456,13 @@ struct peer_cfg_t { double (*get_retransmit_timeout_handover)(peer_cfg_t *this); double (*get_retransmit_base_handover)(peer_cfg_t *this); int (*get_retransmit_retries_handover)(peer_cfg_t *this); + + /** + * Attributes vendor request list + */ + void (*add_vendor_attributes_request_list)(peer_cfg_t *this, char *buffer); + int (*get_next_vendor_attribute_request)(peer_cfg_t *this); + void (*rewind_vendor_attributes_request_list)(peer_cfg_t *this); #endif }; diff --git a/src/libcharon/encoding/payloads/configuration_attribute.c b/src/libcharon/encoding/payloads/configuration_attribute.c index 6c9ca89..8156376 100755 --- a/src/libcharon/encoding/payloads/configuration_attribute.c +++ b/src/libcharon/encoding/payloads/configuration_attribute.c @@ -133,10 +133,6 @@ METHOD(payload_t, verify, status_t, case INTERNAL_ADDRESS_EXPIRY: case INTERNAL_IP4_DHCP: case P_CSCF_IP4_ADDRESS: -#ifdef VOWIFI_CFG - case P_CSCF_IP4_ADDRESS_OPR_TYPE_1: - case P_CSCF_IP4_ADDRESS_OPR_TYPE_2: -#endif if (this->length_or_value != 0 && this->length_or_value != 4) { failed = TRUE; @@ -165,16 +161,10 @@ METHOD(payload_t, verify, status_t, case INTERNAL_IP6_DNS: case INTERNAL_IP6_NBNS: case INTERNAL_IP6_DHCP: +#ifndef VOWIFI_CFG case P_CSCF_IP6_ADDRESS: -#ifdef VOWIFI_CFG - case P_CSCF_IP6_ADDRESS_OPR_TYPE_1: - case P_CSCF_IP6_ADDRESS_OPR_TYPE_2: -#endif - if (this->length_or_value != 0 && this->length_or_value != 16 -#ifdef VOWIFI_CFG - && this->length_or_value != 17 #endif - ) + if (this->length_or_value != 0 && this->length_or_value != 16) { failed = TRUE; } @@ -185,10 +175,6 @@ METHOD(payload_t, verify, status_t, failed = TRUE; } break; -#ifdef VOWIFI_CFG - /* Adding attribute in any length acceptable case*/ - case DEVICE_IMEI: -#endif case APPLICATION_VERSION: case INTERNAL_IP4_SERVER: case INTERNAL_IP6_SERVER: diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c index 5e418cf..afa5a44 100755 --- a/src/libcharon/plugins/attr/attr_provider.c +++ b/src/libcharon/plugins/attr/attr_provider.c @@ -187,21 +187,16 @@ typedef struct { } attribute_type_key_t; static attribute_type_key_t keys[] = { - {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS, IKE_ANY}, - {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS, IKE_ANY}, - {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS, IKE_ANY}, - {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP, IKE_ANY}, - {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK, IKE_ANY}, - {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, IKE_ANY}, - {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET, IKE_ANY}, - {"p-cscf", P_CSCF_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, IKEV2}, -#ifdef VOWIFI_CFG - {"p-cscf", P_CSCF_IP4_ADDRESS_OPR_TYPE_1, P_CSCF_IP6_ADDRESS_OPR_TYPE_1, IKEV2}, - {"p-cscf", P_CSCF_IP4_ADDRESS_OPR_TYPE_2, P_CSCF_IP6_ADDRESS_OPR_TYPE_2, IKEV2}, - {"imei", DEVICE_IMEI, DEVICE_IMEI, IKEV2}, -#endif + {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS, IKE_ANY}, + {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS, IKE_ANY}, + {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS, IKE_ANY}, + {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP, IKE_ANY}, + {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK, IKE_ANY}, + {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, IKE_ANY}, + {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET, IKE_ANY}, + {"p-cscf", P_CSCF_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, IKEV2}, {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE, IKEV1}, - {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN, IKEV1}, + {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN, IKEV1}, }; /** diff --git a/src/libcharon/plugins/p_cscf/p_cscf_handler.c b/src/libcharon/plugins/p_cscf/p_cscf_handler.c index 1b31820..2cfa954 100755 --- a/src/libcharon/plugins/p_cscf/p_cscf_handler.c +++ b/src/libcharon/plugins/p_cscf/p_cscf_handler.c @@ -53,16 +53,6 @@ METHOD(attribute_handler_t, handle, bool, DBG1(DBG_CFG, "received P-CSCF server IP %H", server); server->destroy(server); return TRUE; -#ifdef VOWIFI_CFG - case P_CSCF_IP4_ADDRESS_OPR_TYPE_1: - case P_CSCF_IP4_ADDRESS_OPR_TYPE_2: - DBG1(DBG_CFG,"\n Received P_CSCF_IP4_ADDRESS attribute \n"); - return TRUE; - case P_CSCF_IP6_ADDRESS_OPR_TYPE_1: - case P_CSCF_IP6_ADDRESS_OPR_TYPE_2: - DBG1(DBG_CFG,"\n Received P_CSCF_IP6_ADDRESS attribute\n"); - return TRUE; -#endif default: return FALSE; } diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index e00f67c..372d838 100755 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -890,9 +890,6 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, } #ifdef VOWIFI_CFG - DBG1(DBG_CFG, "Operator Type : %d \n", msg->add_conn.opr_type); - peer_cfg->set_operator(peer_cfg, msg->add_conn.opr_type); - DBG1(DBG_CFG, "Keepalive interval : %d \n", msg->add_conn.keepalive_interval); peer_cfg->set_keepalive_interval(peer_cfg, msg->add_conn.keepalive_interval); @@ -906,6 +903,7 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this, peer_cfg->set_retransmit_timeout_handover(peer_cfg, msg->add_conn.retransmit_handover.timeout); peer_cfg->set_retransmit_base_handover(peer_cfg, msg->add_conn.retransmit_handover.base); peer_cfg->set_retransmit_retries_handover(peer_cfg, msg->add_conn.retransmit_handover.tries); + peer_cfg->add_vendor_attributes_request_list(peer_cfg, msg->add_conn.response.attributes); #endif return peer_cfg; } diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c index e406b5d..347135f 100755 --- a/src/libcharon/plugins/stroke/stroke_handler.c +++ b/src/libcharon/plugins/stroke/stroke_handler.c @@ -42,6 +42,7 @@ struct private_stroke_handler_t { rwlock_t *lock; }; +#ifndef VOWIFI_CFG /** * Attributes assigned to a connection */ @@ -50,22 +51,8 @@ typedef struct { char *name; /** list of DNS attributes, as host_t */ linked_list_t *dns; -#ifdef VOWIFI_CFG - /** list of P-CSCF attributes, as host_t */ - linked_list_t *pcscf; - /** list of IMEI attributes */ - linked_list_t *imei; -#endif } attributes_t; -#ifdef VOWIFI_CFG -#define IMEI_MAX 33 -typedef struct { - /* Device IMEI number*/ - char imei[IMEI_MAX]; -} imei_t; -#endif - /** * Destroy an attributes_t entry */ @@ -111,99 +98,9 @@ CALLBACK(attr_filter, bool, return FALSE; } -#ifdef VOWIFI_CFG -/** - * Filter function to convert host to PCSCF configuration attributes - */ -CALLBACK(attr_pcscf_filter, bool, - ike_sa_t *ike_sa, enumerator_t *orig, va_list args) -{ - configuration_attribute_type_t *type; - chunk_t *data; - host_t *host; - - VA_ARGS_VGET(args, type, data); - - while (orig->enumerate(orig, &host)) - { - switch (host->get_family(host)) - { - case AF_INET: - switch (ike_sa->get_operator(ike_sa)) { - case OPERATOR_TYPE_DEFAULT: - *type = P_CSCF_IP4_ADDRESS; - break; - case OPERATOR_TYPE_TMO_ATT: - *type = P_CSCF_IP4_ADDRESS_OPR_TYPE_1; - break; - case OPERATOR_TYPE_VZW: - *type = P_CSCF_IP4_ADDRESS_OPR_TYPE_2; - break; - default: - *type = P_CSCF_IP4_ADDRESS; - } - break; - case AF_INET6: - switch (ike_sa->get_operator(ike_sa)) { - case OPERATOR_TYPE_DEFAULT: - *type = P_CSCF_IP6_ADDRESS; - break; - case OPERATOR_TYPE_TMO_ATT: - *type = P_CSCF_IP6_ADDRESS_OPR_TYPE_1; - break; - case OPERATOR_TYPE_VZW: - *type = P_CSCF_IP6_ADDRESS_OPR_TYPE_2; - break; - default: - *type = P_CSCF_IP6_ADDRESS; - } - break; - default: - continue; - } - if (host->is_anyaddr(host)) - { - *data = chunk_empty; - } - else - { - *data = host->get_address(host); - } - return TRUE; - } - return FALSE; -} -/** - * Filter function to convert host to PCSCF configuration attributes - */ -CALLBACK(attr_imei_filter, bool, - void *lock, enumerator_t *orig, va_list args) -{ - configuration_attribute_type_t *type; - chunk_t *data; - imei_t *device_imei; - - VA_ARGS_VGET(args, type, data); - - while (orig->enumerate(orig, &device_imei)) - { - *type = DEVICE_IMEI; - *data = chunk_create(device_imei->imei, strlen(device_imei->imei)); - return TRUE; - } - return FALSE; -} -#endif - -#ifdef VOWIFI_CFG -METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, - private_stroke_handler_t *this, ike_sa_t *ike_sa, - linked_list_t *vips, int attr_type) -#else METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, private_stroke_handler_t *this, ike_sa_t *ike_sa, linked_list_t *vips) -#endif { peer_cfg_t *peer_cfg; enumerator_t *enumerator; @@ -220,31 +117,10 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, if (streq(attr->name, peer_cfg->get_name(peer_cfg))) { enumerator->destroy(enumerator); -#ifdef VOWIFI_CFG - if (attr_type == 0) - { -#endif return enumerator_create_filter( attr->dns->create_enumerator(attr->dns), attr_filter, this->lock, (void*)this->lock->unlock); -#ifdef VOWIFI_CFG - } - else if(attr_type == 1) - { - this->lock->unlock(this->lock); - return enumerator_create_filter( - attr->pcscf->create_enumerator(attr->pcscf), - attr_pcscf_filter, ike_sa, NULL); - } - else if(attr_type == 2) - { - return enumerator_create_filter( - attr->imei->create_enumerator(attr->imei), - attr_imei_filter, this->lock, - (void*)this->lock->unlock); - } -#endif } } enumerator->destroy(enumerator); @@ -256,15 +132,10 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, METHOD(stroke_handler_t, add_attributes, void, private_stroke_handler_t *this, stroke_msg_t *msg) { -#ifdef VOWIFI_CFG - attributes_t *attr = NULL; -#endif if (msg->add_conn.me.dns) { enumerator_t *enumerator; -#ifndef VOWIFI_CFG attributes_t *attr = NULL; -#endif host_t *host; char *token; @@ -290,10 +161,6 @@ METHOD(stroke_handler_t, add_attributes, void, INIT(attr, .name = strdup(msg->add_conn.name), .dns = linked_list_create(), -#ifdef VOWIFI_CFG - .pcscf = linked_list_create(), - .imei = linked_list_create(), -#endif ); } attr->dns->insert_last(attr->dns, host); @@ -304,23 +171,168 @@ METHOD(stroke_handler_t, add_attributes, void, } } enumerator->destroy(enumerator); -#ifndef VOWIFI_CFG if (attr) { this->lock->write_lock(this->lock); this->attrs->insert_last(this->attrs, attr); this->lock->unlock(this->lock); } -#endif } -#ifdef VOWIFI_CFG - if (msg->add_conn.pcscf) +} + +METHOD(stroke_handler_t, del_attributes, void, + private_stroke_handler_t *this, stroke_msg_t *msg) +{ + enumerator_t *enumerator; + attributes_t *attr; + + this->lock->write_lock(this->lock); + enumerator = this->attrs->create_enumerator(this->attrs); + while (enumerator->enumerate(enumerator, &attr)) + { + if (streq(msg->del_conn.name, attr->name)) + { + this->attrs->remove_at(this->attrs, enumerator); + attributes_destroy(attr); + break; + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); +} + +METHOD(stroke_handler_t, destroy, void, + private_stroke_handler_t *this) +{ + this->lock->destroy(this->lock); + this->attrs->destroy_function(this->attrs, (void*)attributes_destroy); + free(this); +} + +#else + +#include "vendor_request_data.h" + +/** + * Attributes assigned to a connection + */ +typedef struct { + /** name of the connection */ + char *name; + /** list of attributes, as vendor_request_data_t */ + linked_list_t *list; +} attributes_t; + +/** + * Destroy an attributes_t entry + */ +static void attributes_destroy(attributes_t *this) +{ + this->list->destroy_offset(this->list, offsetof(vendor_request_data_t, destroy)); + free(this->name); + free(this); +} + +CALLBACK(match_by_type, bool, + vendor_request_data_t *this, va_list args) +{ + int type; + + VA_ARGS_VGET(args, type); + return (this->get_attribute_type(this) == type); +} + +METHOD(attribute_handler_t, handle, bool, + private_stroke_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data) +{ + enumerator_t *enumerator; + attributes_t *attr; + bool result = FALSE; + peer_cfg_t *peer_cfg = ike_sa->get_peer_cfg(ike_sa); + + this->lock->read_lock(this->lock); + enumerator = this->attrs->create_enumerator(this->attrs); + while (enumerator->enumerate(enumerator, &attr)) + { + if (streq(attr->name, peer_cfg->get_name(peer_cfg))) + { + if (attr->list->find_first(attr->list, match_by_type, NULL, type)) + { + DBG1(DBG_CFG, "processed attribute %d", type); + + result = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + return result; +} + +CALLBACK(attr_filter, bool, + void *lock, enumerator_t *orig, va_list args) +{ + configuration_attribute_type_t *type; + chunk_t *data; + vendor_request_data_t *attr; + + VA_ARGS_VGET(args, type, data); + + while (orig->enumerate(orig, &attr)) + { + *type = attr->get_attribute_type(attr); + *data = attr->get_data(attr); + return TRUE; + } + return FALSE; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*, + private_stroke_handler_t *this, ike_sa_t *ike_sa, + linked_list_t *vips) +{ + peer_cfg_t *peer_cfg; + enumerator_t *enumerator; + attributes_t *attr; + + ike_sa = charon->bus->get_sa(charon->bus); + if (ike_sa) + { + peer_cfg = ike_sa->get_peer_cfg(ike_sa); + this->lock->read_lock(this->lock); + enumerator = this->attrs->create_enumerator(this->attrs); + while (enumerator->enumerate(enumerator, &attr)) + { + if (streq(attr->name, peer_cfg->get_name(peer_cfg))) + { + enumerator->destroy(enumerator); + return enumerator_create_filter( + attr->list->create_enumerator(attr->list), + attr_filter, this->lock, + (void*)this->lock->unlock); + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + } + return enumerator_create_empty(); +} + +METHOD(stroke_handler_t, add_attributes, void, + private_stroke_handler_t *this, stroke_msg_t *msg) +{ + attributes_t *attr = NULL; + + if (msg->add_conn.me.dns) { enumerator_t *enumerator; host_t *host; char *token; - enumerator = enumerator_create_token(msg->add_conn.pcscf, ",", " "); + enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " "); while (enumerator->enumerate(enumerator, &token)) { if (streq(token, "%config") || streq(token, "%config4")) @@ -341,44 +353,38 @@ METHOD(stroke_handler_t, add_attributes, void, { INIT(attr, .name = strdup(msg->add_conn.name), - .dns = linked_list_create(), - .pcscf = linked_list_create(), - .imei = linked_list_create(), + .list = linked_list_create(), ); } - attr->pcscf->insert_last(attr->pcscf, host); + vendor_request_data_t *request = build_dns_request_data(host); + attr->list->insert_last(attr->list, request); + host->destroy(host); } else { - DBG1(DBG_CFG, "ignoring invalid PCSCF address '%s'", token); + DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token); } } enumerator->destroy(enumerator); } - - if (msg->add_conn.imei) + if (msg->add_conn.request.attributes) { - imei_t *device_imei; - INIT(device_imei); - if (device_imei) + int offset = 0; + + vendor_request_data_t *request = build_vendor_request_data(msg->add_conn.request.attributes, &offset); + while (!request->is_empty(request)) { - strncpy(device_imei->imei, msg->add_conn.imei, IMEI_MAX - 1); - DBG1(DBG_CFG, " Adding IMEI: '%s'", device_imei->imei); if (!attr) { INIT(attr, .name = strdup(msg->add_conn.name), - .dns = linked_list_create(), - .pcscf = linked_list_create(), - .imei = linked_list_create(), + .list = linked_list_create(), ); } - attr->imei->insert_last(attr->imei, device_imei); - } - else - { - DBG1(DBG_CFG, "Failed to add attribute IMEI: '%s'", msg->add_conn.imei); + attr->list->insert_last(attr->list, request); + request = build_vendor_request_data(msg->add_conn.request.attributes, &offset); } + request->destroy(request); } if (attr) { @@ -386,7 +392,6 @@ METHOD(stroke_handler_t, add_attributes, void, this->attrs->insert_last(this->attrs, attr); this->lock->unlock(this->lock); } -#endif } METHOD(stroke_handler_t, del_attributes, void, @@ -418,6 +423,8 @@ METHOD(stroke_handler_t, destroy, void, free(this); } +#endif + /** * See header */ @@ -428,7 +435,11 @@ stroke_handler_t *stroke_handler_create() INIT(this, .public = { .handler = { +#ifndef VOWIFI_CFG .handle = (void*)return_false, +#else + .handle = _handle, +#endif .release = (void*)return_false, .create_attribute_enumerator = _create_attribute_enumerator, }, diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 420d0df..b205911 100755 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -217,8 +217,11 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) pop_string(msg, &msg->add_conn.ikeme.mediated_by); pop_string(msg, &msg->add_conn.ikeme.peerid); #ifdef VOWIFI_CFG - pop_string(msg, &msg->add_conn.pcscf); - pop_string(msg, &msg->add_conn.imei); + /* data arrays */ + pop_string(msg, &msg->add_conn.request.attributes); + pop_string(msg, &msg->add_conn.request.notifies); + pop_string(msg, &msg->add_conn.response.attributes); + pop_string(msg, &msg->add_conn.response.notifies); #endif DBG_OPT(" eap_identity=%s", msg->add_conn.eap_identity); DBG_OPT(" aaa_identity=%s", msg->add_conn.aaa_identity); @@ -235,10 +238,6 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) DBG_OPT(" mediated_by=%s", msg->add_conn.ikeme.mediated_by); DBG_OPT(" me_peerid=%s", msg->add_conn.ikeme.peerid); DBG_OPT(" keyexchange=ikev%u", msg->add_conn.version); -#ifdef VOWIFI_CFG - DBG_OPT(" pcscf=%s", msg->add_conn.pcscf); - DBG_OPT(" imei=%s", msg->add_conn.imei); -#endif this->config->add(this->config, msg); this->attribute->add_dns(this->attribute, msg); @@ -950,7 +949,7 @@ stroke_socket_t *stroke_socket_create() time(&t1); DBG1(DBG_CFG," Created stroke socket at time: %s", ctime(&t1)); DBG1(DBG_CFG, "Changing owner to: %d", AID_RADIO); - if(chown( STROKE_SOCKET, AID_RADIO, AID_RADIO) == -1) + if(chown(STROKE_SOCKET, AID_RADIO, AID_RADIO) == -1) { DBG1(DBG_CFG, "chown failed for socket: %s", strerror(errno)); } diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 4d4d344..b8f17e0 100755 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -68,6 +68,7 @@ #ifdef VOWIFI_CFG #include #include +#include "vendor_response_data.h" #endif #ifdef VOWIFI_PMTU_DISCOVERY #include @@ -3610,62 +3611,44 @@ METHOD(ike_sa_t, destroy, void, } #ifdef VOWIFI_CFG -METHOD(ike_sa_t, get_ip_configuration_attribute, char*, - private_ike_sa_t *this, configuration_attribute_type_t type, int cnt) +METHOD(ike_sa_t, get_configuration_attributes, int, + private_ike_sa_t *this, linked_list_t *list) { - attribute_entry_t entry; - int i, pos = 0, len = INET6_ADDRSTRLEN * cnt + 1 + cnt; + int i, total = 0; charon->bus->set_sa(charon->bus, &this->public); /* remove attributes first, as we pass the IKE_SA to the handler */ charon->bus->handle_vips(charon->bus, &this->public, FALSE); - char* mem = calloc(len, 1); - for (i = 0; i < array_count(this->attributes); i++) + if (this->peer_cfg) { - array_get(this->attributes, i, &entry); - if (entry.handler && (entry.type == type)) - { - if (entry.data.len >= 16) - { - if ((len - pos) < INET6_ADDRSTRLEN) - { - pos++; - break; - } - inet_ntop(AF_INET6, entry.data.ptr, mem + pos, (len - pos)); - } - else if (entry.data.len >= 4) + int type = this->peer_cfg->get_next_vendor_attribute_request(this->peer_cfg); + while (type) + { + for (i = 0; i < array_count(this->attributes); i++) { - if ((len - pos) < INET_ADDRSTRLEN) - { - pos++; - break; + attribute_entry_t entry; + + array_get(this->attributes, i, &entry); + if (entry.handler && (entry.type == type)) + { + vendor_response_data_t *response = build_vendor_response_data(entry.type, entry.data); + total += response->get_length(response); + list->insert_last(list, response); } - inet_ntop(AF_INET, entry.data.ptr, mem + pos, (len - pos)); } - strcat(mem, ","); - pos = strlen(mem); + type = this->peer_cfg->get_next_vendor_attribute_request(this->peer_cfg); } + this->peer_cfg->rewind_vendor_attributes_request_list(this->peer_cfg); } - - if(pos == 0) - { - free(mem); - return NULL; - } - else + if (list->get_count(list) > 0) { - mem[pos - 1] = 0; + vendor_response_data_t *response = build_empty_response_data(); + total += response->get_length(response); + list->insert_last(list, response); } - return mem; -} - -METHOD(ike_sa_t, get_operator, int, - private_ike_sa_t *this) -{ - return this->peer_cfg->get_operator(this->peer_cfg); + return total; } METHOD(ike_sa_t, set_handover, void, @@ -3886,7 +3869,6 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .queue_task_delayed = _queue_task_delayed, .adopt_child_tasks = _adopt_child_tasks, #ifdef VOWIFI_CFG - .get_operator = _get_operator, .set_handover = _set_handover, .is_handover = _get_handover, .set_terminate = _set_terminate, @@ -3895,7 +3877,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator, .wait_for_installed_vip = _wait_for_installed_vip, .get_tun_name = _get_tun_name, .get_mtu = _get_mtu, - .get_ip_configuration_attribute = _get_ip_configuration_attribute, + .get_configuration_attributes = _get_configuration_attributes, #endif #ifdef ME .act_as_mediation_server = _act_as_mediation_server, diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h index 93e8164..363d8a9 100755 --- a/src/libcharon/sa/ike_sa.h +++ b/src/libcharon/sa/ike_sa.h @@ -1210,11 +1210,6 @@ struct ike_sa_t { void (*destroy) (ike_sa_t *this); #ifdef VOWIFI_CFG - /** - * Get operator type - */ - int (*get_operator)(ike_sa_t *this); - /** * Set handover flag */ @@ -1256,9 +1251,9 @@ struct ike_sa_t { int (*get_mtu)(ike_sa_t *this); /** - * Get IP attributes + * Get configuration attributes */ - char* (*get_ip_configuration_attribute)(ike_sa_t *this, configuration_attribute_type_t type, int cnt); + int (*get_configuration_attributes)(ike_sa_t *this, linked_list_t *list); #endif }; diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c index 85e3db3..e746a37 100755 --- a/src/libcharon/sa/ikev2/tasks/ike_config.c +++ b/src/libcharon/sa/ikev2/tasks/ike_config.c @@ -294,11 +294,7 @@ METHOD(task_t, build_i, status_t, enumerator = charon->attributes->create_initiator_enumerator( charon->attributes, this->ike_sa, vips); -#ifdef VOWIFI_CFG - while (enumerator->enumerate(enumerator, &handler, &type, &data, 0)) -#else while (enumerator->enumerate(enumerator, &handler, &type, &data)) -#endif { configuration_attribute_t *ca; entry_t *entry; @@ -322,59 +318,6 @@ METHOD(task_t, build_i, status_t, this->requested->insert_last(this->requested, entry); } enumerator->destroy(enumerator); -#ifdef VOWIFI_CFG - enumerator = charon->attributes->create_initiator_enumerator( - charon->attributes, this->ike_sa, vips); - while (enumerator->enumerate(enumerator, &handler, &type, &data, 1)) - { - configuration_attribute_t *ca; - entry_t *entry; - /* create configuration attribute */ - DBG1(DBG_IKE, "building %N attribute", - configuration_attribute_type_names, type); - ca = configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE, - type, data); - if (!cp) - { - cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST); - } - cp->add_attribute(cp, ca); - - /* save handler along with requested type */ - entry = malloc_thing(entry_t); - entry->type = type; - entry->handler = handler; - - this->requested->insert_last(this->requested, entry); - } - enumerator->destroy(enumerator); - - enumerator = charon->attributes->create_initiator_enumerator( - charon->attributes, this->ike_sa, vips); - while (enumerator->enumerate(enumerator, &handler, &type, &data, 2)) - { - configuration_attribute_t *ca; - entry_t *entry; - /* create configuration attribute */ - DBG1(DBG_IKE, "building %N attribute", - configuration_attribute_type_names, type); - ca = configuration_attribute_create_chunk(PLV2_CONFIGURATION_ATTRIBUTE, - type, data); - if (!cp) - { - cp = cp_payload_create_type(PLV2_CONFIGURATION, CFG_REQUEST); - } - cp->add_attribute(cp, ca); - - /* save handler along with requested type */ - entry = malloc_thing(entry_t); - entry->type = type; - entry->handler = handler; - - this->requested->insert_last(this->requested, entry); - } - enumerator->destroy(enumerator); -#endif vips->destroy(vips); if (cp) diff --git a/src/libstrongswan/networking/tun_device.c b/src/libstrongswan/networking/tun_device.c index a43d63c..a8e4dd6 100755 --- a/src/libstrongswan/networking/tun_device.c +++ b/src/libstrongswan/networking/tun_device.c @@ -435,6 +435,7 @@ METHOD(tun_device_t, destroy, void, this->addresses->remove_at(this->addresses, enumerator); address->destroy(address); } + enumerator->destroy(enumerator); #endif free(this); } diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index a84599f..95934c3 100755 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -31,14 +31,6 @@ */ #define STROKE_BUF_LEN_INC 1024 -#ifdef VOWIFI_CFG -typedef enum { - OPERATOR_TYPE_DEFAULT = 0, - OPERATOR_TYPE_TMO_ATT, - OPERATOR_TYPE_VZW, -} operator_type_t; -#endif - typedef enum list_flag_t list_flag_t; /** @@ -320,10 +312,11 @@ struct stroke_msg_t { uint32_t replay_window; bool sha256_96; #ifdef VOWIFI_CFG - char* interface; - operator_type_t opr_type; - char *pcscf; - char *imei; + char *interface; + struct { + char *attributes; + char *notifies; + } request, response; struct { float timeout; float base; -- 2.20.1