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