Add setter/getter for handling MAC randomization policy
[platform/upstream/connman.git] / src / technology.c
index 440d7eb..c476b3e 100644 (file)
@@ -100,6 +100,9 @@ struct connman_technology {
        bool dbus_registered;
 #if defined TIZEN_EXT
        char **enabled_devices;
+       unsigned int mac_policy;
+       unsigned int preassoc_mac_policy;
+       unsigned int random_mac_lifetime;
 #endif
 #if defined TIZEN_EXT_WIFI_MESH
        DBusMessage *mesh_dbus_msg;
@@ -218,6 +221,19 @@ static void technology_save(struct connman_technology *technology)
                                        "Tethering.Passphrase",
                                        technology->tethering_passphrase);
 
+#ifdef TIZEN_EXT
+       if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
+               g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
+                                       technology->mac_policy);
+
+               g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
+                                       technology->preassoc_mac_policy);
+
+               g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
+                                       technology->random_mac_lifetime);
+       }
+#endif /* TIZEN_EXT */
+
 done:
        g_free(identifier);
 
@@ -488,6 +504,34 @@ static void technology_load(struct connman_technology *technology)
 
        technology->tethering_passphrase = g_key_file_get_string(keyfile,
                                identifier, "Tethering.Passphrase", NULL);
+
+#ifdef TIZEN_EXT
+       if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
+               unsigned int val = 0;
+
+               val = g_key_file_get_uint64(keyfile,
+                               identifier, "MacPolicy", NULL);
+               if (val <= 2)
+                       technology->mac_policy = val;
+               else
+                       technology->mac_policy = 0;
+
+               val = g_key_file_get_uint64(keyfile,
+                               identifier, "PreassocMacPolicy", NULL);
+               if (val <= 2)
+                       technology->preassoc_mac_policy = val;
+               else
+                       technology->preassoc_mac_policy = 0;
+
+               val = g_key_file_get_uint64(keyfile,
+                               identifier, "RandomMacLifetime", NULL);
+               if (val > 0)
+                       technology->random_mac_lifetime = val;
+               else
+                       technology->random_mac_lifetime = 60;
+       }
+#endif /* TIZEN_EXT */
+
 done:
        g_free(identifier);
 
@@ -666,6 +710,18 @@ static void append_properties(DBusMessageIter *iter,
                connman_dbus_dict_append_basic(&dict, "TetheringPassphrase",
                                        DBUS_TYPE_STRING,
                                        &technology->tethering_passphrase);
+
+       connman_dbus_dict_append_basic(&dict, "MacPolicy",
+                                       DBUS_TYPE_UINT32,
+                                       &(technology->mac_policy));
+
+       connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
+                                       DBUS_TYPE_UINT32,
+                                       &(technology->preassoc_mac_policy));
+
+       connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
+                                       DBUS_TYPE_UINT32,
+                                       &(technology->random_mac_lifetime));
 #if defined TIZEN_EXT
        if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
                connman_dbus_dict_append_dict(&dict, "Device.List",
@@ -1078,6 +1134,190 @@ int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
 
        return bssid_len;
 }
+
+void connman_technology_mac_policy_notify(struct connman_technology *technology,
+                                                       unsigned int policy)
+{
+       DBG("Mac polict set to %u", policy);
+
+       technology->mac_policy = policy;
+       technology_save(technology);
+}
+
+void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
+                                               int result, unsigned int policy)
+{
+       struct connman_technology *technology;
+       enum connman_service_type type;
+
+       type = __connman_device_get_service_type(device);
+       technology = technology_find(type);
+
+       if (!technology)
+               return;
+
+       connman_technology_mac_policy_notify(technology, policy);
+}
+
+static DBusMessage *set_mac_policy(struct connman_technology *technology,
+                               DBusMessage *msg, unsigned int policy)
+{
+       DBusMessage *reply = NULL;
+       int err = 0;
+       unsigned int last_policy = technology->mac_policy;
+
+       if (technology->rfkill_driven && technology->hardblocked) {
+               err = -EACCES;
+               goto make_reply;
+       }
+
+       for (GSList *list = technology->device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+
+               err = connman_device_set_mac_policy(device, policy);
+               if (err < 0)
+                       break;
+       }
+
+make_reply:
+       if (err < 0) {
+               if (err != -EACCES && err != -EOPNOTSUPP) {
+                       for (GSList *list = technology->device_list; list; list = list->next) {
+                               struct connman_device *device = list->data;
+
+                               connman_device_set_mac_policy(device, last_policy);
+                       }
+               }
+
+               reply = __connman_error_failed(msg, -err);
+       } else {
+               reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+       }
+
+       return reply;
+}
+
+void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
+                                                       unsigned int policy)
+{
+       DBG("Preassoc mac polict set to %u", policy);
+
+       technology->preassoc_mac_policy = policy;
+       technology_save(technology);
+}
+
+void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
+                                               int result, unsigned int policy)
+{
+       struct connman_technology *technology;
+       enum connman_service_type type;
+
+       type = __connman_device_get_service_type(device);
+       technology = technology_find(type);
+
+       if (!technology)
+               return;
+
+       connman_technology_preassoc_mac_policy_notify(technology, policy);
+}
+
+static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
+                               DBusMessage *msg, unsigned int policy)
+{
+       DBusMessage *reply = NULL;
+       int err = 0;
+       unsigned int last_policy = technology->preassoc_mac_policy;
+
+       if (technology->rfkill_driven && technology->hardblocked) {
+               err = -EACCES;
+               goto make_reply;
+       }
+
+       for (GSList *list = technology->device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+
+               err = connman_device_set_preassoc_mac_policy(device, policy);
+               if (err < 0)
+                       break;
+       }
+
+make_reply:
+       if (err < 0) {
+               if (err != -EACCES && err != -EOPNOTSUPP) {
+                       for (GSList *list = technology->device_list; list; list = list->next) {
+                               struct connman_device *device = list->data;
+
+                               connman_device_set_preassoc_mac_policy(device, last_policy);
+                       }
+               }
+
+               reply = __connman_error_failed(msg, -err);
+       } else {
+               reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+       }
+
+       return reply;
+}
+
+void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
+                                                       unsigned int lifetime)
+{
+       DBG("Random mac lifetime set to %u", lifetime);
+
+       technology->random_mac_lifetime = lifetime;
+       technology_save(technology);
+}
+
+void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
+                                               int result, unsigned int lifetime)
+{
+       struct connman_technology *technology;
+       enum connman_service_type type;
+
+       type = __connman_device_get_service_type(device);
+       technology = technology_find(type);
+
+       if (!technology)
+               return;
+
+       connman_technology_random_mac_lifetime_notify(technology, lifetime);
+}
+
+static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
+                               DBusMessage *msg, unsigned int lifetime)
+{
+       DBusMessage *reply = NULL;
+       int err = 0;
+       unsigned int last_lifetime = technology->random_mac_lifetime;
+
+       if (technology->rfkill_driven && technology->hardblocked) {
+               err = -EACCES;
+               goto make_reply;
+       }
+
+       for (GSList *list = technology->device_list; list; list = list->next) {
+               struct connman_device *device = list->data;
+
+               err = connman_device_set_random_mac_lifetime(device, lifetime);
+       }
+
+make_reply:
+       if (err < 0) {
+               if (err != -EACCES && err != -EOPNOTSUPP) {
+                       for (GSList *list = technology->device_list; list; list = list->next) {
+                               struct connman_device *device = list->data;
+
+                               connman_device_set_random_mac_lifetime(device, last_lifetime);
+                       }
+               }
+
+               reply = __connman_error_failed(msg, -err);
+       } else {
+               reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+       }
+
+       return reply;
+}
 #endif
 
 static DBusMessage *set_property(DBusConnection *conn,
@@ -1203,6 +1443,53 @@ static DBusMessage *set_property(DBusConnection *conn,
                dbus_message_iter_get_basic(&value, &key);
                DBG("BSSID %s", key);
                set_connman_bssid(SET_BSSID, key, NULL);
+       } else if (g_str_equal(name, "MacPolicy")) {
+               dbus_uint32_t mac_policy;
+
+               if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+                       return __connman_error_not_supported(msg);
+
+               if (type != DBUS_TYPE_UINT32)
+                       return __connman_error_invalid_arguments(msg);
+
+               dbus_message_iter_get_basic(&value, &mac_policy);
+
+               if (mac_policy <= 2)
+                       return set_mac_policy(technology, msg, mac_policy);
+               else
+                       return __connman_error_invalid_arguments(msg);
+
+       } else if (g_str_equal(name, "PreassocMacPolicy")) {
+               dbus_uint32_t preassoc_mac_policy;
+
+               if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+                       return __connman_error_not_supported(msg);
+
+               if (type != DBUS_TYPE_UINT32)
+                       return __connman_error_invalid_arguments(msg);
+
+               dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
+
+               if (preassoc_mac_policy <= 2)
+                       return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
+               else
+                       return __connman_error_invalid_arguments(msg);
+
+       } else if (g_str_equal(name, "RandomMacLifetime")) {
+               dbus_uint32_t random_mac_lifetime;
+
+               if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+                       return __connman_error_not_supported(msg);
+
+               if (type != DBUS_TYPE_UINT32)
+                       return __connman_error_invalid_arguments(msg);
+
+               dbus_message_iter_get_basic(&value, &random_mac_lifetime);
+
+               if (random_mac_lifetime > 0)
+                       return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
+               else
+                       return __connman_error_invalid_arguments(msg);
 #endif
        } else
                return __connman_error_invalid_property(msg);
@@ -2960,6 +3247,10 @@ done:
 #if defined TIZEN_EXT
        const char *ifname = connman_device_get_string(device, "Interface");
        __connman_technology_notify_device_detected(technology, ifname, true);
+
+       connman_device_set_mac_policy(device, technology->mac_policy);
+       connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
+       connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
 #endif
        return 0;
 }