1a8390dd8d7e2586d3ed909840a20fd88586599d
[platform/core/api/connection.git] / src / libnetwork.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 <stdio.h>
18 #include <string.h>
19 #include <glib.h>
20 #include <vconf/vconf.h>
21 #include "net_connection_private.h"
22
23 static GSList *prof_handle_list = NULL;
24 static GHashTable *profile_cb_table = NULL;
25
26 struct _profile_cb_s {
27         connection_profile_state_changed_cb callback;
28         connection_profile_state_e state;
29         void *user_data;
30 };
31
32 struct _profile_list_s {
33         int count;
34         int next;
35         net_profile_info_t *profiles;
36 };
37
38 struct _libnet_s {
39         connection_opened_cb opened_cb;
40         connection_closed_cb closed_cb;
41         connection_set_default_cb set_default_cb;
42         void *opened_user_data;
43         void *closed_user_data;
44         void *set_default_user_data;
45         bool registered;
46 };
47
48 static struct _profile_list_s profile_iterator = {0, 0, NULL};
49 static struct _libnet_s libnet = {NULL, NULL, NULL, NULL, NULL, NULL, false};
50
51 static connection_error_e __libnet_convert_to_cp_error_type(net_err_t err_type)
52 {
53         switch (err_type) {
54         case NET_ERR_NONE:
55                 return CONNECTION_ERROR_NONE;
56         case NET_ERR_APP_ALREADY_REGISTERED:
57                 return CONNECTION_ERROR_INVALID_OPERATION;
58         case NET_ERR_APP_NOT_REGISTERED:
59                 return CONNECTION_ERROR_INVALID_OPERATION;
60         case NET_ERR_NO_ACTIVE_CONNECTIONS:
61                 return CONNECTION_ERROR_NO_CONNECTION;
62         case NET_ERR_ACTIVE_CONNECTION_EXISTS:
63                 return CONNECTION_ERROR_ALREADY_EXISTS;
64         case NET_ERR_CONNECTION_DHCP_FAILED:
65                 return CONNECTION_ERROR_DHCP_FAILED;
66         case NET_ERR_CONNECTION_INVALID_KEY:
67                 return CONNECTION_ERROR_INVALID_KEY;
68         case NET_ERR_IN_PROGRESS:
69                 return CONNECTION_ERROR_NOW_IN_PROGRESS;
70         case NET_ERR_OPERATION_ABORTED:
71                 return CONNECTION_ERROR_OPERATION_ABORTED;
72         case NET_ERR_TIME_OUT:
73                 return CONNECTION_ERROR_NO_REPLY;
74         default:
75                 return CONNECTION_ERROR_OPERATION_FAILED;
76         }
77 }
78
79 static const char *__libnet_convert_cp_error_type_to_string(connection_error_e err_type)
80 {
81         switch (err_type) {
82         case CONNECTION_ERROR_NONE:
83                 return "NONE";
84         case CONNECTION_ERROR_INVALID_PARAMETER:
85                 return "INVALID_PARAMETER";
86         case CONNECTION_ERROR_OUT_OF_MEMORY:
87                 return "OUT_OF_MEMORY";
88         case CONNECTION_ERROR_INVALID_OPERATION:
89                 return "INVALID_OPERATION";
90         case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
91                 return "ADDRESS_FAMILY_NOT_SUPPORTED";
92         case CONNECTION_ERROR_OPERATION_FAILED:
93                 return "OPERATION_FAILED";
94         case CONNECTION_ERROR_ITERATOR_END:
95                 return "ITERATOR_END";
96         case CONNECTION_ERROR_NO_CONNECTION:
97                 return "NO_CONNECTION";
98         case CONNECTION_ERROR_NOW_IN_PROGRESS:
99                 return "NOW_IN_PROGRESS";
100         case CONNECTION_ERROR_ALREADY_EXISTS:
101                 return "ALREADY_EXISTS";
102         case CONNECTION_ERROR_OPERATION_ABORTED:
103                 return "OPERATION_ABORTED";
104         case CONNECTION_ERROR_DHCP_FAILED:
105                 return "DHCP_FAILED";
106         case CONNECTION_ERROR_INVALID_KEY:
107                 return "INVALID_KEY";
108         case CONNECTION_ERROR_NO_REPLY:
109                 return "NO_REPLY";
110         }
111
112         return "UNKNOWN";
113 }
114
115 static const char *__libnet_convert_cp_state_to_string(connection_profile_state_e state)
116 {
117         switch (state) {
118         case CONNECTION_PROFILE_STATE_DISCONNECTED:
119                 return "DISCONNECTED";
120         case CONNECTION_PROFILE_STATE_ASSOCIATION:
121                 return "ASSOCIATION";
122         case CONNECTION_PROFILE_STATE_CONFIGURATION:
123                 return "CONFIGURATION";
124         case CONNECTION_PROFILE_STATE_CONNECTED:
125                 return "CONNECTED";
126         default:
127                 return "UNKNOWN";
128         }
129 }
130
131 static void __libnet_set_opened_cb(connection_opened_cb user_cb, void *user_data)
132 {
133         if (user_cb) {
134                 libnet.opened_cb = user_cb;
135                 libnet.opened_user_data = user_data;
136         }
137 }
138
139 static void __libnet_opened_cb(connection_error_e result)
140 {
141         if (libnet.opened_cb)
142                 libnet.opened_cb(result, libnet.opened_user_data);
143
144         libnet.opened_cb = NULL;
145         libnet.opened_user_data = NULL;
146 }
147
148 static void __libnet_set_closed_cb(connection_closed_cb user_cb, void *user_data)
149 {
150         if (user_cb) {
151                 libnet.closed_cb = user_cb;
152                 libnet.closed_user_data = user_data;
153         }
154 }
155
156 static void __libnet_closed_cb(connection_error_e result)
157 {
158         if (libnet.closed_cb)
159                 libnet.closed_cb(result, libnet.closed_user_data);
160
161         libnet.closed_cb = NULL;
162         libnet.closed_user_data = NULL;
163 }
164
165 static void __libnet_set_default_cb(connection_set_default_cb user_cb, void *user_data)
166 {
167         if (user_cb) {
168                 libnet.set_default_cb = user_cb;
169                 libnet.set_default_user_data = user_data;
170         }
171 }
172
173 static void __libnet_default_cb(connection_error_e result)
174 {
175         if (libnet.set_default_cb)
176                 libnet.set_default_cb(result, libnet.set_default_user_data);
177
178         libnet.set_default_cb = NULL;
179         libnet.set_default_user_data = NULL;
180 }
181
182 static void __libnet_state_changed_cb(char *profile_name, connection_profile_state_e state)
183 {
184         if (profile_name == NULL)
185                 return;
186
187         struct _profile_cb_s *cb_info;
188         cb_info = g_hash_table_lookup(profile_cb_table, profile_name);
189
190         if (cb_info == NULL)
191                 return;
192
193         if (cb_info->state == state)
194                 return;
195
196         cb_info->state = state;
197
198         if (state >= 0 && cb_info->callback)
199                 cb_info->callback(state, cb_info->user_data);
200 }
201
202 static void __libnet_clear_profile_list(struct _profile_list_s *profile_list)
203 {
204         if (profile_list->count > 0)
205                 g_free(profile_list->profiles);
206
207         profile_list->count = 0;
208         profile_list->next = 0;
209         profile_list->profiles = NULL;
210 }
211
212 static void __libnet_evt_cb(net_event_info_t*  event_cb, void* user_data)
213 {
214         bool is_requested = false;
215         connection_error_e result = CONNECTION_ERROR_NONE;
216
217         switch (event_cb->Event) {
218         case NET_EVENT_OPEN_RSP:
219                 is_requested = true;
220                 /* fall through */
221         case NET_EVENT_OPEN_IND:
222                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
223                 CONNECTION_LOG(CONNECTION_INFO, "Got connection open %s : %s\n",
224                                         (is_requested) ? "RSP":"IND",
225                                         __libnet_convert_cp_error_type_to_string(result));
226
227                 if (is_requested)
228                         __libnet_opened_cb(result);
229
230                 switch (event_cb->Error) {
231                 case NET_ERR_NONE:
232                 case NET_ERR_ACTIVE_CONNECTION_EXISTS:
233                         CONNECTION_LOG(CONNECTION_INFO, "'Open connection' succeeded\n");
234
235                         __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_CONNECTED);
236                         return;
237                 default:
238                         CONNECTION_LOG(CONNECTION_ERROR, "'Open connection' failed!! [%s]\n",
239                                                 __libnet_convert_cp_error_type_to_string(result));
240                 }
241
242                 __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_DISCONNECTED);
243
244                 break;
245         case NET_EVENT_CLOSE_RSP:
246                 is_requested = true;
247                 /* fall through */
248         case NET_EVENT_CLOSE_IND:
249                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
250                 CONNECTION_LOG(CONNECTION_INFO, "Got connection close %s : %s\n",
251                                         (is_requested) ? "RSP":"IND",
252                                         __libnet_convert_cp_error_type_to_string(result));
253
254                 if (is_requested)
255                         __libnet_closed_cb(result);
256
257                 switch (event_cb->Error) {
258                 case NET_ERR_NONE:
259                         CONNECTION_LOG(CONNECTION_INFO, "'Close connection' succeeded!\n");
260
261                         __libnet_state_changed_cb(event_cb->ProfileName, CONNECTION_PROFILE_STATE_DISCONNECTED);
262                         return;
263                 default:
264                         CONNECTION_LOG(CONNECTION_ERROR, "'Close connection' failed!! [%s]\n",
265                                                 __libnet_convert_cp_error_type_to_string(result));
266                 }
267
268                 break;
269         case NET_EVENT_NET_STATE_IND:
270                 CONNECTION_LOG(CONNECTION_INFO, "Got State changed IND\n");
271
272                 if (event_cb->Datalength != sizeof(net_state_type_t))
273                         return;
274
275                 net_state_type_t *profile_state = (net_state_type_t*)event_cb->Data;
276                 connection_profile_state_e cp_state = _profile_convert_to_cp_state(*profile_state);
277
278                 CONNECTION_LOG(CONNECTION_INFO,
279                                 "Profile State : %s, profile name : %s\n",
280                                 __libnet_convert_cp_state_to_string(cp_state),
281                                 event_cb->ProfileName);
282
283                 __libnet_state_changed_cb(event_cb->ProfileName, cp_state);
284
285                 break;
286         case NET_EVENT_WIFI_SCAN_IND:
287         case NET_EVENT_WIFI_SCAN_RSP:
288                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi scan IND\n");
289                 break;
290         case NET_EVENT_WIFI_POWER_IND:
291         case NET_EVENT_WIFI_POWER_RSP:
292                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi power IND\n");
293                 break;
294         case NET_EVENT_CELLULAR_SET_DEFAULT_RSP:
295                 result = __libnet_convert_to_cp_error_type(event_cb->Error);
296                 CONNECTION_LOG(CONNECTION_INFO, "Got set default profile RSP %d\n", result);
297                 __libnet_default_cb(result);
298                 break;
299         case NET_EVENT_WIFI_WPS_RSP:
300                 CONNECTION_LOG(CONNECTION_INFO, "Got wifi WPS RSP\n");
301                 /* fall through */
302         default :
303                 CONNECTION_LOG(CONNECTION_ERROR, "Error! Unknown Event\n\n");
304                 break;
305         }
306 }
307
308 int __libnet_get_connected_count(struct _profile_list_s *profile_list)
309 {
310         int count = 0;
311         int i = 0;
312
313         for (;i < profile_list->count;i++) {
314                 if (profile_list->profiles[i].ProfileState == NET_STATE_TYPE_ONLINE ||
315                     profile_list->profiles[i].ProfileState == NET_STATE_TYPE_READY)
316                         count++;
317         }
318
319         return count;
320 }
321
322 void __libnet_copy_connected_profile(net_profile_info_t **dest, struct _profile_list_s *source)
323 {
324         int i = 0;
325
326         for (;i < source->count;i++) {
327                 if (source->profiles[i].ProfileState == NET_STATE_TYPE_ONLINE ||
328                     source->profiles[i].ProfileState == NET_STATE_TYPE_READY) {
329                         memcpy(*dest, &source->profiles[i], sizeof(net_profile_info_t));
330                         (*dest)++;
331                 }
332         }
333 }
334
335 bool _connection_libnet_init(void)
336 {
337         int rv;
338
339         if (!libnet.registered) {
340                 rv = net_register_client_ext((net_event_cb_t)__libnet_evt_cb, NET_DEVICE_DEFAULT, NULL);
341                 if (rv != NET_ERR_NONE)
342                         return false;
343
344                 libnet.registered = true;
345
346                 if (profile_cb_table == NULL)
347                         profile_cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
348         }
349
350         return true;
351 }
352
353 bool _connection_libnet_deinit(void)
354 {
355         if (libnet.registered) {
356                 if (net_deregister_client_ext(NET_DEVICE_DEFAULT) != NET_ERR_NONE)
357                         return false;
358
359                 libnet.registered = false;
360
361                 if (profile_cb_table) {
362                         g_hash_table_destroy(profile_cb_table);
363                         profile_cb_table = NULL;
364                 }
365
366                 __libnet_clear_profile_list(&profile_iterator);
367
368                 if (prof_handle_list) {
369                         g_slist_free_full(prof_handle_list, g_free);
370                         prof_handle_list = NULL;
371                 }
372         }
373
374         return true;
375 }
376
377 bool _connection_libnet_check_profile_validity(connection_profile_h profile)
378 {
379         GSList *list;
380         int i = 0;
381
382         for (list = prof_handle_list; list; list = list->next)
383                 if (profile == list->data) return true;
384
385         for (;i < profile_iterator.count;i++)
386                 if (profile == &profile_iterator.profiles[i]) return true;
387
388         return false;
389 }
390
391 bool _connection_libnet_check_profile_cb_validity(connection_profile_h profile)
392 {
393         struct _profile_cb_s *cb_info;
394         net_profile_info_t *profile_info = profile;
395
396         if (profile == NULL)
397                 return false;
398
399         cb_info = g_hash_table_lookup(profile_cb_table, profile_info->ProfileName);
400         if (cb_info != NULL)
401                 return true;
402
403         return false;
404 }
405
406
407 bool _connection_libnet_get_wifi_state(connection_wifi_state_e *state)
408 {
409         net_wifi_state_t wlan_state;
410         net_profile_name_t profile_name;
411
412         if (net_get_wifi_state(&wlan_state, &profile_name) != NET_ERR_NONE) {
413                 CONNECTION_LOG(CONNECTION_ERROR, "Error!! net_get_wifi_state() failed.\n");
414                 return false;
415         }
416
417         switch (wlan_state) {
418         case WIFI_OFF:
419                 *state = CONNECTION_WIFI_STATE_DEACTIVATED;
420                 break;
421         case WIFI_ON:
422         case WIFI_CONNECTING:
423                 *state = CONNECTION_WIFI_STATE_DISCONNECTED;
424                 break;
425         case WIFI_CONNECTED:
426         case WIFI_DISCONNECTING:
427                 *state = CONNECTION_WIFI_STATE_CONNECTED;
428                 break;
429         default :
430                 CONNECTION_LOG(CONNECTION_ERROR, "Error!! Unknown state\n");
431                 return false;
432         }
433
434         return true;
435 }
436
437 bool _connection_libnet_get_ethernet_state(connection_ethernet_state_e* state)
438 {
439         struct _profile_list_s ethernet_profiles = {0, 0, NULL};
440         net_get_profile_list(NET_DEVICE_ETHERNET, &ethernet_profiles.profiles, &ethernet_profiles.count);
441
442         if (ethernet_profiles.count == 0) {
443                 *state = CONNECTION_ETHERNET_STATE_DEACTIVATED;
444                 return true;
445         }
446
447         switch (ethernet_profiles.profiles->ProfileState) {
448         case NET_STATE_TYPE_ONLINE:
449         case NET_STATE_TYPE_READY:
450                 *state = CONNECTION_ETHERNET_STATE_CONNECTED;
451                 break;
452         case NET_STATE_TYPE_IDLE:
453         case NET_STATE_TYPE_FAILURE:
454         case NET_STATE_TYPE_ASSOCIATION:
455         case NET_STATE_TYPE_CONFIGURATION:
456         case NET_STATE_TYPE_DISCONNECT:
457                 *state = CONNECTION_ETHERNET_STATE_DISCONNECTED;
458                 break;
459         default:
460                 return false;
461         }
462
463         __libnet_clear_profile_list(&ethernet_profiles);
464
465         return true;
466 }
467
468 bool _connection_libnet_get_bluetooth_state(connection_bt_state_e* state)
469 {
470         int i = 0;
471         struct _profile_list_s bluetooth_profiles = {0, 0, NULL};
472         net_get_profile_list(NET_DEVICE_BLUETOOTH, &bluetooth_profiles.profiles, &bluetooth_profiles.count);
473
474         if (bluetooth_profiles.count == 0) {
475                 *state = CONNECTION_BT_STATE_DEACTIVATED;
476                 return true;
477         }
478
479         for (; i < bluetooth_profiles.count; i++) {
480                 switch (bluetooth_profiles.profiles[i].ProfileState) {
481                 case NET_STATE_TYPE_ONLINE:
482                 case NET_STATE_TYPE_READY:
483                         *state = CONNECTION_BT_STATE_CONNECTED;
484                         goto done;
485                 case NET_STATE_TYPE_IDLE:
486                 case NET_STATE_TYPE_FAILURE:
487                 case NET_STATE_TYPE_ASSOCIATION:
488                 case NET_STATE_TYPE_CONFIGURATION:
489                 case NET_STATE_TYPE_DISCONNECT:
490                         *state = CONNECTION_BT_STATE_DISCONNECTED;
491                         break;
492                 default:
493                         __libnet_clear_profile_list(&bluetooth_profiles);
494                         return false;
495                 }
496         }
497
498 done:
499         __libnet_clear_profile_list(&bluetooth_profiles);
500
501         return true;
502 }
503
504 int _connection_libnet_get_profile_iterator(connection_iterator_type_e type, connection_profile_iterator_h* profile_iter_h)
505 {
506         int count = 0;
507         int rv;
508         net_profile_info_t *profiles = NULL;
509
510         struct _profile_list_s all_profiles = {0, 0, NULL};
511
512         __libnet_clear_profile_list(&profile_iterator);
513
514         rv = net_get_profile_list(NET_DEVICE_MAX, &all_profiles.profiles, &all_profiles.count);
515
516         if (rv != NET_ERR_NONE) {
517                 if (rv == NET_ERR_NO_SERVICE) {
518                         *profile_iter_h = &profile_iterator;
519                         return CONNECTION_ERROR_NONE;
520                 } else
521                         return CONNECTION_ERROR_OPERATION_FAILED;
522         }
523
524         *profile_iter_h = &profile_iterator;
525
526         switch (type) {
527         case CONNECTION_ITERATOR_TYPE_REGISTERED:
528                 count = all_profiles.count;
529                 CONNECTION_LOG(CONNECTION_INFO, "Total profile count : %d\n", count);
530
531                 if (count == 0)
532                         return CONNECTION_ERROR_NONE;
533
534                 profile_iterator.profiles = all_profiles.profiles;
535
536                 break;
537         case CONNECTION_ITERATOR_TYPE_CONNECTED:
538                 count = __libnet_get_connected_count(&all_profiles);
539                 CONNECTION_LOG(CONNECTION_INFO, "Total connected profile count : %d\n", count);
540
541                 if (count == 0)
542                         return CONNECTION_ERROR_NONE;
543
544                 profiles = g_try_new0(net_profile_info_t, count);
545                 if (profiles == NULL) {
546                         __libnet_clear_profile_list(&all_profiles);
547                         return CONNECTION_ERROR_OUT_OF_MEMORY;
548                 }
549
550                 profile_iterator.profiles = profiles;
551
552                 __libnet_copy_connected_profile(&profiles, &all_profiles);
553
554                 __libnet_clear_profile_list(&all_profiles);
555         }
556
557         profile_iterator.count = count;
558
559         return CONNECTION_ERROR_NONE;
560 }
561
562 int _connection_libnet_get_iterator_next(connection_profile_iterator_h profile_iter_h, connection_profile_h *profile)
563 {
564         if (profile_iter_h != &profile_iterator)
565                 return CONNECTION_ERROR_INVALID_PARAMETER;
566
567         if (profile_iterator.count <= profile_iterator.next)
568                 return CONNECTION_ERROR_ITERATOR_END;
569
570         *profile = &profile_iterator.profiles[profile_iterator.next];
571         profile_iterator.next++;
572
573         return CONNECTION_ERROR_NONE;
574 }
575
576 bool _connection_libnet_iterator_has_next(connection_profile_iterator_h profile_iter_h)
577 {
578         if (profile_iter_h != &profile_iterator)
579                 return false;
580
581         if (profile_iterator.count <= profile_iterator.next)
582                 return false;
583
584         return true;
585 }
586
587 int _connection_libnet_destroy_iterator(connection_profile_iterator_h profile_iter_h)
588 {
589         if (profile_iter_h != &profile_iterator)
590                 return CONNECTION_ERROR_INVALID_PARAMETER;
591
592         __libnet_clear_profile_list(&profile_iterator);
593
594         return CONNECTION_ERROR_NONE;
595 }
596
597 int _connection_libnet_get_current_profile(connection_profile_h *profile)
598 {
599         net_profile_info_t active_profile;
600         int rv;
601
602         rv = net_get_active_net_info(&active_profile);
603         if (rv == NET_ERR_NO_SERVICE)
604                 return CONNECTION_ERROR_NO_CONNECTION;
605         else if (rv != NET_ERR_NONE)
606                 return CONNECTION_ERROR_OPERATION_FAILED;
607
608         *profile = g_try_malloc0(sizeof(net_profile_info_t));
609         if (*profile == NULL)
610                 return CONNECTION_ERROR_OUT_OF_MEMORY;
611
612         memcpy(*profile, &active_profile, sizeof(net_profile_info_t));
613         prof_handle_list = g_slist_append(prof_handle_list, *profile);
614
615         return CONNECTION_ERROR_NONE;
616 }
617
618 int _connection_libnet_open_profile(connection_profile_h profile, connection_opened_cb callback, void* user_data)
619 {
620         if (!(_connection_libnet_check_profile_validity(profile))) {
621                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
622                 return CONNECTION_ERROR_INVALID_PARAMETER;
623         }
624
625         net_profile_info_t *profile_info = profile;
626
627         if (net_open_connection_with_profile(profile_info->ProfileName) != NET_ERR_NONE)
628                 return CONNECTION_ERROR_OPERATION_FAILED;
629
630         __libnet_set_opened_cb(callback, user_data);
631
632         return CONNECTION_ERROR_NONE;
633 }
634
635 int _connection_libnet_get_cellular_service_profile(connection_cellular_service_type_e type, connection_profile_h *profile)
636 {
637         int i = 0;
638         int j = 0;
639         int rv = NET_ERR_NONE;
640         net_service_type_t service_type = _connection_profile_convert_to_libnet_cellular_service_type(type);
641
642         struct _profile_list_s cellular_profiles = {0, 0, NULL};
643
644         rv = net_get_profile_list(NET_DEVICE_CELLULAR, &cellular_profiles.profiles, &cellular_profiles.count);
645         if (rv != NET_ERR_NONE)
646                 return CONNECTION_ERROR_OPERATION_FAILED;
647
648         for (;i < cellular_profiles.count;i++)
649                 if (cellular_profiles.profiles[i].ProfileInfo.Pdp.ServiceType == service_type)
650                         break;
651
652         if (i >= cellular_profiles.count)
653                 return CONNECTION_ERROR_OPERATION_FAILED;
654
655         *profile = g_try_malloc0(sizeof(net_profile_info_t));
656         if (*profile == NULL)
657                 return CONNECTION_ERROR_OUT_OF_MEMORY;
658
659         memcpy(*profile, &cellular_profiles.profiles[i], sizeof(net_profile_info_t));
660
661         if (cellular_profiles.profiles[i].ProfileInfo.Pdp.DefaultConn)
662                 goto done;
663
664         if (type != CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET &&
665             type != CONNECTION_CELLULAR_SERVICE_TYPE_PREPAID_INTERNET)
666                 goto done;
667
668         for (;j < cellular_profiles.count;j++) {
669                 if (i == j)
670                         continue;
671
672                 if (cellular_profiles.profiles[j].ProfileInfo.Pdp.ServiceType != service_type)
673                         continue;
674
675                 if (cellular_profiles.profiles[j].ProfileInfo.Pdp.DefaultConn) {
676                         memcpy(*profile, &cellular_profiles.profiles[j], sizeof(net_profile_info_t));
677                         goto done;
678                 }
679         }
680
681 done:
682         prof_handle_list = g_slist_append(prof_handle_list, *profile);
683
684         return CONNECTION_ERROR_NONE;
685 }
686
687 int _connection_libnet_set_cellular_service_profile_sync(connection_cellular_service_type_e type, connection_profile_h profile)
688 {
689         if (!(_connection_libnet_check_profile_validity(profile))) {
690                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
691                 return CONNECTION_ERROR_INVALID_PARAMETER;
692         }
693
694         net_profile_info_t *profile_info = profile;
695         connection_cellular_service_type_e service_type;
696
697         service_type = _profile_convert_to_connection_cellular_service_type(profile_info->ProfileInfo.Pdp.ServiceType);
698
699         if (service_type != type)
700                 return CONNECTION_ERROR_INVALID_PARAMETER;
701
702         if (net_set_default_cellular_service_profile(profile_info->ProfileName) != NET_ERR_NONE)
703                 return CONNECTION_ERROR_OPERATION_FAILED;
704
705         return CONNECTION_ERROR_NONE;
706 }
707
708 int _connection_libnet_set_cellular_service_profile_async(connection_cellular_service_type_e type,
709                         connection_profile_h profile, connection_set_default_cb callback, void* user_data)
710 {
711         if (!(_connection_libnet_check_profile_validity(profile))) {
712                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
713                 return CONNECTION_ERROR_INVALID_PARAMETER;
714         }
715
716         net_profile_info_t *profile_info = profile;
717         connection_cellular_service_type_e service_type;
718
719         service_type = _profile_convert_to_connection_cellular_service_type(profile_info->ProfileInfo.Pdp.ServiceType);
720
721         if (service_type != type)
722                 return CONNECTION_ERROR_INVALID_PARAMETER;
723
724         if (net_set_default_cellular_service_profile_async(profile_info->ProfileName) != NET_ERR_NONE)
725                 return CONNECTION_ERROR_OPERATION_FAILED;
726
727         __libnet_set_default_cb(callback, user_data);
728
729         return CONNECTION_ERROR_NONE;
730 }
731
732 int _connection_libnet_close_profile(connection_profile_h profile, connection_closed_cb callback, void *user_data)
733 {
734         if (!(_connection_libnet_check_profile_validity(profile))) {
735                 CONNECTION_LOG(CONNECTION_ERROR, "Wrong Parameter Passed\n");
736                 return CONNECTION_ERROR_INVALID_PARAMETER;
737         }
738
739         net_profile_info_t *profile_info = profile;
740
741         if (net_close_connection(profile_info->ProfileName) != NET_ERR_NONE)
742                 return CONNECTION_ERROR_OPERATION_FAILED;
743
744         __libnet_set_closed_cb(callback, user_data);
745
746         return CONNECTION_ERROR_NONE;
747 }
748
749 int _connection_libnet_add_route(const char *interface_name, const char *host_address)
750 {
751         char *endstr = strrchr(host_address, '.');
752
753         if (endstr == NULL ||
754             strcmp(endstr, ".0") == 0 ||
755             strncmp(host_address, "0.", 2) == 0 ||
756             strstr(host_address, ".0.") != NULL ||
757             strstr(host_address, "255") != NULL) {
758                 CONNECTION_LOG(CONNECTION_ERROR, "Invalid IP address Passed\n");
759                 return CONNECTION_ERROR_INVALID_PARAMETER;
760         }
761
762         if (net_add_route(host_address, interface_name) != NET_ERR_NONE)
763                 return CONNECTION_ERROR_OPERATION_FAILED;
764
765         return CONNECTION_ERROR_NONE;
766 }
767
768 void _connection_libnet_add_to_profile_list(connection_profile_h profile)
769 {
770         prof_handle_list = g_slist_append(prof_handle_list, profile);
771 }
772
773 void _connection_libnet_remove_from_profile_list(connection_profile_h profile)
774 {
775         prof_handle_list = g_slist_remove(prof_handle_list, profile);
776         g_free(profile);
777 }
778
779 bool _connection_libnet_add_to_profile_cb_list(connection_profile_h profile,
780                 connection_profile_state_changed_cb callback, void *user_data)
781 {
782         net_profile_info_t *profile_info = profile;
783         char *profile_name = g_strdup(profile_info->ProfileName);
784
785         struct _profile_cb_s *profile_cb_info = g_try_malloc0(sizeof(struct _profile_cb_s));
786         if (profile_cb_info == NULL) {
787                 g_free(profile_name);
788                 return false;
789         }
790
791         profile_cb_info->callback = callback;
792         profile_cb_info->user_data = user_data;
793
794         g_hash_table_insert(profile_cb_table, profile_name, profile_cb_info);
795
796         return true;
797 }
798
799 void _connection_libnet_remove_from_profile_cb_list(connection_profile_h profile)
800 {
801         net_profile_info_t *profile_info = profile;
802         g_hash_table_remove(profile_cb_table, profile_info->ProfileName);
803 }
804
805 int _connection_libnet_set_statistics(net_device_t device_type, net_statistics_type_e statistics_type)
806 {
807         if (net_set_statistics(device_type, statistics_type) != NET_ERR_NONE)
808                 return CONNECTION_ERROR_OPERATION_FAILED;
809
810         return CONNECTION_ERROR_NONE;
811 }
812
813 int _connection_libnet_get_statistics(net_statistics_type_e statistics_type, unsigned long long *size)
814 {
815         if (net_get_statistics(NET_DEVICE_WIFI, statistics_type, size) != NET_ERR_NONE)
816                         return CONNECTION_ERROR_OPERATION_FAILED;
817
818                 return CONNECTION_ERROR_NONE;
819 }
820