2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <vconf/vconf.h>
18 #include <openssl/sha.h>
20 #include "stc-monitor.h"
21 #include "stc-firewall.h"
22 #include "stc-manager-gdbus.h"
23 #include "stc-default-connection.h"
25 /* connman service dbus details */
26 #define CONNMAN_SERVICE "net.connman"
27 #define CONNMAN_PATH "/net/connman"
29 #define CONNMAN_MANAGER_PATH "/"
30 #define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
31 #define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
33 #define CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/cellular_"
34 #define CONNMAN_WIFI_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/wifi_"
35 #define CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/ethernet_"
36 #define CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/bluetooth_"
38 #define CONNMAN_SIGNAL_PROPERTY_CHANGED "PropertyChanged"
40 /* telephony service dbus details */
41 #define TELEPHONY_SERVICE "org.tizen.telephony"
42 #define TELEPHONY_DEFAULT_PATH "/org/tizen/telephony"
44 #define TELEPHONY_SERVICE_MANAGER TELEPHONY_SERVICE".Manager"
45 #define TELEPHONY_SIM_INTERFACE TELEPHONY_SERVICE".Sim"
47 #define TELEPHONY_GET_MODEMS "GetModems"
48 #define TELEPHONY_GET_IMSI "GetIMSI"
50 #define SIM_SLOT_SINGLE 1
52 #define VCONF_TELEPHONY_DEFAULT_DATA_SERVICE "db/telephony/dualsim/default_data_service"
54 default_connection_s g_default_connection;
55 guint g_default_connection_sub_id = 0;
57 static int __telephony_get_current_sim(void)
59 int sim_slot_count = 0;
62 if (vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT_COUNT, &sim_slot_count) != 0) {
63 STC_LOGD("failed to get sim slot count"); //LCOV_EXCL_LINE
64 return -1; //LCOV_EXCL_LINE
67 if (sim_slot_count == SIM_SLOT_SINGLE) {
68 STC_LOGD("It's single sim model"); //LCOV_EXCL_LINE
69 return current_sim; //LCOV_EXCL_LINE
72 if (vconf_get_int(VCONF_TELEPHONY_DEFAULT_DATA_SERVICE, ¤t_sim) != 0) {
73 STC_LOGD("failed to get default data service = %d\n", //LCOV_EXCL_LINE
75 return -1; //LCOV_EXCL_LINE
81 static void __make_imsi_to_subscriber_id(char *imsi)
85 unsigned char md[SHA256_DIGEST_LENGTH];
88 SHA256_Update(&ctx, imsi, strlen(imsi));
89 SHA256_Final(md, &ctx);
91 for (i = 0; i < SHA256_DIGEST_LENGTH; ++i)
92 snprintf(g_default_connection.subscriber_id + (i * 2), 3, "%02x", md[i]);
95 static void __telephony_get_modem_subscriber_id(GDBusConnection *connection,
96 const char *default_modem_name)
98 GVariant *message = NULL;
99 char tel_path[MAX_PATH_LENGTH];
100 char imsi[IMSI_LENGTH];
101 const char *plmn = NULL;
103 const char *msin = NULL;
106 snprintf(tel_path, sizeof(tel_path), "%s/%s", TELEPHONY_DEFAULT_PATH,
108 message = stc_manager_gdbus_call_sync(connection,
111 TELEPHONY_SIM_INTERFACE,
114 if (message == NULL) {
115 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
116 goto done; //LCOV_EXCL_LINE
119 DEBUG_PARAMS(message);
120 DEBUG_PARAM_TYPE(message);
121 g_variant_get(message, "(&s&s)", &plmn, &msin);
123 plmn_len = strlen(plmn);
125 msin_len = strlen(msin);
127 if (msin_len + plmn_len >= IMSI_LENGTH) {
128 STC_LOGD("Incorrect length of mobile subscriber identifier + net id"); //LCOV_EXCL_LINE
129 goto done; //LCOV_EXCL_LINE
132 snprintf(imsi, IMSI_LENGTH, "%s%s", plmn, msin);
133 __make_imsi_to_subscriber_id(imsi);
136 g_variant_unref(message);
140 static void __telephony_update_default_modem_subscriber_id(GDBusConnection *connection)
142 GVariant *message = NULL;
143 GVariantIter *iter = NULL;
144 gchar *default_modem_name = NULL;
145 gchar *modem_name = NULL;
146 int current_sim = __telephony_get_current_sim();
148 if (current_sim < 0) {
149 STC_LOGI("Sim not found"); //LCOV_EXCL_LINE
150 return; //LCOV_EXCL_LINE
153 message = stc_manager_gdbus_call_sync(connection,
155 TELEPHONY_DEFAULT_PATH,
156 TELEPHONY_SERVICE_MANAGER,
157 TELEPHONY_GET_MODEMS,
159 if (message == NULL) {
160 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
161 return; //LCOV_EXCL_LINE
164 g_variant_get(message, "(as)", &iter);
165 DEBUG_PARAMS(message);
166 DEBUG_PARAM_TYPE(message);
167 while (g_variant_iter_loop(iter, "s", &modem_name)) {
168 if (current_sim == 0) {
169 default_modem_name = g_strdup(modem_name);
173 current_sim--; //LCOV_EXCL_LINE
176 __telephony_get_modem_subscriber_id(connection, default_modem_name);
178 FREE(default_modem_name);
179 g_variant_iter_free(iter);
180 g_variant_unref(message);
184 static void __print_default_connection_info(void)
186 STC_LOGI("============= default connection info ============");
187 STC_LOGI("path [%s]", g_default_connection.path);
188 STC_LOGI("type [%d]", g_default_connection.type);
189 STC_LOGI("ifname [%s]", g_default_connection.ifname);
190 STC_LOGI("roaming [%u]", g_default_connection.roaming ? TRUE : FALSE);
191 if (g_default_connection.type == STC_IFACE_DATACALL)
192 STC_LOGI("sub_id [%s]", g_default_connection.subscriber_id);
193 STC_LOGI("==================================================");
196 static void __print_tether_connection_info(void)
198 STC_LOGI("============= tethering connection info ============");
199 STC_LOGI("mode [%u]", g_default_connection.tether_state ? TRUE : FALSE);
200 STC_LOGI("type [%d]", g_default_connection.tether_iface.type);
201 STC_LOGI("ifname [%s]", g_default_connection.tether_iface.ifname);
202 STC_LOGI("====================================================");
205 static void __reset_default_connection_data(void)
207 FREE(g_default_connection.path);
208 FREE(g_default_connection.ifname);
209 FREE(g_default_connection.tether_iface.ifname);
210 g_default_connection.type = STC_IFACE_UNKNOWN;
211 g_default_connection.roaming = FALSE;
212 g_default_connection.tether_iface.type = STC_IFACE_UNKNOWN;
213 g_default_connection.tether_state = FALSE;
216 static gboolean __is_cellular_internet_profile(const char *profile)
218 const char internet_suffix[] = "_1";
223 if (g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX)
225 char *suffix = strrchr(profile, '_');
226 if (g_strcmp0(suffix, internet_suffix) == 0)
233 static gboolean __is_cellular_profile(const char *profile)
238 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
239 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
242 static gboolean __is_wifi_profile(const char *profile)
247 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
248 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
251 static gboolean __is_ethernet_profile(const char *profile)
256 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
257 CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
260 static gboolean __is_bluetooth_profile(const char *profile)
265 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
266 CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
269 static gboolean __is_connected(GVariantIter *array)
271 gboolean is_connected = FALSE;
272 GVariant *variant = NULL;
275 while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
276 if (g_strcmp0(key, "State") != 0)
279 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
280 const gchar *state = NULL;
282 state = g_variant_get_string(variant, NULL);
283 if (g_strcmp0(state, "ready") == 0 ||
284 g_strcmp0(state, "online") == 0)
289 g_variant_unref(variant);
296 static void __get_default_connection_info(GDBusConnection *connection,
297 const char *object_path)
299 GVariant *message = NULL;
300 GVariantIter *iter = NULL;
301 GVariant *variant = NULL;
304 if (object_path == NULL) {
305 STC_LOGI("Object path is NULL, so information not available.");
309 message = stc_manager_gdbus_call_sync(connection,
312 CONNMAN_SERVICE_INTERFACE,
313 "GetProperties", NULL);
314 if (message == NULL) {
315 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
316 goto done; //LCOV_EXCL_LINE
319 g_variant_get(message, "(a{sv})", &iter);
321 STC_LOGE("Profile %s doesn't exist", object_path); //LCOV_EXCL_LINE
322 goto done; //LCOV_EXCL_LINE
325 while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
326 if (g_strcmp0(key, "Ethernet") == 0) {
327 GVariantIter *iter1 = NULL;
328 GVariant *variant1 = NULL;
331 g_variant_get(variant, "a{sv}", &iter1);
333 continue; //LCOV_EXCL_LINE
335 while (g_variant_iter_loop(iter1, "{sv}", &key1,
337 if (g_strcmp0(key1, "Interface") == 0) {
339 g_variant_get_string(variant1,
341 g_default_connection.ifname =
346 g_variant_iter_free(iter1);
348 } else if (g_strcmp0(key, "Roaming") == 0) {
349 gboolean roaming = 0;
351 if (g_variant_is_of_type(variant,
352 G_VARIANT_TYPE_BOOLEAN)) {
353 roaming = g_variant_get_boolean(variant);
354 g_default_connection.roaming = roaming;
361 g_variant_iter_free(iter);
364 g_variant_unref(message);
369 static stc_error_e __get_default_profile(GDBusConnection *connection)
371 GVariant *message = NULL;
372 GVariantIter *iter = NULL;
376 message = stc_manager_gdbus_call_sync(connection,
378 CONNMAN_MANAGER_PATH,
379 CONNMAN_MANAGER_INTERFACE,
380 "GetServices", NULL);
381 if (message == NULL) {
382 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
383 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
386 g_variant_get(message, "(a(oa{sv}))", &iter);
387 while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
388 if (object_path == NULL)
389 continue; //LCOV_EXCL_LINE
391 if (__is_cellular_profile(object_path) &&
392 !__is_cellular_internet_profile(object_path))
395 if (__is_connected(next) == TRUE) {
396 /* reset old default connection data */
397 FREE(g_default_connection.path);
398 FREE(g_default_connection.ifname);
399 g_default_connection.type = STC_IFACE_UNKNOWN;
400 g_default_connection.roaming = FALSE;
402 g_default_connection.path = g_strdup(object_path);
404 g_variant_iter_free(next);
409 g_variant_iter_free(iter);
410 g_variant_unref(message);
412 if (__is_cellular_profile(g_default_connection.path)) {
413 g_default_connection.type = STC_IFACE_DATACALL; //LCOV_EXCL_LINE
414 __telephony_update_default_modem_subscriber_id(connection); //LCOV_EXCL_LINE
415 } else if (__is_wifi_profile(g_default_connection.path)) {
416 g_default_connection.type = STC_IFACE_WIFI; //LCOV_EXCL_LINE
417 } else if (__is_ethernet_profile(g_default_connection.path)) {
418 g_default_connection.type = STC_IFACE_WIRED; //LCOV_EXCL_LINE
419 } else if (__is_bluetooth_profile(g_default_connection.path)) {
420 g_default_connection.type = STC_IFACE_BLUETOOTH; //LCOV_EXCL_LINE
422 g_default_connection.type = STC_IFACE_UNKNOWN; //LCOV_EXCL_LINE
425 __get_default_connection_info(connection, g_default_connection.path);
427 __print_default_connection_info();
429 stc_monitor_update_rstn_by_default_connection(&g_default_connection);
430 stc_firewall_update();
432 return STC_ERROR_NONE;
435 static void _service_signal_cb(GDBusConnection *conn,
436 const gchar *name, const gchar *path,
437 const gchar *interface, const gchar *sig,
438 GVariant *param, gpointer user_data)
440 gchar *sigvalue = NULL;
441 GVariant *variant = NULL;
442 stc_s *stc = (stc_s *)stc_get_manager();
443 ret_msg_if(stc == NULL, "failed to get stc data");
445 if (path == NULL || param == NULL)
448 g_variant_get(param, "(sv)", &sigvalue, &variant);
449 if (sigvalue == NULL)
452 if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
455 if (g_strcmp0(sigvalue, "State") == 0 &&
456 g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
457 const gchar *state = NULL;
459 state = g_variant_get_string(variant, NULL);
460 if (g_strcmp0(state, "ready") == 0 ||
461 g_strcmp0(state, "online") == 0) {
462 if (g_strcmp0(g_default_connection.path, path)) {
463 __reset_default_connection_data();
464 __get_default_profile(stc->connection);
467 if (g_strcmp0(g_default_connection.path, path) == 0) {
468 __reset_default_connection_data(); //LCOV_EXCL_LINE
469 __get_default_profile(stc->connection); //LCOV_EXCL_LINE
472 } else if (g_strcmp0(sigvalue, "Roaming") == 0) {
474 if (g_strcmp0(g_default_connection.path, path) == 0) {
475 gboolean roaming = 0;
477 if (g_variant_is_of_type(variant,
478 G_VARIANT_TYPE_BOOLEAN)) {
479 roaming = g_variant_get_boolean(variant);
480 g_default_connection.roaming = roaming;
492 g_variant_unref(variant);
497 static void __vconf_key_callback(keynode_t *node, void *user_data)
502 STC_LOGE("Invalid parameter");
506 if (vconf_keynode_get_type(node) != VCONF_TYPE_INT) {
507 STC_LOGE("Invalid vconf key type");
511 vconf_key = vconf_keynode_get_int(node);
513 /* Check the tethering type */
515 case VCONFKEY_MOBILE_HOTSPOT_MODE_USB:
516 STC_LOGI("Hotspot mode USB type !");
517 g_default_connection.tether_state = TRUE;
518 g_default_connection.tether_iface.ifname = g_strdup(TETHERING_USB_IF);
519 g_default_connection.tether_iface.type = STC_IFACE_USB;
521 case VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI:
522 STC_LOGI("Hotspot mode Wi-Fi type !");
523 g_default_connection.tether_state = TRUE;
524 g_default_connection.tether_iface.ifname = g_strdup(TETHERING_WIFI_IF);
525 g_default_connection.tether_iface.type = STC_IFACE_WIFI;
527 case VCONFKEY_MOBILE_HOTSPOT_MODE_BT:
528 STC_LOGI("Hotspot mode Bluetooth type !");
529 g_default_connection.tether_state = TRUE;
530 g_default_connection.tether_iface.ifname = g_strdup(TETHERING_BT_IF);
531 g_default_connection.tether_iface.type = STC_IFACE_BLUETOOTH;
533 case VCONFKEY_MOBILE_HOTSPOT_MODE_P2P:
534 STC_LOGI("Hotspot mode P2P type !");
535 g_default_connection.tether_state = TRUE;
536 g_default_connection.tether_iface.ifname = g_strdup(TETHERING_P2P_IF);
537 g_default_connection.tether_iface.type = STC_IFACE_P2P;
539 case VCONFKEY_MOBILE_HOTSPOT_MODE_NONE:
540 STC_LOGI("Hotspot mode none");
541 g_default_connection.tether_state = FALSE;
544 STC_LOGE("Unknown Hotspot mode type !");
548 /* add monitoring for tethering if active found */
549 if (g_default_connection.tether_state == TRUE && g_default_connection.tether_iface.ifname) {
550 __print_tether_connection_info();
551 stc_monitor_update_rstn_by_default_connection(&g_default_connection);
552 stc_firewall_update();
553 STC_LOGI("Data monitoring started for tethering iface !");
557 /* remove monitoring for tethering if in-active found */
558 if (g_default_connection.tether_state == FALSE && g_default_connection.tether_iface.ifname) {
559 stc_monitor_update_rstn_by_default_connection(&g_default_connection);
560 g_free(g_default_connection.tether_iface.ifname);
561 g_default_connection.tether_iface.ifname = NULL;
562 g_default_connection.tether_iface.type = STC_IFACE_UNKNOWN;
563 STC_LOGI("Data monitoring stopped for tethering iface !");
568 stc_error_e stc_default_connection_monitor_init(stc_s *stc)
571 ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
573 __get_default_profile(stc->connection);
574 g_default_connection_sub_id =
575 stc_manager_gdbus_subscribe_signal(stc->connection,
577 CONNMAN_SERVICE_INTERFACE,
578 CONNMAN_SIGNAL_PROPERTY_CHANGED,
580 G_DBUS_SIGNAL_FLAGS_NONE,
584 ret = vconf_notify_key_changed(VCONFKEY_MOBILE_HOTSPOT_MODE, __vconf_key_callback, NULL);
586 STC_LOGE("vconf_notify_key_changed failed: %d", ret);
588 STC_LOGI("Successfully subscribed connman [%s] signal", CONNMAN_SIGNAL_PROPERTY_CHANGED);
589 return STC_ERROR_NONE;
592 stc_error_e stc_default_connection_monitor_deinit(stc_s *stc)
594 ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
596 stc_manager_gdbus_unsubscribe_signal(stc->connection,
597 g_default_connection_sub_id);
598 FREE(g_default_connection.path);
599 FREE(g_default_connection.ifname);
600 return STC_ERROR_NONE;
603 gchar *stc_default_connection_get_ifname(void)
605 return g_strdup(g_default_connection.ifname);
608 default_connection_s *stc_get_default_connection(void)
610 return &g_default_connection;