1bb1a6e75d2134c7c1a56c1b066003245b1e7e3b
[framework/connectivity/connman.git] / src / network.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <string.h>
28
29 #include "connman.h"
30
31 static GSList *network_list = NULL;
32 static GSList *driver_list = NULL;
33
34 struct connman_network {
35         int refcount;
36         enum connman_network_type type;
37         connman_bool_t available;
38         connman_bool_t connected;
39         connman_bool_t roaming;
40         connman_uint8_t strength;
41         connman_uint16_t frequency;
42         char *identifier;
43         char *name;
44         char *node;
45         char *group;
46         char *path;
47         int index;
48
49         struct connman_network_driver *driver;
50         void *driver_data;
51
52         connman_bool_t connecting;
53         connman_bool_t associating;
54
55         struct connman_device *device;
56
57         struct {
58                 void *ssid;
59                 int ssid_len;
60                 char *mode;
61                 unsigned short channel;
62                 char *security;
63                 char *passphrase;
64                 char *agent_passphrase;
65                 char *eap;
66                 char *identity;
67                 char *agent_identity;
68                 char *ca_cert_path;
69                 char *client_cert_path;
70                 char *private_key_path;
71                 char *private_key_passphrase;
72                 char *phase2_auth;
73                 connman_bool_t wps;
74                 connman_bool_t use_wps;
75                 char *pin_wps;
76         } wifi;
77
78         struct {
79                 char *nsp_name;
80                 int nsp_name_len;
81         } wimax;
82 };
83
84 static const char *type2string(enum connman_network_type type)
85 {
86         switch (type) {
87         case CONNMAN_NETWORK_TYPE_UNKNOWN:
88         case CONNMAN_NETWORK_TYPE_VENDOR:
89                 break;
90         case CONNMAN_NETWORK_TYPE_ETHERNET:
91                 return "ethernet";
92         case CONNMAN_NETWORK_TYPE_WIFI:
93                 return "wifi";
94         case CONNMAN_NETWORK_TYPE_WIMAX:
95                 return "wimax";
96         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
97         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
98                 return "bluetooth";
99         case CONNMAN_NETWORK_TYPE_CELLULAR:
100                 return "cellular";
101         }
102
103         return NULL;
104 }
105
106 connman_bool_t __connman_network_has_driver(struct connman_network *network)
107 {
108         if (network == NULL || network->driver == NULL)
109                 return FALSE;
110
111         return TRUE;
112 }
113
114 static gboolean match_driver(struct connman_network *network,
115                                         struct connman_network_driver *driver)
116 {
117         if (network->type == driver->type ||
118                         driver->type == CONNMAN_NETWORK_TYPE_UNKNOWN)
119                 return TRUE;
120
121         return FALSE;
122 }
123
124 static int network_probe(struct connman_network *network)
125 {
126         GSList *list;
127         struct connman_network_driver *driver = NULL;
128
129         DBG("network %p name %s", network, network->name);
130
131         if (network->driver != NULL)
132                 return -EALREADY;
133
134         for (list = driver_list; list; list = list->next) {
135                 driver = list->data;
136
137                 if (match_driver(network, driver) == FALSE)
138                         continue;
139
140                 DBG("driver %p name %s", driver, driver->name);
141
142                 if (driver->probe(network) == 0)
143                         break;
144
145                 driver = NULL;
146         }
147
148         if (driver == NULL)
149                 return -ENODEV;
150
151         if (network->group == NULL)
152                 return -EINVAL;
153
154         switch (network->type) {
155         case CONNMAN_NETWORK_TYPE_UNKNOWN:
156         case CONNMAN_NETWORK_TYPE_VENDOR:
157                 return 0;
158         case CONNMAN_NETWORK_TYPE_ETHERNET:
159         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
160         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
161         case CONNMAN_NETWORK_TYPE_CELLULAR:
162         case CONNMAN_NETWORK_TYPE_WIFI:
163         case CONNMAN_NETWORK_TYPE_WIMAX:
164                 network->driver = driver;
165                 if (__connman_service_create_from_network(network) == NULL) {
166                         network->driver = NULL;
167                         return -EINVAL;
168                 }
169         }
170
171         return 0;
172 }
173
174 static void network_remove(struct connman_network *network)
175 {
176         DBG("network %p name %s", network, network->name);
177
178         if (network->driver == NULL)
179                 return;
180
181         connman_network_set_connected(network, FALSE);
182
183         switch (network->type) {
184         case CONNMAN_NETWORK_TYPE_UNKNOWN:
185         case CONNMAN_NETWORK_TYPE_VENDOR:
186                 break;
187         case CONNMAN_NETWORK_TYPE_ETHERNET:
188         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
189         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
190         case CONNMAN_NETWORK_TYPE_CELLULAR:
191         case CONNMAN_NETWORK_TYPE_WIFI:
192         case CONNMAN_NETWORK_TYPE_WIMAX:
193                 if (network->group != NULL) {
194                         __connman_service_remove_from_network(network);
195
196                         g_free(network->group);
197                         network->group = NULL;
198                 }
199                 break;
200         }
201
202         if (network->driver->remove)
203                 network->driver->remove(network);
204
205         network->driver = NULL;
206 }
207
208 static void network_change(struct connman_network *network)
209 {
210         DBG("network %p name %s", network, network->name);
211
212         if (network->connected == FALSE)
213                 return;
214
215         connman_device_set_disconnected(network->device, TRUE);
216
217         if (network->driver && network->driver->disconnect) {
218                 network->driver->disconnect(network);
219                 return;
220         }
221
222         network->connected = FALSE;
223 }
224
225 static void probe_driver(struct connman_network_driver *driver)
226 {
227         GSList *list;
228
229         DBG("driver %p name %s", driver, driver->name);
230
231         for (list = network_list; list != NULL; list = list->next) {
232                 struct connman_network *network = list->data;
233
234                 if (network->driver != NULL)
235                         continue;
236
237                 if (driver->type != network->type)
238                         continue;
239
240                 if (driver->probe(network) < 0)
241                         continue;
242
243                 network->driver = driver;
244         }
245 }
246
247 static void remove_driver(struct connman_network_driver *driver)
248 {
249         GSList *list;
250
251         DBG("driver %p name %s", driver, driver->name);
252
253         for (list = network_list; list != NULL; list = list->next) {
254                 struct connman_network *network = list->data;
255
256                 if (network->driver == driver)
257                         network_remove(network);
258         }
259 }
260
261 static gint compare_priority(gconstpointer a, gconstpointer b)
262 {
263         const struct connman_network_driver *driver1 = a;
264         const struct connman_network_driver *driver2 = b;
265
266         return driver2->priority - driver1->priority;
267 }
268
269 /**
270  * connman_network_driver_register:
271  * @driver: network driver definition
272  *
273  * Register a new network driver
274  *
275  * Returns: %0 on success
276  */
277 int connman_network_driver_register(struct connman_network_driver *driver)
278 {
279         GSList *list;
280
281         DBG("driver %p name %s", driver, driver->name);
282
283         for (list = driver_list; list; list = list->next) {
284                 struct connman_network_driver *tmp = list->data;
285
286                 if (tmp->type == driver->type)
287                         return -EALREADY;
288
289         }
290
291         driver_list = g_slist_insert_sorted(driver_list, driver,
292                                                         compare_priority);
293
294         probe_driver(driver);
295
296         return 0;
297 }
298
299 /**
300  * connman_network_driver_unregister:
301  * @driver: network driver definition
302  *
303  * Remove a previously registered network driver
304  */
305 void connman_network_driver_unregister(struct connman_network_driver *driver)
306 {
307         DBG("driver %p name %s", driver, driver->name);
308
309         driver_list = g_slist_remove(driver_list, driver);
310
311         remove_driver(driver);
312 }
313
314 static void network_destruct(struct connman_network *network)
315 {
316         DBG("network %p name %s", network, network->name);
317
318         g_free(network->wifi.ssid);
319         g_free(network->wifi.mode);
320         g_free(network->wifi.security);
321         g_free(network->wifi.passphrase);
322         g_free(network->wifi.agent_passphrase);
323         g_free(network->wifi.eap);
324         g_free(network->wifi.identity);
325         g_free(network->wifi.agent_identity);
326         g_free(network->wifi.ca_cert_path);
327         g_free(network->wifi.client_cert_path);
328         g_free(network->wifi.private_key_path);
329         g_free(network->wifi.private_key_passphrase);
330         g_free(network->wifi.phase2_auth);
331         g_free(network->wifi.pin_wps);
332
333         g_free(network->path);
334         g_free(network->group);
335         g_free(network->node);
336         g_free(network->name);
337         g_free(network->identifier);
338
339         network->device = NULL;
340
341         g_free(network);
342 }
343
344 /**
345  * connman_network_create:
346  * @identifier: network identifier (for example an unqiue name)
347  *
348  * Allocate a new network and assign the #identifier to it.
349  *
350  * Returns: a newly-allocated #connman_network structure
351  */
352 struct connman_network *connman_network_create(const char *identifier,
353                                                 enum connman_network_type type)
354 {
355         struct connman_network *network;
356         char *ident;
357
358         DBG("identifier %s type %d", identifier, type);
359
360         network = g_try_new0(struct connman_network, 1);
361         if (network == NULL)
362                 return NULL;
363
364         DBG("network %p", network);
365
366         network->refcount = 1;
367
368         ident = g_strdup(identifier);
369
370         if (ident == NULL) {
371                 g_free(network);
372                 return NULL;
373         }
374
375         network->type       = type;
376         network->identifier = ident;
377
378         network_list = g_slist_append(network_list, network);
379
380         return network;
381 }
382
383 /**
384  * connman_network_ref:
385  * @network: network structure
386  *
387  * Increase reference counter of  network
388  */
389 struct connman_network *connman_network_ref(struct connman_network *network)
390 {
391         DBG("network %p name %s refcount %d", network, network->name,
392                 network->refcount + 1);
393
394         __sync_fetch_and_add(&network->refcount, 1);
395
396         return network;
397 }
398
399 /**
400  * connman_network_unref:
401  * @network: network structure
402  *
403  * Decrease reference counter of network
404  */
405 void connman_network_unref(struct connman_network *network)
406 {
407         DBG("network %p name %s refcount %d", network, network->name,
408                 network->refcount - 1);
409
410         if (__sync_fetch_and_sub(&network->refcount, 1) != 1)
411                 return;
412
413         network_list = g_slist_remove(network_list, network);
414
415         network_destruct(network);
416 }
417
418 const char *__connman_network_get_type(struct connman_network *network)
419 {
420         return type2string(network->type);
421 }
422
423 /**
424  * connman_network_get_type:
425  * @network: network structure
426  *
427  * Get type of network
428  */
429 enum connman_network_type connman_network_get_type(struct connman_network *network)
430 {
431         return network->type;
432 }
433
434 /**
435  * connman_network_get_identifier:
436  * @network: network structure
437  *
438  * Get identifier of network
439  */
440 const char *connman_network_get_identifier(struct connman_network *network)
441 {
442         return network->identifier;
443 }
444
445 /**
446  * connman_network_set_index:
447  * @network: network structure
448  * @index: index number
449  *
450  * Set index number of network
451  */
452 void connman_network_set_index(struct connman_network *network, int index)
453 {
454         struct connman_service *service;
455         struct connman_ipconfig *ipconfig;
456
457         service = __connman_service_lookup_from_network(network);
458         if (service == NULL)
459                 goto done;
460
461         ipconfig = __connman_service_get_ip4config(service);
462
463         DBG("index %d service %p ip4config %p", network->index,
464                 service, ipconfig);
465
466         if (network->index < 0 && ipconfig == NULL) {
467
468                 ipconfig = __connman_service_get_ip4config(service);
469                 if (ipconfig == NULL)
470                         /*
471                          * This is needed for plugins that havent set their
472                          * ipconfig layer yet, due to not being able to get
473                          * a network index prior to creating a service.
474                          */
475                         __connman_service_create_ip4config(service, index);
476                 else
477                         __connman_ipconfig_set_index(ipconfig, index);
478
479         } else {
480                 /* If index changed, the index of ipconfig must be reset. */
481                 if (ipconfig == NULL)
482                         goto done;
483
484                 __connman_ipconfig_set_index(ipconfig, index);
485         }
486
487 done:
488         network->index = index;
489 }
490
491 /**
492  * connman_network_get_index:
493  * @network: network structure
494  *
495  * Get index number of network
496  */
497 int connman_network_get_index(struct connman_network *network)
498 {
499         return network->index;
500 }
501
502 /**
503  * connman_network_set_group:
504  * @network: network structure
505  * @group: group name
506  *
507  * Set group name for automatic clustering
508  */
509 void connman_network_set_group(struct connman_network *network,
510                                                         const char *group)
511 {
512         switch (network->type) {
513         case CONNMAN_NETWORK_TYPE_UNKNOWN:
514         case CONNMAN_NETWORK_TYPE_VENDOR:
515                 return;
516         case CONNMAN_NETWORK_TYPE_ETHERNET:
517         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
518         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
519         case CONNMAN_NETWORK_TYPE_CELLULAR:
520         case CONNMAN_NETWORK_TYPE_WIFI:
521         case CONNMAN_NETWORK_TYPE_WIMAX:
522                 break;
523         }
524
525         if (g_strcmp0(network->group, group) == 0) {
526                 if (group != NULL)
527                         __connman_service_update_from_network(network);
528                 return;
529         }
530
531         if (network->group != NULL) {
532                 __connman_service_remove_from_network(network);
533
534                 g_free(network->group);
535         }
536
537         network->group = g_strdup(group);
538
539         if (network->group != NULL)
540                 network_probe(network);
541 }
542
543 /**
544  * connman_network_get_group:
545  * @network: network structure
546  *
547  * Get group name for automatic clustering
548  */
549 const char *connman_network_get_group(struct connman_network *network)
550 {
551         return network->group;
552 }
553
554 const char *__connman_network_get_ident(struct connman_network *network)
555 {
556         if (network->device == NULL)
557                 return NULL;
558
559         return connman_device_get_ident(network->device);
560 }
561
562 connman_bool_t __connman_network_get_weakness(struct connman_network *network)
563 {
564         switch (network->type) {
565         case CONNMAN_NETWORK_TYPE_UNKNOWN:
566         case CONNMAN_NETWORK_TYPE_VENDOR:
567         case CONNMAN_NETWORK_TYPE_ETHERNET:
568         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
569         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
570         case CONNMAN_NETWORK_TYPE_CELLULAR:
571         case CONNMAN_NETWORK_TYPE_WIMAX:
572                 break;
573         case CONNMAN_NETWORK_TYPE_WIFI:
574                 if (g_strcmp0(network->wifi.mode, "adhoc") == 0)
575                         return TRUE;
576                 if (network->strength > 0 && network->strength < 20)
577                         return TRUE;
578                 break;
579         }
580
581         return FALSE;
582 }
583
584 connman_bool_t connman_network_get_connecting(struct connman_network *network)
585 {
586         return network->connecting;
587 }
588
589 /**
590  * connman_network_set_available:
591  * @network: network structure
592  * @available: availability state
593  *
594  * Change availability state of network (in range)
595  */
596 int connman_network_set_available(struct connman_network *network,
597                                                 connman_bool_t available)
598 {
599         DBG("network %p available %d", network, available);
600
601         if (network->available == available)
602                 return -EALREADY;
603
604         network->available = available;
605
606         return 0;
607 }
608
609 /**
610  * connman_network_get_available:
611  * @network: network structure
612  *
613  * Get network available setting
614  */
615 connman_bool_t connman_network_get_available(struct connman_network *network)
616 {
617         return network->available;
618 }
619
620 /**
621  * connman_network_set_associating:
622  * @network: network structure
623  * @associating: associating state
624  *
625  * Change associating state of network
626  */
627 int connman_network_set_associating(struct connman_network *network,
628                                                 connman_bool_t associating)
629 {
630         DBG("network %p associating %d", network, associating);
631
632         if (network->associating == associating)
633                 return -EALREADY;
634
635         network->associating = associating;
636
637         if (associating == TRUE) {
638                 struct connman_service *service;
639
640                 service = __connman_service_lookup_from_network(network);
641                 __connman_service_ipconfig_indicate_state(service,
642                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
643                                         CONNMAN_IPCONFIG_TYPE_IPV4);
644                 __connman_service_ipconfig_indicate_state(service,
645                                         CONNMAN_SERVICE_STATE_ASSOCIATION,
646                                         CONNMAN_IPCONFIG_TYPE_IPV6);
647         }
648
649         return 0;
650 }
651
652 static void set_associate_error(struct connman_network *network)
653 {
654         struct connman_service *service;
655
656         service = __connman_service_lookup_from_network(network);
657
658         __connman_service_indicate_error(service,
659                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
660 }
661
662 static void set_configure_error(struct connman_network *network)
663 {
664         struct connman_service *service;
665
666         service = __connman_service_lookup_from_network(network);
667
668         __connman_service_indicate_error(service,
669                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
670 }
671
672 static void set_invalid_key_error(struct connman_network *network)
673 {
674         struct connman_service *service;
675
676         service = __connman_service_lookup_from_network(network);
677
678         __connman_service_indicate_error(service,
679                                         CONNMAN_SERVICE_ERROR_INVALID_KEY);
680 }
681
682 static void set_connect_error(struct connman_network *network)
683 {
684         struct connman_service *service;
685
686         service = __connman_service_lookup_from_network(network);
687
688         __connman_service_indicate_error(service,
689                                         CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
690 }
691
692 void connman_network_set_ipv4_method(struct connman_network *network,
693                                         enum connman_ipconfig_method method)
694 {
695         struct connman_service *service;
696         struct connman_ipconfig *ipconfig;
697
698         service = __connman_service_lookup_from_network(network);
699         if (service == NULL)
700                 return;
701
702         ipconfig = __connman_service_get_ip4config(service);
703         if (ipconfig == NULL)
704                 return;
705
706         connman_ipconfig_set_method(ipconfig, method);
707 }
708
709 void connman_network_set_ipv6_method(struct connman_network *network,
710                                         enum connman_ipconfig_method method)
711 {
712         struct connman_service *service;
713         struct connman_ipconfig *ipconfig;
714
715         service = __connman_service_lookup_from_network(network);
716         if (service == NULL)
717                 return;
718
719         ipconfig = __connman_service_get_ip6config(service);
720         if (ipconfig == NULL)
721                 return;
722
723         connman_ipconfig_set_method(ipconfig, method);
724 }
725
726 void connman_network_set_error(struct connman_network *network,
727                                         enum connman_network_error error)
728 {
729         DBG("nework %p, error %d", network, error);
730
731         network->connecting = FALSE;
732         network->associating = FALSE;
733
734         switch (error) {
735         case CONNMAN_NETWORK_ERROR_UNKNOWN:
736                 return;
737         case CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL:
738                 set_associate_error(network);
739                 break;
740         case CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL:
741                 set_configure_error(network);
742                 break;
743         case CONNMAN_NETWORK_ERROR_INVALID_KEY:
744                 set_invalid_key_error(network);
745                 break;
746         case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
747                 set_connect_error(network);
748                 break;
749         }
750
751         network_change(network);
752 }
753
754 void connman_network_clear_error(struct connman_network *network)
755 {
756         struct connman_service *service;
757
758         DBG("network %p", network);
759
760         if (network == NULL)
761                 return;
762
763         if (network->connecting == TRUE || network->associating == TRUE)
764                 return;
765
766         service = __connman_service_lookup_from_network(network);
767         __connman_service_clear_error(service);
768 }
769
770 static void set_configuration(struct connman_network *network)
771 {
772         struct connman_service *service;
773
774         DBG("network %p", network);
775
776         if (network->device == NULL)
777                 return;
778
779         __connman_device_set_network(network->device, network);
780
781         connman_device_set_disconnected(network->device, FALSE);
782
783         service = __connman_service_lookup_from_network(network);
784         __connman_service_ipconfig_indicate_state(service,
785                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
786                                         CONNMAN_IPCONFIG_TYPE_IPV4);
787 }
788
789 static void dhcp_success(struct connman_network *network)
790 {
791         struct connman_service *service;
792         struct connman_ipconfig *ipconfig_ipv4;
793         int err;
794
795         service = __connman_service_lookup_from_network(network);
796         if (service == NULL)
797                 goto err;
798
799         connman_network_set_associating(network, FALSE);
800
801         network->connecting = FALSE;
802
803         ipconfig_ipv4 = __connman_service_get_ip4config(service);
804         err = __connman_ipconfig_address_add(ipconfig_ipv4);
805         if (err < 0)
806                 goto err;
807
808         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
809         if (err < 0)
810                 goto err;
811
812         return;
813
814 err:
815         connman_network_set_error(network,
816                                 CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
817 }
818
819 static void dhcp_failure(struct connman_network *network)
820 {
821         struct connman_service *service;
822
823         service = __connman_service_lookup_from_network(network);
824         if (service == NULL)
825                 return;
826
827         __connman_service_ipconfig_indicate_state(service,
828                                         CONNMAN_SERVICE_STATE_IDLE,
829                                         CONNMAN_IPCONFIG_TYPE_IPV4);
830 }
831
832 static void dhcp_callback(struct connman_network *network,
833                         connman_bool_t success)
834 {
835         DBG("success %d", success);
836
837         if (success == TRUE)
838                 dhcp_success(network);
839         else
840                 dhcp_failure(network);
841 }
842
843 static int set_connected_fixed(struct connman_network *network)
844 {
845         struct connman_service *service;
846         struct connman_ipconfig *ipconfig_ipv4;
847         int err;
848
849         DBG("");
850
851         service = __connman_service_lookup_from_network(network);
852
853         ipconfig_ipv4 = __connman_service_get_ip4config(service);
854
855         set_configuration(network);
856
857         network->connecting = FALSE;
858
859         connman_network_set_associating(network, FALSE);
860
861         err = __connman_ipconfig_address_add(ipconfig_ipv4);
862         if (err < 0)
863                 goto err;
864
865         err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
866         if (err < 0)
867                 goto err;
868
869         return 0;
870
871 err:
872         connman_network_set_error(network,
873                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
874
875         return err;
876 }
877
878 static void set_connected_manual(struct connman_network *network)
879 {
880         struct connman_service *service;
881         struct connman_ipconfig *ipconfig;
882         int err;
883
884         DBG("network %p", network);
885
886         service = __connman_service_lookup_from_network(network);
887
888         ipconfig = __connman_service_get_ip4config(service);
889
890         if (__connman_ipconfig_get_local(ipconfig) == NULL)
891                 __connman_service_read_ip4config(service);
892
893         set_configuration(network);
894
895         err = __connman_ipconfig_address_add(ipconfig);
896         if (err < 0)
897                 goto err;
898
899         err = __connman_ipconfig_gateway_add(ipconfig);
900         if (err < 0)
901                 goto err;
902
903         network->connecting = FALSE;
904
905         connman_network_set_associating(network, FALSE);
906
907         return;
908
909 err:
910         connman_network_set_error(network,
911                                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
912         return;
913 }
914
915 static int set_connected_dhcp(struct connman_network *network)
916 {
917         int err;
918
919         DBG("network %p", network);
920
921         set_configuration(network);
922
923         err = __connman_dhcp_start(network, dhcp_callback);
924         if (err < 0) {
925                 connman_error("Can not request DHCP lease");
926                 return err;
927         }
928
929         return 0;
930 }
931
932 static int manual_ipv6_set(struct connman_network *network,
933                                 struct connman_ipconfig *ipconfig_ipv6)
934 {
935         struct connman_service *service;
936         int err;
937
938         DBG("network %p ipv6 %p", network, ipconfig_ipv6);
939
940         service = __connman_service_lookup_from_network(network);
941         if (service == NULL)
942                 return -EINVAL;
943
944         if (__connman_ipconfig_get_local(ipconfig_ipv6) == NULL)
945                 __connman_service_read_ip6config(service);
946
947         err = __connman_ipconfig_address_add(ipconfig_ipv6);
948         if (err < 0) {
949                 connman_network_set_error(network,
950                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
951                 return err;
952         }
953
954         err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
955         if (err < 0)
956                 return err;
957
958         __connman_connection_gateway_activate(service,
959                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
960
961         __connman_device_set_network(network->device, network);
962
963         connman_device_set_disconnected(network->device, FALSE);
964
965         network->connecting = FALSE;
966
967         return 0;
968 }
969
970 static void autoconf_ipv6_set(struct connman_network *network)
971 {
972         DBG("network %p", network);
973
974         __connman_device_set_network(network->device, network);
975
976         connman_device_set_disconnected(network->device, FALSE);
977
978         /* XXX: Append IPv6 nameservers here */
979
980         network->connecting = FALSE;
981 }
982
983 static gboolean set_connected(gpointer user_data)
984 {
985         struct connman_network *network = user_data;
986         struct connman_service *service;
987         struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
988         enum connman_ipconfig_method ipv4_method, ipv6_method;
989
990         service = __connman_service_lookup_from_network(network);
991
992         ipconfig_ipv4 = __connman_service_get_ip4config(service);
993         ipconfig_ipv6 = __connman_service_get_ip6config(service);
994
995         DBG("service %p ipv4 %p ipv6 %p", service, ipconfig_ipv4,
996                 ipconfig_ipv6);
997
998         ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
999         ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
1000
1001         DBG("method ipv4 %d ipv6 %d", ipv4_method, ipv6_method);
1002         DBG("network connected %d", network->connected);
1003
1004         if (network->connected == TRUE) {
1005                 int ret;
1006
1007                 switch (ipv6_method) {
1008                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1009                 case CONNMAN_IPCONFIG_METHOD_OFF:
1010                         break;
1011                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1012                         autoconf_ipv6_set(network);
1013                         break;
1014                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1015                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1016                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1017                         if (ret != 0) {
1018                                 connman_network_set_error(network,
1019                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1020                                 return FALSE;
1021                         }
1022                         break;
1023                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1024                         break;
1025                 }
1026
1027                 switch (ipv4_method) {
1028                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1029                 case CONNMAN_IPCONFIG_METHOD_OFF:
1030                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1031                         return FALSE;
1032                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1033                         if (set_connected_fixed(network) < 0) {
1034                                 connman_network_set_error(network,
1035                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1036                                 return FALSE;
1037                         }
1038                         return TRUE;
1039                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1040                         set_connected_manual(network);
1041                         return TRUE;
1042                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1043                         if (set_connected_dhcp(network) < 0) {
1044                                 connman_network_set_error(network,
1045                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1046                                 return FALSE;
1047                         }
1048                 }
1049
1050         } else {
1051                 enum connman_service_state state;
1052
1053                 __connman_device_set_network(network->device, NULL);
1054
1055                 switch (ipv4_method) {
1056                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1057                 case CONNMAN_IPCONFIG_METHOD_OFF:
1058                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1059                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1060                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1061                         break;
1062                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1063                         __connman_dhcp_stop(network);
1064                         break;
1065                 }
1066
1067                 /*
1068                  * We only set the disconnect state if we were not in idle
1069                  * or in failure. It does not make sense to go to disconnect
1070                  * state if we were not connected.
1071                  */
1072                 state = __connman_service_ipconfig_get_state(service,
1073                                                 CONNMAN_IPCONFIG_TYPE_IPV4);
1074                 if (state != CONNMAN_SERVICE_STATE_IDLE &&
1075                                         state != CONNMAN_SERVICE_STATE_FAILURE)
1076                         __connman_service_ipconfig_indicate_state(service,
1077                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1078                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1079
1080                 state = __connman_service_ipconfig_get_state(service,
1081                                                 CONNMAN_IPCONFIG_TYPE_IPV6);
1082                 if (state != CONNMAN_SERVICE_STATE_IDLE &&
1083                                         state != CONNMAN_SERVICE_STATE_FAILURE)
1084                         __connman_service_ipconfig_indicate_state(service,
1085                                         CONNMAN_SERVICE_STATE_DISCONNECT,
1086                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1087
1088                 __connman_connection_gateway_remove(service,
1089                                                 CONNMAN_IPCONFIG_TYPE_ALL);
1090
1091                 __connman_ipconfig_address_unset(ipconfig_ipv4);
1092                 __connman_ipconfig_address_unset(ipconfig_ipv6);
1093
1094                 /*
1095                  * Special handling for IPv6 autoconfigured address.
1096                  * The simplest way to remove autoconfigured routes is to
1097                  * disable IPv6 temporarily so that kernel will do the cleanup
1098                  * automagically.
1099                  */
1100                 if (ipv6_method == CONNMAN_IPCONFIG_METHOD_AUTO) {
1101                         __connman_ipconfig_disable_ipv6(ipconfig_ipv6);
1102                         __connman_ipconfig_enable_ipv6(ipconfig_ipv6);
1103                 }
1104
1105                 __connman_service_ipconfig_indicate_state(service,
1106                                         CONNMAN_SERVICE_STATE_IDLE,
1107                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1108
1109                 __connman_service_ipconfig_indicate_state(service,
1110                                         CONNMAN_SERVICE_STATE_IDLE,
1111                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1112         }
1113
1114         network->connecting = FALSE;
1115
1116         connman_network_set_associating(network, FALSE);
1117
1118         return FALSE;
1119 }
1120
1121 /**
1122  * connman_network_set_connected:
1123  * @network: network structure
1124  * @connected: connected state
1125  *
1126  * Change connected state of network
1127  */
1128 int connman_network_set_connected(struct connman_network *network,
1129                                                 connman_bool_t connected)
1130 {
1131         DBG("network %p connected %d", network, connected);
1132
1133         if ((network->connecting == TRUE || network->associating == TRUE) &&
1134                                                         connected == FALSE) {
1135                 connman_network_set_error(network,
1136                                         CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
1137                 __connman_network_disconnect(network);
1138         }
1139
1140         if (network->connected == connected)
1141                 return -EALREADY;
1142
1143         network->connected = connected;
1144
1145         set_connected(network);
1146
1147         return 0;
1148 }
1149
1150 /**
1151  * connman_network_get_connected:
1152  * @network: network structure
1153  *
1154  * Get network connection status
1155  */
1156 connman_bool_t connman_network_get_connected(struct connman_network *network)
1157 {
1158         return network->connected;
1159 }
1160
1161 /**
1162  * connman_network_get_associating:
1163  * @network: network structure
1164  *
1165  * Get network associating status
1166  */
1167 connman_bool_t connman_network_get_associating(struct connman_network *network)
1168 {
1169         return network->associating;
1170 }
1171
1172 /**
1173  * __connman_network_connect:
1174  * @network: network structure
1175  *
1176  * Connect network
1177  */
1178 int __connman_network_connect(struct connman_network *network)
1179 {
1180         int err;
1181
1182         DBG("network %p", network);
1183
1184         if (network->connected == TRUE)
1185                 return -EISCONN;
1186
1187         if (network->connecting == TRUE || network->associating == TRUE)
1188                 return -EALREADY;
1189
1190         if (network->driver == NULL)
1191                 return -EUNATCH;
1192
1193         if (network->driver->connect == NULL)
1194                 return -ENOSYS;
1195
1196         if (network->device == NULL)
1197                 return -ENODEV;
1198
1199         network->connecting = TRUE;
1200
1201         __connman_device_disconnect(network->device);
1202
1203         err = network->driver->connect(network);
1204         if (err < 0) {
1205                 if (err == -EINPROGRESS)
1206                         connman_network_set_associating(network, TRUE);
1207                 else {
1208                         network->connecting = FALSE;
1209                 }
1210
1211                 return err;
1212         }
1213
1214         network->connected = TRUE;
1215         set_connected(network);
1216
1217         return err;
1218 }
1219
1220 /**
1221  * __connman_network_disconnect:
1222  * @network: network structure
1223  *
1224  * Disconnect network
1225  */
1226 int __connman_network_disconnect(struct connman_network *network)
1227 {
1228         int err;
1229
1230         DBG("network %p", network);
1231
1232         if (network->connected == FALSE && network->connecting == FALSE &&
1233                                                 network->associating == FALSE)
1234                 return -ENOTCONN;
1235
1236         if (network->driver == NULL)
1237                 return -EUNATCH;
1238
1239         if (network->driver->disconnect == NULL)
1240                 return -ENOSYS;
1241
1242         network->connecting = FALSE;
1243
1244         err = network->driver->disconnect(network);
1245         if (err == 0) {
1246                 connman_network_set_connected(network, FALSE);
1247                 set_connected(network);
1248         }
1249
1250         return err;
1251 }
1252
1253 static int manual_ipv4_set(struct connman_network *network,
1254                                 struct connman_ipconfig *ipconfig)
1255 {
1256         struct connman_service *service;
1257         int err;
1258
1259         service = __connman_service_lookup_from_network(network);
1260         if (service == NULL)
1261                 return -EINVAL;
1262
1263         err = __connman_ipconfig_address_add(ipconfig);
1264         if (err < 0) {
1265                 connman_network_set_error(network,
1266                         CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL);
1267                 return err;
1268         }
1269
1270         return __connman_ipconfig_gateway_add(ipconfig);
1271 }
1272
1273 int __connman_network_clear_ipconfig(struct connman_network *network,
1274                                         struct connman_ipconfig *ipconfig)
1275 {
1276         struct connman_service *service;
1277         enum connman_ipconfig_method method;
1278         enum connman_ipconfig_type type;
1279
1280         service = __connman_service_lookup_from_network(network);
1281         if (service == NULL)
1282                 return -EINVAL;
1283
1284         method = __connman_ipconfig_get_method(ipconfig);
1285         type = __connman_ipconfig_get_config_type(ipconfig);
1286
1287         switch (method) {
1288         case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1289         case CONNMAN_IPCONFIG_METHOD_OFF:
1290         case CONNMAN_IPCONFIG_METHOD_FIXED:
1291         case CONNMAN_IPCONFIG_METHOD_AUTO:
1292                 return -EINVAL;
1293         case CONNMAN_IPCONFIG_METHOD_MANUAL:
1294                 __connman_ipconfig_address_remove(ipconfig);
1295                 break;
1296         case CONNMAN_IPCONFIG_METHOD_DHCP:
1297                 __connman_dhcp_stop(network);
1298                 break;
1299         }
1300
1301         if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
1302                 __connman_service_ipconfig_indicate_state(service,
1303                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1304                                         CONNMAN_IPCONFIG_TYPE_IPV6);
1305         else if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
1306                 __connman_service_ipconfig_indicate_state(service,
1307                                         CONNMAN_SERVICE_STATE_CONFIGURATION,
1308                                         CONNMAN_IPCONFIG_TYPE_IPV4);
1309
1310         return 0;
1311 }
1312
1313 int __connman_network_set_ipconfig(struct connman_network *network,
1314                                         struct connman_ipconfig *ipconfig_ipv4,
1315                                         struct connman_ipconfig *ipconfig_ipv6)
1316 {
1317         enum connman_ipconfig_method method;
1318         int ret;
1319
1320         if (network == NULL)
1321                 return -EINVAL;
1322
1323         if (ipconfig_ipv6) {
1324                 method = __connman_ipconfig_get_method(ipconfig_ipv6);
1325
1326                 switch (method) {
1327                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1328                 case CONNMAN_IPCONFIG_METHOD_OFF:
1329                         break;
1330                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1331                         autoconf_ipv6_set(network);
1332                         break;
1333                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1334                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1335                         ret = manual_ipv6_set(network, ipconfig_ipv6);
1336                         if (ret != 0) {
1337                                 connman_network_set_error(network,
1338                                         CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
1339                                 return ret;
1340                         }
1341                         break;
1342                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1343                         break;
1344                 }
1345         }
1346
1347         if (ipconfig_ipv4) {
1348                 method = __connman_ipconfig_get_method(ipconfig_ipv4);
1349
1350                 switch (method) {
1351                 case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
1352                 case CONNMAN_IPCONFIG_METHOD_OFF:
1353                 case CONNMAN_IPCONFIG_METHOD_FIXED:
1354                 case CONNMAN_IPCONFIG_METHOD_AUTO:
1355                         return -EINVAL;
1356                 case CONNMAN_IPCONFIG_METHOD_MANUAL:
1357                         return manual_ipv4_set(network, ipconfig_ipv4);
1358                 case CONNMAN_IPCONFIG_METHOD_DHCP:
1359                         return __connman_dhcp_start(network, dhcp_callback);
1360                 }
1361         }
1362
1363         return 0;
1364 }
1365
1366 int connman_network_set_ipaddress(struct connman_network *network,
1367                                         struct connman_ipaddress *ipaddress)
1368 {
1369         struct connman_service *service;
1370         struct connman_ipconfig *ipconfig = NULL;
1371
1372         DBG("network %p", network);
1373
1374         service = __connman_service_lookup_from_network(network);
1375         if (service == NULL)
1376                 return -EINVAL;
1377
1378         ipconfig = __connman_service_get_ipconfig(service, ipaddress->family);
1379         if (ipconfig == NULL)
1380                 return -EINVAL;
1381
1382         __connman_ipconfig_set_local(ipconfig, ipaddress->local);
1383         __connman_ipconfig_set_peer(ipconfig, ipaddress->peer);
1384         __connman_ipconfig_set_broadcast(ipconfig, ipaddress->broadcast);
1385         __connman_ipconfig_set_prefixlen(ipconfig, ipaddress->prefixlen);
1386         __connman_ipconfig_set_gateway(ipconfig, ipaddress->gateway);
1387
1388         return 0;
1389 }
1390
1391 int connman_network_set_nameservers(struct connman_network *network,
1392                                 const char *nameservers)
1393 {
1394         struct connman_service *service;
1395         char **nameservers_array;
1396         int i;
1397
1398         DBG("network %p nameservers %s", network, nameservers);
1399
1400         service = __connman_service_lookup_from_network(network);
1401         if (service == NULL)
1402                 return -EINVAL;
1403
1404         __connman_service_nameserver_clear(service);
1405
1406         if (nameservers == NULL)
1407                 return 0;
1408
1409         nameservers_array = g_strsplit(nameservers, " ", 0);
1410
1411         for (i = 0; nameservers_array[i] != NULL; i++) {
1412                 __connman_service_nameserver_append(service,
1413                                                 nameservers_array[i]);
1414         }
1415
1416         g_strfreev(nameservers_array);
1417
1418         return 0;
1419 }
1420
1421 int connman_network_set_domain(struct connman_network *network,
1422                                 const char *domain)
1423 {
1424         struct connman_service *service;
1425
1426         DBG("network %p domain %s", network, domain);
1427
1428         service = __connman_service_lookup_from_network(network);
1429         if (service == NULL)
1430                 return -EINVAL;
1431
1432         __connman_service_set_domainname(service, domain);
1433
1434         return 0;
1435 }
1436
1437 /**
1438  * connman_network_set_name:
1439  * @network: network structure
1440  * @name: name value
1441  *
1442  * Set display name value for network
1443  */
1444 int connman_network_set_name(struct connman_network *network,
1445                                                         const char *name)
1446 {
1447         DBG("network %p name %s", network, name);
1448
1449         g_free(network->name);
1450         network->name = g_strdup(name);
1451
1452         return 0;
1453 }
1454
1455 /**
1456  * connman_network_set_strength:
1457  * @network: network structure
1458  * @strength: strength value
1459  *
1460  * Set signal strength value for network
1461  */
1462
1463 int connman_network_set_strength(struct connman_network *network,
1464                                                 connman_uint8_t strength)
1465 {
1466         DBG("network %p strengh %d", network, strength);
1467
1468         network->strength = strength;
1469
1470         return 0;
1471 }
1472
1473 connman_uint8_t connman_network_get_strength(struct connman_network *network)
1474 {
1475         return network->strength;
1476 }
1477
1478 int connman_network_set_frequency(struct connman_network *network,
1479                                                 connman_uint16_t frequency)
1480 {
1481         DBG("network %p frequency %d", network, frequency);
1482
1483         network->frequency = frequency;
1484
1485         return 0;
1486 }
1487
1488 connman_uint16_t connman_network_get_frequency(struct connman_network *network)
1489 {
1490         return network->frequency;
1491 }
1492
1493 int connman_network_set_wifi_channel(struct connman_network *network,
1494                                                 connman_uint16_t channel)
1495 {
1496         DBG("network %p wifi channel %d", network, channel);
1497
1498         network->wifi.channel = channel;
1499
1500         return 0;
1501 }
1502
1503 connman_uint16_t connman_network_get_wifi_channel(struct connman_network *network)
1504 {
1505         return network->wifi.channel;
1506 }
1507
1508 /**
1509  * connman_network_set_roaming:
1510  * @network: network structure
1511  * @roaming: roaming state
1512  *
1513  * Set roaming state for network
1514  */
1515 int connman_network_set_roaming(struct connman_network *network,
1516                                                 connman_bool_t roaming)
1517 {
1518         DBG("network %p roaming %d", network, roaming);
1519
1520         network->roaming = roaming;
1521
1522         return 0;
1523 }
1524
1525 /**
1526  * connman_network_set_string:
1527  * @network: network structure
1528  * @key: unique identifier
1529  * @value: string value
1530  *
1531  * Set string value for specific key
1532  */
1533 int connman_network_set_string(struct connman_network *network,
1534                                         const char *key, const char *value)
1535 {
1536         DBG("network %p key %s value %s", network, key, value);
1537
1538         if (g_strcmp0(key, "Name") == 0)
1539                 return connman_network_set_name(network, value);
1540
1541         if (g_str_equal(key, "Path") == TRUE) {
1542                 g_free(network->path);
1543                 network->path = g_strdup(value);
1544         } else if (g_str_equal(key, "Node") == TRUE) {
1545                 g_free(network->node);
1546                 network->node = g_strdup(value);
1547         } else if (g_str_equal(key, "WiFi.Mode") == TRUE) {
1548                 g_free(network->wifi.mode);
1549                 network->wifi.mode = g_strdup(value);
1550         } else if (g_str_equal(key, "WiFi.Security") == TRUE) {
1551                 g_free(network->wifi.security);
1552                 network->wifi.security = g_strdup(value);
1553         } else if (g_str_equal(key, "WiFi.Passphrase") == TRUE) {
1554                 g_free(network->wifi.passphrase);
1555                 network->wifi.passphrase = g_strdup(value);
1556         } else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE) {
1557                 g_free(network->wifi.agent_passphrase);
1558                 network->wifi.agent_passphrase = g_strdup(value);
1559         } else if (g_str_equal(key, "WiFi.EAP") == TRUE) {
1560                 g_free(network->wifi.eap);
1561                 network->wifi.eap = g_strdup(value);
1562         } else if (g_str_equal(key, "WiFi.Identity") == TRUE) {
1563                 g_free(network->wifi.identity);
1564                 network->wifi.identity = g_strdup(value);
1565         } else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE) {
1566                 g_free(network->wifi.agent_identity);
1567                 network->wifi.agent_identity = g_strdup(value);
1568         } else if (g_str_equal(key, "WiFi.CACertFile") == TRUE) {
1569                 g_free(network->wifi.ca_cert_path);
1570                 network->wifi.ca_cert_path = g_strdup(value);
1571         } else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE) {
1572                 g_free(network->wifi.client_cert_path);
1573                 network->wifi.client_cert_path = g_strdup(value);
1574         } else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE) {
1575                 g_free(network->wifi.private_key_path);
1576                 network->wifi.private_key_path = g_strdup(value);
1577         } else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE) {
1578                 g_free(network->wifi.private_key_passphrase);
1579                 network->wifi.private_key_passphrase = g_strdup(value);
1580         } else if (g_str_equal(key, "WiFi.Phase2") == TRUE) {
1581                 g_free(network->wifi.phase2_auth);
1582                 network->wifi.phase2_auth = g_strdup(value);
1583         } else if (g_str_equal(key, "WiFi.PinWPS") == TRUE) {
1584                 g_free(network->wifi.pin_wps);
1585                 network->wifi.pin_wps = g_strdup(value);
1586         } else {
1587                 return -EINVAL;
1588         }
1589
1590         return 0;
1591 }
1592
1593 /**
1594  * connman_network_get_string:
1595  * @network: network structure
1596  * @key: unique identifier
1597  *
1598  * Get string value for specific key
1599  */
1600 const char *connman_network_get_string(struct connman_network *network,
1601                                                         const char *key)
1602 {
1603         DBG("network %p key %s", network, key);
1604
1605         if (g_str_equal(key, "Path") == TRUE)
1606                 return network->path;
1607         else if (g_str_equal(key, "Name") == TRUE)
1608                 return network->name;
1609         else if (g_str_equal(key, "Node") == TRUE)
1610                 return network->node;
1611         else if (g_str_equal(key, "WiFi.Mode") == TRUE)
1612                 return network->wifi.mode;
1613         else if (g_str_equal(key, "WiFi.Security") == TRUE)
1614                 return network->wifi.security;
1615         else if (g_str_equal(key, "WiFi.Passphrase") == TRUE)
1616                 return network->wifi.passphrase;
1617         else if (g_str_equal(key, "WiFi.AgentPassphrase") == TRUE)
1618                 return network->wifi.agent_passphrase;
1619         else if (g_str_equal(key, "WiFi.EAP") == TRUE)
1620                 return network->wifi.eap;
1621         else if (g_str_equal(key, "WiFi.Identity") == TRUE)
1622                 return network->wifi.identity;
1623         else if (g_str_equal(key, "WiFi.AgentIdentity") == TRUE)
1624                 return network->wifi.agent_identity;
1625         else if (g_str_equal(key, "WiFi.CACertFile") == TRUE)
1626                 return network->wifi.ca_cert_path;
1627         else if (g_str_equal(key, "WiFi.ClientCertFile") == TRUE)
1628                 return network->wifi.client_cert_path;
1629         else if (g_str_equal(key, "WiFi.PrivateKeyFile") == TRUE)
1630                 return network->wifi.private_key_path;
1631         else if (g_str_equal(key, "WiFi.PrivateKeyPassphrase") == TRUE)
1632                 return network->wifi.private_key_passphrase;
1633         else if (g_str_equal(key, "WiFi.Phase2") == TRUE)
1634                 return network->wifi.phase2_auth;
1635         else if (g_str_equal(key, "WiFi.PinWPS") == TRUE)
1636                 return network->wifi.pin_wps;
1637
1638         return NULL;
1639 }
1640
1641 /**
1642  * connman_network_set_bool:
1643  * @network: network structure
1644  * @key: unique identifier
1645  * @value: boolean value
1646  *
1647  * Set boolean value for specific key
1648  */
1649 int connman_network_set_bool(struct connman_network *network,
1650                                         const char *key, connman_bool_t value)
1651 {
1652         DBG("network %p key %s value %d", network, key, value);
1653
1654         if (g_strcmp0(key, "Roaming") == 0)
1655                 return connman_network_set_roaming(network, value);
1656         else if (g_strcmp0(key, "WiFi.WPS") == 0)
1657                 network->wifi.wps = value;
1658         else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
1659                 network->wifi.use_wps = value;
1660
1661         return -EINVAL;
1662 }
1663
1664 /**
1665  * connman_network_get_bool:
1666  * @network: network structure
1667  * @key: unique identifier
1668  *
1669  * Get boolean value for specific key
1670  */
1671 connman_bool_t connman_network_get_bool(struct connman_network *network,
1672                                                         const char *key)
1673 {
1674         DBG("network %p key %s", network, key);
1675
1676         if (g_str_equal(key, "Roaming") == TRUE)
1677                 return network->roaming;
1678         else if (g_str_equal(key, "WiFi.WPS") == TRUE)
1679                 return network->wifi.wps;
1680         else if (g_str_equal(key, "WiFi.UseWPS") == TRUE)
1681                 return network->wifi.use_wps;
1682
1683         return FALSE;
1684 }
1685
1686 /**
1687  * connman_network_set_blob:
1688  * @network: network structure
1689  * @key: unique identifier
1690  * @data: blob data
1691  * @size: blob size
1692  *
1693  * Set binary blob value for specific key
1694  */
1695 int connman_network_set_blob(struct connman_network *network,
1696                         const char *key, const void *data, unsigned int size)
1697 {
1698         DBG("network %p key %s size %d", network, key, size);
1699
1700         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1701                 g_free(network->wifi.ssid);
1702                 network->wifi.ssid = g_try_malloc(size);
1703                 if (network->wifi.ssid != NULL) {
1704                         memcpy(network->wifi.ssid, data, size);
1705                         network->wifi.ssid_len = size;
1706                 } else
1707                         network->wifi.ssid_len = 0;
1708         } else {
1709                 return -EINVAL;
1710         }
1711
1712         return 0;
1713 }
1714
1715 /**
1716  * connman_network_get_blob:
1717  * @network: network structure
1718  * @key: unique identifier
1719  * @size: pointer to blob size
1720  *
1721  * Get binary blob value for specific key
1722  */
1723 const void *connman_network_get_blob(struct connman_network *network,
1724                                         const char *key, unsigned int *size)
1725 {
1726         DBG("network %p key %s", network, key);
1727
1728         if (g_str_equal(key, "WiFi.SSID") == TRUE) {
1729                 if (size != NULL)
1730                         *size = network->wifi.ssid_len;
1731                 return network->wifi.ssid;
1732         }
1733
1734         return NULL;
1735 }
1736
1737 void __connman_network_set_device(struct connman_network *network,
1738                                         struct connman_device *device)
1739 {
1740         if (network->device == device)
1741                 return;
1742
1743         if (network->device != NULL)
1744                 network_remove(network);
1745
1746         network->device = device;
1747
1748         if (network->device != NULL)
1749                 network_probe(network);
1750 }
1751
1752 /**
1753  * connman_network_get_device:
1754  * @network: network structure
1755  *
1756  * Get parent device of network
1757  */
1758 struct connman_device *connman_network_get_device(struct connman_network *network)
1759 {
1760         return network->device;
1761 }
1762
1763 /**
1764  * connman_network_get_data:
1765  * @network: network structure
1766  *
1767  * Get private network data pointer
1768  */
1769 void *connman_network_get_data(struct connman_network *network)
1770 {
1771         return network->driver_data;
1772 }
1773
1774 /**
1775  * connman_network_set_data:
1776  * @network: network structure
1777  * @data: data pointer
1778  *
1779  * Set private network data pointer
1780  */
1781 void connman_network_set_data(struct connman_network *network, void *data)
1782 {
1783         network->driver_data = data;
1784 }
1785
1786 void connman_network_update(struct connman_network *network)
1787 {
1788         switch (network->type) {
1789         case CONNMAN_NETWORK_TYPE_UNKNOWN:
1790         case CONNMAN_NETWORK_TYPE_VENDOR:
1791                 return;
1792         case CONNMAN_NETWORK_TYPE_ETHERNET:
1793         case CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN:
1794         case CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN:
1795         case CONNMAN_NETWORK_TYPE_CELLULAR:
1796         case CONNMAN_NETWORK_TYPE_WIFI:
1797         case CONNMAN_NETWORK_TYPE_WIMAX:
1798                 break;
1799         }
1800
1801         if (network->group != NULL)
1802                 __connman_service_update_from_network(network);
1803 }
1804
1805 int __connman_network_init(void)
1806 {
1807         DBG("");
1808
1809         return 0;
1810 }
1811
1812 void __connman_network_cleanup(void)
1813 {
1814         DBG("");
1815 }