add configurable vendor attributes and notifies lists
authorDenis Vinogradov <denis.vinogradov@samsung.com>
Wed, 26 Aug 2020 06:01:57 +0000 (15:01 +0900)
committerSeongsik Kim <sz.kim@samsung.com>
Wed, 9 Sep 2020 04:36:21 +0000 (13:36 +0900)
  Request and response

Change-Id: Ibdab0e2bf9a22fc427c64c7cbf9b66bf85cc84a5
Signed-off-by: Denis Vinogradov <denis.vinogradov@samsung.com>
27 files changed:
Android.mk
src/libcharon/Android.mk
src/libcharon/attributes/attribute_handler.h
src/libcharon/attributes/attribute_manager.c
src/libcharon/attributes/attributes.c
src/libcharon/attributes/attributes.h
src/libcharon/comm/comm_msg.c
src/libcharon/comm/comm_msg.h
src/libcharon/comm/vendor_request_data.c [new file with mode: 0755]
src/libcharon/comm/vendor_request_data.h [new file with mode: 0755]
src/libcharon/comm/vendor_request_list.c [new file with mode: 0755]
src/libcharon/comm/vendor_request_list.h [new file with mode: 0755]
src/libcharon/comm/vendor_response_data.c [new file with mode: 0755]
src/libcharon/comm/vendor_response_data.h [new file with mode: 0755]
src/libcharon/config/peer_cfg.c
src/libcharon/config/peer_cfg.h
src/libcharon/encoding/payloads/configuration_attribute.c
src/libcharon/plugins/attr/attr_provider.c
src/libcharon/plugins/p_cscf/p_cscf_handler.c
src/libcharon/plugins/stroke/stroke_config.c
src/libcharon/plugins/stroke/stroke_handler.c
src/libcharon/plugins/stroke/stroke_socket.c
src/libcharon/sa/ike_sa.c
src/libcharon/sa/ike_sa.h
src/libcharon/sa/ikev2/tasks/ike_config.c
src/libstrongswan/networking/tun_device.c
src/stroke/stroke_msg.h

index abddf6f41280d8fc0c76d040b52e15e4f76f9039..8d6b0e094f900a273d2a04443eb488e60ce55804 100755 (executable)
@@ -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),)
index a278d07e76b41e00c67b282021d8900656d9f2a5..5ff87631f3470fd9ee774a46ab4e4a041ebd503e 100755 (executable)
@@ -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))
 
index 2f1ac3a5537eea03c55b670c694f312f3714391b..cc09befe8cbb88eb0feff2095258b2a62d08fe37 100755 (executable)
@@ -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_ @}*/
index 1d6111ca6229419eca6cae4b76417fa5897444f3..0a0220b254db0e2dfec43b208675026cd294f8b0 100755 (executable)
@@ -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;
index 6381b7c1b01874756586b74db8eb0b911ec8954f..52c2ef1f38ee47dd3a5adba476f4e8825492b862 100755 (executable)
@@ -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",
index 1fdf8d78424b28acf6248af24b67c2faf48e06e5..f632787996dbb1356179e4dde3e97182b534050f 100755 (executable)
@@ -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,
index 09d1ab837bb3a054cea8ef5042c41411843b03f6..38e924f6f3a3b6cf67be6586043212f69df11cee 100755 (executable)
@@ -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");
index ecf3bf731fe03d809e5e7ae9f41fa4003a1ec7bd..1f75b4d9d98d005789b440cbd821e23ecae00cd2 100755 (executable)
@@ -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 (executable)
index 0000000..217a8b0
--- /dev/null
@@ -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 (executable)
index 0000000..98fb39d
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef VENDOR_REQUEST_DATA_H
+#define VENDOR_REQUEST_DATA_H
+
+#include <daemon.h>
+
+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 (executable)
index 0000000..4aef3f1
--- /dev/null
@@ -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 (executable)
index 0000000..f4c5c27
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef VENDOR_REQUEST_LIST_H
+#define VENDOR_REQUEST_LIST_H
+
+#include <daemon.h>
+
+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 (executable)
index 0000000..00b05aa
--- /dev/null
@@ -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 (executable)
index 0000000..c1ec9ca
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef VENDOR_RESPONSE_DATA_H
+#define VENDOR_RESPONSE_DATA_H
+
+#include <daemon.h>
+
+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
index c0178bba37d9db63f0c687a3e3ef9eac6e9cde6e..75edb73dc5ee4c27104349c77128123b26f1a219 100755 (executable)
 #include <collections/linked_list.h>
 #include <utils/identification.h>
 
+#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;
 }
index b060981edc5ff17ae3d8bc167a2a1fa605a183aa..c6d759683370a08651835a2d498cadc087f06d3b 100755 (executable)
@@ -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
 };
 
index 6c9ca89b0dc2c2c8f23af8dc75a12ddcf8d3b66f..8156376cd2a5a908f1026df9a65d34edffba4477 100755 (executable)
@@ -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:
index 5e418cf50bc7c8bf70d066bc7bd598907df7b457..afa5a44f6b7aab4dd626b1c7269e164d26c52099 100755 (executable)
@@ -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},
 };
 
 /**
index 1b31820c0590d6332eae9cda32b3d975dcdb60ea..2cfa954410bb41448b25d23aaae62254669d4a17 100755 (executable)
@@ -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;
        }
index e00f67cef47b264ce1fb08a97976a7af5e39d083..372d83801995436fb27659054a2770d1ec40fa77 100755 (executable)
@@ -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;
 }
index e406b5d2631ab8d8ddeff3911922c7fdd68691a1..347135f9de3b76bdc533a28d7529f4049aed36e9 100755 (executable)
@@ -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,
                        },
index 420d0df71c5adec74ab41ed6120b6575bbde7471..b2059113b1d77376167234d6c4ddb8732b19081c 100755 (executable)
@@ -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));
                }
index 4d4d344717c07402f9553d27da74305bab615019..b8f17e07aadb8210b7f0befaf2db053c6d284793 100755 (executable)
@@ -68,6 +68,7 @@
 #ifdef VOWIFI_CFG
 #include <pthread.h>
 #include <networking/tun_device.h>
+#include "vendor_response_data.h"
 #endif
 #ifdef VOWIFI_PMTU_DISCOVERY
 #include <linux/errqueue.h>
@@ -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,
index 93e81648b0455ce2a4eb44e0ce21be821eb8e571..363d8a9bc86f75c23187279028960da4e2b64c30 100755 (executable)
@@ -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
 };
 
index 85e3db31dabc1c5cd34917e3f1643bcd00b0b77d..e746a3756ae4bddb62bffa34a391ac97bc4f531a 100755 (executable)
@@ -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)
index a43d63c369e5017b020656a090313e1138161fd8..a8e4dd680d37c7602c37056efaafab7512bb8f9d 100755 (executable)
@@ -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);
 }
index a84599fee0b765bd49a4aa55fdb9b30fd8830854..95934c313435915d93b4f3a95bf252b08b1e9388 100755 (executable)
  */
 #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;