Implement API to get IPv6 addresses
[platform/core/api/connection.git] / src / connection.c
1 /*
2  * Copyright (c) 2011-2013 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <glib.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <vconf/vconf.h>
22 #include <system_info.h>
23
24 #include "net_connection_private.h"
25
26 static __thread GSList *conn_handle_list = NULL;
27 static int tv_profile = -1; // Unknown
28
29 //LCOV_EXCL_START
30 static int __connection_convert_net_state(int status)
31 {
32         switch (status) {
33         case VCONFKEY_NETWORK_CELLULAR:
34                 return CONNECTION_TYPE_CELLULAR;
35         case VCONFKEY_NETWORK_WIFI:
36                 return CONNECTION_TYPE_WIFI;
37         case VCONFKEY_NETWORK_ETHERNET:
38                 return CONNECTION_TYPE_ETHERNET;
39         case VCONFKEY_NETWORK_BLUETOOTH:
40                 return CONNECTION_TYPE_BT;
41         case VCONFKEY_NETWORK_DEFAULT_PROXY:
42                 return CONNECTION_TYPE_NET_PROXY;
43         default:
44                 return CONNECTION_TYPE_DISCONNECTED;
45         }
46 }
47
48 static int __connection_convert_cellular_state(int status)
49 {
50         switch (status) {
51         case VCONFKEY_NETWORK_CELLULAR_ON:
52                 return CONNECTION_CELLULAR_STATE_AVAILABLE;
53         case VCONFKEY_NETWORK_CELLULAR_3G_OPTION_OFF:
54                 return CONNECTION_CELLULAR_STATE_CALL_ONLY_AVAILABLE;
55         case VCONFKEY_NETWORK_CELLULAR_ROAMING_OFF:
56                 return CONNECTION_CELLULAR_STATE_ROAMING_OFF;
57         case VCONFKEY_NETWORK_CELLULAR_FLIGHT_MODE:
58                 return CONNECTION_CELLULAR_STATE_FLIGHT_MODE;
59         default:
60                 return CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE;
61         }
62 }
63
64 static bool __connection_check_handle_validity(connection_h connection)
65 {
66         bool ret = false;
67
68         if (connection == NULL)
69                 return false;
70
71         if (g_slist_find(conn_handle_list, connection) != NULL)
72                 ret = true;
73
74         return ret;
75 }
76
77 static connection_type_changed_cb
78 __connection_get_type_changed_callback(connection_handle_s *local_handle)
79 {
80         return local_handle->type_changed_callback;
81 }
82
83 static void *__connection_get_type_changed_userdata(
84                                                         connection_handle_s *local_handle)
85 {
86         return local_handle->type_changed_user_data;
87 }
88
89 static gboolean __connection_cb_type_changed_cb_idle(gpointer user_data)
90 {
91         int state, status;
92         void *data;
93         connection_type_changed_cb callback;
94         connection_handle_s *local_handle = (connection_handle_s *)user_data;
95
96         if (__connection_check_handle_validity((connection_h)local_handle) != true)
97                 return FALSE;
98
99         if (vconf_get_int(VCONFKEY_NETWORK_STATUS, &status) != 0)
100                 return FALSE;
101
102         state = __connection_convert_net_state(status);
103
104         callback = __connection_get_type_changed_callback(local_handle);
105         data = __connection_get_type_changed_userdata(local_handle);
106         if (callback)
107                 callback(state, data);
108
109         return FALSE;
110 }
111
112 static void __connection_cb_type_change_cb(keynode_t *node, void *user_data)
113 {
114         GSList *list;
115         connection_h handle;
116
117         if (_connection_is_created() != true) {
118                 CONNECTION_LOG(CONNECTION_ERROR, "Application is not registered"
119                                 "If multi-threaded, thread integrity be broken.");
120                 return;
121         }
122
123         for (list = conn_handle_list; list; list = list->next) {
124                 handle = (connection_h)list->data;
125                 _connection_callback_add(__connection_cb_type_changed_cb_idle, (gpointer)handle);
126         }
127 }
128
129 static void __connection_cb_ethernet_cable_state_changed_cb(connection_ethernet_cable_state_e state)
130 {
131         CONNECTION_LOG(CONNECTION_INFO, "Ethernet Cable state Indication");
132
133         GSList *list;
134
135         for (list = conn_handle_list; list; list = list->next) {
136                 connection_handle_s *local_handle = (connection_handle_s *)list->data;
137                 if (local_handle->ethernet_cable_state_changed_callback)
138                         local_handle->ethernet_cable_state_changed_callback(state,
139                                         local_handle->ethernet_cable_state_changed_user_data);
140         }
141 }
142
143 static int __connection_get_ethernet_cable_state_changed_callback_count(void)
144 {
145         GSList *list;
146         int count = 0;
147
148         for (list = conn_handle_list; list; list = list->next) {
149                 connection_handle_s *local_handle = (connection_handle_s *)list->data;
150                 if (local_handle->ethernet_cable_state_changed_callback) count++;
151         }
152
153         return count;
154 }
155
156 static int __connection_set_type_changed_callback(connection_h connection,
157                                                         void *callback, void *user_data)
158 {
159         static __thread gint refcount = 0;
160         connection_handle_s *local_handle;
161
162         local_handle = (connection_handle_s *)connection;
163
164         if (callback) {
165                 if (refcount == 0)
166                         vconf_notify_key_changed(VCONFKEY_NETWORK_STATUS,
167                                         __connection_cb_type_change_cb, NULL);
168
169                 refcount++;
170                 CONNECTION_LOG(CONNECTION_INFO, "Successfully registered(%d)", refcount);
171         } else {
172                 if (refcount > 0 &&
173                                 __connection_get_type_changed_callback(local_handle) != NULL) {
174                         if (--refcount == 0) {
175                                 if (vconf_ignore_key_changed(VCONFKEY_NETWORK_STATUS,
176                                                 __connection_cb_type_change_cb) < 0) {
177                                         CONNECTION_LOG(CONNECTION_ERROR, //LCOV_EXCL_LINE
178                                                         "Error to de-register vconf callback(%d)", refcount);
179                                 } else {
180                                         CONNECTION_LOG(CONNECTION_INFO,
181                                                         "Successfully de-registered(%d)", refcount);
182                                 }
183                         }
184                 }
185         }
186
187         local_handle->type_changed_user_data = user_data;
188         local_handle->type_changed_callback = callback;
189
190         return CONNECTION_ERROR_NONE;
191 }
192
193 static connection_address_changed_cb
194 __connection_get_ip_changed_callback(connection_handle_s *local_handle)
195 {
196         return local_handle->ip_changed_callback;
197 }
198
199 static void *__connection_get_ip_changed_userdata(
200                                                         connection_handle_s *local_handle)
201 {
202         return local_handle->ip_changed_user_data;
203 }
204
205 static gboolean __connection_cb_ip_changed_cb_idle(gpointer user_data)
206 {
207         char *ip_addr;
208         void *data;
209         connection_address_changed_cb callback;
210         connection_handle_s *local_handle = (connection_handle_s *)user_data;
211
212         if (__connection_check_handle_validity((connection_h)local_handle) != true)
213                 return FALSE;
214
215         ip_addr = vconf_get_str(VCONFKEY_NETWORK_IP);
216         if (ip_addr == NULL)
217                 CONNECTION_LOG(CONNECTION_ERROR, //LCOV_EXCL_LINE
218                         "vconf_get_str(VCONFKEY_NETWORK_IP) is Failed");
219
220         callback = __connection_get_ip_changed_callback(local_handle);
221         data = __connection_get_ip_changed_userdata(local_handle);
222         /* TODO: IPv6 should be supported */
223         if (callback)
224                 callback(ip_addr, NULL, data);
225
226         free(ip_addr);
227
228         return FALSE;
229 }
230
231 static void __connection_cb_ip_change_cb(keynode_t *node, void *user_data)
232 {
233         GSList *list;
234         connection_h handle;
235
236         if (_connection_is_created() != true) {
237                 CONNECTION_LOG(CONNECTION_ERROR, "Application is not registered"
238                                 "If multi-threaded, thread integrity be broken.");
239                 return;
240         }
241
242         for (list = conn_handle_list; list; list = list->next) {
243                 handle = (connection_h)list->data;
244                 _connection_callback_add(__connection_cb_ip_changed_cb_idle, (gpointer)handle);
245         }
246 }
247
248 static int __connection_set_ip_changed_callback(connection_h connection,
249                                                         void *callback, void *user_data)
250 {
251         static __thread gint refcount = 0;
252         connection_handle_s *local_handle;
253
254         local_handle = (connection_handle_s *)connection;
255
256         if (callback) {
257                 if (refcount == 0)
258                         vconf_notify_key_changed(VCONFKEY_NETWORK_IP,
259                                         __connection_cb_ip_change_cb, NULL);
260
261                 refcount++;
262                 CONNECTION_LOG(CONNECTION_INFO, "Successfully registered(%d)", refcount);
263         } else {
264                 if (refcount > 0 &&
265                                 __connection_get_ip_changed_callback(local_handle) != NULL) {
266                         if (--refcount == 0) {
267                                 if (vconf_ignore_key_changed(VCONFKEY_NETWORK_IP,
268                                                 __connection_cb_ip_change_cb) < 0) {
269                                         CONNECTION_LOG(CONNECTION_ERROR, //LCOV_EXCL_LINE
270                                                         "Error to de-register vconf callback(%d)", refcount);
271                                 } else {
272                                         CONNECTION_LOG(CONNECTION_INFO,
273                                                         "Successfully de-registered(%d)", refcount);
274                                 }
275                         }
276                 }
277         }
278
279         local_handle->ip_changed_user_data = user_data;
280         local_handle->ip_changed_callback = callback;
281
282         return CONNECTION_ERROR_NONE;
283 }
284
285 static connection_address_changed_cb
286 __connection_get_proxy_changed_callback(connection_handle_s *local_handle)
287 {
288         return local_handle->proxy_changed_callback;
289 }
290
291 static void *__connection_get_proxy_changed_userdata(
292                                                         connection_handle_s *local_handle)
293 {
294         return local_handle->proxy_changed_user_data;
295 }
296
297 static gboolean __connection_cb_proxy_changed_cb_idle(gpointer user_data)
298 {
299         char *proxy;
300         void *data;
301         connection_address_changed_cb callback;
302         connection_handle_s *local_handle = (connection_handle_s *)user_data;
303
304         if (__connection_check_handle_validity((connection_h)local_handle) != true)
305                 return FALSE;
306
307         proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY);
308         if (proxy == NULL)
309                 CONNECTION_LOG(CONNECTION_ERROR, //LCOV_EXCL_LINE
310                         "vconf_get_str(VCONFKEY_NETWORK_PROXY) is Failed");
311
312         callback = __connection_get_proxy_changed_callback(local_handle);
313         data = __connection_get_proxy_changed_userdata(local_handle);
314         /* TODO: IPv6 should be supported */
315         if (callback)
316                 callback(proxy, NULL, data);
317
318         free(proxy);
319
320         return FALSE;
321 }
322
323 static void __connection_cb_proxy_change_cb(keynode_t *node, void *user_data)
324 {
325         GSList *list;
326         connection_h handle;
327
328         if (_connection_is_created() != true) {
329                 CONNECTION_LOG(CONNECTION_ERROR, "Application is not registered"
330                                 "If multi-threaded, thread integrity be broken.");
331                 return;
332         }
333
334         for (list = conn_handle_list; list; list = list->next) {
335                 handle = (connection_h)list->data;
336                 _connection_callback_add(__connection_cb_proxy_changed_cb_idle, (gpointer)handle);
337         }
338 }
339
340 static int __connection_set_proxy_changed_callback(connection_h connection,
341                                                         void *callback, void *user_data)
342 {
343         static __thread gint refcount = 0;
344         connection_handle_s *local_handle;
345
346         local_handle = (connection_handle_s *)connection;
347
348         if (callback) {
349                 if (refcount == 0)
350                         vconf_notify_key_changed(VCONFKEY_NETWORK_PROXY,
351                                         __connection_cb_proxy_change_cb, NULL);
352
353                 refcount++;
354                 CONNECTION_LOG(CONNECTION_INFO, "Successfully registered(%d)", refcount);
355         } else {
356                 if (refcount > 0 &&
357                                 __connection_get_proxy_changed_callback(local_handle) != NULL) {
358                         if (--refcount == 0) {
359                                 if (vconf_ignore_key_changed(VCONFKEY_NETWORK_PROXY,
360                                                 __connection_cb_proxy_change_cb) < 0) {
361                                         CONNECTION_LOG(CONNECTION_ERROR, //LCOV_EXCL_LINE
362                                                         "Error to de-register vconf callback(%d)", refcount);
363                                 } else {
364                                         CONNECTION_LOG(CONNECTION_INFO,
365                                                         "Successfully de-registered(%d)", refcount);
366                                 }
367                         }
368                 }
369         }
370
371         local_handle->proxy_changed_user_data = user_data;
372         local_handle->proxy_changed_callback = callback;
373
374         return CONNECTION_ERROR_NONE;
375 }
376
377 static int __connection_set_ethernet_cable_state_changed_cb(connection_h connection,
378                 connection_ethernet_cable_state_chaged_cb callback, void *user_data)
379 {
380         connection_handle_s *local_handle = (connection_handle_s *)connection;
381
382         if (callback) {
383                 if (__connection_get_ethernet_cable_state_changed_callback_count() == 0)
384                         _connection_libnet_set_ethernet_cable_state_changed_cb(
385                                         __connection_cb_ethernet_cable_state_changed_cb);
386
387         } else {
388                 if (__connection_get_ethernet_cable_state_changed_callback_count() == 1 &&
389                                   local_handle->ethernet_cable_state_changed_callback)
390                         _connection_libnet_set_ethernet_cable_state_changed_cb(NULL);
391         }
392
393         local_handle->ethernet_cable_state_changed_callback = callback;
394         local_handle->ethernet_cable_state_changed_user_data = user_data;
395         return CONNECTION_ERROR_NONE;
396 }
397 //LCOV_EXCL_STOP
398
399 static int __connection_get_handle_count(void)
400 {
401         return ((int)g_slist_length(conn_handle_list));
402 }
403
404 /* Connection Manager ********************************************************/
405 EXPORT_API int connection_create(connection_h *connection)
406 {
407         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
408
409         if (connection == NULL || __connection_check_handle_validity(*connection)) {
410                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
411                 return CONNECTION_ERROR_INVALID_PARAMETER;
412         }
413
414         int rv = _connection_libnet_init();
415         if (rv == NET_ERR_ACCESS_DENIED) {
416                 CONNECTION_LOG(CONNECTION_ERROR, "Access denied"); //LCOV_EXCL_LINE
417                 return CONNECTION_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
418         } else if (rv != NET_ERR_NONE) {
419                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to create connection[%d]", rv); //LCOV_EXCL_LINE
420                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
421         }
422
423         *connection = g_try_malloc0(sizeof(connection_handle_s));
424         if (*connection != NULL)
425                 CONNECTION_LOG(CONNECTION_INFO, "New handle created[%p]", *connection);
426         else
427                 return CONNECTION_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
428
429         conn_handle_list = g_slist_prepend(conn_handle_list, *connection);
430
431         return CONNECTION_ERROR_NONE;
432 }
433
434 EXPORT_API int connection_destroy(connection_h connection)
435 {
436         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
437
438         if (!(__connection_check_handle_validity(connection))) {
439                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
440                 return CONNECTION_ERROR_INVALID_PARAMETER;
441         }
442
443         CONNECTION_LOG(CONNECTION_INFO, "Destroy handle: %p", connection);
444
445         __connection_set_type_changed_callback(connection, NULL, NULL);
446         __connection_set_ip_changed_callback(connection, NULL, NULL);
447         __connection_set_proxy_changed_callback(connection, NULL, NULL);
448         __connection_set_ethernet_cable_state_changed_cb(connection, NULL, NULL);
449
450         conn_handle_list = g_slist_remove(conn_handle_list, connection);
451
452         g_free(connection);
453         connection = NULL;
454
455         if (__connection_get_handle_count() == 0) {
456                 _connection_libnet_deinit();
457                 _connection_callback_cleanup();
458         }
459
460         return CONNECTION_ERROR_NONE;
461 }
462
463 EXPORT_API int connection_get_type(connection_h connection, connection_type_e* type)
464 {
465         int rv = 0;
466         int status = 0;
467
468         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
469
470         if (type == NULL || !(__connection_check_handle_validity(connection))) {
471                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
472                 return CONNECTION_ERROR_INVALID_PARAMETER;
473         }
474
475         rv = vconf_get_int(VCONFKEY_NETWORK_STATUS, &status);
476         if (rv != VCONF_OK) {
477                 CONNECTION_LOG(CONNECTION_ERROR, "vconf_get_int Failed = %d", status); //LCOV_EXCL_LINE
478                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
479         }
480
481         CONNECTION_LOG(CONNECTION_INFO, "Connected Network = %d", status);
482
483         *type = __connection_convert_net_state(status);
484
485         return CONNECTION_ERROR_NONE;
486 }
487
488 EXPORT_API int connection_get_ip_address(connection_h connection,
489                                 connection_address_family_e address_family, char** ip_address)
490 {
491         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
492
493         if (ip_address == NULL || !(__connection_check_handle_validity(connection))) {
494                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
495                 return CONNECTION_ERROR_INVALID_PARAMETER;
496         }
497
498         switch (address_family) {
499         case CONNECTION_ADDRESS_FAMILY_IPV4:
500                 *ip_address = vconf_get_str(VCONFKEY_NETWORK_IP);
501                 break;
502         case CONNECTION_ADDRESS_FAMILY_IPV6:
503                 *ip_address = vconf_get_str(VCONFKEY_NETWORK_IP6);
504                 break;
505         default:
506                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
507                 return CONNECTION_ERROR_INVALID_PARAMETER;
508         }
509
510         if (*ip_address == NULL) {
511                 CONNECTION_LOG(CONNECTION_ERROR, "vconf_get_str Failed"); //LCOV_EXCL_LINE
512                 return CONNECTION_ERROR_OPERATION_FAILED;//LCOV_EXCL_LINE
513         }
514
515         return CONNECTION_ERROR_NONE;
516 }
517
518 EXPORT_API int connection_get_proxy(connection_h connection,
519                                 connection_address_family_e address_family, char** proxy)
520 {
521         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
522
523         if (proxy == NULL || !(__connection_check_handle_validity(connection))) {
524                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
525                 return CONNECTION_ERROR_INVALID_PARAMETER;
526         }
527
528         switch (address_family) {
529         case CONNECTION_ADDRESS_FAMILY_IPV4:
530         case CONNECTION_ADDRESS_FAMILY_IPV6:
531                 *proxy = vconf_get_str(VCONFKEY_NETWORK_PROXY);
532                 break;
533         default:
534                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
535                 return CONNECTION_ERROR_INVALID_PARAMETER;
536         }
537
538         if (*proxy == NULL) {
539                 CONNECTION_LOG(CONNECTION_ERROR, "vconf_get_str Failed"); //LCOV_EXCL_LINE
540                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
541         }
542
543         return CONNECTION_ERROR_NONE;
544 }
545
546 EXPORT_API int connection_get_mac_address(connection_h connection, connection_type_e type, char** mac_addr)
547 {
548         FILE *fp;
549         char buf[CONNECTION_MAC_INFO_LENGTH + 1];
550
551         CHECK_FEATURE_SUPPORTED(WIFI_FEATURE, ETHERNET_FEATURE);
552
553         if (type == CONNECTION_TYPE_WIFI)
554                 CHECK_FEATURE_SUPPORTED(WIFI_FEATURE);
555         else if (type == CONNECTION_TYPE_ETHERNET) //LCOV_EXCL_LINE
556                 CHECK_FEATURE_SUPPORTED(ETHERNET_FEATURE); //LCOV_EXCL_LINE
557
558         if (mac_addr == NULL || !(__connection_check_handle_validity(connection))) {
559                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
560                 return CONNECTION_ERROR_INVALID_PARAMETER;
561         }
562
563         switch (type) {
564         case CONNECTION_TYPE_WIFI:
565                 if (__builtin_expect(tv_profile == -1, 0)) {
566                         char *profileName;
567                         system_info_get_platform_string("http://tizen.org/feature/profile", &profileName);
568                         if (*profileName == 't' || *profileName == 'T')
569                                 tv_profile = 1;
570                         else
571                                 tv_profile = 0;
572                         free(profileName);
573                 }
574                 if (tv_profile == 1) {
575                         fp = fopen(WIFI_MAC_INFO_FILE, "r");
576                         if (fp == NULL) {
577                                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to open file %s", WIFI_MAC_INFO_FILE); //LCOV_EXCL_LINE
578                                 return CONNECTION_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
579                         }
580
581                         if (fgets(buf, sizeof(buf), fp) == NULL) {
582                                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get MAC info from %s", WIFI_MAC_INFO_FILE); //LCOV_EXCL_LINE
583                                 fclose(fp); //LCOV_EXCL_LINE
584                                 return CONNECTION_ERROR_OPERATION_FAILED;
585                         }
586
587                         CONNECTION_LOG(CONNECTION_INFO, "%s : %s", WIFI_MAC_INFO_FILE, buf);
588
589                         *mac_addr = (char *)malloc(CONNECTION_MAC_INFO_LENGTH + 1);
590                         if (*mac_addr == NULL) {
591                                 CONNECTION_LOG(CONNECTION_ERROR, "malloc() failed"); //LCOV_EXCL_LINE
592                                 fclose(fp); //LCOV_EXCL_LINE
593                                 return CONNECTION_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
594                         }
595                         g_strlcpy(*mac_addr, buf, CONNECTION_MAC_INFO_LENGTH + 1);
596                         fclose(fp);
597                 } else {
598                         *mac_addr = vconf_get_str(VCONFKEY_WIFI_BSSID_ADDRESS);
599
600                         if (*mac_addr == NULL) {
601                                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get vconf from %s", VCONFKEY_WIFI_BSSID_ADDRESS); //LCOV_EXCL_LINE
602                                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
603                         }
604                 }
605                 break;
606         //LCOV_EXCL_START
607         case CONNECTION_TYPE_ETHERNET:
608                 fp = fopen(ETHERNET_MAC_INFO_FILE, "r");
609                 if (fp == NULL) {
610                         CONNECTION_LOG(CONNECTION_ERROR, "Failed to open file %s", ETHERNET_MAC_INFO_FILE);
611                         return CONNECTION_ERROR_OUT_OF_MEMORY;
612                 }
613
614                 if (fgets(buf, sizeof(buf), fp) == NULL) {
615                         CONNECTION_LOG(CONNECTION_ERROR, "Failed to get MAC info from %s", ETHERNET_MAC_INFO_FILE);
616                         fclose(fp);
617                         return CONNECTION_ERROR_OPERATION_FAILED;
618                 }
619
620                 CONNECTION_LOG(CONNECTION_INFO, "%s : %s", ETHERNET_MAC_INFO_FILE, buf);
621
622                 *mac_addr = (char *)malloc(CONNECTION_MAC_INFO_LENGTH + 1);
623                 if (*mac_addr == NULL) {
624                         CONNECTION_LOG(CONNECTION_ERROR, "malloc() failed");
625                         fclose(fp);
626                         return CONNECTION_ERROR_OUT_OF_MEMORY;
627                 }
628
629                 g_strlcpy(*mac_addr, buf, CONNECTION_MAC_INFO_LENGTH + 1);
630                 fclose(fp);
631
632                 break;
633         //LCOV_EXCL_STOP
634         default:
635                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE
636                 return CONNECTION_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
637         }
638
639         /* Checking Invalid MAC Address */
640         if ((strcmp(*mac_addr, "00:00:00:00:00:00") == 0) ||
641                         (strcmp(*mac_addr, "ff:ff:ff:ff:ff:ff") == 0)) {
642                 CONNECTION_LOG(CONNECTION_ERROR, "MAC Address(%s) is invalid", *mac_addr); //LCOV_EXCL_LINE
643                 return CONNECTION_ERROR_INVALID_OPERATION; //LCOV_EXCL_LINE
644         }
645
646         CONNECTION_LOG(CONNECTION_INFO, "MAC Address %s", *mac_addr);
647
648         return CONNECTION_ERROR_NONE;
649 }
650
651
652 EXPORT_API int connection_get_cellular_state(connection_h connection, connection_cellular_state_e* state)
653 {
654         int rv = 0;
655         int status = 0;
656         int cellular_state = 0;
657 #if defined TIZEN_DUALSIM_ENABLE
658         int sim_id = 0;
659 #endif
660
661         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
662
663         if (state == NULL || !(__connection_check_handle_validity(connection))) {
664                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
665                 return CONNECTION_ERROR_INVALID_PARAMETER;
666         }
667
668         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &status);
669         if (rv != VCONF_OK) {
670                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get cellular state"); //LCOV_EXCL_LINE
671                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
672         }
673
674         CONNECTION_LOG(CONNECTION_INFO, "Cellular: %d", status);
675         *state = __connection_convert_cellular_state(status);
676
677         if (*state == CONNECTION_CELLULAR_STATE_AVAILABLE) {
678 #if defined TIZEN_DUALSIM_ENABLE
679                 rv = vconf_get_int(VCONF_TELEPHONY_DEFAULT_DATA_SERVICE, &sim_id);
680                 if (rv != VCONF_OK) {
681                         CONNECTION_LOG(CONNECTION_ERROR,
682                                         "Failed to get default subscriber id", sim_id);
683                         return CONNECTION_ERROR_OPERATION_FAILED;
684                 }
685
686                 switch (sim_id) {
687                 case CONNECTION_CELLULAR_SUBSCRIBER_1:
688 #endif
689                         rv = vconf_get_int(VCONFKEY_DNET_STATE, &cellular_state);
690 #if defined TIZEN_DUALSIM_ENABLE
691                         break;
692
693                 case CONNECTION_CELLULAR_SUBSCRIBER_2:
694                         rv = vconf_get_int(VCONFKEY_DNET_STATE2, &cellular_state);
695                         break;
696
697                 default:
698                         CONNECTION_LOG(CONNECTION_ERROR, "Invalid subscriber id:%d", sim_id);
699                         return CONNECTION_ERROR_OPERATION_FAILED;
700                 }
701 #endif
702                 if (rv != VCONF_OK) {
703                         CONNECTION_LOG(CONNECTION_ERROR, "Failed to get cellular state"); //LCOV_EXCL_LINE
704                         return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
705                 }
706         }
707
708         CONNECTION_LOG(CONNECTION_INFO, "Cellular state: %d", cellular_state);
709
710         if (cellular_state == VCONFKEY_DNET_NORMAL_CONNECTED ||
711                         cellular_state == VCONFKEY_DNET_SECURE_CONNECTED ||
712                         cellular_state == VCONFKEY_DNET_TRANSFER)
713                 *state = CONNECTION_CELLULAR_STATE_CONNECTED;
714
715         return CONNECTION_ERROR_NONE;
716 }
717
718 EXPORT_API int connection_get_wifi_state(connection_h connection, connection_wifi_state_e* state)
719 {
720         CHECK_FEATURE_SUPPORTED(WIFI_FEATURE);
721
722         if (state == NULL || !(__connection_check_handle_validity(connection))) {
723                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
724                 return CONNECTION_ERROR_INVALID_PARAMETER;
725         }
726
727         int rv = _connection_libnet_get_wifi_state(state);
728         if (rv != CONNECTION_ERROR_NONE) {
729                 CONNECTION_LOG(CONNECTION_ERROR, "Fail to get Wi-Fi state[%d]", rv); //LCOV_EXCL_LINE
730                 return rv; //LCOV_EXCL_LINE
731         }
732
733         CONNECTION_LOG(CONNECTION_INFO, "Wi-Fi state: %d", *state);
734
735         return CONNECTION_ERROR_NONE;
736 }
737
738 //LCOV_EXCL_START
739 EXPORT_API int connection_get_ethernet_state(connection_h connection, connection_ethernet_state_e *state)
740 {
741         CHECK_FEATURE_SUPPORTED(ETHERNET_FEATURE);
742
743         if (state == NULL || !(__connection_check_handle_validity(connection))) {
744                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
745                 return CONNECTION_ERROR_INVALID_PARAMETER;
746         }
747
748         return _connection_libnet_get_ethernet_state(state);
749 }
750
751 EXPORT_API int connection_get_ethernet_cable_state(connection_h connection, connection_ethernet_cable_state_e *state)
752 {
753         CHECK_FEATURE_SUPPORTED(ETHERNET_FEATURE);
754
755         if (state == NULL || !(__connection_check_handle_validity(connection))) {
756                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
757                 return CONNECTION_ERROR_INVALID_PARAMETER;
758         }
759
760         return _connection_libnet_get_ethernet_cable_state(state);
761 }
762
763 EXPORT_API int connection_set_ethernet_cable_state_chaged_cb(connection_h connection,
764                           connection_ethernet_cable_state_chaged_cb callback, void *user_data)
765 {
766         CHECK_FEATURE_SUPPORTED(ETHERNET_FEATURE);
767
768         if (callback == NULL || !(__connection_check_handle_validity(connection))) {
769                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
770                 return CONNECTION_ERROR_INVALID_PARAMETER;
771         }
772
773         return __connection_set_ethernet_cable_state_changed_cb(connection,
774                                                         callback, user_data);
775 }
776
777 EXPORT_API int connection_unset_ethernet_cable_state_chaged_cb(connection_h connection)
778 {
779         CHECK_FEATURE_SUPPORTED(ETHERNET_FEATURE);
780
781         if (!(__connection_check_handle_validity(connection))) {
782                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
783                 return CONNECTION_ERROR_INVALID_PARAMETER;
784         }
785
786         return __connection_set_ethernet_cable_state_changed_cb(connection,
787                                                         NULL, NULL);
788 }
789 //LCOV_EXCL_STOP
790
791 EXPORT_API int connection_get_bt_state(connection_h connection, connection_bt_state_e *state)
792 {
793         CHECK_FEATURE_SUPPORTED(TETHERING_BLUETOOTH_FEATURE);
794
795         if (state == NULL || !(__connection_check_handle_validity(connection))) {
796                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
797                 return CONNECTION_ERROR_INVALID_PARAMETER;
798         }
799
800         return _connection_libnet_get_bluetooth_state(state);
801 }
802
803 EXPORT_API int connection_set_type_changed_cb(connection_h connection,
804                                         connection_type_changed_cb callback, void* user_data)
805 {
806         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
807
808         if (callback == NULL || !(__connection_check_handle_validity(connection))) {
809                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
810                 return CONNECTION_ERROR_INVALID_PARAMETER;
811         }
812
813         return __connection_set_type_changed_callback(connection, callback, user_data);
814 }
815
816 EXPORT_API int connection_unset_type_changed_cb(connection_h connection)
817 {
818         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
819
820         if (!(__connection_check_handle_validity(connection))) {
821                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
822                 return CONNECTION_ERROR_INVALID_PARAMETER;
823         }
824
825         return __connection_set_type_changed_callback(connection, NULL, NULL);
826 }
827
828 EXPORT_API int connection_set_ip_address_changed_cb(connection_h connection,
829                                 connection_address_changed_cb callback, void* user_data)
830 {
831         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
832
833         if (callback == NULL || !(__connection_check_handle_validity(connection))) {
834                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
835                 return CONNECTION_ERROR_INVALID_PARAMETER;
836         }
837
838         return __connection_set_ip_changed_callback(connection, callback, user_data);
839 }
840
841 EXPORT_API int connection_unset_ip_address_changed_cb(connection_h connection)
842 {
843         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
844
845         if (!(__connection_check_handle_validity(connection))) {
846                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
847                 return CONNECTION_ERROR_INVALID_PARAMETER;
848         }
849
850         return __connection_set_ip_changed_callback(connection, NULL, NULL);
851 }
852
853 EXPORT_API int connection_set_proxy_address_changed_cb(connection_h connection,
854                                 connection_address_changed_cb callback, void* user_data)
855 {
856         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
857
858         if (callback == NULL || !(__connection_check_handle_validity(connection))) {
859                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
860                 return CONNECTION_ERROR_INVALID_PARAMETER;
861         }
862
863         return __connection_set_proxy_changed_callback(connection, callback, user_data);
864 }
865
866 EXPORT_API int connection_unset_proxy_address_changed_cb(connection_h connection)
867 {
868         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
869
870         if (!(__connection_check_handle_validity(connection))) {
871                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
872                 return CONNECTION_ERROR_INVALID_PARAMETER;
873         }
874
875         return __connection_set_proxy_changed_callback(connection, NULL, NULL);
876 }
877
878 EXPORT_API int connection_add_profile(connection_h connection, connection_profile_h profile)
879 {
880         int rv = 0;
881         net_profile_info_t *profile_info = profile;
882
883         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
884
885         if (!(__connection_check_handle_validity(connection)) ||
886             !(_connection_libnet_check_profile_validity(profile))) {
887                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
888                 return CONNECTION_ERROR_INVALID_PARAMETER;
889         }
890
891         if (profile_info->profile_type != NET_DEVICE_CELLULAR) {
892                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE
893                 return CONNECTION_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
894         }
895
896         if (profile_info->ProfileInfo.Pdp.PSModemPath[0] != '/' ||
897                         strlen(profile_info->ProfileInfo.Pdp.PSModemPath) < 2) {
898                 CONNECTION_LOG(CONNECTION_ERROR, "Modem object path is NULL"); //LCOV_EXCL_LINE
899                 return CONNECTION_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
900         }
901
902         rv = net_add_profile(profile_info->ProfileInfo.Pdp.ServiceType,
903                                                         (net_profile_info_t*)profile);
904         if (rv == NET_ERR_ACCESS_DENIED) {
905                 CONNECTION_LOG(CONNECTION_ERROR, "Access denied"); //LCOV_EXCL_LINE
906                 return CONNECTION_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
907         } else if (rv != NET_ERR_NONE) {
908                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to add profile[%d]", rv); //LCOV_EXCL_LINE
909                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
910         }
911
912         return CONNECTION_ERROR_NONE;
913 }
914
915 EXPORT_API int connection_remove_profile(connection_h connection, connection_profile_h profile)
916 {
917         int rv = 0;
918         net_profile_info_t *profile_info = profile;
919
920         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE);
921
922         if (!(__connection_check_handle_validity(connection)) ||
923                         !(_connection_libnet_check_profile_validity(profile))) {
924                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
925                 return CONNECTION_ERROR_INVALID_PARAMETER;
926         }
927
928         if (profile_info->profile_type != NET_DEVICE_CELLULAR &&
929             profile_info->profile_type != NET_DEVICE_WIFI) {
930                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE
931                 return CONNECTION_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
932         }
933
934         rv = net_delete_profile(profile_info->ProfileName);
935         if (rv == NET_ERR_ACCESS_DENIED) {
936                 CONNECTION_LOG(CONNECTION_ERROR, "Access denied"); //LCOV_EXCL_LINE
937                 return CONNECTION_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
938         } else if (rv != NET_ERR_NONE) {
939                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to delete profile[%d]", rv); //LCOV_EXCL_LINE
940                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
941         }
942
943         return CONNECTION_ERROR_NONE;
944 }
945
946 EXPORT_API int connection_update_profile(connection_h connection, connection_profile_h profile)
947 {
948         int rv = 0;
949         net_profile_info_t *profile_info = profile;
950
951         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, ETHERNET_FEATURE);
952
953         if (!(__connection_check_handle_validity(connection)) ||
954             !(_connection_libnet_check_profile_validity(profile))) {
955                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
956                 return CONNECTION_ERROR_INVALID_PARAMETER;
957         }
958
959         rv = net_modify_profile(profile_info->ProfileName, (net_profile_info_t*)profile);
960         if (rv == NET_ERR_ACCESS_DENIED) {
961                 CONNECTION_LOG(CONNECTION_ERROR, "Access denied"); //LCOV_EXCL_LINE
962                 return CONNECTION_ERROR_PERMISSION_DENIED; //LCOV_EXCL_LINE
963         } else if (rv != NET_ERR_NONE) {
964                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to modify profile[%d]", rv); //LCOV_EXCL_LINE
965                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
966         }
967
968         return CONNECTION_ERROR_NONE;
969 }
970
971 EXPORT_API int connection_get_profile_iterator(connection_h connection,
972                 connection_iterator_type_e type, connection_profile_iterator_h* profile_iterator)
973 {
974         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
975
976         if (!(__connection_check_handle_validity(connection)) ||
977             (type != CONNECTION_ITERATOR_TYPE_REGISTERED &&
978              type != CONNECTION_ITERATOR_TYPE_CONNECTED &&
979              type != CONNECTION_ITERATOR_TYPE_DEFAULT)) {
980                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
981                 return CONNECTION_ERROR_INVALID_PARAMETER;
982         }
983
984         return _connection_libnet_get_profile_iterator(type, profile_iterator);
985 }
986
987 EXPORT_API int connection_profile_iterator_next(connection_profile_iterator_h profile_iterator,
988                                                         connection_profile_h* profile)
989 {
990         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
991
992         return _connection_libnet_get_iterator_next(profile_iterator, profile);
993 }
994
995 EXPORT_API bool connection_profile_iterator_has_next(connection_profile_iterator_h profile_iterator)
996 {
997         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
998
999         return _connection_libnet_iterator_has_next(profile_iterator);
1000 }
1001
1002 EXPORT_API int connection_destroy_profile_iterator(connection_profile_iterator_h profile_iterator)
1003 {
1004         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
1005
1006         return _connection_libnet_destroy_iterator(profile_iterator);
1007 }
1008
1009 EXPORT_API int connection_get_current_profile(connection_h connection, connection_profile_h* profile)
1010 {
1011         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
1012
1013         if (!(__connection_check_handle_validity(connection)) || profile == NULL) {
1014                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1015                 return CONNECTION_ERROR_INVALID_PARAMETER;
1016         }
1017
1018         return _connection_libnet_get_current_profile(profile);
1019 }
1020
1021 EXPORT_API int connection_get_default_cellular_service_profile(
1022                 connection_h connection, connection_cellular_service_type_e type,
1023                 connection_profile_h *profile)
1024 {
1025         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1026
1027         if (!(__connection_check_handle_validity(connection)) || profile == NULL) {
1028                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1029                 return CONNECTION_ERROR_INVALID_PARAMETER;
1030         }
1031
1032         return _connection_libnet_get_cellular_service_profile(type, profile);
1033 }
1034
1035 EXPORT_API int connection_set_default_cellular_service_profile(connection_h connection,
1036                 connection_cellular_service_type_e type, connection_profile_h profile)
1037 {
1038         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1039
1040         if (!(__connection_check_handle_validity(connection)) || profile == NULL) {
1041                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1042                 return CONNECTION_ERROR_INVALID_PARAMETER;
1043         }
1044
1045         return _connection_libnet_set_cellular_service_profile_sync(type, profile);
1046 }
1047
1048 EXPORT_API int connection_set_default_cellular_service_profile_async(connection_h connection,
1049                 connection_cellular_service_type_e type, connection_profile_h profile,
1050                 connection_set_default_cb callback, void* user_data)
1051 {
1052         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1053
1054         if (!(__connection_check_handle_validity(connection)) ||
1055             profile == NULL || callback == NULL) {
1056                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1057                 return CONNECTION_ERROR_INVALID_PARAMETER;
1058         }
1059
1060         return _connection_libnet_set_cellular_service_profile_async(type, profile, callback, user_data);
1061 }
1062
1063 EXPORT_API int connection_open_profile(connection_h connection, connection_profile_h profile,
1064                                         connection_opened_cb callback, void* user_data)
1065 {
1066         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE);
1067
1068         if (!(__connection_check_handle_validity(connection)) ||
1069             profile == NULL || callback == NULL) {
1070                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1071                 return CONNECTION_ERROR_INVALID_PARAMETER;
1072         }
1073
1074         return _connection_libnet_open_profile(profile, callback, user_data);
1075 }
1076
1077 EXPORT_API int connection_close_profile(connection_h connection, connection_profile_h profile,
1078                                         connection_closed_cb callback, void* user_data)
1079 {
1080         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE);
1081
1082         if (!(__connection_check_handle_validity(connection)) ||
1083             profile == NULL || callback == NULL) {
1084                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1085                 return CONNECTION_ERROR_INVALID_PARAMETER;
1086         }
1087
1088         return _connection_libnet_close_profile(profile, callback, user_data);
1089 }
1090
1091 EXPORT_API int connection_reset_profile(connection_h connection,
1092                                 connection_reset_option_e type, int id, connection_reset_cb callback, void *user_data)
1093 {
1094         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1095
1096         if (!(__connection_check_handle_validity(connection))) {
1097                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed");
1098                 return CONNECTION_ERROR_INVALID_PARAMETER;
1099         }
1100
1101         if (id < 0 || id > 1) {
1102                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed"); //LCOV_EXCL_LINE
1103                 return CONNECTION_ERROR_INVALID_PARAMETER; //LCOV_EXCL_LINE
1104         }
1105
1106         return _connection_libnet_reset_profile(type, id, callback, user_data);
1107 }
1108
1109 EXPORT_API int connection_add_route(connection_h connection, const char* interface_name, const char* host_address)
1110 {
1111         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
1112
1113         if (!(__connection_check_handle_validity(connection)) ||
1114             interface_name == NULL || host_address == NULL) {
1115                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1116                 return CONNECTION_ERROR_INVALID_PARAMETER;
1117         }
1118
1119         return _connection_libnet_add_route(interface_name, host_address);
1120 }
1121
1122 EXPORT_API int connection_remove_route(connection_h connection, const char* interface_name, const char* host_address)
1123 {
1124         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
1125
1126         if (!(__connection_check_handle_validity(connection)) ||
1127             interface_name == NULL || host_address == NULL) {
1128                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1129                 return CONNECTION_ERROR_INVALID_PARAMETER;
1130         }
1131
1132         return _connection_libnet_remove_route(interface_name, host_address);
1133 }
1134
1135 EXPORT_API int connection_add_route_ipv6(connection_h connection, const char *interface_name, const char *host_address, const char * gateway)
1136 {
1137         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, ETHERNET_FEATURE);
1138
1139         if (!(__connection_check_handle_validity(connection)) ||
1140             interface_name == NULL || host_address == NULL) {
1141                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1142                 return CONNECTION_ERROR_INVALID_PARAMETER;
1143         }
1144
1145         return _connection_libnet_add_route_ipv6(interface_name, host_address, gateway);
1146 }
1147
1148 EXPORT_API int connection_remove_route_ipv6(connection_h connection, const char *interface_name, const char *host_address, const char * gateway)
1149 {
1150         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE, ETHERNET_FEATURE);
1151
1152         if (!(__connection_check_handle_validity(connection)) ||
1153             interface_name == NULL || host_address == NULL) {
1154                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1155                 return CONNECTION_ERROR_INVALID_PARAMETER;
1156         }
1157
1158         return _connection_libnet_remove_route_ipv6(interface_name, host_address, gateway);
1159 }
1160
1161 static int __get_cellular_statistic(connection_statistics_type_e statistics_type, long long *llsize)
1162 {
1163         int rv = VCONF_OK, rv1 = VCONF_OK;
1164         int last_size = 0, size = 0;
1165 #if defined TIZEN_DUALSIM_ENABLE
1166         int sim_id = 0;
1167 #endif
1168
1169         if (llsize == NULL) {
1170                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE
1171                 return CONNECTION_ERROR_INVALID_PARAMETER;
1172         }
1173
1174         switch (statistics_type) {
1175         case CONNECTION_STATISTICS_TYPE_LAST_SENT_DATA:
1176         case CONNECTION_STATISTICS_TYPE_LAST_RECEIVED_DATA:
1177         case CONNECTION_STATISTICS_TYPE_TOTAL_SENT_DATA:
1178         case CONNECTION_STATISTICS_TYPE_TOTAL_RECEIVED_DATA:
1179                 break;
1180         default:
1181                 return CONNECTION_ERROR_INVALID_PARAMETER;
1182         }
1183
1184 #if defined TIZEN_DUALSIM_ENABLE
1185         rv = vconf_get_int(VCONF_TELEPHONY_DEFAULT_DATA_SERVICE, &sim_id);
1186         if (rv != VCONF_OK) {
1187                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get default subscriber id");
1188                 *llsize = 0;
1189                 return CONNECTION_ERROR_OPERATION_FAILED;
1190         }
1191
1192         switch (sim_id) {
1193         case 0:
1194 #endif
1195                 switch (statistics_type) {
1196                 case CONNECTION_STATISTICS_TYPE_LAST_SENT_DATA:
1197                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, &last_size);
1198                         break;
1199                 case CONNECTION_STATISTICS_TYPE_LAST_RECEIVED_DATA:
1200                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, &last_size);
1201                         break;
1202                 case CONNECTION_STATISTICS_TYPE_TOTAL_SENT_DATA:
1203                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, &last_size);
1204                         rv1 = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT, &size);
1205                         break;
1206                 case CONNECTION_STATISTICS_TYPE_TOTAL_RECEIVED_DATA:
1207                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, &last_size);
1208                         rv1 = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV, &size);
1209                         break;
1210                 }
1211 #if defined TIZEN_DUALSIM_ENABLE
1212                 break;
1213         case 1:
1214                 switch (statistics_type) {
1215                 case CONNECTION_STATISTICS_TYPE_LAST_SENT_DATA:
1216                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT2, &last_size);
1217                         break;
1218                 case CONNECTION_STATISTICS_TYPE_LAST_RECEIVED_DATA:
1219                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV2, &last_size);
1220                         break;
1221                 case CONNECTION_STATISTICS_TYPE_TOTAL_SENT_DATA:
1222                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT2, &last_size);
1223                         rv1 = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT2, &size);
1224                         break;
1225                 case CONNECTION_STATISTICS_TYPE_TOTAL_RECEIVED_DATA:
1226                         rv = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV2, &last_size);
1227                         rv1 = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV2, &size);
1228                         break;
1229                 }
1230                 break;
1231         default:
1232                 *llsize = 0;
1233                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid subscriber id:%d", sim_id);
1234                 return CONNECTION_ERROR_OPERATION_FAILED;
1235         }
1236 #endif
1237
1238         if (rv != VCONF_OK || rv1 != VCONF_OK) {
1239                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get cellular statistics"); //LCOV_EXCL_LINE
1240                 return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
1241         }
1242
1243         *llsize = (long long)(last_size * 1000) + (long long)(size * 1000);
1244         CONNECTION_LOG(CONNECTION_INFO, "%lld bytes", *llsize);
1245
1246         return CONNECTION_ERROR_NONE;
1247 }
1248
1249 static int __get_statistic(connection_type_e connection_type,
1250                 connection_statistics_type_e statistics_type, long long *llsize)
1251 {
1252         int rv, stat_type;
1253         unsigned long long ull_size;
1254
1255         if (llsize == NULL) {
1256                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter"); //LCOV_EXCL_LINE
1257                 return CONNECTION_ERROR_INVALID_PARAMETER;
1258         }
1259
1260         rv  = _connection_libnet_check_get_privilege();
1261         if (rv == CONNECTION_ERROR_PERMISSION_DENIED)
1262                 return rv;
1263         else if (rv != CONNECTION_ERROR_NONE) {
1264                 CONNECTION_LOG(CONNECTION_ERROR, "Failed to get statistics"); //LCOV_EXCL_LINE
1265                 return CONNECTION_ERROR_OPERATION_FAILED;
1266         }
1267
1268         if (connection_type == CONNECTION_TYPE_CELLULAR)
1269                 return __get_cellular_statistic(statistics_type, llsize);
1270         else if (connection_type == CONNECTION_TYPE_WIFI) {
1271                 switch (statistics_type) {
1272                 case CONNECTION_STATISTICS_TYPE_LAST_SENT_DATA:
1273                         stat_type = NET_STATISTICS_TYPE_LAST_SENT_DATA;
1274                         break;
1275                 case CONNECTION_STATISTICS_TYPE_LAST_RECEIVED_DATA:
1276                         stat_type = NET_STATISTICS_TYPE_LAST_RECEIVED_DATA;
1277                         break;
1278                 case CONNECTION_STATISTICS_TYPE_TOTAL_SENT_DATA:
1279                         stat_type = NET_STATISTICS_TYPE_TOTAL_SENT_DATA;
1280                         break;
1281                 case CONNECTION_STATISTICS_TYPE_TOTAL_RECEIVED_DATA:
1282                         stat_type = NET_STATISTICS_TYPE_TOTAL_RECEIVED_DATA;
1283                         break;
1284                 default:
1285                         return CONNECTION_ERROR_INVALID_PARAMETER;
1286                 }
1287
1288                 rv  = _connection_libnet_get_statistics(stat_type, &ull_size);
1289                 if (rv == CONNECTION_ERROR_PERMISSION_DENIED)
1290                         return rv;
1291                 else if (rv != CONNECTION_ERROR_NONE) {
1292                         CONNECTION_LOG(CONNECTION_ERROR, "Failed to get Wi-Fi statistics"); //LCOV_EXCL_LINE
1293                         *llsize = 0; //LCOV_EXCL_LINE
1294                         return CONNECTION_ERROR_OPERATION_FAILED; //LCOV_EXCL_LINE
1295                 }
1296
1297                 CONNECTION_LOG(CONNECTION_INFO, "%lld bytes", ull_size);
1298                 *llsize = (long long)ull_size;
1299         } else
1300                 return CONNECTION_ERROR_INVALID_PARAMETER;
1301
1302         return CONNECTION_ERROR_NONE;
1303 }
1304
1305 static int __reset_statistic(connection_type_e connection_type,
1306                 connection_statistics_type_e statistics_type)
1307 {
1308         int conn_type;
1309         int stat_type;
1310         int rv;
1311
1312         if (connection_type == CONNECTION_TYPE_CELLULAR)
1313                 conn_type = NET_DEVICE_CELLULAR;
1314         else if (connection_type == CONNECTION_TYPE_WIFI)
1315                 conn_type = NET_DEVICE_WIFI;
1316         else
1317                 return CONNECTION_ERROR_INVALID_PARAMETER;
1318
1319         switch (statistics_type) {
1320         case CONNECTION_STATISTICS_TYPE_LAST_SENT_DATA:
1321                 stat_type = NET_STATISTICS_TYPE_LAST_SENT_DATA;
1322                 break;
1323         case CONNECTION_STATISTICS_TYPE_LAST_RECEIVED_DATA:
1324                 stat_type = NET_STATISTICS_TYPE_LAST_RECEIVED_DATA;
1325                 break;
1326         case CONNECTION_STATISTICS_TYPE_TOTAL_SENT_DATA:
1327                 stat_type = NET_STATISTICS_TYPE_TOTAL_SENT_DATA;
1328                 break;
1329         case CONNECTION_STATISTICS_TYPE_TOTAL_RECEIVED_DATA:
1330                 stat_type = NET_STATISTICS_TYPE_TOTAL_RECEIVED_DATA;
1331                 break;
1332         default:
1333                 return CONNECTION_ERROR_INVALID_PARAMETER;
1334         }
1335
1336         rv = _connection_libnet_set_statistics(conn_type, stat_type);
1337         if (rv != CONNECTION_ERROR_NONE)
1338                 return rv;
1339
1340         CONNECTION_LOG(CONNECTION_INFO, "connection_reset_statistics success");
1341
1342         return CONNECTION_ERROR_NONE;
1343 }
1344
1345 EXPORT_API int connection_get_statistics(connection_h connection,
1346                                 connection_type_e connection_type,
1347                                 connection_statistics_type_e statistics_type, long long* size)
1348 {
1349         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE);
1350
1351         if (connection_type == CONNECTION_TYPE_CELLULAR)
1352                 CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1353         else if (connection_type == CONNECTION_TYPE_WIFI)
1354                 CHECK_FEATURE_SUPPORTED(WIFI_FEATURE);
1355
1356         if (!(__connection_check_handle_validity(connection)) || size == NULL) {
1357                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1358                 return CONNECTION_ERROR_INVALID_PARAMETER;
1359         }
1360
1361         return __get_statistic(connection_type, statistics_type, size);
1362 }
1363
1364 EXPORT_API int connection_reset_statistics(connection_h connection,
1365                                 connection_type_e connection_type,
1366                                 connection_statistics_type_e statistics_type)
1367 {
1368         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE);
1369
1370         if (connection_type == CONNECTION_TYPE_CELLULAR)
1371                 CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE);
1372         else if (connection_type == CONNECTION_TYPE_WIFI)
1373                 CHECK_FEATURE_SUPPORTED(WIFI_FEATURE);
1374
1375         if (!__connection_check_handle_validity(connection)) {
1376                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1377                 return CONNECTION_ERROR_INVALID_PARAMETER;
1378         }
1379
1380         return __reset_statistic(connection_type, statistics_type);
1381 }
1382
1383 EXPORT_API int connection_foreach_ipv6_address(connection_h connection,
1384                 connection_type_e connection_type, connection_ipv6_address_cb callback,
1385                 void *user_data)
1386 {
1387         CHECK_FEATURE_SUPPORTED(TELEPHONY_FEATURE, WIFI_FEATURE,
1388                         TETHERING_BLUETOOTH_FEATURE, ETHERNET_FEATURE);
1389
1390         GSList *ipv6_address_list = NULL;
1391
1392         if (!(__connection_check_handle_validity(connection))) {
1393                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1394                 return CONNECTION_ERROR_INVALID_PARAMETER;
1395         }
1396
1397         int rv = CONNECTION_ERROR_NONE;
1398
1399         switch (connection_type) {
1400         case CONNECTION_TYPE_WIFI:
1401                 rv = net_foreach_ipv6_address(NET_DEVICE_WIFI,
1402                                 &ipv6_address_list);
1403                 break;
1404         case CONNECTION_TYPE_CELLULAR:
1405                 rv = net_foreach_ipv6_address(NET_DEVICE_CELLULAR,
1406                                 &ipv6_address_list);
1407                 break;
1408         case CONNECTION_TYPE_ETHERNET:
1409                 rv = net_foreach_ipv6_address(NET_DEVICE_ETHERNET,
1410                                 &ipv6_address_list);
1411                 break;
1412         case CONNECTION_TYPE_BT:
1413                 rv = net_foreach_ipv6_address(NET_DEVICE_BLUETOOTH,
1414                                 &ipv6_address_list);
1415                 break;
1416         default:
1417                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid parameter");
1418                 return CONNECTION_ERROR_INVALID_PARAMETER;
1419         }
1420
1421         if (rv != NET_ERR_NONE) {
1422                 CONNECTION_LOG(CONNECTION_ERROR, "net_get_multiple_id_address"
1423                                 " Failed = %d\n", rv);
1424                 return CONNECTION_ERROR_OPERATION_FAILED;
1425         }
1426
1427         GSList *list;
1428         for (list = ipv6_address_list; list; list = list->next) {
1429                 rv = callback((char *)list->data, user_data);
1430                 if (rv == false)
1431                         break;
1432         }
1433
1434         g_slist_free_full(ipv6_address_list, g_free);
1435         ipv6_address_list = NULL;
1436
1437         return CONNECTION_ERROR_NONE;
1438 }
1439