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