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